Coreos 安全
Coreos security
我正在玩 coreos 和 digitalocean,我想开始允许我的容器之间进行内部通信。
我已经为所有主机设置了专用网络,现在我想确保某些容器只打开本地主机和内部接口的端口。
我为此探索了很多选择,但 none 似乎令人满意:
- 使用“-p”,我可以确保 docker 绑定到本地接口,但这有两个缺点:
- 我无法通过 SSH 轻松测试服务,因为该流量来自本地主机
- 我需要编写一些 hacky shell 脚本来启动我的服务,以便在
上注入容器 运行 的机器地址
- 我试过使用 flannel,但它不能使流量私密(或者我没有设置正确)
- 我考虑过在容器上使用 iptables 来防止外部访问,但这似乎并不安全
- 我尝试在 coreos 主机上使用 iptables,但是……这很棘手,我无法让它工作。
- 当我尝试在主机上配置 iptables 时,我使用了这里的方法:https://docs.docker.com/articles/networking/#communication-between-containers-and-the-wider-world,通过向 docker 链添加 DROP 规则,但它没有用,并且数据包还是打通了
那么最好的方法是什么,我会花时间让它发挥作用。
总的来说,我想我需要找到我能做的事情:
- 可靠地向所有主机推出
- 未来相当灵活的东西
- 允许 'edge machines' 可从更广泛的互联网访问的内容。
解决方案
我将详细说明我是如何解决这个问题的。感谢 larsks 的帮助。最后,他们的做法是正确的。这在 coreos 上很棘手,因为没有真正稳定的地址,就像 larsks 假设的那样。 coreos 的全部意义在于能够忘记 ip 地址。
我通过找到一种不太糟糕的方法将 ip 地址注入服务文件中的命令来解决这个问题。棘手的是它并不真正支持我期望的许多 shell 功能。我想要做的是将机器的IP地址分配给一个变量,然后将其注入命令:
ip=$(ifconfig eth1 | grep -o 'inet [0-9]*\.[0-9]*\.[0-9]*\.[0-9]*' | grep -o '[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*');
/usr/bin/docker run -p $ip:7000:7000 ...
但是,如前所述,这是行不通的。那么该怎么办?获取 shell!
ExecStart=/usr/bin/sh -c "\
export ip=$(ifconfig eth1 | grep -o 'inet [0-9]*\.[0-9]*\.[0-9]*\.[0-9]*' | grep -o '[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*');\
echo $ip;\
/usr/bin/docker run -p $ip:7000:7000"
一路上我遇到了一些问题。
- 我很确定该命令中没有换行符,所以我必须添加“;”字符
- 当你在 shell 中测试上面的 bash -c 命令时,它会产生与 systemd 执行它时截然不同的效果。在 shell 你需要转义 '$' 字符,而在 systemd 配置文件中,你不需要。
- 我包含了 echo 以便我可以看到命令认为 ip 是什么。
- 当我做这一切时,我实际上在 docker 图像中插入了一个小型网络服务器,这样我就可以使用 curl 进行测试。
这种方法的缺点是它与 ifconfig 的工作方式和 ipv4 相关联。事实上,这种方法不适用于我的 linux mint 笔记本电脑,其中 ifconfig 会生成不同格式的输出。这里重要的一课是在 yaml 或 json 中输出东西,这样 shell json 工具可以更容易地访问东西。
I've got private networking set up for all the hosts, and now I'd like
to ensure that some containers only open ports to localhost and to the
internal interface.
这正是您在指定 IP 地址时使用 -p
选项获得的行为。假设我的主机有两个外部接口,eth0
(地址为 10.0.0.10)和 eth1
(地址为 192.168.0.10),docker0
网桥位于 172.17.42.1/ 16.
如果我像这样启动一个容器:
docker run -p 192.168.0.10:80:80 -d larsks/mini-httpd
这将启动一个容器,该容器可通过位于 192.168.0.10、端口 80 的 eth1
接口访问。此服务也 可访问 -- 从主机容器所在的位置——在 docker0
网络上分配给容器的地址。这类似于 172.17.0.39,端口 80。
这似乎符合您的目标:
- 容器端口通过 "private"
eth1
接口公开。
- 容器端口可从主机访问。
I can't easily test services by SSHing in, because that traffic originates from localhost.
如果您在容器内 运行 ssh,您将在 Docker 分配的 "internal" 地址处通过 ssh 连接到它。但是,如果您在容器中使用 运行 ssh,您可能需要考虑 而不是 并依赖 docker exec
等工具。
I need to write somewhat hacky shell scripts to start my services, in order to inject the address of the machine that the container is running on
有了这个方案,就不需要把机器ip注入容器了
您可以使用环境文件来获取安排服务的主机的 IP 地址(public 和私有地址),而不是 grep-ping IP 地址。这允许您以简单的方式将容器端口绑定到 public 或私有端口。
像这样:
[Service]
EnvironmentFile=/etc/environment
ExecStart=/usr/bin/docker run --name myservice -p \
${COREOS_PUBLIC_IPV4}:80:80 \
${COREOS_PRIVATE_IPV4}:3306:3306 \
ubuntu /bin/bash
我正在玩 coreos 和 digitalocean,我想开始允许我的容器之间进行内部通信。
我已经为所有主机设置了专用网络,现在我想确保某些容器只打开本地主机和内部接口的端口。
我为此探索了很多选择,但 none 似乎令人满意:
- 使用“-p”,我可以确保 docker 绑定到本地接口,但这有两个缺点:
- 我无法通过 SSH 轻松测试服务,因为该流量来自本地主机
- 我需要编写一些 hacky shell 脚本来启动我的服务,以便在 上注入容器 运行 的机器地址
- 我试过使用 flannel,但它不能使流量私密(或者我没有设置正确)
- 我考虑过在容器上使用 iptables 来防止外部访问,但这似乎并不安全
- 我尝试在 coreos 主机上使用 iptables,但是……这很棘手,我无法让它工作。
- 当我尝试在主机上配置 iptables 时,我使用了这里的方法:https://docs.docker.com/articles/networking/#communication-between-containers-and-the-wider-world,通过向 docker 链添加 DROP 规则,但它没有用,并且数据包还是打通了
那么最好的方法是什么,我会花时间让它发挥作用。
总的来说,我想我需要找到我能做的事情:
- 可靠地向所有主机推出
- 未来相当灵活的东西
- 允许 'edge machines' 可从更广泛的互联网访问的内容。
解决方案
我将详细说明我是如何解决这个问题的。感谢 larsks 的帮助。最后,他们的做法是正确的。这在 coreos 上很棘手,因为没有真正稳定的地址,就像 larsks 假设的那样。 coreos 的全部意义在于能够忘记 ip 地址。
我通过找到一种不太糟糕的方法将 ip 地址注入服务文件中的命令来解决这个问题。棘手的是它并不真正支持我期望的许多 shell 功能。我想要做的是将机器的IP地址分配给一个变量,然后将其注入命令:
ip=$(ifconfig eth1 | grep -o 'inet [0-9]*\.[0-9]*\.[0-9]*\.[0-9]*' | grep -o '[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*');
/usr/bin/docker run -p $ip:7000:7000 ...
但是,如前所述,这是行不通的。那么该怎么办?获取 shell!
ExecStart=/usr/bin/sh -c "\
export ip=$(ifconfig eth1 | grep -o 'inet [0-9]*\.[0-9]*\.[0-9]*\.[0-9]*' | grep -o '[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*');\
echo $ip;\
/usr/bin/docker run -p $ip:7000:7000"
一路上我遇到了一些问题。
- 我很确定该命令中没有换行符,所以我必须添加“;”字符
- 当你在 shell 中测试上面的 bash -c 命令时,它会产生与 systemd 执行它时截然不同的效果。在 shell 你需要转义 '$' 字符,而在 systemd 配置文件中,你不需要。
- 我包含了 echo 以便我可以看到命令认为 ip 是什么。
- 当我做这一切时,我实际上在 docker 图像中插入了一个小型网络服务器,这样我就可以使用 curl 进行测试。
这种方法的缺点是它与 ifconfig 的工作方式和 ipv4 相关联。事实上,这种方法不适用于我的 linux mint 笔记本电脑,其中 ifconfig 会生成不同格式的输出。这里重要的一课是在 yaml 或 json 中输出东西,这样 shell json 工具可以更容易地访问东西。
I've got private networking set up for all the hosts, and now I'd like to ensure that some containers only open ports to localhost and to the internal interface.
这正是您在指定 IP 地址时使用 -p
选项获得的行为。假设我的主机有两个外部接口,eth0
(地址为 10.0.0.10)和 eth1
(地址为 192.168.0.10),docker0
网桥位于 172.17.42.1/ 16.
如果我像这样启动一个容器:
docker run -p 192.168.0.10:80:80 -d larsks/mini-httpd
这将启动一个容器,该容器可通过位于 192.168.0.10、端口 80 的 eth1
接口访问。此服务也 可访问 -- 从主机容器所在的位置——在 docker0
网络上分配给容器的地址。这类似于 172.17.0.39,端口 80。
这似乎符合您的目标:
- 容器端口通过 "private"
eth1
接口公开。 - 容器端口可从主机访问。
I can't easily test services by SSHing in, because that traffic originates from localhost.
如果您在容器内 运行 ssh,您将在 Docker 分配的 "internal" 地址处通过 ssh 连接到它。但是,如果您在容器中使用 运行 ssh,您可能需要考虑 而不是 并依赖 docker exec
等工具。
I need to write somewhat hacky shell scripts to start my services, in order to inject the address of the machine that the container is running on
有了这个方案,就不需要把机器ip注入容器了
您可以使用环境文件来获取安排服务的主机的 IP 地址(public 和私有地址),而不是 grep-ping IP 地址。这允许您以简单的方式将容器端口绑定到 public 或私有端口。
像这样:
[Service]
EnvironmentFile=/etc/environment
ExecStart=/usr/bin/docker run --name myservice -p \
${COREOS_PUBLIC_IPV4}:80:80 \
${COREOS_PRIVATE_IPV4}:3306:3306 \
ubuntu /bin/bash