036、容器如何访问外部世界 (2019-02-25 周一)
容器默认使用 bridge 网络, 默认就可以访问docker host以外的网络
root@docker-lab:~# ip route # 查看docker host默认路由走 ens4 , 容器默认bridge网络是 172.17.0.0/16
default via 122.14.192.1 dev ens4 onlink
10.0.0.0/20 dev ens3 proto kernel scope link src 10.0.11.43
10.0.0.0/8 via 10.0.0.1 dev ens3
122.14.192.0/24 dev ens4 proto kernel scope link src 122.14.192.75
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1
root@docker-lab:~# iptables -t nat -nvL # 查看iptables nat表,容器默认bridge网络有一条 MASQUERADE 规则,用来让容器访问外网
Chain PREROUTING (policy ACCEPT 833 packets, 42418 bytes)
pkts bytes target prot opt in out source destination
543K 28M DOCKER all -- * * 0.0.0.0/0 0.0.0.0/0 ADDRTYPE match dst-type LOCAL
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
0 0 DOCKER all -- * * 0.0.0.0/0 !127.0.0.0/8 ADDRTYPE match dst-type LOCAL
Chain POSTROUTING (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
842 52097 MASQUERADE all -- * !docker0 172.17.0.0/16 0.0.0.0/0
Chain DOCKER (2 references)
pkts bytes target prot opt in out source destination
0 0 RETURN all -- docker0 * 0.0.0.0/0 0.0.0.0/0
root@docker-lab:~# docker run -it -d --name busyboxA busybox # 以默认网络运行容器 busyboxA
820167494a50fd676dc4f8c44aec55c1050f5011d51bfdf5a9f7a74955a81a4b
root@docker-lab:~# ip address # 查看docker host 网卡信息
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 52:54:00:02:7e:68 brd ff:ff:ff:ff:ff:ff
inet 10.0.11.43/20 brd 10.0.15.255 scope global ens3
valid_lft forever preferred_lft forever
inet6 fe80::5054:ff:fe02:7e68/64 scope link
valid_lft forever preferred_lft forever
3: ens4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 52:54:01:02:27:95 brd ff:ff:ff:ff:ff:ff
inet 122.14.192.75/24 brd 122.14.192.255 scope global ens4
valid_lft forever preferred_lft forever
inet6 fe80::5054:1ff:fe02:2795/64 scope link
valid_lft forever preferred_lft forever
4: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:0e:6c:b4:04 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::42:eff:fe6c:b404/64 scope link
valid_lft forever preferred_lft forever
5529: veth37d0f1c@if5528: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether 4e:ac:a3:7f:9c:f8 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet6 fe80::4cac:a3ff:fe7f:9cf8/64 scope link
valid_lft forever preferred_lft forever
root@docker-lab:~# docker exec -it busyboxA ip address 查看容器busyboxA网卡信息
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
5528: eth0@if5529: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
root@docker-lab:~# docker exec -it busyboxA ping www.qq.com # 在容器中ping www.qq.com
root@docker-lab:~# tcpdump -i veth37d0f1c -nn icmp # 在docker host 上抓容器网卡出来的包
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on veth37d0f1c, link-type EN10MB (Ethernet), capture size 262144 bytes
09:27:15.107876 IP 172.17.0.2 > 123.151.137.18: ICMP echo request, id 1792, seq 42, length 64
09:27:15.114274 IP 123.151.137.18 > 172.17.0.2: ICMP echo reply, id 1792, seq 42, length 64
09:27:16.107990 IP 172.17.0.2 > 123.151.137.18: ICMP echo request, id 1792, seq 43, length 64
09:27:16.114399 IP 123.151.137.18 > 172.17.0.2: ICMP echo reply, id 1792, seq 43, length 64
root@docker-lab:~# tcpdump -i ens4 -nn icmp # 在docker host 上抓出docker host 的包
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on ens4, link-type EN10MB (Ethernet), capture size 262144 bytes
09:27:25.109079 IP 122.14.192.75 > 123.151.137.18: ICMP echo request, id 1792, seq 52, length 64
09:27:25.115479 IP 123.151.137.18 > 122.14.192.75: ICMP echo reply, id 1792, seq 52, length 64
09:27:26.109201 IP 122.14.192.75 > 123.151.137.18: ICMP echo request, id 1792, seq 53, length 64
09:27:26.115575 IP 123.151.137.18 > 122.14.192.75: ICMP echo reply, id 1792, seq 53, length 64
参考信息:
SNAT,DNAT,MASQUERADE都是NAT,MASQUERADE是SNAT的一个特例。
SNAT是指在数据包从网卡发送出去的时候,把数据包中的源地址部分替换为指定的IP,这样,接收方就认为数据包的来源是被替换的那个IP的主机。
MASQUERADE是用发送数据的网卡上的IP来替换源IP,因此,对于那些IP不固定的场合,比如拨号网络或者通过dhcp分配IP的情况下,就得用MASQUERADE。