Tôi đã gặp một vấn đề rắc rối với NAT nguồn khi sử dụng nhiều VRF trên bộ định tuyến dựa trên Debian. Nó hơi phức tạp để giải thích, vì vậy tôi sẽ cố gắng giải thích rõ ràng, nhưng nó sẽ không ngắn, xin lỗi vì điều đó. Vấn đề nên được dễ dàng để tái sản xuất mặc dù.
Để tách phần "quản lý" của bộ định tuyến (ssh và các dịch vụ khác) khỏi công việc bộ định tuyến của nó (các gói định tuyến và NATing), tôi đã cố gắng thiết lập VRF "mgmt" trong VRF mặc định (dễ xử lý hơn với các ổ cắm dịch vụ) và định tuyến trong VRF được gọi là "tường lửa".
Sơ đồ có thể được tóm tắt như sau:
Giản đồ hệ thống
Mạng "quản lý" là 192.168.100.0/24 và được định tuyến bởi một bộ chuyển mạch L3 có L3 với VRF "tường lửa" của bộ định tuyến thông qua mạng 10.254.5.0/24. Giao diện bộ định tuyến thứ ba là giao diện "internet" và các gói đi qua nó là nguồn NATed. Thiết lập này hoạt động khá tốt cho mọi thứ trong mạng con mgmt, ngoại trừ các gói riêng của bộ định tuyến, nguyên nhân gây ra sự cố.
Giới thiệu về quy tắc iptables:
# Bộ lọc bảng
# chuỗi ĐẦU VÀO
-A INPUT -m conntrack --ctstate LIÊN QUAN, THÀNH LẬP -j CHẤP NHẬN
(một số quy tắc INPUT, cho ssh, snmp, v.v.)
-A INPUT -j DROP
# chuỗi FORWARD
-A FORWARD -m conntrack --ctstate LIÊN QUAN, THÀNH LẬP -j CHẤP NHẬN
-A FORWARD -m conntrack --ctstate INVALID -j DROP
-A VỀ PHÍA TRƯỚC -o eth2 -j CHẤP NHẬN
-A VỀ PHÍA TRƯỚC -j DROP
# Bảng tự nhiên
# chuỗi POSTROUTING
-A POSTROUTING -o eth2 -j SNAT --to-source 192.168.122.100
Về bảng định tuyến:
# VRF mặc định
mặc định qua 192.168.100.1 dev eth0 chỉ số tĩnh nguyên mẫu 20
192.168.100.0/24 dev eth0 liên kết phạm vi kernel proto src 192.168.100.90
# tường lửa VRF
mặc định qua 192.168.122.1 dev eth2 chỉ số tĩnh nguyên mẫu 20
10.254.5.0/24 dev eth1 liên kết phạm vi kernel proto src 10.254.5.2
192.168.100.0/24 proto bgp metric 20 nexthop qua 10.254.5.10 dev eth1 trọng số 1
192.168.122.0/24 dev eth2 liên kết phạm vi kernel proto src 192.168.122.100
Vì vậy, khi một gói từ VRF mặc định cố gắng truy cập internet, nó sẽ thoát ra khỏi eth0, được định tuyến bởi bộ chuyển mạch L3, nhập VRF tường lửa bằng eth1 và được định tuyến và NAT thông qua eth2. Vì tôi theo dõi các kết nối INPUT và FORWARD, conntrack hơi bối rối khi gói tin quay lại và không thể biết phải làm gì với gói tin.
Tôi đã có thể sửa lỗi này cho ICMP và UDP bằng cách sử dụng vùng conntrack trong bảng thô
# Bảng nguyên
# chuỗi PREROUTING
-A PREROUTING -i eth0 -j CT --zone 5
# chuỗi ĐẦU RA
-A OUTPUT -o eth0 -j CT --zone 5
Với các quy tắc này, gói tin bắt nguồn từ bộ định tuyến và đi qua eth0
là thẻ khu 5
và khi các gói đi vào eth0
họ cũng được gắn thẻ khu 5
.
Với lệnh ping tới 8.8.8.8, nó trông như thế này (với lệnh conntrack -E
):
[MỚI] icmp 1 30 src=192.168.100.90 dst=8.8.8.8 type=8 code=0 id=1999 [UNREPLIED] src=8.8.8.8 dst=192.168.100.90 type=0 code=0 id=1999 zone=5
[MỚI] icmp 1 30 src=192.168.100.90 dst=8.8.8.8 type=8 code=0 id=1999 [UNREPLIED] src=8.8.8.8 dst=192.168.122.100 type=0 code=0 id=1999
[CẬP NHẬT] icmp 1 30 src=192.168.100.90 dst=8.8.8.8 type=8 code=0 id=1999 src=8.8.8.8 dst=192.168.122.100 type=0 code=0 id=1999
[CẬP NHẬT] icmp 1 30 src=192.168.100.90 dst=8.8.8.8 type=8 code=0 id=1999 src=8.8.8.8 dst=192.168.100.90 type=0 code=0 id=1999 zone=5
Chúng ta có thể thấy ở đây cái đầu tiên MỚI
kết nối được tạo khi gói đi qua eth0
với khu = 5
thẻ, sau đó là thẻ mới khi nó vào tường lửa VRF thông qua eth1
không có thẻ. Khi có câu trả lời, kết nối thứ hai được cập nhật trước (vì đó là kết nối đối diện với internet) và sau đó là kết nối đầu tiên.
Điều này cũng hoạt động với UDP, ví dụ với truy vấn DNS tới 8.8.8.8
[MỚI] udp 17 30 src=192.168.100.90 dst=8.8.8.8 sport=53369 dport=53 [UNREPLIED] src=8.8.8.8 dst=192.168.100.90 sport=53 dport=53369 zone=5
[MỚI] udp 17 30 src=192.168.100.90 dst=8.8.8.8 sport=53369 dport=53 [UNREPLIED] src=8.8.8.8 dst=192.168.122.100 sport=53 dport=53369
[CẬP NHẬT] udp 17 30 src=192.168.100.90 dst=8.8.8.8 sport=53369 dport=53 src=8.8.8.8 dst=192.168.122.100 sport=53 dport=53369
[CẬP NHẬT] udp 17 30 src=192.168.100.90 dst=8.8.8.8 sport=53369 dport=53 src=8.8.8.8 dst=192.168.100.90 sport=53 dport=53369 khu vực=5
Nhưng với TCP thì không. Truy vấn telnet tới 172.16.10.10 cổng 80 trông như thế này:
[MỚI] tcp 6 120 SYN_SENT src=192.168.100.90 dst=172.16.10.10 sport=60234 dport=80 [UNREPLIED] src=172.16.10.10 dst=192.168.100.90 sport=80 dport=60234 zone=5
[MỚI] tcp 6 120 SYN_SENT src=192.168.100.90 dst=172.16.10.10 sport=60234 dport=80 [UNREPLIED] src=172.16.10.10 dst=192.168.122.100 sport=80 dport=60234
[CẬP NHẬT] tcp 6 58 SYN_RECV src=192.168.100.90 dst=172.16.10.10 sport=60234 dport=80 src=172.16.10.10 dst=192.168.122.100 sport=80 dport=60234
[CẬP NHẬT] tcp 6 57 SYN_RECV src=192.168.100.90 dst=172.16.10.10 sport=60234 dport=80 src=172.16.10.10 dst=192.168.122.100 sport=80 dport=60234
(Dòng cuối lặp lại nhiều lần)
Nếu tôi tcpdump eth2
câu trả lời ở đó:
IP 192.168.122.100.60236 > 172.16.10.10.80: Flags [S], seq 4203590660, win 62720, tùy chọn [mss 1460,sackOK,TS val 1511828881 ecr 0,nop,wscale 7], độ dài 0
IP 172.16.10.10.80 > 192.168.122.100.60236: Flags [S.], seq 3672808466, ack 4203590661, win 65535, tùy chọn [mss 1430,sackOK,TS val 2474659117 ecr 1511828,881, 8nop
IP 192.168.122.100.60236 > 172.16.10.10.80: Flags [S], seq 4203590660, win 62720, tùy chọn [mss 1460,sackOK,TS val 1511829887 ecr 0,nop,wscale 7], độ dài 0
IP 172.16.10.10.80 > 192.168.122.100.60236: Flags [S.], seq 3672808466, ack 4203590661, win 65535, tùy chọn [mss 1430,sackOK,TS val 2474660123 ecr 1511828,881, 8nop
Nhưng vì SIN ACK không bao giờ được xác nhận, bộ định tuyến tiếp tục gửi SIN mới.
Bây giờ, nếu tôi tcpdump eth1
:
IP 192.168.100.90.60238 > 172.16.10.10.80: Flags [S], seq 3124513394, win 62720, tùy chọn [mss 1460,sackOK,TS val 1511928806 ecr 0,nop,wscale 7], độ dài 0
IP 192.168.100.90.60238 > 172.16.10.10.80: Flags [S], seq 3124513394, win 62720, tùy chọn [mss 1460,sackOK,TS val 1511929823 ecr 0,nop,wscale 7], độ dài 0
IP 192.168.100.90.60238 > 172.16.10.10.80: Flags [S], seq 3124513394, win 62720, tùy chọn [mss 1460,sackOK,TS val 1511931839 ecr 0,nop,wscale 7], độ dài 0
Chúng ta có thể thấy rằng câu trả lời không bao giờ được chuyển về 192.168.100.90.
Nếu tôi tắt theo dõi kết nối và cho phép mọi thứ trong iptables, nó sẽ hoạt động. Vì vậy, tôi nghĩ rằng conntrack gặp sự cố đối với các kết nối TCP được quản lý từ chính nó sang vùng khác khi chúng là NAT? Nếu có điều gì đó không rõ ràng, tôi sẽ sẵn lòng trả lời bất kỳ câu hỏi nào về vấn đề này.