대상 OS: Rocky Linux 9

방화벽은 “강하게 막는 것”만큼이나 “지속적으로 관리 가능한 상태로 유지하는 것”이 중요합니다. 특히 규칙(예외)이 늘어날수록 사람이 읽고 검증하기 어려워지고, 그 순간부터는 보안 정책이 아니라 누적된 실수의 집합이 되기 쉽습니다.

Rocky Linux 9 기본 방화벽인 firewalld를 기준으로, 규칙이 커질수록 위험해지는 대표 패턴과 이를 줄이는 운영 방법을 정리합니다. (UFW를 쓰는 환경이라도 문제의 본질은 동일합니다.)

1) 규칙이 커질수록 위험해지는 패턴(운영 실수의 전형)

아래 항목 중 하나라도 반복되면 “규칙이 많아서 안전한 것”이 아니라 “규칙이 많아서 검증이 안 되는 상태”에 가깝습니다.

  • 임시 오픈이 영구화: 장애 대응/테스트용으로 열어둔 포트가 그대로 남아 공격면이 늘어남
  • 누가/왜 열었는지 맥락 부재: 티켓/변경이력/주석이 없어서 나중에 제거를 못함
  • zone 혼용/기본 zone에 무분별 추가: public zone에 다 넣어 전역 오픈과 같은 효과가 발생
  • source 제한 없이 포트 오픈: 특정 대역만 허용해야 하는데 전체(0.0.0.0/0)로 열림
  • service 대신 port 나열: 의미가 흐려져서 “무슨 용도인지” 파악이 어려움


2) 현재 상태를 ‘읽을 수 있게’ 덤프하기(첫 10분 점검)

규칙 최적화의 시작은 “현재 구성이 무엇인지, 어디에 적용됐는지”를 한 번에 보는 것입니다.

# 활성 zone 확인(어떤 인터페이스가 어떤 zone에 붙어 있는지)
sudo firewall-cmd --get-active-zones

# (권장) 활성 zone별 전체 설정 확인
sudo firewall-cmd --list-all

# 모든 zone의 룰을 한 번에 보기(규모가 커졌을 때 특히 유용)
sudo firewall-cmd --list-all-zones

# 런타임/퍼머넌트 차이 확인(자주 놓치는 지점)
sudo firewall-cmd --runtime-to-permanent --dry-run 2>/dev/null || true

포인트는 런타임(running)퍼머넌트(permanent) 불일치입니다. 런타임에만 열려 있거나(재부팅 시 사라짐), 반대로 퍼머넌트에만 있고 런타임에 미적용(재적용 시 갑자기 열림/닫힘)인 경우가 실제 사고로 이어집니다.


3) 규칙을 ‘서비스 단위’로 재구성하기(의미가 보이게 만들기)

가능한 경우 --add-service를 우선합니다. 서비스 단위는 사람이 읽기 쉽고, 표준 포트 변경/추가가 발생했을 때도 관리가 수월합니다.

# 예: HTTPS 허용(퍼머넌트) + 적용
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload

# 특정 포트를 열어야 한다면 포트는 목적/범위를 좁혀 사용
# 예: 내부 관리망에서만 9100/tcp(노드 익스포터 등) 허용
sudo firewall-cmd --permanent --zone=public --add-rich-rule='rule family="ipv4" source address="10.0.0.0/8" port port="9100" protocol="tcp" accept'
sudo firewall-cmd --reload

가능하면 “전역 포트 오픈” 대신 source address 제한을 넣어 공격면을 줄입니다. 또한 rich rule은 룰의 의도를 상대적으로 명확하게 표현할 수 있습니다.


4) ‘늘어나는 규칙’을 막는 운영 루틴(변경관리 + 정기점검)

규칙이 늘어나는 걸 완전히 막을 수는 없습니다. 대신 늘어날 때마다 구조화하면 위험이 덜 커집니다.

  • 변경 티켓 필수: “요청자/목적/기간/영향 범위/롤백”을 최소 항목으로 기록
  • 기본 정책: 테스트용 오픈은 “만료일(자동/수동)”을 포함
  • 월 1회 리뷰: ‘열려 있는 서비스/포트 목록’만 뽑아 빠르게 제거 후보를 찾기
# 열려 있는 서비스/포트만 빠르게 확인(운영 회의용)
sudo firewall-cmd --list-services
sudo firewall-cmd --list-ports


사례(현장에서 자주 겪는 상황)

  • 장애 대응 중 임시 포트 오픈 → “잠깐만”이 6개월이 되어 외부 스캔에 노출
  • 벤더 점검을 위한 원격 접속 허용 → source 제한 없이 포트를 열어두고 계정/접속 제어는 느슨
  • 여러 팀이 규칙을 추가 → 같은 목적의 룰이 중복되고, 어느 룰이 실제로 쓰이는지 아무도 모름

트러블슈팅(증상→원인→해결)

  • 증상: 룰을 추가했는데도 통신이 안 됨
    원인: 다른 zone에 인터페이스가 붙어 있거나, 런타임/퍼머넌트 불일치
    해결: --get-active-zones로 인터페이스-zone 매핑 확인 후 해당 zone에 룰 적용, --reload로 반영
  • 증상: 재부팅 후 갑자기 포트가 닫힘/열림
    원인: 런타임에만 변경(또는 퍼머넌트만 변경)해 상태가 갈라짐
    해결: 변경은 기본적으로 --permanent로 수행하고, 마지막에 --reload로 일관성 유지
  • 증상: 규칙이 너무 많아 제거를 못하겠음
    원인: 목적/소유자/만료일이 없어서 ‘지워도 되는지’ 판단 불가
    해결: 우선 “열려 있는 서비스/포트 목록”만 추려 소유자 지정 후 단계적으로 축소(정기 리뷰 루틴화)

푸터: 방화벽은 한 번 잘 설정하는 것보다, 시간이 지나도 읽히고 검증되는 형태로 유지하는 것이 사고를 줄입니다. 규칙이 늘었다면 ‘차단이 약해졌을 가능성’을 먼저 의심하고, 서비스/소스 제한/변경이력으로 다시 구조화하세요.