为什么我们的防火墙(Ubuntu 8.04)拒绝带有RST的最终数据包(FIN,ACK,PSH)


20

背景技术长期以来,我们的防火墙一直存在问题,有时防火墙会将HTTP请求的部分挂起挂起,直到TCP超时为止。

在防火墙上跟踪流量之后,我注意到它仅在某些定时条件下发生,例如,当Web服务器在客户端已在有效负载上发送其第二个ACK之前发送了整个响应时。[SYN,SYN / ACK,ACK]已被交换,REQUEST已发送并被ACK',并且第一个RESPONSE数据包已被接收并ACK',然后网络服务器将其余的响应主体发送到一个镜头中(8个数据包)包括最后一个FIN,PSH),并且在客户端对其中任何一个进行确认之前,带有RST的Firewall REJECTS指向Web服务器,并保持客户端无限挂起。

这是整个wireshark跟踪以及来自防火墙双方的数据包。192.168.126.161是客户端的专用NAT'et IP地址。172.16.1.2是Web服务器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经过了raw-PREROUTING,conntrack,mangle-PREROUTING,但随后丢失了。我的iptables中没有REJECT规则,我记录了所有DROP规则,但没有一个显示包2133丢失的位置。

我很想在传入的过滤器上使用TRACE目标,但是不幸的是ubuntu 8.04并未附带对TRACE目标的支持。

因此,我认为某些内部隐式路由/ conntrack /篡改规则适用于出于某种原因而重置连接的情况。也许流量触发了一些DOS保护,但是我不知道在哪里进行配置/分析。最令人沮丧的是,数据包被拒绝并且没有任何记录...

同样,从Windows主机请求此文件的工作率为100%,但在某些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

奇怪的是,现在步骤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网络之外的Web服务器的IP被172.16.1.2替换了

编辑最新消息!

好的,最后一次尝试是丢弃RST数据包,这非常有趣,我添加了一个iptables规则,该规则将所有发往目标文件的Web服务器的RST数据包都丢弃了。然后工作,例如,上面日志中的最后一个FIN,ACK,PSH数据包2133被丢弃,但是由于RST被丢弃,因此网络服务器有时间获取所有ACK的蚂蚁,然后决定再次重传最后一个数据包2133,现在,它通过防火墙,因为contrack模块现在已经看到ACK从客户端返回,并允许最后一个ACK,FIN数据包具有最终有效负载。

因此,这绝对是一个时间/窗口问题,该特定文件以及来自客户端的ACK的时间会触发conntrack中的某些内容,从而拒绝来自Web服务器的最终数据包。

到目前为止,谷歌搜索和阅读内核文档不会发现任何会导致这种行为的内容,下一步将是阅读路由/ conntrack模块的内核源代码。

问题解决了

好吧,至少现在我们确切地知道会发生什么,并且有解决该问题的解决方法。

Sergey指出了非常有价值的-m状态--state 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服务器通过有线方式推送的数据比客户端在接收窗口中通告的数据更多(conntrack已处于满状态并进行验证),似乎是FIN数据包到达时conntrack失败了,因为接收窗口实际上超出了很多较早。

我认为这可能是由于Web服务器上网卡中TCP错误卸载所引起的。当我开始对此进行分析时,我在网络服务器上进行了捕获,并根据tcpdump / wireshark跟踪,将巨型帧由内核中的TCP层写入,然后通过网卡将其分割为MTU = 1500的较小帧。因此很显然,这需要在Web服务器中解决,因为发送与接收者在其接收窗口中有广告的数据相比更多的数据是不正确的TCP行为。

多项式和Sergey都提供了有价值的输入,但是Sergey向我指出了conntrack / NAT模块在数据包遍历方面的确切行为。


您的iptables配置中是否有任何REJECT语句?如果是这样,请查看是否可以使用日志记录确定它是哪个规则。
Ladadadada 2011年

不,没有拒绝规则,似乎拒绝发生在路由决策过程中发生在iptablesm之外
ernelli 2011年

防火墙是否可能不支持滑动窗口?来自工作中的客户的捕获与该捕获相比如何?
joeqwerty 2011年

当它工作时,除了将所有数据包正确转发到客户端并且不返回任何RST数据包之外,客户端都会在服务器发送最终FIN之前发送ACK。我检查了一个大文件(300k)的转储,然后没有问题。来自小文件的跟踪也可以使用,带有FIN的最终数据包将被转发。您能否详细说明“防火墙不支持滑动窗口”
ernelli

您能否扩展路由器和实验室客户端之间的连接?您在60和126上具有/ 24子网掩码,因此尚不清楚实验室客户端如何发送流量?他们的网络掩码不是/ 24吗?某种代理arp正在进行吗?在eth0:1上是否有126.0 / 24的别名?
多项式

Answers:


9

http://www.spinics.net/lists/netfilter/msg51408.html上描述了类似的情况:一些本应由NAT处理的数据包以某种方式被标记为INVALID而不是ESTABLISHED,然后进入INPUT链。您应该添加一些规则以-m state --state INVALID进行检查,并且http://www.spinics.net/lists/netfilter/msg51409.html上的答案建议应始终丢弃这样的INVALID数据包,因为对它们未正确执行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校验和卸载损坏有关。)


4

我已经在其他类型的防火墙上看到了这种行为,并且这种行为是如此的相同,以至于我想将它扔在那里。

我遇到的问题是防火墙正在与机箱上的临时端口NAT进入同一空间。如果两者发生冲突,这将导致这种确切的行为,因为内核现在假定连接是为本地计算机设计的。为此,您可以检查几件事。首先,您是否在iptables中指定出站端口配置(使用--to-ports)?或者您是否在机器上修改了临时端口范围:

$ cat /proc/sys/net/ipv4/ip_local_port_range

为了进行诊断,您可以设置捕获并查看是否使用相同的外部fw ip在RST之前的3 * MSL时间(我认为是180s)内看到端口组合。

尽管我不确定这是否是答案,但是如果我处于这种情况,我会先排除掉它,然后再考虑其他几件事。

这容易复制吗?是否可以从防火墙框中捕获更多诊断信息并查看是否发生问题?我会尝试捕获:

$ netstat -anp
$ cat /proc/net/ip_conntrack

尝试复制并查看端口本地是否绑定了某些东西,以及在出现问题期间假面舞会表是什么样子,大约每秒钟进行一次。

如果您对RST出站进行防火墙保护,内部客户端的最终ACK是否会导致连接成功?

最后一件事,您是否正在查看所有日志?您已经检查过dmesg吗?您是否已将syslog配置中防火墙框中的*。*设置为文件以确保?

让我知道你发现了什么!非常感谢您在问题中提供的大量信息,谢谢。


感谢您的努力,我可以100%重现该错误,除少数例外外,所有通过防火墙的请求均有效。那些不工作的人似乎遇到了精确的尺寸/时间问题。我可以通过防火墙将多个Wireshark跟踪添加到同一客户端/ Web服务器之间,以处理更大或更小的请求,这些都可以工作,但是上面的跟踪是被卡住的。我在上面添加了新信息,可能会在此问题上有所作为。
ernelli 2011年

/ proc / sys / net / ipv4 / ip_local_port_range设置为[32768 61000] netstat不显示任何本地绑定的端口。ip_conntrack显示已建立连接,例如,认为自从最后一个FIN尚未转发到客户端以来,该连接仍处于打开状态。状态为数据包= 10字节= 12084 [已确认]标记= 0 secmark = 0使用=
ernelli 2011年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.