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 管理,重启机器仍然生效

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

相关推荐
建群新人小猿2 小时前
陀螺匠企业助手——组织框架图
android·java·大数据·开发语言·容器
爱上猫de鱼6 小时前
linux环境docker部署前后端应用
linux·运维·docker
小王努力学编程7 小时前
LangChain—AI应用开发框架(认识模型)
linux·服务器·人工智能·机器学习·容器·langchain
南宫乘风7 小时前
Kubernetes 中 ConfigMap 和 Secret 热更新:Reloader 实战指南
容器·kubernetes·configmap
辰尘_星启7 小时前
解决幽灵容器
linux·docker·容器·机器人·嵌入式
破无差7 小时前
docker配置报错解决过程dify
docker
培根芝士8 小时前
基于Docker部署M3U8流媒体
docker·容器
卜锦元8 小时前
Docker Compose 部署 MySQL 8.4 LTS(生产级实践方案)
数据库·mysql·docker·容器
独断万古他化8 小时前
Docker 入门前置:容器虚拟化基础之 cgroups 资源控制与 LXC 容器
linux·docker·容器