家庭小主机需要保留“二级域名 + 端口”的公网访问方式,同时让 Redis 等内部服务只供局域网和 WireGuard 使用。这里保留 Docker 自动生成的规则,在 DOCKER-USER 中维护允许访问的来源和公网 TCP 端口。
第一篇记录组网配置, 第二篇解释报文路径。 本篇记录最终采用的家庭防护脚本,以及云主机的安全组分工。
enp1s0;局域网:192.168.0.0/24。wg0,网段 10.10.0.0/24。本方案使用 Docker bridge 与 iptables 后端,仅配置 IPv4。物理网卡上的 DROP 会影响其他转发流量,不应直接用于还承担其他路由任务的网关主机。
10088:springboot附件服务。10081:springboot CAS SSO。10085:springboot lite-task服务。10085:springboot console服务。61208:Glances。40002:FileBrowser,对应容器端口 80。9000:Portainer。以上是当前明确需要开放的列表。管理页面仍需启用各自的认证;Redis 不加入列表,路由器也不转发 Redis。
文件:/usr/local/sbin/docker-user-firewall.sh。网卡、网段和端口数组按实际环境修改。
bash复制代码
#!/usr/bin/env bash
set -e
# 对公网开放的宿主机 TCP 发布端口。
# FileBrowser 的映射为 40002:80,这里填写 40002。
PUBLIC_TCP_PORTS=(10088 10081 10085 10087 61208 40002 9000)
# 检查 Docker 已创建链;-w 等待 iptables 锁释放。
iptables -w -nL DOCKER-USER >/dev/null
# 允许 WireGuard 与局域网来源继续进入 Docker 后续规则。
iptables -w -C DOCKER-USER -i wg0 -s 10.10.0.0/24 -j RETURN 2>/dev/null \
|| iptables -w -I DOCKER-USER 1 -i wg0 -s 10.10.0.0/24 -j RETURN
iptables -w -C DOCKER-USER -i enp1s0 -s 192.168.0.0/24 -j RETURN 2>/dev/null \
|| iptables -w -I DOCKER-USER 1 -i enp1s0 -s 192.168.0.0/24 -j RETURN
# 拒绝其他从物理网卡进入的转发流量,插在白名单之后。
iptables -w -C DOCKER-USER -i enp1s0 -j DROP 2>/dev/null \
|| iptables -w -I DOCKER-USER 3 -i enp1s0 -j DROP
# 以下规则插入链首,保证排在 DROP 前面。
# 允许容器访问外部服务的响应流量,以及已有连接。
iptables -w -C DOCKER-USER \
-m conntrack --ctstate ESTABLISHED,RELATED -j RETURN 2>/dev/null \
|| iptables -w -I DOCKER-USER 1 \
-m conntrack --ctstate ESTABLISHED,RELATED -j RETURN
# 放行公网端口列表。
# 此处已经发生 DNAT,因此用 --ctorigdstport 匹配原始宿主机端口。
for port in "${PUBLIC_TCP_PORTS[@]}"; do
iptables -w -C DOCKER-USER -i enp1s0 -p tcp \
-m conntrack --ctdir ORIGINAL --ctorigdstport "$port" \
-j RETURN 2>/dev/null \
|| iptables -w -I DOCKER-USER 1 -i enp1s0 -p tcp \
-m conntrack --ctdir ORIGINAL --ctorigdstport "$port" \
-j RETURN
done-C 避免重复添加相同规则,-I ... 1 插入链首。RETURN 返回调用链,后续仍由 Docker 规则决定是否放行。--ctorigdstport 匹配宿主机发布端口,因此 40002:80 填写 40002。新增端口:加入 PUBLIC_TCP_PORTS,然后重新运行脚本或重启下文的 systemd 服务。
删除端口:从数组移除,另行删除已存在的规则。例如关闭 9000:
bash复制代码
sudo iptables -w -D DOCKER-USER -i enp1s0 -p tcp \
-m conntrack --ctdir ORIGINAL --ctorigdstport 9000 -j RETURN文件:/etc/systemd/system/docker-user-firewall.service。
ini复制代码
[Unit]
Description=Docker User Firewall Rules
Requires=docker.service
After=docker.service
[Service]
Type=oneshot
ExecStart=/usr/local/sbin/docker-user-firewall.sh
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target首次安装:
bash复制代码
sudo chmod +x /usr/local/sbin/docker-user-firewall.sh
# 只检查 Bash 语法,不执行防火墙规则。
sudo bash -n /usr/local/sbin/docker-user-firewall.sh
sudo systemctl daemon-reload
sudo systemctl enable --now docker-user-firewall.service只更新脚本:
bash复制代码
sudo bash -n /usr/local/sbin/docker-user-firewall.sh
sudo systemctl restart docker-user-firewall.serviceRemainAfterExit=yes 让一次性任务保留已完成状态,不能用再次 start 代替重新执行,应使用 restart。bash复制代码
sudo systemctl status docker-user-firewall.service
# 查看顺序与命中计数,确认允许规则位于物理网卡 DROP 之前。
sudo iptables -L DOCKER-USER -n -v --line-numbers
docker ps --format 'table {{.Names}}\t{{.Ports}}'按来源验证:
10.10.0.2 访问所需服务。验证时注意:
:::端口,需另行配置 IPv6 防护,或明确关闭不使用的 IPv6 发布及入口。云主机采用阿里云安全组管理 Docker 的公网入口,无需部署家庭机这套脚本。
22/TCP、80/TCP、443/TCP、51820/UDP,其他确需公开的服务再逐项添加。3306、Redis 16379、Meilisearch 7700;通过 WireGuard 访问。10086、10088。Docker 在主机内添加转发规则,并不能绕过云平台侧的安全组。WireGuard 解密后的内层服务访问,则继续由主机上的监听地址、防火墙和应用认证决定。
家庭机维护来源和端口列表,云机维护安全组;两边都保留服务认证,并在端口或网络变更后检查实际入口。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。