路由器奇怪的bug

连接路由器的这个地址:http://192.168.1.1/userRpm/StatusRpm.htm被拒绝访问。此后路由器拒绝访问,即使换IP用另一台电脑也不行。为什么? 第二天看仍然这个问题。抓包发现,访问http://192.168.1.1,这边只发出一个SYN包,那边就回复RST。重启路由器方可。难道是路由器的防止DoS攻击?

继续研究,原来是我用Python的urllib2.urlopen打开路由器就会被Reset,Firefox,Wget和curl都是没问题的。经过抓包分析,发现urllib2的连接中,都没有提供Authorization内容,这应该是被路由器拒绝访问的原因。在Wireshark里面,用

ip.addr == 192.168.1.1 and !dns and http.user_agent matches "Python" and http.authbasic

过滤,得不到任何包。

curl发送的包:

Firefox发送的包:

w3m发送的包:

urllib2发送的包

HTTP的Basic Authorization方法,如果客户端直接连,而服务器需要认证,服务器就发回401错误(未认证),客户端提示用户名和密码来再次认证。可是用urllib2的时候,是直接写好认证信息来连接的。我以为是urllib2不支持Persistent Connection导致的呢,因为唯独urllib2发送的包里面有Connection: close的报头。我以前用老的路由器还可以的。我以为那时候的Python版本里面的urllib2没有这个问题呢,还下载的Python的源代码对比,2.3的版本里面确实没有明确指定要发送这个报头。

我插上老的路由器(TP-Link TL-R402)运行我的Python脚本,竟然又是好的。再换回新路由器(TP-Link WR740N),又拒绝了。那么问题只能定位到新路由器的HTTP Server的问题了,它不能正确处理urllib2的请求。如果用urllib2连接,在TCP握手的三个包之后,一个ACK,然后就是一个RST,总共5个包。之后无论用啥连就直接RST。正常情况在客户端GET之后,服务端应该返回401错误,然后客户端再请求认证。可是用别的客户端都可以正常认证,唯独用urllib2就不行。变态的路由器!!!下图前5个包是第一次连接的包,后面2个是重试的包: