5 min read

docker swarm's iptables

docker swarm's iptables
Photo by Sebastian Pena Lambarri / Unsplash

이전 포스팅 docker swarm에 이어서, 여기서는 swarm 통한 nginx 서비스 구축 후 iptables가 어떻게 셋팅되는 지 보도록 한다.

앞에서 설명한 내용에 기반하여, swarm 기반 nginx 서비스는 다음과 같이 구축했다.
CentOS 7 기반이다.

$ docker swarm init --advertise-addr 192.168.61.6
$ docker network create --driver overlay dvg_net
$ docker service create --name dvg_web --network dvg_net nginx:alpine
$ docker service create --name dvg_busybox --network dvg_net busybox sleep 86400
$ docker service update --publish-add published=80,target=80 dvg_web

요약하자면, 192.168.61.6 상에 단일 node로 swarm을 설치했고, dvg_net overlay 네트워크를 추가한 다음 nginx 기반의 dvg_web 서비스와 busybox 기반의 dvg_busybox 서비스를 생성했다. 마지막으로 dvg_web에 80번 port를 오픈하여 외부에서도 접근할 수 있도록 했다.
이 중 busybox 사용한 dvg_busybox 서비스 설치는 생략해도 된다.

설치 전/후에 docker network ls로 확인한 네트워크 목록은 다음과 같다.

NETWORK ID     NAME      DRIVER    SCOPE
7bc54b953c57   bridge    bridge    local
88d02561add3   host      host      local
0102130c5a4b   none      null      local

NETWORK ID     NAME              DRIVER    SCOPE
7bc54b953c57   bridge            bridge    local
c3fb70dc7592   docker_gwbridge   bridge    local  # swarm 생성 시 자동 생성
lghg9ceculyj   dvg_net           overlay   swarm  # 직접 추가
88d02561add3   host              host      local
sodvstaktzgi   ingress           overlay   swarm  # swarm 생성 시 자동 생성
0102130c5a4b   none              null      local

docker network inspect ... 명령으로 각 네트워크에 할당된 prefix를 정리하면 다음과 같다.

  • bridge: 172.17.0.0/16
  • docker_gwbridge: 172.18.0.0/16
  • dvg_net: 10.0.1.0/24
  • ingress: 10.0.0.0/24

이제 iptables rule들을 보도록 하자. 먼저 docker 설치 후 iptables의 filter와 nat 테이블의 룰 리스트다.

$ iptables -S
-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

$ iptables -S -t nat
-N DOCKER
-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 DOCKER -i docker0 -j RETURN

docker에서 추가하는 chain 중 DOCKER-ISOLATION-STAGE-1, DOCKER-ISOLATION-STAGE-2 chain은 docker bridge 간 격리를 위한 것이다. 지금은 docker0 하나에만 적용되어 있어서 이해하기가 쉽지 않지만, swarm 추가 후 docker_gwbridge 관련 rule이 추가되면 보다 이해하기 쉬울 것이다.

마지막으로 DOCKER-USER chain을 거치는데, 여기에 각 사용자가 원하는 추가 iptables rule을 추가하면 된다. 그 외 다른 DOCKER* chain은 docker가 관리하는 것이므로, 가급적 직접 건드리지 않도록 한다.

다음은 포스팅 처음의 swarm 추가 및 dvg_web 서비스 추가 작업에 따라 iptables에 추가되는 chain 및 rule이다.

filter (default) table:
-N DOCKER-INGRESS
-A FORWARD -j DOCKER-INGRESS
-A FORWARD -o docker_gwbridge -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -o docker_gwbridge -j DOCKER
-A FORWARD -i docker_gwbridge ! -o docker_gwbridge -j ACCEPT
-A FORWARD -i docker_gwbridge -o docker_gwbridge -j DROP
-A DOCKER-INGRESS -p tcp -m tcp --dport 80 -j ACCEPT
-A DOCKER-INGRESS -p tcp -m state --state RELATED,ESTABLISHED -m tcp --sport 80 -j ACCEPT
-A DOCKER-INGRESS -j RETURN
-A DOCKER-ISOLATION-STAGE-1 -i docker_gwbridge ! -o docker_gwbridge -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-2 -o docker_gwbridge -j DROP

nat table:
-N DOCKER-INGRESS
-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER-INGRESS
-A OUTPUT -m addrtype --dst-type LOCAL -j DOCKER-INGRESS
-A POSTROUTING -o docker_gwbridge -m addrtype --src-type LOCAL -j MASQUERADE
-A POSTROUTING -s 172.18.0.0/16 ! -o docker_gwbridge -j MASQUERADE
-A DOCKER -i docker_gwbridge -j RETURN
-A DOCKER-INGRESS -p tcp -m tcp --dport 80 -j DNAT --to-destination 172.18.0.2:80
-A DOCKER-INGRESS -j RETURN

docker_gwbridge 인터페이스가 추가됐고 그 외에 ingress overlay network를 위한 DOCKER-INGRESS filter가 추가된 것을 볼 수 있다. 그리고 dvg_web에서 publish한 tcp 80 port 관련 rule을 확인할 수 있을 것이다.

다음은 iptables -vnL 명령의 실행 결과를 발췌 요약한 것이다. INPUT, OUTPUT, DOCKER 등 rule이 없는 chain들을 생략하고, anywhere (0.0.0.0/0)로 동일한 값을 가지는 source, destination 필드와 packet/byte count 등 불필요한 정보도 생략했다.
(이건 다 docker_gw 뭐시기와 DOCKER-ISOLATION- 뭐시기 이름이 너무 길어서 그런 거다)

Chain FORWARD (policy DROP 0 packets, 0 bytes)
 target                    prot opt in              out
 DOCKER-USER               all  --  *               *
 DOCKER-INGRESS            all  --  *               *
 DOCKER-ISOLATION-STAGE-1  all  --  *               *
 ACCEPT                    all  --  *               docker_gwbridge    ctstate RELATED,ESTABLISHED
 DOCKER                    all  --  *               docker_gwbridge
 ACCEPT                    all  --  docker_gwbridge !docker_gwbridge
 ACCEPT                    all  --  *               docker0            ctstate RELATED,ESTABLISHED
 DOCKER                    all  --  *               docker0
 ACCEPT                    all  --  docker0         !docker0
 ACCEPT                    all  --  docker0         docker0
 DROP                      all  --  docker_gwbridge docker_gwbridge

Chain DOCKER-INGRESS (1 references)
 target                    prot opt in              out
 ACCEPT                    tcp  --  *               *                  tcp dpt:80
 ACCEPT                    tcp  --  *               *                  state RELATED,ESTABLISHED tcp spt:80
 RETURN                    all  --  *               *

Chain DOCKER-ISOLATION-STAGE-1 (1 references)
 target                    prot opt in              out
 DOCKER-ISOLATION-STAGE-2  all  --  docker_gwbridge !docker_gwbridge
 DOCKER-ISOLATION-STAGE-2  all  --  docker0         !docker0
 RETURN                    all  --  *               *

Chain DOCKER-ISOLATION-STAGE-2 (2 references)
 target                    prot opt in              out
 DROP                      all  --  *               docker_gwbridge
 DROP                      all  --  *               docker0
 RETURN                    all  --  *               *

Chain DOCKER-USER (1 references)
 target                    prot opt in              out
 RETURN                    all  --  *               *

참고목록

— END OF POST.