[Troubleshooting] 호스트 iptables에 포트를 열었는데 Docker 컨테이너는 왜 그대로 막힐까?

호스트 iptables INPUT에 포트 allow 룰을 추가했는데,
Docker 컨테이너 -p host:container 포트는 여전히 접속이 안 되는 경우가 있다.

결론부터 말하면 이렇다.

Docker 퍼블리시 포트 트래픽은 INPUT이 아니라 FORWARD → DOCKER(-USER) 체인에서 처리된다.
그래서 INPUT에 아무리 룰을 쌓아도, DOCKER 계열 체인에서 DROP이면 그대로 차단된다.


왜 INPUT이 안 먹히나

Docker 포트 퍼블리시 트래픽 흐름은 보통 다음과 같다.

외부 → DNAT → FORWARD → DOCKER-USER → DOCKER → 컨테이너

즉, 컨테이너로 가는 트래픽은 호스트 로컬 프로세스가 아니라 포워딩 트래픽이다.
따라서 차단/허용은 DOCKER 또는 DOCKER-USER에서 해야 한다.


빠른 진단

iptables -L DOCKER -n --line-numbers
iptables -L DOCKER-USER -n --line-numbers

아래 같은 룰이 있으면 사실상 “전부 차단” 상태다.

  • -p tcp --dport 0:65535 -j DROP
  • 조건 없는 broad DROP

가장 위험한 함정 (중요)

❌ DOCKER-USER에서 --dport만 보고 막으면 안된다.

아래 같은 룰은 흔하지만, 운영에선 위험하다.

iptables -I DOCKER-USER -p tcp --dport 8080 -j DROP

이유

DOCKER-USER 체인은 DNAT이 적용된 이후에 동작한다.
즉, 이 시점의 --dport 8080은 **외부 포트가 아니라 “컨테이너 내부 포트”**다.

그래서 이런 상황이 발생한다.

  • 컨테이너 A: -p 9000:8080
  • 컨테이너 B: -p 8080:8080

의도: “외부 8080만 차단”
현실: 내부 포트가 8080인 모든 컨테이너가 같이 차단

이게 운영에서 터지면, 포트만 다르게 분리한 서비스들이 한 번에 죽는다.


안전한 패턴 (권장)

원칙

아래 rule을 문법상 DOCKER로 변경해도 되지만,
운영에서는 DOCKER-USER를 사용하기를 권장한다.

  • ESTABLISHED,RELATED 먼저 허용
  • 차단 대상은 포트가 아니라 ‘컨테이너 IP’로 좁힌다
  • 마지막에 RETURN

예시: 특정 컨테이너만 제어

# 응답 트래픽 허용
iptables -I DOCKER-USER 1 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

# 특정 컨테이너 IP만 대상
iptables -I DOCKER-USER 2 -d 172.17.0.10/32 -p tcp --dport 8080 -s 203.0.113.10/32 -j ACCEPT
iptables -I DOCKER-USER 3 -d 172.17.0.10/32 -p tcp --dport 8080 -j DROP

# 나머지는 Docker 기본 흐름으로
iptables -A DOCKER-USER -j RETURN

포인트:

  • “외부 포트” 기준 제어가 아니라
    “어느 컨테이너로 가는 트래픽인가” 기준으로 제어한다.
  • 그래야 DNAT 이후 구조에서도 사이드 이펙트가 없다.

Tip (운영상 고려대상)

컨테이너 재생성/서버 재부팅 시 컨테이너 내부 IP가 바뀔 수 있다.
운영 환경에서는 다음 중 하나로 안정성을 확보하는 것을 권고.

  • 사용자 정의 bridge 네트워크 + Static IP로 고정 (가장 권장)
  • 또는 외부 포트 기준 매칭이 필요하면 conntrack의 original tuple(예: --ctorigdstport) 기반 룰을 검토
    (단, conntrack 엔트리/커널 모듈/룰 적용 위치에 따라 동작이 달라질 수 있으므로 테스트 필수)

Rule 저장 (재부팅 대비)

  • DOCKER / DOCKER-USER 룰은 재부팅 시 사라질 수 있다.
  • 아래 명령어를 통해 저장을 하도록 한다.
netfilter-persistent save

한 줄 요약

  • Docker 퍼블리시 포트는 INPUT이 아니라 DOCKER(-USER)에서 제어한다
  • DOCKER-USER에서 --dport는 내부 포트 기준이므로, 컨테이너 단위로 좁혀라

이 두 가지만 기억하면, Docker iptables 관련 사고의 90%는 피한다.

🛠 마지막 수정일: 2025.12.26

💡 도움이 필요하신가요?
Zabbix, Kubernetes, 그리고 다양한 오픈소스 인프라 환경에 대한 구축, 운영, 최적화, 장애 분석, 광고 및 협업 제안이 필요하다면 언제든 편하게 연락 주세요.

📧 Contact: jikimy75@gmail.com
💼 Service: 구축 대행 | 성능 튜닝 | 장애 분석 컨설팅

📖 E-BooK [PDF] 전자책 (Gumroad): Zabbix 엔터프라이즈 최적화 핸드북
블로그에서 다룬 Zabbix 관련 글들을 기반으로 실무 중심의 지침서로 재구성했습니다. 운영 환경에서 바로 적용할 수 있는 최적화·트러블슈팅 노하우까지 모두 포함되어 있습니다.


💡 Need Professional Support?
If you need deployment, optimization, or troubleshooting support for Zabbix, Kubernetes, or any other open-source infrastructure in your production environment, or if you are interested in sponsorships, ads, or technical collaboration, feel free to contact me anytime.

📧 Email: jikimy75@gmail.com
💼 Services: Deployment Support | Performance Tuning | Incident Analysis Consulting

📖 PDF eBook (Gumroad): Zabbix Enterprise Optimization Handbook
A single, production-ready PDF that compiles my in-depth Zabbix and Kubernetes monitoring guides.

What are your feelings

Updated on 2025-12-26