NAT 路由器后面的 Web 服务器无法访问

NAT 路由器后面的 Web 服务器无法访问

我在家里运行的一台小型服务器遇到了一个神秘的问题,它位于 NAT 路由器后面。我在那里运行了几个 Web 和其他服务,我也可以通过端口转发从 LAN 外部访问它们。几天以来,我无法再访问 Web 服务器(无论是通过端口 80 还是 443)。但只能从外部LAN!从内部,我仍然可以毫无问题地访问。SSH 仍然可以从外部工作,尽管是在非标准端口上。

因此,我进行了 Wireshark 跟踪,其中 LAN 外的浏览器尝试访问服务器。为了便于阅读和匿名,我将服务器 IP 地址更改为 ssss,将浏览器 IP 地址更改为 bbbb

No.  Time      Source    Destination  Protocol Length Info
1    0.000000  b.b.b.b   s.s.s.s      TCP      66     59468 → 80 [SYN] Seq=0 Win=8192 Len=0 MSS=1460 WS=256 SACK_PERM=1
2    0.022883  s.s.s.s   b.b.b.b      TCP      66     80 → 59468 [SYN, ACK] Seq=0 Ack=1 Win=29200 Len=0 MSS=1380 SACK_PERM=1 WS=128
3    0.022949  b.b.b.b   s.s.s.s      TCP      54     59468 → 80 [ACK] Seq=1 Ack=1 Win=66048 Len=0
4    0.025405  b.b.b.b   s.s.s.s      HTTP     294    GET / HTTP/1.0 
5    0.026677  s.s.s.s   b.b.b.b      HTTP     666    HTTP/1.1 403 Forbidden  (text/html)
6    0.026678  s.s.s.s   b.b.b.b      TCP      54     80 → 59468 [FIN, ACK] Seq=613 Ack=241 Win=0 Len=0
7    0.026678  s.s.s.s   b.b.b.b      TCP      54     80 → 59468 [RST, ACK] Seq=614 Ack=241 Win=0 Len=0

TCP 连接已正确建立。然后浏览器发送 HTTP GET 请求并收到“403 Forbidden”响应。此外,几乎同时地通过 HTTP 响应消息,它会收到 FIN 和 RST 消息!

在服务器端我对相同的通信进行了 tcpdump:

$ sudo tcpdump -n port 80 or port 443
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
16:53:26.625013 IP b.b.b.b.59468 > s.s.s.s.80: Flags [S], seq 2382139585, win 8192, options [mss 1380,nop,wscale 8,nop,nop,sackOK], length 0
16:53:26.625131 IP s.s.s.s.80 > b.b.b.b.59468: Flags [S.], seq 1966829679, ack 2382139586, win 29200, options [mss 1460,nop,nop,sackOK,nop,wscale 7], length 0
16:53:26.647631 IP b.b.b.b.59468 > s.s.s.s.80: Flags [.], ack 1, win 258, length 0
16:53:26.650205 IP b.b.b.b.59468 > s.s.s.s.80: Flags [R.], seq 1, ack 1, win 258, length 0

这里,TCP 连接建立(前三个数据包)仍然正常。但是 HTTP 消息到底在哪里呢?既没有请求也没有响应?!发生了什么?为什么服务器会立即用 RST 数据包关闭连接?

起初我怀疑 Apache 存在一些配置错误(我有时会在不知道自己在做什么的情况下更改那里的内容)。所以我关闭了 Apache 并启动了一个 Python SimpleHTTPServer 脚本。Wireshark 和 tcpdump 跟踪结果基本相同,但现在至少从 Python 脚本中得到了一些错误输出:

----------------------------------------
Exception happened during processing of request from ('b.b.b.b', 59468)
Traceback (most recent call last):
  File "/usr/lib/python2.7/SocketServer.py", line 295, in _handle_request_noblock
    self.process_request(request, client_address)
  File "/usr/lib/python2.7/SocketServer.py", line 321, in process_request
    self.finish_request(request, client_address)
  File "/usr/lib/python2.7/SocketServer.py", line 334, in finish_request
    self.RequestHandlerClass(request, client_address, self)
  File "/usr/lib/python2.7/SocketServer.py", line 655, in __init__
    self.handle()
  File "/usr/lib/python2.7/BaseHTTPServer.py", line 340, in handle
    self.handle_one_request()
  File "/usr/lib/python2.7/BaseHTTPServer.py", line 310, in handle_one_request
    self.raw_requestline = self.rfile.readline(65537)
  File "/usr/lib/python2.7/socket.py", line 476, in readline
    data = self._sock.recv(self._rbufsize)
error: [Errno 104] Connection reset by peer
----------------------------------------

但这并没有给我带来任何帮助。有人知道这一切的原因是什么吗?

答案1

感谢您发送捕获文件。

您的客户端和服务器之间有防火墙或某种中间件(可能是 Cisco ASA),它们会拦截您的 Web 流量并生成 403 消息和 RST 数据包。原因如下:

  1. 客户端和服务器之间的 TCP 三次握手成功完成。往返时间约为30毫秒. 到目前为止一切都很好。
  2. 客户端向服务器发送 HTTP GET 请求。
  3. 403 Forbidden 消息被发送回客户端2毫秒请求发送后远的速度太快,不可能来自实际服务器。从服务器捕获的流量也没有显示任何 HTTP 请求的迹象。两个设备之间的某个设备生成了此 403

    请注意 403 的措辞:

    您正在尝试访问被禁止的站点。

    有关详细信息,请咨询您的系统管理员

    这不是标准的 Apache 403,通过快速 Google,我可以看到对类似消息的引用Cisco ASA 讨论主题我还可以看到你捕获的 403 的源 MAC 确实是 Cisco 设备。

  4. 客户端和服务器都会收到一个 RST 数据包,以强制关闭连接。请注意,每个 RST 数据包的源 IP 都是另一台设备的源 IP。这两台设备之间的某个东西向双方发送了一个伪造的 RST 数据包,声称来自对方。

您究竟在哪里进行外部测试?也许是通过公司网络?

答案2

您在问题中说,在运行 Apache 时您会收到“403 Forbidden”消息。

该消息由 Apache 生成,因此您的请求和响应似乎正在被您的网络正确处理。

我将重点关注 Apache 配置。您如何配置服务器?如果通过 IP 地址,您需要确保 Apache 知道它应该响应本地私有 IP 和您的公共 IP。您可以发布您的 httpd.conf 和 sites-enabled 目录中的文件吗?

相关内容