방화벽이 Docker 컨테이너에 바인딩된 비공개 포트에 대한 공용 트래픽을 허용하는 이유는 무엇입니까?

방화벽이 Docker 컨테이너에 바인딩된 비공개 포트에 대한 공용 트래픽을 허용하는 이유는 무엇입니까?

저는 공용 인터넷이 SSH, HTTP, HTTPS 및 Cockpit에 액세스할 수 있지만 그 외에는 액세스할 수 없는 매우 간단한 방화벽을 Fedora에 구현하려고 합니다. 한편 서버는 포트 8000-8999에서 서로 통신할 수 있는 Docker를 통해 마이크로서비스를 실행합니다.

네트워크 다이어그램

다음 명령을 사용하여 새로운 Fedora Server 설치에서 이를 설정했습니다.

firewall-cmd --zone=public --add-service=cockpit
firewall-cmd --zone=public --add-service=http
firewall-cmd --zone=public --add-service=https

firewall-cmd --zone=internal --add-source=192.168.1.65
firewall-cmd --zone=internal --add-source=192.168.1.66

firewall-cmd --zone=internal --add-port=8000-8999/tcp

firewall-cmd --runtime-to-permanent

으로 구성을 확인하면 --list-all모든 것이 올바르게 보입니다.

> firewall-cmd --list-all --zone=internal
internal (active)
  target: default
  icmp-block-inversion: no
  interfaces:
  sources: 192.168.1.65 192.168.1.66
  services: dhcpv6-client ssh
  ports: 8000-8999/tcp
  protocols:
  forward: no
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:

> firewall-cmd --list-all --zone=public
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: enp2s0
  sources:
  services: cockpit dhcpv6-client http https ssh
  ports:
  protocols:
  forward: no
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:

하지만 이것을 테스트하면http://192.168.1.65:8080. 동일한 내부 네트워크(192.168.128.128)에 있는 컴퓨터뿐만 아니라 외부 컴퓨터의 공개 요청에서도 이를 실행할 수 있습니다. 둘 다 internal' 에 나열되어 있지 않기 때문에 sources방화벽이 요청을 허용하지 않을 것이라고 가정했습니다.

docker인터페이스 가 있는 자동 구성 영역이 있지만 docker0이를 제거해도 내부 포트에 접속하는 기능은 변경되지 않는 것 같습니다.

에 나열되지 않은 소스에서 :8080을 성공적으로 요청할 수 있는 이유는 무엇입니까 internal?

답변1

글쎄, 문제는 내부 포트에 Docker를 사용하고 있다는 사실에서 비롯된 것으로 나타났습니다. 컨테이너가 전 세계 및 서로 통신하도록 하는 프로세스를 단순화하기 위해 Docker는 방화벽/네트워킹에 대해 많은 양의 제어를 수행하기로 결정했습니다. 즉, 만약 당신이~하지 않다컨테이너를 공개적으로 액세스할 수 있기를 원함그리고Docker 데몬과 동일한 시스템에서 방화벽을 통해 공개 액세스를 제어해야 하며, 방화벽을 약간 다르게 구성해야 합니다.Docker에는 이를 수행하는 방법에 대한 공식 문서가 있습니다.. 기본적으로 다음과 같은 옵션이 있습니다.

  • 방화벽 전용 시스템을 별도로 설정하세요. Docker와 방화벽이 리소스를 공유할 필요가 없기 때문에 이것이 아마도 가장 쉬울 것입니다.
  • iptables체인 에 규칙을 추가하세요 DOCKER-USER(이것은 사용자를 위한 답변에 가깝습니다 . 이 접근 방식을 복제하는 iptables방법을 잘 모르겠습니다 ).firewalld
  • iptables=falseDocker 서비스 구성을 설정하여 모든 것을 비활성화하십시오 . (이 블로그 게시물이 옵션에 대해 논의합니다)

나도게시물을 찾았습니다체인 옵션 의 좋은 변형이라고 생각했습니다 DOCKER-USER. 기본적 iptables.conf으로 . iptables-restore -n안타깝게도 이는 iptables해결책이 아니라 firewalld해결책입니다.

이 문제를 진단할 때 어려운 부분 중 하나는 내가 원하는 것과 일치하도록 방화벽을 수정하는 스크립트를 실행하는 것이었습니다. 이 작업은 컴퓨터를 다시 시작하거나 Docker 데몬을 시작할 때까지 작동했습니다. Docker는 iptables시작 시 구성을 덮어씁니다.

답변2

체인 을 다시 생성하여 이 문제를 해결했으며 DOCKER-USER다른 사람이 유용하다고 생각하는 경우를 대비해 공유하고 싶습니다.

이는 Github에서 찾은 솔루션을 기반으로 합니다(https://github.com/firewalld/firewalld/issues/869) 그리고 어떤 천재의 블로그(https://roosbertl.blogspot.com/2019/06/securing-docker-ports-with-firewalld.html) 하지만 조금 조정/정제해야 했습니다.

# 1. Stop Docker
systemctl stop docker.socket
systemctl stop docker.service

# 2. Recreate DOCKER-USER iptables chain with firewalld. Ignore warnings, do not ignore errors
firewall-cmd --permanent --direct --remove-chain ipv4 filter DOCKER-USER
firewall-cmd --permanent --direct --remove-rules ipv4 filter DOCKER-USER
firewall-cmd --permanent --direct --add-chain ipv4 filter DOCKER-USER

# 3. Add iptables rules to DOCKER-USER chain - unrestricted outbound, restricted inbound to private IPs
firewall-cmd --permanent --direct --add-rule ipv4 filter DOCKER-USER 1 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -m comment --comment 'Allow containers to connect to the outside world'
firewall-cmd --permanent --direct --add-rule ipv4 filter DOCKER-USER 1 -j RETURN -s 127.0.0.0/8 -m comment --comment 'allow internal docker communication, loopback addresses'
firewall-cmd --permanent --direct --add-rule ipv4 filter DOCKER-USER 1 -j RETURN -s 172.16.0.0/12 -m comment --comment 'allow internal docker communication, private range'

# 3.1 optional: for wider internal networks
firewall-cmd --permanent --direct --add-rule ipv4 filter DOCKER-USER 1 -j RETURN -s 10.0.0.0/8 -m comment --comment 'allow internal docker communication, private range'
firewall-cmd --permanent --direct --add-rule ipv4 filter DOCKER-USER 1 -j RETURN -s 192.168.0.0/16 -m comment --comment 'allow internal docker communication, private range'

# 4. Block all other IPs. This rule has lowest precedence, so you can add rules before this one later.
firewall-cmd --permanent --direct --add-rule ipv4 filter DOCKER-USER 10 -j REJECT -m comment --comment 'reject all other traffic to DOCKER-USER'

# 5. Activate rules
firewall-cmd --reload

# 6. Start Docker
systemctl start docker.socket
systemctl start docker.service

관련 정보