k8s service ession affinity原理与iptables recent模块
1、iptables recent模块
作用:
iptables的recent模块用于限制一段时间内的连接数, 是谨防大量请求攻击的必杀绝技! 善加利用该模块可充分保证服务器安全。
recent常用参数:
- –name
设定列表名称,即设置跟踪数据库的文件名. 默认DEFAULT; - –rsource
源地址,此为默认。 只进行数据库中信息的匹配,并不会对已存在的数据做任何变更操作; - –rdest
目的地址; - –seconds
指定时间内. 当事件发生时,只会匹配数据库中前"几秒"内的记录,–seconds必须与–rcheck或–update参数共用; - –hitcount
命中次数. hits匹配重复发生次数,必须与–rcheck或–update参数共用; - –set
将地址添加进列表,并更新信息,包含地址加入的时间戳。 即将符合条件的来源数据添加到数据库中,但如果来源端数据已经存在,则更新数据库中的记录信息; - –rcheck
检查地址是否在列表,以第一个匹配开始计算时间; - –update
和rcheck类似,以最后一个匹配计算时间。 如果来源端的数据已存在,则将其更新;若不存在,则不做任何处理; - –remove
在列表里删除相应地址,后跟列表名称及地址。如果来源端数据已存在,则将其删除,若不存在,则不做任何处理; - –reap
此选项只能与 --seconds 结合使用。使用时,这将导致清除早于最后给定秒数的条目
recent模块需要注意的地方:
- 目录/proc/net/下的xt_recent目录是在启用recent模块之后才有的,如果没有在iptables中使用recent模块,/proc/net/目录中是没有xt_recent目录的;
- 因recent模块最多只能记录20条记录,所以当源发送的数据包超过20后,recent模块的计数器会立刻减掉20,这也就是为什么old_packets的值就总是处于1-20之间;
- 如果配合seconds参数使用的是–rcheck参数而不是–update,则recent模块会从收到第一个数据包开始计算阻断时间,而–update是从收到的最后一个数据包开始计算阻断时间,即如果服务器在8点收到了源发出第一个icmp数据包,在8点15分收到源发出的第20个数据包,如果使用的是–rcheck参数,那么8点半的时候,用户就又可以发送icmp数据包了,如果使用是–update参数,则用户必须等到8点40才能发送icmp数据包;
- 当源发送数据包的个数大于或等于recent模块的hitcount参数所指定的值时,相应的iptables规则才会被激活;
recent命令大体有如下三个排列组合:
- –set句在前,–update(或–rcheck)句在后;
- –update(或–rcheck)句在前,–set句在后;
- –set句带或不带-j ACCEPT。基本是上面这三项的排列组合;
启动相应模块:
- modprobe xt_recent
简单示例:
1、每个 IP 只允许在 5 秒内建立 2 个基于 tcp 80 端口的连接
# 检查5秒内的ip列表中源IP是否存在2个
iptables -A INPUT -p tcp --dport 80 -m state --state NEW -m recent --name webpool --rcheck --seconds 5 --hitcount 2 -j DROP
# 放行NEW状态的数据包,并记录至ip列表
iptables -A INPUT -p tcp --dport 80 -m state --state NEW -m recent --name webpool --set -j ACCEPT
# 放行ESTABLISHED状态的数据包
iptables -A INPUT -p tcp --dport 80 -m state --state ESTABLISHED -j ACCEPT
2、在连接 ssh 前,先使用 ping 才能连接
# 匹配icmp请求包(包大小为29),并将源IP加入ip列表(sudo ping 192.168.10.150 -s 1)
iptables -I INPUT -p icmp --icmp-type 8 -m length --length 29 -m recent --name sshlogin --set -j REJECT --reject-with icmp-host-unreachable
# 允许10秒内存在于列表中的IP连接22端口
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --name sshlogin --rcheck --seconds 10 -j ACCEPT
# 允许ESTABLISHED状态的ssh连接
iptables -A INPUT -p tcp --dport 22 -m state --state ESTABLISHED -j ACCEPT
3、限制每ip在一分钟内最多对服务器只能有8个http连接
iptables -I INPUT -p tcp --dport 80 -d 192.168.10.10 -m state --state NEW -m recent --name httpuser --set
iptables -A INPUT -m recent --update --name httpuser --seconds 60 --hitcount 9 -j LOG --log-prefix 'HTTP attack: '
iptables -A INPUT -m recent --update --name httpuser --seconds 60 --hitcount 9 -j DROP
4、对连接到服务器B的SSH连接进行限制,每个IP每小时只限连接5次
-A INPUT -p tcp --dport 22 -m state --state NEW -m recent --name SSHPOOL --rcheck --seconds 3600 --hitcount 5 -j DROP
-A INPUT -p tcp --dport 22 -m state --state NEW -m recent --name SSHPOOL --set -j ACCEPT
5、限制无法ssh直接连接服务器,需先用较大包ping一下,此时在15秒内才可以连接上
这里大包指ping包内容为100字节,则加上IP头, ICMP头的28字节,总共128字节。
iptables -P INPUT DROP
iptables -A INPUT -s 127.0.0.1/32 -j ACCEPT
iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A INPUT -p icmp --icmp-type 8 -m length --length 128 -m recent --set --name SSHOPEN --rsource -j ACCEPT
iptables -A INPUT -p icmp --icmp-type 8 -j ACCEPT
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --rcheck --seconds 15 --name SSHOPEN --rsource -j ACCEPT
更精确的用法:
1、限制80端口60秒内每个IP只能发起10个新连接,超过记录日记及丢失数据包,可防CC及非伪造IP的syn flood。
iptables -A INPUT -p tcp --dport 80 --syn -m recent --name webpool --rcheck --seconds 60 --hitcount 10 -j LOG --log-prefix 'DDOS:' --log-ip-options
iptables -A INPUT -p tcp --dport 80 --syn -m recent --name webpool --rcheck --seconds 60 --hitcount 10 -j DROP
iptables -A INPUT -p tcp --dport 80 --syn -m recent --name webpool --set -j ACCEPT
备忘:每个IP目标端口为80的新连接会记录在案,可在/proc/net/xt_recent/目录内查看,rcheck检查此IP是否在案及请求次数,如果超过规则就丢弃数据包,否则进入下条规则并更新列表信息。
2、发送特定指定执行相应操作,按上例如果自己IP被阻止了,可设置解锁哦。
iptables -A INPUT -p tcp --dport 5000 --syn -j LOG --log-prefix "WEBOPEN: "
#记录日志,前缀WEBOPEN:
iptables -A INPUT -p tcp --dport 5000 --syn -m recent --remove --name webpool --rsource -j REJECT --reject-with tcp-reset
#符合规则即删除webpool列表内的本IP记录
3、芝麻开门,默认封闭SSH端口,为您的SSH服务器设置开门暗语。
iptables -A INPUT -p tcp --dport 50001 --syn -j LOG --log-prefix "SSHOPEN: "
#记录日志,前缀SSHOPEN:
iptables -A INPUT -p tcp --dport 50001 --syn -m recent --set --name sshopen --rsource -j REJECT --reject-with tcp-reset
#目标端口tcp50001的新数据设定列表为sshopen返回TCP重置,并记录源地址。
iptables -A INPUT -p tcp --dport 22 --syn -m recent --rcheck --seconds 15 --name sshopen --rsource -j ACCEPT
#开启SSH端口,15秒内允许记录的源地址登录SSH。
nc host 50001 #开门钥匙
telnet host 50001
nmap -sS host 50001
指定端口容易被破解密钥,可以使用ping指定数据包大小为开门钥匙。
iptables -A INPUT -p icmp --icmp-type 8 -m length --length 78 -j LOG --log-prefix "SSHOPEN: "
#记录日志,前缀SSHOPEN:
iptables -A INPUT -p icmp --icmp-type 8 -m length --length 78 -m recent --set --name sshopen --rsource -j ACCEPT
#指定数据包78字节,包含IP头部20字节,ICMP头部8字节。
iptables -A INPUT -p tcp --dport 22 --syn -m recent --rcheck --seconds 15 --name sshopen --rsource -j ACCEPT
ping -s 50 host #Linux下解锁
ping -l 50 host #Windows下解锁
2、k8s service ession affinity原理
$sudo iptables-save | grep k8s-nginx-affinity
-A KUBE-SEP-HDMJEKA4BFKBU6OK -s 10.244.0.145/32 -m comment --comment "default/k8s-nginx-affinity:" -j KUBE-MARK-MASQ
-A KUBE-SEP-HDMJEKA4BFKBU6OK -p tcp -m comment --comment "default/k8s-nginx-affinity:" -m recent --set --name KUBE-SEP-HDMJEKA4BFKBU6OK --mask 255.255.255.255 --rsource -m tcp -j DNAT --to-destination 10.244.0.145:80
-A KUBE-SEP-Q5HAFBJX4HVXF6EM -s 10.244.0.144/32 -m comment --comment "default/k8s-nginx-affinity:" -j KUBE-MARK-MASQ
-A KUBE-SEP-Q5HAFBJX4HVXF6EM -p tcp -m comment --comment "default/k8s-nginx-affinity:" -m recent --set --name KUBE-SEP-Q5HAFBJX4HVXF6EM --mask 255.255.255.255 --rsource -m tcp -j DNAT --to-destination 10.244.0.144:80
-A KUBE-SEP-YFKOY7G33LWKGTLC -s 10.244.0.143/32 -m comment --comment "default/k8s-nginx-affinity:" -j KUBE-MARK-MASQ
-A KUBE-SEP-YFKOY7G33LWKGTLC -p tcp -m comment --comment "default/k8s-nginx-affinity:" -m recent --set --name KUBE-SEP-YFKOY7G33LWKGTLC --mask 255.255.255.255 --rsource -m tcp -j DNAT --to-destination 10.244.0.143:80
-A KUBE-SERVICES ! -s 10.244.0.0/16 -d 10.109.59.245/32 -p tcp -m comment --comment "default/k8s-nginx-affinity: cluster IP" -m tcp --dport 80 -j KUBE-MARK-MASQ
-A KUBE-SERVICES -d 10.109.59.245/32 -p tcp -m comment --comment "default/k8s-nginx-affinity: cluster IP" -m tcp --dport 80 -j KUBE-SVC-UBXGHWUUHMMRNNE6
-A KUBE-SVC-UBXGHWUUHMMRNNE6 -m comment --comment "default/k8s-nginx-affinity:" -m recent --rcheck --seconds 10800 --reap --name KUBE-SEP-YFKOY7G33LWKGTLC --mask 255.255.255.255 --rsource -j KUBE-SEP-YFKOY7G33LWKGTLC
-A KUBE-SVC-UBXGHWUUHMMRNNE6 -m comment --comment "default/k8s-nginx-affinity:" -m recent --rcheck --seconds 10800 --reap --name KUBE-SEP-Q5HAFBJX4HVXF6EM --mask 255.255.255.255 --rsource -j KUBE-SEP-Q5HAFBJX4HVXF6EM
-A KUBE-SVC-UBXGHWUUHMMRNNE6 -m comment --comment "default/k8s-nginx-affinity:" -m recent --rcheck --seconds 10800 --reap --name KUBE-SEP-HDMJEKA4BFKBU6OK --mask 255.255.255.255 --rsource -j KUBE-SEP-HDMJEKA4BFKBU6OK
-A KUBE-SVC-UBXGHWUUHMMRNNE6 -m comment --comment "default/k8s-nginx-affinity:" -m statistic --mode random --probability 0.33332999982 -j KUBE-SEP-YFKOY7G33LWKGTLC
-A KUBE-SVC-UBXGHWUUHMMRNNE6 -m comment --comment "default/k8s-nginx-affinity:" -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-Q5HAFBJX4HVXF6EM
-A KUBE-SVC-UBXGHWUUHMMRNNE6 -m comment --comment "default/k8s-nginx-affinity:" -j KUBE-SEP-HDMJEKA4BFKBU6OK
-A KUBE-SEP-HDMJEKA4BFKBU6OK -p tcp -m comment --comment "default/k8s-nginx-affinity:" -m recent --set --name KUBE-SEP-HDMJEKA4BFKBU6OK --mask 255.255.255.255 --rsource -m tcp -j DNAT --to-destination 10.244.0.145:80
-A KUBE-SEP-Q5HAFBJX4HVXF6EM -p tcp -m comment --comment "default/k8s-nginx-affinity:" -m recent --set --name KUBE-SEP-Q5HAFBJX4HVXF6EM --mask 255.255.255.255 --rsource -m tcp -j DNAT --to-destination 10.244.0.144:80
-A KUBE-SEP-YFKOY7G33LWKGTLC -p tcp -m comment --comment "default/k8s-nginx-affinity:" -m recent --set --name KUBE-SEP-YFKOY7G33LWKGTLC --mask 255.255.255.255 --rsource -m tcp -j DNAT --to-destination 10.244.0.143:80
-A KUBE-SVC-UBXGHWUUHMMRNNE6 -m comment --comment "default/k8s-nginx-affinity:" -m recent --rcheck --seconds 10800 --reap --name KUBE-SEP-YFKOY7G33LWKGTLC --mask 255.255.255.255 --rsource -j KUBE-SEP-YFKOY7G33LWKGTLC
-A KUBE-SVC-UBXGHWUUHMMRNNE6 -m comment --comment "default/k8s-nginx-affinity:" -m recent --rcheck --seconds 10800 --reap --name KUBE-SEP-Q5HAFBJX4HVXF6EM --mask 255.255.255.255 --rsource -j KUBE-SEP-Q5HAFBJX4HVXF6EM
-A KUBE-SVC-UBXGHWUUHMMRNNE6 -m comment --comment "default/k8s-nginx-affinity:" -m recent --rcheck --seconds 10800 --reap --name KUBE-SEP-HDMJEKA4BFKBU6OK --mask 255.255.255.255 --rsource -j KUBE-SEP-HDMJEKA4BFKBU6OK
-A KUBE-SEP-HDMJEKA4BFKBU6OK -p tcp -m comment --comment "default/k8s-nginx-affinity:" -m recent --set --name KUBE-SEP-HDMJEKA4BFKBU6OK --mask 255.255.255.255 --rsource -m tcp -j DNAT --to-destination 10.244.0.145:80
-A KUBE-SVC-UBXGHWUUHMMRNNE6 -m comment --comment "default/k8s-nginx-affinity:" -m recent --rcheck --seconds 10800 --reap --name KUBE-SEP-HDMJEKA4BFKBU6OK --mask 255.255.255.255 --rsource -j KUBE-SEP-HDMJEKA4BFKBU6OK
-A KUBE-SEP-HDMJEKA4BFKBU6OK -p tcp -m comment --comment "default/k8s-nginx-affinity:" -m recent --set --name KUBE-SEP-HDMJEKA4BFKBU6OK --mask 255.255.255.255 --rsource -m tcp -j DNAT --to-destination 10.244.0.145:80
-m recent --set --name KUBE-SEP-HDMJEKA4BFKBU6OK --mask 255.255.255.255 --rsource
-A KUBE-SVC-UBXGHWUUHMMRNNE6 -m comment --comment "default/k8s-nginx-affinity:" -m recent --rcheck --seconds 10800 --reap --name KUBE-SEP-HDMJEKA4BFKBU6OK --mask 255.255.255.255 --rsource -j KUBE-SEP-HDMJEKA4BFKBU6OK
总结: