配置 VPS 防火墙并采取 “默认拒绝,按需放行” 的策略是保障服务器网络安全的最有效手段之一。
在主流的 Linux 发行版(如 Ubuntu 或 Debian)中,最推荐使用 UFW (Uncomplicated Firewall) 来进行配置。它的底层是 iptables/nftables,但语法更加人性化。
以下是配置 UFW 以实现只放行指定端口的完整流程:
# 1. 核心配置:放行与启用
⚠️ 极其重要的一步: 在启用防火墙之前,必须先放行 SSH 端口,否则你会被立刻锁在服务器外面。
```bash # 1. 允许 SSH 连接(如果你的 SSH 不是默认的 22 端口,请替换为你的自定义端口,例如 2222/tcp) sudo ufw allow 22/tcp # 2. 设置默认拒绝所有入站连接 sudo ufw default deny incoming # 3. 设置默认允许所有出站连接(保证服务器能正常访问外部网络,如下载更新、发起 API 请求) sudo ufw default allow outgoing # 4. 放行你需要的其他指定端口(按需执行) sudo ufw allow 80/tcp # HTTP sudo ufw allow 443/tcp # HTTPS # sudo ufw allow 8080/tcp # 举例:放行特定的后端服务端口 # 5. 放行本地回环 ufw allow in on lo ufw allow out on lo # 6. 找出你容器真实的网段,查看所有 Docker 网络的子网 docker network ls -q | xargs docker network inspect -f '{{.Name}}: {{range .IPAM.Config}}{{.Subnet}}{{end}}' # 7. 添加涵盖所有 Docker 网络的终极规则: sudo ufw allow from 172.16.0.0/12 to any port 13955 proto tcp # 8. 启用防火墙 sudo ufw enable # 9.禁止端口 sudo ufw delete allow 2222/tcp # 10.查看当前的防火墙规则 sudo ufw status numbered ```
启用后,系统会提示这可能会中断现有的 SSH 连接,输入 y 确认即可(只要你正确执行了第一步,你的连接就不会断开)。
你可以通过以下命令检查当前的防火墙状态和规则列表:
sudo ufw status numbered |
# 2. 生产环境的进阶注意事项
在实际的服务器基础设施管理中,单纯配置 UFW 往往不够,特别是当你使用了以下技术栈时:
# ⚠️ 容器化服务穿透问题 (Docker 绕过 UFW)
如果你在服务器上运行容器化服务,Docker 默认会直接修改 iptables,这会导致 UFW 的规则对 Docker 映射的端口失效。 即使你在 UFW 中没有放行 8080,只要 Docker 执行了 -p 8080:80 ,外部依然可以直接访问。
最佳实践方案:
不要将容器端口直接暴露给 0.0.0.0 。在 docker-compose.yml 或 docker run 中,将端口绑定到本地回环地址 127.0.0.1 ,然后使用 Nginx 等反向代理工具来接管流量。
# docker-compose.yml 示例 | |
services: | |
app: | |
image: my-backend-app | |
ports: | |
- "127.0.0.1:8080:80" # 仅本地可访问 |
这样外部流量只能通过 Nginx(监听已在 UFW 中放行的 80/443 端口)进入,从而将防火墙控制权交还回 UFW。
# ☁️ 云服务商的安全组 (Security Groups)
如果你使用的是 AWS、GCP 或阿里云等云服务商的实例,它们在基础设施层还有一道 “外部防火墙”(通常称为安全组或防火墙规则)。
- 你的网络请求必须 同时 通过云控制台的安全组规则和服务器内部的 UFW 规则。确保在云服务商的网页控制台中也开放了对应的入站端口,否则即使 UFW 放行了也无法连通。
# 🛡️ 配合 CDN/WAF 的严格限制
如果你使用了 CDN 或安全防护代理来保护你的网站,为了防止攻击者绕过代理直接攻击你的服务器源 IP,你可以配置 UFW 只允许来自这些特定服务商 IP 段的流量访问你的 Web 端口。
# 示例:只允许特定 IP 访问你的 443 端口 | |
sudo ufw allow from 192.168.1.100 to any port 443 |
验证防火墙是否按预期拦截流量,是非常严谨的安全习惯!
要测试未放行的端口是否真的被阻拦,你必须从服务器的外部(比如你的个人电脑)发起连接测试,并且可以配合服务器内部的日志来抓取拦截证据。
以下是三种最常用的验证方法:
# 方法一:从你的个人电脑发起连接(最直接)
UFW 默认的拦截策略是 DROP (直接丢弃数据包,假装没看见),而不是 REJECT (明确告诉对方连接被拒绝)。因此,当你测试被阻拦的端口时,预期的现象是 “卡住直到超时 (Timeout)”,而不是 “立刻提示连接被拒绝 (Connection refused)”。
你可以在你自己的电脑(不是 VPS 上)打开终端或命令行,尝试连接一个没有在 UFW 中放行的端口(例如 80 或 8080 ):
- 如果你使用 macOS 或 Linux 电脑:
使用nc(Netcat) 命令:
nc -vz 你的服务器IP 8080 |
预期结果: 命令会卡住很久,最后提示类似 Connection timed out ,说明防火墙把你的请求 “吃掉” 了。
- 如果你使用 Windows 电脑:
可以使用 PowerShell 里的Test-NetConnection命令:
Test-NetConnection -ComputerName 你的服务器IP -Port 8080 |
预期结果: 等待片刻后,输出结果中的 TcpTestSucceeded 会显示为 False 。
# 方法二:在服务器上实时查看防火墙拦截日志(铁证如山)
如果你想亲眼看到防火墙 “挡下” 了攻击或探测,可以开启 UFW 的日志功能。
1. 在你的 VPS 上开启 UFW 日志:
sudo ufw logging on | |
# 测试完成后将日志关掉 | |
sudo ufw logging off |
(默认是 low 级别,只会记录被阻拦的入站连接,刚好符合我们的需求。)
2. 实时滚动查看系统日志:
在 VPS 端运行以下命令,终端会停留在那里实时刷新最新的系统日志:
sudo tail -f /var/log/syslog | grep UFW | |
# 注意:如果是比较新的 Ubuntu 版本,系统日志可能迁移到了 journalctl: | |
# sudo journalctl -f -k | grep UFW |
3. 进行测试:
保持 VPS 的日志窗口不关,然后用你的个人电脑(或在线工具)去访问 VPS 上一个未放行的端口。
此时,你的 VPS 终端里应该会立刻弹出一行类似这样的红字 / 日志:
[UFW BLOCK] IN=eth0 OUT= MAC=... SRC=你的电脑IP DST=你的服务器IP LEN=60 TOS=0x00 ... PROTO=TCP SPT=54321 DPT=8080 ...
看到 [UFW BLOCK] 和对应的目标端口 ( DPT=8080 ),就证明防火墙不仅生效了,而且准确地拦截了该流量。
# 方法三:使用在线端口扫描工具(最简单)
如果你不想在本地敲命令,可以使用第三方的网页版端口扫描器。
- 在浏览器搜索并打开类似
ping.eu/port-chk/或yougetsignal.com/tools/open-ports/的网站。 - 输入你的 VPS IP 地址,并填入一个你没有放行的端口(如
8080)。 - 点击检查。
预期结果: 网站会告诉你该端口是Closed或Filtered(被过滤 / 被防火墙阻挡)。
测试完毕后的小建议:
如果你通过 “方法二” 确认了防火墙工作正常,可以通过 sudo ufw logging off 关闭日志,以免将来无休止的互联网自动化扫描把你服务器的磁盘空间塞满日志文件。