跳转到帖子
在手机APP中查看

一个更好的浏览方法。了解更多

PHP论坛人

主屏幕上的全屏APP,带有推送通知、徽章等。

在iOS和iPadOS上安装此APP
  1. 在Safari中轻敲分享图标
  2. 滚动菜单并轻敲添加到主屏幕
  3. 轻敲右上角的添加按钮。
在安卓上安装此APP
  1. 轻敲浏览器右上角的三个点菜单 (⋮) 。
  2. 轻敲添加到主屏幕安装APP
  3. 轻敲安装进行确认。

Debian 13 原生nftables防火牆 IPv4/IPv6 雙棧防護、Fail2ban入侵防護、Systemd開機自動啟動

精选回复

Debian 13 原生nftables防火牆 IPv4/IPv6 雙棧防護、Fail2ban入侵防護、Systemd開機自動啟動




******************************************************************************************
Fail2ban Part 1

Fail2ban暫時只設定SSH防護,等待LNMP服務都安裝配置完畢,再回來增加 監獄 (Jail) 設定
******************************************************************************************





---------------
前言
---------------

為何選擇原生 nftables?

相較於 iptables 或 ufw,nftables 具備以下優勢:

雙棧統一管理:使用 inet 位址族,一套規則同時覆蓋 IPv4 與 IPv6,不會有遺漏

原子性載入:規則集一次性套用,不會出現套用到一半的中間狀態

內建計量器 (meter):per-IP 速率限制更精確,無需外部模組

語法預驗證:nft -c -f  可在套用前驗證語法,大幅降低鎖死風險

Fail2ban 整合:與 Fail2ban 1.1.0 完整整合


-----------------------------
IPv4 與 IPv6 雙棧的必要性
-----------------------------

許多管理員只設定 IPv4 防火牆,卻忽略 IPv6。若伺服器持有 IPv6 位址而未設定 IPv6 規則,IPv6 流量將完全不受保護,形同開了一扇隱形後門

本文使用 inet 位址族,同一套規則自動覆蓋 IPv4 與 IPv6,不會有遺漏


--------------
整體架構
--------------

外部流量
   │
   ▼
nftables (inet filter)
   ├── BADPKT chain ── 記錄並丟棄非法封包
   ├── INPUT chain
   │     ├── 已建立連線 → ACCEPT(優先)
   │     ├── 無效/異常封包 → goto BADPKT
   │     ├── 封鎖清單 (blacklist set) → DROP
   │     ├── SSH 速率限制(per-IP meter)
   │     ├── Web 速率限制(per-IP meter)
   │     ├── ICMPv4 / ICMPv6
   │     └── 其餘 → DROP(記錄)
   ├── FORWARD chain → DROP(非路由器)
   └── OUTPUT chain → ACCEPT
         │
         ▼
    Fail2ban(動態封鎖暴力攻擊 IP)
         └── 操作 nftables set,動態加入封鎖清單



---------------------------
安全提醒 (操作前必讀)
---------------------------

錯誤的規則會導致SSH連線立即中斷,操作前請先開啟 VNC / Serial Console / IPMI 等帶外管理備援

務必將你目前的管理IP加入允許清單 (包含 IPv6 位址)

腳本提供30秒測試模式:規則套用後 30秒自動復原,可安全驗證

雲端伺服器注意:AWS、GCP、Hetzner 等平台的內網 IP(如 10.x.x.x)若有負載平衡或監控需求,需填入 PRIVATE_IPS_V4

修改前請備份重要資料






----------
事前準備
----------

查看目前透過SSH連線的來源IP (包含 IPv6)
ss -tnp | grep :22 | grep ESTAB




查詢 IPv4
curl -4 ifconfig.me



查詢 IPv6 (若有)
curl -6 ifconfig.me



請記下你的管理IP (包含 IPv6 位址),稍後需填入防火牆腳本



------------------
確認IPv6狀態
------------------

檢查 IPv6 是否啟用 (0 = 啟用)
sysctl net.ipv6.conf.all.disable_ipv6


確認本機 IPv6 位址
ip -6 addr show





---------------------------------
安裝nftables並清除衝突工具
---------------------------------


更新套件清單
apt update


安裝 nftables
apt install -y nftables




啟用並啟動 nftables 服務
systemctl enable --now nftables


systemctl start nftables



------------------------------
確認nftables版本與狀態
------------------------------

確認nftables版本,預期 nftables v1.0.x 以上
nft --version



確認nftables狀態,預期:active
systemctl status nftables





-------------------------
停用衝突的防火牆工具
-------------------------


同時啟用多套防火牆工具會造成規則衝突,請依實際安裝情況停用



若有安裝ufw,請將其停用以避免規則衝突
systemctl disable --now ufw



若有安裝firewalld,請將其停用以避免規則衝突
systemctl disable --now firewalld




若有安裝 iptables/ip6tables,請將其停用以避免規則衝突

systemctl disable --now iptables


systemctl disable --now ip6tables



----------------------
確認初始規則狀態
----------------------


應顯示空的規則集或僅有nftables預設空表
nft list ruleset

--------------------
建立防火牆腳本
--------------------

建立腳本目錄
mkdir -p /usr/local/bin


建立防火牆腳本
vi /usr/local/bin/firewall.sh


firewall.sh


請將提供的防火牆腳本 firewall.sh 內容複製貼上

將腳本 你的管理員IPv4 替換為你的

將腳本 你的管理員IPv6 替換為你的 (若無 IPv6 可留空)


# 1. 封鎖清單:禁止連線的 IP 或網段(支援 IPv4 與 IPv6,空格分隔)
BADIPS=""


# 2. 私有 IP 網段
# ⚠️ 重要:只加入【實際會連線到本機】的內網網段!
# 例如:VPC 內網是 10.0.0.0/8 → 只填 10.0.0.0/8
# 若無內網連線需求,請留空。切勿加入所有私有網段,以免降低安全性。
PRIVATE_IPS_V4=""

# IPv6 唯一本地位址(如有 VPC 內網需求才填,否則留空)
PRIVATE_IPS_V6=""


# 3. 允許對內連線的 TCP 通訊埠
# 格式:「埠號,來源IP」,多個項目用空格分隔
IN_TCP_PORTALLOWED="22,你的管理員IPv4 22,你的管理員IPv6 888,你的管理員IPv4 80 443"




儲存檔案並離開vi編輯器
按 Esc,輸入 :wq,按 Enter

----------------
設定腳本權限
----------------

設定腳本權限 (700 表示僅 root 可讀寫執行,提高安全性)

chmod 700 /usr/local/bin/firewall.sh


chown root:root /usr/local/bin/firewall.sh



安裝 conntrack(用於統計功能)
apt install -y conntrack





-----------------
測試防火牆腳本
-----------------

執行測試模式
/usr/local/bin/firewall.sh


執行後進入30秒測試模式:
規則立即套用 (IPv4 + IPv6 同步)
腳本先進行語法驗證 (nft -c),語法錯誤不會套用
30秒內未中斷 → 規則自動清除,不影響後續連線
30秒內按下 Ctrl+C → 規則保留,進行下一步







---------------------------------------
另開終端機確認連線 (測試期間進行)
---------------------------------------

測試SSH連線 (應成功)
ssh 你的伺服器IP


測試 IPv4 對外連線 (應成功)
ping -c 3 8.8.8.8


測試 IPv6 對外連線 (若有 IPv6)
ping6 -c 3 google.com



--------------------------
永久套用規則
--------------------------

在測試倒數結束前按 Ctrl+C 保留規則,然後執行:


/usr/local/bin/firewall.sh start


start 模式會額外將規則寫入 /etc/nftables.conf,供 systemd 服務開機載入



---------------------
確認規則已套用
---------------------


查看目前規則集 (nftables 原生指令)
nft list ruleset


查看 input chain
nft list chain inet filter input


查看封包計數
nft -a list chain inet filter input


查看統計資訊
/usr/local/bin/firewall.sh stats



-----------------------------
systemd 開機自動啟動
-----------------------------

方案說明

本教學採用自訂 systemd 服務 (firewall.service) 驅動腳本,而非直接依賴 nftables.service 載入靜態設定


原因:

腳本在每次啟動時動態建構規則,可整合環境變數與條件判斷

Before=network-pre.target 確保規則在網路啟動前就位,不留空窗期





建立 systemd 服務檔
vi /etc/systemd/system/firewall.service


貼上以下內容


[Unit]
Description=Custom nftables Firewall (IPv4 + IPv6 Dual Stack)
Before=network-pre.target
Wants=network-pre.target
DefaultDependencies=no

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/local/bin/firewall.sh start
ExecStop=/usr/local/bin/firewall.sh stop
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target



儲存檔案並離開vi編輯器
按 Esc,輸入 :wq,按 Enter




------------------
啟用並啟動服務
------------------

重新載入 systemd 設定
systemctl daemon-reload


設定開機自動啟動
systemctl enable firewall.service


立即啟動
systemctl start firewall.service


檢查服務狀態,應顯示 active (exited)
systemctl status firewall.service


查看啟動日誌
journalctl -u firewall.service --no-pager



---------------------------------------
停用 nftables.service 避免衝突
---------------------------------------

重要:nftables.service 預設會在開機時載入 /etc/nftables.conf。若讓它與自訂 firewall.service 並存,可能發生規則衝突或重複載入


停用 nftables.service (改由 firewall.service 接管)

systemctl disable nftables.service


systemctl stop nftables.service


-----------------------------------
持久化核心參數 (sysctl)
-----------------------------------

腳本中的 sysctl -w 指令只是 臨時調整,重開機後會恢復預設值。要持久化,需建立設定檔


建立
vi /etc/sysctl.d/99-hardening.conf



貼上內容



# TCP SYN Cookie(防 SYN Flood)
net.ipv4.tcp_syncookies = 1

# 忽略廣播 ping
net.ipv4.icmp_echo_ignore_broadcasts = 1

# 忽略偽造錯誤回應
net.ipv4.icmp_ignore_bogus_error_responses = 1

# 拒絕 ICMP 重新導向(防路由劫持)
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv6.conf.all.accept_redirects = 0
net.ipv6.conf.default.accept_redirects = 0

# 拒絕來源路由(防 IP spoofing)
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0
net.ipv6.conf.all.accept_source_route = 0
net.ipv6.conf.default.accept_source_route = 0

# 反向路徑過濾(防 IP spoofing)
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1

# 記錄不可能的來源位址(Martian packets)
net.ipv4.conf.all.log_martians = 1





儲存檔案並離開vi編輯器
按 Esc,輸入 :wq,按 Enter



----------------------
立即套用
----------------------


立即套用
sysctl -p /etc/sysctl.d/99-hardening.conf



驗證,預期輸出:net.ipv4.tcp_syncookies = 1
sysctl net.ipv4.tcp_syncookies



------------------------
Fail2ban 安裝與配置
------------------------

Fail2ban會持續掃描系統日誌 (如 /var/log/auth.log),偵測到多次登入失敗時,自動將來源IP加入 iptables/ip6tables 封鎖規則,提供動態的入侵防護



安裝 Fail2ban (whois用於查詢被封鎖IP的資訊)

apt update


apt install -y fail2ban whois



確認版本,顯示為 Fail2Ban v1.1.0
fail2ban-client --version






------------------
建立自訂設定檔
------------------

為何不直接修改 jail.conf?

/etc/fail2ban/jail.conf 是套件提供的預設設定,套件更新時會被覆蓋

正確做法是建立 /etc/fail2ban/jail.local,Fail2ban啟動時 .local 的設定會覆蓋 .conf,這樣可以在套件更新後保留你的自訂設定

建立 jail.local 覆蓋預設值

vi /etc/fail2ban/jail.local

貼上以下內容

jail.local.txt

儲存檔案並離開vi編輯器

按 Esc,輸入 :wq,按 Enter

暫時只設定SSH防護,等待LNMP服務都安裝配置完畢,再回來增加 監獄 (Jail) 設定

------------------------
啟用 Fail2ban
------------------------

啟用並啟動
systemctl enable --now fail2ban


確認狀態,應顯示 active (running)
systemctl status fail2ban




---------------------
驗證與測試
---------------------


測試 Fail2ban 設定檔語法
fail2ban-client -t


預期輸出:OK: configuration test is successful





-------------------
重開機驗證
-------------------


重開機
reboot



確認IP轉發已啟用,應顯示 net.ipv4.ip_forward = 1
sysctl net.ipv4.ip_forward


確認IP轉發已啟用,應顯示 net.ipv6.conf.all.forwarding = 1
sysctl net.ipv6.conf.all.forwarding



確認防火牆規則已自動載入
nft list ruleset


nft list chain inet filter input




確認防火牆服務狀態,應顯示 active (exited)
systemctl status firewall.service



確認 fail2ban 服務狀態,應顯示為 active (running)
systemctl status fail2ban.service


查看所有啟用的監獄
fail2ban-client status


查看 SSH 監獄狀態
fail2ban-client status sshd


確認白名單已正確載入 (應顯示你的管理員IPv4與IPv6、你的VPS私有IP)
fail2ban-client get sshd ignoreip



確認 Fail2ban 已整合 nftables (應顯示 f2b- 開頭的規則)

若剛設好,可能尚無觸發,無輸出為正常

nft list ruleset | grep f2b




確認核心參數已持久化

sysctl net.ipv4.tcp_syncookies


正確結果(已啟用)應顯示 net.ipv4.tcp_syncookies = 1



sysctl net.ipv4.conf.all.accept_redirects

正確結果(已禁用)應顯示 net.ipv4.conf.all.accept_redirects = 0





確認服務監聽狀態

ss -tlnp | grep -E ':22'


0.0.0.0:22 ← SSH 監聽IPv4位址
[::]:22         ← SSH 監聽IPv6位址

兩個都有顯示,表示雙棧監聽 (IPv4 + IPv6)




------------------
測試封鎖功能
------------------

手動封鎖測試 IPv4 (RFC 5737 文件用IP,不影響任何人)
fail2ban-client set sshd banip 192.0.2.100


手動封鎖測試 IPv6
fail2ban-client set sshd banip 2001:db8::100


查看監獄狀態 (Banned IP 應顯示被封鎖的IP)
fail2ban-client status sshd


確認 nftables 規則已產生
nft list ruleset | grep f2b


解除封鎖 (測試完畢後)
fail2ban-client set sshd unbanip 192.0.2.100

fail2ban-client set sshd unbanip 2001:db8::100



---------------------
常見陷阱與排錯指南
---------------------

陷阱 1:IPv6 防火牆未設定

症狀:IPv4 連線正常,IPv6 流量完全開放

說明:使用 inet 位址族已同時涵蓋 IPv4 與 IPv6,本教學不會有此問題。若自行修改規則只用 ip 族,則需額外建立 ip6 族規則

驗證:
nft list ruleset | grep 'inet\|ip6'


應看到 table inet filter,代表雙棧皆受保護




陷阱 2:ICMPv6 被封鎖

症狀:IPv6 連線時通時不通,或無法取得 IPv6 位址 (SLAAC 失效)

解決:確認 IN_ICMPV6_ALLOWED 包含 133-136 (NDP 鄰居探索) 類型

nft list chain inet filter input | grep icmpv6





陷阱 3:雲端內網IP被封鎖

症狀:重開機後負載平衡器或監控系統無法連線 (常見於 AWS/GCP/Hetzner)

解決:在腳本的 PRIVATE_IPS_V4 填入對應的私有網段 (如 10.0.0.0/8)




陷阱 4:忘記加入管理 IP

症狀:執行 firewall.sh start 後SSH立即斷線

解決:透過帶外管理 (VNC/Console) 執行:

nft flush ruleset

然後修正腳本中的管理IP再重新測試




陷阱 5:服務只監聽 IPv4

症狀:nftables 規則正確,但 IPv6 用戶仍無法連線論壇

解決:確認 NGINX 監聽 ::80 而非 0.0.0.0:80:

ss -tlnp | grep :80

# :::80  → 雙棧(正確)

# 0.0.0.0:80 → 僅 IPv4(需修改 NGINX 設定)



NGINX 設定應包含:
listen 80;
listen [::]:80;
listen 443 ssl;
listen [::]:443 ssl;





陷阱 6:sysctl 參數重開機後消失

症狀:重開機後 net.ipv4.tcp_syncookies 回到預設值 0

解決:確認已完成 持久化核心參數sysctl的設定,建立 /etc/sysctl.d/99-hardening.conf



陷阱 7:nftables.service 與 firewall.service 衝突

症狀:重開機後規則被 nftables.service 覆蓋或清空

解決:確認已停用 nftables.service:

systemctl is-enabled nftables.service


若顯示 enabled,執行:
systemctl disable nftables.service






陷阱 8:Fail2ban 白名單未加入 VPS私有IP

症狀:Fail2ban 誤封鎖雲端平台的健康檢查IP,導致服務中斷

解決:在 jail.local 的 ignoreip 加入VPS分配的私有IP

查看VPS的私有IP
ip addr show | grep 'inet '

確認白名單
fail2ban-client get sshd ignoreip





陷阱 9:論壇靜態資源或API被速率限制誤封

症狀:正常用戶在短時間內大量載入頁面 (CDN 回源、搜尋爬蟲) 被速率限制

解決:調高 WEB_RATE_LIMIT,或針對已知的 CDN / 爬蟲 IP 段加入白名單

# 例如允許 Cloudflare IP 不受速率限制(需手動更新 IP 段)
# 在腳本 PRIVATE_IPS_V4 中加入 Cloudflare IP 段
# 最新 IP 段:https://www.cloudflare.com/ips/




陷阱 10:網卡名稱不是 eth0

症狀:NAT 規則套用後,SNAT 功能無效

解決:Debian 13 在部分主機商的網卡名稱可能為 ens3、ens18、enp1s0 等,需先確認

找出實際的網卡名稱,再修改 nft-nat-vpc.sh 中的 IFACE 變數
ip link show





------------------------
日常維護指令速查
------------------------

查看完整規則集
nft list ruleset


查看 input chain (含規則)
nft list chain inet filter input


即時監控被丟棄的封包
journalctl -k -f | grep -E "BADPKT|DROP|INPUT_DROP"


查看核心日誌
dmesg -w | grep -E "BADPKT|DROP"



----------------
管理防火牆
----------------

手動啟動防火牆
/usr/local/bin/firewall.sh start


手動停止防火牆 (清除所有規則)
/usr/local/bin/firewall.sh stop


測試模式 (修改規則後先測試)
/usr/local/bin/firewall.sh


透過 systemd
systemctl start firewall.service

systemctl stop  firewall.service

systemctl restart firewall.service

systemctl status firewall.service


--------------------
管理 Fail2ban
--------------------

查看所有監獄
fail2ban-client status


查看特定監獄 (如 sshd)
fail2ban-client status sshd


手動封鎖 IP
fail2ban-client set sshd banip 1.2.3.4


解除封鎖 IP
fail2ban-client set sshd unbanip 1.2.3.4


重新載入設定
fail2ban-client reload


查看日誌
journalctl -u fail2ban.service --no-pager -n 50


------------------
查看服務日誌
------------------

防火牆服務日誌 (本次開機)
journalctl -u firewall.service --boot


Fail2ban 服務日誌 (本次開機)
journalctl -u fail2ban.service --boot


即時監控所有相關日誌
journalctl -f | grep -E "fail2ban|nftables|BADPKT|DROP"

本帖最后于,由Jack编辑

创建帐户或登录后发表意见

帐户

导航

搜索

配置浏览器推送通知

Chrome (安卓)
  1. 轻敲地址栏旁的锁形图标。
  2. 轻敲权限 → 通知。
  3. 调整你的偏好。
Chrome (台式电脑)
  1. 点击地址栏中的挂锁图标。
  2. 选择网站设置。
  3. 找到通知选项并调整你的偏好。