Я хочу использовать HAProxy для завершения зашифрованных TLS-соединений TCP и для передачи незашифрованного TCP-трафика различным серверным модулям на основе указания имени сервера, используемого для инициирования TLS-соединения.
У меня есть 3 службы, работающие на внутреннем сервере, каждая на другом порту (5001, 5002, 5003). HAProxy привязывается к порту 5000. Я хотел бы маршрутизировать соединения с первыми двумя серверами по имени или с третьим, если совпадений нет. Я инициирую подключение к HAProxy, используя openssl s_client
. Однако в журналах я вижу, что соединения всегда маршрутизируются только на сервер по умолчанию, то есть, похоже, что SNI игнорируется.
DNS:
A record demo.sni.example.com 1.2.3.4
CNAME 1.sni.example.com pointing to demo.sni.example.com
CNAME 2.sni.example.com pointing to demo.sni.example.com
т.е. я бы хотел, чтобы произошла следующая маршрутизация:
SNI = 1.sni.example.com:5000 -> 1.2.3.4:5001
SNI = 2.sni.example.com:5000 -> 1.2.3.4:5002
anything else on port 5000 -> 1.2.3.4:5003
haproxy.cfg:
global
log stdout format raw local0 info
defaults
timeout client 30s
timeout server 30s
timeout connect 5s
option tcplog
frontend tcp-proxy
bind :5000 ssl crt combined-cert-key.pem
mode tcp
log global
tcp-request inspect-delay 5s
tcp-request content accept if { req_ssl_hello_type 1 }
use_backend bk_sni_1 if { req.ssl_sni -i 1.sni.example.com }
use_backend bk_sni_2 if { req.ssl_sni -i 2.sni.example.com }
default_backend bk_default
backend bk_sni_1
mode tcp
log global
balance roundrobin
server server1 1.2.3.4:5001 check
backend bk_sni_2
mode tcp
log global
balance roundrobin
server server1 1.2.3.4:5002 check
backend bk_default
mode tcp
log global
balance roundrobin
server server1 1.2.3.4:5003 check
combined-cert-key.pem
- это самозаверяющий файл сертификата плюс ключ, где CN - это IP-адрес сервера (1.2.3.4
) и есть SAN всех значений DNS и IP.
Подключения инициированы с помощью openssl s_client
:
Я пробовал подключиться через DNS (записи A и CNAME, а также IP):
echo test | openssl s_client -connect demo.sni.example.com:5000 -servername 1.sni.example.com
echo test | openssl s_client -connect 1.sni.example.com:5000 -servername 1.sni.example.com
echo test | openssl s_client -connect 1.2.3.4:5000 -servername 1.sni.example.com
Однако все соединения направляются в серверную часть по умолчанию. bk_default
.
Что заставляет HAProxy не распознавать имя сервера SNI? (Я использую последний образ докера HAProxy: https://hub.docker.com/_/haproxy)
Ответ - использовать ssl_fc_sni, вместо того req.ssl_sni
. Первый предназначен для сеансов с завершением SSL, а второй - для сеансов, в которых TCP проходит напрямую.