原理
iptables是k8s网络的基础,了解iptables是认知k8s网络的必须。
iptables的底层实现是netfilter。netfilter的架构就是在整个网络流程的若干位置放置一些钩子,并在每个钩子上挂载一些处理函数进行处理
ip层有5个钩子点。对应的就是iptables的5条内置链。
分别是PREROUTING、POSTROUTING、INPUT、OUTPUT和FORWARD
一个数据包的处理流程:
- 一个数据包到达网卡之后,首先进行PREROUTING。即路由前的处理。在这里可以进行dnat
- 然后进行路由处理。具体就是判断这个包是要给自己本机进程的还是给其他机器的。
- 如果是给其他机器的。就到FORWARD链,进行转发操作。
- 如果是给本地进程的,就到了INPUT链。这里可以做拒绝或者接收的各种判断。
accept的就给本地进程处理,reject的就直接到OUTPUT链 - 在OUTPUT链又可以配置规则决定这个包可否对外发出
- 能对外发的,再经过一次路由,决定从哪个网卡出去,下一跳地址是哪等等
- 最后,不管是FORWARD来的,还是OUTPUT来的。再出去之前都要经过POSTROUTING。
在这里可以做SNAT转换
iptables有5表5链
5链上面已经说了,5表是哪5表呢?
- filter表。最常用。用来控制数据包是接收还是拒绝或者丢弃。
- nat表。很常用。用来进行dnat和snat
- mangle表。可以修改IP头信息
- raw表。iptables是有状态的,即iptables对数据包有连接追踪。而raw是用来去除这种追踪机制的
- security表。不常用。和安全有关。
这5张表的优先级从高到低是:raw、mangle、nat、filter、security
不是每个表都有这5条链。表和链的对应关系。
PREROUTING | FORWARD | INPUT | OUTPUT | POSTROUTING | |
raw表 | √ | √ | |||
mangle表 | √ | √ | √ | √ | √ |
nat表(SNAT) | √ | √ | |||
nat表(DNAT) | √ | √ | |||
filter表 | √ | √ | √ | ||
security表 | √ | √ | √ |
重点关注nat表和filter表即可。
操作命令
查看iptables规则
iptables -L -n
使用iptables命令,必须指定针对哪个表进行操作,默认是filter表
所以等价于
iptables -t filter -L -n
我这边的输出,有INPUT、FORWARD和OUTPUT这三条系统内置链。还有大量的k8s-cni插件创建的自定义链。
仔细观察,自定义链中会有一个引用计数
比如名为DOCKER的自定义链,就被FORWARD内置链引用
iptables的每条链下面的规则处理顺序是从上到下逐条遍历执行的。碰到DROP,REJECT,RETURN这些内置动作就会跳出。
可以看到INPUT、FORWARD和OUTPUT这三条系统内置链的规则策略都是ACCEPT
也可以修改。比如修改INPUT链的策略为DROP
iptables --policy INPUT DROP
通常我们的服务器ssh都是拒绝所有外部服务器远程登录的,就是用的DROP策略。
需要单独配置白名单,及ACL控制
iptables -A INPUT -s x.x.x.x/24 -p tcp --dport 22 -j ACCEPT
-A的意思是以追加(Append)的方式增加这条规则。即加到最后面。后面的INPUT是追加到哪条链。
其他的方式还有-I 插入的方式,可指定插入的位置,如果不指定会加到最前面。
-s就是允许的网段。
策略REJECT和DROP的区别
这两个都能做到拒绝连接的作用。但是效果上有区别,REJECT在拒绝后还会回一个拒绝报文,告诉你被拒绝了,别傻等了。
而DROP是直接把你的请求报文丢了,也不会任何信息,就让你傻等着直到超时。
阻止包
如果要阻止本地8000端口对外建立连接,应该在OUTPUT链上加规则
iptables -A OUTPUT -p tcp --dport 8000 -j DROP
如果要阻止外界访问我们的8000端口,应该在INPUT链上加规则
iptables -A INPUT -p tcp --dport 8000 -j DROP
也可以指定阻止ip的所有包
iptables -A INPUT -s x.x.x.x -j DROP
ip也可以是网段,x.x.x.x/24。如果配置成0.0.0.0/0就会拒绝所有的外来包
禁用ping
大部分的公有云默认都是禁止ping的。是通过禁止icmp协议实现。
iptables -A INPUT -p icmp -j DROP
端口转发
我们的web服务运行在8000端口,但是想让外界访问时依旧访问80端口。这可以通过配置端口转发实现。
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 8000
这里需要用到nat表的PREROUTING链
-i 指定网口
-j 的策略时REDIRECT。--to-port指定转发到哪个端口
删除规则
删除指定规则
iptables -D INPUT -p icmp -j DROP
使用-D后面跟要删除的规则。和添加规则的写法一样。就是把-A换成-D
保存
上面这些操作都是临时的,重启服务器会丢失。需要保存修改
iptables-save
DNAT
DNAT也是规则可执行的策略之一。作用是可以修改目标IP地址和目标端口。
原理和端口转发类似。也是作用在nat表的PREROUTING链。区别是端口转发不修改ip地址。
iptables -t nat -A PREROUTING -d 6.6.6.6 -p tcp --dport 80 -j DNAT --to-destination 10.250.100.100:8000
-d 6.6.6.6 --dport 80匹配到访问6.6.6.6 80端口的包,都将该包的目的地址改成10.250.100.100:8000
多说一句,如果转发的目的IP地址是其他服务器时,需要确保启用ip forward功能,即把Linux当交换机用
echo 1>/proc/sys/net/ipv4/ip_forward
SNAT
和DNAT改变目的地址类似,SNAT改变包的源地址。
SNAT发生在nat表的POSTROUTING链
iptables -t nat -A POSTROUTING -s 6.6.6.6 -j SNAT --to-source 10.250.100.100
对源地址是6.6.6.6的包,修改其源地址ip为10.250.100.100