Я использую следующую конфигурацию для завершения SSL, чтобы я мог проверить запрос, выполнить перезапись URL, ACL и т. Д., А затем перенаправить трафик SSL обратно на мои внутренние серверы. Однако я не могу зациклиться на работе. Я могу зациклиться на работе, если просто использую "режим tcp" и выполняю прямую маршрутизацию tcp, но липкость перестает работать, как только я начинаю завершать SSL во внешнем интерфейсе.
Вот мой конфиг:
frontend https-forward
bind *:443 ssl crt /etc/haproxy/certs.d/combo.pem
option http-server-close
option forwardfor
reqadd X-Forwarded-Proto:\ https
reqadd X-Forwarded-Port:\ 443
capture request header Referrer len 64
capture request header Content-Length len 10
capture request header User-Agent len 64
# set HTTP Strict Transport Security (HTST) header
rspadd Strict-Transport-Security:\ max-age=15768000
# some ACLs and URL rewrites...
default_backend backstuff
backend backstuff
log 127.0.0.1 local2 notice
balance roundrobin
option ssl-hello-chk
stick-table type binary len 32 size 30k expire 30m
acl clienthello req_ssl_hello_type 1
acl serverhello rep_ssl_hello_type 2
tcp-request inspect-delay 5s
tcp-request content accept if clienthello
tcp-response content accept if serverhello
stick on payload_lv(43,1) if clienthello
stick store-response payload_lv(43,1) if serverhello
server PO1 10.35.59.160:443 ssl verify none maxconn 5000
server PO2 10.35.59.161:443 ssl verify none maxconn 5000
Причина, по которой вы не можете придерживаться идентификатора сеанса SSL, как при использовании mode http
(по умолчанию, если вы явно не укажете mode tcp
) заключается в том, что вы пытаетесь сделать это с определенными байтами полезной нагрузки пакета, тогда как на самом деле пакеты уже были декодированы, и эти смещения могут содержать полностью случайные данные.
У вас есть два варианта.
Палка на основе IP-адреса источника
Если вы не против того, чтобы придерживаться IP-адреса клиента, а не идентификатора сеанса SSL, как вы делаете сейчас, вы можете изменить свою конфигурацию, чтобы она выглядела следующим образом:
frontend https-forward
bind *:443 ssl crt /etc/haproxy/certs.d/combo.pem
mode http
option http-server-close
option forwardfor
reqadd X-Forwarded-Proto:\ https
reqadd X-Forwarded-Port:\ 443
capture request header Referrer len 64
capture request header Content-Length len 10
capture request header User-Agent len 64
# set HTTP Strict Transport Security (HTST) header
rspadd Strict-Transport-Security:\ max-age=15768000
# some ACLs and URL rewrites...
default_backend backstuff
backend backstuff
mode http
log 127.0.0.1 local2 notice
balance roundrobin
option ssl-hello-chk
stick-table type ip size 30k expire 30m
stick on src
server PO1 10.35.59.160:443 ssl verify none maxconn 5000
server PO2 10.35.59.161:443 ssl verify none maxconn 5000
Ключевыми изменениями являются stick-table
и stick on
строк, а также явное использование mode http
.
Как вы уже сказали, если многие клиенты, обращающиеся к вашему сайту, находятся за NAT, все они окажутся на одном сервере, так что это не самое плавное распределение, но оно работает и обеспечивает желаемую функциональность.
Использовать идентификатор сеанса SSL, декодированный HAProxy
Здесь вам нужно использовать знания HAproxy о подключении через ssl_fc_session_id
(документы).
ssl_fc_session_id : двоичный
Возвращает SSL ID фронтального соединения, когда входящее соединение было выполнено через транспортный уровень SSL / TLS. Полезно привязать данного клиента к серверу. Важно отметить, что некоторые браузеры обновляют свой идентификатор сеанса каждые несколько минут.
В этом случае вы должны использовать ту же конфигурацию, которую я предоставил выше, но с stick-table
и stick
строки изменены на:
stick-table type binary len 32 size 30k expire 30m
stick on ssl_fc_session_id
Это действительно больше всего похоже на то, чего вы пытаетесь достичь.