明明在自己电脑上能打开,发给别人却打不开——这是每个自建网站的新手都会遇到的灵魂拷问。
别慌,99% 的情况不是你的代码有问题,而是网络层面的几个小开关没打开。下面从最常见到最隐蔽,一步步排查。
1. 你绑定了 127.0.0.1,而不是 0.0.0.0
这是最最常见的坑。
# ❌ 这样写,只有本机才能访问
app.run(host='127.0.0.1', port=5000)
# ✅ 这样写,局域网内所有设备都能访问
app.run(host='0.0.0.0', port=5000)127.0.0.1 是本地回环地址——相当于一扇门只朝向屋里,外面的人根本找不到。0.0.0.0 则监听所有网络接口,包括局域网 IP。
同理:
# ❌ 只监听 localhost
python -m http.server 8000
# ✅ 监听所有接口
python -m http.server 8000 --bind 0.0.0.0验证方法
在本机用 localhost 和 局域网 IP 分别访问:
curl http://localhost:8000 # ✅ 应该正常
curl http://192.168.1.100:8000 # ❌ 如果连不上 → 绑定问题如果能通过 localhost 访问但不能通过局域网 IP 访问,就是你绑定了 127.0.0.1。
2. 防火墙拦住了端口
即使你绑定了 0.0.0.0,系统防火墙可能默认拦截非授信端口。
Linux(iptables / firewalld)
# 查看防火墙状态
sudo systemctl status firewalld
# 放行指定端口(以 8000 为例)
sudo firewall-cmd --add-port=8000/tcp --permanent
sudo firewall-cmd --reload
# 或者临时关闭防火墙测试(注意安全!)
sudo systemctl stop firewalldLinux(ufw)
sudo ufw allow 8000/tcp
sudo ufw reloadWindows 防火墙
控制面板 → Windows Defender 防火墙 → 高级设置 → 入站规则 → 新建规则 → 端口 → 输入你的端口号 → 允许连接。
验证方法
在本机用 nc 或 telnet 测试端口是否开放:
nc -zv 192.168.1.100 8000如果本机能连上但外网连不上,说明问题出在更上层(路由器或 ISP)。
3. 路由器没做端口转发
你的服务器在局域网内(比如 IP 192.168.1.100),外部请求无法直接到达局域网内部。需要在路由器上设置 端口转发(Port Forwarding):
- 登录路由器管理后台(通常是
192.168.1.1或192.168.0.1) - 找到「端口转发」或「虚拟服务器」选项
- 添加规则:
- 外部端口:80(或你用的端口)
- 内部 IP:你的服务器局域网 IP(如
192.168.1.100) - 内部端口:你的服务端口
- 协议:TCP
⚠️ 运营商可能屏蔽 80/443 等常见端口,可以换成高位端口(如 8080、8443、30000+),配合域名解析使用。
验证方法
在局域网外(比如用手机 4G 断掉 Wi-Fi)访问 你的公网IP:端口。如果打不开,大概率是端口转发没生效。
4. 你没有公网 IP
家庭宽带默认使用 NAT(网络地址转换),多台设备共享一个公网 IP。查询你的公网 IP:
curl ifconfig.me然后在局域网内访问 公网IP:端口:
- 如果在局域网内能访问这个公网 IP → 你有公网 IP ✅
- 如果打不开 → 你的 IP 可能是 CGNAT(运营商级 NAT),即多个用户共享一个公网 IP
确认是否 CGNAT
查看路由器 WAN 口 IP,和 ifconfig.me 获取的 IP 对比:
- 一致 → 你有独立公网 IP ✅
- 不一致 → 你处于 CGNAT 下 ❌
解决方案
- 打电话给运营商要求改为公网 IP(通常可以免费申请,就说家里要装监控)
- 或者使用 内网穿透(见下文第 6 点)
5. 运营商屏蔽了端口
电信、联通、移动会屏蔽家庭宽带的 80、443、25 等常用端口,防止私自搭建网站。
验证方法
尝试使用高位端口(50000+),如果高位端口可用而 80/443 不可用,就是被运营商屏蔽了。
解决方案:
- 服务监听高位端口,通过 反向代理(Nginx/Caddy)将域名指向高位端口
- 或者用 Cloudflare Tunnel(见下文)
6. 终极方案:内网穿透
如果没有公网 IP,或者不想折腾路由器,用内网穿透是最省心的方案。
frp(推荐)
在有公网 IP 的服务器上部署 frp 服务端,内网机器连接上去:
# frpc.ini(内网机器配置)
[common]
server_addr = 你的公网服务器IP
server_port = 7000
[web]
type = tcp
local_ip = 127.0.0.1
local_port = 8000
remote_port = 8000Cloudflare Tunnel(免费且无需公网 IP)
# 安装 cloudflared
wget https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64
# 登录并创建隧道
cloudflared tunnel login
cloudflared tunnel create my-tunnel
# 配置域名指向本地服务
cloudflared tunnel route dns my-tunnel your-domain.com
# 启动
cloudflared tunnel run my-tunnelNgrok(快速测试)
ngrok http 8000会生成一个 https://xxx.ngrok.io 的临时域名,直接发给别人就能访问。适合快速演示。
7. 另外两个容易忽略的原因
排查到这里还是打不开,回头检查这两个「假故障」:
端口被别的程序占用了。 你以为服务起来了,其实端口被另一个进程占着(服务启动失败,或者跑到了别的端口上)。确认到底谁在监听:
sudo ss -tlnp | grep :8000如果看到的进程不是你启动的那个,换一个端口,或者把占用端口的程序停掉。
浏览器缓存骗了你。 你看到的「能打开」可能是缓存的旧页面 —— 尤其在改过端口、改过绑定地址之后。用无痕窗口打开,或者干脆用手机流量网络再试一次,就能排除这一项。
8. 排查流程图
网站打不开
│
├─ 本机能访问吗?
│ ├─ 否 → 服务没启动 / 端口错了 / 绑定 127.0.0.1 ← 回第 1 点
│ └─ 是
│ │
├─ 同局域网能访问吗?
│ ├─ 否 → 防火墙拦截 ← 回第 2 点
│ └─ 是
│ │
├─ 外网能访问吗?
│ ├─ 否 → 有公网 IP 吗?
│ │ ├─ 有 → 端口转发没配 / 运营商封端口 ← 回第 3、5 点
│ │ └─ 无 → CGNAT / 内网穿透 ← 回第 4、6 点
│ └─ 是 → 🎉 恭喜,网站已经正常对外服务了!总结
| 问题 | 表现 | 解决 |
|---|---|---|
| 绑定 127.0.0.1 | 本机能访问,局域网内不能 | 改为 0.0.0.0 |
| 防火墙拦截 | 本机 telnet 不通端口 | 放行端口或关闭防火墙 |
| 未做端口转发 | 外网无法访问内网 IP | 路由器设置端口转发 |
| 没有公网 IP | 公网 IP 和路由器 WAN IP 不一致 | 申请公网 IP 或用内网穿透 |
| 运营商封端口 | 80/443 不通,高位端口可用 | 换高位端口 + 反向代理 |
| 端口被别的程序占用 | 服务启动失败,或访问到别的程序 | sudo ss -tlnp \| grep :<端口> 查占用进程,换端口 |
| 浏览器缓存了旧页面 | 你以为能访问,别人访问不了 | 无痕窗口 / 换网络(如手机流量)再试 |
一句话总结:先确保绑定 0.0.0.0,再开防火墙,再做端口转发,没有公网 IP 就用内网穿透。按这个顺序走一遍,99% 的问题都能解决。