Как работает переключение сертификатов HTTPS (как на suche.org)?

20

Для тех, кто не знает, что такое Suche.org, это веб-сайт, который имеет отличную оценку A + по лабораториям SSL в каждой категории: (результат работы лаборатории SSL по Suche.org ). Мне стало известно об этом веб-сайте, когда я открыл еще один тикет о том, что сертификаты ECC не работают в Chrome , и один из респондентов использовал этот сайт в качестве примера.

Что меня смущает, так это то, что хотя в Protocol Supportразделе отчета говорится, что веб-сайт использует только TLSv1.2 ...

TLS 1.2 Yes
TLS 1.1 No
TLS 1.0 No
SSL 3   No
SSL 2   No

Это явно не так, поскольку в Handshake Simulationразделе показано, что некоторые из имитированных старых клиентов используют TLSv1.0 для подключения ...

Android 4.0.4   EC 384 (SHA256)     TLS 1.0 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA   ECDH secp521r1  FS
Android 4.1.1   EC 384 (SHA256)     TLS 1.0 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA   ECDH secp521r1  FS
Android 4.2.2   EC 384 (SHA256)     TLS 1.0 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA   ECDH secp521r1  FS
Android 4.3     EC 384 (SHA256)     TLS 1.0 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA   ECDH secp521r1  FS
Android 4.4.2   EC 384 (SHA256)     TLS 1.2 TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384   ECDH secp521r1  FS

Это немного расстраивает, потому что, если я отключу TLSv1.0 на моем тестовом сайте, вот так ...

# Apache example
SSLProtocol all -SSLv3 -SSLv2 -TLSv1

Запуск сканирования SSL Labs на моем тестовом веб-сайте приводит к следующему для некоторых старых клиентов:

Android 4.0.4   Server closed connection
Android 4.1.1   Server closed connection
Android 4.2.2   Server closed connection
Android 4.3     Server closed connection
Android 4.4.2   EC 384 (SHA256)     TLS 1.2 TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256   ECDH secp256r1  FS

Как можно одновременно разрешить только соединения TLSv1.2, но при этом поддерживать и старых клиентов?

Скотт Крукс
источник
Должны ли мы сделать заголовок более общим, что-то вроде «HTTPS cert Switching logic»?
gf_
1
@ gf_ Хорошая идея. Выполнено.
Скотт Крукс

Ответы:

17

Я вполне уверен, что они проверяют возможности клиента и действуют соответственно, как объяснено в теме, связанной с ответом @Jeff .

Чтобы понять, как это может выглядеть в деталях, взгляните на это . Он показывает реализацию, сделанную HAProxyдля обслуживания разных клиентов разными сертификатами, в зависимости от их возможностей. Я сделал полное копирование / вставку, чтобы предотвратить гниение ссылок, и потому что я думаю, что этот вопрос может быть интересен в будущем:

Сертификаты SHA-1 находятся на выходе, и вам следует как можно скорее перейти на сертификат SHA-256 ... если у вас нет очень старых клиентов и вы должны некоторое время поддерживать совместимость с SHA-1.

Если вы находитесь в такой ситуации, вам нужно либо принудить своих клиентов обновить (сложно), либо внедрить некоторую логику выбора сертификата: мы называем это «переключение сертификатов».

Наиболее детерминированный метод выбора заключается в предоставлении сертификатов SHA-256 клиентам, которые представляют ПРИВЕТ КЛИЕНТА TLS1.2, который явно объявляет о своей поддержке SHA256-RSA (0x0401) в расширении signature_algorithms.

Расширения алгоритма подписи

Современные веб-браузеры отправят это расширение. Однако я не знаю ни о каком распределителе нагрузки с открытым исходным кодом, который в настоящее время может проверять содержимое расширения signature_algorithms. Это может произойти в будущем, но на данный момент самый простой способ добиться сертификата переключения - это использовать ACL SNAP HAProxy: если клиент представляет расширение SNI, направьте его в бэкэнд, который представляет сертификат SHA-256. Если он не представляет расширение, предположим, что это старый клиент, использующий SSLv3 или неработающую версию TLS, и предоставьте ему сертификат SHA-1.

Это может быть достигнуто в HAProxy путем объединения внешнего интерфейса и внутреннего интерфейса:

HAProxy сертификат переключения

global
        ssl-default-bind-ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128
-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-R
SA-AES256-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK

frontend https-in
        bind 0.0.0.0:443
        mode tcp
        tcp-request inspect-delay 5s
        tcp-request content accept if { req_ssl_hello_type 1 }
        use_backend jve_https if { req.ssl_sni -i jve.linuxwall.info }

        # fallback to backward compatible sha1
        default_backend jve_https_sha1

backend jve_https
        mode tcp
        server jve_https 127.0.0.1:1665
frontend jve_https
        bind 127.0.0.1:1665 ssl no-sslv3 no-tlsv10 crt /etc/haproxy/certs/jve_sha256.pem tfo
        mode http
        option forwardfor
        use_backend jve

backend jve_https_sha1
        mode tcp
        server jve_https 127.0.0.1:1667
frontend jve_https_sha1
        bind 127.0.0.1:1667 ssl crt /etc/haproxy/certs/jve_sha1.pem tfo ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA
        mode http
        option forwardfor
        use_backend jve

backend jve
        rspadd Strict-Transport-Security:\ max-age=15768000
        server jve 172.16.0.6:80 maxconn 128

Приведенная выше конфигурация получает входящий трафик в интерфейсе, называемом «https-in». Этот интерфейс находится в режиме TCP и проверяет КЛИЕНТ ПРИВЕТ, исходящий от клиента, для определения значения расширения SNI. Если это значение существует и соответствует нашему целевому сайту, оно отправляет соединение на сервер с именем «jve_https», который перенаправляет на внешний интерфейс, также называемый «jve_https», где сертификат SHA256 настроен и передан клиенту.

Если клиенту не удается представить CLIENT HELLO с SNI или представить SNI, который не соответствует нашему целевому сайту, он перенаправляется на бэкэнд «https_jve_sha1», а затем на соответствующий ему интерфейс, где обслуживается сертификат SHA1. Этот интерфейс также поддерживает более старый набор шифров для поддержки старых клиентов.

Оба интерфейса в конечном итоге перенаправляют на один сервер с именем «jve», который отправляет трафик на веб-серверы назначения.

Это очень простая конфигурация, и в конечном итоге ее можно улучшить, используя лучшие списки ACL (HAproxy регулярно добавляет новостные), но для базовой конфигурации переключения сертификатов она выполняет свою работу!

gf_
источник
9

Аналогичный вопрос был задан по адресу https://community.qualys.com/thread/16387.

Я думаю, что этот ответ является решением:

suche.org - умная реализация. Насколько я понимаю, он запрашивает возможности клиента, а затем предлагает только лучшее из имеющихся, чтобы устранить любые сомнения.

Джефф
источник
2
«он запрашивает возможности клиента», однако, не совсем полезное описание. Вряд ли для кого-либо еще достаточно информации, чтобы сделать свою собственную реализацию.
Уомбл