[TOC]
背景:在容器网络,docker容器一般都是一个与宿主机不同网段的IP,假设某个docker容器的IP为172.17.0.2,它所在的宿主机的IP为192.168.2.103,那么这个docker容器如何能够ping通公网比如114呢?
本文,我们将介绍连接跟踪是如何使得docker容器能ping通公网的。
首先,在主机103上,docker会在iptables的POSTROUTING链上生成如何的一条规则:
```
$ iptables -t nat -nL POSTROUTING
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
MASQUERADE all -- 172.17.0.0/16 0.0.0.0/0
```
这条规则的意思是,容器的包从宿主机出去的时候,会进行MASQUERADE操作(类似SNAT),也就是说,容器的包从宿主机出去后,源IP变成了宿主机的IP,这样外网回复的包就能到达宿主机。
那么问题又来了,外网回复的包到达宿主机时,目的地址为宿主机的IP,宿主机如何知道把这个包转发给容器呢,而且如何把目的地址转换成容器的IP呢?
这个,就和linux的连接跟踪有关了。
我们从容器中ping一个不通的IP
```
$ ping -c 1 114.114.114.115
```
发送一个ping包后,我们查看连接跟踪表中的内容:
```
$ cat /proc/net/nf_conntrack
ipv4 2 icmp 1 28 src=172.17.0.2 dst=114.114.114.115 type=8 code=0 id=33 [UNREPLIED] src=114.114.114.115 dst=192.168.2.103 type=0 code=0 id=33 mark=0 secctx=system_u:object_r:unlabeled_t:s0 zone=0 use=2
...
```
一般这个文件中会有很多内容,很难找到这一行,所以我们一般用conntrack命令(需要安装conntrack-tools)来过滤:
```
$ conntrack -L --proto icmp --orig-src 172.17.0.2
icmp 1 27 src=172.17.0.2 dst=114.114.114.115 type=8 code=0 id=14 [UNREPLIED] src=114.114.114.115 dst=192.168.2.103 type=0 code=0 id=14 mark=0 secctx=system_u:object_r:unlabeled_t:s0 use=1
```
上面这条记录的意思是:如果宿主机收到了回复包`114.114.114.115 -> 192.168.2.103`,那么要把这个包的转换成`114.114.114.115 -> 172.17.0.2`。
我们来详细地分析一下上面的这一条连接跟踪记录,在这条记录中:
* 第一列`icmp`表示协议,第二列`1`表示协议号
* 第三列表示这条连接跟踪记录的生存时间(TTL),这里只剩27秒了,它的默认值是在`/proc/sys/net/ipv4/netfilter/ip_ct_icmp_timeout`中
* 第四行和第五列表示原始包的源IP与目的IP,`[UNREPLIED]`后面的表示回复包的源IP与目的IP
* 第六、七、八列`type=8 code=0 id=14`以及`[UNREPLIED]`后面几个对应字段是ICMP协议的一些信息。我们举个例子来说明几个字段的用途:
比如我们在容器内同时运行两个ping,那么如何判断回复包是哪个Ping的?请求包中`type=8`表示这是一个`echo request`(即ping发送的包)类型的包,`id=14`表示ping的id为`14`(每个ping命令都会有一个id);回复包中`type=0`表示包的类型为`echo reply`(即ping的回复包)。后半部分的意思是:只有当收到的包,它的协议为ICMP、类型为`echo reply`(`type=0`)、id为`14`,才会把目的地址转换为容器地址
到这里,我们就大概了解,容器为什么能连通外网了。
- 常用命令
- 用户与用户组
- 创建用户与用户组
- 快速脚本
- umask
- Yum源
- 基础Yum源
- Epel源
- 制作Yum源
- 同步Yum源
- 为Yum源配置代理
- 下载RPM及依赖
- 系统与内核
- 获取内核的rpm包
- 升级内核
- Iptables
- 基本语法
- 匹配条件
- 基础匹配条件
- 扩展匹配条件
- Addrtype
- Set
- TCP
- Mark
- Multiport
- 目标
- 基本目标
- 扩展目标
- DNAT
- LOG
- CT
- NOTRACK
- MARK
- IP set
- 连接追踪
- 初识连接追踪
- 连接追踪详解
- NAT
- 思路与参考汇总
- 数据结构
- FAQ
- Keepalived
- 单网卡多VIP
- 安装Keepalived
- 双网卡绑VIP
- 别名VIP和辅助VIP
- LVS
- 安装LVS
- Ipvsadm命令
- 磁盘与分区
- 基础知识
- 创建分区
- 格式化与挂载
- Fstab
- LVM
- LVM扩容
- Swap分区
- Tmpfs
- 网络相关
- 重命名网卡
- resolv.conf
- Tcpdump
- nslookup与dig
- ifcg-xxx
- 主机名
- 软件安装
- NFS
- Squid
- Redsocks
- Shadowsocks
- 时钟同步
- Chrony
- FTP
- 文件句柄
- 简介
- 设置文件句柄
- 其他
- SSH密钥登录
- 进程组-会话-终端
- X11转发
- 环境变量
- 常见问题
- 系统进程数
- 系统调用
- 系统调用FAQ
- 用户程序如何进行系统调用
