介紹
在應用程式設定中將離散組件部署到不同節點上是一種常見的方式,可以減輕負載並開始進行水平擴展。一個典型的例子是將數據庫配置在與應用程序分開的伺服器上。雖然這種設置具有許多優點,但通過網絡連接涉及一組新的安全問題。
在本指南中,我們將演示如何在分散式設置中的每個伺服器上設置防火牆。我們將配置我們的策略以允許組件之間預期的流量,同時拒絕其他流量。
您也可以配置 DigitalOcean 的 Cloud 防火牆,它運行為 DigitalOcean 基礎設施上的附加外部層。這樣,您就不必在伺服器本身上配置防火牆。
在本指南中的演示中,我們將使用兩台 Ubuntu 22.04 伺服器。一台將使用 Nginx 提供 Web 應用程式,另一台將為應用程式提供 MySQL 數據庫。儘管我們將使用此設置作為示例,但您應該能夠推斷出所涉及的技術以滿足您自己的伺服器要求。
先決條件
開始之前,您需要兩個全新的Ubuntu 22.04伺服器。在每台伺服器上新增一個帶有sudo
特權的常規使用者帳戶。要做到這一點,請參照我們的Ubuntu 22.04初始伺服器設置指南
。我們將保護的應用程式設置基於此指南。如果您想跟隨該示例進行操作,請按照該教程所示的方式設置應用程式和資料庫伺服器。否則,您可以將本文作為一般參考資料。
第一步 – 設置防火牆
您將首先為每個伺服器實施基線防火牆配置。我們將採取安全優先的方法來執行策略。我們將鎖定除SSH流量之外的幾乎所有內容,然後在防火牆上為我們的特定應用程式打開洞口。
本指南遵循iptables
語法。在Ubuntu 22.04上,使用nftables
後端自動安裝了iptables
,因此您不需要安裝任何其他套件。
使用nano
或您喜歡的文本編輯器,打開/etc/iptables/rules.v4
文件:
- sudo nano /etc/iptables/rules.v4
從防火牆模板指南中複製配置:
*filter
# 允许所有出站流量,但默认情况下拒绝所有入站和转发数据包
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]
# 自定义协议链
:UDP - [0:0]
:TCP - [0:0]
:ICMP - [0:0]
# 可接受的UDP流量
# 可接受的TCP流量
-A TCP -p tcp --dport 22 -j ACCEPT
# 可接受的ICMP流量
# 常规接受策略
-A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
-A INPUT -i lo -j ACCEPT
# 拒绝无效数据包
-A INPUT -m conntrack --ctstate INVALID -j DROP
# 将流量传递到特定于协议的链
## 仅允许新连接(已建立和相关的连接应已处理)
## 对于TCP,另外只允许新的SYN数据包,因为这是建立新TCP连接的唯一有效
## 方法
-A INPUT -p udp -m conntrack --ctstate NEW -j UDP
-A INPUT -p tcp --syn -m conntrack --ctstate NEW -j TCP
-A INPUT -p icmp -m conntrack --ctstate NEW -j ICMP
# 拒绝任何通过的流量
## 尝试使用协议特定的拒绝消息
-A INPUT -p udp -j REJECT --reject-with icmp-port-unreachable
-A INPUT -p tcp -j REJECT --reject-with tcp-reset
-A INPUT -j REJECT --reject-with icmp-proto-unreachable
# 提交更改
COMMIT
*raw
:PREROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
COMMIT
*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
COMMIT
*security
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
COMMIT
*mangle
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
COMMIT
保存并关闭文件。如果使用nano
,按Ctrl+X
退出,然后按Y并按Enter。
如果您在实际环境中实施此操作,请勿重新加载防火墙规则。加载此处概述的规则集将立即中断应用程序和数据库服务器之间的连接。您需要调整规则以反映我们的运营需求,然后再重新加载。
第2步——发现您的服务使用的端口
為了允許您的組件之間進行通信,您需要知道正在使用的網絡端口。您可以通過檢查配置文件找到正確的網絡端口,但是一種與應用程序無關的找到正確端口的方法是檢查哪些服務正在我們每台機器上監聽連接。
您可以使用netstat
工具來查找此信息。由於您的應用程序僅通過IPv4進行通信,因此我們將添加-4
參數,但是如果您也使用IPv6,則可以刪除該參數。您需要找到運行服務的其他參數是-p
、-l
、-u
、-n
和-t
,您可以提供為-plunt
。
這些參數可以分解如下:
p
: Show the PID and name of the program to which each socket belongs.l
: Show only listening sockets.u
: Show UDP traffic.n
: Show numeric output instead of service names.t
: Show TCP traffic.
- sudo netstat -4plunt
在您的 Web 服務器上,您的輸出可能如下所示:
OutputActive Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1058/sshd
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 4187/nginx
第一個突出顯示的列顯示服務的 IP 地址和端口,該服務在該行末尾突出顯示正在監聽的。特殊的0.0.0.0
地址表示所討論的服務正在監聽所有可用地址。
在您的數據庫服務器上,您的輸出可能如下所示:
- sudo netstat -4plunt
OutputActive Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1097/sshd
tcp 0 0 192.0.2.30:3306 0.0.0.0:* LISTEN 3112/mysqld
您可以完全相同地閱讀這些列。在此示例中,192.0.2.30
地址表示數據庫服務器的私有 IP 地址。在先決教程中,您限制了 MySQL 只能使用私有接口,出於安全考慮。
請注意在此步驟中找到的值。這些是您需要調整防火牆配置所需的網絡詳細信息。
在您的 Web 服務器上,您需要確保以下端口是可訪問的:
- 端口 80 在所有地址上
- 端口 22 在所有地址上(防火牆規則中已經考慮到)
您的資料庫伺服器必須確保以下端口是可存取的:
- 地址
192.0.2.30
(或其關聯介面)上的端口 3306 - 端口 22 在所有地址上(防火牆規則中已經考慮到)
步驟 3 — 調整網頁伺服器防火牆規則
現在您已獲得所需的端口資訊,您將調整您的網頁伺服器防火牆規則集。以 sudo
權限在您的編輯器中開啟規則檔案:
- sudo nano /etc/iptables/rules.v4
在網頁伺服器上,您需要將端口 80 添加到您的可接受流量列表中。由於伺服器正在監聽所有可用地址 — 網頁伺服器通常期望從任何地方存取 — 您不會限制規則的介面或目的地地址。
您的網頁訪客將使用 TCP 協議進行連接。您的框架已經有一個名為 TCP
的自定義鏈用於 TCP 應用例外。您可以將端口 80 添加到該鏈中,就在您的 SSH 端口例外之下:
*filter
. . .
# 可接受的 TCP 流量
-A TCP -p tcp --dport 22 -j ACCEPT
-A TCP -p tcp --dport 80 -j ACCEPT
. . .
您的網絡伺服器將與您的數據庫伺服器建立連接。您的出站流量在防火牆中沒有限制,與已建立的連接相關的入站流量被允許,因此我們不需要在此伺服器上開放任何額外的端口來允許此連接。
完成後保存並關閉文件。您的網絡伺服器現在具有防火牆策略,將允許所有合法的流量,同時阻止其他一切。
測試您的規則文件以查找語法錯誤:
- sudo iptables-restore -t < /etc/iptables/rules.v4
如果沒有顯示語法錯誤,重新加載防火牆以實施新的規則集:
- sudo service iptables-persistent reload
步驟 4 — 調整數據庫伺服器防火牆規則
在您的數據庫伺服器上,您需要允許訪問您伺服器的私有 IP 地址的端口 3306
。在這種情況下,該地址是 192.0.2.30
。您可以限制特定訪問這個地址,或者您可以通過匹配分配該地址的介面來限制訪問。
要找到與該地址相關聯的網絡介面,運行 ip -4 addr show scope global
:
- ip -4 addr show scope global
Output2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
inet 203.0.113.5/24 brd 104.236.113.255 scope global eth0
valid_lft forever preferred_lft forever
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
inet 192.0.2.30/24 brd 192.0.2.255 scope global eth1
valid_lft forever preferred_lft forever
突出顯示的區域顯示 eth1
介面與該地址相關聯。
接下來,您將在數據庫伺服器上調整防火牆規則。在數據庫伺服器上以 sudo
權限打開規則文件:
- sudo nano /etc/iptables/rules.v4
再次,您將會在我們的TCP
鏈中添加一條規則,以形成對您的 Web 和數據庫服務器之間連接的例外情況。
要根據實際地址來限制訪問,您可以像這樣添加規則:
*filter
. . .
# 可接受的 TCP 流量
-A TCP -p tcp --dport 22 -j ACCEPT
-A TCP -p tcp --dport 3306 -d 192.0.2.30 -j ACCEPT
. . .
如果您更願意基於容納該地址的接口來允許例外情況,則可以改為添加類似於此的規則:
*filter
. . .
# 可接受的 TCP 流量
-A TCP -p tcp --dport 22 -j ACCEPT
-A TCP -p tcp --dport 3306 -i eth1 -j ACCEPT
. . .
完成後,保存並關閉文件。
使用以下命令檢查語法錯誤:
- sudo iptables-restore -t < /etc/iptables/rules.v4
準備就緒後,重新加載防火牆規則:
- sudo service iptables-persistent reload
現在,您的兩個服務器應該受到保護,而不會限制它們之間必要的數據流動。
結論
在設置應用程序時,適當地實施防火牆應始終是您部署計劃的一部分。儘管我們演示了使用兩台運行 Nginx 和 MySQL 的服務器的配置,但上述技術示範的技術適用於您的具體技術選擇無關。
要了解更多有關防火牆和iptables
的信息,請參閱以下指南: