Добавляем ChaCha20-Poly1305 в nginx

Длительное время я смотрел с завистью на результаты SSL-тестов проектов, имеющих поддержку ChaCha20-Poly1305 среди используемых шифров соединения. Как известно, поддержка тех или иных шифров обеспечивается пакетом OpenSSL, а не веб-сервером nginx, только вот актуальная на сегодняшний день версия OpenSSL 1.0.2g ни разу не поддерживает нужные нам алгоритмы. Как же они реализованы у других?


Как выяснилось, компания «Cloudflare» выпустила патч к OpenSSL, обеспечивающий поддержку ChaCha20-Poly1305, но применить его можно, как вы, наверное, уже догадались, к исходному коду, а не к собранному (установленному) пакету. Патч даже кратковременно попадал в репозиторий Gentoo, однако по какой-то причине был оттуда удален. Тем не менее, если вы интересуетесь такими глубокими вопросами, то я думаю, что для вас не составит труда собрать OpenSSL из исходного кода, тем более, что для многих сборка nginx после очередного релиза уже стала обыденной.

Обратите внимание, что в данной статье я буду использовать актуальные на момент публикации версии OpenSSL 1.0.2g и nginx 1.9.12, а вот вам уже лучше будет посмотреть на сайтах, нет ли чего-нибудь поновее. Также очень важно, чтобы система была 64-битной (x86_64), поскольку для других архитектур патч не подходит (-m32 не помогает, если кто подумал, что это и есть корень проблемы). Дополнительно замечу, что сборка nginx происходит при уже установленной версии из репозитория (после установки своей версии нужно зафиксировать пакет при помощи apt-get, дабы он не подпадал под автоматическое обновление). Итак, для начала перейдем в директорию «opt»:

# cd /opt
Сюда мы скачаем дистрибутив OpenSSL:

# wget https://www.openssl.org/source/openssl-1.0.2g.tar.gz
который затем распакуем:

# tar -xzvf openssl-1.0.2g.tar.gz
Получится из этого директория «openssl-1.0.2g», но мне не нравится лишняя для меня часть, поэтому я переименую ее просто в «openssl»:

# mv /opt/openssl-1.0.2g /opt/openssl

Переходим в эту директорию и начинаем делать патч (Горбачева на этом моменте передернуло бы):

# cd /opt/openssl
# wget https://raw.githubusercontent.com/cloudflare/sslconfig/master/patches/openssl__chacha20_poly1305_draft_and_rfc_ossl102g.patch
# patch -p1 < openssl__chacha20_poly1305_draft_and_rfc_ossl102g.patch

На этот этап прошу обратить особое внимание, так как версия патча должна строго соответствовать версии OpenSSL — если вы ее меняли, то обратитесь сюда за соответствующим патчем (ссылка для wget скрывается за кнопкой «raw»).

Теперь переходим к самому ответственному — подготовке и сборке OpenSSL. Я лично собирал OpenSSL впервые, поэтому воспользовался подсказкой с одного форума. Думаю, что вам она тоже подойдет:

# ./config threads shared enable-ec_nistp_64_gcc_128 -Wl,-rpath=/usr/local/ssl/lib -fPIC -DOPENSSL_PIC -DOPENSSL_THREADS -D_REENTRANT -DDSO_DLFCN -DHAVE_DLFCN_H -m64 -DL_ENDIAN -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -Wl,-Bsymbolic-functions -Wl,-z,relro -Wall -DMD32_REG_T=int -DOPENSSL_IA32_SSE2 -DOPENSSL_BN_ASM_MONT -DOPENSSL_BN_ASM_MONT5 -DOPENSSL_BN_ASM_GF2m -DSHA1_ASM -DSHA256_ASM -DSHA512_ASM -DMD5_ASM -DAES_ASM -DVPAES_ASM -DBSAES_ASM -DWHIRLPOOL_ASM -DGHASH_ASM -DECP_NISTZ256_ASM
# make depend

Если все прошло без ошибок, то с OpenSSL мы закончили. Теперь время переходить к nginx.

Тут все аналогично, поэтому не буду комментировать каждую строку, вместо этого просто укажу порядок действий:

# mkdir /opt/nginx
# wget http://nginx.org/download/nginx-1.9.12.tar.gz
# tar -xzvf nginx-1.9.12.tar.gz
# rm nginx-1.9.12.tar.gz
# cd nginx-1.9.12

Далее следует процесс конфигурирования и установки. Выглядит все примерно следющим образом:

./configure --with-cc-opt="-g -O2 -fstack-protector --param=ssp-buffer-size=4 -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -m64 -mtune=native -mfpmath=sse -pipe -Wall -fexceptions -grecord-gcc-switches -fPIE -Wno-sign-compare -Wno-string-plus-int -Wno-deprecated-declarations -Wno-unused-parameter -Wno-unused-const-variable -Wno-conditional-uninitialized -Wno-mismatched-tags -Wno-c++11-extensions -Wno-sometimes-uninitialized -Wno-parentheses-equality -Wno-tautological-compare -Wno-self-assign -Wno-deprecated-register -Wno-deprecated -Wno-invalid-source-encoding -Wno-pointer-sign -Wno-parentheses -Wno-enum-conversion" \
--with-ld-opt="-Wl,-z,relro,-z,now -Wl,-rpath -Wl,-Bsymbolic-functions -Wl,--as-needed -fPIE" \ --user=www-data \ --group=www-data \ --prefix=/etc/nginx \ --sbin-path=/usr/sbin/nginx \ --conf-path=/etc/nginx/nginx.conf \ --http-log-path=/var/log/nginx/access.log \ --error-log-path=/var/log/nginx/error.log \ --lock-path=/var/run/nginx.lock \ --pid-path=/var/run/nginx.pid \ --http-client-body-temp-path=/var/cache/nginx/body \ --http-fastcgi-temp-path=/var/cache/nginx/fastcgi \ --http-proxy-temp-path=/var/cache/nginx/proxy \ --http-scgi-temp-path=/var/cache/nginx/scgi \ --http-uwsgi-temp-path=/var/cache/nginx/uwsgi \ --with-debug \ --with-file-aio \ --with-http_slice_module \ --with-http_addition_module \ --with-http_auth_request_module \ --with-http_dav_module \ --with-http_geoip_module \ --with-http_gunzip_module \ --with-http_gzip_static_module \ --with-http_image_filter_module \ --with-http_realip_module \ --with-http_secure_link_module \ --with-http_ssl_module \ --with-http_stub_status_module \ --with-http_sub_module \ --with-http_v2_module \ --with-http_xslt_module \ --with-ipv6 \ --with-mail --with-mail_ssl_module \ --with-stream \ --with-stream_ssl_module \ --with-threads \ --with-libatomic \ --with-pcre-jit \ --with-pcre \
--with-pcre=/opt/pcre-8.38 \
--with-zlib=/opt/zlib-1.2.8 \
--with-openssl=/opt/openssl \
--add-module=/some/nginx/module \
--with-openssl-opt=enable-ec_nistp_64_gcc_128

# make && make install

Поскольку моя конфигурация достаточно специфическая, я приведу пример с того же форума с небольшим пояснением. Если у вас уже есть свои параметры сборки, то пользуйтесь ими, добавив то, что выделено полужирным. Если вы впервые собираете nginx, то вполне можно пользоваться и тем, что я привел в примере с учетом того, что некоторые параметры в зависимости от ваших потребностей нужно будет либо удалить, либо добавить. Курсивом выделено то, что вам вряд-ли понадобится, но для примера оставлю.

Если после этого «nginx -v» возвращает 1.9.12 — все прошло отлично, но ChaCha20-Poly1305 еще не активирована. Для ее активации нужно в конфигурации ваших сайтов (или сервера в целом, если применяется одна конфигурация на всех) изменить список используемых шифров на:

ssl_ciphers EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;

Небольшое замечание: результаты Qualys'а можно улучшить по части «Protocol support» путем отключения TLSv1, однако данное решение отрубит доступ многим не сильно уж и старым клиентам, так что пока считаю отключение TLSv1 преждевременным (попробуйте сами — запустите SSL-тест с TLSv1 и без — результат на лицо).

На этом наше дело завершено. Если в процессе сборки или установки возникают проблемы — смело гуглите их по тексту ошибки. 99% таких проблем находится и решается за 10 минут. К примеру, недавно я не смог собрать nginx с ngx_mod_pagespeed. Компилятор убивал процесс на середине «objs/addon/src/ngx_pagespeed.o» и все. Оказалось, что причина тут кроется в малом количестве оперативной памяти и лечится добавлением SWAP.

По материалам: FreeVPS

17.03.2016, 22:51
  nginx, OpenSSL.
Просмотров: 8576.