创建 Docker 网桥以通过特定接口路由传出流量

创建 Docker 网桥以通过特定接口路由传出流量

我正在尝试创建新的 docker 网络桥接器,通过我的第二个网络接口路由传出流量,我设法使容器流量通过所需的接口,但是我失去了从本地主机与容器通信的能力,同样也无法从容器内部通信。这是迄今为止的配置。

我的网络接口:

eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.0.0.3  netmask 255.255.255.0  broadcast 10.0.0.255

eth1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.0.1.3  netmask 255.255.255.0  broadcast 10.0.1.255

docker_backup: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.18.0.1  netmask 255.255.0.0  broadcast 172.18.255.255

Docker 网桥配置

[
    {
        "Name": "docker_backup",
        "Id": "5252a641d2087e5d4ed6aa142327a3193c2142d8fe5cac6b6a163d0154819d6d",
        "Created": "2021-11-19T16:36:37.037180993+03:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.18.0.0/16",
                    "Gateway": "172.18.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": true,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {},
        "Options": {
            "com.docker.network.bridge.enable_ip_masquerade": "false",
            "com.docker.network.bridge.name": "docker_backup"
        },
        "Labels": {}
    }
]

猫/等/iproute2/rt_tables

#
# reserved values
#
255     local
254     main
253     default
0       unspec
#
# local
#
#1      inr.ruhep
1 docker_backup

iptables

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
SNAT       all  --  172.18.0.0/16        0.0.0.0/0            to:10.0.1.3
MASQUERADE  all  --  172.19.0.0/16        0.0.0.0/0
MASQUERADE  all  --  172.23.0.0/16        0.0.0.0/0
MASQUERADE  tcp  --  172.18.0.3           172.18.0.3           tcp dpt:80

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

路由和 IP 表

ip rule add from 172.18.0.0/16 tab docker_backup
ip route add 172.18.0.0/16 dev eth1 tab docker_backup
ip route add default via 10.0.1.1 dev eth1 tab docker_backup
iptables -t nat -A POSTROUTING -s 172.18.0.0/16 ! -o docker_backup -j SNAT --to-source 10.0.1.3

netstat -an | grep ‘听’

# netstat -an | grep 'LISTEN '
tcp        0      0 127.0.0.1:3493          0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:139             0.0.0.0:*               LISTEN
tcp        0      0 127.0.0.1:6379          0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:8080            0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN
tcp        0      0 127.0.0.1:8081          0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:5938            0.0.0.0:*               LISTEN
tcp        0      0 10.0.1.3:8083           0.0.0.0:*               LISTEN
tcp        0      0 127.0.0.1:5941          0.0.0.0:*               LISTEN
tcp        0      0 127.0.0.53:53           0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN
tcp        0      0 127.0.0.1:631           0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:443             0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:445             0.0.0.0:*               LISTEN
tcp        0      0 10.0.1.3:6881           0.0.0.0:*               LISTEN

路线

Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         homerouter.cpe  0.0.0.0         UG    100    0        0 eth0
10.0.0.0        0.0.0.0         255.255.255.0   U     100    0        0 eth0
10.0.1.0        0.0.0.0         255.255.255.0   U     101    0        0 eth1
link-local      0.0.0.0         255.255.0.0     U     1000   0        0 eth1
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0
172.18.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker_backup
172.19.0.0      0.0.0.0         255.255.0.0     U     0      0        0 br-3271a2013d45
172.23.0.0      0.0.0.0         255.255.0.0     U     0      0        0 br-1855923fbb3f

docker-compose 示例

version: "3.8"

services:
    tester:
        image: linuxserver/nginx
        environment:
            - TZ=Asia/Kuwait
        volumes:
            - ./config:/config
        ports:
            - 127.0.0.1:8081:80
        networks:
            docker_backup:
                ipv4_address: 172.18.0.3
networks:
    docker_backup:
        external: true

从堡垒主机 curl 尝试:

(07:27:55) [email protected] ~/tests
# curl -v localhost:8081
*   Trying 127.0.0.1:8081...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8081 (#0)
> GET / HTTP/1.1
> Host: localhost:8081
> User-Agent: curl/7.68.0
> Accept: */*
>
* Recv failure: Connection reset by peer
* Closing connection 0
curl: (56) Recv failure: Connection reset by peer
(07:28:10) [email protected] ~/tests
# curl -v 172.18.0.3:80
*   Trying 172.18.0.3:80...
* TCP_NODELAY set
* connect to 172.18.0.3 port 80 failed: No route to host
* Failed to connect to 172.18.0.3 port 80: No route to host
* Closing connection 0
curl: (7) Failed to connect to 172.18.0.3 port 80: No route to host

从容器内部我可以使用 eth1 IP 地址连接到外部世界

root@50ed3e196cde:/# curl -LSs ifconfig.io
37.xx.xxx.xx

路由 & ifconfig & ping 到容器网关。

root@434d48b82d6a:/# route

Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         server          0.0.0.0         UG    0      0        0 eth0
172.18.0.0      *               255.255.0.0     U     0      0        0 eth0

root@434d48b82d6a:/# ping -W 5 172.18.0.1

PING 172.18.0.1 (172.18.0.1): 56 data bytes
--- 172.18.0.1 ping statistics ---
4 packets transmitted, 0 packets received, 100% packet loss

root@434d48b82d6a:/# ifconfig

eth0      Link encap:Ethernet  HWaddr 02:42:AC:12:00:03
          inet addr:172.18.0.3  Bcast:172.18.255.255  Mask:255.255.0.0

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0

但是,任何 ping 其他 docker 或主主机 ip(即本地地址)的尝试都会失败。

root@50ed3e196cde:/# curl -v --connect-timeout 5 172.18.0.1
*   Trying 172.18.0.1:80...
* After 5000ms connect time, move on!
* connect to 172.18.0.1 port 80 failed: Operation timed out
* Connection timeout after 5000 ms
* Closing connection 0
curl: (28) Connection timeout after 5000 ms

我可以从主主机 ping 容器 ip,但无法访问任何公开的服务。

# ping 172.18.0.3
PING 172.18.0.3 (172.18.0.3) 56(84) bytes of data.
64 bytes from 172.18.0.3: icmp_seq=1 ttl=64 time=0.095 ms
64 bytes from 172.18.0.3: icmp_seq=2 ttl=64 time=0.074 ms
64 bytes from 172.18.0.3: icmp_seq=3 ttl=64 time=0.092 ms
64 bytes from 172.18.0.3: icmp_seq=4 ttl=64 time=0.086 ms
64 bytes from 172.18.0.3: icmp_seq=5 ttl=64 time=0.087 ms
64 bytes from 172.18.0.3: icmp_seq=6 ttl=64 time=0.089 ms
^C
--- 172.18.0.3 ping statistics ---
6 packets transmitted, 6 received, 0% packet loss, time 5098ms
rtt min/avg/max/mdev = 0.074/0.087/0.095/0.006 ms
(07:10:15) [email protected] ~/tests
# ping 172.18.0.3^C
(07:10:19) [email protected] ~/tests
# curl -v http://172.18.0.3:80
*   Trying 172.18.0.3:80...
* TCP_NODELAY set
* connect to 172.18.0.3 port 80 failed: No route to host
* Failed to connect to 172.18.0.3 port 80: No route to host
* Closing connection 0
curl: (7) Failed to connect to 172.18.0.3 port 80: No route to host

所以,问题是我该如何修改路由或 iptables 规则以使流量从本地地址流向容器,并从容器流向本地地址,同时保持传出的 ip?

答案1

我通过在主主机上添加新的 IP 规则来修复此问题,该规则将到容器子网的流量路由到主表中。

ip rule add to 172.18.0.0/16 lookup main priority 10

相关内容