Một Linux server có hai NIC hoặc hai uplink dễ gửi gói ra đúng Internet nhưng nhận reply về sai đường, làm session chập chờn, firewall state không khớp hoặc packet bị reverse-path filtering loại bỏ. Policy routing giải quyết bằng Routing Policy Database: chọn routing table theo source address, interface, fwmark và các thuộc tính khác trước khi tra route theo destination.
Bài viết bám theo tài liệu iproute2 về ip rule, ip route và tài liệu Linux kernel về IP sysctl. Cú pháp persistence khác giữa NetworkManager, systemd-networkd, Netplan và network scripts; hãy áp dụng bằng đúng network manager của distribution.
1. Vì sao một bảng route không đủ?
Routing truyền thống chủ yếu chọn đường theo destination. Khi host có hai địa chỉ public:
wan0:192.0.2.10/24, gateway192.0.2.1;wan1:198.51.100.10/24, gateway198.51.100.1.
Nếu main table ưu tiên default qua wan0, reply cho connection đi vào 198.51.100.10 có thể bị gửi ra wan0. ISP thường không chấp nhận source thuộc uplink khác; thiết bị stateful trên đường đi cũng thấy luồng không đối xứng.
Các địa chỉ trong bài thuộc dải tài liệu RFC 5737, không phải IP triển khai thật.
2. RPDB và routing table là hai tầng quyết định
- RPDB: kernel duyệt
ip ruletheo priority tăng dần; số nhỏ được xét trước. - Routing table: rule phù hợp chỉ định table; trong table đó, longest-prefix match chọn route.
ip rule show
ip route show table local
ip route show table main
ip route show table default
Mặc định thường có rule priority 0 tra table local, 32766 tra main và 32767 tra default. Không xóa rule local. Mọi custom rule nên có priority rõ ràng, duy nhất và nằm trong dải được tổ chức quản lý.
3. Mỗi uplink cần một table hoàn chỉnh
Đặt tên table giúp cấu hình dễ audit, ví dụ trong file rt_tables phù hợp với distro:
100 isp_a
200 isp_b
Table chỉ có default route thường chưa đủ. Nó cần connected route để kernel biết gateway reachable và preferred source cho uplink đó:
ip route replace 192.0.2.0/24 \
dev wan0 src 192.0.2.10 table 100
ip route replace default \
via 192.0.2.1 dev wan0 table 100
ip route replace 198.51.100.0/24 \
dev wan1 src 198.51.100.10 table 200
ip route replace default \
via 198.51.100.1 dev wan1 table 200
replace giúp thao tác idempotent hơn add, nhưng lệnh chạy tay vẫn chỉ là trạng thái runtime và có thể mất sau reboot/network restart.
4. Source-based rule giữ reply đúng uplink
ip rule add priority 1000 \
from 192.0.2.10/32 table 100
ip rule add priority 1010 \
from 198.51.100.10/32 table 200
Traffic có source 192.0.2.10 tra table 100; source 198.51.100.10 tra table 200. Điều này phù hợp cho service bind đúng local address và reply giữ source là địa chỉ nhận connection.
Không tạo hai rule cùng priority rồi hy vọng thứ tự ổn định. Ghi owner và mục đích của từng dải priority trong source of truth.
5. Kiểm chứng bằng ip route get
ip route get 203.0.113.80 from 192.0.2.10
ip route get 203.0.113.80 from 198.51.100.10
ip route get 203.0.113.80 \
from 10.10.20.15 iif lan0
ip -details rule show
ip route show table 100
ip route show table 200
ip route show chỉ liệt kê cấu hình; ip route get thực hiện lookup như kernel nhìn thấy, có thể truyền source, incoming interface và mark. Kết quả cần kiểm tra gateway, device, source và table. Sau đó mới probe thật với source cụ thể và capture hai phía.
ping -I 192.0.2.10 203.0.113.80
tcpdump -ni wan0 host 203.0.113.80
tcpdump -ni wan1 host 203.0.113.80
6. Route cho mạng nội bộ phải có trong custom table
Nếu table 100 chỉ có connected WAN và default, packet từ source policy muốn tới mạng nội bộ có thể bị đẩy ra ISP. Thêm route LAN/service network cần thiết vào mỗi table hoặc thiết kế rule để lookup main trước/sau một cách có chủ ý.
ip route replace 10.10.0.0/16 \
via 10.10.0.1 dev lan0 table 100
ip route replace 10.10.0.0/16 \
via 10.10.0.1 dev lan0 table 200
Không copy ví dụ nếu 10.10.0.1 không phải topology thật. Inventory mọi connected, management, storage, overlay, VPN và blackhole route mà workload cần trước khi chuyển rule.
7. fwmark cho policy không thể biểu diễn bằng source
Source rule không đủ khi router forward nhiều client, transparent proxy hoặc application cần chọn uplink theo class. Netfilter/nftables có thể đặt packet mark; RPDB dùng fwmark để chọn table:
# Chỉ minh họa lookup; cách đặt/khôi phục mark phải nằm trong policy nftables
ip rule add priority 1100 fwmark 0x1/0xff table 100
ip rule add priority 1110 fwmark 0x2/0xff table 200
ip route get 203.0.113.80 mark 0x1
ip route get 203.0.113.80 mark 0x2
Packet mark và conntrack mark không tự đồng bộ. Luồng stateful thường cần lưu quyết định vào connection mark rồi restore cho packet reply ở đúng hook trước route lookup. Thứ tự nftables chain, priority, NAT và routing phải được test end-to-end; một rule mark đúng cú pháp nhưng chạy sau lookup sẽ không có tác dụng.
8. NAT không thay policy routing
SNAT/masquerade đổi source, còn policy routing chọn đường. Với host forward/NAT, cả hai phải thống nhất:
- traffic ra ISP A được route và SNAT bằng địa chỉ A;
- traffic ra ISP B được route và SNAT bằng địa chỉ B;
- reply thuộc connection được nhận diện và trở lại đúng path;
- firewall forwarding policy cho phép đúng zone/interface.
Không dùng một rule masquerade rộng cho mọi egress nếu cần địa chỉ ổn định hoặc audit được. Policy routing cũng không thay firewall: có route không đồng nghĩa packet được phép.
9. Reverse-path filtering và route bất đối xứng
rp_filter kiểm tra source của packet đến bằng lookup đường về:
| Giá trị | Hành vi IPv4 | Phù hợp |
|---|---|---|
| 0 | Không reverse-path validation | Chỉ khi có kiểm soát chống spoof khác và lý do rõ |
| 1 | Strict: interface vào phải là best reverse path | Host đơn giản, route đối xứng |
| 2 | Loose: source phải reachable qua một interface | Asymmetric/complex routing theo hướng dẫn kernel |
Giá trị hiệu lực liên quan cả conf/all và interface; một số distro bật strict mode bằng startup policy. Không tắt global theo thói quen. Đo topology, áp theo interface nếu có thể và duy trì ingress anti-spoof bằng firewall/provider controls.
sysctl net.ipv4.conf.all.rp_filter
sysctl net.ipv4.conf.wan0.rp_filter
sysctl net.ipv4.conf.wan1.rp_filter
sysctl net.ipv4.conf.all.src_valid_mark
Nếu fwmark được dùng đối xứng trong lookup, src_valid_mark=1 có thể cần để reverse-path lookup xét mark. Đây là quyết định kiến trúc, không phải option sửa lỗi chung.
10. Hai NIC cùng subnet và ARP flux
Khi nhiều interface nằm cùng L2 subnet, Linux coi IP là thuộc host và có thể trả ARP qua interface không mong đợi. Source routing một mình chưa chắc đủ. Các sysctl như arp_filter, arp_ignore và arp_announce có trade-off riêng; cấu hình sai có thể làm mất reachability.
Ưu tiên thiết kế mỗi uplink ở subnet/VLAN riêng. Nếu buộc cùng subnet, test ARP/neighbor behavior, bonding/VRF alternatives và yêu cầu provider trên lab representative trước production.
11. Failover không chỉ là thêm hai default route
Route metric trong main table có thể chọn default ưu tiên, nhưng source rule đưa packet sang custom table khác. Mỗi table cần policy failover riêng. Gateway còn trả ARP cũng không chứng minh Internet, DNS hay ứng dụng upstream hoạt động.
- Health check qua từng source/uplink tới nhiều target độc lập.
- Phân biệt link down, gateway down, upstream partial failure và DNS failure.
- Chống flapping bằng success/failure threshold và hold-down.
- Không chuyển source
192.0.2.10qua ISP B nếu ISP B chặn địa chỉ đó. - Session hiện hữu thường không sống qua đổi public source; ứng dụng phải reconnect.
Active-active, ECMP và per-flow load balancing là thiết kế khác active-standby. Conntrack, NAT, hashing và return path phải đồng thuận trên mọi thiết bị.
12. Persistence: một nơi làm source of truth
Lệnh ip phù hợp để thử nghiệm và chẩn đoán, nhưng network manager có thể ghi đè. Chọn một cơ chế được distro hỗ trợ:
- NetworkManager connection profiles/routing rules;
- systemd-networkd
[Route]và[RoutingPolicyRule]; - Netplan sinh cấu hình cho renderer bên dưới;
- automation quản lý toàn bộ state, có idempotency và rollback.
Không vừa sửa runtime bằng script boot vừa để NetworkManager quản lý cùng route. Version-control cấu hình, validate trước apply và kiểm tra lại sau reboot, DHCP renew, link flap và network service restart.
13. Thay đổi từ xa mà không tự khóa server
- Đảm bảo console/out-of-band access hoạt động.
- Chụp
ip -details rule,ip route show table all, address và neighbor state. - Đặt change window và rollback tự động có thời hạn.
- Thêm table/route trước, kiểm tra
ip route get, rồi mới thêm rule. - Giữ management subnet có route rõ ràng và test từ phiên SSH thứ hai.
- Persist cấu hình, reboot có kiểm soát và chạy lại probe hai chiều.
Không flush toàn bộ rule/route trên máy remote đang phụ thuộc chính network đó. Xóa từng entry theo priority/table đã xác minh.
14. IPv6 cần thiết kế riêng
IPv6 cũng hỗ trợ nhiều table và ip -6 rule, nhưng Router Advertisement, source-address selection, nhiều prefix, temporary address và policy nhà mạng làm behavior khác IPv4. Không mặc định NAT66 để bắt chước IPv4. Theo dõi route do RA/DHCPv6 tạo, chọn source và firewall ICMPv6; test ip -6 route get ... from ... cho từng prefix.
15. Monitoring và runbook
| Tín hiệu | Điều cần phát hiện |
|---|---|
| Rule/table desired state | Network manager hoặc operator làm lệch cấu hình |
| Source-specific probes | Một uplink hỏng trong khi probe mặc định vẫn xanh |
| Route-get assertions | Gateway/device/source không đúng policy |
| Neighbor và link state | ARP/NDP, carrier hoặc gateway lỗi |
| Drops/firewall/conntrack | Asymmetry, invalid state hoặc capacity |
| rp_filter/martian log | Packet hợp lệ bị source validation loại |
Khi sự cố, bắt packet đồng thời ở LAN và cả hai WAN, tra route với đúng source/mark/iif, kiểm tra rule priority, table, neighbor, nftables counters, conntrack và sysctl. Đừng kết luận từ một ping không chỉ định source.
Checklist production
- Mỗi uplink có table chứa connected route, default và internal routes cần thiết.
- Rule có priority duy nhất, owner và source of truth.
ip route getđúng cho từng source, iif và mark quan trọng.- NAT, conntrack mark và policy routing đồng thuận hai chiều.
rp_filter/src_valid_marktheo threat model, không tắt mù quáng.- Failover probe đi qua đúng uplink và chống flapping.
- Management/monitoring/storage network có route rõ ràng.
- Persistence được quản lý bởi một công cụ, đã test qua reboot/link flap.
- Có console và rollback trước mọi thay đổi remote.
- IPv4 và IPv6 được kiểm chứng riêng.
Kết luận
Linux policy routing hiệu quả khi được nhìn như một chương trình hai tầng: rule chọn table, table chọn route. Với nhiều uplink, mục tiêu không chỉ “ra được Internet” mà là source, egress, NAT, return path và reverse-path validation cùng nhất quán. Table đầy đủ, priority rõ ràng, kiểm thử bằng ip route get, persistence duy nhất và probe theo từng source biến một cấu hình nhiều NIC mong manh thành hạ tầng có thể vận hành.




Chưa có bình luận. Hãy là người đầu tiên chia sẻ ý kiến.