docker在网桥模式下主机端口映射到容器端口的实现

前置知识

iptables:捕获并控制容器和主机之间的流量, 可以通过iptables -t nat -nL命令查看iptables的(S/D)NAT规则
docker0:虚拟交换机
veth1b62ff4@if56:虚拟交换机的虚拟接口
上下两个虚拟接口成对出现
eth0@if57:容器的虚拟接口


网络环境

CentOS:ens33->192.168.40.180/24、docker0->172.17.0.1/16、veth1b62ff4@if56
CentOS的容器:eth0@if57->172.17.0.2/16(gateway:172.17.0.1)
Windows11:VMnet8->192.168.40.1/24


假设CentOS的容器有一个8080/tcp的web服务映射到了CentOS的80/tcp

这个时候Windows11通过浏览器去访问http://192.168.40.180:80, CentOS的ens33接口接收到这个数据包后, iptables的DNAT规则会在数据包被路由之前修改数据包的目的地址和目的端口为172.17.0.2:8080,修改完成后, 数据包会被路由到docker0虚拟机交换机, 虚拟交换机会把数据包发送到veth1b62ff4@if56虚拟接口, CentOS的容器上的eth0@if57虚拟接口就会接收到数据包并通过eth0@if57虚拟接口发送回复数据包, CentOS的docker0交换机通过veth1b62ff4@if56虚拟接口接收到这个数据包后, iptables的DNAT规则会在数据包被路由之前修改数据包的源地址和源端口为192.168.40.180:80, 修改完成后,数据包通过路由就会从CentOS的ens33接口发送出去, 最后Windows11的VMnet8接口接收到数据包会交给浏览器处理。
下面是一个简单的表达:
win11浏览器访问http://192.168.40.180:80(192.168.40.1:12345->192.168.40.180:80) --> win11-VMnet8 --> CentOS-ens33 --> CentOS-iptables-DNAT-修改数据包为192.168.40.1:12345->172.17.0.2:8080 --> CenOS-docker0 --> CentOS-veth1b62ff4@if56 --> CentOS的容器-eth0@if57 --> CentOS的容器-服务(172.17.0.2:8080->192.168.40.1:12345) --> CentOS的容器-eth0@if57 --> CentOS-veth1b62ff4@if56 --> CenOS-docker0 --> CentOS-iptables-DNAT-修改数据包为192.168.40.180:80->192.168.40.1:12345 --> CentOS-ens33 --> win11-VMnet8 --> win11浏览器处理
示意图:Docker容器映射端口到主机.excalidraw


查看iptables的DNAT规则和SNAT规则

[root@xianchaomaster1 ~]# iptables -t nat -nL
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination
DOCKER     all  --  0.0.0.0/0            0.0.0.0/0            ADDRTYPE match dst-type LOCAL

Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination
DOCKER     all  --  0.0.0.0/0           !127.0.0.0/8          ADDRTYPE match dst-type LOCAL

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination
MASQUERADE  all  --  172.17.0.0/16        0.0.0.0/0
MASQUERADE  tcp  --  172.17.0.2           172.17.0.2           tcp dpt:80

Chain DOCKER (2 references)
target     prot opt source               destination
RETURN     all  --  0.0.0.0/0            0.0.0.0/0
DNAT       tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:80 to:172.17.0.2:80

可以看到DNAT规则, 为什么没有SNAT规则?

MASQUERADE 是 SNAT 的一种特殊形式,通常在动态网络环境下(如容器或虚拟机)使用。MASQUERADE 自动将源 IP 地址修改为出站接口的 IP 地址,而不需要手动指定静态 IP,因此它通常比传统的 SNAT 更常用。

posted @ 2025-01-19 21:06  UNGIIN  阅读(91)  评论(0)    收藏  举报