在跟踪防火墙上的流量后,我注意到它仅在某些时间条件下发生,例如,当客户端在有效载荷上发送第二个ACK之前,Web服务器已发送了整个响应. [SYN,SYN / ACK,ACK]已经被交换,REQUEST已被发送并且已经确认并且第一个RESPONSE数据包已经被接收并且被确认,然后网络服务器一次性发送其余的响应主体(8个数据包)包括最后一个FIN,PSH)并且在客户端确认任何这些之前,防火墙拒绝向网络服务器发送RST并使客户端保持无限.
以下是整个wireshark跟踪,其中包含来自防火墙两侧的数据包. 192.168.126.161是客户端的私有NAT’et IP地址. 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
根据这个chart,我一直在挖掘和记录数据包遍历,似乎最后一个传入的数据包2133超过了原始的PREROUTING,conntrack,mangle-PREROUTING但后来丢失了.我的iptables中没有REJECT规则,我记录了所有DROP规则,但没有一个显示数据包2133丢失的位置.
我很乐意在传入的过滤器上使用TRACE目标,但不幸的是,ubuntu 8.04不附带TRACE目标的支持.
因此,我认为某些内部隐式路由/ conntrack / mangling规则适用于某种原因会重置连接.也许流量会触发一些DOS保护,但我不知道在哪里配置/分析它.最令人沮丧的是,数据包被拒绝,没有任何记录……
同样请求此文件100%来自Windows主机,但它在某些Linux主机上失败,99.9%的请求通过,但有时数据包的时间会在我们的防火墙中触发此行为.
编辑
好的,现在我已经在iptables中添加了大量的日志记录,看起来好像发生了以下情况(仍然不知道为什么!)
对于成功遍历防火墙的数据包,将执行以下步骤,表/步参考自here
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
奇怪的是,步骤5中的分组2133的路由决定现在不同于其他分组的路由决定.在分析有效的请求时,例如不会卡住,即使最后一个FIN也能正确路由.它似乎是内核中的一个错误,或者路由决策在某种程度上是有状态的.
编辑
可能导致这些问题的一件事是以下事实:流量在防火墙和本地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
我们的fw外部IP再次被10.1.1.1取代,NAT网络外的网络服务器的ip被替换为172.16.1.2
编辑突发新闻!
好的最后一次尝试是DROP RST数据包,非常非常有趣,我添加了一个iptables规则,该规则删除了所有RST数据包,这些数据包都是我们在请求文件时遇到问题的网络服务器.然后它工作,例如上面的日志中的最后一个FIN,ACK,PSH数据包2133被丢弃,但是由于RST被丢弃,网络服务器有时间获得所有ACK的蚂蚁然后决定再次重发最后一个数据包,包2133,现在它通过防火墙,因为对战模块现在已经看到ACK从客户端返回并允许最后的ACK,FIN数据包和最终有效载荷.
所以这肯定是一个时间/窗口问题,这个特定的文件,来自客户端的ACK的时间,触发conntrack中的一些东西拒绝来自网络服务器的最终数据包.
到目前为止,谷歌搜索和阅读内核文件显示没有任何可能导致此行为,下一步将是读取路由/ conntrack模块的内核源代码.
问题解决了
好吧,至少现在我们确切知道发生了什么,并有一个解决问题的解决方法.
谢尔盖指出非常有价值的-m状态 – 状态INVALID匹配规则在调试中有很多帮助,我现在意识到没有明确的INVALID数据包规则的iptables设置不完整,所以有时似乎会发生奇怪的行为.
当启用在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再次是外部Web服务器(行为不正确),10.1.1.1是防火墙的外部地址.
在Web服务器上比客户端在接收窗口(跟踪连接的全状态,并验证这一点)发布的电线推动更多的数据,似乎它是当FIN数据包到达该连接跟踪捞出,因为接收窗口实际上是超出了很多早.
我认为这可能是由于网络服务器上的网卡中的TCP卸载不正确造成的.当我开始分析这个时,我在网络服务器上进行了捕获,根据tcpdump / wireshark跟踪,jumbo帧由内核中的TCP层写入,然后由网卡分割成MTU = 1500的较小帧.显然,这需要在网络服务器中得到解决,因为发送比接收者在其接收窗口中有广告的数据更多的TCP行为是不正确的.
Polynomial和Sergey都提供了宝贵的意见,但谢尔盖向我指出了conntrack / NAT模块关于数据包遍历的确切行为.
如果你的有问题的数据包真的标记为INVALID,添加iptables -I INPUT -m state –state INVALID -j DROP可能会解决问题(破坏的数据包不会到达本地进程,也不会导致RST响应,然后TCP将在超时后从丢失的数据包中恢复.然后,您可以尝试进一步调试问题,如http://www.spinics.net/lists/netfilter/msg51411.html中所述:
echo 255 >/proc/sys/net/netfilter/nf_conntrack_log_invalid
(在这种特殊情况下,问题是由路径上的某些网络硬件损坏引起的,可能与某些TCP校验和卸载故障相结合.)