【问题标题】:Docker: How to re-create dockers additional iptables rules?Docker:如何重新创建 dockers 的附加 iptables 规则?
【发布时间】:2014-11-13 02:31:47
【问题描述】:

当 docker-demon 启动时,它会向 iptables 添加一些规则。 当通过iptables -F 删除所有规则时,我必须停止并重新启动 docker 恶魔以重新创建 dockers 规则。

有没有办法让 docker 重新添加它的附加规则?

【问题讨论】:

    标签: docker iptables


    【解决方案1】:

    最好的方法是重启你的 docker 服务,然后它将你的 docker 规则重新添加到 iptables。 (基于 deb:sudo service docker restart

    但是,如果您只是想在不重新启动服务的情况下恢复这些规则,我保存了我的规则,以便您检查并调整它以适合您,然后使用 sudo iptables-restore ./iptables-docker-ports.backup 加载

    编辑并保存到./iptables-docker-ports.backup

    # Generated by iptables-save v1.4.21 on Thu Apr 30 20:48:42 2015
    *nat
    :PREROUTING ACCEPT [18:1080]
    :INPUT ACCEPT [18:1080]
    :OUTPUT ACCEPT [22:1550]
    :POSTROUTING ACCEPT [22:1550]
    :DOCKER - [0:0]
    -A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
    -A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER
    -A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE
    -A POSTROUTING -s 172.17.0.1/32 -d 172.17.0.1/32 -p tcp -m tcp --dport 80 -j MASQUERADE
    -A DOCKER ! -i docker0 -p tcp -m tcp --dport 3001 -j DNAT --to-destination 172.17.0.1:80
    COMMIT
    # Completed on Thu Apr 30 20:48:42 2015
    # Generated by iptables-save v1.4.21 on Thu Apr 30 20:48:42 2015
    *filter
    :INPUT ACCEPT [495:53218]
    :FORWARD ACCEPT [0:0]
    :OUTPUT ACCEPT [480:89217]
    :DOCKER - [0:0]
    -A FORWARD -o docker0 -j DOCKER
    -A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
    -A FORWARD -i docker0 ! -o docker0 -j ACCEPT
    -A FORWARD -i docker0 -o docker0 -j ACCEPT
    -A DOCKER -d 172.17.0.1/32 ! -i docker0 -o docker0 -p tcp -m tcp --dport 80 -j ACCEPT
    COMMIT
    # Completed on Thu Apr 30 20:48:42 2015
    

    【讨论】:

    • 非常感谢,这是我唯一找到默认 docker 配置来重置我的 iptables 规则的帖子,完美!
    • 这将停止您的容器!重新启动 docker 服务会停止所有容器。不是解决方案。
    【解决方案2】:

    如果您在主机上运行 Ubuntu,则可以在启动 docker 守护程序后使用iptables-save 实用程序将 iptables 规则保存到文件中。然后,刷新旧规则后,您可以使用 iptables-restore 和保存的规则文件简单地恢复原始 docker 规则。

    如果您不想恢复所有旧的 iptables 规则,您可以更改保存的规则文件以仅保留您需要的规则。

    如果您运行的是其他操作系统,您可能会找到类似的替代方案。

    【讨论】:

    • docker 的规则总是一样的吗?我可以将它们永久添加到我的 iptables-restore 配置文件中吗?
    • 详细说明:我使用 iptables-persistent 和自定义规则文件作为防火墙。每当我需要打开一个端口时,我都会编辑我的规则文件并使用iptables-apply 应用它。我在我的规则文件中保留了一个干净的结构和大量用于文档的 cmets,因此覆盖它不是一种选择。
    • 小心盲目地保存/恢复规则,因为容器的 IP 在重启时会发生变化!
    【解决方案3】:

    默认配置下的 Docker,在 bridge 模式下运行时,确实会操纵 iptables(很多)unless you disable it(然后您必须配置自己的 NAT 规则)。

    默认的网络相关配置可能如下,尽管配置 /etc/docker/daemon.json 可能不存在(现在 you can't print effective configuration):

    {
    "userland-proxy": true,
    "iptables": true,
    "ip-forward": true,
    "ip-masq": true,
    "ipv6": false
    }
    

    Docker daemon 启动后,会注入以下规则(filter):

    -N DOCKER
    -N DOCKER-ISOLATION-STAGE-1
    -N DOCKER-ISOLATION-STAGE-2
    -N DOCKER-USER
    
    -A FORWARD -j DOCKER-USER
    -A FORWARD -j DOCKER-ISOLATION-STAGE-1
    -A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
    -A FORWARD -o docker0 -j DOCKER
    -A FORWARD -i docker0 ! -o docker0 -j ACCEPT
    -A FORWARD -i docker0 -o docker0 -j ACCEPT
    
    -A DOCKER-ISOLATION-STAGE-1 -i docker0 ! -o docker0 -j DOCKER-ISOLATION-STAGE-2
    -A DOCKER-ISOLATION-STAGE-1 -j RETURN
    -A DOCKER-ISOLATION-STAGE-2 -o docker0 -j DROP
    -A DOCKER-ISOLATION-STAGE-2 -j RETURN
    -A DOCKER-USER -j RETURN
    

    为了了解 Docker 的作用,这里是 a list of Docker-generated iptables rules 并附有简短说明。如果你刷新 iptables 规则,而 Docker 守护进程和一些容器正在运行,你可能会破坏对现有容器的访问(但可能不会破坏任何东西,下面会详细介绍)。

    service docker restart 后所有默认规则都注入防火墙(您可以通过运行iptables-saveiptables -Siptables -S -t nat 来检查它)。假设您想保持容器运行并且只生成缺少的 NAT 规则。

    docker ps 为我们提供了正在运行的容器列表:

    CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                         NAMES
    865569da8d36        nginx               "nginx -g 'daemon of…"   17 hours ago        Up 17 hours         0.0.0.0:4564->80/tcp, 0.0.0.0:32237->80/tcp   jovial_sammet
    

    docker inspect我们可以得到端口映射

    $ docker inspect -f '{{.NetworkSettings.Ports}}' 865569da8d36
    map[80/tcp:[{0.0.0.0 4564} {0.0.0.0 32237}]]
    

    现在我们只需要 Docker 容器的内部 IP 地址:

    $ docker inspect -f '{{.NetworkSettings.IPAddress}}' 865569da8d36
    172.17.0.2
    

    现在使用一些 bash/jq 我们可以generate the dynamic iptables rules:

    $ bash docker_iptables --noop
    iptables -A DOCKER -d 172.17.0.2
    iptables -t nat -A DOCKER ! -i docker0 -p tcp -m tcp --dport 4564 -j DNAT --to-destination 172.17.0.2:80
    iptables -A DOCKER -d 172.17.0.2
    iptables -t nat -A DOCKER ! -i docker0 -p tcp -m tcp --dport 32237 -j DNAT --to-destination 172.17.0.2:80
    

    所以问题的答案是:不,不停止所有容器。但是可以手动重新添加规则(注意:此脚本不涵盖所有 Docker 功能,例如,如果您要公开在 Docker 容器以外的其他网络中运行的某些服务)。

    当您使用暴露的端口 (-p) 启动 Docker 容器时:

    docker run --rm -d -p 32237:80 -p 4564:80 nginx
    

    Docker 也启动了 docker-proxy。那是什么?

    $ netstat -tulpn | grep docker-proxy
    tcp        0      0 0.0.0.0:32237           0.0.0.0:*               LISTEN      20487/docker-proxy  
    tcp        0      0 0.0.0.0:4564            0.0.0.0:*               LISTEN      20479/docker-proxy
    

    Linux 内核不允许环回流量的路由,因此无法将 netfilter NAT 规则应用于来自 127.0.0.0/8 的数据包。 docker-proxy is generally considered as an inelegant solution to such problems

    当您在没有 Docker 规则的情况下恢复 iptables 时,容器端口可能仍可通过 docker-proxy 使用。不过这可能会带来一些performance issues in networking,因为docker-proxy 不会像内核的netfilter 一样快。

    【讨论】:

      猜你喜欢
      • 2023-01-26
      • 1970-01-01
      • 2015-07-17
      • 2018-03-29
      • 1970-01-01
      • 1970-01-01
      • 2018-01-11
      • 2013-09-05
      • 2019-10-05
      相关资源
      最近更新 更多