之前我介紹過利用 fail2ban 來封鎖嘗試使用暴力破解登入 ssh 的有心份子,但是如果你有嚴重的潔癖,看到滿滿的登入錯誤訊息就渾身不舒服想要更進一步降低此一風險,還有一些措施可以施作,其中最常見的建議就是不要使用預設的埠號 (TCP:22)。改用其他埠號雖然看似很有效,但是一旦遇到埠號掃描的攻擊行為並被有心份子知道實際使用的埠號,其實就跟使用預設埠號沒啥兩樣。如果我們可以隱藏實際使用的埠號,並於特殊情況下才予以現形,那就不用擔心埠號掃描的攻擊方式了。
我們可以利用 iptables 內建的 recent module 來達成此一目標,想要連結 ssh 服務的一方必須先對某個特定的埠號進行"敲門"動作,iptables 才會對此 IP 位址開放 ssh 服務所使用的埠號。以下我們就透過實際的例子來加以說明,實作的環境是 CentOS 6:
- 修改 ssh 服務所使用的埠號
ssh 服務的設定檔為 /etc/ssh/sshd_config,將
改為#Port 22
其中 2222 表示我們想要 sshd 服務所使用的埠號。Port 2222
- 重新啟動 ssh 服務
指令為service sshd restart
- 匯出 iptables 所使用的設定
指令為
如果你使用其他工具 (如webmin) 來設定 iptables,那麼就不需要進行 iptables 規則的匯入與匯出,可以直接加入所需規則。iptables-save > /tmp/iptables
- 修改 iptables 的規則
在 /tmp/iptables 適當的位置加入用紅色標示的兩行規則 (請務必加在 default policy 之前):
其中 54321 是我們用來敲門的埠號,而 2222 則是 ssh 服務實際上所使用的埠號。同時記得刪除 ssh 服務的預設規則-A INPUT -p tcp -m state --state NEW -m tcp --dport 3306 -j ACCEPT
-A INPUT -p tcp --dport 54321 -m recent --set --name SSH-PHASE1
-A INPUT -p tcp --dport 2222 -m recent --rcheck --seconds 5 --name SSH-PHASE1 -j ACCEPT
-A INPUT -j REJECT --reject-with icmp-host-prohibited
-A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT - 匯入 iptables 的規則
指令是iptables-restore < /tmp/iptables
- 測試新的規則
從另外一台主機執行下列指令
其中 ip_address 請換成前一台主機的 IP 位址。順利的話,應該可以看到 ssh 的登入提示符號。如果我們在 telnet 與 ssh 兩個指令之間停頓超過 5 秒,將無法連結至 ssh 服務,也就是說每次敲門後的開放只保留 5 秒,5 秒過後又自動加以關閉。如以一來,即使利用埠號掃描攻擊也很難發現 ssh 服務真正使用的埠號。telnet ip_address 54321; ssh ip_address –p 2222
- 刪除規則暫存檔
指令是rm –f /tmp/iptables
- 將規則寫入 iptables 的啟動設定
如果測試無誤,我們就可以把規則寫入 iptables 的啟動設定,以確保每次啟動 iptables 時都能套用此一設定。指令是service iptables save
透過兩行簡單的iptables 規則設定,我們大幅減少 ssh 服務埠號被偵測出的可能性,對 ssh 服務的保護將更加完善。最後,即使使用了 iptables 的敲門機制來保護 ssh 的服務埠, fail2ban 依舊有其必要性,理由如下:
- fail2ban 不只可用來保護 ssh 服務,還可以用來保護包含 ftp 與 pop3 在內的各項網路服務。
- 通常 iptables 規則中總會有些例外 IP 位址可以對系統暢行無阻,雖說這些 IP 位址多為內部使用,但是別忘了內部使用的 IP 位址並不等於絕對安全。
- 避免日後有人不小心移除了相關設定。相信我,這種糗事發生的機會比你想像中還來的高出許多。
- 一旦知道這個"敲門"用的埠號後,此一機制同樣可能遭受暴力攻擊。什麼人會知道這個敲門埠號?你猜對了,正是離職員工!