Длительное время я смотрел с завистью на результаты 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
# wget https://www.openssl.org/source/openssl-1.0.2g.tar.gz
# tar -xzvf openssl-1.0.2g.tar.gz
# 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.