新装好的一台云服务器,安全组里图省事勾了"放行全部端口",三天后你发现它开始对外疯狂发包;给客户装的 Redis 为了方便调试直接绑了 0.0.0.0:6379 且没设密码,第二天数据被清空、还多了一个陌生的定时任务。这类事故的共同点不是技术不够,而是暴露面太大。互联网上每一台公网服务器都在被自动化程序持续扫描,一个开放端口从暴露到被探测,通常只需要几分钟到几小时。本文讨论的不是"哪个端口绝对安全"——没有任何端口是靠"冷门"来保证安全的——而是如何用最小权限原则,把该开的端口开得可控、把不该开的端口彻底关掉。
一、最小权限原则:先把暴露面压到最小
最小权限原则在端口管理上的含义很直白:只开放业务必需的端口,只对必需的来源 IP 开放,并且默认拒绝其他一切。它之所以比"多装防护"更重要,有三个现实原因。
1.1 每一个开放端口都是一份长期负债
你开放一个端口,等于承诺要长期维护它背后那个服务的安全:跟进补丁、管理账号、审计日志、关注漏洞公告。Redis 未授权访问、Elasticsearch 未授权访问、Docker Remote API 未授权访问、etcd 未授权访问——这些年几乎所有大规模数据泄露事件,根因都不是"端口被爆破",而是"这个端口本来就不该出现在公网上"。关掉端口是零成本且一劳永逸的防护;加防护是有成本且需要持续维护的。
1.2 默认拒绝比逐个封禁可靠得多
很多人的防火墙策略是"默认放行,发现坏人再封",这在自动化扫描面前必输无疑。正确顺序是反过来:先 iptables -P INPUT DROP 或 ufw default deny incoming,再逐条放行真正需要的服务。这样即使你以后装了新软件、开了新服务,也不会意外暴露到公网。
1.3 纵深防御:三层都要设防
- 第一层:服务本身。让服务只监听内网地址或 127.0.0.1,从源头不暴露。例如 Redis 配置
bind 127.0.0.1,MySQL 配置bind-address = 127.0.0.1。 - 第二层:主机防火墙。iptables / nftables / ufw / firewalld,做端口与来源 IP 的双重限制。
- 第三层:网络安全组。云厂商提供的虚拟化层防火墙,优先级高于主机内部规则,是最外层的一道。
三层中任何一层生效都能挡住攻击,但只有三层都配置正确,你才能在某一层被误改时仍然安全。
二、常见服务端口速查:哪些能开、哪些绝不能开
下表按"是否建议暴露到公网"给出判断。请特别注意:不建议开放不等于服务不能用,绝大多数情况是"只在内网用"或"通过 SSH 隧道 / VPN 访问"。
| 端口 | 服务 | 是否建议公网开放 | 主要风险 | 建议做法 |
|---|---|---|---|---|
| 22 | SSH | 可以,但需严格限制 | 暴力破解、弱口令、0day | 禁止 root 直登、禁用密码改用密钥、限制来源 IP、部署 fail2ban |
| 80 | HTTP | 可以 | 明文传输、中间人劫持 | 仅做 443 跳转,不承载实际业务 |
| 443 | HTTPS | 可以 | 应用层漏洞、CC 攻击 | 强制 TLS 1.2 以上,配 WAF 或 CDN |
| 21 | FTP | 不建议 | 明文口令、匿名用户、历史漏洞多 | 改用 SFTP(复用 22 端口)或对象存储 |
| 23 | Telnet | 绝不允许 | 完全明文,口令可被直接嗅探 | 卸载服务,用 SSH 替代 |
| 25 | SMTP | 视情况,常被限制 | 被用作开放中继导致 IP 被拉黑 | 关闭中继、配置 SPF/DKIM/DMARC,或改用 587/465 |
| 53 | DNS | 仅权威/递归服务器按需开放 | 被利用做反射放大攻击 | 递归与权威分离,限制递归来源,启用响应速率限制 |
| 111 / 2049 | rpcbind / NFS | 绝不允许 | 信息泄露、未授权挂载 | 仅内网使用并限定来源网段 |
| 445 / 139 | SMB | 绝不允许 | 历史高危漏洞密集,勒索软件主要入口 | 彻底关闭,跨网文件共享走 VPN |
| 1433 / 1521 | MSSQL / Oracle | 绝不允许 | 弱口令、提权、数据泄露 | 仅内网监听,远程用 SSH 隧道 |
| 3306 / 5432 | MySQL / PostgreSQL | 绝不允许 | 弱口令、未授权访问、数据被删勒索 | bind 到内网地址,限制来源 IP,强口令 |
| 6379 | Redis | 绝不允许 | 未授权访问可导致任意文件写入与命令执行 | bind 127.0.0.1、设置 requirepass、rename-command 高危命令 |
| 11211 | Memcached | 绝不允许 | 未授权访问且可被用于反射放大 | 仅监听 127.0.0.1 或内网 |
| 2375 / 2376 | Docker Daemon | 绝不允许 | 未授权访问等同于拿到宿主机 root | 2375 必须关闭;仅用本地 socket 或 2376 配 TLS 证书 |
| 2379 / 2380 | etcd | 绝不允许 | 未授权访问泄露集群全部配置与密钥 | 仅内网监听并开启证书认证 |
| 27017 | MongoDB | 绝不允许 | 默认无认证,数据被勒索删除高发 | 开启 auth,bind 内网,限制来源 |
| 9200 / 9300 | Elasticsearch | 绝不允许 | 默认无认证,数据可被任意读写 | 开启安全认证,仅内网监听 |
| 3389 | RDP | 强烈不建议直接开放 | 暴力破解、勒索软件入口 | 先连 VPN 再连 RDP,或限制来源 IP 并启用网络级别认证 |
| 5900 | VNC | 不建议 | 认证薄弱、明文传输 | 仅通过 SSH 隧道访问 |
| 8080 / 8888 | 备用 HTTP / 管理面板 | 视情况 | 常被误配为无认证管理后台 | 管理后台必须加认证并限制来源 IP |
| 161 | SNMP | 不建议 | 社区名泄露导致信息泄露 | 改用 v3 并限制来源,或直接关闭 |
| 123 | NTP | 不建议对公网提供 | 可被用于反射放大攻击 | 作为客户端同步即可,不对外提供授时服务 |
三、盘点:我这台机器到底开了哪些端口
很多人以为自己只开了 80 和 443,实际一查有三十多个监听。原因通常是系统预装服务和容器、Docker、K8s 组件自动映射的端口。先用下面的命令做一次完整盘点。
3.1 本机视角
# 列出所有 TCP/UDP 监听端口及对应进程(-l 监听 -n 不解析 -t TCP -u UDP -p 进程)
ss -lntup
# 只看监听中的 TCP 端口及进程
ss -lntp
# 提取本地监听地址端口列表
ss -lnt | awk 'NR>1 {print $4}' | sort -u
# 用 lsof 交叉核对(部分系统上 ss 的 -p 需要 root 权限)
lsof -i -nP | grep LISTEN
看结果时重点关注三件事:监听地址是 0.0.0.0(所有网卡)还是 127.0.0.1(仅本机)或是具体内网 IP;进程名是否认识;是否有预期之外的高位端口(常见来源:Docker 容器映射、Node/Python 调试服务、各类 Agent)。
3.2 外部视角
本机看到的监听不等于外部能访问到——中间还隔着主机防火墙和云安全组。所以必须再从外部做一次核对。请仅对你拥有或已获授权的资产执行:
# 从另一台机器扫描自己的服务器,做外部视角验证(-Pn 跳过主机发现 -sV 识别服务版本) nmap -Pn -sT -sV -T4 --top-ports 1000 203.0.113.10 # 只验证某一个端口是否可达 nc -vz -w 3 203.0.113.10 6379 # 检查防火墙当前放行情况 iptables -L INPUT -n -v --line-numbers ufw status numbered firewall-cmd --list-all
外部扫出来的端口如果比本机监听的还多,说明有容器或 NAT 映射在起作用;如果比本机少,说明防火墙生效了,这是正常且期望的结果。两边结果应当能对上账,对不上就要逐层排查。
四、按服务器角色给出端口白名单
| 服务器角色 | 建议对外开放端口 | 仅内网开放 | 必须关闭 |
|---|---|---|---|
| 公网 Web 服务器 | 80、443、22(限来源 IP) | 无 | 其他全部 |
| 数据库服务器 | 22(限来源 IP) | 3306 / 5432 / 27017 等,限应用服务器 IP | 公网暴露的所有数据端口 |
| 应用服务器(内网) | 无,或仅 22(限堡垒机 IP) | 8080 等业务端口,限负载均衡 IP | 公网暴露的任何业务端口 |
| 堡垒机 / 跳板机 | 22(限办公出口 IP) | 无 | 其他全部,且不应安装任何业务服务 |
| 缓存服务器(Redis/Memcached) | 无 | 6379 / 11211,限应用服务器 IP | 公网暴露 |
| 邮件服务器 | 25、587、465、993 | 无 | 必须关闭开放中继 |
五、用防火墙落地最小权限
5.1 ufw(Ubuntu/Debian 推荐)
# 先设默认策略:拒绝所有入站,允许所有出站 ufw default deny incoming ufw default allow outgoing # 放行 SSH,强烈建议限定来源网段,并对 22 启用连接速率限制 ufw allow from 203.0.113.0/24 to any port 22 proto tcp ufw limit 22/tcp # 放行 Web 端口 ufw allow 80/tcp ufw allow 443/tcp # 启用并查看带编号的规则(编号用于删除规则:ufw delete 3) ufw enable ufw status numbered
操作顺序有个坑:执行 ufw default deny incoming 之后、执行 ufw enable 之前,务必先放行 SSH。如果你是通过 SSH 远程操作的,一旦在没放行 22 的情况下启用 ufw,连接会立刻断开。建议首次操作时先在控制台的 VNC 里做,或者用 at 定时一个自动回滚任务兜底。
5.2 iptables(通用)
# 默认策略:入站丢弃 iptables -P INPUT DROP iptables -P FORWARD DROP iptables -P OUTPUT ACCEPT # 放行本地回环,否则很多本机服务会异常 iptables -A INPUT -i lo -j ACCEPT # 放行已建立的连接与相关连接(这一条非常关键,否则出方向的响应包回不来) iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT # SSH 仅允许办公出口网段 iptables -A INPUT -p tcp --dport 22 -s 203.0.113.0/24 -j ACCEPT # Web 端口对公网开放 iptables -A INPUT -p tcp --dport 80 -j ACCEPT iptables -A INPUT -p tcp --dport 443 -j ACCEPT # 允许 ICMP 但限速,既保留 ping 排障能力又降低被洪水利用的风险 iptables -A INPUT -p icmp --icmp-type echo-request -m limit --limit 5/s -j ACCEPT
规则写完后不要忘记持久化,否则重启即失效。Debian/Ubuntu 用 netfilter-persistent save(需先 apt install iptables-persistent),RHEL 系可用 service iptables save 或 iptables-save > /etc/sysconfig/iptables。
5.3 firewalld(RHEL/CentOS/Rocky)
# 查看当前区域与放行内容 firewall-cmd --get-default-zone firewall-cmd --list-all # 先加一条仅允许指定来源访问 ssh 的富规则,再移除对全网开放的 ssh 服务 firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="203.0.113.0/24" service name="ssh" accept' firewall-cmd --permanent --remove-service=ssh # 放行 Web firewall-cmd --permanent --add-service=http firewall-cmd --permanent --add-service=https # 重新加载并核对 firewall-cmd --reload firewall-cmd --list-all
六、端口收敛的实施步骤
- 盘点现状:用
ss -lntup列出全部监听,用nmap从外部核对,形成一张"端口—进程—用途—是否必需"的清单。 - 标记必需性:对每个端口标注"公网必需 / 内网必需 / 完全不需要"三类。判断不了就先标为不需要,观察一周看有没有人反馈。
- 先改服务监听地址:把数据库、缓存类服务改成监听 127.0.0.1 或内网地址,这一步不依赖防火墙,最彻底。
- 再配置主机防火墙:按角色白名单逐条放行,默认拒绝。优先用 ufw 或 firewalld 这类高层工具,减少出错概率。
- 最后收敛云安全组:把安全组改成同样的白名单,确保两层一致。注意先加后删,避免中间态断连。
- 灰度验证:从外部用
nc -vz逐个验证该通的通、该断的断,同时观察业务监控至少 24 小时。 - 固化为基线:把最终规则写进配置管理(Ansible、cloud-init 或镜像模板),让新开的机器自动带上正确的端口策略。
小结
端口安全的核心不是记住"哪个端口危险",而是建立"默认拒绝、按需放行"的习惯。一台合格的公网 Web 服务器,对外开放端口应该只有 80、443 和严格限制来源的 22;数据库、缓存、容器管理端口一律只出现在内网。落地时按"服务监听地址 → 主机防火墙 → 云安全组"三层顺序推进,并用 ss -lntup 与 nmap 做本机与外部的双视角核对。把端口清单纳入基线管理,比事后补救要省心得多。
避坑建议
- 不要靠"改个冷门端口"来保证安全:端口扫描是全端口的,改成 2222 或 54321 只能减少日志噪音,挡不住真正的攻击者,反而会让你放松口令和密钥管理。
- 不要忽略 Docker 会绕过 iptables:
docker run -p 8080:80会直接写入 iptables 规则,可能让你的 ufw 策略失效,容器场景需要额外关注 DOCKER-USER 链。 - 不要在远程 SSH 里直接
ufw enable:务必先放行 22,否则会当场把自己锁在门外。 - 不要忘记放行 lo 回环:很多本机服务依赖 127.0.0.1 通信,
INPUT默认 DROP 后不放行 lo 会出现各种莫名其妙的故障。 - 不要忘了 ESTABLISHED,RELATED 规则:没有这条,服务器主动向外发起连接的返回包会被自己挡掉,表现为"能 ping 通但打不开网页"之类怪问题。
- 不要改完就走:每收敛一次端口都要观察 24 小时业务监控,有些内部依赖(监控采集、日志上报、授权校验回调)不会立刻暴露。
企业QQ咨询




