저는 공용 인터넷이 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=false
Docker 서비스 구성을 설정하여 모든 것을 비활성화하십시오 . (이 블로그 게시물이 옵션에 대해 논의합니다)
나도게시물을 찾았습니다체인 옵션 의 좋은 변형이라고 생각했습니다 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