Tôi dùng netifd để tách quyết định định tuyến thay vì nhồi nhiều default route vào một bảng. Bản hướng dẫn chính thức này bao phủ cả IPv4 và IPv6, vì vậy tôi giữ lại toàn bộ các tình huống mẫu thay vì chỉ chép một cấu hình VPN đơn giản.1
Mục tiêu và giới hạn
PBR là cách chọn đường đi dựa trên chính sách của quản trị viên. Với pbr_netifd, mỗi interface được gán một routing table riêng rồi các rule có priority cụ thể sẽ quyết định traffic đi vào table nào. Cách này phù hợp với interface, subnet, địa chỉ IP và port; nếu cần match theo domain thì nên xem PBR app. mwan3 lại dành cho load-balancing hoặc failover nhiều WAN, không phải thay thế trực tiếp cho từng rule bên dưới.1
Trước khi làm, tôi cần có interface lan, vpn, wan hoặc wan6 đã hoạt động; có quyền SSH; biết rõ tuyến tới endpoint VPN; và có một bản sao /etc/config/network cùng /etc/config/firewall. Mỗi đoạn dưới đây đều kết thúc bằng commit và restart, nên nên áp dụng từng mẫu một, kiểm tra rồi mới chuyển sang mẫu tiếp theo.
Nguyên tắc
Gán mỗi interface vào routing table riêng; để netifd tự tạo các route nền tảng.
Giữ default route trên từng upstream interface, nhưng không đặt các route tĩnh giống nhau vào nhiều table.
Đưa tunnel endpoint và mạng nội bộ vào các rule cụ thể trước khi đưa default route vào rule tổng quát.
Priority khoảng 30000 thường đứng trước main table; khoảng 40000–80000 đứng sau main table. Hãy kiểm tra ip rule thực tế sau khi reload.
Nếu dùng IPv6, hãy cân nhắc NAT/NPT và source filter theo đúng topology; đừng coi cấu hình IPv4 là đủ để ngăn rò rỉ IPv6.1
Hướng dẫn
Tôi giữ nguyên cú pháp UCI của nguồn. Các tên lan, vpn, dmz, wan, wan6, wgclient và các routing table ID chỉ là các tên mà mẫu nguồn yêu cầu; hãy đổi chúng theo cấu hình thật của router, không đổi nửa chừng giữa các đoạn.
Route LAN vào VPN và DMZ vào WAN
Mẫu đầu tiên đặt lan vào table 1, vpn vào table 2, dmz vào table 3, rồi đưa traffic vào từ LAN tới lookup 2 với priority 30000. Default route của DMZ vẫn nằm trong table WAN theo setup đã có.1
1
2
3
4
5
6
7
8
9
10
11
12
13
for IPV in 46douci set network.lan.ip${IPV}table="1"uci set network.vpn.ip${IPV}table="2"uci set network.dmz.ip${IPV}table="3"uci -q delete network.lan_vpn${IPV%4}uci set network.lan_vpn${IPV%4}="rule${IPV%4}"uci set network.lan_vpn${IPV%4}.in="lan"uci set network.lan_vpn${IPV%4}.lookup="2"uci set network.lan_vpn${IPV%4}.priority="30000"doneuci commit network
service network restart
Route LAN của VPN server qua VPN client
Mẫu này giả định WireGuard client đã có peer. Hai dòng allowed_ips để peer nhận default route IPv4 và IPv6, sau đó LAN được đưa vào table VPN.1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
uci add_list network.wgclient.allowed_ips="0.0.0.0/0"uci add_list network.wgclient.allowed_ips="::/0"for IPV in 46douci set network.lan.ip${IPV}table="1"uci set network.vpn.ip${IPV}table="2"uci -q delete network.lan_vpn${IPV%4}uci set network.lan_vpn${IPV%4}="rule${IPV%4}"uci set network.lan_vpn${IPV%4}.in="lan"uci set network.lan_vpn${IPV%4}.lookup="2"uci set network.lan_vpn${IPV%4}.priority="30000"doneuci commit network
service network restart
Route LAN vào VPN, rớt VPN thì quay về WAN
Ở đây table 2 được gán cho wan/wan6 và priority 40000, nên có thể dùng WAN làm đường dự phòng sau khi rule VPN không còn áp dụng. Tôi vẫn phải kiểm tra trạng thái tunnel và bảng ip rule thay vì mặc định rằng failover đã hoạt động.1
1
2
3
4
5
6
7
8
9
10
11
12
for IPV in 46douci set network.lan.ip${IPV}table="1"uci set network.wan${IPV%4}.ip${IPV}table="2"uci -q delete network.lan_wan${IPV%4}uci set network.lan_wan${IPV%4}="rule${IPV%4}"uci set network.lan_wan${IPV%4}.in="lan"uci set network.lan_wan${IPV%4}.lookup="2"uci set network.lan_wan${IPV%4}.priority="40000"doneuci commit network
service network restart
Route LAN vào VPN theo IP set
Nguồn tạo ipset chứa các mạng của WAN, đánh dấu traffic LAN không khớp các mạng đó bằng 0x1, rồi lookup vào table VPN. Đây là nhánh dùng khi cần giữ một số đích ngoài VPN.1
for IPV in 46douci -q delete firewall.wan_set${IPV%4}uci set firewall.wan_set${IPV%4}="ipset"uci set firewall.wan_set${IPV%4}.name="wan${IPV%4}"uci set firewall.wan_set${IPV%4}.family="ipv${IPV}"uci set firewall.wan_set${IPV%4}.match="net"uci -q delete firewall.lan_mark${IPV%4}uci set firewall.lan_mark${IPV%4}="rule"uci set firewall.lan_mark${IPV%4}.name="Mark-LAN-VPN"uci set firewall.lan_mark${IPV%4}.src="lan"uci set firewall.lan_mark${IPV%4}.dest="*"uci set firewall.lan_mark${IPV%4}.ipset="!wan${IPV%4} dest"uci set firewall.lan_mark${IPV%4}.proto="all"uci set firewall.lan_mark${IPV%4}.family="ipv${IPV}"uci set firewall.lan_mark${IPV%4}.set_mark="0x1"uci set firewall.lan_mark${IPV%4}.target="MARK"uci set network.lan.ip${IPV}table="1"uci set network.vpn.ip${IPV}table="2"uci -q delete network.lan_vpn${IPV%4}uci set network.lan_vpn${IPV%4}="rule${IPV%4}"uci set network.lan_vpn${IPV%4}.in="lan"uci set network.lan_vpn${IPV%4}.mark="1"uci set network.lan_vpn${IPV%4}.lookup="2"uci set network.lan_vpn${IPV%4}.priority="30000"doneuci commit firewall
uci commit network
service firewall restart
service network restart
Route LAN vào VPN nhưng giữ port WAN forwarding
Mẫu này đánh dấu traffic HTTPS của một máy LAN theo MAC 00:11:22:33:44:55 và port 443, sau đó đẩy phần đã đánh dấu vào table WAN. MAC và port trong nguồn là ví dụ kỹ thuật; tôi phải thay bằng máy chủ thật, đồng thời kiểm tra rule forward/redirect riêng của firewall.1
uci -q delete firewall.lan_web
uci set firewall.lan_web="rule"uci set firewall.lan_web.name="Mark-HTTPS"uci set firewall.lan_web.src="lan"uci set firewall.lan_web.src_mac="00:11:22:33:44:55"uci set firewall.lan_web.src_port="443"uci set firewall.lan_web.dest="*"uci set firewall.lan_web.proto="tcp"uci set firewall.lan_web.set_mark="0x1"uci set firewall.lan_web.target="MARK"for IPV in 46douci set network.lan.ip${IPV}table="1"uci set network.wan${IPV%4}.ip${IPV}table="2"uci -q delete network.lan_web${IPV%4}uci set network.lan_web${IPV%4}="rule${IPV%4}"uci set network.lan_web${IPV%4}.in="lan"uci set network.lan_web${IPV%4}.mark="1"uci set network.lan_web${IPV%4}.lookup="2"uci set network.lan_web${IPV%4}.priority="30000"doneuci commit firewall
uci commit network
service firewall restart
service network restart
Route LAN sang OpenVPN
Nguồn giả định interface OpenVPN tên vpn. Default route 0.0.0.0/0 và ::/0 được đặt trong table 2, rồi LAN lookup table đó.1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
for IPV in 46douci set network.lan.ip${IPV}table="1"uci set network.vpn.ip${IPV}table="2"uci -q delete network.vpn_rt${IPV%4}uci set network.vpn_rt${IPV%4}="route${IPV%4}"uci set network.vpn_rt${IPV%4}.interface="vpn"uci -q delete network.lan_vpn${IPV%4}uci set network.lan_vpn${IPV%4}="rule${IPV%4}"uci set network.lan_vpn${IPV%4}.in="lan"uci set network.lan_vpn${IPV%4}.lookup="2"uci set network.lan_vpn${IPV%4}.priority="30000"doneuci set network.vpn_rt.target="0.0.0.0/0"uci set network.vpn_rt6.target="::/0"uci commit network
service network restart
Route LAN sang Tailscale
Tailscale có thể tự tạo rule. Mẫu dưới đây tạo rule riêng ở priority 30000 và dùng goto="10000" để override rule tích hợp, vì vậy phải kiểm tra ip rule sau khi Tailscale khởi động.1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
for IPV in 46douci set network.lan.ip${IPV}table="1"uci -q delete network.lan_vpn${IPV%4}uci set network.lan_vpn${IPV%4}="rule"uci set network.lan_vpn${IPV%4}.in="lan"uci set network.lan_vpn${IPV%4}.lookup="52"uci set network.lan_vpn${IPV%4}.priority="30000"uci -q delete network.pbr${IPV%4}uci set network.pbr${IPV%4}="rule"uci set network.pbr${IPV%4}.goto="10000"uci set network.pbr${IPV%4}.priority="1"doneuci commit network
service network restart
Prohibitive routes
Thay vì để traffic rơi xuống một default route không mong muốn, mẫu này tạo route kiểu prohibit trong table VPN. Interface loopback được dùng làm interface luôn up theo giả định của nguồn; hãy kiểm tra kết quả với ip route trước khi áp dụng trên router đang phục vụ người dùng.1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
for IPV in 46douci set network.vpn.ip${IPV}table="2"uci -q delete network.vpn_ks${IPV%4}uci set network.vpn_ks${IPV%4}="route${IPV%4}"uci set network.vpn_ks${IPV%4}.interface="loopback"uci set network.vpn_ks${IPV%4}.type="prohibit"uci set network.vpn_ks${IPV%4}.metric="9000"uci set network.vpn_ks${IPV%4}.table="2"doneuci set network.vpn_ks.target="0.0.0.0/0"uci set network.vpn_ks6.target="::/0"uci commit network
service network restart
Prohibitive rules
Nhánh cuối tạo rule action="prohibit" cho traffic từ LAN ở priority 32000. Đây là ranh giới an toàn để tránh leak khi VPN không có tuyến; nhưng nếu đặt priority sai, rule có thể chặn cả các exception hợp lệ.1
Kiểm tra và rollback
Sau mỗi mẫu, chạy ip rule show, ip -6 rule show, ip route show table all, ip -6 route show table all và kiểm tra endpoint VPN. Test một client LAN, một đích phải đi VPN và một đích phải đi WAN. Nếu mất mạng, khôi phục bản sao /etc/config/network hoặc /etc/config/firewall qua console/SSH đã chuẩn bị rồi restart dịch vụ; không trộn nhiều mẫu trước khi biết mẫu nào gây lỗi.
1
2
3
4
5
6
7
8
9
10
for IPV in 46douci -q delete network.lan_ks${IPV%4}uci set network.lan_ks${IPV%4}="rule${IPV%4}"uci set network.lan_ks${IPV%4}.in="lan"uci set network.lan_ks${IPV%4}.action="prohibit"uci set network.lan_ks${IPV%4}.priority="32000"doneuci commit network
service network restart
Góp Ý / Bình Luận / Đánh giá