iptables -A INPUT -f -j DROP 丢弃碎片规则无效

参考网址:https://ask.csdn.net/questions/1059469

练习iptables的攻击规则,发现如下的命令无效。
iptabled -A INPUT -f -j DROP

测试
win10: 192.168.0.2
linux: 192.168.0.5
测试1:无分片的报文
win10# ping 192.168.0.5 -->可以ping通 
测试2:带分片的报文
win10# ping 192.168.0.5 -l 3000 -->可以ping通 
测试3:linux过滤分片的报文
linux# iptables -A INPUT -f -j DROP
win10# ping 192.168.0.5 -l 3000 -->依旧可以ping通 
linux# iptables -nvL
Chain INPUT (policy ACCEPT 6729 packets, 8666K bytes)
num   pkts bytes target     prot opt in     out     source               destination
1        0     0 DROP       all  -f  *      *       0.0.0.0/0            0.0.0.0/0
可以发现,规则没有匹配到任何一个报文。

网上找到关于 -f 分片的说明:

iptables -A INPUT -f
Dropping IP fragments is probably obsolete advice: the Linux kernel can and will automatically re-assemble and sanity-check all fragments as needed anyway. This happens before packets are handled by iptables connection tracking, so it is likely this rule may never match anything.

找到kernel 对于碎片整理的代码

p_input.c
ip_rcv()
{
    return NF_HOOK(NFPROTO_IPV4, NF_INET_PRE_ROUTING,
               net, NULL, skb, dev, NULL,
               ip_rcv_finish);
}
net/ipv4/netfilter/nf_defrag_ipv4.c
static struct nf_hook_ops ipv4_defrag_ops[] = {
    {
        .hook       = ipv4_conntrack_defrag,
        .pf     = NFPROTO_IPV4,
        .hooknum    = NF_INET_PRE_ROUTING,          #注册的链
        .priority   = NF_IP_PRI_CONNTRACK_DEFRAG,   #优先级
    }

发现defrag(碎片整理) 在PRE_ROUTING chain处理的,优先于INPUT chain 处理。
猜想可能是defrag导致 iptables -f无效,于是在ubuntu上做如下验证。

猜想验证:
linux
#kernel配置文件
/usr/src/linux-headers-4.4.0-148-generic/.config
CONFIG_NF_DEFRAG_IPV4=m
lsmod|grep nf_defrag_ipv4 #确认没有加载此模块
win10:
win10# ping 192.168.0.5 -l 3000 -->依旧可以ping通
 
Linux# iptables -nvL #发现依旧匹配没有匹配到数据包
验证结论:与defrag 功能无关。

计划:
看iptables -f 在netfilter 处理逻辑的,代码是否调用到相关的函数。

问题:
请问大家,相关的背景,原理。
针对测试,有相关的解决解决方案。

2020/03/20 更新

测试环境变更
win10: 192.168.0.2
Getway: 10.110.14.5
Dest_IP:10.110.14.16
分析:
1.报文分析
win10# ping xxx -l 3000 -n 1
一共发出三个报文,wireshark 抓到信息
No1 tcp ip.len=1500 flag=0x2000
No2 tcp ip.len=1500 flag=0x2000
No3 icmp ip.len=68 flag=0x0x72
2.linux调试
kernel/net/ip_input.c
int ip_rcv()
{
    ...
    if((iph->protocol == 1) && ip_is_fragment(iph)){
        printk("xxx find icmp frag len=%d id=%x s%x d%x\n",ntohs(iph->tot_len),ntohs(iph->id),
                ntohs(iph->saddr),ntohs(iph->daddr));
    }
}
可以打印出这个三个报文。
3.验证1:iptables 是否能匹配到这三个报文。
在iptables PREROUTING, INPUT添加如下规则
iptables -t mangle -A PREROUTING  -s 192.168.0.2 -d 10.110.14.16 -j LOG --log-prefix "11 mangle"
iptables -t mangle -A PREROUTING  -s 192.168.0.2 -d 10.110.14.16 -f -j LOG --log-prefix "12 mangle"
iptables -t nat -A PREROUTING  -s 192.168.0.2 -d 10.110.14.16 -j LOG --log-prefix "22 nat"
iptables  -I INPUT 10 -s 192.168.0.2 -d 10.110.14.16 -j LOG --log-prefix "33 filt"
dmesg 打印log:
[ 3188.325756] 11 mangleIN=BR_LAN OUT= MAC=d8:6c:a1:2f:37:a7:e8:4e:06:66:93:50:08:00 SRC=192.168.0.2 DST=10.110.14.16 LEN=3028 TOS=0x00 PREC=0x00 TTL=128 ID=22063 PROTO=ICMP TYPE=8 CODE=0 ID=1 SEQ=2847
[ 3188.343275] 22 natIN=BR_LAN OUT= MAC=d8:6c:a1:2f:37:a7:e8:4e:06:66:93:50:08:00 SRC=192.168.0.2 DST=10.110.14.16 LEN=3028 TOS=0x00 PREC=0x00 TTL=128 ID=22063 PROTO=ICMP TYPE=8 CODE=0 ID=1 SEQ=2847
验证结论:
1.对比第1,2条规则:
  1.ID=22063(分片报文标志MF 0x2000)说明分片报文。
  2.-f 无法匹配ip报文MF标志位。
  3.defrag的优先级是高于mangle PREROUTING的,此处LEN=3028应该是完整报文(待验证)。但No1,No2两个分片报文确认没有匹配。
2.对比第1,4规则:
  1.此处验证有误,由于是getway,需要在FORWARD中匹配。
4.验证2:直接在ip_rcv中丢弃报文
kernel/net/ip_input.c
int ip_rcv()
{
    ...
    if((iph->protocol == 1) && ip_is_fragment(iph)){
        printk("xxx find icmp frag len=%d id=%x s%x d%x\n",ntohs(iph->tot_len),ntohs(iph->id),
                ntohs(iph->saddr),ntohs(iph->daddr));
+       goto drop;
    }
}
win10# ping xxx -l 3000 -n 1
结果:ping failed
 
验证结论:
1.使用ip_is_fragment() 判断可行。
计划:
1.此处修改不符合规范,暂定使用iptable 新增模块来实现。
2.很好奇-f 到底是如何匹配报文,暂未找到代码实现。
 

2020/03/24 更新
解决方法

echo 0 > /proc/sys/net/ipv4/ipfrag_low_thresh
echo 0 > /proc/sys/net/ipv4/ipfrag_high_thresh

Change fragments buffer to 0. Drop fragments packages.

总结:其实就是两种解决方法

方法一:iptables

iptabled -t raw -A PREROUTING -f -j DROP

方法二:修改proc文件系统

echo 0 > /proc/sys/net/ipv4/ipfrag_low_thresh
echo 0 > /proc/sys/net/ipv4/ipfrag_high_thresh

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值