打开/关闭搜索
搜索
打开/关闭菜单
66
939
81
2762
md5.pw
导航
首页
最近更改
随机页面
MediaWiki帮助
特殊页面
上传文件
打开/关闭外观设置菜单
通知
打开/关闭个人菜单
未登录
未登录用户的IP地址会在进行任意编辑后公开展示。
user-interface-preferences
个人工具
登录
请求账号
查看“︁如何避免 Docker 端口意外暴露”︁的源代码
来自md5.pw
分享此页面
更多语言
查看
阅读
查看源代码
查看历史
associated-pages
页面
讨论
更多操作
←
如何避免 Docker 端口意外暴露
因为以下原因,您没有权限编辑该页面:
您请求的操作仅限属于该用户组的用户执行:
用户
您可以查看和复制此页面的源代码。
== 前言 == 刚接触 Docker 或者平常只使用 1Panel 这类面板的小白用户,最常遇到的问题应该就是明明 UFW 里没开放端口,但公网却可以直接通过端口访问容器。 以 1Panel 为例,如果你在应用商店安装应用时,勾选了“端口外部访问”,此时的容器就会监听 <code>0.0.0.0</code> [[File:Bwh-docker-port-1.webp|center]] 无论你有没有在 UFW 中开放这个端口,它都已经暴露到了公网。 [[File:Bwh-docker-port-2.webp|center]] 这个“陈年老坑”的原理很简单,因为 Docker 会直接修改 Linux 的 <code>iptables</code> 规则,而这些规则的优先级高于 UFW,并且在 UFW 中也不会显示 Docker 添加的规则。 要想解决这个问题并不难,下面介绍一下最常见的几种解决方法。 == 解决方法 == === 禁用 iptables(不推荐) === 既然 Docker 会直接修改 iptables 绕过 UFW ,那直接禁用掉 iptables 自动配置,不就轻松秒杀了吗? 在 <code>/etc/docker/daemon.json</code> 中添加:<code>{"iptables": false}</code> [[File:Bwh-docker-port-3.webp|center]] 相信你看到过网上许多的“庸医”教程就是这么教的,虽然说能够解决端口意外暴露的问题,但禁用 iptables 自动配置的同时还可能导致容器无法访问外部网络或容器间通信失败。 因此'''非常不推荐'''直接禁用 iptables。 === 安全组(暂不支持) === 如果你买的服务器有安全组功能,这个问题解决起来就非常的简单了,只要在后台的安全组中禁用端口,Docker 无论如何也不可能绕过安全组。 但是可惜'''搬瓦工'''暂时还不支持类似安全组的外置防火墙,可以接着看下面的解决方案,通过合理配置 Docker 和 iptables 来解决这个问题。 === 监听 127.0.0.1(推荐) === 对于大多数用户,端口映射时监听本地 <code>127.0.0.1:8080:80</code> 是最好的解决方法,对应 1Panel 中就是不勾选“端口外部访问”。 ==== Docker ==== <syntaxhighlight lang="sh"> -p 127.0.0.1:8080:80 </syntaxhighlight> ==== Docker Compose ==== <syntaxhighlight lang="yaml"> ports: - "127.0.0.1:8080:80" </syntaxhighlight>'''本机'''的其他应用可以正常通过端口访问到容器,而外部访问不了,如果是 Web 应用可以直接用 Nginx 反向代理。 但这个方法也不是完美的,当你想用'''另一台'''服务器反向代理时,监听 <code>127.0.0.1</code> 会导致装有 Nginx 的服务器也访问不到容器。 === host 模式 === 直接使用 host 模式也是一个比较常用的解决方案,在 host 模式下,容器不会获得独立的网络命名空间,而是直接共享宿主机的 IP 和端口,自然就可以用 UFW 来控制端口是否开放。 ==== Docker ==== <syntaxhighlight lang="sh"> --network </syntaxhighlight> ==== Docker Compose ==== <syntaxhighlight lang="yaml"> network_mode: "host" </syntaxhighlight>但'''缺点'''也非常的明显,共享宿主机的网络会导致网络没有隔离、端口冲突等一系列副作用。例如,几个容器的端口都为 80,就没法同时运行了。 === 虚拟局域网 === 如果你有用'''另一台'''服务器反代的需求,又不希望使用 host 模式,可以用 ZeroTier、Tailscale 之类的组网工具,给两台服务器组一个虚拟局域网,也是个不错的解决方案。 '''当然如果你两台服务器都是搬瓦工的并且位于同一个机房,可以直接利用 Private Network 开启内网,可以省去组建虚拟局域网的步骤''' 可以参考这篇文章 [[搬瓦工进阶教程:利用 Private Network 构建高速内网集群]] 在容器映射端口时,除了映射本机的 <code>127.0.0.0.1:8080:80</code>,再加上一条虚拟局域网的 IP,如 <code>192.168.100.1:8080:80</code>,另一台服务器反代时,填写 <code>192.168.100.1:8080</code> 即可。 ==== Docker ==== <syntaxhighlight lang="sh"> -p 127.0.0.1:8080:80 \ -p 192.168.100.1:8080:80 </syntaxhighlight> ==== Docker Compose ==== <syntaxhighlight lang="yaml"> ports: - "127.0.0.1:8080:80" # 仅本机访问 - "192.168.100.1:8080:80" # 仅通过特定局域网 IP 访问 </syntaxhighlight> === ufw-docker(推荐) === 要是你既不想用组网工具,又不想(或不能)用 host 模式,还想用另一台服务器的 Nginx 来反代容器,有没有'''更完美'''的解决方法呢? 有的,兄弟有的。 ufw-docker 是 GitHub 上开源的一个解决方案,具体原理可以查看仓库的 README,我们这里简单介绍一下如何使用。 ==== 手动配置 ==== 修改 UFW 的配置文件 <code>/etc/ufw/after.rules</code>,在最后添加上如下规则:<syntaxhighlight lang="text" line="1"> # BEGIN UFW AND DOCKER *filter :ufw-user-forward - [0:0] :ufw-docker-logging-deny - [0:0] :DOCKER-USER - [0:0] -A DOCKER-USER -j ufw-user-forward -A DOCKER-USER -m conntrack --ctstate RELATED,ESTABLISHED -j RETURN -A DOCKER-USER -m conntrack --ctstate INVALID -j DROP -A DOCKER-USER -i docker0 -o docker0 -j ACCEPT -A DOCKER-USER -j RETURN -s 10.0.0.0/8 -A DOCKER-USER -j RETURN -s 172.16.0.0/12 -A DOCKER-USER -j RETURN -s 192.168.0.0/16 -A DOCKER-USER -j ufw-docker-logging-deny -m conntrack --ctstate NEW -d 10.0.0.0/8 -A DOCKER-USER -j ufw-docker-logging-deny -m conntrack --ctstate NEW -d 172.16.0.0/12 -A DOCKER-USER -j ufw-docker-logging-deny -m conntrack --ctstate NEW -d 192.168.0.0/16 -A DOCKER-USER -j RETURN -A ufw-docker-logging-deny -m limit --limit 3/min --limit-burst 10 -j LOG --log-prefix "[UFW DOCKER BLOCK] " -A ufw-docker-logging-deny -j DROP COMMIT # END UFW AND DOCKER </syntaxhighlight>接着重启 UFW <code>systemctl restart ufw</code>。 此时即便你的容器监听的是 <code>0.0.0.0</code>,外部也是无法访问的,同时也不会影响 Docker 容器内部网络以及容器之间的通信。<blockquote>⚠️ '''注意:'''如果重启 UFW 仍不生效,可能需要重启服务器。</blockquote>假设现在有一个监听了 <code>0.0.0.0:8080:80</code> 的容器,私有地址为 <code>172.17.0.2</code>,如果要开放端口可以执行以下命令:<blockquote>⚠️ '''注意:'''<code>port</code> 为内部的 80 端口,并非映射的 8080 端口</blockquote> <syntaxhighlight lang="sh"> ufw route allow proto tcp from any to 172.17.0.2 port 80 </syntaxhighlight> 如果没有填写私有地址 <code>172.17.0.2</code>,则会开放所有内部端口为 80 的容器 <syntaxhighlight lang="sh"> ufw route allow proto tcp from any to any port 80 </syntaxhighlight> '''如果你有大量容器需要让另一台服务器反代,可以直接对那台服务器的 IP 开放''' <syntaxhighlight lang="sh"> ufw route allow proto tcp from x.x.x.x to any </syntaxhighlight> 想要查看或删除规则,可以执行 <syntaxhighlight lang="sh"> ufw status numbered </syntaxhighlight> 删除只需要执行 <code>ufw delete</code> + 编号 <syntaxhighlight lang="sh"> ufw delete 2 </syntaxhighlight> ==== 工具 ==== 如果觉得以上操作过于繁琐,也没关系,ufw-docker 还提供了'''工具'''简化所有操作 <syntaxhighlight lang="sh"> wget -O /usr/local/bin/ufw-docker \ <nowiki>https://github.com/chaifeng/ufw-docker/raw/master/ufw-docker</nowiki> chmod +x /usr/local/bin/ufw-docker </syntaxhighlight> 使用以下命令可以一键修改 UFW 的 <code>after.rules</code> 文件 <syntaxhighlight lang="sh"> ufw-docker install </syntaxhighlight> 具体的操作可以通过 <code>ufw-docker help</code> 查看,这里就不过多介绍了。 <syntaxhighlight lang="sh"> ufw-docker allow mysql 3306/tcp </syntaxhighlight> <syntaxhighlight lang="sh"> ufw-docker delete allow mysql 3306/tcp </syntaxhighlight> [[index.php?title=Category:500 常见应用指南 — Application Guides]]
返回
如何避免 Docker 端口意外暴露
。
查看“︁如何避免 Docker 端口意外暴露”︁的源代码
来自md5.pw