Blu*_*lue 2 iptables docker docker-compose
我有一个通过 docker-compose 文件创建的新应用程序。该文件包含2个网络:
version: '2.1'
# ----------------------------------
# Services
# ----------------------------------
services:
application:
image: tianon/true
volumes:
- ${APPLICATION_PATH}:/var/www
nginx:
build:
context: ./docker/nginx
volumes_from:
- application
volumes:
- ${DOCKER_STORAGE}/nginx-logs:/var/log/nginx
- ${NGINX_SITES_PATH}:/etc/nginx/sites-available
ports:
- "${NGINX_HTTP_PORT}:80"
- "${NGINX_HTTPS_PORT}:443"
networks:
- frontend
- backend
redis:
build:
context: ./docker/redis
volumes:
- ${DOCKER_STORAGE}/redis:/data
ports:
- "${REDIS_PORT}:6379"
networks:
- backend
# ----------------------------------
# Networks
# ----------------------------------
networks:
frontend:
driver: "bridge"
backend:
driver: "bridge"
# ----------------------------------
# Volumes
# ----------------------------------
volumes:
redis:
driver: "local"
Run Code Online (Sandbox Code Playgroud)
您会注意到我这里有 2 个网络,frontend并且backend. 问题很简单:
frontend向世界公开,但允许backend服务相互通信而不向世界公开?(我假设使用 iptables,或者在 docker 中指定我想要向主机公开哪个网络)对于赏金:docker 中显然有一种方法可以定义多个覆盖网络。我原以为,将一个网络暴露给外界会很简单。我正在尝试在 docker 或 iptables 中找到一种简单的方法来做到这一点。当前的答案给了我一些方向,但需要每个端口的手动规则。我想要一个关于如何保护我的“前端”网络的正确答案,而不必在 iptables 中指定特定端口。
完成@BMitch的回答以满足您的需求..
您可以使用额外的容器间网络(如果您看到需要或用例,则可以使用多个容器间网络。),因为为了使此类设置可靠地工作,每个容器仅分配一个非内部网络至关重要。否则,您无法真正确定将为映射端口上的传入流量选择哪个桥接网络(或者至少它不可真正配置)。
显示此类设置的示例 compose 文件:
version: '3.6'
services:
c1:
container_name: c1
image: "centos:latest"
entrypoint: /bin/bash -c "while sleep 10; do sleep 10; done"
ports:
- "5000:5000"
networks:
- front
- inter
c2:
container_name: c2
image: "centos:latest"
entrypoint: /bin/bash -c "while sleep 10; do sleep 10; done"
ports:
- "5001:5001"
networks:
- inter
c3:
container_name: c3
image: "centos:latest"
entrypoint: /bin/bash -c "while sleep 10; do sleep 10; done"
ports:
- "5002:5002"
networks:
- back
- inter
c4:
container_name: c4
image: "centos:latest"
entrypoint: /bin/bash -c "while sleep 10; do sleep 10; done"
ports:
- "5003:5003"
networks:
- back
- inter
networks:
front:
name: front
driver: bridge
driver_opts:
com.docker.network.bridge.name: dockerfront
back:
name: back
driver: bridge
driver_opts:
com.docker.network.bridge.name: dockerback
inter:
name: inter
driver: bridge
internal: true
driver_opts:
com.docker.network.bridge.name: dockerinter
Run Code Online (Sandbox Code Playgroud)
它为您的公共服务创建一个网桥([docker]front),为您的后端服务创建一个网桥([docker]back),以及一个内部网桥(即使在请求时也不会发布端口,因此可以安全地添加为附加网络) ([docker]intern) 并将它们分配给容器。
实际上,从外部无法通过端口 5001 访问 c2,因此可以省略该容器的端口。只是为了显示结果:
# iptables -nvL DOCKER -t nat
Chain DOCKER (2 references)
pkts bytes target prot opt in out source destination
0 0 RETURN all -- dockerback * 0.0.0.0/0 0.0.0.0/0
0 0 RETURN all -- dockerfront * 0.0.0.0/0 0.0.0.0/0
0 0 RETURN all -- docker0 * 0.0.0.0/0 0.0.0.0/0
0 0 DNAT tcp -- !dockerback * 0.0.0.0/0 0.0.0.0/0 tcp dpt:5002 to:172.27.0.2:5002
0 0 DNAT tcp -- !dockerfront * 0.0.0.0/0 0.0.0.0/0 tcp dpt:5000 to:172.25.0.2:5000
0 0 DNAT tcp -- !dockerback * 0.0.0.0/0 0.0.0.0/0 tcp dpt:5003 to:172.27.0.3:5003
Run Code Online (Sandbox Code Playgroud)
dockerback现在您可以添加桥接链的访问规则DOCKER-USER:
# iptables -I DOCKER-USER ! -s 10.0.0.0/24 -o dockerback -j DROP
# iptables -nvL DOCKER-USER
Chain DOCKER-USER (1 references)
pkts bytes target prot opt in out source destination
3 156 DROP all -- * dockerback !10.0.0.0/24 0.0.0.0/0
10 460 RETURN all -- * * 0.0.0.0/0 0.0.0.0/0
Run Code Online (Sandbox Code Playgroud)
请注意:当前版本 19.03.3 存在DOCKER-USER未创建链的错误,该错误已在 19.03.4 中修复,很快就会推出。如果您有该版本,您可以自己添加链(必须在每次重新启动 docker 守护进程后完成):
iptables -N DOCKER-USER
iptables -I FORWARD -j DOCKER-USER
iptables -A DOCKER-USER -j RETURN
Run Code Online (Sandbox Code Playgroud)
可能你会找到一个更合适的地方来放置这些规则,但这是 docker 建议的方式。(我可以考虑修复网桥的网络,并将规则放入通用转发规则中,不适用于重新启动、接口重新创建等情况下的 docker 操作。)
另外(或相反),您可以在计算机上使用额外的 IP 将后端服务绑定到另一个 IP,然后在该级别使用前端服务和过滤器。另外,意味着与上面完全相同的 docker 设置,但另外指定了com.docker.network.bridge.host_binding_ipv4驱动程序选项(这只是已发布端口的默认 IP) - 或者只使用一个网络并根据服务类型指定绑定地址。然后在 DOCKER-USER 中或在适当的地方使用与传入接口匹配的 conntrack 模块 ctorigdst 来阻止 FORWARD。
| 归档时间: |
|
| 查看次数: |
9337 次 |
| 最近记录: |