Bối cảnh, trong một thời gian dài, chúng tôi đã gặp sự cố với tường lửa của mình, đôi khi giữ các yêu cầu HTTP bị treo một phần cho đến khi hết TCP.
Sau khi theo dõi lưu lượng truy cập trên tường lửa, tôi nhận thấy rằng nó chỉ xảy ra trong một số điều kiện thời gian nhất định, ví dụ như khi máy chủ web đã gửi toàn bộ phản hồi trước khi máy khách gửi ACK thứ hai trên tải trọng. [SYN, SYN / ACK, ACK] đã được trao đổi, REQUEST đã được gửi và ACK'ed và gói RESPONSE đầu tiên đã được nhận và ACK'ed, sau đó máy chủ web sẽ gửi phần còn lại của cơ thể phản hồi trong một lần chụp (8 gói bao gồm FIN, PSH) cuối cùng và trước khi máy khách đã ACK bất kỳ trong số đó, Tường lửa DỰ ÁN với RST về phía máy chủ web và giữ máy khách treo vô hạn.
Dưới đây là toàn bộ dấu vết của wireshark với các gói từ cả hai phía của tường lửa. 192.168.126.161 là địa chỉ IP NAT'et riêng của khách hàng. 172.16.1.2 là IP máy chủ web (không hiển thị IP công cộng thực) và 10.1.1.1 là IP bên ngoài tường lửa (không hiển thị IP công cộng thực)
2105 0.086275 192.168.126.161 172.16.1.2 TCP 37854 > http [SYN] Seq=0 Win=5840 Len=0 MSS=1460 SACK_PERM=1 TSV=89375083 TSER=0
2106 0.000066 10.1.1.1 172.16.1.2 TCP 37854 > http [SYN] Seq=0 Win=5840 Len=0 MSS=1460 SACK_PERM=1 TSV=89375083 TSER=0
2107 0.002643 172.16.1.2 10.1.1.1 TCP http > 37854 [SYN, ACK] Seq=0 Ack=1 Win=32768 Len=0 MSS=1460
2108 0.007705 172.16.1.2 192.168.126.161 TCP http > 37854 [SYN, ACK] Seq=0 Ack=1 Win=32768 Len=0 MSS=1460
2109 0.006301 192.168.126.161 172.16.1.2 TCP 37854 > http [ACK] Seq=1 Ack=1 Win=5840 Len=0
2110 0.000025 10.1.1.1 172.16.1.2 TCP 37854 > http [ACK] Seq=1 Ack=1 Win=5840 Len=0
2111 0.000007 192.168.126.161 172.16.1.2 HTTP GET /test/style.css HTTP/1.1
2112 0.000015 10.1.1.1 172.16.1.2 HTTP GET /test/style.css HTTP/1.1
2113 0.001536 172.16.1.2 10.1.1.1 TCP http > 37854 [ACK] Seq=1 Ack=111 Win=32658 Len=0
2114 0.000014 172.16.1.2 192.168.126.161 TCP http > 37854 [ACK] Seq=1 Ack=111 Win=32658 Len=0
2115 0.002274 172.16.1.2 10.1.1.1 HTTP HTTP/1.1 200 OK (text/css)
2116 0.000025 172.16.1.2 192.168.126.161 HTTP HTTP/1.1 200 OK (text/css)
2117 0.005689 192.168.126.161 172.16.1.2 TCP 37854 > http [ACK] Seq=111 Ack=1461 Win=8760 Len=0
2118 0.000024 10.1.1.1 172.16.1.2 TCP 37854 > http [ACK] Seq=111 Ack=1461 Win=8760 Len=0
2119 0.001536 172.16.1.2 10.1.1.1 HTTP Continuation or non-HTTP traffic
2120 0.000026 172.16.1.2 192.168.126.161 HTTP Continuation or non-HTTP traffic
2121 0.000007 172.16.1.2 10.1.1.1 HTTP Continuation or non-HTTP traffic
2122 0.000023 172.16.1.2 192.168.126.161 HTTP Continuation or non-HTTP traffic
2123 0.000313 172.16.1.2 10.1.1.1 HTTP Continuation or non-HTTP traffic
2124 0.000030 172.16.1.2 192.168.126.161 HTTP Continuation or non-HTTP traffic
2125 0.000007 172.16.1.2 10.1.1.1 HTTP Continuation or non-HTTP traffic
2126 0.000023 172.16.1.2 192.168.126.161 HTTP Continuation or non-HTTP traffic
2127 0.000009 172.16.1.2 10.1.1.1 HTTP Continuation or non-HTTP traffic
2128 0.000023 172.16.1.2 192.168.126.161 HTTP Continuation or non-HTTP traffic
2129 0.001108 172.16.1.2 10.1.1.1 HTTP Continuation or non-HTTP traffic
2130 0.000035 172.16.1.2 192.168.126.161 HTTP Continuation or non-HTTP traffic
2131 0.000008 172.16.1.2 10.1.1.1 HTTP Continuation or non-HTTP traffic
2132 0.000022 172.16.1.2 192.168.126.161 HTTP Continuation or non-HTTP traffic
2133 0.000007 172.16.1.2 10.1.1.1 HTTP Continuation or non-HTTP traffic
REJECT-->
2134 0.000089 10.1.1.1 172.16.1.2 TCP 37854 > http [RST] Seq=111 Win=0 Len=0
CLIENT FIRST ACK-->
2135 0.002421 192.168.126.161 172.16.1.2 TCP 37854 > http [ACK] Seq=111 Ack=2921 Win=11680 Len=0
2136 0.000033 10.1.1.1 172.16.1.2 TCP 37854 > http [ACK] Seq=111 Ack=2921 Win=11680 Len=0
2137 0.000007 192.168.126.161 172.16.1.2 TCP 37854 > http [ACK] Seq=111 Ack=4381 Win=14600 Len=0
2138 0.000014 10.1.1.1 172.16.1.2 TCP 37854 > http [ACK] Seq=111 Ack=4381 Win=14600 Len=0
2139 0.000008 192.168.126.161 172.16.1.2 TCP 37854 > http [ACK] Seq=111 Ack=5841 Win=17520 Len=0
2140 0.000014 10.1.1.1 172.16.1.2 TCP 37854 > http [ACK] Seq=111 Ack=5841 Win=17520 Len=0
2141 0.000007 192.168.126.161 172.16.1.2 TCP 37854 > http [ACK] Seq=111 Ack=7301 Win=20440 Len=0
2142 0.000013 10.1.1.1 172.16.1.2 TCP 37854 > http [ACK] Seq=111 Ack=7301 Win=20440 Len=0
2143 0.000007 192.168.126.161 172.16.1.2 TCP 37854 > http [ACK] Seq=111 Ack=8761 Win=23360 Len=0
2144 0.000015 10.1.1.1 172.16.1.2 TCP 37854 > http [ACK] Seq=111 Ack=8761 Win=23360 Len=0
2145 0.000007 192.168.126.161 172.16.1.2 TCP 37854 > http [ACK] Seq=111 Ack=10221 Win=26280 Len=0
2146 0.000013 10.1.1.1 172.16.1.2 TCP 37854 > http [ACK] Seq=111 Ack=10221 Win=26280 Len=0
2147 0.001059 192.168.126.161 172.16.1.2 TCP 37854 > http [ACK] Seq=111 Ack=11681 Win=29200 Len=0
2148 0.000018 10.1.1.1 172.16.1.2 TCP 37854 > http [ACK] Seq=111 Ack=11681 Win=29200 Len=0
Tôi đã đào và ghi nhật ký truyền tải gói theo biểu đồ này và có vẻ như gói đến cuối cùng 2133 đã vượt qua quá trình TẠM DỪNG, conntrack, mangle-PREROUTING nhưng sau đó bị mất. Tôi không có quy tắc DỰ ÁN trong iptables của mình, tôi ghi nhật ký tất cả các quy tắc DROP và không có quy tắc nào hiển thị nơi gói 2133 bị mất.
Tôi rất thích sử dụng mục tiêu TRACE trên bộ lọc đến, nhưng thật không may, Ubuntu 8.04 không được cung cấp với sự hỗ trợ cho mục tiêu TRACE.
Vì vậy, tôi tin rằng một số quy tắc định tuyến / conntrack / mangling ngầm bên trong áp dụng rằng vì một số lý do đặt lại kết nối. Có thể lưu lượng kích hoạt một số bảo vệ DOS, nhưng tôi không biết cấu hình / phân tích đó ở đâu. Điều khó chịu nhất là một gói bị từ chối và không có gì được ghi lại ...
Cũng yêu cầu tệp này hoạt động 100% từ các máy chủ windows, nhưng nó không thành công trên một số máy chủ Linux nhất định và 99,9% tất cả các yêu cầu được thực hiện nhưng đôi khi thời gian của các gói kích hoạt hành vi này trong tường lửa của chúng tôi.
EDIT Ok, bây giờ tôi đã thêm hàng tấn đăng nhập vào iptables và có vẻ như điều sau xảy ra (vẫn không biết tại sao!)
Đối với các gói vượt qua tường lửa thành công, các bước sau đây được thực hiện, tham chiếu bảng / bước từ đây
Table 3-3 step
2 raw-pre
conntrack
3 mangle-pre
4 [nat-pre]
5 routing-decision -> destination forward
6 mangle-fwd
7 filter-fwd
8 mangle-post
9 [nat-post]
Gói 2133 bị từ chối vượt qua các bước sau:
Table 3-1 steps for the incoming FIN,ACK packet 2133
2 raw-pre
conntrack
3 mangle-pre
4 [nat-pre]
5 routing-decision -> destination local
6 mangle-input
7 filter-input
8 local process emits RST -> webserver
Table 3-2 steps for the outgoing RST packet 2134 in response to 2133
1 raw-out
2 routing decision
conntrack
3 mangle-out
reroute-check
4 [nat-out]
5 filter-out
6 mangle-post
7 nat-post
Điều kỳ lạ là quyết định định tuyến cho gói 2133 ở bước 5 bây giờ khác với quyết định định tuyến cho các gói khác. Khi phân tích các yêu cầu hoạt động, ví dụ như không bị kẹt, ngay cả FIN cuối cùng cũng được định tuyến chính xác. Có vẻ như một lỗi trong kernel hoặc quyết định định tuyến là trạng thái theo một cách nào đó.
CHỈNH SỬA
Một điều có thể gây ra những vấn đề này là thực tế sau đây, lưu lượng được định tuyến giữa tường lửa và mạng LAN cục bộ, do đó mạng LAN máy khách không được kết nối trực tiếp với tường lửa thông qua L2.
+---------------------------+ +------------------+ +------------------------+
| | | Router | ( Lab network ) | |
( Internet ) -- + eth1 eth0 +-------+ +-- ( ) -+ Client 192.168.126.161 |
| 10.1.1.1 192.168.60.254 | | | ( 192.168.126.0/24 ) | |
+---------------------------+ +------------------+ +------------------------+
Trong ảnh này, 10.1.1.1 thể hiện địa chỉ IP bên ngoài của tường lửa, tất cả các địa chỉ khác là địa chỉ IP thực được sử dụng.
Đây là bảng định tuyến trên tường lửa:
Destination Gateway Genmask Flags Metric Ref Use Iface
10.1.1.0 0.0.0.0 255.255.255.240 U 0 0 0 eth1
192.168.126.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
192.168.60.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
0.0.0.0 10.1.1.15 0.0.0.0 UG 0 0 0 eth1
Lưu ý rằng 10.1.1.0 và gw 10.1.1.15 mặc định được tạo thành, phần còn lại hoàn toàn giống như được sử dụng. Tôi đã phải tự thêm tuyến 192.168.126.0/24 để truy cập mạng phòng thí nghiệm từ eth0 (192.168.60.254).
Dưới đây là một số nhật ký mở rộng về truyền tải gói cho gói 2133 cuối cùng bị từ chối do được chuyển đến máy chủ cục bộ (ví dụ: tường lửa).
[16406874.374588] raw pre IN=eth1 OUT= MAC=00:02:b3:b9:ff:b5:00:90:1a:10:06:88:08:00 SRC=172.16.1.2 DST=10.1.1.1 LEN=1004 TOS=0x00 PREC=0x00 TTL=55 ID=13739 DF PROTO=TCP SPT=80 DPT=53497 WINDOW=5840 RES=0x00 ACK PSH FIN URGP=0
[16406874.374625] mangle pre IN=eth1 OUT= MAC=00:02:b3:b9:ff:b5:00:90:1a:10:06:88:08:00 SRC=172.16.1.2 DST=10.1.1.1 LEN=1004 TOS=0x00 PREC=0x00 TTL=55 ID=13739 DF PROTO=TCP SPT=80 DPT=53497 WINDOW=5840 RES=0x00 ACK PSH FIN URGP=0
[16406874.374667] mangle in IN=eth1 OUT= MAC=00:02:b3:b9:ff:b5:00:90:1a:10:06:88:08:00 SRC=172.16.1.2 DST=10.1.1.1 LEN=1004 TOS=0x00 PREC=0x00 TTL=55 ID=13739 DF PROTO=TCP SPT=80 DPT=53497 WINDOW=5840 RES=0x00 ACK PSH FIN URGP=0
[16406874.374699] filter in IN=eth1 OUT= MAC=00:02:b3:b9:ff:b5:00:90:1a:10:06:88:08:00 SRC=172.16.1.2 DST=10.1.1.1 LEN=1004 TOS=0x00 PREC=0x00 TTL=55 ID=13739 DF PROTO=TCP SPT=80 DPT=53497 WINDOW=5840 RES=0x00 ACK PSH FIN URGP=0
[16406874.374780] mangle out IN= OUT=eth1 SRC=10.1.1.1 DST=172.16.1.2 LEN=40 TOS=0x00 PREC=0x00 TTL=64 ID=0 DF PROTO=TCP SPT=53497 DPT=80 WINDOW=0 RES=0x00 RST URGP=0
[16406874.374807] mangle post IN= OUT=eth1 SRC=10.1.1.1 DST=172.16.1.2 LEN=40 TOS=0x00 PREC=0x00 TTL=64 ID=0 DF PROTO=TCP SPT=53497 DPT=80 WINDOW=0 RES=0x00 RST URGP=0
[16406874.378813] mangle pre IN=eth0 OUT= MAC=00:02:b3:b9:ff:b4:00:90:1a:10:0c:dd:08:00 SRC=192.168.126.161 DST=172.16.1.2 LEN=40 TOS=0x00 PREC=0x00 TTL=63 ID=35424 DF PROTO=TCP SPT=53497 DPT=80 WINDOW=11680 RES=0x00 ACK URGP=0
[16406874.378863] mangle fwd IN=eth0 OUT=eth1 SRC=192.168.126.161 DST=172.16.1.2 LEN=40 TOS=0x00 PREC=0x00 TTL=62 ID=35424 DF PROTO=TCP SPT=53497 DPT=80 WINDOW=11680 RES=0x00 ACK URGP=0
Một lần nữa, IP bên ngoài fw của chúng tôi đã được thay thế bằng 10.1.1.1 và ip của máy chủ web bên ngoài mạng NAT được thay thế bằng 172.16.1.2
Tin tức mới nhất EDIT!
Lần thử cuối cùng là DROP gói RST, rất thú vị, tôi đã thêm một quy tắc iptables bỏ tất cả các gói RST đến máy chủ web mà chúng tôi gặp sự cố khi yêu cầu tệp. Và sau đó, nó hoạt động, ví dụ như gói FIN, ACK, PSH 2133 cuối cùng trong nhật ký ở trên bị hủy, nhưng vì RST bị hủy, máy chủ web có thời gian để lấy tất cả các kiến của ACK sau đó quyết định truyền lại gói cuối cùng, gói 2133 một lần nữa, và bây giờ nó đi qua tường lửa vì mô-đun contrack giờ đã thấy ACK quay trở lại từ máy khách và cho phép gói ACK, FIN cuối cùng với tải trọng cuối cùng.
Vì vậy, đây chắc chắn là một vấn đề về thời gian / cửa sổ, tệp cụ thể này, với thời gian của ACK từ máy khách, sẽ kích hoạt một cái gì đó trong conntrack từ chối gói cuối cùng từ máy chủ web.
Cho đến nay, việc googling và đọc tài liệu Kernel không tiết lộ điều gì có thể gây ra hành vi này, bước tiếp theo sẽ là đọc mã nguồn kernel cho mô đun định tuyến / conntrack.
VẤN ĐỀ GIẢI QUYẾT
Chà, ít nhất bây giờ chúng tôi biết chính xác những gì xảy ra và có một cách giải quyết để giải quyết vấn đề.
Sergey đã chỉ ra quy tắc kết hợp INVALID ở trạng thái rất có giá trị, giúp ích rất nhiều cho việc gỡ lỗi, bây giờ tôi nhận ra rằng thiết lập iptables không có quy tắc rõ ràng cho các gói INVALID đôi khi không có hành vi lạ.
Khi cho phép đăng nhập vào mô-đun conntrack vì nguyên nhân gây ra gói không hợp lệ, điều gì xảy ra khá rõ ràng và tôi đã nghi ngờ về điều này.
[16659529.322465] nf_ct_tcp: SEQ is over the upper bound (over the window of the receiver) IN= OUT= SRC=172.16.1.2 DST=10.1.1.1 LEN=1004 TOS=0x00 PREC=0x00 TTL=55 ID=40874 DF PROTO=TCP SPT=80 DPT=55498 SEQ=658735108 ACK=1194081763 WINDOW=5840 RES=0x00 ACK PSH FIN URGP=0
Một lần nữa, 172.16.1.2 là máy chủ web bên ngoài (hoạt động không chính xác) và 10.1.1.1 là địa chỉ bên ngoài của tường lửa.
Máy chủ web đẩy nhiều dữ liệu qua dây hơn máy khách đã quảng cáo trong cửa sổ nhận (conntrack đầy trạng thái và xác minh điều này), có vẻ như đó là khi gói FIN đến mà conntrack bỏ ra vì cửa sổ nhận thực sự vượt quá nhiều sớm hơn.
Tôi tin rằng điều đó có thể do việc giảm tải TCP không chính xác trong card mạng trên máy chủ web. Khi tôi bắt đầu phân tích điều này, tôi đã chụp được trên máy chủ web và theo các khung jumbo tcpdump / wireshark được ghi bởi lớp TCP trong kernel sau đó được phân đoạn thành các khung nhỏ hơn với MTU = 1500 bằng thẻ mạng. Vì vậy, rõ ràng điều này cần phải được quảng cáo trong máy chủ web vì nó không đúng hành vi TCP để gửi nhiều dữ liệu hơn người nhận có quảng cáo trong cửa sổ nhận của nó.
Cả Polynomial và Sergey đều cung cấp đầu vào có giá trị, nhưng Serge chỉ cho tôi hành vi chính xác của mô đun conntrack / NAT liên quan đến truyền tải gói.