獲取聯絡與訂閱

ufw 實例幾則

2021.06.18

從簡化 iptables 開始

不可否認 iptables 始終是 Linux 網路模塊不可或缺的核心, 然而近些年來的 Linux 發行版總是熱衷於透過各類基於 iptables 的上層管理工具間接為用戶簡化 Linux 下網路模塊的操作流程從而降低管理門檻, 這也從一個側面反映出在大多數情況下 iptables 的諸多特性並不適用於 普通 用戶. 這實際上源於普通用戶的網路管理需求往往僅限於允許拒絕及轉發等這類簡單的常規策略, 顯而易見的是 ufw 等基於 iptables 的上層管理工具可以高效快速的完成同類別的任務, 並在一定程度上確保普通用戶的過失操作無法影響到核心的網路模塊. 也正因如此, 不妨對上述幾點常規策略的運用實例作整理, 以便作日後參照.

實例概要

允許訪問指定端口

這是 ufw 最為基礎的語法之一, 實際上其用法也非常靈活, 適用於各類普通用戶的快速配置與部署. 同時需要稍作贅述的是, 在此之前需要透過 ufw enable 啟用並在每項規則添加後透過 ufw reload 重新加載從而使其生效.

ufw allow ssh
ufw allow 22/tcp

上述兩則命令的效果完全相同, 這是由於 ufw 內附部分常見服務的默認端口, 與此相同的還有:

ufw allow http
ufw allow 80/tcp

ufw allow https
ufw allow 443/tcp

需要注意的是 ufw 始終 以相關服務的默認端口為基準 配置, 如果你的 ssh 端口並不在 22/tcp 上那 ufw 也並不能夠正確完成 ufw allow ssh 的語法, 同類規則也都同理.

僅允許來自特定地址的訪問

對此實例非常有代表性的是時常遇到的部分服務僅對某些網路段開放, 這一簡單的配置往往能夠極大地提升安全性並確保服務的可用. 不妨以只允許 10.0.0.0/8 這一內網段訪問設備上的 https 服務為例:

ufw allow from 10.0.0.0/8 to any port 443 proto tcp

如果需要同時指定 tcpudp 可以寫作兩則或直接去掉協議規則:

ufw allow from 10.0.0.0/8 to any port 443

進一步也可得到當需要允許來自特定地址的所有訪問時:

ufw allow from 10.0.0.0/8

所有的配置之後切勿忘記 ufw reload 重新加載使其生效.

僅允許來自 Cloudflare 的訪問

承上接下地講, 我們可以透過上述語法快速添加 Cloudflare 的 IP 段作為部分服務的白名單, 從而達到僅允許 CDN 連接的效果, 有效避免繞過 CDN 的攻擊:

for cloudflare in `curl https://www.cloudflare.com/ips-v4`; do ufw allow proto tcp from $cloudflare to any port 443; done
for cloudflare in `curl https://www.cloudflare.com/ips-v6`; do ufw allow proto tcp from $cloudflare to any port 443; done

端口轉發

對這一常見的需求我們往往有許多選擇, 但從穩定性和性能上講, 如果直接在網路模塊核心完成端口轉發, 而不依賴於其他工具或系統服務顯然是最好不過. ufw 的端口轉發儘管並不能夠直接透過命令使用, 但總體流程依然非常簡單方便. 首先需要在 /etc/default/ufw 中配置轉發開關, 同時在 /etc/ufw/sysctl.conf 啟用轉發規則, 隨後便可以在 /etc/ufw/before.rules 中部署轉發規則了, 其語法如下:

# NAT Table rules
*nat
:PREROUTING ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
# Port Forwardings 
-A PREROUTING -p tcp --dport $localport -j DNAT --to-destination $remoteaddr:remoteport
-A POSTROUTING -p tcp -d $remoteaddr --dport $remoteport -j SNAT --to-source $localaddr
# don't delete the 'COMMIT' line or these rules won't be processed
COMMIT

需要注意的是 *natCOMMIT 才是完整的轉發模塊, 切勿分割或與 /etc/ufw/before.rules 中其他模塊穿插衝突. 如果需要多項轉發只需要加入多行即可, 並不需要多個 *nat 轉發模塊.

關閉 IPv6

需要注意的是, 這裏的關閉 IPv6 並不是實際網路上的 IPv6 連接, 僅僅指關閉 ufw 對於 IPv6 連接的管理:

sed -i 's|IPV6=yes|IPV6=no|g' /etc/default/ufw

即在 /etc/default/ufw 中配置 IPv6 為關閉狀態.

deny 與 reject

deny 與 reject 都能夠拒絕訪問, 其區別在於使用 deny 時, 對方不會得到任何告知, 而使用 reject 時則明確告知對方被拒絕了.

刪除規則並按序審查

伺服器網路規則越來越多往往是不可避免的, 稍不注意就會弄錯次序從而配置失誤, 特別是在 ufw 的刪除策略是以序號為基準的情況下, 這一點顯得更為重要. 在每次刪除特定規則時確認規則序號再刪除並重新加載生效才是更安全妥當的:

ufw status numbered
ufw delete 1
ufw reload

重置 ufw

在伺服器的重新配置過程中, 對於防火墻規則的逐個審查顯得非常多餘和浪費精力, 此時便可以透過 ufw reset 重置所有規則使 ufw 回到最初狀態. 需要特別注意的是 重置後的 ufw 處於未啟用狀態 需要 ufw enable 手動啟用.

ufw 與 iptables 的基於關係

除上述常規場景之外, 想必還有更多網路模塊的特殊需求, 比如大量端口的批量轉發等等. 儘管這並不代表 ufw 不可以勝任或代為負責, 但當這種場景出現並迫切需要解決時 iptables 始終是最好的選擇, 規範的管理鏈表和完整的配置系統, 相信能夠更好地完成複雜多變的任務. 而在此時, ufw 簡便高效的優勢也並不存在了. 總而言之, ufw 和 iptables 是基於關係, 分別代表著簡便高效和規範完整, 並沒有 ufw 代替 iptables 的爭論, 需求場景才能夠決定執行的實際.