HAProxy基于FQDN转发SSH请求至后端失败:ACL不生效导致连接被关闭
HAProxy基于FQDN转发SSH请求至后端失败:ACL不生效导致连接被关闭
兄弟,你踩了一个典型的协议认知坑——SSH是纯TCP协议,它根本不会像HTTP请求那样携带Host头,所以你用hdr(host)这个ACL规则完全拿不到任何匹配值,自然永远触发不了后端转发逻辑。
咱们拆解下问题根源:
- 你配置的HAProxy是
mode tcp,这种模式下HAProxy只能识别IP和TCP层的数据包,没有办法读取应用层的Host字段(那是HTTP协议特有的内容)。 - 看你贴的
ssh -vvv输出,整个连接过程里完全没有发送Host相关的信息,这也直接印证了:SSH客户端从不会把FQDN信息传递给HAProxy。
下面分两种场景给你解决方案:
场景1:每个FQDN对应独立的公网IP
如果你的HAProxy服务器上,myHostname.myDomain.com有单独绑定的公网IP,那最简单稳定的办法就是直接基于目标IP做转发:
frontend my_ssh_frontend bind x1.y1.z1.t1:122 # 填写myHostname.myDomain.com对应的公网IP mode tcp option tcplog # 无需ACL,直接将该IP上122端口的所有TCP流量转发到后端 default_backend my_ssh_backend backend my_ssh_backend mode tcp server myserver1 x2.y2.z2.t2:22 check
这种方式不需要修改客户端任何配置,直接就能用。
场景2:只有一个公网IP(同IP多域名)
如果必须用同一个IP区分多个FQDN的SSH流量,那得借助SSL的SNI机制(只有SSL握手阶段会传递服务器名称),步骤如下:
- 给后端SSH服务添加SSL包装:可以用
stunnel把后端的SSH 22端口包装成SSL端口,或者直接让SSH服务启用SSL(部分新版SSH支持)。 - 修改HAProxy配置:
frontend my_ssh_frontend bind *:122 mode tcp option tcplog option ssl-hello-chk # 检测SSL握手,确保流量是SSL类型 # 用SNI字段匹配目标FQDN acl my_ssh_acl ssl_fc_sni myHostname.myDomain.com use_backend my_ssh_backend if my_ssh_acl backend my_ssh_backend mode tcp server myserver1 x2.y2.z2.t2:443 check # 填写后端SSL包装后的端口
- 客户端连接方式调整:需要用支持SNI的命令连接,比如:
ssh -o ProxyCommand="openssl s_client -connect %h:122 -servername %h" admin-media@myHostname.myDomain.com
快速验证方法
你可以先临时修改HAProxy前端,把所有流量直接转发到后端,排除后端连通性问题:
frontend my_ssh_frontend bind *:122 mode tcp option tcplog default_backend my_ssh_backend
如果这样能成功连接到后端SSH,就100%确认是原来的hdr(host)ACL规则无效导致的问题了。
备注:内容来源于stack exchange,提问作者SebMa
相关产品推荐
相关产品推荐

