原理

iptables是k8s网络的基础,了解iptables是认知k8s网络的必须。

iptables的底层实现是netfilter。netfilter的架构就是在整个网络流程的若干位置放置一些钩子,并在每个钩子上挂载一些处理函数进行处理

ip层有5个钩子点。对应的就是iptables的5条内置链。

分别是PREROUTING、POSTROUTING、INPUT、OUTPUT和FORWARD

k8s 容器内No route to host_容器

 

一个数据包的处理流程:

  1. 一个数据包到达网卡之后,首先进行PREROUTING。即路由前的处理。在这里可以进行dnat
  2. 然后进行路由处理。具体就是判断这个包是要给自己本机进程的还是给其他机器的。
  3. 如果是给其他机器的。就到FORWARD链,进行转发操作。
  4. 如果是给本地进程的,就到了INPUT链。这里可以做拒绝或者接收的各种判断。
    accept的就给本地进程处理,reject的就直接到OUTPUT链
  5. 在OUTPUT链又可以配置规则决定这个包可否对外发出
  6. 能对外发的,再经过一次路由,决定从哪个网卡出去,下一跳地址是哪等等
  7. 最后,不管是FORWARD来的,还是OUTPUT来的。再出去之前都要经过POSTROUTING。
    在这里可以做SNAT转换

iptables有5表5链

5链上面已经说了,5表是哪5表呢?

  1. filter表。最常用。用来控制数据包是接收还是拒绝或者丢弃。
  2. nat表。很常用。用来进行dnat和snat
  3. mangle表。可以修改IP头信息
  4. raw表。iptables是有状态的,即iptables对数据包有连接追踪。而raw是用来去除这种追踪机制的
  5. 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

k8s 容器内No route to host_kubernetes_02

 

我这边的输出,有INPUT、FORWARD和OUTPUT这三条系统内置链。还有大量的k8s-cni插件创建的自定义链。

仔细观察,自定义链中会有一个引用计数

k8s 容器内No route to host_服务器_03

比如名为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