Bối cảnh & Lý do: Khi IPsec thuần làm gián đoạn OSPF lúc 2 giờ sáng
Đồng hồ điểm 2:15 sáng thứ Bảy. Dashboard giám sát của bạn bùng nổ hàng loạt cảnh báo: các subnet tại ba văn phòng chi nhánh từ xa đột ngột biến mất khỏi bảng định tuyến core. Trên các edge router, các IPsec Security Association (SA) phase 1 và phase 2 vẫn báo trạng thái active và hoạt động bình thường. Tuy nhiên, tiến trình OSPF lại bị treo ở trạng thái INIT, không thể thiết lập quan hệ láng giềng (neighbor adjacency).
Nguyên nhân là do: IPsec tunnel mode dạng policy-based tiêu chuẩn chỉ mã hóa các gói tin IP unicast khớp với traffic selector đã khai báo. Nó sẽ loại bỏ hoàn toàn các gói tin broadcast và multicast.
Trong khi đó, OSPF lại phụ thuộc vào các gói tin hello multicast gửi tới 224.0.0.5 (tất cả OSPF router) và 224.0.0.6 (tất cả router được chỉ định – designated router) mỗi 5 đến 10 giây. Không có các gói multicast này, các node không thể tìm thấy láng giềng, đồng bộ cơ sở dữ liệu trạng thái liên kết (LSDB) hay phát hiện đường truyền bị đứt. Nếu mạng lưới của bạn mở rộng từ 2 lên 20 chi nhánh, việc duy trì hàng tá static route dự phòng qua các tunnel IPsec thuần túy sẽ nhanh chóng biến thành cơn ác mộng vận hành.
Generic Routing Encapsulation (GRE) chính là giải pháp giải quyết vấn đề này. GRE đóng gói bất kỳ payload Layer 3 nào bên trong gói tin IP point-to-point tiêu chuẩn bằng IP protocol 47. Mặc dù vậy, GRE nguyên bản lại gửi toàn bộ dữ liệu dưới dạng cleartext qua internet công cộng. Việc bọc GRE bên trong IPsec Transport Mode mang lại giải pháp toàn diện: GRE đảm nhận việc truyền tải các gói multicast mà OSPF yêu cầu, còn IPsec sẽ mã hóa toàn bộ dữ liệu trước khi đi ra ngoài mạng WAN.
Kiến trúc này là giải pháp chuẩn mực cho các edge router chạy Linux và các mô hình SD-WAN sử dụng phần cứng phổ thông thay cho các gateway độc quyền đắt đỏ.
Cài đặt: Trang bị strongSwan và FRRouting cho Linux
Chúng ta cần hai gói phần mềm trên mỗi gateway Linux: strongSwan để xử lý đàm phán IKEv2 cùng các chính sách IPsec kernel, và FRRouting (FRR) để quản lý tiến trình OSPF. Kernel Linux sẽ tự động xử lý GRE tunnel thông qua iproute2.
Trong bài viết này, chúng ta sẽ cấu hình hai gateway Debian/Ubuntu đóng vai trò là edge router:
- HQ Gateway (Node A): WAN Public
198.51.100.1(trêneth0), LAN10.10.0.0/24, Tunnel IP172.16.1.1/30 - Branch Gateway (Node B): WAN Public
203.0.113.2(trêneth0), LAN10.20.0.0/24, Tunnel IP172.16.1.2/30
Cài đặt các gói cần thiết trên cả hai máy:
sudo apt-get update
sudo apt-get install -y strongswan strongswan-pki libcharon-extra-plugins frr iproute2 iptables
Tiếp theo, bật tính năng chuyển tiếp gói tin IPv4 (packet forwarding) và nạp các kernel module cần thiết. Thiết lập rp_filter = 0 hoặc chuyển sang loose mode (2) nhằm tránh việc kernel âm thầm loại bỏ các gói tin GRE đã đóng gói khi đi vào interface ảo:
sudo modprobe ip_gre
sudo modprobe esp4
sudo modprobe xfrm4_mode_transport
# Lưu cấu hình sysctl vĩnh viễn
sudo tee /etc/sysctl.d/99-router.conf << 'EOF'
net.ipv4.ip_forward = 1
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.rp_filter = 0
net.ipv4.conf.all.rp_filter = 0
EOF
sudo sysctl --system
Cấu hình: Xây dựng đường truyền GRE mã hóa
Bước 1: Tạo interface GRE Tunnel
Trên HQ Gateway (Node A), khởi tạo interface GRE point-to-point ảo:
sudo ip tunnel add gre1 mode gre remote 203.0.113.2 local 198.51.100.1 ttl 255
sudo ip addr add 172.16.1.1/30 dev gre1
sudo ip link set dev gre1 mtu 1400
sudo ip link set dev gre1 up
Cấu hình interface tương ứng trên Branch Gateway (Node B):
sudo ip tunnel add gre1 mode gre remote 198.51.100.1 local 203.0.113.2 ttl 255
sudo ip addr add 172.16.1.2/30 dev gre1
sudo ip link set dev gre1 mtu 1400
sudo ip link set dev gre1 up
Việc hạ MTU của interface xuống 1400 (và cố định TCP MSS ở mức 1360) là cực kỳ quan trọng. Thao tác này giúp bù trừ cho 24 byte của GRE header cùng khoảng 50 đến 73 byte overhead của IPsec ESP, ngăn ngừa tình trạng phân mảnh gói tin ngầm trên các đường truyền WAN 1500-byte tiêu chuẩn.
Bước 2: Cấu hình strongSwan IPsec ở Transport Mode
Chúng ta sử dụng IPsec ở Transport Mode thay vì Tunnel Mode. Do gói GRE bên ngoài đã có sẵn IP header public có thể định tuyến (protocol 47), transport mode sẽ chèn header ESP ngay sau IP header gốc mà không cần gắn thêm IP header thứ hai gây lãng phí băng thông.
Trên HQ Gateway (Node A), khai báo pre-shared key trong /etc/ipsec.secrets:
198.51.100.1 203.0.113.2 : PSK "SuperSecretProductionKey2026!"
Thêm định nghĩa kết nối vào /etc/ipsec.conf trên HQ Gateway (Node A):
config setup
charondebug="ike 1, knl 1, cfg 1"
conn %default
keyexchange=ikev2
ike=aes256gcm128-sha256-modp2048!
esp=aes256gcm128-modp2048!
dpdaction=restart
dpddelay=10s
dpdtimeout=30s
auto=start
conn gre-ipsec
type=transport
left=198.51.100.1
leftprotoport=gre
right=203.0.113.2
rightprotoport=gre
authby=secret
Thiết lập cấu hình tương tự trên Branch Gateway (Node B):
# /etc/ipsec.secrets
203.0.113.2 198.51.100.1 : PSK "SuperSecretProductionKey2026!"
# /etc/ipsec.conf
config setup
charondebug="ike 1, knl 1, cfg 1"
conn %default
keyexchange=ikev2
ike=aes256gcm128-sha256-modp2048!
esp=aes256gcm128-modp2048!
dpdaction=restart
dpddelay=10s
dpdtimeout=30s
auto=start
conn gre-ipsec
type=transport
left=203.0.113.2
leftprotoport=gre
right=198.51.100.1
rightprotoport=gre
authby=secret
Khởi động và kích hoạt strongSwan trên cả hai gateway:
sudo systemctl restart strongswan-starter
sudo ipsec up gre-ipsec
Bước 3: Cấu hình OSPF qua FRRouting
Kích hoạt tiến trình OSPF trong /etc/frr/daemons bằng cách đặt ospfd=yes, sau đó khởi động lại dịch vụ:
sudo sed -i 's/ospfd=no/ospfd=yes/' /etc/frr/daemons
sudo systemctl restart frr
Mở shell thống nhất của FRR bằng lệnh vtysh trên HQ Gateway (Node A) để cấu hình routing instance:
sudo vtysh
configure terminal
router ospf
ospf router-id 172.16.1.1
network 172.16.1.0/30 area 0.0.0.0
network 10.10.0.0/24 area 0.0.0.0
exit
interface gre1
ip ospf network point-to-point
ip ospf hello-interval 5
ip ospf dead-interval 20
exit
exit
write memory
Thực hiện cấu hình tương ứng trên Branch Gateway (Node B):
sudo vtysh
configure terminal
router ospf
ospf router-id 172.16.1.2
network 172.16.1.0/30 area 0.0.0.0
network 10.20.0.0/24 area 0.0.0.0
exit
interface gre1
ip ospf network point-to-point
ip ospf hello-interval 5
ip ospf dead-interval 20
exit
exit
write memory
Việc đặt ip ospf network point-to-point rõ ràng sẽ bỏ qua quá trình bầu chọn Designated Router (DR) và Backup Designated Router (BDR). Điều này giúp giảm lưu lượng trao đổi trạng thái liên kết và cho phép hội tụ láng giềng chỉ trong tích tắc qua tunnel.
Kiểm tra & Giám sát: Xác minh hệ thống hoạt động
Một câu lệnh chạy không báo lỗi chưa thể đảm bảo lưu lượng đang được truyền đi an toàn. Bạn nên luôn kiểm tra riêng biệt từng layer trong network stack.
1. Kiểm tra IPsec Transport SA
Kiểm tra strongSwan để xác nhận SA ở transport-mode đã được thiết lập:
sudo ipsec statusall
Tìm các Security Association đang active khớp với các endpoint GRE của bạn:
gre-ipsec{1}: INSTALLED, TRANSPORT, reqid 1, ESP SPIs: c8f4a120_e21b5591
gre-ipsec{1}: AES_GCM_16 256, 128450 bytes_i, 129320 bytes_o, rekeying in 45 minutes
gre-ipsec{1}: 198.51.100.1/32[gre] === 203.0.113.2/32[gre]
Tiếp theo, xác nhận rằng subsystem XFRM của kernel Linux đã nạp các quy tắc chuyển đổi transport:
sudo ip xfrm state
sudo ip xfrm policy
2. Kiểm tra quan hệ láng giềng OSPF (Neighbor Adjacency)
Trong FRR, hãy đảm bảo hai gateway đã đạt trạng thái full adjacency:
sudo vtysh -c "show ip ospf neighbor"
Kết quả dự kiến:
Neighbor ID Pri State Dead Time Address Interface
172.16.1.2 0 Full/ - 00:00:18 172.16.1.2 gre1:172.16.1.1
Nếu trạng thái neighbor vẫn bị kẹt ở Init hoặc 2-Way, hãy kiểm tra lại các quy tắc iptables hoặc nftables của bạn. Đảm bảo chính sách firewall cho phép giao thức GRE (protocol 47) cùng các cổng UDP 500 và 4500 trên interface bên ngoài.
3. Kiểm tra bảng định tuyến Kernel & Bắt gói tin (Packet Capture)
Xác nhận OSPF đã thêm subnet LAN của chi nhánh từ xa vào bảng định tuyến Linux:
ip route show proto ospf
Bạn sẽ thấy subnet từ xa được định tuyến qua interface GRE ảo:
10.20.0.0/24 via 172.16.1.2 dev gre1 proto ospf metric 20
Cuối cùng, thực hiện bắt gói tin trên interface WAN vật lý trong khi ping tới một máy chủ thuộc mạng LAN từ xa (ví dụ: ping -c 3 10.20.0.15):
sudo tcpdump -ni eth0 host 203.0.113.2
Bạn chỉ được thấy các gói tin ESP(spi=0x...) truyền qua eth0. Nếu các gói tin GRE hoặc OSPFv2-Hello chưa mã hóa xuất hiện trên đường truyền, hãy dừng lưu lượng ngay lập tức và kiểm tra lại chỉ thị leftprotoport=gre trong cấu hình IPsec của bạn.

