Linux中國

使用 fail2ban 和 FirewallD 黑名單保護你的系統

如果你運行的伺服器有面向公眾的 SSH 訪問,你可能遇到過惡意登錄嘗試。本文介紹了如何使用兩個實用程序來防止入侵者進入我們的系統。

為了防止反覆的 ssh 登錄嘗試,我們來看看 fail2ban。而且,如果你不經常旅行,基本上停留在一兩個國家,你可以將 FirewallD 配置為只允許從你選擇的國家訪問

首先,讓我們為不熟悉這些應用程序的人員介紹一些術語,以完成這項工作:

fail2ban:一個守護進程,用于禁止發生多次認證錯誤的主機。fail2ban 將監控 SystemD 日誌,以查找對任何已啟用的「 監獄 jail 」的失敗的驗證嘗試。在達到指定失敗次數後,它將添加一個防火牆規則,在配置的時間內阻止該特定 IP 地址。

FirewallD:一個帶有 D-Bus 介面的防火牆守護進程,提供動態防火牆。除非你另行決定使用傳統的 iptables,否則你已經在所有支持的 Fedora 和 CentOS 上安裝了 FirewallD。

假定前提

  • 主機系統有一個互聯網連接,並且要麼是直接暴露在互聯網上,要麼是通過 DMZ(這兩個都是非常糟糕的想法,除非你知道你在做什麼),要麼是有一個埠從路由器轉發過來。
  • 雖然大部分的內容可能適用於其他系統,但本文假設當前系統是 Fedora(31 及以上)或 RHEL/CentOS 8 版本。在 CentOS 上,你必須用 sudo dnf install epel-release 啟用 Fedora EPEL 倉庫。

安裝與配置

Fail2Ban

很有可能已經有某個 Firewalld 區已經允許 SSH 訪問,但 sshd 服務本身默認沒有啟用。要手動啟動它,並且不在啟動時永久啟用它:

$ sudo systemctl start sshd

或者在系統啟動時啟用,並同時啟動它:

$ sudo systemctl enable --now sshd

下一步就是安裝、配置、啟用 fail2ban。和往常一樣,安裝可以通過命令行完成:

$ sudo dnf install fail2ban

安裝完畢後,下一步就是配置「監獄」(你要以設置的任何閾值監視並禁止的服務)。默認情況下,IP 會被禁止 1 小時(這其實不夠長)。最好的做法是使用 *.local 文件覆蓋系統默認值,而不是直接修改 *.config 文件。如果我們查看我的 jail.local,我們可以看到:

# cat /etc/fail2ban/jail.local
[DEFAULT]

# "bantime" is the number of seconds that a host is banned.
bantime  = 1d

# A host is banned if it has generated "maxretry" during the last "findtime"
findtime  = 1h

# "maxretry" is the number of failures before a host get banned.
maxretry = 5

換成通俗的語言講,就是在過去一小時內嘗試 5 次後,該 IP 將被封禁 1 天。對於多次被封的 IP,也可以選擇增加封禁時間,但這是另一篇文章的主題。

下一步是配置「監獄」。在本教程中顯示的是 sshd,但其他服務的步驟大致相同。在 /etc/fail2ban/jail.d 中創建一個配置文件。這是我的文件:

# cat /etc/fail2ban/jail.d/sshd.local
[sshd]
enabled = true

就這麼簡單! 很多配置已經在為 Fedora 構建的軟體包中處理了(提示:我是當前的維護者)。接下來啟用並啟動 fail2ban 服務:

$ sudo systemctl enable --now fail2ban

希望沒有立即出錯,如果沒有,請使用下面的命令檢查 fail2ban 的狀態:

$ sudo systemctl status fail2ban

如果它沒有錯誤地啟動,應該是這樣的:

$ systemctl status fail2ban
● fail2ban.service - Fail2Ban Service
Loaded: loaded (/usr/lib/systemd/system/fail2ban.service; disabled; vendor preset: disabled)
Active: active (running) since Tue 2020-06-16 07:57:40 CDT; 5s ago
Docs: man:fail2ban(1)
Process: 11230 ExecStartPre=/bin/mkdir -p /run/fail2ban (code=exited, status=0/SUCCESS)
Main PID: 11235 (f2b/server)
Tasks: 5 (limit: 4630)
Memory: 12.7M
CPU: 109ms
CGroup: /system.slice/fail2ban.service
└─11235 /usr/bin/python3 -s /usr/bin/fail2ban-server -xf start
Jun 16 07:57:40 localhost.localdomain systemd[1]: Starting Fail2Ban Service…
Jun 16 07:57:40 localhost.localdomain systemd[1]: Started Fail2Ban Service.
Jun 16 07:57:41 localhost.localdomain fail2ban-server[11235]: Server ready

如果是剛剛啟動的,fail2ban 不太可能顯示任何有意思的信息,但要檢查 fail2ban 的狀態,並確保「監獄」被啟用,請輸入:

$ sudo fail2ban-client status
Status
|- Number of jail:      1
`- Jail list:   sshd

sshd 「監獄」的上級狀態也會顯示出來。如果啟用了多個「監獄」,它們會在這裡顯示出來。

要查看一個「監獄」的詳細狀態,只需在前面的命令中添加「監獄」名稱。下面是我的系統的輸出,它已經運行了一段時間。我已經從輸出中刪除了被禁止的 IP:

$ sudo fail2ban-client status sshd
Status for the jail: sshd
|- Filter
|  |- Currently failed: 8
|  |- Total failed:     4399
|  `- Journal matches:  _SYSTEMD_UNIT=sshd.service + _COMM=sshd
`- Actions
   |- Currently banned: 101
   |- Total banned:     684
   `- Banned IP list:   ...

監控 fail2ban 日誌文件是否有入侵嘗試,可以通過「尾隨」日誌來實現:

$ sudo tail -f /var/log/fail2ban.log

tail 是一個很好的命令行工具,默認情況下,它可以顯示一個文件的最後 10 行。添加 -f 告訴它尾隨文件,這是個觀察一個仍在被寫入的文件的很好方式。

由於輸出的內容中有真實的 IP,所以這裡不會提供樣本,但它的可讀性很高。INFO 行通常是登錄的嘗試。如果從一個特定的 IP 地址進行了足夠多的嘗試,你會看到一個 NOTICE 行顯示一個 IP 地址被禁止。在達到禁止時間後,你會看到一個 NOTICE 解禁行。

注意幾個警告行。最常見的情況是,當添加了一個禁止後,fail2ban 發現該 IP 地址已經在其禁止資料庫中,這意味著禁止可能無法正常工作。如果是最近安裝的 fail2ban 包,它應該被設置為 FirewallD 的富規則。這個包在 fail2ban-0.11.1-6 版本時從 ipset 方式切換到了富規則方式,所以如果你的 fail2ban 安裝時間較早,它可能還在嘗試使用 ipset 方式,這種方式使用的是傳統的 iptables,不是很可靠。

FirewallD 配置

被動還是主動?

有兩種策略可以分開或一起使用:被動地將單個 IP 地址或主動地根據來源國將子網永久列入黑名單。

對於被動方式,一旦 fail2ban 運行了一段時間,最好再運行 sudo fail2ban-client status sshd 來看看有哪些壞蛋。很可能會有很多被禁止的 IP 地址。選擇一個,然後試著對它運行 whois。在輸出結果中可能會有很多有趣的信息,但是對於這個方法來說,只有來源國是重要的。為了保持簡單,讓我們過濾掉除了國家以外的所有信息。

在這個例子中,我們將使用一些著名的域名:

$ whois google.com | grep -i country
Registrant Country: US
Admin Country: US
Tech Country: US
$ whois rpmfusion.org | grep -i country
Registrant Country: FR
$ whois aliexpress.com | grep -i country
Registrant Country: CN

使用 grep -i 的原因是為了使 grep 不區分大小寫,而大多數條目都使用的是 「Country」,而有些條目則是全小寫的 「country」,所以這種方法無論如何都能匹配。

現在知道了嘗試入侵的來源國,問題是,「是否有來自這個國家的人有合法的理由連接到這台計算機?」如果答案是否定的,那麼封鎖整個國家應該是可以接受的。

從功能上看,主動式方法它與被動式方法沒有太大區別,然而,來自有些國家的入侵企圖是非常普遍的。如果你的系統既不放在這些國家裡,也沒有任何源自這些國家的客戶,那麼為什麼不現在就把它們加入黑名單而是等待呢?(LCTT 譯註:我的經驗是,動輒以國家的範疇而列入黑名單有些過於武斷。建議可以將該 IP 所屬的 WHOIS 網段放入到黑名單,因為這些網段往往具有相同的使用性質,如都用於用戶接入或 IDC 託管,其安全狀況也大致相同,因此,如果有來自該網段的某個 IP 的惡意嘗試,可以預期該網段內的其它 IP 也可能被利用來做這樣的嘗試。)

黑名單腳本和配置

那麼如何做到這一點呢?用 FirewallD ipset。我開發了下面的腳本來儘可能地自動化這個過程:

#!/bin/bash
# Based on the below article
# https://www.linode.com/community/questions/11143/top-tip-firewalld-and-ipset-country-blacklist

# Source the blacklisted countries from the configuration file
. /etc/blacklist-by-country

# Create a temporary working directory
ipdeny_tmp_dir=$(mktemp -d -t blacklist-XXXXXXXXXX)
pushd $ipdeny_tmp_dir

# Download the latest network addresses by country file
curl -LO http://www.ipdeny.com/ipblocks/data/countries/all-zones.tar.gz
tar xf all-zones.tar.gz

# For updates, remove the ipset blacklist and recreate
if firewall-cmd -q --zone=drop --query-source=ipset:blacklist; then
    firewall-cmd -q --permanent --delete-ipset=blacklist
fi

# Create the ipset blacklist which accepts both IP addresses and networks
firewall-cmd -q --permanent --new-ipset=blacklist --type=hash:net 
    --option=family=inet --option=hashsize=4096 --option=maxelem=200000 
    --set-description="An ipset list of networks or ips to be dropped."

# Add the address ranges by country per ipdeny.com to the blacklist
for country in $countries; do
    firewall-cmd -q --permanent --ipset=blacklist 
        --add-entries-from-file=./$country.zone && 
        echo "Added $country to blacklist ipset."
done

# Block individual IPs if the configuration file exists and is not empty
if [ -s "/etc/blacklist-by-ip" ]; then
    echo "Adding IPs blacklists."
    firewall-cmd -q --permanent --ipset=blacklist 
        --add-entries-from-file=/etc/blacklist-by-ip && 
        echo "Added IPs to blacklist ipset."
fi

# Add the blacklist ipset to the drop zone if not already setup
if firewall-cmd -q --zone=drop --query-source=ipset:blacklist; then
    echo "Blacklist already in firewalld drop zone."
else
    echo "Adding ipset blacklist to firewalld drop zone."
    firewall-cmd --permanent --zone=drop --add-source=ipset:blacklist
fi

firewall-cmd -q --reload

popd
rm -rf $ipdeny_tmp_dir

這個應該安裝到 /usr/local/sbin,不要忘了讓它可執行!

$ sudo chmod +x /usr/local/sbin/firewalld-blacklist

然後創建一個配置文件 /etc/blacklist-by-country

# Which countries should be blocked?
# Use the two letter designation separated by a space.
countries=""

而另一個配置文件 /etc/blacklist-by-ip,每行只有一個 IP,沒有任何額外的格式化。

在這個例子中,從 ipdeny 的區文件中隨機選擇了 10 個國家:

# ls | shuf -n 10 | sed "s/.zone//g" | tr 'n' ' '
nl ee ie pk is sv na om gp bn

現在只要在配置文件中加入至少一個國家,就可以運行了!

$ sudo firewalld-blacklist
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   142  100   142    0     0   1014      0 --:--:-- --:--:-- --:--:--  1014
100  662k  100  662k    0     0   989k      0 --:--:-- --:--:-- --:--:--  989k
Added nl to blacklist ipset.
Added ee to blacklist ipset.
Added ie to blacklist ipset.
Added pk to blacklist ipset.
Added is to blacklist ipset.
Added sv to blacklist ipset.
Added na to blacklist ipset.
Added om to blacklist ipset.
Added gp to blacklist ipset.
Added bn to blacklist ipset.
Adding ipset blacklist to firewalld drop zone.
success

要驗證 FirewallD 黑名單是否成功,請檢查 drop 區和 blacklist ipset。

$ sudo firewall-cmd --info-zone=drop
drop (active)
  target: DROP
  icmp-block-inversion: no
  interfaces:
  sources: ipset:blacklist
  services:
  ports:
  protocols:
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:

$ sudo firewall-cmd --info-ipset=blacklist | less
blacklist
  type: hash:net
  options: family=inet hashsize=4096 maxelem=200000
  entries:

第二條命令將輸出所有的子網,這些子網是基於被封殺的國家而添加的,可能會相當長。

那麼現在我該怎麼做?

雖然在開始的時候,監控的頻率會比較高,但隨著時間的推移,入侵嘗試的次數應該會隨著黑名單的增加而減少。那麼目標應該是維護而不是主動監控。

為此,我創建了一個 SystemD 服務文件和定時器,這樣每月都會刷新由 ipdeny 維護的每個國家的子網。事實上,這裡討論的所有內容都可以從我的 pagure.io 項目中下載。

是不是很高興你看完了整篇文章?現在只要把服務文件和定時器下載到 /etc/systemd/system/,並啟用定時器就行了:

$ sudo systemctl daemon-reload
$ sudo systemctl enable --now firewalld-blacklist.timer

via: https://fedoramagazine.org/protect-your-system-with-fail2ban-and-firewalld-blacklists/

作者:hobbes1069 選題:lujun9972 譯者:wxy 校對:wxy

本文由 LCTT 原創編譯,Linux中國 榮譽推出


本文轉載來自 Linux 中國: https://github.com/Linux-CN/archive

對這篇文章感覺如何?

太棒了
0
不錯
0
愛死了
0
不太好
0
感覺很糟
0
雨落清風。心向陽

    You may also like

    Leave a reply

    您的郵箱地址不會被公開。 必填項已用 * 標註

    此站點使用Akismet來減少垃圾評論。了解我們如何處理您的評論數據

    More in:Linux中國