Rocky Linux 및 AlmaLinux firewalld 설정 가이드
Rocky Linux와 AlmaLinux에서 firewalld를 사용하여 SSH 허용, 웹 포트 개방 및 차단하는 방법을 설명합니다. --permanent 플래그 사용 시 주의할 점과 영역 개념을 정리하여 재부팅 후에도 방화벽 규칙이 안전하게 유지되도록 돕습니다.
firewalld의 정의와 Rocky 및 AlmaLinux가 이를 기본으로 제공하는 이유
firewalld는 Rocky Linux, AlmaLinux 및 기타 Red Hat Enterprise Linux(RHEL) 리빌드 배포판에 기본으로 설치되는 방화벽 관리자입니다. 두 배포판 모두 이 설정을 직접 선택했다기보다는 상속받은 것인데, CentOS의 방향 전환 이후 Rocky와 AlmaLinux가 어떻게 Red Hat의 결과물을 리빌드하게 되었는지를 알면 이 결정이 더 합리적으로 이해됩니다. firewalld는 직접 패킷을 검사하지 않습니다. 저장된 설정을 유지하고 이를 nftables 규칙으로 변환하는 역할을 합니다. firewall-cmd 명령어를 사용하면 서버를 온라인 상태로 유지하면서 설정을 편집할 수 있습니다. 이 가이드의 내용은 두 배포판 간에 차이가 없는데, Rocky와 AlmaLinux를 구분 짓는 요소는 방화벽이 아니라 호환성 약속과 지원하는 CPU 범위이기 때문입니다.
Ubuntu VPS에서 ufw가 작동하는 방식을 이미 알고 있다면 firewalld의 역할도 쉽게 이해할 수 있습니다. firewalld는 ufw에는 없는 두 가지 개념을 추가합니다. 첫 번째는 영역(zones)으로, 패킷이 분류되는 이름이 지정된 정책입니다. 두 번째는 실시간 규칙과 저장된 규칙의 분리인데, 이는 --permanent 플래그와 관련이 있으며 이 도구에서 가장 혼란을 일으키는 원인이기도 합니다.
아래의 모든 내용은 사용자의 서버에서 직접 실행하는 명령어입니다. 서버 내부에서 올바르게 보이는 규칙이라도 인터넷 환경에서는 다를 수 있으므로, 모든 변경 사항은 반드시 다른 기기에서 테스트하십시오.
다른 작업을 시작하기 전에 SSH를 먼저 여십시오
대부분의 Rocky 및 AlmaLinux 설치 환경에는 firewalld가 이미 설치되어 실행 중이며, 기본 설정은 SSH를 허용합니다. 일부 최소화된 클라우드 이미지에서는 이 설정이 제외되어 있을 수 있습니다. 무조건 가정하지 말고 확인하십시오.
sudo dnf install -y firewalld
sudo systemctl enable --now firewalld
sudo firewall-cmd --statefirewall-cmd --state은 running을 출력합니다. 서비스가 중지된 상태라면 다른 모든 firewall-cmd 호출은 FirewallD is not running을 반환하고 0이 아닌 종료 코드를 냅니다. 명령어가 아무런 반응을 보이지 않을 때 가장 먼저 확인해야 할 사항입니다.
이제 현재 허용된 설정을 읽어 보십시오.
sudo firewall-cmd --list-all실제 출력에는 몇 줄이 더 포함됩니다. 다음은 중요한 항목입니다.
public (active)
target: default
interfaces: eth0
sources:
services: cockpit dhcpv6-client ssh
ports:
rich rules:services: 라인의 ssh 덕분에 현재 세션이 유지되는 것입니다. 만약 이 항목이 없다면 다른 설정을 건드리기 전에 먼저 추가하십시오. SSH 규칙 없이 방화벽을 시작하면 세션이 즉시 끊기며 다시 접속할 수 없게 됩니다.
sudo firewall-cmd --permanent --add-service=ssh
sudo firewall-cmd --reloadtarget: default은 일치하는 패킷이 없을 경우 ICMP(internet control message protocol) host-prohibited 응답과 함께 거부됨을 의미합니다. 따라서 닫힌 포트에 접근하는 클라이언트는 즉시 No route to host을 보게 됩니다. 대상을 DROP로 설정하면 서버가 아무런 응답을 하지 않게 되며, 스캐너는 타임아웃이 발생할 때까지 대기하게 됩니다.
sudo firewall-cmd --permanent --zone=public --set-target=DROP
sudo firewall-cmd --reload해당 설정을 적용하기 전에 비용을 고려하십시오. DROP는 서버가 ping에 응답하는 것까지 차단하므로, 사용 중인 모니터링 도구 역시 응답을 받지 못하게 됩니다.
규칙이 사라진 이유는 무엇입니까? --permanent 플래그
firewalld는 두 가지 설정을 동시에 유지합니다. 런타임 설정은 커널이 현재 즉시 적용하고 있는 설정입니다. 영구 설정은 /etc/firewalld/zones/public.xml에 저장되며, 리로드나 재부팅 후에 다시 불러와지는 설정입니다.
--permanent 없이 명령을 실행하면 런타임 설정만 변경됩니다. 즉시 적용되지만, 다음 리로드나 부팅 시 사라집니다. --permanent을 포함한 명령은 파일에 내용을 기록할 뿐 현재 실행 중인 설정은 변경하지 않으므로, 리로드하기 전까지는 포트가 닫힌 상태로 유지됩니다. 두 동작 모두 버그가 아닙니다. 명령을 실행하면 어느 경우든 success가 출력되기 때문에 사용자가 혼란을 겪는 경우가 많습니다.
항상 두 명령을 함께 사용하십시오.
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --reload두 설정을 모두 읽어보면 어떤 실수를 했는지 가장 빠르게 확인할 수 있습니다.
sudo firewall-cmd --list-services
sudo firewall-cmd --permanent --list-services첫 번째 명령은 현재 적용된 설정을 출력합니다. 두 번째 명령은 저장된 설정을 출력합니다. 현재 설정에는 있는데 저장된 설정에는 없는 서비스가 있다면, 해당 규칙은 다음 리로드 시 사라집니다. 저장된 설정에는 있는데 현재 설정에는 없다면, 리로드를 수행하지 않은 것입니다. sudo firewall-cmd --runtime-to-permanent는 현재 적용된 모든 설정을 저장된 파일로 복사하며, 이는 실험적인 작업을 마친 후 유용하게 사용할 수 있습니다.
--reload은 연결 추적 상태를 유지하므로 SSH 세션이 끊기지 않습니다. --complete-reload은 커널 모듈까지 다시 불러오며 상태를 초기화하므로, 일반적으로 사용자의 연결을 포함한 모든 열린 연결이 종료됩니다. 일반적인 리로드를 사용하십시오.
안전장치가 하나 내장되어 있습니다. 런타임 규칙은 스스로 만료될 수 있습니다.
sudo firewall-cmd --add-service=http --timeout=5m이 규칙은 5분 후에 스스로 제거됩니다. 이 명령은 --permanent과 함께 사용할 수 없으며, 바로 그 점이 핵심입니다. 이는 확신할 수 없는 변경 사항을 테스트하기 위한 용도입니다. 더 오래된 안전장치가 더 효과적입니다. 규칙을 수정하는 동안 두 번째 SSH 세션을 열어두고, 새로운 로그인으로 규칙이 정상 작동함을 확인하기 전까지는 기존 세션을 닫지 마십시오.
존(Zone)의 개념과 VPS에서 기본 존만 중요한 이유
존은 권한의 집합에 신뢰 수준을 결합한 단위입니다. firewalld는 모든 수신 패킷을 정확히 하나의 존에 할당합니다. 먼저 패킷의 출발지 주소를 각 존의 sources: 목록과 대조합니다. 일치하는 항목이 없으면 패킷이 들어온 인터페이스가 바인딩된 존을 사용합니다. 인터페이스가 어떤 존에도 바인딩되어 있지 않다면 패킷은 기본 존으로 전달됩니다.
sudo firewall-cmd --get-default-zone
sudo firewall-cmd --get-active-zones네트워크 인터페이스가 하나인 VPS에서는 거의 항상 public이 기본 존이며, 이것이 여러분이 사용할 유일한 존입니다. --zone= 인자 없이 사용하는 firewall-cmd은 기본 존에 적용되므로, 이 가이드의 모든 짧은 명령어는 존 이름을 명시하지 않아도 정상적으로 작동합니다.
다음은 오후 내내 시간을 낭비하게 만드는 실패 사례입니다. 인터페이스가 다른 존에 바인딩되어 있으면, 여러분이 추가한 규칙은 public에 적용되지만 실제 트래픽은 다른 곳에서 처리됩니다. 따라서 아무런 효과가 나타나지 않으며 경고 메시지도 출력되지 않습니다. --get-active-zones 명령어로 바인딩 상태를 확인하십시오.
public
interfaces: eth0인터페이스가 다른 존 이름 아래에 표시된다면, --zone=를 사용하여 해당 존에 규칙을 작성하거나 인터페이스를 이동시키십시오.
sudo firewall-cmd --permanent --zone=public --change-interface=eth0
sudo firewall-cmd --reloadRocky 및 AlmaLinux에서는 NetworkManager가 인터페이스를 관리하며, 연결이 활성화될 때 존 설정을 다시 적용합니다. 재부팅 후 설정이 초기화되지 않도록 NetworkManager에서도 존을 설정하십시오. 첫 번째 명령어에서 연결 이름을 확인하십시오. 장치 이름과 같은 경우는 거의 없습니다.
sudo nmcli connection show
sudo nmcli connection modify "System eth0" connection.zone public출발지 주소 매칭은 인터페이스 매칭보다 우선순위가 높으며, 이를 통해 특정 주소에 다른 정책을 적용할 수 있습니다. 내장된 trusted 존은 모든 트래픽을 허용합니다.
sudo firewall-cmd --permanent --zone=trusted --add-source=203.0.113.10/32
sudo firewall-cmd --reload이 존은 주의해서 사용해야 합니다. 해당 주소에 대해 서버의 모든 포트를 개방하며, 여기에는 비공개라고 생각했던 데이터베이스 포트도 포함됩니다. 특정 호스트 전체가 아니라 특정 포트만 허용하려면 rich rule을 사용하십시오.
firewalld 서비스란 무엇인가?
서비스는 XML 파일로 제공되는 포트들의 명명된 묶음입니다. --add-service=https은 443/tcp 포트를 여는데, 이는 /usr/lib/firewalld/services/https.xml이 https의 의미를 정의하기 때문입니다.
sudo firewall-cmd --get-services
sudo firewall-cmd --info-service=https--info-service은 해당 이름 뒤에 숨겨진 포트 번호를 출력합니다:
https
ports: 443/tcp이름이 존재하는 경우에는 해당 이름을 사용하십시오. 6개월 뒤에 --list-all을 다시 보더라도 명확하게 이해할 수 있으며, Cockpit과 같은 패키지는 자체적인 서비스 파일을 설치하기 때문입니다. 정의가 없는 항목에는 --add-port를 사용하십시오.
주의할 점은 다음과 같습니다: ssh 서비스는 22/tcp 포트만을 의미합니다. 만약 서버의 SSH 접근 강화 과정에서 SSH 포트를 다른 번호로 변경했다면, --add-service=ssh는 실제로 사용 중인 포트를 열어주지 않습니다.
sudo firewall-cmd --permanent --add-port=2222/tcp
sudo firewall-cmd --reloadRHEL을 재구축할 때는 해당 포트에 두 번째 잠금 장치가 존재합니다. SELinux(Security-Enhanced Linux)는 포트 번호에 레이블을 지정하며, sshd는 할당된 레이블 이외의 포트에는 바인딩할 수 없습니다. 이 경우 서비스는 시작을 거부하며 로그에는 error: Bind to port 2222 on 0.0.0.0 failed: Permission denied.이라는 메시지가 기록됩니다. 먼저 포트에 레이블을 지정하십시오.
sudo dnf install -y policycoreutils-python-utils
sudo semanage port -a -t ssh_port_t -p tcp 2222현재 열려 있는 포트를 확인하려면 어떻게 해야 합니까?
sudo firewall-cmd --list-all
sudo firewall-cmd --list-rich-rules
sudo nft list table inet firewalld | head -n 40처음 두 명령은 firewalld가 인식하는 상태를 보고합니다. 세 번째 명령은 커널이 실제로 보유한 규칙을 firewalld가 소유한 테이블에서 읽어옵니다. 이 결과들은 서로 일치해야 합니다.
위의 명령들만으로는 충분한 증거가 되지 않습니다. 다른 머신에서 테스트를 수행하십시오.
nc -zv 203.0.113.20 443서버 자체에서 테스트를 실행하지 마십시오. firewalld는 루프백 인터페이스로 들어오는 모든 트래픽을 허용하므로, 규칙 설정과 관계없이 curl http://localhost:8080은 항상 성공합니다. 해당 테스트는 서비스가 실행 중이라는 사실만 알려줄 뿐, 방화벽 상태에 대해서는 아무런 정보도 제공하지 않습니다.
웹 포트 허용
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload
sudo firewall-cmd --list-services마지막 명령을 실행하면 기존 항목과 함께 http https이 목록에 표시되어야 합니다. 사이트가 여전히 응답하지 않는다면 방화벽 문제가 아닐 수 있습니다. 규칙은 패킷을 허용할 뿐이며, 해당 포트에서 프로세스가 실제로 수신 대기 중이어야 합니다.
sudo ss -tlnp0.0.0.0:443 또는 *:443으로 표시된 소켓은 모든 주소에서 연결을 수락합니다. 127.0.0.1:443로 표시된 소켓은 루프백 주소에서만 응답하며, 방화벽 규칙을 어떻게 설정하더라도 외부에서 접근할 수 없습니다. 리눅스의 포트와 수신 대기 소켓에서 이 차이점을 더 자세히 다룹니다.
포트를 다시 닫으려면 어떻게 해야 합니까?
sudo firewall-cmd --permanent --remove-service=http
sudo firewall-cmd --reload여기에도 --permanent 규칙이 적용되며, 이 방향에서는 더 치명적으로 작용합니다. 런타임에서만 서비스를 제거하면 포트가 닫힌 것처럼 보이지만, 다음 리로드나 재부팅 시 저장된 파일에서 다시 열리게 됩니다. 이는 실행한 검사가 통과되기 때문에 알아차리기 어려운 보안 구멍이 됩니다.
존재하지 않는 항목을 제거하려고 하면 Warning: NOT_ENABLED: http이 출력되지만 종료 코드는 0을 반환합니다. 동일한 항목을 두 번 추가하면 Warning: ALREADY_ENABLED: http가 출력됩니다. 두 경우 모두 안전합니다. 이름이 잘못된 경우는 다릅니다. Error: INVALID_SERVICE는 firewalld에 해당 이름의 정의가 없으며 아무것도 변경되지 않았음을 의미합니다.
--list-all에 cockpit이 표시되고 포트 9090에서 Cockpit 웹 콘솔을 사용하지 않는다면 해당 서비스를 제거하십시오. 열려 있는 모든 포트는 사용자가 계속 패치해야 하는 서비스입니다. 유지하기로 결정한 서비스의 경우, dnf-automatic을 사용하여 보안 업데이트를 타이머 기반으로 설치할 수 있으므로 사용자가 일일이 기억할 필요가 없습니다. 다만 패치를 설치하는 것과 실행하는 것은 별개이므로, 업데이트가 적용된 후에는 needs-restarting을 통해 이전 라이브러리를 사용 중인 서비스를 확인해야 합니다.
특정 소스 주소로 포트 접근 제한
Rich rule은 일반적인 서비스 이름만으로 의도를 표현할 수 없을 때 사용하는 상세 설정 방식입니다. SSH 접근을 특정 사무실 주소로 제한하려면 두 개의 명령어가 필요하며, 사람들은 종종 두 번째 명령어를 잊어버립니다.
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="203.0.113.10/32" service name="ssh" accept'
sudo firewall-cmd --permanent --remove-service=ssh
sudo firewall-cmd --reload존(zone)은 첫 번째 일치 항목에서 멈추는 번호 매겨진 목록이 아니라 권한의 집합입니다. Rich rule은 특정 주소에 대한 허용(accept)을 추가할 뿐, 누구도 거부(deny)하지 않습니다. ssh이 여전히 services: 라인에 있다면, 인터넷 전체가 여전히 22번 포트에 접근할 수 있으며 Rich rule은 아무런 실질적인 변화를 주지 못합니다. 광범위한 항목을 제거해야만 좁은 범위의 규칙이 의미를 갖습니다.
서비스 이름이 없는 포트의 경우, 서비스 이름 대신 포트 번호를 지정하십시오.
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="203.0.113.10/32" port port="5432" protocol="tcp" accept'시끄러운 네트워크 트래픽을 차단하고 기록을 남기려면, Rich rule 언어의 문법에 따라 action 앞에 log 요소를 배치해야 합니다.
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="198.51.100.0/24" log prefix="fw-drop " level="info" limit value="3/m" drop'
sudo firewall-cmd --reload
sudo journalctl -k -g fw-droplimit 값은 패킷 홍수로 인해 저널이 가득 차는 것을 방지합니다. SSH를 단일 주소로 고정하기 전에 해당 주소가 안정적인지 확인하십시오. IP 주소가 수시로 바뀌는 가정용 회선을 사용하면 주소가 변경되는 날 접근이 차단될 수 있으므로, 먼저 제공업체의 콘솔 접근 권한이 정상적으로 작동하는지 확인하십시오.
ufw 명령어와 그에 대응하는 firewall-cmd 명령어
동일한 작업이라도 도구에 따라 방식이 다릅니다. 모든 --permanent 줄 뒤에는 sudo firewall-cmd --reload가 필요합니다. 목록 형태로는 이를 모두 보여주기 어렵습니다.
sudo ufw enable은sudo systemctl enable --now firewalld가 됩니다.sudo ufw disable는sudo systemctl disable --now firewalld이 됩니다.sudo ufw status verbose은sudo firewall-cmd --list-all이 됩니다.sudo ufw allow OpenSSH는sudo firewall-cmd --permanent --add-service=ssh이 됩니다.sudo ufw allow 443/tcp은sudo firewall-cmd --permanent --add-port=443/tcp가 됩니다.sudo ufw delete allow 443/tcp은sudo firewall-cmd --permanent --remove-port=443/tcp가 됩니다.sudo ufw allow from 203.0.113.10 to any port 22는 위에서 설명한 rich rule이 됩니다.sudo ufw reload은sudo firewall-cmd --reload이 됩니다.sudo ufw default deny incoming은 이미public영역이 동작하는 방식이며,--set-target=DROP은 그에 대한 조용한(silent) 버전입니다.sudo ufw logging on은sudo firewall-cmd --set-log-denied=all가 됩니다.
한 가지 분명히 해야 할 차이점이 있습니다. ufw는 번호가 매겨진 목록을 유지하므로 1번 위치에 규칙을 삽입할 수 있습니다. firewalld에는 규칙 번호가 없으므로 "이 규칙을 첫 번째로 배치"한다는 개념은 적용되지 않습니다. 두 개의 firewalld 항목이 서로 모순되는 것처럼 보일 경우, 설정 내에 거부(deny) 규칙이 없다면 허용(accept) 규칙이 우선합니다. 광범위한 허용 규칙은 직접 삭제해야 합니다.
방화벽이 닫혀 있는데도 Docker 컨테이너에 접속할 수 있는 이유는 무엇입니까?
컨테이너 포트를 게시하면 해당 트래픽은 방화벽의 영역(zone) 제어 범위에 도달하지 않기 때문입니다. docker run -d -p 8080:80 nginx은 Docker가 자체 NAT(네트워크 주소 변환) 및 포워딩 규칙을 작성하도록 지시합니다. 8080 포트로 들어온 패킷은 재작성되어 컨테이너로 전달되므로, 호스트로 전달되는 것이 아니라 포워딩됩니다. 사용자의 영역에 있는 services: 및 ports: 설정은 호스트로 전달되는 패킷만 제어합니다. Docker의 규칙은 포워딩 경로를 제어하며, 이 규칙은 패킷을 허용합니다.
그 결과 sudo firewall-cmd --list-all 명령에서는 8080 포트가 보이지 않지만, 다른 머신에서 nc -zv 203.0.113.20 8080을 실행하면 연결이 성공하는 서버 상태가 됩니다. Docker가 설치한 규칙을 확인하십시오:
sudo iptables -t nat -L DOCKER -n해결 방법은 publish 플래그에 있습니다. 포트를 루프백(loopback) 주소에 바인딩하고 그 앞에 리버스 프록시를 배치하십시오.
docker run -d -p 127.0.0.1:8080:80 nginx이제 컨테이너는 서버 내부의 curl http://127.0.0.1:8080 요청에만 응답하며 외부에서는 접근할 수 없습니다. Ubuntu 사용자도 동일한 문제에 직면하며, 자세한 내용은 Docker 컨테이너가 ufw를 우회하여 포트를 게시하는 이유에서 확인할 수 있습니다. Rocky 및 AlmaLinux의 기본 저장소에서 제공하는 Rootful Podman 역시 동일한 NAT 방식을 사용하여 포트를 게시하므로, 영역 목록만 신뢰하지 말고 다른 머신에서 직접 테스트해야 합니다. 이러한 중복 문제는 이들 배포판에 Docker Engine을 설치할 때 Ubuntu 가이드에는 없는 몇 가지 추가 단계가 필요한 이유이기도 하며, Podman이 이미 docker 명령을 점유하고 있다는 점부터 고려해야 합니다.
재부팅 후에도 설정이 유지되도록 하기 및 발생 가능한 오류
sudo systemctl is-enabled firewalld
sudo systemctl status firewalldenabled과 active (running)을 사용해야 합니다. 실행 중이지만 활성화되지 않은 방화벽은 첫 재부팅 전까지만 서버를 보호합니다. 이 확인 작업은 새 VPS 설정 후 첫 10분 체크리스트에 SSH 키 및 업데이트와 함께 포함되어야 합니다.
원시 nftables 명령어와 firewalld는 함께 사용할 수 없습니다. firewalld는 inet firewalld라는 테이블을 독점적으로 관리합니다. sudo nft flush ruleset을 실행하면 해당 테이블이 삭제되어 서버가 모든 트래픽에 노출되지만, firewall-cmd --list-all는 커널의 실제 상태가 아닌 firewalld가 인지하는 설정값만 출력합니다. sudo firewall-cmd --reload를 실행해야 규칙이 다시 설치됩니다. 규칙을 작성할 때는 firewall-cmd을 사용하여 재로드 후에도 설정이 유지되도록 하십시오.
한 서버에 두 개의 방화벽 관리자를 두지 마십시오. firewalld와 함께 ufw나 iptables-services을 설치하면 서로의 존재를 모르는 두 프로그램이 규칙을 작성하게 되며, 마지막에 시작된 서비스가 우선권을 갖게 됩니다. 하나만 선택하십시오. Rocky 및 AlmaLinux에서는 배포판 차원에서 지원하는 firewalld를 사용하는 것이 좋습니다.
서버 앞단의 제공자 방화벽. 많은 VPS 관리 패널은 별도의 네트워크 방화벽을 제공합니다. --list-all에서 포트가 열려 있음에도 외부 연결이 실패한다면, 서버 설정을 변경하기 전에 관리 패널을 먼저 확인하십시오. 반대의 경우도 마찬가지입니다. 패널에서 규칙을 열어두어도 firewalld가 패킷을 거부하면 연결되지 않습니다.
sudo 없이 firewall-cmd 실행. 모든 변경 사항에는 root 권한이 필요합니다. 권한 없이 실행하면 인증 단계에서 요청이 거부되어 아무것도 수정되지 않으며, 마치 명령어가 무시된 것처럼 보일 수 있습니다.
대부분의 작업은 다음 6가지 명령어로 해결됩니다. 상태를 확인하는 --list-all, 포트를 여는 --permanent --add-service 또는 --add-port, 포트를 닫는 --permanent --remove-service, 저장된 파일을 적용하는 --reload, 그리고 실험 후 설정을 초기화하는 --runtime-to-permanent입니다. 기본 영역은 public이며, 플래그는 --permanent입니다. 가장 확실한 확인 방법은 다른 외부 장비에서 직접 접속을 시도하는 것입니다.
FAQ
재부팅 후 firewalld 규칙이 사라지는 이유는 무엇입니까?
규칙이 런타임 설정에만 적용되었기 때문입니다. sudo firewall-cmd --add-service=http은 즉시 적용되지만 재로드나 재부팅 시 삭제됩니다. /etc/firewalld/zones/public.xml에 저장된 설정 파일은 변경되지 않았기 때문입니다. --permanent를 추가한 뒤 sudo firewall-cmd --reload을 실행하십시오. 이미 수동으로 추가한 규칙을 유지하려면 sudo firewall-cmd --runtime-to-permanent을 실행하여 현재 적용된 규칙을 저장된 파일로 복사하십시오.
--permanent 옵션으로 규칙을 추가했는데 왜 아무런 변화가 없습니까?
--permanent는 파일에 내용을 기록할 뿐 실행 중인 방화벽에는 영향을 주지 않기 때문입니다. sudo firewall-cmd --reload을 통해 저장된 설정을 커널에 로드하기 전까지는 포트가 닫힌 상태로 유지됩니다. sudo firewall-cmd --list-services와 sudo firewall-cmd --permanent --list-services를 비교해 보십시오. 저장된 목록에는 항목이 있는데 현재 적용된 목록에는 없다면, 재로드를 수행하지 않은 것입니다.
--add-service와 --add-port 중 무엇을 사용해야 합니까?
운영 중인 서비스에 정의된 이름이 있다면 --add-service을 사용하십시오. 이는 의도를 명확히 하며, sudo firewall-cmd --info-service=https을 통해 해당 이름이 어떤 포트를 포함하는지 정확히 확인할 수 있습니다. 서비스가 정의되어 있지 않거나 표준 포트가 아닌 곳에서 수신 대기 중이라면 --add-port을 사용하십시오. ssh 서비스는 22/tcp 포트만 의미하므로, SSH를 2222 포트로 옮겼다면 --add-port=2222/tcp을 사용하고 해당 포트에 대한 SELinux 레이블도 함께 설정해야 합니다.
firewall-cmd에서 포트가 닫혀 있는데 왜 Docker 컨테이너에는 접근할 수 있습니까?
포트를 게시(publish)하면 Docker가 자체 NAT 규칙을 통해 패킷을 컨테이너로 전달합니다. 따라서 패킷이 호스트에 도달하지 않으며, 방화벽 존의 서비스 및 포트 목록은 호스트로 전달되는 패킷만 제어합니다. --list-all에는 아무것도 나타나지 않지만 컨테이너는 외부에서 응답하게 됩니다. docker run -d -p 127.0.0.1:8080:80 nginx를 사용하여 루프백 주소로 게시하고, 그 앞에 리버스 프록시를 배치하십시오.
Rocky Linux에서 firewalld 대신 ufw를 설치해도 됩니까?
한 서버에 두 개의 방화벽 관리자를 설치하면 서로의 규칙을 알지 못한 채 설정을 덮어쓰게 되며, 마지막에 시작된 서비스의 규칙만 남게 됩니다. firewalld는 Rocky Linux와 AlmaLinux에서 지원하는 기본 도구이며 이미 설치되어 있습니다. 또한 ufw가 사용하는 것과 동일한 nftables 백엔드를 제어합니다. 기본 존과 --permanent 플래그 사용법만 익히면 도구 전체를 충분히 활용할 수 있습니다.