iptables 防 Docker 绕过:DOCKER-USER 链限制 Nacos 8848 仅 localhost 可访问

1. 背景:为什么要封 8848 / 4243?

在内网环境里,我们经常会遇到这种情况:

  • Nacos(8848) 只想给本机 Java 服务用,不希望其他机器(B/C/D...)也能访问

  • Docker Remote API(4243) 如果被开放,风险非常高(相当于别人可以远程控制你的 Docker)

所以目标非常明确:

✅ 4243:彻底封死

✅ 8848:只允许本机访问(localhost),其他机器一律拒绝

✅ 重启机器后规则仍然生效(不靠手工敲命令)


2. 先确认:8848 是宿主机服务还是 Docker 暴露出来的?

先看 8848 到底是谁在监听:

netstat -ntlp | grep 8848

你可能会看到类似输出:

tcp6 0 0 :::8848 :::* LISTEN 2710/docker-proxy

这代表:

  • 8848 是 Docker 容器映射出来的端口

  • docker-proxy 在宿主机监听 8848


3. 为什么你封了 INPUT 还是能访问?

很多人第一反应是封 INPUT:

iptables -I INPUT -p tcp --dport 8848 -j DROP

但是在 Docker 场景下,有时候会出现:

规则加了,但其他机器还是能访问 8848

原因是:

  • Docker 会创建自己的链路(FORWARD / DOCKER / DOCKER-USER)

  • 端口映射的流量可能会走转发链路,不一定完全依赖 INPUT

所以更稳的做法是:

✅ INPUT 负责控制宿主机端口访问

✅ DOCKER-USER 负责控制容器转发访问(防 Docker 绕过)


4. 最推荐方案:写 systemd 服务,开机自动生效

这里我用 systemd oneshot 服务 来实现:

  • 开机自动插入 iptables 规则

  • 不依赖 iptables-save

  • 内网机器也能稳定落地


5. 一键写入配置(可直接复制执行)

⚠️ 下面这一段你可以直接复制执行,它会创建规则服务文件:

复制代码
cat > /etc/systemd/system/iptables-local.service <<'EOF'
[Unit]
Description=Local iptables rules (Nacos localhost only)
After=network.target docker.service
Requires=docker.service

[Service]
Type=oneshot

# ===============================
# 1. dockerd API:彻底封死
# ===============================
ExecStart=/usr/sbin/iptables  -I INPUT -p tcp --dport 4243 -j DROP
ExecStart=/usr/sbin/ip6tables -I INPUT -p tcp --dport 4243 -j DROP

# ===============================
# 2. nacos 8848:只允许本机
# ===============================

# IPv4
ExecStart=/usr/sbin/iptables -I INPUT 1 -i lo -p tcp --dport 8848 -j ACCEPT
ExecStart=/usr/sbin/iptables -I INPUT 2 -p tcp --dport 8848 -j DROP

# IPv6
ExecStart=/usr/sbin/ip6tables -I INPUT 1 -i lo -p tcp --dport 8848 -j ACCEPT
ExecStart=/usr/sbin/ip6tables -I INPUT 2 -p tcp --dport 8848 -j DROP

RemainAfterExit=yes

[Install]
WantedBy=multi-user.target
EOF

6. 让服务生效(立即执行 + 开机自启)

执行下面命令:

复制代码
systemctl daemon-reload
systemctl enable iptables-local.service --now
systemctl status iptables-local.service

如果你看到类似:

Active: active (exited)

说明规则已经插入成功。


7. 验证规则是否真的生效

7.1 检查 4243 是否被封死

iptables -nvL INPUT --line-numbers | grep 4243

如果出现 DROP 就说明 OK。


7.2 检查 8848 是否只允许本机访问

iptables -nvL INPUT --line-numbers | grep 8848

你应该能看到类似两条规则(顺序很关键):

  1. lo 放行

  2. 其他全部 DROP


7.3 实际测试(最重要)

A 机器本机 执行:

curl -I http://127.0.0.1:8848

应该可以正常返回。

然后在 B/C/D 机器 执行:

curl -I http://A机器IP:8848

应该连接失败或超时(被 DROP)。


8. 注意事项:为什么要加 IPv6 规则?

你之前看到的监听是:

tcp6 :::8848

这意味着服务同时可能支持 IPv6 访问。

如果你只封 IPv4,不封 IPv6,有些环境下仍可能绕过。

所以这里我把 ip6tables 也一起加上了,避免漏网。


9. 常见问题(排坑)

Q1:服务启动失败,提示 No chain/target/match by that name

比如你之前遇到的:

ip6tables: No chain/target/match by that name.

原因通常是:

  • 你去操作了 DOCKER-USER 但 IPv6 的链不存在

  • 或者 Docker 没启导致链还没创建

解决办法:

  • 规则写 INPUT(宿主机)一般不会有这个问题

  • 如果要写 DOCKER-USER,建议加 Requires=docker.service 并确保 Docker 已启动


Q2:我封了 INPUT,但其他机器还是能访问 8848?

这种情况大概率是:

  • 你封的是 INPUT,但端口映射流量走了 FORWARD / DOCKER 链路

  • 或者你规则顺序不对(DROP 在 ACCEPT 前面)

正确思路是:

  • INPUT 控制宿主机

  • DOCKER-USER 控制容器转发(更强硬)


10. 总结

这套方案解决了两个核心问题:

  • 4243(Docker Remote API):彻底封死,避免被远程控制

  • 8848(Nacos):只允许本机访问,其他机器全部拒绝

并且:

✅ 不依赖外网

✅ 不依赖 iptables-save

✅ systemd 管理,重启机器仍然生效

✅ 顺序可控,规则稳定落地

相关推荐
小p13 小时前
docker学习: 2. 构建镜像Dockerfile
docker
小p1 天前
docker学习: 1. docker基本使用
docker
崔小汤呀2 天前
Docker部署Nacos
docker·容器
缓解AI焦虑2 天前
Docker + K8s 部署大模型推理服务:资源划分与多实例调度
docker·容器
1candobetter2 天前
Docker Compose Build 与 Up 的区别:什么时候必须重建镜像
docker·容器·eureka
シ風箏2 天前
MySQL【部署 04】Docker部署 MySQL8.0.32 版本(网盘镜像及启动命令分享)
数据库·mysql·docker
BugShare2 天前
继《小爱音响》详细说下怎么部署,尤其是关于Docker部分
docker·nas·xiaomusic
至此流年莫相忘2 天前
Kubernetes实战篇之配置与存储
云原生·容器·kubernetes
小马爱打代码2 天前
Docker:完全指南从入门到精通
运维·docker·容器