主题
02 — 防火墙与端口
采集时间:2026-11-08 04:12 CST(ufw 已于 04:05 启用)
1. 结论速览
| 检查项 | 状态 | 说明 |
|---|---|---|
| ufw | ✅ active | 2026-11-08 04:05 启用 |
| 入站默认策略 | DROP | 仅放行 22 / 80 / 443 |
| 出站默认策略 | ACCEPT | — |
| 转发默认策略 | ACCEPT | 为 Docker 特意从 DROP 改为 ACCEPT |
| firewalld | 未安装 | — |
| nftables | 未使用(docker 用 iptables 后端) | — |
| 阿里云安全组 | 🔴 仅放行 22/tcp + ICMP(外部实测 73 端口确认) | 见第 6 节 |
| 公网可达端口 | 仅 22 | 80/443 被安全组阻断 |
主机防火墙已生效。目前防线 = 阿里云安全组(外部)+ ufw(主机)。
⚠️ 最重要的一条:安全组只放行了 22 和 ICMP
经过 73 个端口的外部实测(2026-11-08):
除 22/tcp 和 ICMP 外,所有端口在公网均不可达 —— 包括 80 和 443。
ufw 虽然放行了 80/443,但安全组在更外层就把包丢了, 所以现在无法对外提供任何 Web 服务。详见第 6 节的探测方法与结论。
2. UFW 状态
Status: active
Logging: on (low)
Default: deny (incoming), allow (outgoing), allow (routed)
New profiles: skip放行规则
| 端口 | 用途 | 备注 |
|---|---|---|
| 22/tcp | SSH | ⚠️ 公网可达,建议收窄来源 |
| 80/tcp | HTTP | 为后续 Web 部署预留 |
| 443/tcp | HTTPS | 为后续 Web 部署预留 |
IPv4 与 IPv6 均已放行。
⚠️ 关键改动:DEFAULT_FORWARD_POLICY
/etc/default/ufw 原值:
DEFAULT_INPUT_POLICY="DROP"
DEFAULT_OUTPUT_POLICY="ACCEPT"
DEFAULT_FORWARD_POLICY="DROP" ← 会导致 Docker 容器无外网改为:
DEFAULT_FORWARD_POLICY="ACCEPT"原因:Docker 依赖 netfilter 的 FORWARD 链做容器 NAT。若 FORWARD 默认 DROP, 容器能启动但无法访问外网、DNS 也解析不了,且报错隐蔽(容器内表现为超时)。
已验证:启用 ufw + 装 Docker 后,容器内 wget https://myip.ipip.net 正常返回,证明转发链路通畅。
备份:/etc/default/ufw.bak.<时间戳>
3. iptables 现状
委托给 ufw 和 docker 管理:
| 链 | 策略 | 说明 |
|---|---|---|
| INPUT | DROP | ufw 管理 |
| FORWARD | DROP | docker 在链首插入自己的 ACCEPT 跳转规则 |
| OUTPUT | ACCEPT | — |
- ufw 建立 104 条规则(含自定义链
ufw-*) - docker 安装后新增 15 条(
DOCKER、DOCKER-USER、DOCKER-ISOLATION-STAGE-*、nat 表的MASQUERADE等)
手工
iptables -S看到-P FORWARD DROP是正常的: docker 通过-A FORWARD -j DOCKER-USER等规则在默认 DROP 之前放行, 所以容器网络仍然可用(已实测)。
4. 已知问题:Docker 绕过 ufw
这是 Docker 的固有行为,不是配置失误:
Docker 直接操作 iptables 的
DOCKER链发布容器端口,不经过 ufw 的 INPUT 规则。 即:docker run -p 8080:80后,公网上任何 IP 都能访问 8080,即使 ufw 没放行 8080。
应对建议(部署业务时务必注意):
| 场景 | 做法 |
|---|---|
| 只给反代访问的内部服务 | docker run -p 127.0.0.1:8080:80 —— 绑定 loopback,不对外 |
| 需要对外的服务 | 走 nginx 反代,只把 nginx 的 80/443 放开 |
| 需要严格管控 | 在 DOCKER-USER 链里加限制规则 |
5. 监听端口(当前)
| 端口 | 协议 | 绑定地址 | 进程 | 暴露面 |
|---|---|---|---|---|
| 22 | TCP | 0.0.0.0 / [::] | sshd | 🔴 公网 |
| 80 | — | — | (已放行,暂无服务监听) | — |
| 443 | — | — | (已放行,暂无服务监听) | — |
| 1080 | TCP | 127.0.0.1 | ss-local | 🟢 仅本机 |
| 8118 | TCP | 127.0.0.1 / [::1] | privoxy | 🟢 仅本机 |
| 53 | TCP/UDP | 127.0.0.53 | systemd-resolved | 🟢 仅本机 |
| 68 | UDP | 172.26.199.94 | systemd-networkd | 🟢 仅本机 |
| 323 | UDP | 127.0.0.1 / ::1 | chronyd | 🟢 仅本机 |
代理端口(1080 / 8118)都只绑 loopback,公网不可达,因此无需在 ufw 放行。
6. 阿里云安全组 —— 已通过外部探测反推
服务器内部看不到安全组规则。但用外部 TCP 探测可以反推策略:
| 探测结果 | 含义 |
|---|---|
| OPEN(握手成功) | 安全组放行 + 有服务监听 |
| CLOSED(收到 RST) | 包到达了服务器 → 安全组放行,只是没服务监听 |
| FILTERED(超时无响应) | 包被丢弃 → 安全组阻断 |
实测结果(2026-11-08,从公网侧探测 73 个端口)
| 结果 | 端口 |
|---|---|
| ✅ OPEN | 仅 22/tcp(SSH) |
| ⚪ CLOSED | 无(没有任何"安全组放行但无服务"的端口) |
| ❌ FILTERED(被阻断) | 除 22 外全部 72 个,含 80、443、8080、8443、5432、3306、6379、27017、9200、3000、8000、5000、9000、2375、6443、21、25、587、993… |
ICMP:✅ 可达(ping 通)
结论
当前安全组是阿里云默认策略:只放行 22/tcp 和 ICMP,其余全部拒绝。
⚠️ 这意味着现在无法对外提供任何 Web 服务 —— 即使 ufw 已放行 80/443、 服务也正常监听,公网依然访问不到,因为在安全组这一层就被丢了。
注意区分:
ufw放行 80/443 只解决主机内的过滤;安全组在云网络层,优先级更外。 两层都要通才行。
三层过滤关系(重要)
公网用户
↓ ① 阿里云安全组(云网络层,当前只放 22 + ICMP)← 主要瓶颈
↓ ② ufw(主机层,已放 22/80/443)
↓ ③ 服务是否监听(当前 22 在听;80/443 无服务)
服务器探测局限说明
- 结果反映本运维 IP 视角。若安全组对 22 做了来源 IP 限制,其他来源可能表现不同(无法从单点验证)。
- 无法获取安全组的规则明细(授权对象、优先级),只能得到"通/不通"的结论。
若要放开 Web 端口
| 方案 | 是否需控制台 | 说明 |
|---|---|---|
| 控制台改安全组 | ✅ 需要 | 最正统,你当前可登录但找不到入口 → 见下方"控制台操作步骤" |
| ❌ 不需要 | 已排除:无 AccessKey 且不便生成 | |
| SSH 隧道 | ❌ 不需要 | ssh -L 8080:127.0.0.1:80 tenodx,仅本人可访问,立即可用 |
| 反向隧道(Cloudflare Tunnel / frp) | ❌ 不需要 | 服务器主动出站建连,绕过入站限制;需域名或公网中继 |
7. 控制台操作步骤(能登录但找不到安全组入口)
实例:
i-2zehcg17z0nko8qusdz8| 地域:华北2(北京)
最容易踩的坑:地域选错
安全组是「地域级」资源。 如果控制台顶部地域不是 华北2(北京), 在安全组列表里就完全看不到这台机器的安全组,看起来就像"找不到入口"。
路径 A:从实例直接进(最可靠)
- 登录阿里云控制台 → 顶部搜索框输入
ECS→ 进入 云服务器 ECS - 左侧 实例与镜像 → 实例
- 顶部地域切换到 华北2(北京)
- 找到实例
i-2zehcg17z0nko8qusdz8,点击实例 ID 进入详情 - 在详情页找到 安全组 标签页 → 点安全组 ID
- 进入后点 访问规则 → 入方向 → 手动添加
路径 B:从安全组列表进
- 左侧菜单 网络与安全 → 安全组
- 地域切到 华北2(北京)
- 按实例 ID
i-2zehcg17z0nko8qusdz8筛选 - 点安全组 ID → 访问规则 → 入方向 → 手动添加
需要添加的两条规则
| 协议类型 | 端口范围 | 授权对象 | 优先级 | 描述 |
|---|---|---|---|---|
| 自定义 TCP | 80/80 | 0.0.0.0/0 | 1 | HTTP |
| 自定义 TCP | 443/443 | 0.0.0.0/0 | 1 | HTTPS |
保存后立即生效,不需要重启实例。 建议同时把 22 端口的授权对象从
0.0.0.0/0收窄到你的固定 IP(可选,当前密码登录已关 + fail2ban 在跑,风险可接受)。
如果提示"没有权限"
那是 RAM 子账号权限不足,需要主账号或有管理员权限的人授予以下策略之一:
AliyunECSFullAccess(全量,省事)- 或自定义策略仅含:
ecs:DescribeSecurityGroups、ecs:AuthorizeSecurityGroup、ecs:RevokeSecurityGroup
改完如何验证
让 DSH 重新做一次外部探测即可:
「安全组改好了,复测一下」—— 我会重跑 73 端口扫描确认 80/443 是否放通。
8. 常用命令
bash
ufw status verbose # 查看状态与规则
ufw status numbered # 带编号(便于删除)
ufw app list # 可用应用配置
ufw allow 8080/tcp comment 'App' # 放行
ufw delete <编号> # 删除
ufw reload # 重载
iptables -S | grep DOCKER # 查看 docker 规则9. 待办
| 优先级 | 事项 |
|---|---|
| 🔴 P0 | 在控制台放行安全组 80/443(否则 Web 服务无法对外,见第 7 节步骤) |
| P1 | 控制台把 22 端口授权对象收窄到固定 IP(可选) |
| P2 | 部署业务时注意 Docker 端口发布绕过 ufw 的问题(见第 4 节) |
| ✅ 已完成 | |
| ✅ 已完成 | |
| ✅ 已完成 |
fail2ban 配置摘要
文件: /etc/fail2ban/jail.local
[DEFAULT]
bantime = 1h # 封禁 1 小时
findtime = 10m # 统计窗口 10 分钟
maxretry = 5 # 5 次失败触发
ignoreip = 127.0.0.1/8 ::1 223.73.45.39 # 白名单,防自锁
banaction = ufw # 封禁规则写入 ufw,可用 ufw status 查看
backend = systemd # 从 journal 读取日志
[sshd]
enabled = true
port = 22常用命令:
bash
fail2ban-client status # 总览
fail2ban-client status sshd # 查看封禁列表
fail2ban-client set sshd unbanip 1.2.3.4 # 手动解封
fail2ban-client set sshd banip 1.2.3.4 # 手动封禁注意:
MaxAuthTries 6与 fail2banmaxretry 5会叠加 —— 单次连接尝试超 6 次密钥会先被 sshd 断开,跨连接的累计失败才由 fail2ban 统计。