3.6 防火牆
防火牆可以由你設定條件,允許什麼連線可以連入、什麼連線禁止通過,限制條件包括服務、ip 及 port 等。
早期 CentOS 是使用 iptables 來設定防火牆,但現在有一個新的 firewalld 服務,可以讓操作更容易,它的底層仍是使用 iptables。
# 安裝
sudo yum install firewalld
# 啟動
systemctl start firewalld
# 開機時自動啟動
systemctl enable firewalld
# 目前狀態
systemctl status firewalld
防火牆的狀態可以查看目前是否正在運作及開機時是否自動啟動:
啟動防火牆後,就可以來設定限制條件了:
# 允許 SSH (22)
sudo firewall-cmd --permanent --add-service=ssh
# 允許 HTTP (80)
sudo firewall-cmd --permanent --add-service=http
# 允許 HTTPS (443)
sudo firewall-cmd --permanent --add-service=https
# 允許 MySQL (3306)
sudo firewall-cmd --permanent --add-service=mysql
# 移除服務
sudo firewall-cmd --permanent --remove-service=mysql
--permanent
表示條件永久有效,--add-service
表示允許通過的服務;要移除服務則使用 --remove-service
。
如果要針對 port 來設定:
# 允許的 port
sudo firewall-cmd --permanent --add-port=1234/tcp
--add-port
表示允許的 port 號,/tcp
表示使用 TCP 協定。
都設定好之後可以查看結果清單:
sudo firewall-cmd --permanent --list-all
結果可能如下:
public (active)
target: default
icmp-block-inversion: no
interfaces: eth0 eth1
sources:
services: ssh dhcpv6-client http https mysql
ports: 1234/tcp
protocols:
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:
當你都設定好之後,記得重新啟動防火牆讓設定生效:
# 重新載入設定檔
sudo firewall-cmd --reload
# 或重新啟動防火牆
systemctl restart firewalld
目前為止,我們針對服務及 port 來設定,允許它們可以通過防火牆。但是對於 ip 就不能這麼做,除非你的系統只允許某些人來使用,否則一個一個 ip 來設定允許連線是不太可能的事,因此我們要反過,允許所有的 ip 連線,但是禁止那些想做壞事的 ip。
# 拒絕 123.123.123.123 這個 ip 的連線
sudo firewall-cmd --permanent --zone=public --add-rich-rule="rule family='ipv4' source address='123.123.123.123/24' reject"
請對照前面 --list-all
的項目,我們對 public
這個區域,增加 rich rules
,拒絕 reject
它的連線,另外也可使用丟棄 drop
。
拒絕和丟棄兩者的差別是 reject
會回傳 「ICMP destination-unreachable (目的地無法訪問的 ICMP 訊息)」給來源機器;drop
(又稱黑洞) 則是直接把封包丟掉,對方不會收到任何訊息。至於用哪個則沒有定論,被指定為 reject
的來源主機會立即收到無法訪問的訊息,連線會立即中斷,它有可能誤以為伺服器不存在,因為訊息明確,屬於符合規範的動作;drop
則因為是個黑洞,來源主機不知道連線發生了什麼事,因此會保持連線一陣子,直到 timeout 才終止,來源端可能會發現自己被防火牆擋掉了。
3.7 Fail2ban
一開始我為了阻止想嘗試登入我的伺服器的 ip,寫了一支簡單的程式,搭配排程器使用,讓它定期去讀取 SSH 登入的 log 檔 /var/log/secure
,找出其中登入失敗超過一定次數的 ip ,將其加入防火牆中。如此一來,被加入防火牆黑名單的 ip,在連線抵達伺服器時就直接被擋在牆外,連嘗試登入的機會都沒有。
後來我找到 fail2ban 這個工具來幫我處理這件事,它可以在開機時就啟動並常駐在背景服務,依照我的設定決定封鎖什麼條件的非法連線,還可以指定永久封鎖或只封鎖一段時間。
3.7.1 安裝
# 安裝
sudo yum -y install fail2ban
# 啟動
systemctl start fail2ban
# 開機時啟動
systemctl enable fail2ban
# 查看狀態
systemctl status fail2ban
# 停止
systemctl stop fail2ban
# 重新啟動
systemctl restart fail2ban
fail2ban 服務的設定檔在 /etc/fail2ban/fail2ban.conf
,但是不要去修改這個檔案。
在 /etc/fail2ban
目錄中,所有的 .conf
都可以被 .local
覆寫;fail2ban 服務會先讀取 .conf
檔,然後再讀取 .local
檔,後面讀取的設定覆寫前面的;千萬不要去修改 .conf
檔,避免升級時發生錯誤。
3.7.2 設定 jail
要學會如何使用 fail2ban,就要先瞭解 jail (監獄)檔如何設定。
/etc/fail2ban/jail.conf
是一個設定樣板檔,它已經針對許多服務做了基本的設定,例如 SSH 登入服務的 sshd
、SSH DDOS 攻擊的 sshd-ddos
及 Apache、Nginx 等的樣板設定,記得不要去更動這個檔案的內容。
在 jail.conf
中的設定並不會被啟用,我們必須自行建立 jail.local
然後選擇需要的來啟用,並視需要䨱蓋樣板中的設定值。
jail 檔除了可以放在 /etc/fail2ban/
目錄下,還可以放在 /etc/fail2ban/jail.d
目錄下,可以讓每個 jail 獨立成一個檔案,方便管理。
現在,動手建立我們的 jail.local
:
cd /etc/fail2ban
vim jail.local
設定範例如下:
# 預設值,所有的 jail 通用
[DEFAULT]
# 封鎖 30 天 (單位:秒)
bantime = 2592000
# 或是永久封鎖
# bantime = -1
# 以下為兩個連動的參數,表示在限定時間內重試的次數
# 限定時間內(一天內,單位:秒)
findtime = 86400
# 重試的次數
maxretry = 3
# 意思是:只要在限定時間內重試超過限定的次數,就封鎖
# 針對 sshd 服務的 jail
[sshd]
# 啟用這個 jail
enabled = true
# 指定過濾器
filter = sshd
# 針對 ssh ddos 攻擊的 jail
[ssh-ddos]
enabled = true
# 指定 port
port = ssh,sftp
filter = sshd-ddos
# 指定 log 檔的位置
logpath = /var/log/messages
# 覆寫 [DEFAULT] 中的重試次數的設定
maxretry = 2
注意!設定項目與值間的等號 =
兩邊必須留空格。
每組 jail 以方括號 []
表示, [DEFAULT]
區塊指定的內容會套用到所有 jail 上。要知道有哪些 jail 可用,可以查看 jail.conf
中的 JAILS 這個區塊。
jail 選項的說明:
filter
:用來過濾要偵測的條件,一個 jail 只能有一個。logpath
:提供給filter
用的 log 檔路徑,預設值為/var/log/messages
。maxretry
:重試的最大次數,預設值 3 次。可以想像成提款機的密碼輸入錯誤最多 3 次,然後就鎖卡。findtime
:單位為秒,搭配maxretry
,指定在限定時間內允許的重試次數,例如 1 天內最多只能錯誤 3 次,超過就封鎖。預設值是 600 秒。bantime
:就是讓非法份子坐牢的時間,單位為秒,例如封鎖某個重試次數達最大值的 ip 1 天。預設值是 600 秒;把值指定為負值表示為 permanent (即無期徒刑,永久封鎖)。
fail2ban 提供 fail2ban-client
這個指令讓你使用:
# 啟動
sudo fail2ban-client start
# 停止
sudo fail2ban-client stop
# 重新載入設定(有修改 jail 內容時需執行)
sudo fail2ban-client reload
# 查 jail 狀態
sudo fail2ban-client status
# 顯示結果如下:
Status
|- Number of jail: 2 # <- 表示目前啟用的 jail 數量
`- Jail list: sshd, sshd-ddos # <- 啟用的 jail 清單
# 查指定 jail 的狀態,例如 sshd
sudo fail2ban-client status sshd
# 顯示結果如下:
Status for the jail: sshd
|- Filter
| |- Currently failed: 0 # <- 目前失敗的數量
| |- Total failed: 0 # <- 全部失敗的總數
| `- Journal matches: _SYSTEMD_UNIT=sshd.service + _COMM=sshd
`- Actions
|- Currently banned: 0 # <- 目前封鎖的數量
|- Total banned: 0 # <- 全部封鎖的總數
`- Banned IP list: # <- 已封鎖的 ip 清單
# 如果要查看 fail2ban 的 log
sudo tail -f /var/log/fail2ban.log
# 使用 tail 來看最後(最新)的 log 狀態
# -f 會持續更新,ctrl + c 離開
以上是針對 SSH 的設定範例,接下來是針對 Nginx 的一些設定範例。
3.7.3 Nginx 保護
3.7.3.1 針對 Forbidden 保護
當有人連到你的網站,但輸入錯誤的 URI 時,就會出現 forbidden (被禁止) 的訊息,大部份情況是單純輸入錯誤,但是有心人可能會亂猜你的 URI 來找漏洞,這時候可以使用 fail2ban 讓這些連線暫時關禁閉。
首先,建立 forbidden 過濾器 /etc/fail2ban/filter.d/nginx-forbidden.local
:
[Definition]
failregex = ^.* \[error\] \d+#\d+: .* forbidden.*,.* client: <HOST>.*, .*$
ignoreregex =
這個過濾器會去找出 Nginx 的 error.log 檔中出現 forbidden 的連線客戶端。
接著建立 /etc/fail2ban/jail.d/nginx-forbidden.local
:
[nginx-forbidden]
enabled = true
# 使用我們前面建立的過濾器
filter = nginx-forbidden
port = http,https
logpath = /var/log/nginx/error.log
# 一天內
findtime = 86400
# Forbidden 5 次
maxretry = 5
# 封鎖一天
bantime = 86400
3.7.3.2 針對登入錯誤的保護
建立 /etc/fail2ban/jail.d/nginx-http-auth.local
:
# 啟用 fail2ban 提供的 jail
[nginx-http-auth]
enabled = true
# 使用 fail2ban 提供的過濾器
filter = nginx-http-auth
port = http,https
logpath = /var/log/nginx/error.log
action = iptables-multiport[name=Forbidden, port="http,https"]
findtime = 86400
maxretry = 3
bantime = 86400
3.7.3.3 針對機器人的保護
建立 /etc/fail2ban/jail.d/nginx-badbots.local
:
[nginx-badbots]
enabled = true
port = http,https
filter = nginx-botsearch
logpath = /var/log/nginx/error.log
findtime = 86400
maxretry = 3
# 永久封鎖
bantime = -1
每當你完成一個 jail 設定檔時,最好先檢查是否有錯誤:
sudo fail2ban-client -d
如果沒出現 ERROR 的話就表示成功了,最後記得重新讀取設定檔:
sudo fail2ban-client reload
3.7.4 白名單
如果你想將某個 ip 區段加入白名單 (jail.local):
[DEFAULT]
# ...略
# 白名單,忽略的 ip 段,
# 以下為遮罩,一個 ip 共分為 4 段,第一段以 /8 表示,
# 意思是固定第一段的數值,後面則全部接受
# /8 表示 127.x.x.x 這段
# /16 表示 127.0.x.x 這段
# /24 表示 127.0.0.x 這段
ignoreip = 127.0.0.1/8 10.0.0.0/8 # <-- 以空白隔開不同段的 ip
3.7.5 解除封鎖
如果要取消被封鎖的 ip 讓它出獄:
sudo fail2ban-client set sshd unbanip 123.123.123.123
其他更詳細的設定,可以參考 fail2ban 操作手冊。
繼續閱讀:動手學 VPS 架站:使用 CentOS 7 + Nginx + PHP-FPM + MariaDB (7) - 網頁伺服器
由 Tony Blog 撰寫,請勿全文複製,轉載時請註明出處及連結,謝謝 😀
我要留言
留言小提醒:
1.回覆時間通常在晚上,如果太忙可能要等幾天。
2.請先瀏覽一下其他人的留言,也許有人問過同樣的問題。
3.程式碼請先將它編碼後再貼上。(線上編碼:http://bit.ly/1DL6yog)
4.文字請加上標點符號及斷行,難以閱讀者恕難回覆。
5.感謝您的留言,您的問題也可能幫助到其他有相同問題的人。