Firewall

如何阻止傳入的 IPv6 片段?

  • April 23, 2019

我的防火牆配置有問題。我想阻止特定介面中的所有 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表中,並且可能僅在 中有意義PREROUTINGip6tables將能夠看到片段。它可以在那裡過濾它們,或者選擇跳過 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

這只是一個沒有多大意義的例子。

引用自:https://serverfault.com/questions/964072