//TODO这篇有点乱,持续整理中
1.引入
举例,从内网访问外网
问题:
服务器收到的包 源ip是192.168.1.66,他不知道怎么把包返回去.
那如果每一台机器都有一个外网地址呢? 也不太现实,没有那么多外网地址.
还好有NAT,也就是network address translate.路由器可以在包发往服务器的时候,把包的源ip,从192.168.1.66-->2.22.22.12. 这样,在服务端收到包后,返回回去的时候,可以发给路由器.
同时,路由器在收到返回的包后,把目的Ip,2.22.22.12--->192.168.1.66. 如此,client收到这个请求了,而且还无感知.
可见,nat机制在苦苦支撑当今的网络
那么,nat是怎么实现的呢?
内核对网络包的处理,是使用的netfilter框架.工作在内核态.而对外暴露了一些使用接口.
iptables
组成:
filter 表:处理过滤功能,主要包含以下三个链。
-
INPUT 链:过滤所有目标地址是本机的数据包
- FORWARD 链:过滤所有路过本机的数据包
- OUTPUT 链:过滤所有由本机产生的数据包
nat 表:主要处理网络地址转换,可以进行 SNAT(改变源地址)、DNAT(改变目标地址),包含以下三个链。
- PREROUTING 链:可以在数据包到达时改变目标地址
- OUTPUT 链:可以改变本地产生的数据包的目标地址
- POSTROUTING 链:在数据包离开时改变数据包的源地址
- 那么一个数据包是怎么过滤的呢?网上大概流传着两个版本,主要在于 包流出的时候,是先OUTPUT-->route 还是 route-->OUTPUT. 无奈,还是看看一些译文吧..
router
route表
[root@localhost ~]# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 192.168.1.1 0.0.0.0 UG 100 0 0 ens33
172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 docker0
192.168.1.0 0.0.0.0 255.255.255.0 U 100 0 0 ens33
测试
[root@localhost ~]# curl 192.168.1.12:8086/hello
^C
[root@localhost ~]# curl 192.168.1.15:8086/hello
hello, world!
增加一条规则:
OUTPUT用于修改目标地址ip
iptables -t nat -A OUTPUT -p tcp -d 192.168.1.13 --dport 8086 -j DNAT --to-destination 192.168.1.15:8086
之后测试
[root@localhost ~]# curl 192.168.1.12:8086/hello
hello, world!
istio中,pod在启动时,会添加2个容器,一个是sidecar容器,用于处理网络请求. 一个是pilot-agent容器.用于管理sidecar的声明周期.
还有一个Init Containers.
用于生成iptables.
//流出流量处理
iptables -t nat -N ISTIO_REDIRECT //增加ISTIO_REDIRECT链处理流出流量
iptables -t nat -A ISTIO_REDIRECT -p tcp -j REDIRECT --to-port "${PROXY_PORT}" // 重定向流量到Sidecar的端口上
iptables -t nat -N ISTIO_OUTPUT // 增加ISTIO_OUTPUT链处理流出流量
iptables -t nat -A OUTPUT -p tcp -j ISTIO_OUTPUT// 将OUTPUT链的流量重定向到ISTIO_OUTPUT链上
for uid in ${PROXY_UID}; do
iptables -t nat -A ISTIO_OUTPUT -m owner --uid-owner "${uid}" -j RETURN //Sidecar本身的流量不转发
done
for gid in ${PROXY_GID}; do
iptables -t nat -A ISTIO_OUTPUT -m owner --gid-owner "${gid}" -j RETURN //Sidecar本身的流量不转发
done
iptables -t nat -A ISTIO_OUTPUT -j ISTIO_REDIRECT //将ISTIO_OUTPUT链的流量转发到ISTIO_REDIRECT
//流入流量处理
iptables -t nat -N ISTIO_IN_REDIRECT //增加ISTIO_IN_REDIRECT链处理流入流量
iptables -t nat -A ISTIO_IN_REDIRECT -p tcp -j REDIRECT --to-port "${PROXY_PORT}" // 将流入流量重定向到Sidecar端口
iptables -t ${table} -N ISTIO_INBOUND //增加ISTIO_INBOUND链处理流入流量
iptables -t ${table} -A PREROUTING -p tcp -j ISTIO_INBOUND //将PREROUTING的流量重定向到ISTIO_INBOUND链
iptables -t nat -A ISTIO_INBOUND -p tcp --dport "${port}" -j ISTIO_IN_REDIRECT //将ISTIO_INBOUND链上指定目的端口的流量重定向到ISTIO_IN_REDIRECT链