【无标题】

前言:一个让人抓狂的"灵异事件"

最近,新配置了一台联通云的 Ubuntu 22.04 服务器。本来高高兴兴地部署好了 Nginx,结果在本地电脑用浏览器访问公网 IP(http://***.***.***.***/)时,却怎么也打不开,浏览器一直无情地提示:"已重置连接(Connection reset)"。

但神奇的是,当我在本地使用 nc(Netcat)命令去测试端口连通性时,发现底层 TCP 握手又是完全正常的。既然网络是通的,为什么浏览器就是连不上呢?今天就来和大家聊聊,我是如何一步步揪出这个"幕后黑手"的。

第一步:排查自己的服务器,确认不是内部问题

遇到外网访问不了,第一反应肯定是检查自己服务器的配置是不是搞错了。我按部就班地做了以下三件事:

  1. 查云平台安全组:登录联通云控制台,反反复复确认了入方向的安全组规则,确定 80 端口确实是放行的。

  2. 查系统自带防火墙:为了防止被系统自带的 UFW 拦截,我敲了下面这条命令查看状态:

    复制代码
    # 看看防火墙到底拦没拦
    sudo ufw status verbose

    结果返回的是Status: inactive 说明我的ufw防火墙并没有启动,不是它的问题,并没有拦截 80 端口的流量。

  3. 查 Nginx 监听地址:有时候服务虽然启动了,但只允许本机访问。我用下面的命令确认了一下它是不是监听了所有网卡:

    bash 复制代码
    # 推荐用 ss 命令看端口监听情况
    sudo ss -tulnp | grep ':80'
    
    # 如果你的系统没有 ss,也可以用 netstat
    sudo netstat -tulnp | grep ':80'

    一看输出,Nginx 稳稳地监听在 0.0.0.0:80,代表对所有外部网络开放。

经过这一套"体检",我确信自己的服务器内部没有任何问题。那么,究竟是谁半路把数据包给劫持了?

第二步:本地 nc 探路,意外发现"敲门成功"

为了判断到底是网络断了还是服务器拒绝了请求,我决定从本地电脑发起探测。nc(Netcat)被称为网络工具里的"瑞士军刀",非常适合用来测试底层的 TCP 链路是否畅通。

如果你使用的是 Linux 或 macOS 系统,可以直接打开终端;如果是 Windows 用户,可以使用 PowerShell 或在安装了 Netcat 的环境下运行以下命令:

bash 复制代码
# -v 表示显示详细信息,-z 表示只扫描端口而不发送任何数据
nc -vz ***.***.***.*** 80

执行后,屏幕上很快返回了 Connection to ***.***.***.*** port 80 [tcp/http] succeeded!。这说明我的本地电脑和服务器之间的 TCP 三次握手是完全成功的,80 端口确确实实处于开放状态。

既然底层网络没问题,那为什么浏览器一发 HTTP 请求就被掐断呢?

第三步:服务端抓包,意外发现"毫无动静"

带着疑惑,我决定在服务器上开启 tcpdump 抓包,专门盯着 80 端口,看看有没有恶意的断开请求(RST 包)。刚开始因为语法写错报了好几次错,调整之后终于成功开启了监听:

bash 复制代码
# 抓取所有网卡上 80 端口的 TCP 流量,-nn 表示不解析主机名和端口名
sudo tcpdump -i any -nn port 80 and tcp

接着,我在本地电脑疯狂刷新浏览器发起请求。但是!服务器这边的抓包终端居然毫无反应,连个敲门砖(SYN 包)都没抓到

这个"毫无动静"的现象,反而成了最关键的线索。它直接证明了一件事:我的 HTTP 请求数据包,压根就没有进到这台服务器的操作系统里!

第四步:真相大白------未备案拦截机制

结合前面"内部全通、nc 能通、浏览器报错、抓包没记录"这几个特征,真凶终于浮出水面了:数据包在进入服务器之前,就被云平台底层的网关或者运营商的设备给悄悄拦截了。

原来,在国内的网络合规要求下,如果云服务器的公网 IP 还没有完成 ICP 备案,服务商就会在网络层自动掐断所有发往 80 和 443 端口的网页流量。同时,拦截设备还会向你的浏览器发送一个伪造的断开信号(RST 包),骗浏览器以为是服务器主动断开的,这就解释了为什么会弹出"已重置连接"。

第五步:换个端口,完美破局

为了验证我的猜想,我决定绕开 80 端口试试水。我把 Nginx 的默认监听端口改成了非标准的 8090,并在联通云控制台的安全组里顺手放行了 8090 端口。然后回到本地电脑,用浏览器的无痕模式访问 http://***.***.***.***:8090。唰的一下,熟悉的 Nginx 欢迎页面瞬间弹了出来!至此,案件完美告破。

附:修改 Nginx 端口的标准操作流程

如果你也遇到了类似的问题需要临时更换端口,可以参考以下完整步骤:

  1. 编辑配置文件:Ubuntu/Debian 系统的站点配置通常不在主文件里,而是存放在单独的目录中。你可以使用编辑器打开默认配置:

    bash 复制代码
    sudo nano /etc/nginx/sites-available/default
  2. 修改监听端口 :在文件中找到 server 块,将默认的 listen 80 default_server; 和对应的 IPv6 行修改为你期望的新端口号(例如 8090):

    nginx 复制代码
    server {
        listen 8090 default_server;
        listen [::]:8090 default_server;
        # ... 其他原有配置保持不变
    }
  3. 检查语法并重载:保存退出后,务必先验证配置是否有误,再重新加载服务使其生效:

    bash 复制代码
    sudo nginx -t
    sudo systemctl reload nginx
  4. 放行对应端口 :最后别忘了在操作系统防火墙(如 sudo ufw allow 8090/tcp)以及云平台的安全组入方向规则中,同步放开新的端口。

总结与避坑指南

这次折腾下来我发现,这根本不是服务器内部的故障,而是典型的合规性网络拦截。如果你也遇到了类似的问题,可以参考以下两条出路:

  1. 还在开发或测试阶段? 如果业务还没正式上线,可以直接使用像 8090、8080 这样的非标端口对外提供服务,不用备案也能畅通无阻。
  2. 准备正式对外开放? 如果希望用户直接输入网址就能访问(不带端口号),那就必须老老实实去云服务商控制台提交 ICP 备案申请。等管局审核通过后,底层的拦截策略自然就会解除了。

以后遇到"连接重置"别急着死磕服务器配置,先用 nc 探探路,再用抓包工具看看数据包有没有真正抵达主机,能帮你省下大把掉头发的时间!