关键在于利用SNI在四层实现HTTPS分流,不终止TLS、不解密流量,通过Nginx stream模块匹配$ssl_preread_server_name路由至对应上游,需Nginx≥1.19.4、OpenSSL≥1.1.1并启用stream_ssl_preread模块。

要让外网 HTTPS 流量(443 端口)安全、稳定地转发到内网容器,关键不是“简单改端口”,而是理清流量路径、匹配链路时机、处理双向地址转换,并兼顾容器网络特性。下面分三步说清楚核心操作和常见坑点。
确认网络拓扑与容器接入方式
HTTPS 流量转发成败,首先取决于容器如何接入宿主机网络:
- 若容器使用 bridge 模式(默认),它有独立 IP(如 172.17.0.2),需走 DNAT + SNAT 回包路径;
- 若容器用 host 模式,直接共享宿主机网络栈,只需 DNAT 到 127.0.0.1:443 或容器监听端口,无需 SNAT;
- 若容器在 自定义网桥或 overlay 网络中(如 Docker compose 默认),务必确认宿主机能路由到该子网(如 172.20.0.0/16),否则 DNAT 后包会丢弃。
配置 NAT 表的两条核心规则
假设宿主机公网 IP 是 203.195.32.138,外网网卡为 eth1,容器 IP 是 172.17.0.2,监听 443 端口:
-
DNAT 规则(进向):在 PREROUTING 链把目标为公网 IP 的 443 流量重定向到容器:
iptables -t nat -A PREROUTING -d 203.195.32.138 -p tcp --dport 443 -j DNAT --to-destination 172.17.0.2:443 -
SNAT 或 MASQUERADE 规则(出向回包):确保容器返回的响应包源地址被统一成宿主机地址,避免客户端收到私有 IP 导致 TLS 握手失败:
iptables -t nat -A POSTROUTING -s 172.17.0.2 -d 172.17.0.2 -o eth1 -j MASQUERADE
(更稳妥写法是匹配连接跟踪状态:-m conntrack --ctstate ESTABLISHED,RELATED -j SNAT --to-source 203.195.32.138)
配套必须启用的系统与防火墙设置
缺一不可,否则规则不生效或连接中断:
-
开启内核 IP 转发:
echo 'net.ipv4.ip_forward = 1' >> /etc/sysctl.conf && sysctl -p -
放行 FORWARD 链(对 bridge 容器必需):
iptables -A FORWARD -i eth1 -o docker0 -p tcp --dport 443 -m state --state NEW -j ACCEPT
iptables -A FORWARD -i docker0 -o eth1 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT -
允许 INPUT 链接收 443 请求(否则 SYN 包被 DROP):
iptables -A INPUT -i eth1 -p tcp --dport 443 -m state --state NEW -j ACCEPT -
保存规则并设开机加载(CentOS/RHEL):
iptables-save > /etc/sysconfig/iptables
systemctl enable iptables
HTTPS 特别注意事项
转发 HTTPS 不只是端口映射,还要保障 TLS 层不受干扰:
- 容器内服务(如 Nginx)的
server_name和证书域名必须与外网访问域名一致,iptables 不改 Host 头; - 若容器监听的是非标准端口(如 8443),DNAT 目标写
--to-destination 172.17.0.2:8443,但外网仍用 443 访问; - 避免在 NAT 规则中加
-m multiport或复杂匹配,HTTPS 单连接多帧,简单精准匹配更可靠; - 建议搭配
iptables -t nat -nL -v查看规则命中计数,验证流量是否真走到 DNAT 链。











