IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> Linux 网络命名空间与 Docker 容器网络(二) -> 正文阅读

[系统运维]Linux 网络命名空间与 Docker 容器网络(二)

内容接上篇文章 ,我们已经手动创建了两个网络命名空间【也可称为容器】,并用一个网桥将它们连接起来了:
在这里插入图片描述

让容器可以 ping 通外网 IP

现在在容器内不能 ping 通我主机上的 eth0【IP是192.168.71.131/24】,也不能到达外网【以外网 IP 114.114.114.114 为例】:

root@ubuntu21:~# ip netns exec netns0 ping 192.168.71.131
ping: connect: Network is unreachable
root@ubuntu21:~# ip netns exec netns0 ping 114.114.114.114
ping: connect: Network is unreachable
root@ubuntu21:~# ip netns exec netns0 ip route show
172.18.0.0/16 dev ceth0 proto kernel scope link src 172.18.0.10 

这是因为容器内只有一条主机路由,没有默认路由。

从主机上也不能 ping 通容器:

root@ubuntu21:~# ping 172.18.0.10
PING 172.18.0.10 (172.18.0.10) 56(84) bytes of data.
^C
--- 172.18.0.10 ping statistics ---
2 packets transmitted, 0 received, 100% packet loss, time 1022ms

容器和主机间不能互 ping 的原因在于网桥上没有配置 IP 地址,于是给网桥 br0 配上 IP 172.18.0.1/24:

ip addr add 172.18.0.1/16 dev br0

这样主机和容器间就能互 ping 成功了:

root@ubuntu21:~# ping 172.18.0.10
PING 172.18.0.10 (172.18.0.10) 56(84) bytes of data.
64 bytes from 172.18.0.10: icmp_seq=1 ttl=64 time=0.238 ms
64 bytes from 172.18.0.10: icmp_seq=2 ttl=64 time=0.087 ms
^C
--- 172.18.0.10 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1030ms
rtt min/avg/max/mdev = 0.087/0.162/0.238/0.075 ms

现在容器内可以 ping 通主机上的网桥,却还是不能 ping 通 eth0 :

root@ubuntu21:~# ip netns exec netns0 ping 192.168.71.131
ping: connect: Network is unreachable

于是我们在容器内添加一条默认路由

ip netns exec netns0 ip route add default via 172.18.0.1

这下就可以 ping 通 eth0 了:

root@ubuntu21:~# ip netns exec netns0 ping 192.168.71.131
PING 192.168.71.131 (192.168.71.131) 56(84) bytes of data.
64 bytes from 192.168.71.131: icmp_seq=1 ttl=64 time=0.112 ms
64 bytes from 192.168.71.131: icmp_seq=2 ttl=64 time=0.120 ms
^C
--- 192.168.71.131 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1020ms
rtt min/avg/max/mdev = 0.112/0.116/0.120/0.004 ms

现在就是这样的情形:
在这里插入图片描述

但是容器内还是 ping 不通外网 IP:

root@ubuntu21:~# ip netns exec netns0 ping 114.114.114.114
PING 114.114.114.114 (114.114.114.114) 56(84) bytes of data.
^C
--- 114.114.114.114 ping statistics ---
2 packets transmitted, 0 received, 100% packet loss, time 1001ms

我们稍加分析一下就知道:ping 外网 IP 的时候,ICMP 报文源 IP 是内网 IP 172.18.0.10,这样 ICMP 响应是无法回来的,所以 ping 不通。

有没有办法将出去的报文 IP 修改为出接口上的 IP?有的,使用 iptables 伪装源 IP 就行:

iptables -t nat -A POSTROUTING -s 172.18.0.0/16 ! -o br0 -j MASQUERADE

这下就可以 ping 通外网了:

root@ubuntu21:~# ip netns exec netns0 ping 114.114.114.114
PING 114.114.114.114 (114.114.114.114) 56(84) bytes of data.
64 bytes from 114.114.114.114: icmp_seq=1 ttl=127 time=39.4 ms
64 bytes from 114.114.114.114: icmp_seq=2 ttl=127 time=36.8 ms
^C
--- 114.114.114.114 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1002ms
rtt min/avg/max/mdev = 36.807/38.117/39.428/1.310 ms

Docker

我的主机现在安装了 Docker ,查看下 iptables nat 表的规则:

root@ubuntu21:~# iptables -t nat -S
-P PREROUTING ACCEPT
-P INPUT ACCEPT
-P OUTPUT ACCEPT
-P POSTROUTING ACCEPT
-N DOCKER
-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
-A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER
-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE
-A POSTROUTING -s 172.18.0.0/16 ! -o br0 -j MASQUERADE
-A DOCKER -i docker0 -j RETURN

看到这条规则了吗:

-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE

这是 Docker 安装时添加的规则,是不是和我们加的一模一样!

再查看下 iptables filter 表的规则:

root@ubuntu21:~# iptables -S
-P INPUT ACCEPT
-P FORWARD DROP
-P OUTPUT ACCEPT
-N DOCKER
-N DOCKER-ISOLATION-STAGE-1
-N DOCKER-ISOLATION-STAGE-2
-N DOCKER-USER
-A FORWARD -j DOCKER-USER
-A FORWARD -j DOCKER-ISOLATION-STAGE-1
-A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -o docker0 -j DOCKER
-A FORWARD -i docker0 ! -o docker0 -j ACCEPT
-A FORWARD -i docker0 -o docker0 -j ACCEPT
-A DOCKER-ISOLATION-STAGE-1 -i docker0 ! -o docker0 -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-1 -j RETURN
-A DOCKER-ISOLATION-STAGE-2 -o docker0 -j DROP
-A DOCKER-ISOLATION-STAGE-2 -j RETURN
-A DOCKER-USER -j RETURN

因为容器到外部网络的流量要经过 FORWARD 链再走 POSTROUTING 链 ,而FORWARD 链默认策略是丢弃,所以 Docker 添加了这条规则:

-A FORWARD -i docker0 ! -o docker0 -j ACCEPT

将容器到外网的流量放行!

让外部网络访问容器内的服务

现在我们在容器内启动一个 http 服务,监听端口 5000:

root@ubuntu21:~# ip netns exec netns0 python -m http.server 5000
Serving HTTP on 0.0.0.0 port 5000 (http://0.0.0.0:5000/) ...

然后在主机上使用 eth0 的 IP 192.168.71.131 curl 一下【因为外部网络只知道 eth0 的 IP】:

root@ubuntu21:~# curl 192.168.71.131:5000
curl: (7) Failed to connect to 192.168.71.131 port 5000: Connection refused

提示 5000 端口在 eth0 上没有开放!我们需要将容器内的 5000 端口 publish 到主机上。

我们想到可以用 iptables 修改数据包目的 IP 为 172.18.0.10 ,这样数据包就会发送到容器内了。来验证一下:

root@ubuntu21:~# iptables -t nat -A OUTPUT -d 192.168.71.131 -p tcp -m tcp --dport 5000 -j DNAT --to-destination 172.18.0.10:5000
root@ubuntu21:~# curl 192.168.71.131:5000
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
...

OK 的。现在主机上可以访问这个服务了,但是从外部网络【另一台虚拟机上】却仍无法访问:

gns3@gns3vm:~$ curl 192.168.71.131:5000
curl: (7) Failed to connect to 192.168.71.131 port 5000: Connection refused

于是还要在 nat 表 PREROUTING 链再添加这条规则:

root@ubuntu21:~# iptables -t nat -A PREROUTING -d 192.168.71.131 -p tcp -m tcp --dport 5000 -j DNAT --to-destination 172.18.0.10:5000

这下就可以访问了:

gns3@gns3vm:~$ curl 192.168.71.131:5000
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
...

Docker

现在我们启动一个 Docker 容器,将主机内的 80 端口 映射到容器内的 80 端口:

docker run -d -p 80:80 docker/getting-started

看下 iptables nat 表规则:

root@ubuntu21:~# iptables -t nat -S  
-P PREROUTING ACCEPT
-P INPUT ACCEPT
-P OUTPUT ACCEPT
-P POSTROUTING ACCEPT
-N DOCKER
-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
-A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER
-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE
-A POSTROUTING -s 172.17.0.2/32 -d 172.17.0.2/32 -p tcp -m tcp --dport 80 -j MASQUERADE
-A DOCKER -i docker0 -j RETURN
-A DOCKER ! -i docker0 -p tcp -m tcp --dport 80 -j DNAT --to-destination 172.17.0.2:80

最后在 DOCKER 链增加了一条 DNAT 规则:

-A DOCKER ! -i docker0 -p tcp -m tcp --dport 80 -j DNAT --to-destination 172.17.0.2:80

是不是和我们加的规则一模一样!

再查看 iptables filter 表:

root@ubuntu21:~# iptables -S              
-P INPUT ACCEPT
-P FORWARD DROP
-P OUTPUT ACCEPT
-N DOCKER
-N DOCKER-ISOLATION-STAGE-1
-N DOCKER-ISOLATION-STAGE-2
-N DOCKER-USER
-A FORWARD -j DOCKER-USER
-A FORWARD -j DOCKER-ISOLATION-STAGE-1
-A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -o docker0 -j DOCKER
-A FORWARD -i docker0 ! -o docker0 -j ACCEPT
-A FORWARD -i docker0 -o docker0 -j ACCEPT
-A DOCKER -d 172.17.0.3/32 ! -i docker0 -o docker0 -p tcp -m tcp --dport 80 -j ACCEPT
-A DOCKER-ISOLATION-STAGE-1 -i docker0 ! -o docker0 -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-1 -j RETURN
-A DOCKER-ISOLATION-STAGE-2 -o docker0 -j DROP
-A DOCKER-ISOLATION-STAGE-2 -j RETURN
-A DOCKER-USER -j RETURN

外部网络的流量进来在做 DNAT 之后要走 FORWARD 链,因为 FORWARD 链默认策略是丢弃,所以 Docker 在 DOCKER 链添加了如下的规则:

-A DOCKER -d 172.17.0.3/32 ! -i docker0 -o docker0 -p tcp -m tcp --dport 80 -j ACCEPT

放行外部网络访问容器的 TCP 80 端口流量!

  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2022-04-18 18:25:00  更:2022-04-18 18:27:22 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 21:02:11-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码