用 ss -lntp 或 netstat -lntp 看端口,几乎每条都写着 LISTEN,很多人却说不清这个状态到底代表什么、为什么端口明明是 LISTEN 但就是连不上。LISTEN 是 TCP 状态机里服务端"等待连接"的状态,它只能说明"有程序在这个端口上准备接受连接",并不能保证外部一定访问得到。
这篇文章先把 LISTEN 的含义、监听地址的各种写法讲透——0.0.0.0、127.0.0.1、::、具体网卡地址分别意味着什么,这是"本地能连、远程连不上"问题的根子。然后讲怎么正确查看监听列表、怎么区分本地测试和远程测试、怎么判断是程序没监听、监听了错地址还是被防火墙挡了。
文中会给出一张"监听正常但访问不通"的排查表,以及在不同发行版上配置服务监听地址的方法。涉及改监听地址、改防火墙的操作会给出风险提示和回滚方式,避免误操作导致服务不可达。
一、LISTEN 状态到底代表什么
TCP 是面向连接的协议,通信前要建立连接。服务端程序调用 socket() 创建套接字、bind() 绑定地址端口、listen() 进入监听状态,之后内核就会接受指向这个地址端口的连接请求。LISTEN 就是"套接字已经 bind 并 listen,可以接受连接但当前还没有建立起会话"的状态。
它和 ESTABLISHED 的区别很直观:LISTEN 是"门开着等客人",ESTABLISHED 是"客人已经进门在聊天"。一条 LISTEN 连接不会变成 ESTABLISHED,而是每次有新客户端连上来,内核就基于这个监听套接字派生出一条新的 ESTABLISHED 连接。所以你会看到:一个端口只有一条 LISTEN 记录,却可能同时挂着成千上万条 ESTABLISHED 记录,它们共用同一个本地端口。
LISTEN 状态能确认的事:有程序占用了这个端口,并且愿意接受 TCP 连接。LISTEN 状态不能确认的事:程序逻辑是否正常、防火墙是否放行、外部网络是否能路由过来、程序绑定的地址范围是不是外部可达——这些都要另外验证。这正是"端口 LISTEN 但连不上"的根源。
顺带说清 TCP 和 UDP 的区别:UDP 是无连接的,没有三次握手,所以 UDP 的 ss/netstat 输出里状态通常显示为 UNCONN(unconnected)而不是 LISTEN。看到 UDP 端口是 UNCONN 是正常的,不要误以为它没在监听。
二、监听地址的几种写法与含义
打开监听列表,最关键的一列是"Local Address",同一个端口绑到不同地址,可达范围完全不同:
| 监听地址写法 | 含义 | 谁能访问 |
|---|---|---|
0.0.0.0:80 |
监听所有 IPv4 接口 | 本机 + 所有能路由到的外部地址 |
127.0.0.1:8080 |
只监听本地回环 | 仅本机内部,外部一律不可达 |
192.168.1.10:3306 |
只监听某块网卡的具体 IP | 仅能路由到该 IP 的客户端 |
[::]:80 |
监听所有 IPv6 接口(部分系统同时接管 IPv4) | IPv6 及按配置的 IPv4 客户端 |
[::1]:8080 |
只监听 IPv6 回环 | 仅本机 IPv6 回环 |
最常见的"坑"就是 127.0.0.1 和 0.0.0.0 的区别。很多服务(数据库、缓存、管理后台)为了安全默认只绑 127.0.0.1,这样外部无论如何都连不上——这不是故障,是设计。比如 MySQL 默认 bind-address = 127.0.0.1,Redis 默认 bind 127.0.0.1。如果你确实需要远程访问,得改配置让它们监听 0.0.0.0 或具体网卡地址,同时务必配套做访问控制。
0.0.0.0 表示监听本机所有 IPv4 网卡,不管你有几块网卡、几个 IP,它都接。:: 是 IPv6 的对应写法,在不少发行版上它还会同时接受 IPv4 连接(受 net.ipv6.bindv6only 影响)。要特别小心的是:把管理端口从 127.0.0.1 改成 0.0.0.0 意味着把服务暴露到了网络上,这是"监听地址改错导致被入侵"的经典事故。
三、查看监听状态的正确命令
# 最常用:-l 只显示监听,-n 数字显示端口,-t TCP,-p 显示进程
sudo ss -lntp
# 看 UDP 监听(状态为 UNCONN)
sudo ss -lnup
# 同时看 TCP + UDP
sudo ss -lntup
# 老工具 netstat(需 net-tools,老系统兼容用)
# RHEL/CentOS/Rocky:
yum install net-tools
# Debian/Ubuntu:
apt install net-tools
sudo netstat -lntp
# 统计本机一共监听了多少端口
sudo ss -lnt | tail -n +2 | wc -l
# 查某个端口被谁监听
sudo ss -lntp | grep ':80 '
sudo lsof -i :80 # 需 lsof,RHEL 用 yum install lsof,Debian 用 apt install lsof
sudo fuser 80/tcp
ss -lntp 的完整输出示例及每列含义:
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 511 0.0.0.0:80 0.0.0.0:* users:(("nginx",pid=1234,fd=6))
LISTEN 0 128 127.0.0.1:3306 0.0.0.0:* users:(("mysqld",pid=2345,fd=21))
LISTEN 0 511 [::]:443 [::]:* users:(("nginx",pid=1234,fd=7))
注意 LISTEN 行里 Recv-Q 和 Send-Q 的特殊含义:对监听套接字,Recv-Q 是当前已完成三次握手、等待应用 accept() 的连接数,Send-Q 是全连接队列的上限(backlog)。这两个值帮我们判断"连接已经到达内核、但应用来不及 accept"的情况——Recv-Q 长期接近 Send-Q 就说明应用处理太慢。这一点是判断"端口 LISTEN 但连接超时"的重要线索。
四、本地测试与远程测试的区别
判断端口通不通,一定要分清"在哪测"。本地测试通不代表远程通,远程不通也不代表服务有问题。
本地测试(在服务器本机上执行):
# 用 nc 测端口是否能连(RHEL 用 yum install nmap-ncat,Debian 用 apt install netcat-openbsd)
nc -zv 127.0.0.1 80
nc -zv 192.168.1.10 80
# 用 curl 测 HTTP 服务
curl -v http://127.0.0.1:80/
# 用 telnet(RHEL 用 yum install telnet,Debian 用 apt install telnet)
telnet 127.0.0.1 80
# 快速扫本机常用端口
ss -lnt | awk 'NR>1 {print $4}'
本地测试用 127.0.0.1 能通,只说明服务在本机回环上正常。要测"外部地址是否可达",本机应该用本机的真实网卡 IP(如 192.168.1.10)而不是回环地址去测。如果 nc -zv 127.0.0.1 80 通、nc -zv 192.168.1.10 80 不通,那说明服务只绑了回环,或者绑定的网卡不对。
远程测试(从另一台机器执行):
# 从客户端测服务器真实 IP 的端口
nc -zv 203.0.113.10 80
curl -v http://203.0.113.10/
# 用 nmap 扫端口状态(RHEL 用 yum install nmap,Debian 用 apt install nmap)
nmap -p 80,443 203.0.113.10
# 用 telnet 看是"连接被拒绝"还是"超时"
telnet 203.0.113.10 80
远程测试的结果能区分故障类型:"Connection refused(连接被拒绝)"通常意味着目标主机可达但该端口没有程序监听(或监听地址不接收该来源),内核回了一个 RST;"Connection timed out(超时无响应)"则通常是中间有防火墙静默丢包,或者目标地址本身不可达。这两种报错指向完全不同的排查方向,见下节表格。
五、"监听正常但访问不通"排查表
| 现象 | 可能原因 | 验证方法 | 处理方向 |
|---|---|---|---|
| 本地 127.0.0.1 通,远程不通 | 服务只绑了回环地址 | ss -lntp 看 Local Address |
改监听地址为 0.0.0.0 或网卡 IP |
| 远程 refused | 端口无监听/绑错地址 | 远程 nc -zv 报 refused |
确认服务在跑、监听地址正确 |
| 远程 timeout | 防火墙静默 DROP | 远程 nc 无响应或极慢 |
检查 firewalld/iptables/云安全组 |
| 本机 IP 不通、回环通 | 只绑回环 或 本机防火墙拦 | 本机 nc -zv <本机IP> |
改绑定 + 放行本机防火墙 |
| 时通时不通 | 后端多实例监听不一致 | 多台后端都查 ss -lntp |
统一各实例监听配置 |
| IPv6 通、IPv4 不通 | 服务绑在 :: 上仅 IPv6 |
ss -lnt 看是 :: 还是 0.0.0.0 |
显式绑 0.0.0.0 或双栈 |
防火墙是"timeout"类问题的头号嫌疑。RHEL/CentOS/Rocky 常用 firewalld,Debian/Ubuntu 常用 ufw 或直接 iptables:
# firewalld(RHEL 系)
firewall-cmd --list-all
firewall-cmd --list-ports
# 放行 80(临时,重启失效)
firewall-cmd --add-port=80/tcp
# 永久放行
firewall-cmd --permanent --add-port=80/tcp && firewall-cmd --reload
# ufw(Ubuntu/Debian)
ufw status verbose
ufw allow 80/tcp
# iptables 直接看(两系通用)
iptables -L -n --line-numbers
iptables -L -n -t nat
别忘了云服务器还有一层"安全组"或"网络 ACL",它不在操作系统里,iptables 看不到。如果本机防火墙已放行但仍 timeout,要去云控制台确认安全组入方向规则放行了对应端口。这是"本地一切正常、外网就是连不上"的常见盲区。
六、配置监听地址的实操
当确认需要让服务对外监听时,改的是"服务的配置",不是系统参数。以几个常见服务为例:
# Nginx:/etc/nginx/nginx.conf 或 conf.d 下站点配置
# 只监听本机:
# listen 127.0.0.1:80;
# 监听所有地址:
# listen 80; # 等价于 0.0.0.0:80
# listen [::]:80;
nginx -t && systemctl reload nginx
# MySQL/MariaDB:/etc/my.cnf 或 /etc/mysql/mysql.conf.d/mysqld.cnf
# bind-address = 127.0.0.1 # 仅本机
# bind-address = 0.0.0.0 # 所有地址(务必配合授权与防火墙)
systemctl restart mysqld
# Redis:/etc/redis.conf
# bind 127.0.0.1 # 仅本机
# bind 0.0.0.0 # 所有地址(强烈建议同时设密码 + 防火墙)
systemctl restart redis
# 反查某个监听端口属于哪个程序
sudo ss -lntp | grep ':8080 '
sudo lsof -i :8080
对于自己写的程序,监听地址通常在配置文件或启动参数里,比如常见框架的 host/bind/listen 字段,改成 0.0.0.0 或指定网卡 IP 即可。但要注意:把端口从回环改成 0.0.0.0 等于把它暴露到网络,对于数据库、缓存、管理后台这类不该公网暴露的服务,绝不能图省事绑 0.0.0.0。 正确做法是绑内网网卡地址,或用 SSH 隧道、跳板机访问。
风险提示与回滚:改监听地址前先备份配置文件(如 cp /etc/redis.conf /etc/redis.conf.bak),改完用 ss -lntp 确认新地址生效、从预期来源做一次连通性测试,再观察业务。若导致服务不可达,把配置改回原值并重启即可回滚。改防火墙规则时建议先用 --add-port(firewalld 的 runtime)测试,确认无误后再写 --permanent;iptables 用 iptables-save > /root/iptables.bak 先留底。
常见问题
Q:端口是 LISTEN 就一定能连上吗?
不一定。LISTEN 只说明有程序在本机绑定了该端口并等待连接。能不能连上还取决于:绑定的地址是否包含客户端的可达范围、本机防火墙是否放行、云安全组是否放行、中间网络是否可达。这些任何一环有问题都会导致"LISTEN 但连不上"。
Q:0.0.0.0 和 127.0.0.1 监听到底差在哪?
0.0.0.0 监听所有 IPv4 网卡上的这个端口,外部可达;127.0.0.1 只监听回环,只有本机进程能连。数据库、缓存类服务默认绑回环是出于安全考虑,需要远程访问时要显式改配置并加访问控制。
Q:远程测试报 "Connection refused" 和 "timeout" 有什么区别?
refused 表示目标主机可达、但该端口没有程序接收连接(内核直接回了 RST),常见于服务没起或绑错地址;timeout 表示发出的包没有得到任何回应,通常是中间防火墙静默丢包或地址不可达。前者查服务,后者查防火墙和网络。
Q:UDP 端口显示 UNCONN 是不是没在监听?
不是。UDP 无连接,ss/netstat 对 UDP 显示 UNCONN 是正常的,表示套接字已绑定但无连接状态。要测试 UDP 服务是否工作,得用对应协议去实际收发,而不是看状态。
Q:本机 nc -zv <本机IP> 不通,是不是服务有问题?
先看监听地址是不是 0.0.0.0。如果服务绑的是 127.0.0.1,用本机真实 IP 去连是不通的,这是正常的。如果服务绑了 0.0.0.0 但用真实 IP 连不上,则要检查本机 iptables/firewalld 是否拦截了入向流量。
总结
- LISTEN 表示服务端套接字已
bind并listen、等待接受连接,它只保证"本机有程序盯着这个端口",不保证外部可达。 - 监听地址决定可达范围:
0.0.0.0对外全开、127.0.0.1仅本机、具体网卡 IP 限定来源;大量"本地通远程不通"都源于服务只绑了回环。 - 查看监听用
sudo ss -lntp(TCP)和sudo ss -lnup(UDP),LISTEN 行的 Recv-Q 是等待 accept 的连接数、Send-Q 是队列上限,可用于判断应用是否处理不过来。 - 测试要分本地和远程:本地测真实网卡 IP 而非只看回环,远程用
nc -zv/curl测;refused 查服务绑地址,timeout 查防火墙与安全组。 - 改监听地址前先备份配置、确认绑定目标网卡、配套访问控制和防火墙放行;云环境别忘安全组这一层,改完全量验证后再固化配置。
企业QQ咨询




