พื้นหลังเป็นเวลานานที่เราประสบปัญหากับไฟร์วอลล์ของเราที่บางครั้งทำให้การร้องขอ HTTP ถูกระงับการโหลดบางส่วนจนกระทั่ง TCP หมดเวลา
หลังจากติดตามปริมาณการใช้งานบนไฟร์วอลล์ฉันสังเกตเห็นว่ามันเกิดขึ้นเฉพาะในช่วงเวลาที่กำหนดเช่นเมื่อเว็บเซิร์ฟเวอร์ส่งการตอบสนองทั้งหมดก่อนที่ลูกค้าจะส่ง ACK ตัวที่สองบนเพย์โหลด [SYN, SYN / ACK, ACK] มีการแลกเปลี่ยนคำขอได้รับการส่งและ ACK'ed และได้รับแพ็คเก็ต RESPONSE แรกและ ACK'ed จากนั้นเว็บเซิร์ฟเวอร์จะส่งเนื้อหาการตอบสนองที่เหลือในหนึ่งช็อต (8 แพ็คเก็ต รวมถึง FIN สุดท้าย, PSH) และก่อนที่ลูกค้าจะได้รับ ACK ใด ๆ เหล่านั้นไฟร์วอลล์จะทำการตอบโต้ด้วย RST ไปยังเว็บเซิร์ฟเวอร์และทำให้ไคลเอนต์ไม่มีที่สิ้นสุด
นี่คือการติดตามทั้งหมดของ wireshark ที่มีแพ็กเก็ตจากทั้งสองด้านของไฟร์วอลล์ 192.168.126.161 เป็นที่อยู่ IP ของ NAT'et ส่วนตัวของลูกค้า 172.16.1.2 เป็นเว็บเซิร์ฟเวอร์ IP (ไม่แสดง IP สาธารณะจริง) และ 10.1.1.1 เป็น IP ภายนอกไฟร์วอลล์ (ไม่แสดง IP สาธารณะจริง)
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
ฉันขุดและบันทึกการสำรวจเส้นทางแพ็คเก็ตตามแผนภูมินี้และดูเหมือนว่าแพ็คเก็ตที่เข้ามาล่าสุด 2133 ได้รับการผ่านการประมวลผลแบบดิบ, การควบคุม, การทำลาย, การประลอง แต่ก็หายไป ฉันไม่มีกฎการปฏิเสธใน iptables ของฉันฉันบันทึกกฎ DROP ทั้งหมดและไม่มีกฎใดที่แสดงว่าแพ็กเก็ต 2133 หายไป
ฉันชอบที่จะใช้เป้าหมายการสืบค้นกลับบนตัวกรองขาเข้า แต่น่าเสียดายที่อูบุนตู 8.04 ไม่ได้จัดส่งพร้อมการสนับสนุนเป้าหมายการติดตาม
ดังนั้นฉันจึงเชื่อว่ากฎการกำหนดเส้นทาง / conntrack / mangling ภายในบางอย่างมีผลบังคับใช้นั้นด้วยเหตุผลบางประการรีเซ็ตการเชื่อมต่อ อาจทราฟฟิกทริกเกอร์การป้องกัน DOS บางอย่าง แต่ฉันไม่รู้ว่าจะกำหนดค่า / วิเคราะห์ได้อย่างไร สิ่งที่น่าผิดหวังที่สุดคือแพ็คเก็ตถูกปฏิเสธและไม่มีอะไรเข้าสู่ระบบ ...
การร้องขอไฟล์นี้ทำงานได้ 100% จากโฮสต์ windows แต่มันล้มเหลวในโฮสต์ Linux บางตัวและ 99.9% ของการร้องขอทั้งหมดดำเนินการผ่าน แต่บางครั้งเวลาของแพ็กเก็ตทำให้เกิดพฤติกรรมนี้ในไฟร์วอลล์ของเรา
แก้ไข ตกลงตอนนี้ฉันได้เพิ่มการเข้าสู่ระบบมากมายใน iptables และดูเหมือนว่าสิ่งต่อไปนี้เกิดขึ้น (ยังไม่รู้ว่าทำไม!)
สำหรับแพ็กเก็ตที่ประสบความสำเร็จในการข้ามไฟร์วอลล์ทำตามขั้นตอนต่อไปนี้อ้างอิงตาราง / ขั้นตอนจากที่นี่
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]
แพ็คเก็ต 2133 ที่ถูกปฏิเสธผ่านเส้นทางเหล่านี้:
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
สิ่งที่แปลกคือการตัดสินใจกำหนดเส้นทางสำหรับแพ็กเก็ต 2133 ในขั้นตอนที่ 5 ตอนนี้แตกต่างจากการตัดสินใจกำหนดเส้นทางสำหรับแพ็กเก็ตอื่น ๆ เมื่อวิเคราะห์คำขอที่ได้ผลเช่นไม่ติดขัดแม้ FIN สุดท้ายจะถูกกำหนดเส้นทางอย่างเหมาะสม ดูเหมือนว่ามีข้อบกพร่องในเคอร์เนลหรือการตัดสินใจกำหนดเส้นทางเป็น stateful ในบางวิธี
แก้ไข
สิ่งหนึ่งที่อาจทำให้เกิดปัญหาเหล่านี้คือข้อเท็จจริงดังต่อไปนี้ทราฟฟิกถูกกำหนดเส้นทางระหว่างไฟร์วอลล์และ LAN ท้องถิ่นดังนั้น LAN ไคลเอ็นต์ไม่ได้เชื่อมต่อโดยตรงกับไฟร์วอลล์ผ่าน 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 ) | |
+---------------------------+ +------------------+ +------------------------+
ในภาพนี้ 10.1.1.1 แสดงที่อยู่ IP ภายนอกของไฟร์วอลล์ที่อยู่อื่นทั้งหมดเป็นที่อยู่ IP จริงที่ใช้
นี่คือตารางเส้นทางในไฟร์วอลล์:
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
โปรดทราบว่า 10.1.1.0 และ gw เริ่มต้น 10.1.1.15 ถูกสร้างขึ้นส่วนที่เหลือจะเหมือนกับที่ใช้ ฉันต้องเพิ่มเส้นทาง 192.168.126.0/24 ด้วยตนเองเพื่อไปยังเครือข่ายแล็บจาก eth0 (192.168.60.254)
ต่อไปนี้เป็นบันทึกที่ครอบคลุมเกี่ยวกับการสำรวจเส้นทางแพ็คเก็ตสำหรับแพ็คเก็ต 2133 ครั้งล่าสุดที่ได้รับการปฏิเสธเนื่องจากถูกกำหนดเส้นทางไปยังโลคัลโฮสต์ (เช่นไฟร์วอลล์)
[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
IP ภายนอก fw ภายนอกของเราถูกแทนที่ด้วย 10.1.1.1 และ ip ของเว็บเซิร์ฟเวอร์นอกเครือข่าย NAT'ed จะถูกแทนที่ด้วย 172.16.1.2
แก้ไขข่าวด่วน!
ตกลงล่าสุดพยายามที่จะ DROP แพ็คเก็ต RST ที่น่าสนใจมากฉันเพิ่มกฎ iptables ที่ลดลงแพ็คเก็ต RST ทั้งหมดที่กำหนดไว้ในเว็บเซิร์ฟเวอร์เรามีปัญหาในการร้องขอไฟล์จาก และจากนั้นก็ทำงานเช่น FIN สุดท้าย ACK, PSH แพ็คเก็ต 2133 ในบันทึกด้านบนถูกทิ้ง แต่เนื่องจาก RST ถูกทิ้งเว็บเซิร์ฟเวอร์มีเวลาที่จะได้รับมดทั้งหมดของ ACK จากนั้นตัดสินใจที่จะส่งแพ็กเก็ตสุดท้ายแพ็คเก็ต 2133 อีกครั้ง และตอนนี้มันจะผ่านไฟร์วอลล์ตั้งแต่โมดูล contrack ตอนนี้ได้เห็น ACK กลับมาจากลูกค้าและอนุญาตให้ ACK สุดท้ายแพ็คเก็ต FIN ด้วยอัตราสุดท้าย
ดังนั้นจึงเป็นปัญหาเวลา / หน้าต่างแน่นอนไฟล์นี้โดยเฉพาะกับเวลาของ ACK จากลูกค้าเรียกสิ่งที่ conntrack ที่ปฏิเสธแพ็กเก็ตสุดท้ายจากเว็บเซิร์ฟเวอร์
จนถึงตอนนี้ googling และการอ่านเอกสารของเคอร์เนลไม่พบสิ่งใดที่ทำให้เกิดพฤติกรรมนี้ขั้นตอนต่อไปคือการอ่านซอร์สโค้ดเคอร์เนลสำหรับโมดูลการเราต์ / คอนแท็ค
แก้ไขปัญหา
อย่างน้อยตอนนี้เราก็รู้ว่าเกิดอะไรขึ้นและมีวิธีแก้ปัญหาที่แก้ปัญหาได้
Sergey ชี้ไปที่รัฐที่มีค่ามาก - กฎการจับคู่ INVALID รัฐซึ่งช่วยในการตรวจแก้จุดบกพร่องมากมายตอนนี้ฉันทราบว่าการตั้งค่า iptables โดยไม่มีกฎที่ชัดเจนสำหรับแพ็กเก็ต INVALID ไม่สมบูรณ์ดังนั้นพฤติกรรมแปลก ๆ บางครั้งดูเหมือนจะเกิดขึ้น
เมื่อเปิดใช้งานการเข้าสู่ระบบในโมดูล conntrack สำหรับสิ่งที่ทำให้เกิดแพ็คเก็ตที่ไม่ถูกต้องสิ่งที่เกิดขึ้นมันชัดเจนและฉันสงสัยเกี่ยวกับเรื่องนี้
[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
อีกครั้ง 172.16.1.2 เป็นเว็บเซิร์ฟเวอร์ภายนอก (ซึ่งทำงานไม่ถูกต้อง) และ 10.1.1.1 เป็นที่อยู่ภายนอกของไฟร์วอลล์
เว็บเซิร์ฟเวอร์ส่งข้อมูลผ่านสายมากกว่าไคลเอนต์ที่โฆษณาในหน้าต่างรับ (การเชื่อมต่อเต็มรัฐและตรวจสอบสิ่งนี้) ดูเหมือนว่าเมื่อแพ็คเก็ต FIN มาถึงที่เชื่อมต่อ bails ออกเนื่องจากหน้าต่างรับเกินจริงมาก ก่อน
ฉันเชื่อว่าอาจเกิดจากการถ่าย TCP ไม่ถูกต้องในการ์ดเครือข่ายบนเว็บเซิร์ฟเวอร์ เมื่อฉันเริ่มวิเคราะห์สิ่งนี้ฉันได้จับภาพบนเว็บเซิร์ฟเวอร์และตามเฟรมจัมโบ้ tcpdump / wireshark ร่องรอยที่เขียนโดยเลเยอร์ TCP ในเคอร์เนลซึ่งถูกแบ่งเป็นเฟรมขนาดเล็กด้วย MTU = 1500 โดยการ์ดเครือข่าย เห็นได้ชัดว่าสิ่งนี้จำเป็นต้องได้รับการแก้ไขในเว็บเซิร์ฟเวอร์เนื่องจากมันไม่ถูกต้องพฤติกรรม TCP ในการส่งข้อมูลมากกว่าผู้รับมีโฆษณาในหน้าต่างรับของมัน
ทั้ง Polynomial และ Sergey ให้การป้อนข้อมูลที่มีค่า แต่ Sergey ชี้ให้ฉันเห็นถึงพฤติกรรมที่ถูกต้องของโมดูล conntrack / NAT ที่เกี่ยวกับการข้ามแพ็คเก็ต