Docker: How to re-create dockers additional iptables rules?

后端 未结 3 953
心在旅途
心在旅途 2020-12-24 05:57

When the docker-demon starts it adds a couple of rules to iptables. When all rules are deleted via iptables -F i have to stop and restart the docker demon to r

3条回答
  •  囚心锁ツ
    2020-12-24 06:35

    Docker in default configuration, when running in bridge mode, does manipulate iptables (a lot) unless you disable it (then you would have to configure your own NAT rules).

    The default network-related configuration is probably following, although the config /etc/docker/daemon.json might not exist (and as of now you can't print effective configuration):

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

    After Docker daemon starts, it injects following rules (in 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
    

    In order to understand what Docker does, here is a list of Docker-generated iptables rules with a short explanation. If you flush iptables rules, while Docker daemon and some containers are running, you might break access to existing containers (but probably won't break anything, more about this below).

    After service docker restart all default rules are injected into firewall (you can check it by running iptables-save or iptables -S, iptables -S -t nat). Assuming you want to keep your containers running and only generate missing NAT rules.

    docker ps gives us list of running containers:

    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
    

    And from docker inspect we can obtain the port mapping

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

    now we need just the internal IP address of Docker container:

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

    Now using some bash/jq we can 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
    

    So the answer to the question is: No, not without stopping all containers. But the rules can be re-added manually (NOTE: this script doesn't cover all Docker functionality, e.g. if you're exposing some service running in other network than Docker container).

    When you start Docker container with exposed ports (-p):

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

    Docker spins up also docker-proxy. What's that?

    $ 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
    

    The Linux kernel does not allow the routing of loopback traffic, and therefore it's not possible to apply netfilter NAT rules to packets originating from 127.0.0.0/8. docker-proxy is generally considered as an inelegant solution to such problems.

    When you restore iptables without Docker rules, the container ports might be still available via docker-proxy. However this might bring some performance issues in networking, as docker-proxy won't be as fast as kernel's netfilter.

提交回复
热议问题