Много где написано о том, как получить 100% и A+ по тесту от Qualys. При всём при том практически везде директивы ssl_ciphers и подобные даются как эдакие магические строки, которые нужно просто вставить, и надеяться, что автор не подводит вас под монастырь. Эта статья призвана исправить это недоразумение. По прочтению этой статьи директива ssl_ciphers потеряет для вас всякую магию, а ECDHE и AES будут как друзья да братья. Также вы узнаете почему 100% по тестам — не всегда хорошо в реальности. Работать будем с Debian 8.7. Если у вас другой дистрибутив, то версии должны быть такие же или более новые. Настроим nginx для получения сертификатов от Let's Encrypt по инструкции, но только до получения сертификата для нашего домена. Конфиг используем минимальный. Ничего лишнего. Всё по умолчанию. Теперь прогоним тест для этого сервера.  С настройками по умолчанию результат так себе. На четвёрку, если по-нашему. Ругаются на слабые параметры для обмена ключами по алгоритму Диффи — Хеллмана (далее просто DH).  Можно было бы сделать усиленные параметры, но такие параметры и скорости не добавляют, и некоторыми старыми клиентами поддерживаются. Те же старые клиенты поддерживают и протокол DH на эллиптических кривых (ECDHE), значит мы ничего не теряем и даже приобретаем в скорости, если вслед за Google, Facebook, Mozilla и CloudFlare полностью откажемся от медленных EDH шифров в пользу ECDHE. Дальше просто. Нужен список рекомендованных шифров. Для сертификата с ключем RSA из того списка нужны шифры только с проверкой подлинности через RSA. Из них исключим шифры слабее 256 бит, и шифры DHE. Перечислим оставшиеся в конфигурационной директиве. Но одного этого будет недостаточно. Нужен ключ минимум на 4096 бит. И другая кривая. В используемой версии OpenSSL можно выбрать только одну. Выберем самую надёжную из популярных. Для оценки с плюсом добавим HSTS. Наконец, отключим старые протоколы для 100% оценки по графе Protocol Support. Полный конфиг получается следующий. Проверим, что никакой ошибки в настройке шифров и протоколов нет. Шифры на месте, хоть и не в том порядке. Но это ожидаемо. Можно запускать тест.  Оценка пять с плюсом. Счастье, радость. Казалось бы. Но есть одна проблема. Если результаты теста прокрутить до раздела Handshake Simulation, то мы увидим что на наш сайт не попадут пользователи IE любых версий младше 11, Java до SE 8, Android до версии 4.3 и даже некоторые версии Safari. Про софт, собранный с OpenSSL версии младше 0.9.8, даже и не говорю. Есть и ещё одна проблема: производительность. Наш ключ на 4096 бит непосредственно влияет на скорость установки соединения, при этом не слишком усиливает защиту. Шифры на 256 бит тоже не помогают ускорить соединеие, что касается мобильных устройств с маломощными процессорами и прочих клиентов без AES-NI (аппаратного ускорения). В случае RSA легко убедиться в негативном влиянии на скорость, используя встроенный в OpenSSL тест. На маломощном Celeron 1007U разница очевидна. Подпись на стороне сервера делается в семь раз медленнее. Проверка подписи на клиенте — в 3.6 раза медленнее. На другом железе тенденция остаётся та же. Этот проигрыш в скорости — плата за усиление стойкости шифра на какие-то 16%. Аналогичным образом проверим скорость рекомендуемых шифров на OpenSSL 1.1.0e.  На Celeron 1007U шифр ChaCha20/Poly1305 будет в два раза быстрее AES-128, а последний на треть быстрее AES-256. На Core i7 с AES-NI картина другая: ChaCha20/Poly1305 будет медленнее AES-128 на треть, а AES-256 лишь немного медленнее AES-128. При шифровании картина примерно та же. Обмен ключами с используемой по умолчанию кривой prime256v1 (она же secp256r1 или NIST P-256) будет существенно быстрее, чем с усиленной кривой secp384r1 (NIST P-384). Работа с P-384 требует в 7-9 раз больше времени в зависимости от операции. Если сравнить ECDSA и RSA, то видно что в случае ECDSA вычислительная нагрузка ложится больше на клиента, чем на сервер. Если вы захотите повторить тесты у себя, то перед тестами стоит поднять приоритет текущего процесса. Очевидно одно: к выбору шифров и параметров нужно подходить более взвешено. Перечисление шифров списком — не лучшая идея потому что уже скоро можно будет штатно, без перекомпиляции и сторонних источников, использовать ChaCha20/Poly1305 в nginx. С явным заданием шифров сервер не будет использовать любые новые виды шифрования без перенастройки. Это не то, о чем вы хотите думать каждый день. Будет лучше выбирать шифры по ключевым словам или тегам, каждое из которых соответствуют какой-то группе шифров. Ключевые слова в разных версиях OpenSSL отличаются, но мы всегда можем их проверить. Например, тег EECDH соответствует всем шифрам с обменом одноразовыми (эфемерными) ключами по алгориму DH с эллиптическими кривыми.  Шифры показываются в списке согласно приоритету: клиент выберет первый подходщящий шифр, просматривая список в указанном порядке. Если бы у нас была самая последняя версия OpenSSL, то для получения того же списка мы бы использовали понятный тег ECDHE, дающий тот же самый список и соответствующий префиксу шифров. В текущей версии такого тега нет, потому используем какой есть. В полученном списке бросаются в глаза шифры без, собственно, шифрования, которые идут с отметкой Enc=None. Исключим такие шифры, дающие только аутентификацию. Заодно исключим шифры без аутентификации. Для полного и безвозратного исключения теги групп aNULL и eNULL c неподходящими шифрами упомянуты с отрицанием. В списке не останется шифров с Au=None или с Enc=None. Теги можно сочетать, получая пересечения множеств шифров. Получим шифры, сочетающие ECDHE, AES-256 и GCM. Группы шифров можно переместить ниже по приоритету, указав с плюсом в начале. Понизим приоритет у шифров с AES-256, не удаляя их. Можно временно убрать какую-то группу шифров, чтобы потом добавить её в другом виде. Исключим из всех ECDHE шифров шифры с 3DES, а затем вернём их обратно, но только в сочетании с обменом ключами RSA. Такие слабые шифры должны оказаться в самом конце списка. Теперь у нас есть всё, чтобы составить список шифров для nginx, которые не будет требовать дополнения при выходе новых версий OpenSSL, теряя старые шифры и приобретая новые без какого-либо участия с нашей стороны. Мы учём необходимость поддержки старых браузеров и требования к скорости. Начнём с получения уже используемого нам списка шифров, но не будем исключать шифры для сертификатов c EC на случай если мы когда-нибудь захотим использовать такой вид сертификатов. На деле нам нужнен не столько конкретно AES, а сколько не нужны слабые шифры 3DES и RC4. Последний исключим полностью и навсегда. Отдадим приоритет более быстрым шифрам, понизив его для AES-256. Совсем удалять AES-256 не будем на случай если кому-то очень будет нужен именно AES-256. (Добавочные биты у него — воображаемые.) Такая строка шифров не исключит ChaCha20/Poly1305 в следующей версии OpenSSL. Для некоторых устаревших клиентов вернём AES без эфемерных ключей. Наконец, вернём 3DES без эфемерных ключей чисто для IE8/XP. Помочь IE6/XP никак нельзя — он по умолчанию не поддерживает TLS. С шифрами закончили. Для поддержки старых клиентов нам нужно вернуть младшие версии TLS и, для скорости, использовать обычную кривую и сертификат на 2048 бит. С таким конфигом мы получаем ровно такой результат как у Google на начало 2017 года.  При этом мы точно знаем что у всех клиентов сайт открывается настолько быстро, насколько это возможно без использования слабых шифров: все современные браузеры используют ECDHE. Также вам обязательно нужно настроить OCSP stapling и, опционально, кеш TLS сессий. Инженер-программист