如何阻止傳入的 IPv6 片段?
我的防火牆配置有問題。我想阻止特定介面中的所有 IPv6 分段數據包。所以,我嘗試了:
# ip6tables -A INPUT -d <ipv6_address> -i eth0 -m ipv6header --header ipv6-frag --soft -j DROP
但 IPv6 碎片化流量不斷湧入。
我還找到了這個連結:https ://www.secfu.net/2015/03/25/how-to-block-incoming-ipv6-fragments-in-latest-red-hat-releases/,它解釋了ipv6-在最新的 CentOS 中,frag 或 frag 不會阻止 ipv6 分段流量,因為在 bug id 1011214 (kernel-2.6.32-437.el6) 之後 netfilter 開始處理重新組裝的數據包而不是碎片,就像 IPv4 那樣。同一篇文章建議使用如下所示的 nftables:
table ip6 filter { chain preroute500 { type filter hook prerouting priority -500; policy accept; ip6 nexthdr ipv6-frag counter packets 2 bytes 2104 } }
我怎樣才能使用 ip6tables 做類似的事情?
# cat /etc/system-release CentOS Linux release 7.5.1804 (Core) # uname -r 5.0.8-1.el7.elrepo.x86_64
如前所述,您應該確保阻塞片段確實是您的目標,而不是您認為最適合您的目標的方法,但會有更好的方法存在。無論如何,為了它的價值,你必須:
- 使用足夠新的核心。該功能是在核心 4.16 中添加的。CentOS 使用 3.10。雖然許多功能都被向後移植(從 nftables 開始,它在 vanilla 3.10 核心上不可用,但在 RHEL/CentOS 的 3.10 上),但從最新的 CentOS 7.6 核心開始,這個特性並沒有被向後移植。由於您使用的是“elrepo”5.0.8 核心,因此該功能存在。這是功能描述及其存在的原因(主要用於路由,或至少用於無狀態/非 NAT 防火牆路由情況):
網路過濾器:nf_defrag:
如果設置了 NOTRACK,則跳過碎片整理 conntrack 碎片整理僅在某些模組(如 CONNTRACK 或 NAT)明確請求時才需要。對於普通轉發場景,不需要碎片整理,如果在規則中設置了 NOTRACK,則可以跳過。
由於 conntrack defrag 目前的優先級高於原始表,因此設置 NOTRACK 是不夠的。我們只需要為 iptables 將 raw 移到更高的優先級。
這是通過引入模組參數“raw_before_defrag”來實現的,該參數允許更改原始表的優先級以將其放在碎片整理之前。預設情況下,該參數被禁用,原始表的優先級為 NF_IP_PRI_RAW 以支持傳統行為。如果啟用了模組參數,則原始表的優先級設置為 NF_IP_PRI_RAW_BEFORE_DEFRAG。
- (如果需要刪除現有的原始 ip6tables 規則,解除安裝並)
ip6table_raw
使用參數載入模組raw_before_defrag=1
,因此原始的鉤子(在 PREROUTING 中)在碎片整理的 -400 之前從 prio -300 切換到 -450。modprobe ip6table_raw raw_before_defrag=1
這應該得到一個核心消息,如
ip6table_raw: Enabling raw table before defrag
現在在
raw
表中,並且可能僅在 中有意義PREROUTING
,ip6tables將能夠看到片段。它可以在那裡過濾它們,或者選擇跳過 conntrack (iptables -t raw -A PREROUTING ... -j CT --notrack
),正如功能更新檔中所解釋的,這也將跳過碎片整理,允許其他鏈處理它們(當然不包括nat
表的鍊或任何其他與 conntrack 相關的功能)。請注意,要見證測試網路命名空間中描述的問題,必須首先人為地為conntrack與**defrag的依賴項啟用conntrack操作,直到第一次需要時才會啟動。這是一個網路命名空間範例:
ip netns add sender ip netns add receiver ip -n sender link add veth0 address 02:00:00:00:00:01 type veth peer netns receiver name veth0 address 02:00:00:00:00:02 ip -n sender link set veth0 up ip -n receiver link set veth0 up
這有效:
# ip netns exec sender ping6 -s 4000 fe80::ff:fe00:2%veth0 PING fe80::ff:fe00:2%veth0(fe80::ff:fe00:2%veth0) 4000 data bytes 4008 bytes from fe80::ff:fe00:2%veth0: icmp_seq=1 ttl=64 time=0.069 ms ^C
在此之後,它將不再起作用:
ip netns exec receiver ip6tables -A INPUT -m ipv6header --header ipv6-frag --soft -j DROP
一旦conntrack在網路命名空間中啟動,這些命令顯然會導致無操作:
ip netns exec receiver ip6tables -A INPUT -m conntrack --ctstate ESTABLISHED ip netns exec receiver ip6tables -D INPUT -m conntrack --ctstate ESTABLISHED
ipv6 碎片整理也被啟動。現在之前的 ping 將始終有效,因為 INPUT 中的規則只看到碎片整理的數據包。
使用先前(重新)載入
ip6table_raw
的帶有參數的模組raw_before_defrag=1
,這將恢復碎片 ping 的阻塞:ip netns exec receiver ip6tables -t raw -A PREROUTING -m ipv6header --header ipv6-frag --soft -j DROP
或者,可以將感興趣的數據包標記為notrack,從而免除它們的conntrack,因此也不接受碎片整理
filter/INPUT
處理,從而允許使用鏈中的規則再次過濾它們。因此,與之前的raw
規則不同,這也會阻止 ping 數據包(每個 ping 有 3 個),但這次又在filter/INPUT
鏈中:ip netns exec receiver ip6tables -t raw -A PREROUTING -m ipv6header --header ipv6-frag --soft -j CT --notrack
這只是一個沒有多大意義的例子。