Linux

使用 nftables 創建動態黑名單

  • April 24, 2020

我想用 nftables 創建一個動態黑名單。在嵌入式設備上的 0.8.3 版本下,我使用 nft list 規則集創建了一個如下所示的規則集:

table inet filter {
set blackhole {
   type ipv4_addr
   size 65536
   flags timeout
}

chain input {
   type filter hook input priority 0; policy drop;
   ct state invalid drop
   ct state established,related accept
   iif "lo" accept
   ip6 nexthdr 58 icmpv6 type { destination-unreachable, packet-too-big, time-exceeded, parameter-problem, echo-request, echo-reply, mld-listener-query, mld-listener-report, mld-listener-done, nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert, ind-neighbor-solicit, ind-neighbor-advert, mld2-listener-report } accept
   ip protocol icmp icmp type { echo-reply, destination-unreachable, echo-request, router-advertisement, router-solicitation, time-exceeded, parameter-problem } accept
   ip saddr @blackhole counter packets 0 bytes 0 drop
   tcp flags syn tcp dport ssh meter flood { ip saddr timeout 1m limit rate over 10/second burst 5 packets}  set add ip saddr timeout 1m @blackhole drop
   tcp dport ssh accept
}

chain forward {
   type filter hook forward priority 0; policy drop;
}

chain output {
   type filter hook output priority 0; policy accept;
}
}

對我來說,這只是一個臨時解決方案。我想使用官方手冊頁中的範例進行動態黑名單。如果我使用手冊頁中的官方範例,我的 nftables 文件如下所示:

table inet filter {
set blackhole{
       type ipv4_addr
       flags timeout
       size 65536
}
chain input {
       type filter hook input priority 0; policy drop;

       # drop invalid connections
       ct state invalid drop

       # accept traffic originating from us
       ct state established,related accept

       # accept any localhost traffic
       iif lo accept

       # accept ICMP
       ip6 nexthdr 58 icmpv6 type { destination-unreachable, packet-too-big, time-exceeded, parameter-problem, echo-request, echo-reply, mld-listener-query, mld-listener-report, mld-listener-done, nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert, ind-neighbor-solicit, ind-neighbor-advert, mld2-listener-report } accept
       ip protocol icmp icmp type { destination-unreachable, router-solicitation, router-advertisement, time-exceeded, parameter-problem, echo-request, echo-reply } accept

       # accept SSH (port 22)
       ip saddr @blackhole counter drop
       tcp flags syn tcp dport ssh meter flood { ip saddr timeout 10s limit rate over 10/second} add @blackhole { ip saddr timeout 1m } drop
       tcp dport 22 accept

}


chain forward {
       type filter hook forward priority 0; policy drop;
}

chain output {
       type filter hook output priority 0; policy accept;
}

}

但是,當我使用 nft -f myfile 在版本 0.8.3 上傳入此 nftables 文件時,我收到此錯誤:

Error: syntax error, unexpected add, expecting newline or semicolon
   tcp flags syn tcp dport ssh meter flood { ip saddr timeout 10s limit rate over 10/second} add @blackhole { ip saddr timeout 1m } drop

我不知道為什麼會這樣,但根據wiki,它應該從 0.8.1 版和核心 4.3 版開始工作。

我有版本 0.8.3 和核心 4.19.94。

我已經在 Debian Buster 下測試了官方手冊頁中 0.9.0 版的規則集。手冊頁中的規則集適用於 Debian,但 ip 僅被阻止一次。

在這個例子中,我想創建一個防火牆規則,如果對我的設備啟動暴力攻擊,它會阻止 ssh 埠上的 ip 地址。但我想阻止 ip 例如 5 分鐘。在那之後,應該可以從攻擊者的 ip 再次連接到設備。如果他再次進行暴力破解,則應再次阻止 ip 5 分鐘,依此類推。如果可以使用 nftables,我想避免為我的嵌入式設備使用其他軟體,如 sshguard 或 fail2ban。

我希望任何人都可以幫助我。謝謝!

hydra工具同時多次連接到 SSH 伺服器。在 OP 的情況下(comment : hydra -l <username> -P </path/to/passwordlist.txt> -I -t 6 ssh://<ip-address>)它將使用 6 個並發執行緒連接。

根據伺服器設置,一個連接通常可以嘗試 5 或 6 個密碼,並且在被 SSH 伺服器拒絕之前大約需要 10 秒,所以我看不到如何超過每秒10 次連接嘗試的速率(但就是這種情況) . 這可能意味著觸發的是超過 5 次連接嘗試在不到 1/2 秒內完成。我不太相信 的準確性10/s,但可以假設它發生在這裡。

版本和語法問題

不適用於 0.8.1 或 0.8.3 版本的語法是此送出中出現的較新語法:

src:重新訪問語法以從數據包路徑更新集合和映射

對於集合,我們允許這樣做:

  nft add rule x y ip protocol tcp update @y { ip saddr}

$$ … $$

它是在 0.8.3 版之後送出的,因此僅適用於 nftables >= 0.8.4

在同一頁面中,從數據包路徑更新集的目前 wiki 修訂版仍顯示具有前一種語法的命令

 % nft add rule filter input set add ip saddr @myset

$$ … $$

並以較新的語法顯示結果:

$$ … $$

                add @myset { ip saddr }

$$ … $$

某些 wiki 頁面或最新的聯機幫助頁可能不適用於較舊的 nftables 版本。

無論如何,如果使用核心 4.19 執行,應首選*nftables >= 0.9.0 以獲得附加功能。*例如,它在Debian 10Debian 9 backports中可用。

黑名單應該在有狀態的接受規則之前完成

一旦 IP 被添加到黑名單中,這並不會阻止已建立的連接繼續進行,不受阻礙和無人問津,直到它們被 SSH 伺服器本身斷開連接。那是因為之前通常存在短路規則:

        # accept traffic originating from us
        ct state established,related accept

此評論具有誤導性:它不接受來自我們的流量,任何流量已經在進行。這是一個短路規則。它的作用是通過只為新連接解析所有規則來處理有狀態的連接:此規則之後的任何規則都適用於新連接。一旦連接被接受,它們各自的數據包就會一直被接受,直到連接結束。

對於黑名單處理的具體案例,應將具體的黑名單規則或其中的一部分放在這條短路規則之前,以便能夠立即生效。在OP的情況下是:

        ip saddr @blackhole counter drop

它應該在ct state established,related accept規則之前移動。

現在,一旦將攻擊者添加到黑名單中,其他正在進行的連接將無法獲得一些剩餘的免費嘗試來猜測密碼:它們將立即掛起。

如果有黑名單,請考慮白名單

作為旁注,廉價iif lo accept規則本身可以作為優化和列入白名單之前移動:所有(甚至長期存在的)本地建立的連接現在也將被列入黑名單,以防濫用(例如:從 127.0.0.1 開始) . 考慮在規則前添加各種白名單規則@blackhole

可選擇更快地警告應用程序

為了防止來自伺服器的持續回復到達黑名單 IP(特別是對於 UDP 流量,對 TCP,包括 SSH 沒有多大用處),daddr也可以在inet filter output鏈中添加等效規則 using,拒絕以更快地通知本地程序試圖發出它們應該中止的資訊:

   ip daddr @blackhole counter reject

集合之間的差異addupdate應用於集合

現在有了這樣的設置,即使正在進行的連接立即停止,攻擊者也能夠繼續嘗試並在 1 百萬之後獲得一個新的短視窗,這不是最佳的。

條目必須在輸入規則中*更新。*如果條目已經存在,將刷新計時器,而什麼也不做。這將繼續阻止任何進一步(不成功)連接到 SSH 伺服器的嘗試,直到攻擊者放棄,打開視窗為零。(我上面添加的輸出規則不應該改變,這不是攻擊者的行為):@blackhole ... drop``update``add

代替:

ip saddr @blackhole counter drop

with(仍然保留舊語法):

ip saddr @blackhole counter set update ip saddr timeout 1m @blackhole drop

它甚至應該在ct state invalid規則之前移動,否則如果攻擊者嘗試無效數據包(例如 TCP 數據包不是已知連接的一部分,例如來自已經忘記的連接的延遲 RST),則該集合將不會被更新,而它本來可以更新。

限制已建立連接的最大數量

需要核心 >= 4.18 和 nftables >= 0.9.0,因此無法使用 OP 的目前配置完成。

攻擊者可能會發現它不能一次連接太多次,但只要連接速度不要太快,它仍然可以無限制地繼續添加新連接。

還可以使用其他計量規則添加對並發連接的限制(可用於 iptables ):connlimit

tcp flags syn tcp dport 22 meter toomanyestablished { ip saddr ct count over 3 } reject with tcp reset

將允許任何給定的 IP 地址只有 3 個已建立的 SSH 連接。

或者,同時觸發 @blackhole 集(這次使用更新的語法):

tcp flags syn tcp dport 22 meter toomanyestablished { ip saddr ct count over 3 } add @blackhole { ip saddr timeout 1m } drop

在 OP 的情況下,這甚至應該在之前的計量規則之前觸發。小心使用以避免合法使用者受到影響(但請參閱 openssh 的ControlMaster選項)。

IPv4 和 IPv6

由於沒有通用的 IPv4+IPv6 集地址類型,所有處理 IPv4 的規則(只要有 2 個字母 word ip)可能應該複製到ip6其中包含並處理 IPv6 集的鏡像規則中。

引用自:https://unix.stackexchange.com/questions/581964