所有动态
- 今天
-
Debian 13 從核心層面徹底停用 IPv6
Debian 13 從核心層面徹底停用 IPv6 ------ 前言 ------ 雖然 IPv6 是未來的網路通訊協定趨勢,但在某些特定場景下,我們可能希望完全關閉 IPv6 功能。常見的應用情境包括: 網路故障排查:釐清問題是否與 IPv6 相關 老舊應用程式相容性:部分舊版軟體對 IPv6 支援不佳 安全性考量:減少網路攻擊面,簡化網路堆疊 資源受限環境:降低系統負載,避免不必要的網路流量 對於 Debian 13 用戶而言,單純透過系統設定「關閉」IPv6 並不夠徹底 本文將從核心引導參數著手,讓 IPv6 協定棧在系統啟動初期就完全停用,從根源杜絕任何 IPv6 流量的產生 ----------------------------- 為什麼要從核心層面停用? ----------------------------- 常見的停用方法 (如調整 sysctl 參數) 雖然有效,但存在一個時間窗口:這些設定在系統啟動後的階段才生效 這意味著在參數應用之前,核心的 IPv6 模組已經載入,可能會產生短暫的 IPv6 流量,如鄰居發現 (Neighbor Discovery)、路由器請求 (Router Advertisement) 等流量 透過核心參數 ipv6.disable=1,可以直接命令核心不初始化 IPv6 子系統,這才是真正意義上的完全關閉 ------------------ 安全性提醒 ------------------ 停用 IPv6 可能影響某些雲端服務或 CDN (如 Cloudflare、Google),建議先確認應用場景是否允許 --------------------------- 修改 GRUB 核心啟動參數 --------------------------- 使用 root 權限開啟 GRUB 設定檔 vi /etc/default/grub 修改核心啟動參數 在檔案中找到 GRUB_CMDLINE_LINUX_DEFAULT 這行,通常預設如下: GRUB_CMDLINE_LINUX_DEFAULT="quiet" 在引號內追加參數 ipv6.disable=1,修改後應如下: GRUB_CMDLINE_LINUX_DEFAULT="quiet ipv6.disable=1" 重要提醒: 如果該行中原本有其他參數 (如 splash、net.ifnames=0 等),請務必保留它們,只需在末尾加入 ipv6.disable=1,並用空格與前面的參數隔開 儲存檔案並離開編輯器 按 Esc,輸入 :wq 後按 Enter ----------------- 更新GRUB配置 ----------------- 執行以下指令,使修改生效: update-grub 成功執行後,應看到類似 Found linux image: ... 的輸出,且沒有錯誤訊息 --------- 重開機 --------- 核心參數的變更需要重啟才能生效 reboot -------------- 驗證與排查 -------------- 確認核心參數已套用 重開機後執行 cat /proc/cmdline 應包含:ipv6.disable=1 若沒有出現,表示 GRUB 未成功更新 重開機後,檢查 IPv6 位址是否存在 ip a | grep inet6 沒有任何輸出 或只看到 ::1 (IPv6 的 loopback 位址,在極少數情況下可能仍有顯示) 通常表示已成功停用 測試 IPv6 連線 ping6 google.com 預期結果應顯示:connect: Network is unreachable 檢查核心設定 grep CONFIG_IPV6 /boot/config-$(uname -r) 輸出 CONFIG_IPV6=y 是正常的,這表示 IPv6 是編譯進核心而非模組,我們只能「停用」而非「移除」它 確認核心是否接受停用指令 cat /proc/sys/net/ipv6/conf/all/disable_ipv6 返回 1:完美,IPv6 已停用 返回 0:停用失敗,請檢查 GRUB 設定是否有拼寫錯誤,或是否有其他服務 (如 systemd-networkd) 覆蓋了核心設定 ------------------ 終極驗證方式 ------------------ 指令 sysctl net.ipv6.conf.all.disable_ipv6 若出現以下訊息,代表 IPv6 子系統真的完全不存在了: sysctl: cannot stat /proc/sys/net/ipv6/conf/all/disable_ipv6: No such file or directory 即使核心停用了IPv6,某些應用程式 (如 curl、wget) 或服務在解析DNS時,仍可能會因為 glibc 的位址選擇規則而產生短暫的IPv6連線嘗試 雖然此時網路層會直接拒絕,但為了追求極致純淨,建議額外進行以下操作 編輯 /etc/gai.conf vi /etc/gai.conf 這個檔案控制了位址解析的優先權。找到如下行並取消註釋,告訴系統優先使用IPv4映射位址: 找到下面這一行,去掉前面的 '#' 號 precedence ::ffff:0:0/96 100 儲存檔案並離開編輯器 按 Esc,輸入 :wq 後按 Enter ------- 補充 ------- 後續優化設定 即使核心層面已停用 IPv6,某些應用程式或服務仍可能嘗試使用 IPv6,導致延遲或日誌錯誤。以下提供幾個補充設定,讓系統更純淨 ---------------------------- SSH伺服器的「監聽限制」 ---------------------------- 許多SSH設定預設會監聽 any (包含 v4/v6)。雖然核心關閉了,但建議明確指定IPv4協議 編輯 /etc/ssh/sshd_config vi /etc/ssh/sshd_config 找到 #AddressFamily any 這行,取消註解並修改為 AddressFamily inet 儲存檔案並離開編輯器 按 Esc,輸入 :wq 後按 Enter 重新啟動SSH服務 systemctl restart ssh 驗證SSH服務狀態是否正常 systemctl status ssh ---------------------------- 清理 /etc/hosts 檔案 ---------------------------- /etc/hosts 通常包含 ::1 localhost 的條目,雖然不影響網路流量,但某些應用程式會優先嘗試解析 IPv6 位址而導致延遲 編輯 hosts 檔案 vi /etc/hosts 將含有 ::1 的行刪除或加上註解 # ::1 localhost ip6-localhost ip6-loopback # ff02::1 ip6-allnodes # ff02::2 ip6-allrouters 儲存檔案並離開編輯器 按 Esc,輸入 :wq 後按 Enter --------------------- 強制 APT 使用 IPv4 --------------------- 避免 APT 在更新時嘗試連接 IPv6 鏡像站 echo 'Acquire::ForceIPv4 "true";' | sudo tee /etc/apt/apt.conf.d/99force-ipv4 確認設定已寫入 cat /etc/apt/apt.conf.d/99force-ipv4 ---------------------------- 黑名單IPv6模組 (進階保護) ---------------------------- 建立模組黑名單檔案 vi /etc/modprobe.d/blacklist-ipv6.conf 加入以下內容 blacklist ipv6 儲存檔案並離開編輯器 按 Esc,輸入 :wq 後按 Enter 儲存後,更新 initramfs 使黑名單在開機時生效 update-initramfs -u ----------------- 封包監聽驗證 ----------------- 安裝 apt install tcpdump -y 使用 tcpdump 監聽所有介面的 IPv6 封包 tcpdump -i any ip6 正常情況下應沒有任何封包輸出 若在 VPS/雲主機 上仍看到 IPv6 封包,可能是由以下原因造成: Hypervisor 層級注入的封包 Host bridge 發送的封包 主機商網路層送入的封包 這些情況並非主機內部問題,無需擔心 ----------------- 常見問題與排除 ----------------- Q1:為什麼修改 GRUB 後 IPv6 沒有關閉? 可能原因: GRUB 設定檔拼寫錯誤 (如 ipv6.disable=1 誤寫為 ipv6.disable=0) 忘記執行 update-grub 更新設定 有其他服務 (如 NetworkManager、systemd-networkd) 覆蓋了核心設定 Q2:關閉 IPv6 會影響系統正常運作嗎? 一般不會。大多數應用程式在 IPv6 不可用時會優雅地降級使用 IPv4。但如果某些服務強制依賴 IPv6,可能會出現異常,此時建議保留 IPv6
- 昨天
-
這裡提供一個iptables防火牆規則 firewall.sh (IPv4 + IPv6 規則)
#!/bin/bash # ============================================================================= # 防火牆腳本 - Debian 13 / iptables-nft + ip6tables-nft # 存放路徑:/usr/local/bin/firewall.sh # 權限設定:chmod 700 /usr/local/bin/firewall.sh # 整合 systemd 開機啟動 # # 版本: 3.2 (正式版) # 功能說明: # - 支援 start (永久生效) / stop (清除規則) / test (測試模式) 參數 # - 同時設定 IPv4 (iptables) 與 IPv6 (ip6tables) 規則 # - 測試模式 30 秒後自動清除規則(避免鎖死) # - 包含核心參數調校(抗攻擊、防 IP Spoofing) # - 支援來源 IP 限制、連續埠、反向排除 # - 包含 Rate Limiting、Fragment 阻擋、ICMP/ICMPv6 防護 # - 優化日誌記錄避免過多訊息 # ============================================================================= # ========================== 使用者設定區塊 ========================== # # 警告:修改前請務必閱讀註解,確認管理 IP 已正確設定(含 IPv6) # 1. 禁止連線的 IP 或網段(支援 IPv4 與 IPv6) # 範例:BADIPS="198.108.0.0/16 203.0.113.0/24 2001:db8::/32" BADIPS="" # 2. 不可能出現的私有 IP(RFC 1918 / 私有 IPv6) # ⚠️ 注意:若您的伺服器本身 IP 屬於以下網段,請務必移除對應項目! # 10.0.0.0/8 → 大型企業內網(AWS、Hetzner 等雲端內網請注意) # 172.16.0.0/12 → 中型企業內網(Docker 預設網段也在這範圍) # 192.168.0.0/16→ 小型辦公室/家庭網路 # fc00::/7 → IPv6 唯一本地位址(等同 IPv4 私有網段) IMPOSSIBLE_IPS="10.0.0.0/8 172.16.0.0/12 192.168.0.0/16 fc00::/7" # 3. 允許對內連線的 TCP 通訊埠(支援來源 IP 限制與反向排除) # 格式說明: # - 單一埠:22 # - 連續埠:7000:7009 # - 指定來源 IPv4:22,192.168.1.100 # - 指定來源 IPv6:22,2001:db8::1 # - 反向排除(禁止特定 IP):22,!192.168.1.100 # # 重要:請將以下 IP 換成您當前連線的管理 IP! IN_TCP_PORTALLOWED="22,你的管理員IPv4 22,你的管理員IPv6 80 443" # 4. 允許對內連線的 UDP 通訊埠(格式同上) IN_UDP_PORTALLOWED="" # 5. 允許對內連線的 ICMP 類型(IPv4) # 常用類型:0 (echo reply)、3 (destination unreachable)、 # 8 (echo request/ping)、11 (time exceeded/traceroute) IN_ICMP_ALLOWED="0 3 8 11" # 6. 允許對內連線的 ICMPv6 類型(IPv6 必要,請勿隨意刪減) # ICMPv6 是 IPv6 正常運作的基礎,封鎖會導致連線異常 # 1: Destination Unreachable # 2: Packet Too Big(Path MTU Discovery 必要) # 3: Time Exceeded(traceroute6 使用) # 4: Parameter Problem # 128: Echo Request(ping6) # 129: Echo Reply # 133: Router Solicitation(NDP:取得路由器資訊) # 134: Router Advertisement(NDP:路由器廣播) # 135: Neighbor Solicitation(NDP:等同 ARP Request) # 136: Neighbor Advertisement(NDP:等同 ARP Reply) # 137: Redirect # 141: Inverse Neighbor Discovery Solicitation # 142: Inverse Neighbor Discovery Advertisement IN_ICMPV6_ALLOWED="1 2 3 4 128 129 133 134 135 136 137 141 142" # 7. Rate Limiting 設定 ENABLE_RATE_LIMIT="yes" # 是否啟用 rate limiting SSH_RATE="10/60" # SSH: 60秒內10次 WEB_RATE="100/60" # Web: 60秒內100次 ICMP_RATE="5" # ICMP ping 每秒次數 # 8. 備份目錄設定 # 腳本備份目錄 BACKUP_DIR="/root/firewall-backups" # ========================== 系統函式區塊 ========================== # # 以下為程式邏輯,若不熟悉 shell script,請勿任意修改 set -e trap 'echo "錯誤: 指令失敗於行號: $LINENO"; exit 1' ERR IPTABLES="/usr/sbin/iptables" IP6TABLES="/usr/sbin/ip6tables" SYSCTL="/usr/sbin/sysctl" # 建立備份目錄 mkdir -p "$BACKUP_DIR" cp "$0" "$BACKUP_DIR/firewall.sh.$(date +%Y%m%d_%H%M%S)" 2>/dev/null || true # 檢查必要指令 for cmd in $IPTABLES $IP6TABLES $SYSCTL; do if ! command -v $cmd >/dev/null 2>&1; then echo "錯誤: 找不到 $cmd 指令" exit 1 fi done # 檢查 conntrack 模組 if ! $IPTABLES -m conntrack --help >/dev/null 2>&1; then echo "錯誤: conntrack 模組不可用" echo "請執行: modprobe nf_conntrack" exit 1 fi # ----------------------------------------------------------------------------- # 輔助函式:判斷 IP 版本 # ----------------------------------------------------------------------------- is_ipv6() { echo "$1" | grep -q ':'; } is_ipv4() { echo "$1" | grep -q '\.' && ! echo "$1" | grep -q ':'; } # ----------------------------------------------------------------------------- # 停止功能:清除所有規則 # ----------------------------------------------------------------------------- do_stop() { echo -n "Stopping firewall (flushing all rules)..." $IPTABLES -P INPUT ACCEPT $IPTABLES -P OUTPUT ACCEPT $IPTABLES -P FORWARD ACCEPT $IPTABLES -t filter -F $IPTABLES -t filter -X $IP6TABLES -P INPUT ACCEPT $IP6TABLES -P OUTPUT ACCEPT $IP6TABLES -P FORWARD ACCEPT $IP6TABLES -t filter -F $IP6TABLES -t filter -X echo " OK" echo " 警告:所有防火牆規則已清除,伺服器目前無任何防護!" } if [ "$1" = "stop" ]; then do_stop exit 0 fi # ----------------------------------------------------------------------------- # 初始化 # ----------------------------------------------------------------------------- echo -n "Initializing iptables/ip6tables..." $IPTABLES -P INPUT ACCEPT $IPTABLES -P FORWARD ACCEPT $IPTABLES -P OUTPUT ACCEPT $IPTABLES -t filter -F $IPTABLES -t filter -X $IP6TABLES -P INPUT ACCEPT $IP6TABLES -P FORWARD ACCEPT $IP6TABLES -P OUTPUT ACCEPT $IP6TABLES -t filter -F $IP6TABLES -t filter -X echo " OK" # 判斷模式 MODE="test" [ "$1" = "start" ] && MODE="start" # ----------------------------------------------------------------------------- # 核心參數調校 # ----------------------------------------------------------------------------- echo -n "Tuning kernel parameters..." # SYN Flood 防護 $SYSCTL -w net.ipv4.tcp_syncookies=1 > /dev/null 2>&1 # ICMP 攻擊防護 $SYSCTL -w net.ipv4.icmp_echo_ignore_broadcasts=1 > /dev/null 2>&1 $SYSCTL -w net.ipv4.icmp_ignore_bogus_error_responses=1 > /dev/null 2>&1 # 關閉 ICMP Redirect(防中間人攻擊) $SYSCTL -w net.ipv4.conf.all.accept_redirects=0 > /dev/null 2>&1 $SYSCTL -w net.ipv4.conf.default.accept_redirects=0 > /dev/null 2>&1 $SYSCTL -w net.ipv4.conf.all.send_redirects=0 > /dev/null 2>&1 $SYSCTL -w net.ipv4.conf.default.send_redirects=0 > /dev/null 2>&1 # 關閉 Source Routing $SYSCTL -w net.ipv4.conf.all.accept_source_route=0 > /dev/null 2>&1 $SYSCTL -w net.ipv4.conf.default.accept_source_route=0 > /dev/null 2>&1 # 反向路徑過濾(單網卡設1,多網卡或VPN請改2) $SYSCTL -w net.ipv4.conf.all.rp_filter=1 > /dev/null 2>&1 $SYSCTL -w net.ipv4.conf.default.rp_filter=1 > /dev/null 2>&1 # 記錄可疑封包(IP Spoofing) $SYSCTL -w net.ipv4.conf.all.log_martians=1 > /dev/null 2>&1 # IPv6 防護 $SYSCTL -w net.ipv6.conf.all.accept_redirects=0 > /dev/null 2>&1 $SYSCTL -w net.ipv6.conf.default.accept_redirects=0 > /dev/null 2>&1 $SYSCTL -w net.ipv6.conf.all.accept_source_route=0 > /dev/null 2>&1 $SYSCTL -w net.ipv6.conf.default.accept_source_route=0 > /dev/null 2>&1 echo " OK" # ----------------------------------------------------------------------------- # 通用解析函式(支援 IP 限制、反向排除) # ----------------------------------------------------------------------------- parse_entry() { local entry="$1" local proto="$2" local family="$3" local cmd src_ip port src [ "$family" = "ipv4" ] && cmd="$IPTABLES" || cmd="$IP6TABLES" case "$entry" in *,*) port=$(echo "$entry" | cut -d, -f1) src=$(echo "$entry" | cut -d, -f2-) if echo "$src" | grep -q '^!'; then src_ip=$(echo "$src" | sed 's/^!//') # 版本過濾 if { [ "$family" = "ipv4" ] && is_ipv6 "$src_ip"; } || \ { [ "$family" = "ipv6" ] && is_ipv4 "$src_ip"; }; then return fi # 反向排除:先 DROP 該來源 $cmd -A INPUT -p "$proto" --dport "$port" -m conntrack --ctstate NEW -s "$src_ip" -j DROP # 再 ACCEPT 其他 if [ "$proto" = "tcp" ] && [ "$port" = "22" ] && [ "$ENABLE_RATE_LIMIT" = "yes" ]; then if [ "$family" = "ipv6" ]; then $cmd -A INPUT -p "$proto" --dport "$port" -m conntrack --ctstate NEW ! -s "$src_ip" -j SSH_ACCEPT6 else $cmd -A INPUT -p "$proto" --dport "$port" -m conntrack --ctstate NEW ! -s "$src_ip" -j SSH_ACCEPT fi elif [ "$proto" = "tcp" ] && { [ "$port" = "80" ] || [ "$port" = "443" ]; } && [ "$ENABLE_RATE_LIMIT" = "yes" ]; then if [ "$family" = "ipv6" ]; then $cmd -A INPUT -p "$proto" --dport "$port" -m conntrack --ctstate NEW ! -s "$src_ip" -j WEB_ACCEPT6 else $cmd -A INPUT -p "$proto" --dport "$port" -m conntrack --ctstate NEW ! -s "$src_ip" -j WEB_ACCEPT fi else $cmd -A INPUT -p "$proto" --dport "$port" -m conntrack --ctstate NEW ! -s "$src_ip" -j ACCEPT fi else # 版本過濾 if { [ "$family" = "ipv4" ] && is_ipv6 "$src"; } || \ { [ "$family" = "ipv6" ] && is_ipv4 "$src"; }; then return fi # 指定來源 if [ "$proto" = "tcp" ] && [ "$port" = "22" ] && [ "$ENABLE_RATE_LIMIT" = "yes" ]; then $cmd -A INPUT -p "$proto" --dport "$port" -m conntrack --ctstate NEW -s "$src" -j SSH_ACCEPT elif [ "$proto" = "tcp" ] && { [ "$port" = "80" ] || [ "$port" = "443" ]; } && [ "$ENABLE_RATE_LIMIT" = "yes" ]; then $cmd -A INPUT -p "$proto" --dport "$port" -m conntrack --ctstate NEW -s "$src" -j WEB_ACCEPT else $cmd -A INPUT -p "$proto" --dport "$port" -m conntrack --ctstate NEW -s "$src" -j ACCEPT fi fi ;; *) # 純埠 if [ "$proto" = "tcp" ] && [ "$entry" = "22" ] && [ "$ENABLE_RATE_LIMIT" = "yes" ]; then if [ "$family" = "ipv6" ]; then $cmd -A INPUT -p "$proto" --dport "$entry" -m conntrack --ctstate NEW -j SSH_ACCEPT6 else $cmd -A INPUT -p "$proto" --dport "$entry" -m conntrack --ctstate NEW -j SSH_ACCEPT fi elif [ "$proto" = "tcp" ] && { [ "$entry" = "80" ] || [ "$entry" = "443" ]; } && [ "$ENABLE_RATE_LIMIT" = "yes" ]; then if [ "$family" = "ipv6" ]; then $cmd -A INPUT -p "$proto" --dport "$entry" -m conntrack --ctstate NEW -j WEB_ACCEPT6 else $cmd -A INPUT -p "$proto" --dport "$entry" -m conntrack --ctstate NEW -j WEB_ACCEPT fi else $cmd -A INPUT -p "$proto" --dport "$entry" -m conntrack --ctstate NEW -j ACCEPT fi ;; esac } # ========================== IPv4 規則 ========================== # echo -n "Applying IPv4 firewall rules..." $IPTABLES -P INPUT DROP $IPTABLES -P FORWARD DROP $IPTABLES -P OUTPUT ACCEPT # Loopback $IPTABLES -A INPUT -i lo -j ACCEPT # 建立 BADPKT 鏈 $IPTABLES -N BADPKT $IPTABLES -A BADPKT -m limit --limit 1/min --limit-burst 3 -j LOG --log-prefix "IPv4_BADPKT: " --log-level 4 $IPTABLES -A BADPKT -j DROP # Rate limiting 鏈 if [ "$ENABLE_RATE_LIMIT" = "yes" ]; then $IPTABLES -N SSH_ACCEPT $IPTABLES -N WEB_ACCEPT SSH_HITCOUNT=$(echo $SSH_RATE | cut -d/ -f1) SSH_SECONDS=$(echo $SSH_RATE | cut -d/ -f2) $IPTABLES -A SSH_ACCEPT -m recent --name SSH4 --set $IPTABLES -A SSH_ACCEPT -m recent --name SSH4 --update --seconds $SSH_SECONDS --hitcount $SSH_HITCOUNT -j LOG --log-prefix "SSH4_RATE_DROP: " --log-level 4 $IPTABLES -A SSH_ACCEPT -m recent --name SSH4 --update --seconds $SSH_SECONDS --hitcount $SSH_HITCOUNT -j DROP $IPTABLES -A SSH_ACCEPT -j ACCEPT WEB_HITCOUNT=$(echo $WEB_RATE | cut -d/ -f1) WEB_SECONDS=$(echo $WEB_RATE | cut -d/ -f2) $IPTABLES -A WEB_ACCEPT -m recent --name WEB4 --set $IPTABLES -A WEB_ACCEPT -m recent --name WEB4 --update --seconds $WEB_SECONDS --hitcount $WEB_HITCOUNT -j LOG --log-prefix "WEB4_RATE_DROP: " --log-level 4 $IPTABLES -A WEB_ACCEPT -m recent --name WEB4 --update --seconds $WEB_SECONDS --hitcount $WEB_HITCOUNT -j DROP $IPTABLES -A WEB_ACCEPT -j ACCEPT fi # 允許已建立連線(插到第一條) $IPTABLES -I INPUT 1 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT # 阻擋 INVALID $IPTABLES -A INPUT -m conntrack --ctstate INVALID -j BADPKT # 阻擋非 SYN 的新連線 $IPTABLES -A INPUT -p tcp ! --syn -m conntrack --ctstate NEW -j BADPKT # 阻擋異常 TCP Flag for flags in \ "ALL NONE" \ "SYN,FIN SYN,FIN" \ "SYN,RST SYN,RST" \ "FIN,RST FIN,RST" \ "ACK,FIN FIN" \ "ACK,URG URG" \ "ACK,PSH PSH" \ "ALL FIN,URG,PSH" \ "ALL SYN,RST,ACK,FIN,URG" \ "ALL ALL" \ "ALL FIN" do $IPTABLES -A INPUT -p tcp --tcp-flags $flags -j BADPKT done # 阻擋黑名單與私有 IP for ip in $BADIPS $IMPOSSIBLE_IPS; do if is_ipv4 "$ip"; then $IPTABLES -A INPUT -s "$ip" -j DROP fi done # 允許 TCP 埠 for entry in $IN_TCP_PORTALLOWED; do parse_entry "$entry" tcp ipv4 done # 允許 UDP 埠 for entry in $IN_UDP_PORTALLOWED; do parse_entry "$entry" udp ipv4 done # 允許 ICMP(含 rate limiting) if [ "$ENABLE_RATE_LIMIT" = "yes" ]; then $IPTABLES -A INPUT -p icmp --icmp-type 8 -m limit --limit $ICMP_RATE/sec --limit-burst 5 -j ACCEPT $IPTABLES -A INPUT -p icmp --icmp-type 8 -j LOG --log-prefix "ICMP_RATE_DROP: " --log-level 4 $IPTABLES -A INPUT -p icmp --icmp-type 8 -j DROP fi for type in $IN_ICMP_ALLOWED; do if [ "$ENABLE_RATE_LIMIT" = "yes" ] && [ "$type" = "8" ]; then continue fi $IPTABLES -A INPUT -p icmp --icmp-type "$type" -m conntrack --ctstate NEW,ESTABLISHED,RELATED -j ACCEPT done echo " OK" # ========================== IPv6 規則 ========================== # echo -n "Applying IPv6 firewall rules..." $IP6TABLES -P INPUT DROP $IP6TABLES -P FORWARD DROP $IP6TABLES -P OUTPUT ACCEPT $IP6TABLES -A INPUT -i lo -j ACCEPT # 建立 BADPKT6 鏈 $IP6TABLES -N BADPKT6 $IP6TABLES -A BADPKT6 -m limit --limit 1/min --limit-burst 3 -j LOG --log-prefix "IPv6_BADPKT: " --log-level 4 $IP6TABLES -A BADPKT6 -j DROP # Rate limiting 鏈 (IPv6) if [ "$ENABLE_RATE_LIMIT" = "yes" ]; then $IP6TABLES -N SSH_ACCEPT6 $IP6TABLES -N WEB_ACCEPT6 SSH_HITCOUNT=$(echo $SSH_RATE | cut -d/ -f1) SSH_SECONDS=$(echo $SSH_RATE | cut -d/ -f2) $IP6TABLES -A SSH_ACCEPT6 -m recent --name SSH6 --set $IP6TABLES -A SSH_ACCEPT6 -m recent --name SSH6 --update --seconds $SSH_SECONDS --hitcount $SSH_HITCOUNT -j LOG --log-prefix "SSH6_RATE_DROP: " --log-level 4 $IP6TABLES -A SSH_ACCEPT6 -m recent --name SSH6 --update --seconds $SSH_SECONDS --hitcount $SSH_HITCOUNT -j DROP $IP6TABLES -A SSH_ACCEPT6 -j ACCEPT WEB_HITCOUNT=$(echo $WEB_RATE | cut -d/ -f1) WEB_SECONDS=$(echo $WEB_RATE | cut -d/ -f2) $IP6TABLES -A WEB_ACCEPT6 -m recent --name WEB6 --set $IP6TABLES -A WEB_ACCEPT6 -m recent --name WEB6 --update --seconds $WEB_SECONDS --hitcount $WEB_HITCOUNT -j LOG --log-prefix "WEB6_RATE_DROP: " --log-level 4 $IP6TABLES -A WEB_ACCEPT6 -m recent --name WEB6 --update --seconds $WEB_SECONDS --hitcount $WEB_HITCOUNT -j DROP $IP6TABLES -A WEB_ACCEPT6 -j ACCEPT fi # 允許已建立連線 $IP6TABLES -I INPUT 1 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT # 阻擋 INVALID $IP6TABLES -A INPUT -m conntrack --ctstate INVALID -j BADPKT6 # 阻擋非 SYN 的新連線 $IP6TABLES -A INPUT -p tcp ! --syn -m conntrack --ctstate NEW -j BADPKT6 # 阻擋異常 TCP Flag for flags in \ "ALL NONE" \ "SYN,FIN SYN,FIN" \ "SYN,RST SYN,RST" \ "FIN,RST FIN,RST" \ "ACK,FIN FIN" \ "ACK,URG URG" \ "ACK,PSH PSH" \ "ALL FIN,URG,PSH" \ "ALL SYN,RST,ACK,FIN,URG" \ "ALL ALL" \ "ALL FIN" do $IP6TABLES -A INPUT -p tcp --tcp-flags $flags -j BADPKT6 done # 阻擋 IPv6 fragment 攻擊 $IP6TABLES -A INPUT -m ipv6header --header frag --soft -j LOG --log-prefix "IPv6_FRAG_DROP: " --log-level 4 $IP6TABLES -A INPUT -m ipv6header --header frag --soft -j DROP # 允許必要 IPv6 通訊 $IP6TABLES -A INPUT -s fe80::/10 -j ACCEPT # Link-local $IP6TABLES -A INPUT -p udp --sport 547 --dport 546 -j ACCEPT # DHCPv6 # MLD (Multicast Listener Discovery) $IP6TABLES -A INPUT -p ipv6-icmp --icmpv6-type 130 -j ACCEPT $IP6TABLES -A INPUT -p ipv6-icmp --icmpv6-type 131 -j ACCEPT $IP6TABLES -A INPUT -p ipv6-icmp --icmpv6-type 132 -j ACCEPT # 阻擋黑名單與私有 IPv6 for ip in $BADIPS $IMPOSSIBLE_IPS; do if is_ipv6 "$ip"; then $IP6TABLES -A INPUT -s "$ip" -j DROP fi done # 允許 TCP 埠(IPv6) for entry in $IN_TCP_PORTALLOWED; do parse_entry "$entry" tcp ipv6 done # 允許 UDP 埠(IPv6) for entry in $IN_UDP_PORTALLOWED; do parse_entry "$entry" udp ipv6 done # 允許 ICMPv6 for type in $IN_ICMPV6_ALLOWED; do $IP6TABLES -A INPUT -p ipv6-icmp --icmpv6-type "$type" -m conntrack --ctstate NEW,ESTABLISHED,RELATED -j ACCEPT done echo " OK" # ========================== 顯示統計 ========================== # echo "" echo "防火牆規則統計:" echo "----------------" echo "IPv4 規則數:$($IPTABLES -L -v -n | wc -l)" echo "IPv6 規則數:$($IP6TABLES -L -v -n | wc -l)" echo "" # ========================== 測試模式 ========================== # if [ "$MODE" = "start" ]; then echo "" echo "防火牆已啟動(start 模式),規則持續生效。" echo "若要停用請執行:/usr/local/bin/firewall.sh stop" exit 0 fi # 測試模式 WAIT=30 cleanup() { echo "" echo -n "正在清除規則(測試結束)..." $IPTABLES -P INPUT ACCEPT $IPTABLES -P OUTPUT ACCEPT $IPTABLES -P FORWARD ACCEPT $IPTABLES -t filter -F $IPTABLES -t filter -X $IP6TABLES -P INPUT ACCEPT $IP6TABLES -P OUTPUT ACCEPT $IP6TABLES -P FORWARD ACCEPT $IP6TABLES -t filter -F $IP6TABLES -t filter -X echo " OK" echo "測試模式結束。若有問題請修正規則後重新測試。" exit 0 } trap cleanup INT TERM echo "" echo "========================================================" echo "!!! 測試模式 !!!" echo "防火牆規則已套用(IPv4 + IPv6)" echo "將在 ${WAIT} 秒後自動清除規則,以防止鎖死。" echo "" echo "請在另一終端機確認連線是否正常:" echo " SSH 連線測試:ssh localhost" echo " Ping 測試:ping -c 3 8.8.8.8" echo " Web 測試:curl -I http://localhost" echo " IPv6 測試:ping6 -c 3 google.com" echo "" echo "若連線正常,請按 Ctrl+C 中斷倒數,然後執行:" echo " /usr/local/bin/firewall.sh start" echo "========================================================" echo "" i=1 while [ "$i" -le "$WAIT" ]; do printf "\r等待中... %d 秒後自動清除規則 (按 Ctrl+C 保留規則) " "$((WAIT - i + 1))" sleep 1 i=$((i + 1)) done echo "" cleanup firewall.sh
-
Debian 13防火牆建置:iptables (nf_tables backend) IPv4+IPv6 雙棧防護、Fail2ban入侵防護、Systemd開機自動啟動
Debian 13防火牆建置:iptables (nf_tables backend) IPv4+IPv6 雙棧防護、Fail2ban入侵防護、Systemd開機自動啟動 ------ 前言 ------ 在Debian 13中,iptables 預設使用 nf_tables 後端 (指令為 iptables-nft / ip6tables-nft),這代表: 指令名稱仍為 iptables 和 ip6tables (保持向下相容) 底層核心架構已切換為 nftables,效能與擴充性更佳 IPv4 與 IPv6 是兩套獨立的規則集,必須分別設定 常見安全漏洞: 許多管理員只設定 IPv4 防火牆,卻忽略 IPv6。如果伺服器有 IPv6 位址而 ip6tables 規則為空,IPv6 流量將完全不受保護 適用對象: 想繼續使用 iptables 指令語法的管理員 需要同時保護 IPv4 與 IPv6 的環境 希望透過 systemd 開機自動載入規則 需要整合 Fail2ban 防止暴力攻擊 安全提醒: 錯誤的規則可能導致SSH連線中斷,操作前建議先開啟 VNC / Serial Console / IPMI 等帶外管理備援 務必將你目前的管理IP加入允許清單 (包含IPv6位址) 修改前請先備份重要資料 測試模式非常重要:腳本提供 30 秒測試模式,可在規則鎖死連線時自動復原 雲端伺服器注意:AWS、GCP、Hetzner 等平台的內網 IP(10.x.x.x)可能需要保留,否則負載平衡或監控會失效 ---------- 事前準備 ---------- 查看目前 IPv4 連線IP ss -tnp | grep :22 | grep ESTAB 查看目前 IPv6 連線IP ss -tnp | grep :22 | grep ESTAB | grep '::' 請記下你的管理 IP (包含 IPv6 位址),稍後需填入防火牆腳本 --------------------------------- 安裝iptables防火牆並確認後端 --------------------------------- 在Debian 13中,ip6tables 是 iptables 套件的一部分,會一併安裝 更新套件清單 apt update 安裝 iptables (ip6tables會一併安裝) apt install -y iptables 確認後端類型,應顯示 iptables v1.8.11 (nf_tables) iptables --version 確認後端類型,應顯示 ip6tables v1.8.11 (nf_tables) ip6tables --version 檢查 ip6tables 指令是否存在,預期輸出:/usr/sbin/ip6tables which ip6tables 檢查IPv6是否啟用,預期輸出:net.ipv6.conf.all.disable_ipv6 = 0 (0表示啟用) sysctl net.ipv6.conf.all.disable_ipv6 檢查這台VPS/雲主機的IPv6位址是否存在,應該會顯示你的IPv6位址 (如果有的話) ip -6 addr show 檢查初始規則狀態 IPv4規則 (初始應為空或僅有基本規則) iptables -L -v -n IPv6規則 (應為空) ip6tables -L -v -n ------------------------- 停用衝突的防火牆工具 ------------------------- 注意:請勿移除 nftables 套件,它是核心 Netfilter 框架的一部分 若有安裝ufw,請將其停用以避免規則衝突 systemctl disable --now ufw 若有安裝firewalld,請將其停用以避免規則衝突 systemctl disable --now firewalld ------------------------- 防火牆腳本建立與設定 ------------------------- 建立腳本目錄 (若目錄不存在) mkdir -p /usr/local/bin 建立防火牆腳本 vi /usr/local/bin/firewall.sh 請將提供的防火牆腳本 firewall.sh 內容複製貼上 將腳本 你的管理員IPv4 替換為你的 將腳本 你的管理員IPv6 替換為你的 (若無 IPv6 可留空) # 1. 禁止連線的 IP 或網段(支援 IPv4 與 IPv6) # 範例:BADIPS="198.108.0.0/16 203.0.113.0/24 2001:db8::/32" BADIPS="198.108.0.0/16 203.0.113.0/24 2001:db8::/32" # 2. 不可能出現的私有 IP(RFC 1918 / 私有 IPv6) # 注意:若您的伺服器本身 IP 屬於以下網段,請務必移除對應項目! # 10.0.0.0/8 → 大型企業內網(Hetzner、AWS 內部網路等請注意) # 172.16.0.0/12 → 中型企業內網(Docker 預設橋接網段也在此範圍) # 192.168.0.0/16 → 小型辦公室/家庭網路 # fc00::/7 → IPv6 唯一本地位址(等同 IPv4 私有網段) IMPOSSIBLE_IPS="10.0.0.0/8 172.16.0.0/12 192.168.0.0/16 fc00::/7" # 3. 允許對內連線的 TCP 通訊埠(支援來源 IP 限制與反向排除) # 格式說明: # - 單一埠:22 # - 連續埠:7000:7009 # - 指定來源 IPv4:22,192.168.1.100 # - 指定來源 IPv6:22,2001:db8::1 # - 反向排除(禁止特定 IP 存取該埠,其他人允許):22,!192.168.1.100 # # 重要:請將「你的管理員IPv4」換成您當前連線的 IPv4 位址! # 若有 IPv6 連線,請一併填入;若無 IPv6 管理需求,可刪除該項。 IN_TCP_PORTALLOWED="22,你的管理員IPv4 22,你的管理員IPv6 80 443" ESC儲存並離開 :wq ---------------- 設定腳本權限 ---------------- 設定腳本權限 (700 表示僅 root 可讀寫執行,提高安全性) chmod 700 /usr/local/bin/firewall.sh ----------------- 測試防火牆腳本 ----------------- 執行腳本 /usr/local/bin/firewall.sh 執行後會進入 30 秒測試模式: 規則立即套用 若 30 秒內未中斷(Ctrl+C),規則自動清除,不影響後續連線 若 30 秒內按下 Ctrl+C,規則保留;此時即可確認測試通過 --------------------------------------- 另開終端機確認連線 (測試期間進行) --------------------------------------- 測試SSH連線 (應成功) ssh 你的伺服器IP 測試 IPv4 對外連線 (應成功) ping -c 3 8.8.8.8 測試 IPv6 對外連線 (若有 IPv6) ping6 -c 3 google.com 測試 Web (若本機有服務) curl -I http://localhost curl -I https://localhost 若有開放其他服務,也一併測試 --------------- 查看規則狀態 --------------- 查看 IPv4 規則 (含封包計數) iptables -L -v -n --line-numbers 查看 IPv6 規則 ip6tables -L -v -n --line-numbers -------------------------- 確認無誤後永久套用規則 -------------------------- 在測試倒數結束前按 Ctrl+C 保留規則,然後執行 /usr/local/bin/firewall.sh start ----------------------------- systemd 開機自動啟動 ----------------------------- 建立 systemd 服務檔 vi /etc/systemd/system/firewall.service 複製貼上以下內容 [Unit] Description=Custom iptables/ip6tables Firewall (nf_tables backend) 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 [Install] WantedBy=multi-user.target ESC儲存並離開 :wq ------------------ 啟用並啟動服務 ------------------ 重新載入 systemd 設定 systemctl daemon-reload 設定開機自動啟動 systemctl enable firewall.service 立即啟動 systemctl start firewall.service 檢查服務狀態,應顯示 active (exited) systemctl status firewall.service 查看啟動日誌 journalctl -u firewall.service 確認 IPv4 規則已套用 iptables -L -v -n 確認 IPv6 規則已套用 ip6tables -L -v -n ------------------------ 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 貼上以下內容 請將內容中 你的管理員IPv4 / 你的管理員IPv6,替換為你的實際IP [DEFAULT] # 白名單:這些IP永遠不會被封鎖,務必填入你的管理員IP (包含IPv6) # 可填多個,空格分隔;支援 CIDR 網段 ignoreip = 127.0.0.1/8 ::1 你的管理員IPv4 你的管理員IPv6 # 封鎖時間:24 小時 (秒) bantime = 86400 # 計算失敗次數時間窗:10 分鐘 (秒) findtime = 600 # 允許失敗次數:超過此次數即觸發封鎖 maxretry = 5 # 封鎖動作:不使用 ipset,使用標準 iptables-multiport # 支援 IPv4 與 IPv6 雙棧 (Fail2ban會自動選用 iptables 或 ip6tables) banaction = iptables-multiport banaction_allports = iptables-allports # 永久封鎖條件 (recidive 會用到) bantime.increment = true bantime.factor = 2 bantime.formula = bantime * (1<<(ban_count if ban_count<20 else 20)) / 2 # --------------------------------------------------------- # 以下是各個要啟動的監獄 (Jail) 設定 # --------------------------------------------------------- # SSH登入防護 [sshd] enabled = true port = ssh logpath = %(sshd_log)s backend = %(sshd_backend)s # SSH 暴力掃描 (更嚴格) # 針對短時間大量嘗試的掃描機器人,3次即封鎖 [sshd-ddos] enabled = true port = ssh filter = sshd logpath = %(sshd_log)s maxretry = 3 bantime = 604800 ESC儲存並離開 :wq 暫時只設定SSH防護,等待LNMP服務都安裝配置完畢,再回來增加 監獄 (Jail) 設定 ------------------------ 啟動 Fail2ban ------------------------ 啟用並立即啟動 systemctl enable fail2ban --now 檢查狀態 systemctl status fail2ban 檢查監獄狀態 fail2ban-client status fail2ban-client status sshd ------------------- 驗證與重開機測試 ------------------- 重開機 reboot 防火牆規則應自動載入 iptables -L -v -n ip6tables -L -v -n 確認 防火牆 服務狀態,應顯示為 active (exited) systemctl status firewall.service 確認 fail2ban 服務狀態,應顯示為 active (running) systemctl status fail2ban.service 驗證iptables規則,檢查是否已產生 f2b- 開頭的規則鏈 (這代表 Fail2ban 已成功介入 iptables) iptables -L -n | grep f2b ip6tables -L -n | grep f2b 查看開機期間的服務日誌 journalctl -u firewall.service --boot journalctl -u fail2ban.service --boot 查看防火牆日誌 journalctl -k | grep -E "BADPKT|DROP" --------------------- 常見陷阱與排錯指南 --------------------- 陷阱 1:IPv6 防火牆未設定 症狀:IPv4 連線正常,IPv6 連線失敗或完全開放 解決:確認 ip6tables -L -n 有規則,且 ICMPv6 類型已開放 ip6tables -L -n 陷阱 2:ICMPv6 被封鎖 症狀:IPv6 連線時通時不通,或無法取得 IPv6 位址 解決:確認 IN_ICMPV6_ALLOWED 包含必要類型(133-136 等) 陷阱 3:雲端內網 IP 被封鎖 症狀:重開機後負載平衡器或監控系統無法連線 解決:在 IMPOSSIBLE_IPS 中移除對應的私有網段(如 10.0.0.0/8) 陷阱 4:忘記加入管理 IP 症狀:執行 firewall.sh start 後 SSH 立即斷線 解決:透過帶外管理重啟,或等待測試模式自動復原 陷阱 5:服務綁定問題 症狀:IPv6 防火牆開放但服務仍無法連線 解決:檢查服務是否監聽在 ::(雙棧): ss -tlnp | grep :80 :::80 表示雙棧,0.0.0.0:80 表示僅 IPv4 陷阱 6:Fail2ban 與自訂鏈衝突 症狀:Fail2ban 封鎖失效,或規則順序錯誤 解決:確認 f2b- 鏈在 INPUT 鏈中的順序(應在最後) 陷阱 7:conntrack 模組未載入 症狀:執行腳本時出現 iptables: No chain/target/match by that name 解決:手動載入模組: modprobe nf_conntrack echo "nf_conntrack" >> /etc/modules ----------------- 維護與日誌查看 ----------------- 查看被封鎖的封包 核心日誌中的防火牆記錄 journalctl -k | grep -E "BADPKT|DROP" 即時監控 dmesg -w | grep -E "BADPKT|DROP" 手動管理 Fail2ban 解除封鎖特定 IP fail2ban-client set sshd unbanip 203.0.113.99 重新載入設定 fail2ban-client reload 查看所有 jail 狀態 fail2ban-client status ------------------ 防火牆腳本維護 ------------------ 手動停止防火牆 (清除所有規則) /usr/local/bin/firewall.sh stop 手動啟動防火牆 /usr/local/bin/firewall.sh start 修改規則後測試 測試模式 /usr/local/bin/firewall.sh 測試通過後 /usr/local/bin/firewall.sh start
- 前几天
-
Debian 13 防火牆建置:使用iptables (nf_tables backend) 與 systemd 開機自動啟動
Debian 13 防火牆建置:使用iptables (nf_tables backend) 與 systemd 開機自動啟動 ------ 前言 ------ 在Debian 13中,iptables預設使用 nf_tables backend (iptables-nft) 這代表: 指令仍是iptables 核心架構實際為nftables 效能與擴充性較舊版iptables-legacy更佳 此方式適合: 想保留 iptables 指令習慣者 需要穩定腳本相容性者 安全提示:錯誤的規則可能導致SSH斷線。建議操作前開啟主機商的VNC/Serial Console,或先將自己的IP加入允許清單 --------------------------------- 安裝iptables防火牆並確認後端 --------------------------------- 更新套件清單 apt update 安裝iptables apt install -y iptables 確認後端類型,應顯示 iptables v1.8.11 (nf_tables) ,代表系統正在使用nftables核心架構 iptables --version 確認目前規則狀態 (初始應為空或僅有基本規則) iptables -L -v ------------------ 避免防火牆衝突 ------------------ 注意:請勿移除 nftables 套件,因為它是Linux kernel 的 Netfilter 框架 + nftables userspace 工具 若有安裝ufw,請將其停用以避免規則衝突 systemctl disable ufw --now -------------------- 配置防火牆腳本 -------------------- 將規則寫入腳本,方便管理與自動化 建立腳本目錄 (若目錄不存在) mkdir -p /usr/local/bin 建立防火牆腳本 vi /usr/local/bin/firewall.sh 請將提供的防火牆腳本 firewall.sh 內容複製貼上 並將 你的管理員IP 替換掉 # 1. 禁止連線的 IP 或網段(空白分隔) BADIPS="198.108.0.0/16 141.212.0.0/16" # 2. 不可能出現的私有 IP(RFC 1918) # 注意:若您的伺服器本身 IP 屬於以下網段,請務必刪除該行! # 10.0.0.0/8 → 大型企業內網 # 172.16.0.0/12 → 中型企業內網 # 192.168.0.0/16→ 小型辦公室/家庭網路 IMPOSSIBLE_IPS="192.168.0.0/16" # 3. 允許對內連線的 TCP 通訊埠 # 重要:請務必將「你的管理員IP」換成您當前連線的IP,否則套用 DROP 後將無法連線! IN_TCP_PORTALLOWED="22,你的管理員IP 888,你的管理員IP 80 443" ESC儲存並離開 :wq 設定腳本權限 (權限說明:700 表示僅 root 可讀寫執行,提高安全性) chmod 700 /usr/local/bin/firewall.sh ----------------- 測試防火牆腳本 ----------------- 執行腳本 (進入測試模式,7秒後自動清除規則) /usr/local/bin/firewall.sh 確認規則是否正常載入 iptables -L 若確認規則正確,使用 start 參數永久套用 /usr/local/bin/firewall.sh start ----------------------------- 整合 systemd 開機自動啟動 ----------------------------- 為了確保重開機後防火牆自動生效,我們建立一個 systemd 服務檔 建立服務檔 vi /etc/systemd/system/firewall.service 複製貼上以下內容 [Unit] Description=Custom iptables Firewall Service (nftables backend) DefaultDependencies=no Before=network-pre.target Wants=network-pre.target [Service] Type=oneshot RemainAfterExit=yes ExecStart=/usr/local/bin/firewall.sh start ExecStop=/usr/local/bin/firewall.sh stop StandardOutput=journal [Install] WantedBy=multi-user.target ESC儲存並離開 :wq ------------------ 啟用並啟動服務 ------------------ 重新載入 systemd 設定 systemctl daemon-reload 設定開機自動啟動 systemctl enable firewall.service 立即啟動服務 systemctl start firewall.service ---------------- 確認服務狀態 ---------------- 查看服務狀態,應顯示 active (exited) systemctl status firewall.service 查看啟動日誌 journalctl -u firewall.service ----------- 驗證設定 ----------- 重開機 reboot 重開機後確認防火牆規則是否自動載入 確認防火牆規則存在 iptables -L 確認服務狀態,若規則正確顯示,且服務狀態為 active (exited),表示設定成功 systemctl status firewall.service ------- 補充 ------- 先允許管理員IP的SSH,再套用DROP預設策略,避免鎖死自己 使用 journalctl 追蹤 systemd 啟動過程,方便除錯 定期備份防火牆腳本,並在更新前先於測試環境驗證 確認哪些連線埠正在對外監聽 ss -tnlp 查看已建立的連線 ss -tnp
-
iptables防火牆規則 firewall.sh (修改版)
#!/bin/sh # ----------------------------------------------------------------------------- # 防火牆腳本 - 適用於 Debian 13 / iptables-nft (nf_tables backend) # 存放路徑:/usr/local/bin/firewall.sh # 權限設定:chmod 700 /usr/local/bin/firewall.sh # 整合 systemd 開機啟動 (參考 firewall.service) # # 功能說明: # - 支援 start / stop 參數 # - 無參數執行時進入測試模式,7 秒後自動清除規則(避免鎖死自己) # - 包含核心參數調校(抗攻擊、防 IP Spoofing) # - 支援來源 IP 限制、連續埠、反向排除 # ----------------------------------------------------------------------------- # ========================== 使用者設定區塊 ========================== # # 警告:修改前請務必閱讀註解,並確認您的管理 IP 已正確設定! # 1. 禁止連線的 IP 或網段(空白分隔) # 範例:BADIPS="198.108.0.0/16 203.0.113.0/24" BADIPS="" # 2. 不可能出現的私有 IP(RFC 1918) # 注意:若您的伺服器本身 IP 屬於以下網段,請務必刪除該行! # 10.0.0.0/8 → 大型企業內網 # 172.16.0.0/12 → 中型企業內網 # 192.168.0.0/16→ 小型辦公室/家庭網路 IMPOSSIBLE_IPS="10.0.0.0/8 172.16.0.0/12 192.168.0.0/16" # 3. 允許對內連線的 TCP 通訊埠 # 格式說明: # - 單一埠:22 # - 連續埠:7000:7009(包含 7000~7009) # - 指定來源 IP:22,192.168.1.100 # - 反向排除(!):22,!192.168.1.100(允許所有人,除了該 IP) # - 網段寫法:22,10.0.0.0/8 # # 重要:請務必將「你的管理員IP」換成您當前連線的 IP,否則套用 DROP 後將無法連線! IN_TCP_PORTALLOWED="22,你的管理員IP 888,你的管理員IP 80 443" # 4. 允許對內連線的 UDP 通訊埠(格式同上) IN_UDP_PORTALLOWED="" # 5. 允許對內連線的 ICMP 類型 # 常用類型: # 0:Echo Reply(回應 PING) # 3:Destination Unreachable # 8:Echo Request(允許外部 PING 本機) # 11:Time Exceeded(traceroute 需要) IN_ICMP_ALLOWED="8" # ========================== 系統函式區塊 ========================== # # 警告:以下為程式邏輯,若您不熟悉 shell script,請勿任意修改 # 停止功能:清除所有規則,完全開放防火牆(供 systemd ExecStop 或緊急使用) if [ "$1" = "stop" ]; then echo -n "Stopping firewall (flushing all rules)..." iptables -P INPUT ACCEPT iptables -P OUTPUT ACCEPT iptables -P FORWARD ACCEPT iptables -t filter -F iptables -t filter -X echo " OK" echo "警告:所有防火牆規則已清除,伺服器目前無任何防護!" exit 0 fi # 清除現有規則,還原預設策略 echo -n "Initializing iptables..." iptables -P INPUT ACCEPT iptables -P FORWARD ACCEPT iptables -P OUTPUT ACCEPT iptables -t filter -F iptables -t filter -X echo " OK" # 若帶有 start 參數,則跳過測試模式 [ "$1" = "start" ] && skiptest="1" # ========================== 核心參數調校 ========================== # # 這些設定可提升伺服器對抗某些網路攻擊的能力 # 啟用 SYN Cookies(防止 SYN Flood 攻擊) sysctl -w net.ipv4.tcp_syncookies=2 > /dev/null 2>&1 # 忽略廣播 PING(防止 Smurf 攻擊) sysctl -w net.ipv4.icmp_echo_ignore_broadcasts=2 > /dev/null 2>&1 || \ sysctl -w net.ipv4.icmp_echo_ignore_all_broadcasts=2 > /dev/null 2>&1 # 忽略格式錯誤的 ICMP 封包 sysctl -w net.ipv4.icmp_ignore_bogus_error_responses=2 > /dev/null 2>&1 || \ sysctl -w net.ipv4.icmp_echo_ignore_bogus_error_responses=2 > /dev/null 2>&1 # 關閉 ICMP 重新導向(防止路由表被惡意變更) sysctl -w net.ipv4.conf.all.accept_redirects=0 > /dev/null 2>&1 sysctl -w net.ipv4.conf.default.accept_redirects=0 > /dev/null 2>&1 sysctl -w net.ipv4.conf.all.send_redirects=0 > /dev/null 2>&1 sysctl -w net.ipv4.conf.default.send_redirects=0 > /dev/null 2>&1 # 關閉來源路由(防止封包偽造) sysctl -w net.ipv4.conf.all.accept_source_route=0 > /dev/null 2>&1 sysctl -w net.ipv4.conf.default.accept_source_route=0 > /dev/null 2>&1 # 啟用逆向路徑過濾(防止 IP Spoofing) sysctl -w net.ipv4.conf.all.rp_filter=2 > /dev/null 2>&1 sysctl -w net.ipv4.conf.default.rp_filter=2 > /dev/null 2>&1 # TCP 逾時調校(加快斷線偵測) sysctl -w net.ipv4.tcp_retries1=3 > /dev/null 2>&1 sysctl -w net.ipv4.tcp_fin_timeout=30 > /dev/null 2>&1 sysctl -w net.ipv4.tcp_keepalive_time=1400 > /dev/null 2>&1 # 注意:以下功能為現代 TCP 必要選項,請勿關閉: # - tcp_window_scaling(高延遲高頻寬連線效能) # - tcp_sack(封包遺失重傳效率) # - tcp_timestamps(RTT 計算與 PAWS 保護) # ========================== 防火牆規則設定 ========================== # echo -n "Applying firewall rules..." # 設定預設策略:INPUT 與 FORWARD 預設丟棄,OUTPUT 預設允許 iptables -P INPUT DROP iptables -P FORWARD DROP iptables -P OUTPUT ACCEPT # 允許 Loopback 介面(本機程式互相通訊) iptables -A INPUT -i lo -j ACCEPT # -------------------------- 可疑封包處理 -------------------------- # # 建立 BADPKT 鏈,集中記錄與丟棄可疑封包 iptables -N BADPKT iptables -A BADPKT -m limit --limit 3/min -j LOG --log-prefix "BADPKT: " iptables -A BADPKT -j DROP # 阻擋連線狀態為 INVALID 的封包 iptables -A INPUT -m conntrack --ctstate INVALID -j BADPKT # 阻擋非 SYN 的新連線(異常連線嘗試) iptables -A INPUT -p tcp ! --syn -m conntrack --ctstate NEW -j BADPKT # 阻擋各種異常 TCP Flags 組合(掃描或攻擊手法) iptables -A INPUT -p tcp --tcp-flags ALL NONE -j BADPKT iptables -A INPUT -p tcp --tcp-flags SYN,FIN SYN,FIN -j BADPKT iptables -A INPUT -p tcp --tcp-flags SYN,RST SYN,RST -j BADPKT iptables -A INPUT -p tcp --tcp-flags FIN,RST FIN,RST -j BADPKT iptables -A INPUT -p tcp --tcp-flags ACK,FIN FIN -j BADPKT iptables -A INPUT -p tcp --tcp-flags ACK,URG URG -j BADPKT iptables -A INPUT -p tcp --tcp-flags ACK,PSH PSH -j BADPKT iptables -A INPUT -p tcp --tcp-flags ALL FIN,URG,PSH -j BADPKT iptables -A INPUT -p tcp --tcp-flags ALL SYN,RST,ACK,FIN,URG -j BADPKT iptables -A INPUT -p tcp --tcp-flags ALL ALL -j BADPKT iptables -A INPUT -p tcp --tcp-flags ALL FIN -j BADPKT # -------------------------- 狀態允許規則 -------------------------- # # 允許已建立連線與相關連線(回應封包不需重新驗證) iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT # -------------------------- 阻擋特定 IP -------------------------- # iptables -N BADIP iptables -A BADIP -j DROP for ip in $BADIPS $IMPOSSIBLE_IPS; do # 忽略空白變數 [ -n "$ip" ] && iptables -A INPUT -s $ip -j BADIP done # -------------------------- 允許特定連線 -------------------------- # # 允許 TCP 連線 for entry in $IN_TCP_PORTALLOWED; do # 處理格式 "port,source" 或 "port" case "$entry" in *,*) port=$(echo "$entry" | cut -d, -f1) src=$(echo "$entry" | cut -d, -f2-) # 處理反向排除 "!" 符號 if echo "$src" | grep -q '^!'; then src_ip=$(echo "$src" | sed 's/^!//') iptables -A INPUT -p tcp --dport $port --syn -m conntrack --ctstate NEW -s $src_ip -j DROP iptables -A INPUT -p tcp --dport $port --syn -m conntrack --ctstate NEW -j ACCEPT else iptables -A INPUT -p tcp --dport $port --syn -m conntrack --ctstate NEW -s $src -j ACCEPT fi ;; *) iptables -A INPUT -p tcp --dport $entry --syn -m conntrack --ctstate NEW -j ACCEPT ;; esac done # 允許 UDP 連線(無 SYN 標誌) for entry in $IN_UDP_PORTALLOWED; do case "$entry" in *,*) port=$(echo "$entry" | cut -d, -f1) src=$(echo "$entry" | cut -d, -f2-) if echo "$src" | grep -q '^!'; then src_ip=$(echo "$src" | sed 's/^!//') iptables -A INPUT -p udp --dport $port -m conntrack --ctstate NEW -s $src_ip -j DROP iptables -A INPUT -p udp --dport $port -m conntrack --ctstate NEW -j ACCEPT else iptables -A INPUT -p udp --dport $port -m conntrack --ctstate NEW -s $src -j ACCEPT fi ;; *) iptables -A INPUT -p udp --dport $entry -m conntrack --ctstate NEW -j ACCEPT ;; esac done # 允許 ICMP 類型 for entry in $IN_ICMP_ALLOWED; do case "$entry" in *,*) type=$(echo "$entry" | cut -d, -f1) src=$(echo "$entry" | cut -d, -f2-) if echo "$src" | grep -q '^!'; then src_ip=$(echo "$src" | sed 's/^!//') iptables -A INPUT -p icmp --icmp-type $type -m conntrack --ctstate NEW -s $src_ip -j DROP iptables -A INPUT -p icmp --icmp-type $type -m conntrack --ctstate NEW -j ACCEPT else iptables -A INPUT -p icmp --icmp-type $type -m conntrack --ctstate NEW -s $src -j ACCEPT fi ;; *) iptables -A INPUT -p icmp --icmp-type $entry -m conntrack --ctstate NEW -j ACCEPT ;; esac done # 對外連線不限制(預設 OUTPUT ACCEPT) # 若需要限制對外連線,可在 OUTPUT 鏈設定規則,此處不贅述 echo " OK" # ========================== 測試模式 ========================== # if [ "$skiptest" = "1" ]; then exit 0 fi echo "" echo "!!! 測試模式 !!!" echo "防火牆規則已套用,將在 7 秒後自動清除,以防止您意外鎖定自己。" echo "若您仍能正常連線,請按 Ctrl + C 中斷,然後執行:" echo " /usr/local/bin/firewall.sh start" echo "" i=1 while [ "$i" -le 7 ]; do echo -n "." sleep 1 i=$((i + 1)) done echo "" echo -n "正在清除規則..." iptables -P INPUT ACCEPT iptables -P OUTPUT ACCEPT iptables -P FORWARD ACCEPT iptables -t filter -F iptables -t filter -X echo " OK" echo "測試模式結束。若連線中斷,請使用 VNC/Serial Console 重新登入並修正規則。" firewall.sh
- 之前的
-
使用 rm 指令刪除整個論壇目錄 (請務必謹慎操作)
使用 rm 指令刪除整個論壇目錄 (請務必謹慎操作) ---------------------------- 重要安全警告 (請務必閱讀) ---------------------------- rm 指令具有以下特性,使用前務必了解 無法回復:刪除後無法從資源回收筒還原 立即生效:執行後立刻永久刪除 沒有二次確認:使用 -f 參數時不會詢問 權限影響大:使用 root 權限可刪除任何檔案 黃金法則:刪除前務必三次確認目標路徑是否正確 ------- 前言 ------- 在純測試論壇功能、或重新安裝論壇時,直接刪除整個目錄是最快速的方法 然而,rm 指令具有不可回復性,操作時務必謹慎 適合在無Linux面板情況 (手搓LNMP),能夠快速刪除目錄與檔案,簡單操作幾下,就能再次安裝新論壇 ------------------- 刪除整個論壇目錄 ------------------- 當需要完整移除論壇檔案時,請依照以下步驟進行 SSH登入,進入上層目錄 cd /var/www/ 再次確認目前所在位置 (確保畫面顯示為 /var/www) pwd 執行刪除指令,刪除整個論壇目錄 rm -r 域名.com/ 參數說明 -r(recursive):遞迴刪除整個目錄及其內容 刻意不使用 -f,避免誤刪時完全沒有警告 ---------------------------------- 僅刪除目錄中的特定檔案或子目錄 ---------------------------------- SSH登入,進入該論壇目錄 cd /var/www/域名.com 查看檔案清單 (確認目標檔案名稱與權限) ls -l 刪除特定目錄 rm -r 目錄名稱/ 刪除單一檔案 rm 檔案名稱 ------------------------------- 重新建立論壇目錄與權限設定 ------------------------------- 刪除完成後,若需要重新部署論壇,請重新建立目錄與正確權限 建立論壇目錄 mkdir -p /var/www/域名.com --------------------- 設定權限 (重要) --------------------- 將所有權交給網頁伺服器用戶 chown -R www-data:www-data /var/www/域名.com 設定目錄權限為 755 chmod -R 755 /var/www/域名.com 為什麼這樣設定? www-data:確保 Nginx / PHP-FPM 可正常存取 755:目錄可讀取與執行,避免過度開放權限 ----------- 後續步驟 ----------- 透過SFTP上傳論壇程式 重新設定資料庫與設定檔 瀏覽論壇,確認是否正常運作
-
Invision Community 5.0.0 ~ 5.0.x 之間的論壇版本升級
Invision Community 5.0.0 ~ 5.0.x 之間的論壇版本升級 ------------------------------------ 暫時關閉論壇 ------------------------------------ 目的:避免升級過程中,會員操作導致資料錯誤或異常 論壇後端 -> 系統 -> 一般配置 -> 關閉或開啟論壇 -> x 關閉 關閉的原因 -> 建議填寫原因,例如:系統升級維護中,預計於 XX:XX 完成,造成不便敬請見諒 儲存 -> ----------------------------------- 下載Invision Community最新版本 ----------------------------------- 建議在Windows就先解壓縮,雖然論壇升級是直接覆蓋檔案後升級,但可以先刪除不必要的檔案 然後重新壓縮為 ips.zip ------------------------------------ 先備份資料庫、網站目錄 ------------------------------------ 升級前先備份DB資料庫、Web網站目錄,避免升級失敗無法回復 注意:先將今日的自動備份檔,改個檔名,再下備份指令 (不然檔名會重覆) 指令 bash /root/backup.sh ------------------------- 停止Nginx (重要) ------------------------- 在進行檔案替換前,請務必先停止Nginx,確保檔案替換時不會產生衝突 systemctl stop nginx 為什麼要先停? 避免檔案解壓時造成讀寫衝突 使用SFTP上傳Invision Community論壇的最新版本 (ips.zip) 前往論壇根目錄 /var/www/域名.com SSH登入,解壓縮Invision Community論壇的最新版本 (ips.zip) 並覆蓋檔案 cd /var/www/域名.com 解壓縮並覆蓋舊檔案 (-o 參數表示覆蓋) unzip -o ips.zip 然後刪除壓縮檔ips.zip rm ips.zip 將所有權變更為網頁伺服器使用者 (確保 Nginx / PHP 有正確的讀寫權限) chown -R www-data:www-data /var/www/域名.com cd /var/www/域名.com 確認輸出顯示為 www-data www-data ls -l 為了主機安全,設定標準檔案權限 將所有「目錄」設為 755 find /var/www/域名.com -type d -exec chmod 755 {} \; 將所有「檔案」設為 644 find /var/www/域名.com -type f -exec chmod 644 {} \; --------------------- 排程任務權限確認 --------------------- 確保IPS論壇的 task.php 具備執行權限 chmod 755 /var/www/域名.com/applications/core/interface/task/task.php 檢查 crontab 設定 (如有需要) crontab -l | grep task.php ---------------------------------- 強化 conf_global.php 安全性 ---------------------------------- 修改權限為 640 或 600 chmod 640 /var/www/域名.com/conf_global.php ------------- 啟動Nginx ------------- 啟動Nginx,啟動Web服務 systemctl start nginx ------------------------ 升級論壇 ------------------------ 瀏覽器進入論壇 https://域名.com/admin/upgrade/ 依照提示,登入管理員帳號 -> 開始升級過程 -> 完成升級 注意:升級過程請勿關閉瀏覽器或中斷連線 ------------------------ 升級完成後,開啟論壇 ------------------------ 論壇後端 -> 系統 -> 一般配置 -> 關閉或開啟論壇 -> v (是) -> 儲存 論壇後端 -> 系統 -> 獲得支援 -> 清除系統快取 在 [獲得支援] 這裡,有些錯誤會提示你需要解決 ------------------------ 更新中文語言包 ------------------------ 如果有新版本的IPS中文包,則需要更新(覆蓋) ------------------------ 重建網站地圖 ------------------------ 論壇後端 -> 系統 -> 搜尋引擎最佳化 -> 右上方的 重建網站地圖 ------------------------ 重建搜尋索引 ------------------------ 論壇後端 -> 系統 -> 搜尋 -> 右上方的 重建搜尋索引 -> 同意 注意事項 若使用第三方插件或模板主題,升級前請先確認有無推出新版本 升級後請徹底測試論壇功能,若有問題,請在論壇後端的支援頁,關閉部分第三方插件,確認是否為第三方插件的問題
-
413 Request Entity Too Large
413 Request Entity Too Large 解決這個問題的核心原因只有一個,因為 client_max_body_size 太小 修改 nginx.conf vi /etc/nginx/nginx.conf 搜尋 client_max_body_size 並修改為 client_max_body_size 200m; ESC儲存並離開 :wq 測試設定 (必要步驟) nginx -t 重新載入 (不中斷連線) systemctl reload nginx
-
Invision Community論壇啟用Redis加速
Invision Community論壇啟用 Redis 加速 為什麼論壇需要 Redis? 提升讀取速度:記憶體存取比硬碟快數十倍,顯著提升頁面加載速度 。 減輕資料庫壓力:大幅降低 MySQL 的查詢負載,讓資料庫在高負載時仍能穩定運作 。 改善使用者體驗:減少瀏覽延遲,特別是在高併發存取時能維持流暢度 。 檢查論壇是否啟用Redis 論壇後端 -> 系統 -> 獲得支援 -> 快取引擎:None (表示未啟用Redis) 設置Redis加速 論壇後端 -> 系統 -> 進階配置 -> 資料儲存 -> 預設情況是 如果在安裝LNMP過程中,有確實安裝Redis,就能選擇 資料儲存方式 -> Redis 快取方式 -> Redis IPS論壇有兩個地方可啟用Redis,在此由自己的VPS硬體配置決定開啟或關掉誰 Redis server address -> 127.0.0.1 Redis port number -> 6379 使用Redis來減少MySQL Overhead -> v 是 Redis將用於會話、管理主題瀏覽數 -> 儲存 接下來,出現選項 [下載 constants.php],按下按鈕,下載constants.php這個檔案 再使用SFTP將constants.php上傳到IPS論壇的根目錄 為什麼需要 constants.php? 論壇會透過此檔案定義Redis連線與快取設定 若檔案不存在,Redis將不會生效 當SFTP上傳 constants.php 這個檔案後,回到瀏覽器,按下 [繼續] 接下來,SSH登入 修正檔案擁有者與權限,設為 www-data (避免Nginx/PHP 使用者無法讀寫) chown www-data:www-data /var/www/域名.com/constants.php cd /var/www/域名.com 確認輸出顯示為 www-data www-data ls -l 回到瀏覽器,論壇後端 -> 系統 -> 獲得支援 -> 可以看到 快取引擎:Redis 表示論壇已啟用Redis
-
Invision Community論壇啟用偽靜態與自訂友善網址
Invision Community論壇啟用偽靜態與自訂友善網址 事前準備 在前面步驟,已於Nginx配置了偽靜態規則 (/etc/nginx/rewrite/ips.conf) 現在,還需要到IPS論壇後端開啟偽靜態功能,並修改網址的顯示方式 ------------------------------------ IPS論壇後端,也需要設置偽靜態 ------------------------------------ 論壇後端 -> 系統 -> 搜尋引擎最佳化 -> 偽靜態網址? -> [v] 是 -> 確認 回到論壇前端,論壇網址將不再顯示 index.php 自訂友善網址格式 如果希望網址更簡潔 (移除標題文字),可依以下步驟調整: https://域名.com/topic/2-新主題標題/ 改法為 論壇後端 -> 系統 -> 進階配置 -> 友善網址 -> 看到友善網址後面連接 -?? 問號的 -> 編輯 -> 友善網址 -> 只刪掉 -{?} 然後按下確認,千萬別改錯了 這種 -{?} 要修改的地方很多,並且插件安裝越多,也就修改越多 以後再安裝什麼插件,一樣要來此處修改它,別忘了 修改好後的友善網址 ------------------------- 清除快取 ------------------------- 論壇後端 -> 系統 -> 支援 -> 清除快取 完成以上步驟後,論壇網址將從: https://域名.com/topic/2-新主題標題/ 變為更簡潔的格式: https://域名.com/topic/2/ 注意事項 修改網址結構可能影響搜尋引擎收錄,建議在 Google Search Console 提交新的網站地圖 若為已經有流量的老站,不建議頻繁變更網址結構
-
大马猴注册了
-
phpMyAdmin建立新的資料庫用戶名、資料庫用戶密碼、資料庫名
phpMyAdmin建立新的資料庫用戶名、資料庫用戶密碼、資料庫名 ---------------------------------------------------------------------- phpMyAdmin建立新的資料庫用戶名、資料庫用戶密碼 ---------------------------------------------------------------------- phpMyAdmin首頁 -> 使用者帳號 -> 新增使用者帳號 通常是建立 域名_com ,但不能用中文字 使用者名稱:xxxx_com 主機名稱:localhost 密碼:請使用底下的產生密碼 -> 按 產生,將產生隨機密碼 如果你的VPS只安裝一個論壇,那麼權限都給出 全域權限 -> v 全選 -> 執行 將顯示 已新增了新的使用者。 ---------------------------------------------------------------------- phpMyAdmin建立資料庫名 ---------------------------------------------------------------------- phpMyAdmin首頁 -> 上方的資料庫選項 -> 建立新資料庫 -> 資料庫名 通常也是資料庫用戶名 xxxx_com 編碼與排序 -> 選擇 utf8mb4_unicode_ci -> 建立 ---------------------------------------------------------------------- 資料庫用戶名、資料庫用戶密碼、資料庫名 ---------------------------------------------------------------------- 資料庫用戶名 -> xxxx_com 資料庫用戶密碼 -> 自動產生的隨機密碼 資料庫名 -> xxxx_com
-
安裝phpMyAdmin、修改為 888 port、使用IP當phpMyAdmin的網址來管理資料庫
安裝phpMyAdmin、修改為 888 port、使用IP當phpMyAdmin的網址來管理資料庫 ---------------------------- 安裝phpMyAdmin ---------------------------- 開始修改 vi /etc/nginx/sites-available/default 搜尋內容 index index.html index.htm index.nginx-debian.html; 修改為 index index.html index.htm index.php; ESC儲存並離開 :wq 先到phpMyAdmin官網,最新版本是多少,例如 phpMyAdmin 5.2.3 https://www.phpmyadmin.net/ cd /root wget -P Downloads https://files.phpmyadmin.net/phpmyadmin.keyring wget -P Downloads https://files.phpmyadmin.net/phpMyAdmin/5.2.3/phpMyAdmin-5.2.3-all-languages.tar.gz cd Downloads gpg --import phpmyadmin.keyring wget https://files.phpmyadmin.net/phpMyAdmin/5.2.3/phpMyAdmin-5.2.3-all-languages.tar.gz.asc gpg --verify phpMyAdmin-5.2.3-all-languages.tar.gz.asc mkdir /var/www/html/phpMyAdmin tar xvf phpMyAdmin-5.2.3-all-languages.tar.gz --strip-components=1 -C /var/www/html/phpMyAdmin cp /var/www/html/phpMyAdmin/config.sample.inc.php /var/www/html/phpMyAdmin/config.inc.php vi /var/www/html/phpMyAdmin/config.inc.php 搜尋 $cfg['blowfish_secret'] = ''; 修改為 $cfg['blowfish_secret'] = '自定一個長度為32位元的隨機字串'; ESC儲存並離開 :wq chmod 660 /var/www/html/phpMyAdmin/config.inc.php chown -R www-data:www-data /var/www/html/phpMyAdmin 重新加载Nginx nginx -t systemctl reload nginx 然後修改 (請注意這是搭配PHP 8.4的設置) vi /etc/nginx/sites-available/default 搜尋這代碼 location / { # First attempt to serve request as file, then # as directory, then fall back to displaying a 404. try_files $uri $uri/ =404; } 然後,在這段代碼的底下,加入 location ~ \.php$ { include snippets/fastcgi-php.conf; fastcgi_pass unix:/var/run/php/php8.4-fpm.sock; } ESC儲存並離開 :wq 重新加载Nginx nginx -t systemctl reload nginx 現在瀏覽器可以進入phpMyAdmin (此時 http 是用 80 port) http://你的IP/phpMyAdmin --------------------------------- phpMyAdmin改為 888 port --------------------------------- 我慣用伺服器IP當作phpMyAdmin的網址,並改為 888 port,利用防火牆擋住全部IP連入,限自己的IP才能連入phpMyAdmin 預設網站目錄是放在 /var/www/html/phpMyAdmin/ 修改為 888 port,才能連到phpMyAdmin vi /etc/nginx/sites-available/default 搜尋 listen 80 default_server; 修改為 listen 888 default_server; 下面那一行,使用 # 註解掉 #listen [::]:80 default_server; ESC儲存並離開 :wq 重新加载Nginx nginx -t systemctl reload nginx 重開機,再次確認是否能正確運行 reboot phpMyAdmin 已改為 888 port 然後雲主機的WAF防火牆、iptables防火牆,也要修改 888 port 只允許自己的IP才可以連入 這時,防火牆都修改完畢,瀏覽器進入你的伺服器IP http://你的IP:888/phpMyAdmin/ 你將看到這個訊息 尚未設定 phpMyAdmin 設定儲存空間,部份延伸功能將無法使用。了解原因。 或者前往任一個資料庫的「操作」分頁設定。 你需要下載 https://www.phpmyadmin.net/downloads/phpMyAdmin-latest-all-languages.tar.gz 解壓縮 phpMyAdmin-latest-all-languages.tar.gz 尋找目錄中 /sql/create_tables.sql 找到 create_tables.sql 返回瀏覽器 phpMyAdmin -> 匯入 -> 要匯入的檔案 -> 選擇檔案 -> create_tables.sql -> 匯入 將顯示 完成匯入,共執行了 21 個查詢指令。 (create_tables.sql) 然後返回phpMyAdmin首頁 尚未設定 phpMyAdmin 設定儲存空間,部份延伸功能將無法使用。-----> 已經沒有顯示這一條訊息
-
安裝第三方Nginx 1.29、更改主機名
安裝第三方Nginx 1.29、更改主機名 --------------- 安裝Nginx --------------- 本教學適用於 Debian 13 (需root權限),假設系統尚未安裝Nginx 此來源 https://n.wtf/ 提供第三方 Nginx(目前為 1.29.x),若想使用 Debian 官方版本可略過此步 增加 https://n.wtf GPG Key curl -sSL https://n.wtf/public.key | gpg --dearmor > /usr/share/keyrings/n.wtf.gpg 加入 https://n.wtf/ 的Nginx源 echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/n.wtf.gpg] https://mirror-cdn.xtom.com/sb/nginx/ $(lsb_release -sc) main" > /etc/apt/sources.list.d/n.wtf.list apt update apt install zip unzip apt install curl vim wget gnupg dpkg apt-transport-https lsb-release ca-certificates 安裝nginx apt install nginx-extras -y 瀏覽nginx版本,顯示 nginx version: nginx-n.wtf/1.29.4 nginx -V ---------------------------- 更改主機名 ---------------------------- 更改主機名,修改 hostname 可能影響提示字元或部分服務,非必要可略過 hostnamectl set-hostname 域名.com 離開SSH exit 再次SSH登入 將顯示為 Linux 域名.com 6.12.63+deb13-cloud-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.12.63-1 (2025-12-30) x86_64 ---------------------------- 配置Nginx ---------------------------- 預設網站目錄 mkdir -p /var/www/域名.com 新增 域名.com.conf vi /etc/nginx/sites-available/域名.com.conf server { listen 80; root /var/www/域名.com; index index.html index.htm; server_name 域名.com; location / { try_files $uri $uri/ =404; } } ESC儲存並離開 :wq 若 /etc/nginx/sites-enabled/ 已存在其他網站,請先確認不衝突 軟連結到 /etc/nginx/sites-enabled 目錄,讓它生效 ln -s /etc/nginx/sites-available/域名.com.conf /etc/nginx/sites-enabled/域名.com.conf 重新載入Nginx nginx -t systemctl reload nginx 在網站目錄中,新增一個index.html vi /var/www/域名.com/index.html 在此檔案中,複製並貼上 <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>TEST</title> </head> <body> TEST </body> </html> ESC儲存並離開 :wq ---------------------------------- 開機啟動Nginx ---------------------------------- 開機啟動 systemctl enable nginx 啟動 systemctl start nginx 重開機 reboot 確認開機有自動啟動nginx,顯示 Active: active (running) systemctl status nginx 這時,瀏覽器可進入你的網站 http://域名.com/index.html
-
安裝資料庫MariaDB 11.8與配置,資料庫最佳化 4 - 8G RAM
安裝資料庫MariaDB 11.8與配置,資料庫最佳化 4 - 8G RAM -------------------------------- 安裝MariaDB與配置 -------------------------------- 下載GPG Key curl -sSL https://mariadb.org/mariadb_release_signing_key.asc | gpg --dearmor > /usr/share/keyrings/mariadb.gpg 加入MariaDB 11.8的源 echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/mariadb.gpg] https://mirror-cdn.xtom.com/mariadb/repo/11.8/debian $(lsb_release -sc) main" > /etc/apt/sources.list.d/mariadb.list 更新 apt update 安裝 MariaDB 11.8.x 最新穩定版 apt install mariadb-server mariadb-client Configuring mariadb-server Feedback plugin collects basic anonymous statistical information that can be used by the developers to improve MariaDB. This is an easy way to help with MariaDB development. Collected statistics can be viewed at http://mariadb.org/feedback-plugin Enable the Feedback plugin and submit anonymous usage information? <Yes> /<No> 選擇 <No> 瀏覽版本,已安裝 11.8.5-MariaDB mariadb -V ------------------- 安全設置 ------------------- mariadb-secure-installation NOTE: RUNNING ALL PARTS OF THIS SCRIPT IS RECOMMENDED FOR ALL MariaDB SERVERS IN PRODUCTION USE! PLEASE READ EACH STEP CAREFULLY! 注意:建議所有 MariaDB 運行此腳本的所有部分生產使用中的伺服器! 請仔細閱讀每個步驟! In order to log into MariaDB to secure it, we'll need the current password for the root user. If you've just installed MariaDB, and haven't set the root password yet, you should just press enter here. 為了登入 MariaDB 並確保其安全,我們需要 root 使用者目前的密碼。如果你剛剛安裝了MariaDB,並且尚未設定root密碼,則只需在此處按Enter 鍵即可。 Enter current password for root (enter for none): 輸入 root 的目前密碼 (不輸入): 按 Enter OK, successfully used password, moving on... 好的,密碼已成功使用,繼續... Setting the root password or using the unix_socket ensures that nobody can log into the MariaDB root user without the proper authorisation. 設定root密碼或使用 unix_socket 可確保任何人在未經適當授權的情況下都無法登入MariaDB root使用者。 You already have your root account protected, so you can safely answer 'n'. 你的root帳戶已受到保護,因此你可以安全地回答 'n'。 Switch to unix_socket authentication [Y/n] 切換到 unix_socket 身份驗證 [Y/n] 按 n 若為單機伺服器,建議按 Y,使用 unix_socket 驗證(較安全) Change the root password? [Y/n] 更改root密碼? [Y/n] 按 y New password: 輸入你自定義root的密碼 Re-enter new password: 再次輸入你自定義root的密碼 By default, a MariaDB installation has an anonymous user, allowing anyone to log into MariaDB without having to have a user account created for them. This is intended only for testing, and to make the installation go a bit smoother. You should remove them before moving into a production environment. 預設情況下,MariaDB安裝有一個匿名用戶,允許任何人登入MariaDB,而無需為其建立用戶帳戶。這僅用於測試,並使安裝過程更加順利。你應該在進入生產環境之前刪除它們。 Remove anonymous users? [Y/n] 刪除匿名用戶? [Y/n] 按 y Normally, root should only be allowed to connect from 'localhost'. This ensures that someone cannot guess at the root password from the network. 通常,只允許root從 'localhost' 連線。這可確保其他人無法從網路猜測root密碼。 Disallow root login remotely? [Y/n] 禁止遠端root登入? [Y/n] 要按 y By default, MariaDB comes with a database named 'test' that anyone can access. This is also intended only for testing, and should be removed before moving into a production environment. 預設情況下,MariaDB附帶一個名為 'test' 的資料庫,任何人都可以存取。這也僅用於測試,應在進入生產環境之前將其刪除。 Remove test database and access to it? [Y/n] 刪除測試資料庫並存取它? 按 y Reloading the privilege tables will ensure that all changes made so far will take effect immediately. 重新載入權限表將確保迄今為止所做的所有變更都會立即生效。 Reload privilege tables now? [Y/n] 現在重新載入權限表? [Y/n] 按 y All done! If you've completed all of the above steps, your MariaDB installation should now be secure. Thanks for using MariaDB! 重啟資料庫 systemctl restart mariadb -------------- UTF-8 -------------- vi /etc/mysql/mariadb.conf.d/50-client.cnf 在 [client] 底下,加入這一行 default-character-set = utf8mb4 # # This group is read by the client library # Use it for options that affect all clients, but not the server # [client] # Example of client certificate usage #ssl-cert = /etc/mysql/client-cert.pem #ssl-key = /etc/mysql/client-key.pem # # Allow only TLS encrypted connections #ssl-verify-server-cert = on default-character-set = utf8mb4 # This group is *never* read by mysql client library, though this # /etc/mysql/mariadb.cnf.d/client.cnf file is not read by Oracle MySQL # client anyway. # If you use the same .cnf file for MySQL and MariaDB, # use it for MariaDB-only client options [client-mariadb] ESC儲存並離開 :wq --------------------------------------------------------------------------------- 資料庫最佳化 / 數據庫優化 4 - 8 GB --------------------------------------------------------------------------------- 修改 vi /etc/mysql/mariadb.conf.d/50-server.cnf # These groups are read by MariaDB server. # Use it for options that only the server (but not clients) should see # this is read by the standalone daemon and embedded servers [server] # this is only for the mariadbd daemon [mariadbd] # # * Basic Settings # port = 3306 user = mariadb pid-file = /run/mysqld/mysqld.pid basedir = /usr datadir = /var/lib/mysql tmpdir = /tmp # Broken reverse DNS slows down connections considerably and name resolve is # safe to skip if there are no "host by domain name" access grants #skip-name-resolve # Instead of skip-networking the default is now to listen only on # localhost which is more compatible and is not less secure. #預設僅監聽 localhost,如需遠端連線請自行調整 bind-address = 127.0.0.1 # # * Fine Tuning # #MyISAM index buffer,多數 InnoDB 環境影響有限 key_buffer_size = 32M #大型資料庫匯入,需求可提高 max_allowed_packet = 1G table_open_cache = 384 sort_buffer_size = 1024K net_buffer_length = 8K read_buffer_size = 1024K read_rnd_buffer_size = 768K myisam_sort_buffer_size = 8M thread_cache_size = 128 tmp_table_size = 128M max_heap_table_size = 128M explicit_defaults_for_timestamp = true #skip-networking max_connections = 100 max_connect_errors = 100 open_files_limit = 65535 #若不使用主從複製或 PITR,可考慮關閉 binlog log-bin=mysql-bin binlog_format=mixed server-id = 1 expire_logs_days = 10 default_storage_engine = InnoDB # # * Logging and Replication # expire_logs_days = 10 # # * Character sets # # MariaDB default is now utf8 4-byte character set. # No Debian specific default is required. # # * InnoDB # innodb_file_per_table = 1 innodb_buffer_pool_size = 4G #若調整此值導致無法啟動,請確認 ib_logfile 已重新建立 innodb_log_file_size = 256M innodb_log_buffer_size = 16M innodb_flush_log_at_trx_commit = 1 innodb_lock_wait_timeout = 50 [mysqldump] quick #大型資料庫匯入,需求可提高 max_allowed_packet = 1G [mysql] no-auto-rehash [myisamchk] key_buffer_size = 20M sort_buffer_size = 20M read_buffer = 2M write_buffer = 2M [mysqlhotcopy] interactive-timeout # InnoDB is enabled by default with a 10MB datafile in /var/lib/mysql/. # Read the manual for more InnoDB related options. There are many! # Most important is to give InnoDB 80 % of the system RAM for buffer use: # https://mariadb.com/kb/en/innodb-system-variables/#innodb_buffer_pool_size #innodb_buffer_pool_size = 8G # this is only for embedded server [embedded] # This group is only read by MariaDB servers, not by MySQL. # If you use the same .cnf file for MySQL and MariaDB, # you can put MariaDB-only options here [mariadbd] # This group is only read by MariaDB-11.8 servers. # If you use the same .cnf file for MariaDB of different versions, # use this group for options that older servers don't understand [mariadb-11.8] ESC儲存並離開 :wq ------------------------------------- 重啟 & 重開機 ------------------------------------- 重啟 systemctl restart mariadb 開機啟動mariadb systemctl enable mariadb 啟動mariadb systemctl start mariadb 瀏覽狀態 systemctl status mariadb 重開機 reboot 重開機,確認MariaDB可以自動啟動,顯示 Active: active (running) systemctl status mariadb
-
安裝資料庫MariaDB 11.8與配置,資料庫最佳化 2 - 3G RAM
安裝資料庫MariaDB 11.8與配置,資料庫最佳化 2 - 3G RAM -------------------------------- 安裝MariaDB與配置 -------------------------------- 下載GPG Key curl -sSL https://mariadb.org/mariadb_release_signing_key.asc | gpg --dearmor > /usr/share/keyrings/mariadb.gpg 加入MariaDB 11.8的源 echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/mariadb.gpg] https://mirror-cdn.xtom.com/mariadb/repo/11.8/debian $(lsb_release -sc) main" > /etc/apt/sources.list.d/mariadb.list 更新系統 apt update 安裝 MariaDB 11.8.x 最新穩定版 apt install mariadb-server mariadb-client Configuring mariadb-server Feedback plugin collects basic anonymous statistical information that can be used by the developers to improve MariaDB. This is an easy way to help with MariaDB development. Collected statistics can be viewed at http://mariadb.org/feedback-plugin Enable the Feedback plugin and submit anonymous usage information? <Yes> /<No> 選擇 <No> 瀏覽版本,已安裝 11.8.5-MariaDB mariadb -V ------------------- 安全設置 ------------------- mariadb-secure-installation NOTE: RUNNING ALL PARTS OF THIS SCRIPT IS RECOMMENDED FOR ALL MariaDB SERVERS IN PRODUCTION USE! PLEASE READ EACH STEP CAREFULLY! 注意:建議所有 MariaDB 運行此腳本的所有部分生產使用中的伺服器! 請仔細閱讀每個步驟! In order to log into MariaDB to secure it, we'll need the current password for the root user. If you've just installed MariaDB, and haven't set the root password yet, you should just press enter here. 為了登入 MariaDB 並確保其安全,我們需要 root 使用者目前的密碼。如果你剛剛安裝了MariaDB,並且尚未設定root密碼,則只需在此處按Enter 鍵即可。 Enter current password for root (enter for none): 輸入 root 的目前密碼 (不輸入): 按 Enter OK, successfully used password, moving on... 好的,密碼已成功使用,繼續... Setting the root password or using the unix_socket ensures that nobody can log into the MariaDB root user without the proper authorisation. 設定root密碼或使用 unix_socket 可確保任何人在未經適當授權的情況下都無法登入MariaDB root使用者。 You already have your root account protected, so you can safely answer 'n'. 你的root帳戶已受到保護,因此你可以安全地回答 'n'。 Switch to unix_socket authentication [Y/n] 切換到 unix_socket 身份驗證 [Y/n] 按 n 若為單機伺服器,建議按 Y,使用 unix_socket 驗證(較安全) Change the root password? [Y/n] 更改root密碼? [Y/n] 按 y New password: 輸入你自定義root的密碼 Re-enter new password: 再次輸入你自定義root的密碼 By default, a MariaDB installation has an anonymous user, allowing anyone to log into MariaDB without having to have a user account created for them. This is intended only for testing, and to make the installation go a bit smoother. You should remove them before moving into a production environment. 預設情況下,MariaDB安裝有一個匿名用戶,允許任何人登入MariaDB,而無需為其建立用戶帳戶。這僅用於測試,並使安裝過程更加順利。你應該在進入生產環境之前刪除它們。 Remove anonymous users? [Y/n] 刪除匿名用戶? [Y/n] 按 y Normally, root should only be allowed to connect from 'localhost'. This ensures that someone cannot guess at the root password from the network. 通常,只允許root從 'localhost' 連線。這可確保其他人無法從網路猜測root密碼。 Disallow root login remotely? [Y/n] 禁止遠端root登入? [Y/n] 要按 y By default, MariaDB comes with a database named 'test' that anyone can access. This is also intended only for testing, and should be removed before moving into a production environment. 預設情況下,MariaDB附帶一個名為 'test' 的資料庫,任何人都可以存取。這也僅用於測試,應在進入生產環境之前將其刪除。 Remove test database and access to it? [Y/n] 刪除測試資料庫並存取它? 按 y Reloading the privilege tables will ensure that all changes made so far will take effect immediately. 重新載入權限表將確保迄今為止所做的所有變更都會立即生效。 Reload privilege tables now? [Y/n] 現在重新載入權限表? [Y/n] 按 y All done! If you've completed all of the above steps, your MariaDB installation should now be secure. Thanks for using MariaDB! 重啟資料庫 systemctl restart mariadb -------------- UTF-8 -------------- vi /etc/mysql/mariadb.conf.d/50-client.cnf 在 [client] 底下,加入這一行 default-character-set = utf8mb4 # # This group is read by the client library # Use it for options that affect all clients, but not the server # [client] # Example of client certificate usage #ssl-cert = /etc/mysql/client-cert.pem #ssl-key = /etc/mysql/client-key.pem # # Allow only TLS encrypted connections #ssl-verify-server-cert = on default-character-set = utf8mb4 # This group is *never* read by mysql client library, though this # /etc/mysql/mariadb.cnf.d/client.cnf file is not read by Oracle MySQL # client anyway. # If you use the same .cnf file for MySQL and MariaDB, # use it for MariaDB-only client options [client-mariadb] ESC儲存並離開 :wq --------------------------------------------------------------------------------- 資料庫最佳化 / 數據庫優化 2 - 3 GB --------------------------------------------------------------------------------- 修改 vi /etc/mysql/mariadb.conf.d/50-server.cnf # These groups are read by MariaDB server. # Use it for options that only the server (but not clients) should see # this is read by the standalone daemon and embedded servers [server] # this is only for the mariadbd daemon [mariadbd] # # * Basic Settings # port = 3306 user = mariadb pid-file = /run/mysqld/mysqld.pid basedir = /usr datadir = /var/lib/mysql tmpdir = /tmp # Broken reverse DNS slows down connections considerably and name resolve is # safe to skip if there are no "host by domain name" access grants #skip-name-resolve # Instead of skip-networking the default is now to listen only on # localhost which is more compatible and is not less secure. #預設僅監聽 localhost,如需遠端連線請自行調整 bind-address = 127.0.0.1 # # * Fine Tuning # #MyISAM index buffer,多數 InnoDB 環境影響有限 key_buffer_size = 32M #大型資料庫匯入,需求可提高 max_allowed_packet = 1G table_open_cache = 192 sort_buffer_size = 768K net_buffer_length = 8K read_buffer_size = 768K read_rnd_buffer_size = 512K myisam_sort_buffer_size = 8M thread_cache_size = 96 tmp_table_size = 128M max_heap_table_size = 128M explicit_defaults_for_timestamp = true #skip-networking max_connections = 100 max_connect_errors = 100 open_files_limit = 65535 #若不使用主從複製或 PITR,可考慮關閉 binlog log-bin=mysql-bin binlog_format=mixed server-id = 1 expire_logs_days = 10 default_storage_engine = InnoDB # # * Logging and Replication # expire_logs_days = 10 # # * Character sets # # MariaDB default is now utf8 4-byte character set. # No Debian specific default is required. # # * InnoDB # innodb_file_per_table = 1 innodb_buffer_pool_size = 2G #若調整此值導致無法啟動,請確認 ib_logfile 已重新建立 innodb_log_file_size = 256M innodb_log_buffer_size = 16M innodb_flush_log_at_trx_commit = 1 innodb_lock_wait_timeout = 50 [mysqldump] quick #大型資料庫匯入,需求可提高 max_allowed_packet = 1G [mysql] no-auto-rehash [myisamchk] key_buffer_size = 20M sort_buffer_size = 20M read_buffer = 2M write_buffer = 2M [mysqlhotcopy] interactive-timeout # InnoDB is enabled by default with a 10MB datafile in /var/lib/mysql/. # Read the manual for more InnoDB related options. There are many! # Most important is to give InnoDB 80 % of the system RAM for buffer use: # https://mariadb.com/kb/en/innodb-system-variables/#innodb_buffer_pool_size #innodb_buffer_pool_size = 8G # this is only for embedded server [embedded] # This group is only read by MariaDB servers, not by MySQL. # If you use the same .cnf file for MySQL and MariaDB, # you can put MariaDB-only options here [mariadbd] # This group is only read by MariaDB-11.8 servers. # If you use the same .cnf file for MariaDB of different versions, # use this group for options that older servers don't understand [mariadb-11.8] ESC儲存並離開 :wq ------------------------------------- 重啟 & 重開機 ------------------------------------- 重啟 systemctl restart mariadb 開機啟動mariadb systemctl enable mariadb 啟動mariadb systemctl start mariadb 瀏覽狀態 systemctl status mariadb 重開機 reboot 重開機,確認MariaDB可以自動啟動,顯示 Active: active (running) systemctl status mariadb
-
安裝PHP 8.4與配置
----------------------------- 修改為安裝sury.org的PHP源 ----------------------------- apt install wget wget -O /usr/share/keyrings/php.gpg https://packages.sury.org/php/apt.gpg echo "deb [signed-by=/usr/share/keyrings/php.gpg] https://packages.sury.org/php/ $(lsb_release -sc) main" > /etc/apt/sources.list.d/php.list 更新源 apt update apt install curl vim gnupg dpkg apt-transport-https lsb-release ca-certificates -y apt install php-pear -y apt install php8.4-{fpm,cli,mysql,curl,gd,mbstring,xml,zip,imap,soap,gmp,bcmath,redis} -y 瀏覽pear版本 pear version 可看到 PEAR Version: 1.10.16 可看到 PHP Version: 8.4.16 可看到 Zend Engine Version: 4.4.16 可看到 Running on: Linux 000 6.12.63+deb13-cloud-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.12.63-1 (2025-12-30) x86_64 如果要安裝其他元件,可以搜尋看看有無對應的套件 apt-cache search php8.4* | grep php 修改 php.ini 防跨目錄/路徑攻擊 sed -i 's@^;*cgi.fix_pathinfo=.*@cgi.fix_pathinfo=0@' /etc/php/8.4/fpm/php.ini 檢查 grep cgi.fix_pathinfo /etc/php/8.4/fpm/php.ini 你應該看到 cgi.fix_pathinfo=0 設置系統預設的PHP版本 update-alternatives --list php update-alternatives --set php /usr/bin/php8.4 update-alternatives --config php 重啟PHP systemctl restart php8.4-fpm --------------------------------------- 確認有安裝exif、gmp、imagick、redis --------------------------------------- apt install php8.4-exif -y apt install imagemagick -y apt install php8.4-imagick -y 重啟PHP systemctl restart php8.4-fpm 已安裝的PHP擴展,確定已安裝了 exif、gmp、imagick、redis /bin/php8.4 -m ------------------ 修改php.ini ------------------ 本教學只修改 PHP-FPM 的 php.ini,CLI 使用的是 /etc/php/8.4/cli/php.ini vi /etc/php/8.4/fpm/php.ini 使用Xshell 8軟體上面的選項,編輯 -> 尋找 -> 尋找目標,將能快速找到以下這些要修改的地方 停用危險函數 搜尋 disable_functions = 修改为,請注意:部分套件(如 Composer、queue、worker)可能需要 exec / proc_open,請依實際需求調整 disable_functions = passthru,exec,system,chroot,chgrp,chown,shell_exec,proc_open,proc_get_status,popen,ini_alter,ini_restore,dl,readlink,symlink,popepassthru,stream_socket_server,pcntl_exec 搜尋以下這些,並修改它們的值 max_execution_time = 300 max_input_time = 180 memory_limit = 512M 顯示PHP程式錯誤,正式運作的論壇通常是 Off 關閉狀態 display_errors = Off post_max_size = 100M upload_max_filesize = 100M max_file_uploads = 100 default_socket_timeout = 180 ESC儲存並離開 :wq 重啟PHP systemctl restart php8.4-fpm 瀏覽PHP的版本,確定你是安裝PHP 8.4 php -v 開機啟動PHP8.4 systemctl enable php8.4-fpm 啟動PHP8.4 systemctl start php8.4-fpm 瀏覽狀態 systemctl status php8.4-fpm 重開機 reboot 重開機後,確認PHP有自動啟動 systemctl status php8.4-fpm
-
使用SFTP代替FTP
----------------------- 使用SFTP代替FTP ----------------------- Windows常見的FTP客戶端Filezilla、Flashfxp、Winscp、cuteftp等都是支援sftp,只需要在登入時選擇sftp協定,輸入SSH的帳號密碼 我慣用 FileZilla Client http://filezilla-project.org/
-
調整swap
-------------- 調整swap -------------- 安裝LNMP前,先調整swap為 x GB 瀏覽RAM記憶體 free -h Swap: 0B 如果看到total為0,表示沒設置swap 已設定swap的情況,例如 Swap: 6.2Gi 表示swap設置為6GB 建立一個資料夾用於存放swap mkdir /var/swapfile 調整swap為 4GB (視情況而定) dd if=/dev/zero of=/var/swapfile/file.swap bs=1024k count=4096 建立一個swap檔案 mkswap /var/swapfile/file.swap 修改swap資料夾權限 chmod 0600 /var/swapfile chmod 0600 /var/swapfile/file.swap 到fstab檔案中新增開機自動掛載設定 vi /etc/fstab 就能開機啟用這個swap,在底部加入 /var/swapfile/file.swap swap swap defaults 0 0 ESC儲存並離開 :wq 啟用 swapon /var/swapfile/file.swap 重開機 reboot 再次確認swap是否已調整為 4GB free -h
-
SSH連線工具:Xshell
Xshell是一款專為Windows平台設計的SSH (Secure Shell) 用戶端軟體 它提供高穩定性、多分頁管理、金鑰登入、自動指令執行等進階功能,是遠端管理Linux伺服器、VPS、雲端主機與網路設備的常用工具 對於個人與教育用途,Xshell提供免費版本,非常適合學生、研究人員與自架伺服器使用者 官方網站與下載 https://www.xshell.com/zh/Xshell/ https://cdn.netsarang.net/v8/Xshell-latest-p 適用情境 遠端管理 Linux / Unix 伺服器 VPS / 雲主機 維護 學術教學與終端機指令實作 連接 VMware / VirtualBox 虛擬機 網路設備 (如交換器、防火牆) 管理 注意事項 免費版僅供個人與教育用途,商業使用需購買授權 建議從官方網站下載,以確保軟體安全性
-
步驟
----------------------------------------- 在手搓LNMP之前,需要先完成Linux配置 Debian 13安裝與配置 ----------------------------------------- 域名解析 調整swap 使用SFTP代替FTP 安裝PHP 8.4與配置 安裝資料庫MariaDB 11.8與配置,資料庫最佳化 2 - 3G RAM 安裝資料庫MariaDB 11.8與配置,資料庫最佳化 4 - 8G RAM 安裝第三方Nginx 1.29、更改主機名 安裝phpMyAdmin、修改為 888 port、使用IP當phpMyAdmin的網址來管理資料庫 phpMyAdmin建立新的資料庫用戶名、資料庫用戶密碼、資料庫名 安裝acme.sh + Google Public CA 自動續簽SSL憑證 修改 域名.com.conf、IPS論壇偽靜態 設置Cron 413 Request Entity Too Large 安裝 Elasticsearch 或 OpenSearch 任選其一即可 安裝 Elasticsearch 8.17 強化中文搜尋 (Invision Community 5.0.5 開始採用新版本) 安裝 OpenSearch 2.5.0 強化中文搜尋 (論壇目前 不支援 此版本) 選擇「安裝新的論壇」或者是「恢復現有的論壇」 上傳Invision Community論壇程式、解壓縮、設置權限 安裝新的 Invision Community 5.0 論壇 「恢復現有的論壇」,適用於更換伺服器、環境遷移 (例如 舊主機 → 新主機),或將論壇還原至指定日期的備份檔 恢復現有的論壇 DB資料庫 與 Web網站檔案 Cron執行論壇任務、自動備份DB資料庫、自動備份Web網站檔案 Invision Community論壇啟用 Elasticsearch / OpenSearch 強化中文搜尋 Invision Community論壇啟用偽靜態與自訂友善網址 Invision Community論壇啟用 Redis 加速 Invision Community 5.0.0 ~ 5.0.x 之間的論壇版本升級 Invision Community 5.0 論壇升級後,記得更新中文語言包 每日自動備份、僅保留最近3天備份檔、異地備份 額外補充 使用 rm 指令刪除整個論壇目錄 (請務必謹慎操作)
-
Debian 13啟用BBR加速
------------------------- Debian 13啟用BBR加速 ------------------------- 什麼是BBR? BBR (Bottleneck Bandwidth and Round-trip propagation time) 是由Google開發的TCP擁塞控制演算法。相較於傳統的CUBIC演算法,BBR具有以下優勢: 高傳輸速率:在封包遺失或高延遲環境下仍能保持良好表現 低延遲體驗:減少封包在網路佇列中的等待時間 頻寬最大化:更精準地探測可用頻寬,提升資源利用率 適用場景包括: 跨國或跨洲的遠距離連線 高延遲網路 (如衛星連線) VPS伺服器最佳化 大量資料傳輸的應用 雖然Debian 13的核心版本 (如 6.12+) 已原生支援BBR,但我們仍需確認環境 uname -r 返回的内核 6.12.63+deb13-cloud-amd64 注意:核心版本需高於 4.9 才能支援BBR。Debian 13預設核心版本通常為 6.1x,完全符合需求 建立BBR設定檔 (需具備root權限) 建議在 /etc/sysctl.d/ 目錄下建立獨立設定檔,這比直接修改系統主文件更易於維護 提示:數字 99 代表最高優先級,確保設定不會被其他設定覆蓋 vi /etc/sysctl.d/99-bbr.conf 貼上以下內容 net.core.default_qdisc = fq net.ipv4.tcp_congestion_control = bbr net.core.rmem_max = 67108864 net.core.wmem_max = 67108864 net.ipv4.tcp_rmem = 4096 87380 67108864 net.ipv4.tcp_wmem = 4096 65536 67108864 ESC儲存並離開 :wq 重開機 reboot ----------------------- 驗證BBR是否成功啟用 ----------------------- 確認擁塞控制演算法 sysctl net.ipv4.tcp_congestion_control 預期輸出 net.ipv4.tcp_congestion_control = bbr 查看系統支援的演算法清單 sysctl net.ipv4.tcp_available_congestion_control 輸出中應包含 bbr 確認佇列規則 sysctl net.core.default_qdisc 預期輸出 net.core.default_qdisc = fq 檢查即時連線 若想看目前TCP連線是否真正套用BBR,可觀察即時封包 ss -ti | grep bbr 可能結果: 有輸出:顯示正在使用BBR的連線資訊,表示BBR正常運作 無輸出:表示目前沒有活動連線,或連線數較少。這是正常的,不代表設定失敗 測試建議:可以產生一些網路流量 (如下載檔案) 後再次執行此指令
-
Debian 13將預設防火牆改為iptables並設定開機自動啟動
Debian 13將預設防火牆改為iptables並設定開機自動啟動 ------ 前言 ------ 本教學適用Debian系統,將預設的 nftables/ufw 防火牆替换為 iptables,並透過 rc.local 開機自動載入防火牆規則 注意:操作需root權限,調整防火牆規則可能導致SSH斷線。執行前請確認你有VNC或實體終端機存取權限 ---------------------- 安裝iptables防火牆 ---------------------- 在安裝新工具前,必須先移除可能產生衝突的現有防火牆服務 更新套件清單 apt update 安裝iptables apt install -y iptables 確認安裝版本 iptables --version 應顯示為 iptables v1.8.x (nf_tables) 類似的訊息 移除nftables防火牆 (如果已安裝) apt remove --purge nftables 移除ufw防火牆 (如果已安裝) apt remove --purge ufw ------------------- 確認iptables狀態 ------------------- 查看目前規則 (預設應為空或僅有基本規則) iptables -L -v ------------------------ 建立防火牆規則腳本 ------------------------ 建立一個結構化的腳本,以便未來維護規則 建立腳本目錄 mkdir -p /usr/local/bin 建立防火牆腳本 vi /usr/local/bin/firewall.sh 請將提供的防火牆腳本 firewall.sh 內容貼上 接下來,編輯腳本以符合你的需求 # 設定禁止連線的IP,可使用空白分隔多個IP,也可以使用網段的寫法 BADIPS="198.108.0.0/16 141.212.0.0/16" # 設定不可能出現的私有IP,請依照您的環境自行刪減網段 # 若您的IP為 192.168.x.x ,請刪除 192.168.0.0/16 IMPOSSIBLE_IPS="192.168.0.0/16" # 允許對內連線的 TCP 通訊埠 # 格式:埠號 埠號,來源IP # 注意:若前後設定有重疊,則系統將以後設定者為準 IN_TCP_PORTALLOWED="22,你的IP 888,你的IP 80 443" ESC儲存並離開 :wq 設定腳本權限 (權限說明:700 表示僅 root 可讀寫執行,提高安全性) chmod 700 /usr/local/bin/firewall.sh ----------------- 測試防火牆腳本 ----------------- 執行腳本 (會進入測試模式,7秒後自動清除規則) /usr/local/bin/firewall.sh 確認規則是否正常載入 iptables -L 若確認規則正確,使用 start 參數永久套用 /usr/local/bin/firewall.sh start --------------------- 設定開機自動啟動 --------------------- Debian近期版本預設不啟用rc.local,需要手動配置 網路找到 rc.local 設定開機自動啟動 https://u.sb/debian-rc-local/ 查看 rc-local 服務設定檔 cat /lib/systemd/system/rc-local.service 檢查服務狀態 systemctl status rc-local 建立 /etc/rc.local 檔案並編輯 vi /etc/rc.local 複製貼上以下內容 #!/bin/sh -e # # rc.local # # This script is executed at the end of each multiuser runlevel. # Make sure that the script will "exit 0" on success or any other # value on error. # # In order to enable or disable this script just change the execution # bits. # # By default this script does nothing. # 啟動自訂防火牆規則 /usr/local/bin/firewall.sh start exit 0 ESC儲存並離開 :wq 設定rc.local權限 chmod 700 /etc/rc.local 啟用 rc-local 服務 systemctl enable --now rc-local ----------- 驗證設定 ----------- 重開機 reboot 開機後確認防火牆規則,若成功執行,要看到你指定的IP有出現 iptables -L 確認 rc-local 服務狀態 systemctl status rc-local.service 應顯示 active (exited)
-
如何將Debian 13更新至最新狀態
------------------------------------ 如何將Debian 13更新至最新狀態 ------------------------------------ 在執行系統更新前請確認: 已備份重要資料 (建議快照或完整備份) 若為遠端主機,請確認有備用登入方式 (例如主機商控制台) 生產環境建議先於測試機驗證更新 確認目前系統版本 uname -a ; lsb_release -a 預期輸出範例: Linux hostname 6.12.63+deb13-cloud-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.12.63-1 (2025-12-30) x86_64 GNU/Linux No LSB modules are available. Distributor ID:Debian Description:Debian GNU/Linux 13 (trixie) Release:13 Codename:trixie 檢查套件來源 cat /etc/apt/sources.list 官方標準來源應包含: deb http://deb.debian.org/debian trixie main contrib non-free non-free-firmware deb http://security.debian.org/debian-security trixie-security main contrib non-free non-free-firmware 若來源錯誤,更新可能失敗或安裝到非官方套件 更新套件清單 apt update 檢視可升級套件 apt list --upgradable 升級套件 基本升級 apt upgrade -y 特性: 不移除舊套件 不安裝新依賴 風險最低 完整升級 (重大更新時使用) apt full-upgrade 差異說明: upgrade 僅更新既有套件 full-upgrade 允許安裝新依賴與移除舊套件 建議情境: 核心更新 發行版維護期更新 套件衝突修正 再次檢查是否還有可升級的套件,若顯示 Listing ... Done 代表已無可更新套件 apt list --upgradable 清理不需要的套件快取,移除已下載的舊版本套件檔案 apt autoclean 移除不再需要的套件 apt autoremove 如果升級了核心或重要系統套件,建議重新啟動 reboot 驗證更新結果,重開機後,再次檢查版本與核心 uname -a ; lsb_release -a ---------- 補充 ---------- 安裝自動更新工具 apt install unattended-upgrades dpkg-reconfigure unattended-upgrades 效果:自動安裝安全修補、降低漏洞風險、適合伺服器環境 檢查更新日誌 cat /var/log/apt/history.log 可查看:更新時間、更新套件、操作紀錄
-
DD完成後,SSH無法連線,可能需要noVNC登入並手動配置網路卡
DD完成後,SSH無法連線,最常見的原因是需要重新配置網路卡 請透過noVNC遠端控制台登入 帳號為 root,密碼為剛才DD時你的自訂密碼 進行以下設定 ---------------------------------------------- 重新配置 VPS/雲主機 的 網路卡名稱 與 IP設定 ---------------------------------------------- 在上一個步驟中 已提前記下 網路卡名稱 與 IP設定,例如: 網路卡名稱:ens5 IP位址 與 子網路遮罩:10.2.83.41/16 Gateway (閘道):10.2.255.253 DNS:8.8.8.8 DNS:8.8.4.4 編輯網路設定檔 (將 ens5 替換為你的網路卡名稱) vi /etc/systemd/network/10-ens5.network 貼上以下內容 (請根據你之前記下的實際資訊) 若主機商同時提供 內網IP/外網IP,優先設定內網IP #如果需要設定外網IP,可以加入第二個Address # Address=你的外網IP/子網路遮罩 [Match] Name=ens5 [Network] Address=10.2.83.41/16 Gateway=10.2.255.253 DNS=8.8.8.8 DNS=8.8.4.4 ESC儲存並離開 :wq ----------------------- 啟用並重啟網路服務 ----------------------- 啟用開機自動啟動 systemctl enable systemd-networkd 重新啟動網路服務 systemctl restart systemd-networkd 重新載入網路設定 networkctl reload ----------- 測試連線 ----------- 檢查IP是否正確設定 (將 ens5 替換為你的網路卡名稱) ip addr show ens5 測試外網連線 ping -c 4 8.8.8.8 若以上測試都通過,表示網路設定正常 重啟後應該可以正常透過SSH連線 reboot ----------------------- 安裝完成後建議事項 ----------------------- 驗證系統版本 cat /etc/os-release 立即修改root密碼 passwd 設定防火牆 (ufw 或 iptables),僅開放必要Port 若日後更換IP導致被防火牆鎖住,可透過noVNC遠端控制台修改防火牆規則
-
透過DD方式重新安裝Debian 13 (適用VPS/雲主機)
---------------- 前言與風險警告 ---------------- 本教學介紹如何使用 DD (Disk Deployment 磁碟部署) 方式,在VPS或雲主機上快速部署全新的Debian 13 警告: DD安裝會直接將映像檔寫入整顆系統碟,完全覆蓋原有作業系統 僅適用於 VPS/雲主機 環境,不適用於實體主機 不建議在正式營運中的主機直接操作 務必事先備份所有重要資料 請確認主機商提供 noVNC 遠端控制台,以便在SSH無法連線時,進行系統檢查、網路修復或修改防火牆規則 -------------------------------- 記下 網路卡名稱 與 IP設定 -------------------------------- 在DD前的準備 (非常重要) 請先記下 VPS/雲主機 的 網路卡名稱 與 IP設定 以便DD後,若發現SSH無法連線時,可以重新配置網路卡 SSH登入,找到狀態為 routable 的網路卡名稱 networkctl list 範例:這裡的 ens5 就是網路卡名稱 IDX LINK TYPE OPERATIONAL SETUP 1 lo loopback carrier unmanaged 2 ens5 ether routable configured 查看指定網路卡的IP (將ens5換成你的網路卡名稱) ip addr show ens5 查看網路卡狀態 (將ens5換成你的網路卡名稱) networkctl status ens5 查看DNS設定 cat /etc/resolv.conf 請務必記下以下資訊,例如: 網路卡名稱:ens5 IP位址 與 子網路遮罩:10.2.83.41/16 Gateway (閘道):10.2.255.253 DNS:8.8.8.8 DNS:8.8.4.4 ------------------------ 開始DD安裝Debian 13 ------------------------ SSH登入,更新系統並安裝必要工具 apt update -y apt install wget -y ------------------ 下載DD安裝腳本 ------------------ 本教學使用 第三方腳本 (非Debian官方):https://github.com/leitbogioro/Tools 下載DD腳本 wget --no-check-certificate https://raw.githubusercontent.com/leitbogioro/Tools/master/Linux_reinstall/InstallNET.sh 設定執行權限 chmod a+x /root/InstallNET.sh ------------------ 執行DD安裝指令 ------------------ 執行DD安裝指令,建議直接加參數,指定安裝debian 13、mirror鏡像源就近選擇 香港 (或者你的VPS所在地)、自訂root密碼 bash InstallNET.sh -debian 13 -mirror "http://ftp.hk.debian.org/debian/" -pwd 輸入你的自訂密碼 當畫面出現以下訊息時:[Finish] Input 'reboot' to continue the subsequential installation. 請依照指示重啟 reboot ------------------ DD安裝過程說明 ------------------ 重啟後,SSH會斷線,這是正常現象 請立即透過noVNC遠端控制台登入 系統將自動進行解壓與安裝 (約 10~30 分鐘) 如圖所示,主機商提供的noVNC遠端控制台 如圖所示,在noVNC控制台 ,可看見DD過程,系統將自動進行解壓與安裝 (約 10~30 分鐘) DD完成後系統會再次重啟,並顯示登入畫面 --------------- SSH登入 --------------- 再次透過SSH連線並登入,帳號為 root,密碼為剛才DD時你的自訂密碼 --------------- SSH無法連線 --------------- 若SSH無法連線,最常見的原因是網路未正確配置,請透過noVNC登入並手動配置網路 接下來在noVNC遠端控制台重新配置網路卡