欢迎访问我的博客,你的支持,是我最大的动力!

iptables常用命令及kube-proxy中iptables技术分析

Docker 小马奔腾 8768℃ 评论
目录:
[显示]

Linux上防火墙实际是通过内核的netfilter来实现的,iptables和firewalld仅仅是一个维护和管理工具。

在CentOS7上,执行systemctl stop firewalld后,并不会禁用netfilter功能,也就是说,数据包的匹配过滤仍然进行,只是会清空规则。此时通过iptables -S会看到,INPUT、FORWARD、OUTPUT链策略均为ACCEPT,即全部放行

Linux中网络数据包处理流程如下图:

iptables体系结构

系统防火墙基于五条链chain和四张表table

五条链:
PREROUTING,用于目标地址转换DNAT,规则表raw,managle,nat
INPUT,处理输入数据包,规则表managle,nat,filter
FORWARD,处理转发数据包,规则表managle,filter
OUTPUT,处理输出数据包,规则表raw,managle,nat,filter
POSTROUTING,用于源地址转换SNAT,规则表mangle,nat
四张表:
raw,高级功能,如网址过滤
managle,拆解报文,进行相应修改,重新封装,数据包修改(QoS),用于实现服务质量
nat,网络地址转换,用于网关路由器
filter,包过滤,用于防火墙规则
动作:
accept,接收数据包,跳往下一个chain
reject,拦阻,并通过发送方,中止
drop,丢弃数据包,中止
redirect,重定向、映射、透明代理,将包导向到另一个端口PNAT,继续
snat,源地址转换,跳往下一个chain
dnat,目标地址转换,跳往下一个chain
masquerade,ip伪装(NAT),改写包源IP,跳往下一个chain
log,记录日志,继续
snat,改写包源IP,跳往下一个chain
dnat,改写包目的IP,跳往下一个chain
mirror,对调源IP和目的IP,中止
queue,将包交给其他程序处理,中止
return,结束当前,返回主链,适用于自定义链,返回
mark,染色,继续
执行顺序:
从规则表中自上而下依次执行,未匹配则继续下一条规则的匹配
若匹配,则根据规则中动作选择后续执行方向:
1)继续当前队列内下一条规则
log,redirect,mark
2)中止当前队列跳转到下一队列
accept,masquerade,snat,dnat
3)中止所有队列的执行
drop,reject,mirror,queue
命令参数

命令格式:
iptables -t 表名 <-A/I/D/R> 规则链名 [规则号] <-i/o 网卡名> -p 协议名 <-s 源IP/源子网> --sport 源端口 <-d 目标IP/目标子网> --dport 目标端口 -j 动作

命令:
-A/--append chain,向规则链末尾追加
-D/--delete chain,-D/--delete chain rulenum,删除链中某条规则(规则编号从1开始)
-I/--insert chain [rulenum],插入规则
-R/--replace chain rulenum,替换规则
-L/--list [chain [rulenum]],列出规则,按chain区分
-S/--list-rules [chain [rulenum]],列出规则,命令格式
-F/--flush [chain],清空全部[指定链]
-Z/--zero [chain [rulenum]],重置计数器
-N/--new chain,创建自定义链
-X/--delete-chain [chain],删除自定义链
-P/--policy target,修改默认策略
-E/--rename-chain old-chain new-chain,重命名

 

选项:
-4/--ipv4 -6/--ipv6
-p/--protocol proto,协议类型
-s/--source address[/mask][...],源IP
-d/--destination adress[/mask][...],目的IP
-i/--in-interface,网卡进
-o/--out-interface,网卡出
-j/--jump target,跳转
-g/--goto chain,转到链,不return
-m/--match match,使用扩展
-n/--numeric ,数字方式显示
-t/--table table,表名,默认filter
-v/--verbose,详情模式
-x/--exact,显示精确值
扩展模块

iprange模块
范围匹配,--src-rang连接的源地址范围;--dst-range连接的目标地址范围
iptables -t filter -I INPUT -m iprange --src-range 192.168.1.127-192.168.1.146 -j DROP

string模块
--algo,指定匹配算法,有bm、kmp;--string要匹配的字符串
iptables -t filter -I INPUT -p tcp --sport 80 -m string --algo bm --string "aabb" -j REJECT

time模块
--timestart,--timestop,时间范围,不可取反
--weekdays,星期几,可取反
--monthdays,日期,可取反
--datestart,--datestop,日期范围不可取反
iptables -t filter -I OUTPUT -p tcp --dport 80 -m time --timestart 09:00:00 --timestop 19:00:00 -j REJECT
iptables -t filter -I OUTPUT -p tcp --dport 80 -m time --datestart 2017-12-24 --datestop 2017-12-27 -j REJECT
iptables -t filter -I OUTPUT -p tcp --dport 80 -m time --timestart 09:00:00 --timestop 18:00:00 --weekdays 6,7 -j REJECT

connlimit模块
--connlimit-above,单独使用时,表示每个ip的连接数量
--connlimit-mask,不能单独使用,对某类IP段内的一定数量的IP进行连接数量限制
iptables -I INPUT -p tcp --dport 22 -m connlimit --connlimit-above 2 -j REJECT
iptables -I INPUT -p tcp --dport 22 -m connlimit --connlimit-above 20 --connlimit-mask 24 -j REJECT

limit模块
--limit-burst,令牌桶中令牌最大数量;--limit令牌桶中生成新令牌的频率
iptables -t filter -I INPUT -p icmp -m limit --limit-burst 3 --limit 10/minute -j ACCEPT

state模块
指定连接状态
--state {NEW,ESTATBLISHED,INVALID,RELATED}

multiport模块
指定多端口号
--sport,--dport,--ports

模块目录,并不是所有文件都是模块
ls /lib/modules/3.10.0-514.el7.x86_64/kernel/net/netfilter
当前使用的模块
cat /proc/net/ip_tables_matches
检查某模块是否存在
iptables -m mark --help

常用命令
清除iptables
iptables -F #清空规则
iptables -X #删除自定义链
iptables -Z #重置计数器
查看现有规则
iptables -L -n -v  #-v会显示包和数据大小数据
以序号显示规则
iptables -L -n --line-numbers
显示nat表规则
iptables -S -t nat
显示扩展帮助信息
iptables -m addrtype --help
保存规则
iptables-save #会打印到屏幕上
iptables-save > /etc/iptables/iptables.rules #保存到文件中
iptables-restore < /etc/iptables/iptables.rules #恢复
规则示例
iptables -A INPUT -s 127.0.0.1 -d 127.0.0.1 -j ACCEPT #允许本地回环接口(即运行本机访问本机)
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT #允许已建立的或相关连的通行
iptables -A OUTPUT -j ACCEPT #允许所有本机向外的访问
iptables -A INPUT -p tcp --dport 22 -j ACCEPT #允许访问22端口
iptables -A INPUT -p tcp --dport 80 -j ACCEPT #允许访问80端口
iptables -A INPUT -p tcp --dport 21 -j ACCEPT #允许ftp服务的21端口
iptables -A INPUT -p tcp --dport 20 -j ACCEPT #允许FTP服务的20端口
iptables -A INPUT -j reject #禁止其他未允许的规则访问
iptables -A FORWARD -j REJECT #禁止其他未允许的规则访问
iptables -I INPUT -s 123.45.6.7 -j DROP #屏蔽单个IP的命令
kube-proxy中的iptables应用

发送到NodePort上的数据,通过iptables重写向到bube-proxy对应的端口上,然后由kube-proxy进一步把数据发送到其中一个pod上

查看k8s的service情况

#kubectl describe svc
Name: kubernetes
Namespace: default
Labels: component=apiserver
provider=kubernetes
Annotations: <none>
Selector: <none>
Type: ClusterIP
IP: 169.169.0.1
Port: https 443/TCP
Endpoints: 192.168.10.130:6443
Session Affinity: ClientIP
Events: <none>

Name: myweb
Namespace: default
Labels: <none>
Annotations: <none>
Selector: app=myweb
Type: NodePort
IP: 169.169.196.246
Port: <unset> 8080/TCP
NodePort: <unset> 30001/TCP
Endpoints: 172.17.0.2:8080,172.17.0.4:8080
Session Affinity: None
Events: <none>

查看iptables
四张表中,只有filter表和nat表有数据

# iptables-save
*mangle
:PREROUTING ACCEPT [37472:28313102]
:INPUT ACCEPT [37152:28174999]
:FORWARD ACCEPT [320:138103]
:OUTPUT ACCEPT [31489:2773038]
:POSTROUTING ACCEPT [31809:2911141]
COMMIT
*raw

:PREROUTING ACCEPT [55300:37962694]
:OUTPUT ACCEPT [46848:4119391]
COMMIT
*nat

:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:KUBE-MARK-DROP - [0:0]
:KUBE-MARK-MASQ - [0:0]
:KUBE-NODEPORTS - [0:0]
:KUBE-POSTROUTING - [0:0]
:KUBE-SEP-27XNDJTPYDMB4Z2G - [0:0]
:KUBE-SEP-CU7O35VLHTQDCXTP - [0:0]
:KUBE-SEP-K64KHB7E4BRFS6T5 - [0:0]
:KUBE-SERVICES - [0:0]
:KUBE-SVC-NPX46M4PTMTKRN6Y - [0:0]
:KUBE-SVC-YG65S75AKNCDZRSF - [0:0]
-A PREROUTING -m comment --comment "kubernetes service portals" -j KUBE-SERVICES
-A OUTPUT -m comment --comment "kubernetes service portals" -j KUBE-SERVICES
-A POSTROUTING -m comment --comment "kubernetes postrouting rules" -j KUBE-POSTROUTING
-A KUBE-MARK-DROP -j MARK --set-xmark 0x8000/0x8000
-A KUBE-MARK-MASQ -j MARK --set-xmark 0x4000/0x4000
-A KUBE-NODEPORTS -p tcp -m comment --comment "default/myweb:" -m tcp --dport 30001 -j KUBE-MARK-MASQ
-A KUBE-NODEPORTS -p tcp -m comment --comment "default/myweb:" -m tcp --dport 30001 -j KUBE-SVC-YG65S75AKNCDZRSF
-A KUBE-POSTROUTING -m comment --comment "kubernetes service traffic requiring SNAT" -m mark --mark 0x4000/0x4000 -j MASQUERADE
-A KUBE-SEP-27XNDJTPYDMB4Z2G -s 192.168.10.130/32 -m comment --comment "default/kubernetes:https" -j KUBE-MARK-MASQ
-A KUBE-SEP-27XNDJTPYDMB4Z2G -p tcp -m comment --comment "default/kubernetes:https" -m recent --set --name KUBE-SEP-27XNDJTPYDMB4Z2G --mask 255.255.255.255 --rsource -m tcp -j DNAT --to-destination 192.168.10.130:6443
-A KUBE-SEP-CU7O35VLHTQDCXTP -s 172.17.0.2/32 -m comment --comment "default/myweb:" -j KUBE-MARK-MASQ
-A KUBE-SEP-CU7O35VLHTQDCXTP -p tcp -m comment --comment "default/myweb:" -m tcp -j DNAT --to-destination 172.17.0.2:8080
-A KUBE-SEP-K64KHB7E4BRFS6T5 -s 172.17.0.4/32 -m comment --comment "default/myweb:" -j KUBE-MARK-MASQ
-A KUBE-SEP-K64KHB7E4BRFS6T5 -p tcp -m comment --comment "default/myweb:" -m tcp -j DNAT --to-destination 172.17.0.4:8080
-A KUBE-SERVICES -d 169.169.0.1/32 -p tcp -m comment --comment "default/kubernetes:https cluster IP" -m tcp --dport 443 -j KUBE-SVC-NPX46M4PTMTKRN6Y
-A KUBE-SERVICES -d 169.169.196.246/32 -p tcp -m comment --comment "default/myweb: cluster IP" -m tcp --dport 8080 -j KUBE-SVC-YG65S75AKNCDZRSF
-A KUBE-SERVICES -m comment --comment "kubernetes service nodeports; NOTE: this must be the last rule in this chain" -m addrtype --dst-type LOCAL -j KUBE-NODEPORTS
-A KUBE-SVC-NPX46M4PTMTKRN6Y -m comment --comment "default/kubernetes:https" -m recent --rcheck --seconds 10800 --reap --name KUBE-SEP-27XNDJTPYDMB4Z2G --mask 255.255.255.255 --rsource -j KUBE-SEP-27XNDJTPYDMB4Z2G
-A KUBE-SVC-NPX46M4PTMTKRN6Y -m comment --comment "default/kubernetes:https" -j KUBE-SEP-27XNDJTPYDMB4Z2G
-A KUBE-SVC-YG65S75AKNCDZRSF -m comment --comment "default/myweb:" -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-CU7O35VLHTQDCXTP
-A KUBE-SVC-YG65S75AKNCDZRSF -m comment --comment "default/myweb:" -j KUBE-SEP-K64KHB7E4BRFS6T5
COMMIT
*filter

:INPUT ACCEPT [37:9489]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [30:2777]
:KUBE-FIREWALL - [0:0]
:KUBE-SERVICES - [0:0]
-A INPUT -j KUBE-FIREWALL
-A INPUT -m comment --comment "kubernetes service portals" -j KUBE-SERVICES
-A OUTPUT -j KUBE-FIREWALL
-A OUTPUT -m comment --comment "kubernetes service portals" -j KUBE-SERVICES
-A KUBE-FIREWALL -m comment --comment "kubernetes firewall for dropping marked packets" -m mark --mark 0x8000/0x8000 -j DROP
COMMIT

例如客户端访问node的30001端口,即118.110.11.1:xxxx->192.168.10.150:30001

先看进站的情况

第一步,进入INPUT链

-A INPUT -j KUBE-FIREWALL
根据规则,会跳转到KUBE-FIREWALL自定义链

第二步,跳转到KUBE-FIREWALL链

-A KUBE-FIREWALL -m comment --comment "kubernetes firewall for dropping marked packets" -m mark --mark 0x8000/0x8000 -j DROP
因为并没有标记0x8000/0x8000,所以不会被丢弃,返回INPUT链

第三步,匹配INPUT链的第二个规则

-A INPUT -m comment --comment "kubernetes service portals" -j KUBE-SERVICES
跳转到KUBE-SERVICES链

第四步,进入KUBE_SERVICES链

-A KUBE-SERVICES -d 169.169.196.246/32 -p tcp -m comment --comment "default/myweb: cluster IP" -m tcp --dport 8080 -j KUBE-SVC-YG65S75AKNCDZRSF
-A KUBE-SERVICES -d 169.169.0.1/32 -p tcp -m comment --comment "default/kubernetes:https cluster IP" -m tcp --dport 443 -j KUBE-SVC-NPX46M4PTMTKRN6Y
-A KUBE-SERVICES -m comment --comment "kubernetes service nodeports; NOTE: this must be the last rule in this chain" -m addrtype --dst-type LOCAL -j KUBE-NODEPORTS
因为我们目标是192.168.10.150:30001,仅匹配第三条规则,-dst-type LOCAL意思是匹配到发往本主机的连接,即目的是192.168.10.150

第五步,进入KUBE-NODEPORTS

-A KUBE-NODEPORTS -p tcp -m comment --comment "default/myweb:" -m tcp --dport 30001 -j KUBE-MARK-MASQ
-A KUBE-NODEPORTS -p tcp -m comment --comment "default/myweb:" -m tcp --dport 30001 -j KUBE-SVC-YG65S75AKNCDZRSF
...
-A KUBE-MARK-MASQ -j MARK --set-xmark 0x4000/0x4000
先执行第一条跳转到KUBE-MARK-MASQ标识一个标签,然后跳转到KUBE-SVC-YG65S75AKNCDZRSF

第六步,进入KUBE-SVC-YG65S75AKNCDZRSF

-A KUBE-SVC-YG65S75AKNCDZRSF -m comment --comment "default/myweb:" -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-CU7O35VLHTQDCXTP
-A KUBE-SVC-YG65S75AKNCDZRSF -m comment --comment "default/myweb:" -j KUBE-SEP-K64KHB7E4BRFS6T5
第一行是软负载均衡的实现方法,使用了statistic模块的random模式,根据probability的定义,有50%的概率匹配到该规则,然后跳转到KUBE-SEP-CU7O35VLHTQDCXTP
如果没有匹配上,则会执行下一条,跳转到KUBE-SEP-K64KHB7E4BRFS6T5

第七步,DNAT到目标地址

-A KUBE-SEP-CU7O35VLHTQDCXTP -s 172.17.0.2/32 -m comment --comment "default/myweb:" -j KUBE-MARK-MASQ
-A KUBE-SEP-CU7O35VLHTQDCXTP -p tcp -m comment --comment "default/myweb:" -m tcp -j DNAT --to-destination 172.17.0.2:8080
#若匹配到CU7O35VLHTQDCXTP,显然源地址118.110.11.1不匹配第一条,但可以匹配第二条,最后通过DNAT访问到docker容器的地址:172.17.0.2:8080
-A KUBE-SEP-K64KHB7E4BRFS6T5 -s 172.17.0.4/32 -m comment --comment "default/myweb:" -j KUBE-MARK-MASQ
-A KUBE-SEP-K64KHB7E4BRFS6T5 -p tcp -m comment --comment "default/myweb:" -m tcp -j DNAT --to-destination 172.17.0.4:8080
#若匹配到K64KHB7E4BRFS6T5,最终会到达另一个容器

返回的数据包分析方法类似
同理,还可以解释在192.168.10.150本机上可以通过169.169.196.246:8080访问到service,通过169.169.0.1:443访问到apiserver,显然,这不是通过路由表实现的,因为路由表中到达这两个地址只有默认路由,但是通过默认路由是不能真正访问到数据的

转载请注明:轻风博客 » iptables常用命令及kube-proxy中iptables技术分析

喜欢 (5)or分享 (0)