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

后端 未结 3 954
心在旅途
心在旅途 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:08

    If you're running Ubuntu on the host, you can use the iptables-save utility to save the iptables rules to a file after you start the docker daemon. Then, once you flush the old rules, you can simply restore the original docker rules using iptables-restore & the saved rules file.

    If you don't want to restore all the old iptables rules, you can alter the saved rules file to keep only the ones you need.

    If you're running another operating system, you might find a similar alternative.

    0 讨论(0)
  • 2020-12-24 06:14

    the best way is to restart your docker service, then it'll re-add your docker rules to iptables. (on deb-based: sudo service docker restart)

    however, if you just want to restore those rules without restarting your service, i saved mine so you can inspect, and adjust it to work for you, then load using sudo iptables-restore ./iptables-docker-ports.backup

    edit and save this to ./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
    
    0 讨论(0)
  • 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.

    0 讨论(0)
提交回复
热议问题