使用firewalld为HTTPS与WSS(WebSocket)配置不同端口转发的方案咨询
好问题!你碰到的核心难点在于HTTPS和WSS都基于TCP 443端口,常规的firewalld端口转发只能按端口/协议维度区分,没法识别应用层的请求类型。不过我们可以通过firewalld结合iptables的高级匹配规则来解决这个问题,下面给你两种实用的方案:
方案一:基于HTTP握手头的应用层(L7)过滤(适合标准WSS场景)
绝大多数WSS连接都是通过HTTP请求升级而来的,握手请求里会包含Upgrade: websocket和Connection: Upgrade这两个关键HTTP头。我们可以利用iptables的layer7匹配模块,让firewalld识别这类请求并转发到7071端口,剩下的443端口请求则默认转发到HTTPS服务的8080端口。
具体步骤:
安装依赖模块(以CentOS/RHEL系统为例):
首先需要安装支持layer7过滤的iptables扩展组件:yum install xtables-addons iptables-services -y然后手动加载layer7模块:
modprobe xt_layer7(如果需要开机自动加载,可将
xt_layer7写入/etc/modules-load.d/iptables.conf文件)调整转发规则顺序:
先移除你之前配置的HTTPS 443→8080转发规则(因为我们要优先匹配WSS请求):firewall-cmd --remove-forward-port=port=443:proto=tcp:toport=8080 --permanent添加WSS专属转发规则:
这条规则会匹配所有443端口的TCP请求,且包含Upgrade: websocket头的请求,转发到7071端口:firewall-cmd --add-rich-rule='rule family="ipv4" port port="443" protocol="tcp" match layer7-protocol="http" header="Upgrade" value="websocket" forward-port port="443" protocol="tcp" to-port="7071"' --permanent恢复HTTPS默认转发规则:
剩下的非WSS请求(也就是常规HTTPS请求),继续转发到8080端口:firewall-cmd --add-forward-port=port=443:proto=tcp:toport=8080 --permanent重载firewalld生效:
firewall-cmd --reload
测试方法:
- 测试HTTPS:用
curl -v https://你的域名,检查请求是否被转发到8080端口的服务 - 测试WSS:用
wscat -c wss://你的域名(需要先安装wscat:npm install -g wscat),验证是否能连接到7071端口的WebSocket服务
方案二:基于SNI的TLS层匹配(更可靠,适合子域名场景)
如果你的WSS服务使用了单独的子域名(比如ws.yourdomain.com),推荐用这个方案。它通过匹配TLS握手阶段的SNI(服务器名称指示)字段来区分请求,不需要解析HTTP内容,性能更好,也更稳定。
具体步骤:
安装TLS匹配模块:
yum install iptables-mod-tls -y modprobe xt_tls(同样,可将
xt_tls写入/etc/modules-load.d/iptables.conf实现开机自动加载)移除原有HTTPS转发规则:
firewall-cmd --remove-forward-port=port=443:proto=tcp:toport=8080 --permanent添加SNI匹配的WSS转发规则:
匹配SNI为ws.yourdomain.com的443端口请求,转发到7071:firewall-cmd --add-rich-rule='rule family="ipv4" port port="443" protocol="tcp" match tls sni="ws.yourdomain.com" forward-port port="443" protocol="tcp" to-port="7071"' --permanent恢复HTTPS默认转发规则:
firewall-cmd --add-forward-port=port=443:proto=tcp:toport=8080 --permanent重载firewalld生效:
firewall-cmd --reload
重要注意事项:
- 规则顺序优先级:一定要把WSS的匹配规则放在HTTPS默认转发规则的前面,firewalld会按规则顺序匹配,先匹配到的请求会被优先处理。
- 兼容性:layer7过滤依赖HTTP请求的明文头,如果你的WSS是直接基于TLS的非标准握手(这种情况极少),方案一会失效,此时方案二是更好的选择。
- 性能差异:SNI匹配在TLS层完成,几乎没有性能开销;而layer7过滤需要解析HTTP内容,高流量场景下可能会有轻微性能影响。
备注:内容来源于stack exchange,提问作者VIVEK

