리눅스에선 방화벽을 관리할 때는 기본적으로 iptables를 사용합니다.
도커를 운용하게 되면 이전에 관리하던 것 처럼 iptables로 방화벽 관리하면 된다고 생각 하지만, 도커는 패킷이 도달하기 전에 Forward 체인에서 docker 체인으로 바로 넘어가기 때문에 docker 컨테이너들은 방화벽을 우회하게 됩니다.
그래서 공식적으로 도커에선 Docker User라는 체인을 사용하라고 권장합니다. 도커 체인으로 넘어가기 전에 Docker User체인을 먼저 거치도록 작동되어 컨테이너로 들어가는 방화벽을 관리 할 수 있습니다.
1. 도커 방화벽 관리의 한계점들
하지만 실무에서 DOCKER-USER 체인을 수동으로만 관리하기에는 까다로운 걸림돌이 많습니다. 흔히 생각하는 대안들과 그 한계점은 다음과 같습니다.
-
도커 재시작 시 규칙 증발:
DOCKER-USER규칙은 커널 메모리에 실시간으로 올라가므로, 도커 서비스 전체를 재시작하게 되면 iptables 또한 초기화되어 기존에 넣었던 룰셋은 사라지게 됩니다. -
컨테이너 동적 IP 변경 문제: 그러면
iptables-persistent나firewalld로 룰셋을 저장 관리하면 된다고 생각하지만 도커를 재시작하게 되면 컨테이너의 ip 주소가 변경됩니다. 그로인해 이전 ip가 저장되어 다시 적용을 하게 되면 통신이 안될 수 있습니다. (conntrack 패키지를 사용하거나 고정 ip를 사용하면 가능합니다.) -
"iptables": false옵션의 부작용: 도커 설정에서 아예 iptables를 사용안함(false)으로 변경해서 사용하는 방법도 있지만 이는 권장되는 방법은 아닙니다. (컨테이너 아웃바운드 NAT 등이 작동하지 않아 관리가 더욱 어려워짐) -
UFW 환경의 대안: ufw를 사용하는 환경이라면
ufw-docker라는 오픈소스 서비스를 사용해 보는것도 좋은 방법이 될 수 있습니다. - 외부 방화벽 사용: 외부 방화벽을 사용하여 이러한 문제를 정석으로 방화벽을 관리하는 방법도 있습니다.
따라서 서버 관리자가 도커를 운용 할 때는 방화벽 관리가 여간 불편한게 아닙니다.
2. 스크립트와 Systemd를 이용한 자동 관리
그래서 그나마 괜찮은 방법을 찾아 소개해 보려고 합니다. 바로 스크립트를 이용한 관리 방법입니다.
스크립트를 활용해 시스템 데몬과 연동해 두면, 도커가 실행될 때 iptables 차단 룰셋이 자동으로 들어가도록 구성할 수 있습니다. 이 방식은 컨테이너 내부 IP 변경에 영향을 받지 않고, 외부 입구 인터페이스와 악성 출발지 IP만 지정해서 깔끔하게 차단할 수 있습니다.
주의 사항 : INPUT 체인은 따로 관리해야 합니다
이 스크립트에서 관리하는 영역은 오직 ‘도커 컨테이너로 향하는 길목(DOCKER-USER)’뿐입니다. DOCKER-USER에 악성 IP를 막아두어도, 그 IP가 우리 서버 자체의 SSH(22번 포트)나 호스트에 직접 설치된 서비스들을 찌르고 들어오는 것은 막지 못합니다.
그러므로 서버 자체 접근도 차단해야 하니까, 기존 방화벽(UFW나 INPUT 체인 룰셋)에도 차단 규칙을 따로 넣어서 이중으로 관리를 해야 합니다. 이 스크립트는 철저히 도커 전용 방화벽 분리 관리용으로만 사용합니다.
구체적인 설정 순서는 다음과 같습니다.
3. 단계별 구축 방법
[Step 1] 방화벽 주입 스크립트 작성
먼저 서버 부팅이나 도커 재시작 시 실시간으로 실행될 쉘 스크립트 파일을 생성합니다.
sudo vim /usr/local/bin/docker-firewall.sh
내용은 복잡한 반복문 없이 명령어를 한 줄씩 리스트 형태로 나열합니다. 나중에 차단할 IP가 늘어나면 아래에 그대로 복사해서 추가하면 됩니다.
1. 블랙리스트 방식
#!/bin/bash # 등록 전 DOCKER-USER 체인 초기화 iptables -F DOCKER-USER # ens3로 들어오는 패킷 중, 이미 연결된 세션(Established)은 통과 iptables -A DOCKER-USER -i ens3 -m conntrack --ctstate RELATED,ESTABLISHED -j RETURN # 차단 규칙 DOCKER-USER 체인 최상단 추가 iptables -A DOCKER-USER -i ens3 -s 211.xxx.xxx.xxx -j DROP iptables -A DOCKER-USER -i ens3 -s 118.xxx.xxx.xxx -j DROP iptables -A DOCKER-USER -i ens3 -s 220.xxx.xxx.0/24 -j DROP
2. 화이트리스트 방식
#!/bin/bash # 등록 전 DOCKER-USER 체인 초기화 iptables -F DOCKER-USER # ens3로 들어오는 패킷 중, 이미 연결된 세션(Established)은 통과 iptables -A DOCKER-USER -i ens3 -m conntrack --ctstate RELATED,ESTABLISHED -j RETURN # 허용할 특정 IP/대역들을 DOCKER-USER 체인 상단에 추가 iptables -A DOCKER-USER -i ens3 -s 211.xxx.xxx.xxx -j RETURN iptables -A DOCKER-USER -i ens3 -s 118.xxx.xxx.xxx -j RETURN iptables -A DOCKER-USER -i ens3 -s 220.xxx.xxx.0/24 -j RETURN # ens3로 들어오는 외부 트래픽 차단(DROP) iptables -A DOCKER-USER -i ens3 -j DROP
파일을 저장하고 나온 뒤, 스크립트가 실행될 수 있도록 권한을 부여합니다.
sudo chmod +x /usr/local/bin/docker-firewall.sh
[Step 2] Systemd 서비스 등록
도커 서비스가 재시작되면서 iptables 체인을 밀어버리더라도, 도커가 켜진 직후에 이 스크립트가 바로 따라 들어가서 규칙을 재주입하도록 systemd 서비스로 등록합니다.
sudo vim /etc/systemd/system/docker-firewall.service
아래 내용을 붙여넣고 저장합니다.
[Unit] Description=Docker Custom Firewall Rules (DOCKER-USER) After=docker.service Requires=docker.service [Service] Type=oneshot RemainAfterExit=yes ExecStart=/usr/local/bin/docker-firewall.sh [Install] WantedBy=multi-user.target
[Step 3] 서비스 활성화 및 적용 설정이 끝났다면 데몬을 새로고침하고, 부팅 시 자동 실행 등록과 동시에 지금 즉시 서비스를 구동시킵니다.
# systemd 매니저 구성 새로고침 sudo systemctl daemon-reload # 서비스 활성화 및 즉시 실행 sudo systemctl enable --now docker-firewall.service
[Step 4] 정상 작동 확인
이제 실제로 규칙이 커널에 잘 주입되었는지 테스트해 보기 위해 도커 서비스를 재시작해 봅니다.
sudo systemctl restart docker
도커가 껐다 켜지면서 iptables를 한 번 밀었겠지만, 우리가 만든 docker-firewall 서비스가 곧바로 뒤따라가며 규칙을 다시 꽂아주게 됩니다. 아래 명령어로 확인해 봅니다.
sudo iptables -L DOCKER-USER -n -v --line-numbers Chain DOCKER-USER (1 references) num pkts bytes target prot opt in out source destination 1 0 0 DROP all -- eth0 * 220.xxx.xxx.0/24 0.0.0.0/0 2 12 720 DROP all -- eth0 * 118.xxx.xxx.xxx 0.0.0.0/0 3 5 300 DROP all -- eth0 * 211.xxx.xxx.xxx 0.0.0.0/0 4 2450 147K RETURN all -- * * 0.0.0.0/0 0.0.0.0/0
조회해 보면 DOCKER-USER 체인 최상단에 우리가 지정한 악성 IP들이 DROP 상태로 정상 반영되어 있는 것을 볼 수 있습니다.
마치며
개별 컨테이너를 재시작(docker restart)할 때는 iptables가 날아가지 않으니 가만히 유지되고, 도커 서비스 전체가 재기동되거나 서버가 리부팅될 때만 이 스크립트가 자동 복구를 해줍니다.
리눅스 자체 기능만으로 도커 네트워크를 제어할 수 있는 하나의 방법으로 참고해 보셨으면 좋겠습니다.
본 글은 AI를 참고하여 작성 하였습니다.




