端口是什么:Linux 服务如何监听端口
端口是服务器把进入的流量分派给正确服务的方式。学习用 ss 命令查看谁在监听,并区分本地端口和公网端口。
端口到底是什么
端口是一个数字,它让一台服务器可以同时运行许多服务,而它们的流量不会混在一起。您的 VPS 只有一个 IP 地址,但它可能同时运行一个 Web 服务器、一个 SSH 服务器和一个数据库。当一个数据包到达时,操作系统需要知道它是发给哪一个的。端口号就是答案。Web 流量走 443 端口,SSH 走 22 端口。IP 地址把数据包送到您的服务器;端口把它送到服务器上正确的那个程序。
端口是一个 16 位(bit)的数字:16 位可以表示 0 到 65535,而 0 是保留的,所以实际上端口的范围是 1 到 65535。低于 1024 的端口是“知名端口”(well-known ports),需要 root 权限才能打开,这就是标准服务都在那里的原因:22 用于 SSH,80 用于 HTTP,443 用于 HTTPS,53 用于 DNS。1024 以上的端口则可以由普通程序自由使用。
端口有两种,TCP 和 UDP,而其中一种里的某个端口号和另一种里相同的端口号是彼此独立的。TCP 是大多数服务使用的、基于连接的协议,比如 SSH、HTTP 和数据库。UDP 是无连接的,用于 DNS 和某些 VPN 之类的场景。当您在防火墙里开放一个端口时,通常会指明是哪一种,例如 22/tcp。
监听意味着有一个程序在某个端口上等待
一个想要接收连接的程序会请求内核在某个端口上“监听”(listen)。从那一刻起,这个端口就在这台机器上打开了,程序会应答到达该端口的任何内容,当然要受防火墙的约束。一个没有任何程序在监听的端口只会拒绝连接。所以在任何一次安全检查中,第一个问题都是:什么在监听,以及在哪里监听。
回答这个问题的命令是 ss:
sudo ss -tlnp这些参数的含义是:TCP(t)、只看监听中的套接字(l)、数字端口(n,这样您看到的是 22 而不是 ssh)、以及占用端口的进程(p)。一个典型的结果:
State Recv-Q Local Address:Port Process
LISTEN 0 0.0.0.0:22 sshd
LISTEN 0 127.0.0.1:5432 postgres
LISTEN 0 [::]:80 nginxProcess 这一列告诉您每个端口是由哪个程序占用的,您可以借此找出某个自己并不打算让它继续运行的东西。
Local Address 这一列才是关键
请仔细阅读每个端口前面的地址,因为它决定了谁能访问到这个服务。有三种情况您会不断遇到。
0.0.0.0:22 的意思是“在这台机器拥有的每一个 IPv4 地址上监听”,包括它的公网地址。在防火墙允许的前提下,这个服务可以通过 IPv4 从互联网访问到。
[::]:80 对 IPv6 来说是同样的意思:在每一个 IPv6 地址上监听,公网地址也包括在内。许多程序默认就绑定在这里,而且在 Linux 上,一个 :: 套接字往往同时也接受 IPv4。
127.0.0.1:5432 的意思是“只在环回地址(loopback)上监听”。127.0.0.1 是一台机器用来和自己通信的地址,从其他任何地方都无法路由到它。绑定在这里的服务只能从这台服务器自身访问到,永远无法从互联网访问,无论您的防火墙怎么设置。上面那行 Postgres 从设计上就是安全的。
由此可以直接得出一条实用规则:一个只被您自己的应用使用的数据库、缓存或管理面板,应该绑定到 127.0.0.1,而不是 0.0.0.0。如果它从不在公网地址上监听,那么攻击者就没有任何可以访问的东西。
监听不等于可访问
还有一个区别能省去很多困惑。一个端口在机器上处于打开状态(意思是有程序在监听),和这个端口从外部可访问(意思是防火墙允许它),是两回事。远程客户端要连接进来,这两者必须同时成立。
所以有两层控制。您通过设置每个服务的绑定地址,来决定什么在监听。您通过防火墙,来决定外部世界能访问到什么。一台管理良好的服务器两者都用:服务只在需要的地方绑定,而防火墙拒绝一切您没有明确允许的东西。用 ss 查看什么在监听是第一步;决定防火墙允许什么是第二步,这在 UFW 防火墙入门 中有讲解。
这里有一个会坑到人的细节。IPv4 和 IPv6 是相互独立的,一个只覆盖 IPv4 的防火墙会让那些 [::] 服务在 IPv6 上敞开着。这个具体的陷阱有它自己的一篇文章:IPv6 防火墙陷阱。
FAQ
怎么查看我的 Linux 服务器上开放了哪些端口?
TCP 运行 sudo ss -tlnp,UDP 运行 sudo ss -ulnp。这会列出每一个监听中的套接字、端口、它绑定到的本地地址,以及占用它的进程。请看 Local Address 这一列:0.0.0.0 或 [::] 表示服务对网络暴露,而 127.0.0.1 表示它只在机器自身上监听。
0.0.0.0 和 127.0.0.1 有什么区别?
0.0.0.0 表示“在所有 IPv4 地址上监听”,包括公网地址,所以这个服务可以从网络访问到。127.0.0.1 是环回地址,是机器用来和自己通信的地址,从其他任何地方都无法路由到它,所以绑定到它的服务只能在本地访问。请把内部服务绑定到 127.0.0.1,这样它们就永远不会被暴露。
一个服务要正常工作,我需要在防火墙里开放端口吗?
只有那些必须从其他机器访问的服务才需要。绑定到 127.0.0.1 的服务不需要任何防火墙规则,因为外部本来就无法访问它。位于 0.0.0.0 或 [::] 上的服务需要一条防火墙规则来放行流量,并且在您添加规则之前应该默认拒绝。
TCP 端口和 UDP 端口有什么区别?
TCP 是基于连接的,大多数服务都使用它,比如 SSH、Web 服务器和数据库。UDP 是无连接的,DNS 和某些 VPN 会用到。TCP 里的某个号码和 UDP 里相同的号码是彼此独立的端口,所以 53/tcp 和 53/udp 是不同的。写防火墙规则时您要指明协议,例如 22/tcp。