# OpenWrt 管理指令 **目標設備**:`192.168.42.10`(OpenWrt 24.10.4) **WAN IP**:`125.229.110.50`(PPPoE / HiNet) --- ## 整體架構圖 ### 網路拓撲 ``` Internet (HiNet) │ PPPoE 125.229.110.50 │ ┌────────────────────▼────────────────────┐ │ OpenWrt 24.10.4 │ │ 192.168.42.10 │ │ │ │ ┌─ 服務 ──────────────────────────┐ │ │ │ dnsmasq odhcpd sqm banip │ │ │ │ miniupnpd dropbear uhttpd │ │ │ └─────────────────────────────────┘ │ │ │ │ ┌─ 防火牆 (nftables / fw4) ────────┐ │ │ │ taiwan_ips set(每週一 04:00 更新)│ │ │ └─────────────────────────────────┘ │ │ │ │ ┌─ WireGuard wg0 ──────────────────┐ │ │ │ 10.0.0.1/24 port 51820/UDP │ │ │ └─────────────────────────────────┘ │ └────────────────┬────────────────────────┘ │ br-lan 192.168.42.0/24 │ ┌─────────┬───────────┼───────────┬─────────────┐ ▼ ▼ ▼ ▼ ▼ .100 .101 .115 .117 .124 / .126 Jump Box RustDesk SQL Server SQL Server 反代 / Headscale ``` --- ### 防火牆區域(Firewall Zones) ``` ┌──────────┐ REJECT in ┌──────────┐ ACCEPT in │ wan │ ──────────────▶ │ lan │ ◀──────────── │(pppoe_wan│ REJECT fwd │192.168.42│ ACCEPT fwd │ wan6) │ │ .0/24 │ └──────────┘ └──────────┘ ▲ ACCEPT in ACCEPT fwd ┌──────────┐ │ vpn │ │ (wg0) │ │10.0.0/24 │ └──────────┘ ``` --- ### 對外開放的 Port(WAN → LAN) | WAN Port | 協定 | 目標 | 服務 | Taiwan IP 限制 | |---|---|---|---|:---:| | `22` | TCP | `192.168.42.100:22` | SSH Jump Box | ✅ | | `80` | TCP | `192.168.42.124:80` | Nginx Proxy Manager | — | | `443` | TCP | `192.168.42.124:443` | Nginx Proxy Manager | — | | `3478` | UDP | `192.168.42.126:3478` | Headscale DERP STUN | — | | `3479` | UDP | `192.168.42.127:3479` | NetBird STUN | — | | `7835` | TCP | `192.168.42.100:7835` | Bore Tunnel | ✅ | | `8080` | TCP | `192.168.42.126:8080` | Headscale HTTP API | — | | `9090` | TCP | `192.168.42.126:9090` | Headscale Metrics | — | | `9000–10000` | TCP | `192.168.42.100:9000–10000` | Bore Range | — | | `21115–21119` | TCP/UDP | `192.168.42.101:21115–21119` | RustDesk HBBS/HBBR | — | | `30022` | TCP | `192.168.42.115:22` | SSH → .115 | — | | `50022` | TCP | `192.168.42.117:22` | SSH → .117 | — | | `50443` | TCP | `192.168.42.126:50443` | Headscale gRPC | — | | `51433` | TCP | `192.168.42.115:1433` | SQL Server (.115) | — | | `31433` | TCP | `192.168.42.117:1433` | SQL Server (.117) | — | | `51820` | UDP | router wg0 | WireGuard | — | > **STUN port 說明**:標準 STUN port 為 `3478/udp`,已由 Headscale DERP(`.126`)佔用。NetBird(`.127`)後上線,為避免衝突改用 `3479/udp`(`stunPorts: [3479]`,對應 `/opt/netbird/config.yaml`)。Client 設定的 STUN URI 需指向 `stun::3479`。 --- ### LAN 裝置 | IP | 主機名稱 / 用途 | |---|---| | `192.168.42.10` | OpenWrt 路由器 | | `192.168.42.100` | Jump Box(SSH、Bore)| | `192.168.42.101` | RustDesk Server | | `192.168.42.115` | SQL Server A | | `192.168.42.117` | SQL Server B | | `192.168.42.124` | Nginx Proxy Manager + Gitea(:31337)| | `192.168.42.126` | Headscale | | `192.168.42.127` | NetBird(Management + Signal + STUN/TURN)| | `192.168.42.220` | TimmydeMBP | --- ### WireGuard VPN 拓撲 ``` 外部(任意網路) │ │ UDP 51820 ▼ 192.168.42.10 ←→ wg0: 10.0.0.1/24 │ ├── 10.0.0.2 Workstation └── 10.0.0.3 iPhone 15 Pro Max VPN client 加入後可存取: ├── 192.168.42.0/24 (整個 LAN) └── 10.0.0.0/24 (其他 VPN peer) ``` --- ### Taiwan IP 過濾機制 ``` 外部請求 │ ▼ nftables 檢查 source IP 是否在 taiwan_ips set │ ├── 是 → 允許通過(SSH Jump Box、Bore Tunnel) └── 否 → REJECT ``` - IP 清單來源:`https://www.ipdeny.com/ipblocks/data/countries/tw.zone` - 自動更新:每週一 04:00(`crontab`) - 手動更新:`sh /root/42_10/update_tw_ip.sh` --- ## 系統狀態確認 ```sh # 開機時間與負載 uptime # 記憶體用量 free -m # 磁碟空間 df -h # 近期系統紀錄 logread -l 50 # 即時追蹤紀錄 logread -f ``` --- ## 套件管理 ```sh # 更新套件列表 opkg update # 安裝套件 opkg install # 移除套件 opkg remove # 列出已安裝套件 opkg list-installed # 升級所有套件 opkg list-upgradable | cut -f 1 -d ' ' | xargs -r opkg upgrade ``` --- ## 防火牆(nftables / fw4) ```sh # 列出所有規則 nft list ruleset # 列出特定 table nft list table inet fw4 # 重新載入防火牆設定 fw4 restart # 備份目前規則 nft list ruleset > /etc/nftables.backup # 清除特定集合 nft flush set inet fw4 taiwan_ips # 查看 Taiwan IP 集合(元素數量) nft list set inet fw4 taiwan_ips | grep -c elements ``` --- ## 網路診斷 ```sh # 介面清單與狀態 ip -br addr # 路由表 ip route show # 測試對外網路 ping -c 4 8.8.8.8 # DNS 查詢 nslookup google.com # 查看監聽 Port netstat -tuln # 測試指定 Port 是否可到達 nc -zv -w 5 ``` --- ## 日誌 ```sh # 查看系統紀錄 logread # 即時監控 logread -f # 最近 50 筆 logread -l 50 # 過濾防火牆相關 logread | grep -i firewall ``` --- ## 服務管理 ```sh # 啟動 / 停止 / 重啟 /etc/init.d/ start /etc/init.d/ stop /etc/init.d/ restart # 查看狀態 /etc/init.d/ status # 開機自動啟動 / 停用 /etc/init.d/ enable /etc/init.d/ disable ``` --- ## 設定備份與還原 ```sh # 備份整個系統設定 sysupgrade -b /tmp/backup-$(date +%Y%m%d).tar.gz # 還原設定 sysupgrade -r /tmp/backup-YYYYMMDD.tar.gz # 備份防火牆設定 cp /etc/config/firewall /etc/config/firewall.bak # 編輯設定檔 vi /etc/config/firewall ``` --- ## Taiwan IP 集合管理 ```sh # 重新抓取並更新 Taiwan IP 清單 sh /root/42_10/update_tw_ip.sh # 確認目前集合內容 nft list set inet fw4 taiwan_ips # 手動補充單一 IP(如 VPS 未被涵蓋) nft add element inet fw4 taiwan_ips { } ``` **資料來源**:`https://www.ipdeny.com/ipblocks/data/countries/tw.zone` 建議搭配 cron 定期執行 `update_tw_ip.sh`,例如每月一次: ```sh # crontab -e 0 3 1 * * sh /root/42_10/update_tw_ip.sh ``` --- ## 防火牆規則驗證 ```sh # 本機執行:SSH 進路由器並格式化輸出規則 sh /root/42_10/show_nft_rules.sh # 驗證台灣 IP 通行、非台灣 IP 攔截 sh /root/42_10/test_connection.sh ``` `test_connection.sh` 會: 1. 查詢目前出口 IP 所在地(透過 `https://ip.lotimmy.com/json`) 2. 對 `125.229.110.50` 的指定 Port(`51433`, `31433`)發起測試 3. 判斷結果是否符合預期(台灣 IP 應通過,非台灣 IP 應被攔截) --- ## 轉發規則調整 若需移除已失效的 Port 轉發(如原本指向不存在主機),執行: ```sh sh /root/42_10/remove_mysql_forward.sh ``` 手動移除流程: ```sh # 找出目標規則 ssh root@192.168.42.10 "uci show firewall | grep " # 刪除並提交 ssh root@192.168.42.10 "uci delete firewall. && uci commit firewall" # 重載防火牆 ssh root@192.168.42.10 "fw4 restart" # 確認規則已移除 ssh root@192.168.42.10 "nft list chain inet fw4 dstnat_wan | grep " ``` --- ## WireGuard VPN **架構**:路由器作為 server,外部裝置以 client 身份連入,取得對 LAN(`192.168.42.0/24`)的存取權。 ``` 外部裝置 │ UDP 51820 ▼ 192.168.42.10 wg0: 10.0.0.1/24 ← server ├── 10.0.0.2 Workstation └── 10.0.0.3 iPhone 15 Pro Max ``` ### 狀態查看 ```sh # 查看所有 peer 連線狀況(last handshake、傳輸量) wg show # 只看介面摘要 wg show wg0 ``` ### 新增 Peer ```sh # 1. 在路由器上產生新的 keypair wg genkey | tee /tmp/peer_private.key | wg pubkey > /tmp/peer_public.key cat /tmp/peer_private.key cat /tmp/peer_public.key # 2. 加入 peer 設定(以 10.0.0.4 為例) uci add network wireguard_wg0 uci set network.@wireguard_wg0[-1].public_key='' uci set network.@wireguard_wg0[-1].private_key='' uci set network.@wireguard_wg0[-1].persistent_keepalive='25' uci add_list network.@wireguard_wg0[-1].allowed_ips='10.0.0.4/32' uci add_list network.@wireguard_wg0[-1].allowed_ips='192.168.42.0/24' uci set network.@wireguard_wg0[-1].dns='1.1.1.1' uci set network.@wireguard_wg0[-1].description='<裝置名稱>' uci commit network service network restart ``` ### 移除 Peer ```sh # 找出目標 peer 的索引 uci show network | grep -n '' # 刪除(假設是 @wireguard_wg0[2]) uci delete network.@wireguard_wg0[2] uci commit network service network restart ``` ### Client 設定檔範本 將以下內容存為 `.conf` 檔匯入裝置(WireGuard app 或 `wg-quick`): ```ini [Interface] PrivateKey = Address = 10.0.0.x/24 DNS = 1.1.1.1 [Peer] PublicKey = s7fZj/dlgcjc1q4Pd1EaeoCOgq8EStyS30h30hOL1RI= Endpoint = 125.229.110.50:51820 AllowedIPs = 192.168.42.0/24, 10.0.0.0/24 PersistentKeepalive = 25 ``` > `AllowedIPs` 只填 `192.168.42.0/24, 10.0.0.0/24` 表示 split tunnel(只有內網流量走 VPN)。 > 若要讓所有流量都走 VPN,改為 `0.0.0.0/0, ::/0`。 ### 現有 Peer 一覽 | 描述 | VPN IP | Public Key(前 8 碼) | |---|---|---| | Workstation | `10.0.0.2` | `daM1BFUS` | | iPhone 15 Pro Max | `10.0.0.3` | `PZVrUwd1` | ### 防火牆規則說明 | 規則 | 說明 | |---|---| | WAN UDP 51820 → ACCEPT | 允許外部 client 建立 VPN tunnel | | vpn → lan ACCEPT + masq | VPN client 可存取內網,並做 NAT | 若防火牆規則遺失,手動補回: ```sh # 允許 WireGuard 進入 uci add firewall rule uci set firewall.@rule[-1].name='Allow-WireGuard' uci set firewall.@rule[-1].src='wan' uci set firewall.@rule[-1].dest_port='51820' uci set firewall.@rule[-1].proto='udp' uci set firewall.@rule[-1].target='ACCEPT' uci commit firewall fw4 restart ``` --- ## Tailscale(Headscale client) 路由器以 Tailscale client 身份加入自架的 Headscale tailnet(control server:`https://headscale.lotimmy.com`,user `mainnet`)。節點名 `openwrt`,tailnet IP `100.64.0.9`。 > ⚠️ **邊界路由器絕對不可用 `--accept-routes`。** `.10` 是站點 gateway,tailnet 上已有節點宣告 `192.168.42.0/24`;一旦 `--accept-routes`,`.10` 會把這條路由裝進 `tailscale0`,**黑洞掉自己的 LAN、DNAT 轉送與站內 Headscale 控制面 → 全站斷線**,且重開機不會自愈(prefs 會保留)。2026-06 曾因此造成 sev1。 ### 安裝與連線 ```sh opkg update && opkg install tailscale # 約 9.6MB 下載,overlay 佔用 ~30MB /etc/init.d/tailscale enable /etc/init.d/tailscale start # 連線(必須 --accept-routes=false) tailscale up --login-server https://headscale.lotimmy.com --accept-routes=false ``` 正常時 `tailscale status` 會出現 `Some peers are advertising routes but --accept-routes is false`,且 `ip route get 192.168.42.x` 應走 `dev br-lan`(不是 tailscale)。 > Headscale control 走 `headscale.lotimmy.com`(→ WAN `125.229.110.50`)會髮夾彎回站內 NPM,憑證 CN 不符而連不上。已在 `.10` 的 `/etc/hosts` 加 split-DNS 覆寫,直接走內網 NPM: > ``` > 192.168.42.124 headscale.lotimmy.com > ``` ### 出事時的救援(in-band 全斷) 若 `.10` 路由被劫持、LAN/tailnet/WAN 全進不去,改走 **WireGuard**(`wg0: 10.0.0.1` 與被黑洞的 `192.168.42.0/24` 無關): ```sh # 在任一 WG peer(如 iPhone 10.0.0.3) ssh root@10.0.0.1 tailscale down # 立即撤掉劫持路由,全站恢復,免重開機 ``` 備援:OpenWrt failsafe 模式(開機狂按 reset)→ 網路線直插、靜態 `192.168.1.x` → `ssh root@192.168.1.1` → `/etc/init.d/tailscale disable`。 ### 從 tailnet 管理 `.10`(選用) 目前 `tailscale0` 未納入任何 fw4 zone,所以 **tailnet → 路由器 SSH 會被 reject**(節點仍可被 `tailscale ping`)。若需從 tailnet 直接管理,將 `tailscale0` 加入 `lan` zone 或新增對應 input 規則。