infra
Platform

모듈 맵

[Network] CentOS/Ubuntu 서버 방화벽(firewalld / ufw) 포트 열기

0 / 35 완료

펼치기
0 / 35 완료0%

네트워크 트러블슈팅 · 22 / 35

[Network] CentOS/Ubuntu 서버 방화벽(firewalld / ufw) 포트 열기

CentOS의 firewalld와 Ubuntu의 ufw로 특정 포트를 허용합니다

🚨INCIDENT ALERT
HIGH

서비스는 정상적으로 8080에서 리스닝 중인데 외부 접속은 타임아웃입니다. 클라우드 보안그룹을 열어도 OS 안의 firewalld가 마지막 관문에서 패킷을 막고 있었습니다.

호스트 방화벽은 서버 안쪽의 마지막 문입니다. 열기 전에 무엇을 열고 있는지 정확히 확인해야 합니다.

OS 호스트 방화벽 포트 열기 (firewalld / ufw)

애플리케이션을 배포했는데 외부에서 접속이 안 될 때, OS 방화벽이 포트를 차단하고 있는 경우가 매우 흔합니다. 이 챕터에서는 CentOS의 firewalld와 Ubuntu의 ufw로 원하는 포트를 안전하게 열고 확인하는 방법을 익힙니다.


1. 방화벽 레이어 이해

이번 챕터에서 배울 것
  • 1네트워크 방화벽과 OS 호스트 방화벽 레이어의 차이를 설명할 수 있다
  • 2firewalld 존(zone) 개념을 이해하고 CentOS에서 포트를 관리할 수 있다
  • 3ufw 기본 명령어로 Ubuntu 포트 허용 규칙을 관리할 수 있다
  • 4--permanent 옵션 누락 시 재부팅 후 규칙이 소실되는 문제를 해결할 수 있다
  • 5포트를 열어도 접속이 안 될 때 SELinux, 바인딩 주소를 단계별로 추가 점검할 수 있다
실습 환경 준비
firewalld 상태 및 현재 규칙 확인 (CentOS)
firewall-cmd --list-all
ufw 상태 및 규칙 확인 (Ubuntu)
ufw status verbose
프로세스 리스닝 여부 확인
ss -tulnp | grep 8080
SELinux 상태 확인 (CentOS)
sestatus
💡개념

네트워크 방화벽 vs OS 호스트 방화벽 레이어

포트 8080을 열었는데도 외부에서 접속이 안 됩니다. AWS 보안 그룹에서 열었고, ss -tlnp로 확인하니 프로세스도 LISTEN 중입니다. 그런데 실제로는 firewalld가 OS 레벨에서 막고 있었습니다. 방화벽이 네트워크 방화벽과 OS 호스트 방화벽 두 레이어로 나뉜다는 것을 모르면 한 곳만 확인하고 "설정 다 맞는데 왜 안 되지"를 반복하게 됩니다.

네트워크 방화벽 vs OS 호스트 방화벽 레이어 — 트래픽은 클라우드 보안그룹(네트워크 방화벽)을 통과한 뒤 호스트의 firewalld/ufw(OS 방화벽)도 통과해야 프로세스에 도달. 보안그룹에서 8080을 열고 프로세스가 LISTEN해도 OS 방화벽이 막으면 접속 불가 — 두 레이어를 모두 확인해야 함확대

방화벽은 어느 레이어에서 동작하느냐에 따라 역할이 다릅니다.

방화벽 레이어 구조

[인터넷]
    ↓
[네트워크 방화벽 / UTM]  ← 여러 서버를 동시 보호
    ↓                       (라우터, 방화벽 어플라이언스)
[스위치/라우터]
    ↓
[OS 호스트 방화벽]       ← 해당 서버 자체만 보호
    ↓                       (firewalld / ufw / iptables)
[애플리케이션]
구분네트워크 방화벽OS 호스트 방화벽
위치네트워크 인프라 장비서버 OS 내부
관리 주체네트워크/보안팀시스템 관리자
적용 범위여러 서버/구간단일 서버
도구Cisco ASA, pf, AWS SGfirewalld, ufw, iptables

심층 방어(Defense in Depth)

두 레이어를 함께 사용하면, 한쪽이 뚫려도 나머지 레이어에서 막을 수 있습니다. 특히 내부망에서 서버 간 이동 공격(Lateral Movement)을 OS 방화벽으로 막는 것이 중요합니다.

firewalld, ufw, iptables의 관계

  • iptables — Linux 커널 방화벽 프레임워크 (실제 규칙 처리)
    • firewalld — CentOS/RHEL의 iptables 프론트엔드
    • ufw — Ubuntu의 iptables 프론트엔드

firewalld와 ufw는 iptables를 사용하기 쉽게 감싸주는 관리 도구입니다. 직접 iptables를 작성하는 것보다 실수가 적습니다.

💡개념

firewall-cmd 한 줄이 실제 차단·허용이 되기까지 — 선언부터 패킷 평가까지

firewall-cmd --add-port=8080/tcp --permanent을 쳤는데 아직 접속이 안 되거나, 반대로 목록엔 없는데 열려 있는 경우가 있습니다. 이는 명령 한 줄이 곧바로 패킷을 막는 게 아니라 선언 → 백엔드 변환 → 활성 반영 → 패킷 평가라는 단계를 거치기 때문입니다. 이 파이프라인을 알면 "열었는데 막힘"이 어느 단계에서 어긋났는지 짚을 수 있습니다.

TEXT
[관리자]  firewall-cmd --add-port=8080/tcp --permanent   (또는 ufw allow 8080/tcp)
   │
   ① 규칙 선언: 어느 zone에 무엇을(포트·서비스·rich rule) 허용/거부할지 기술
   │     --permanent → 디스크 설정 파일에 기록 (이 시점엔 아직 미적용)
   │
   ② 백엔드 변환: firewalld/ufw가 이 선언을 실제 커널 규칙으로 번역
   │     RHEL9+ = nftables, 구형·ufw = iptables 규칙으로 생성
   │
   ③ 활성 반영: firewall-cmd --reload / ufw는 자동으로 런타임에 로드
   │     이 단계를 건너뛰면 파일엔 있어도 커널엔 없음
   │
   ④ 패킷 평가: 트래픽이 오면 그 패킷이 속한 zone의 규칙과 대조 → 허용/거부
   ▼
[허용된 경우만] 서비스(8080)에 도달

각 단계에서 무슨 일이 일어나고, 막히면(열었는데 막힘) 어떤 증상인가:

단계하는 일여기서 막히면
① 규칙 선언firewall-cmd·ufw로 zone·포트·서비스를 허용/거부로 선언--permanent만 하고 런타임 반영을 안 하면 지금은 적용 안 됨 / --permanent 없이 하면 재부팅·재시작 때 사라짐
② 백엔드 변환선언을 nftables·iptables 규칙으로 번역해 커널에 넣을 형태로 만듦한 호스트에서 firewalld와 ufw를 동시에 쓰면 두 규칙 집합이 충돌·중복 / Docker가 넣는 FORWARD 규칙은 이 경로 밖이라 firewalld 목록에 안 보여도 열림
③ 활성 반영--reload(firewalld)로 저장된 설정을 런타임 커널에 로드--reload를 안 하면 설정 파일엔 있는데 실제론 안 열림·안 막힘 / --list-all(런타임)과 --permanent --list-all이 다르면 미반영 신호
④ 패킷 평가도착 패킷의 인터페이스·출발지로 zone을 정하고 그 zone 규칙과 대조인터페이스가 예상과 다른 zone에 묶여 있으면(zone 불일치) 열어둔 규칙이 그 패킷엔 적용 안 됨 / 출발지 기반 zone이 인터페이스 zone을 이김

즉 **"방화벽에서 열었는데 막힌다"의 대부분은 ③(리로드 안 함) 아니면 ④(zone 불일치)**입니다. firewall-cmd --get-active-zones로 인터페이스가 어느 zone인지 확인하고, firewall-cmd --list-all(런타임)과 firewall-cmd --permanent --list-all을 대조해 반영 여부를 봅니다. ufw는 ufw status verbose로 active·규칙을 확인하고, 실제 커널 규칙은 iptables -L이나 nft list ruleset로 백엔드까지 내려가 대조합니다.


2. CentOS — firewalld 사용법

💡개념

firewalld 존(zone)과 포트 관리

CentOS/RHEL 서버에서 포트를 열었는데 적용이 안 됩니다. --permanent 옵션을 빠뜨렸거나, 잘못된 zone에 규칙을 추가한 경우입니다. firewalld의 zone 개념을 이해하지 못하면 포트를 열어도 왜 적용이 안 되는지, 재부팅 후 왜 원상 복구가 되는지 이유를 알 수 없습니다.

firewalld 존(zone)과 포트 관리 — firewalld는 인터페이스·출발지를 zone(public·trusted·internal 등)에 묶어 신뢰 수준별로 규칙을 적용. --permanent 없이 추가한 규칙은 런타임에만 적용돼 재부팅 시 사라지고, 잘못된 zone에 추가하면 적용 안 됨. --permanent 추가 후 --reload 필요확대

firewalld는 존(zone) 개념으로 네트워크 인터페이스를 분류하고 각 존에 다른 정책을 적용합니다.

주요 존과 기본 정책

설명기본 정책
public외부 공개 네트워크선택적 허용
trusted완전히 신뢰하는 네트워크모든 연결 허용
internal내부 네트워크선택적 허용
drop가장 엄격모든 연결 차단
block엄격들어오는 연결 거부

주요 명령어

위험 명령어

이 명령은 방화벽 정책을 변경해 현재 접속 중인 세션이나 운영 트래픽에 즉시 영향을 줄 수 있습니다. 적용 전 허용 대상 IP·포트와 롤백 명령을 확인하세요.

로컬 터미널
# 실습 디렉토리 준비
mkdir -p /tmp/networking/part4/exam_22 && cd /tmp/networking/part4/exam_22

# 서비스 상태 확인
systemctl status firewalld

# 서비스 시작/활성화
systemctl start firewalld
systemctl enable firewalld

# 현재 활성 존과 규칙 전체 확인
firewall-cmd --list-all

# 특정 존의 규칙 확인
firewall-cmd --zone=public --list-all

# 현재 적용된 포트 목록만 확인
firewall-cmd --list-ports

# 포트 추가 (영구 적용)
firewall-cmd --zone=public --add-port=8080/tcp --permanent
firewall-cmd --reload

# 포트 제거 (영구)
firewall-cmd --zone=public --remove-port=8080/tcp --permanent
firewall-cmd --reload

# 런타임(즉시)과 영구 동시에 추가
firewall-cmd --zone=public --add-port=8080/tcp
firewall-cmd --zone=public --add-port=8080/tcp --permanent
🔍실행 후 확인할 것
  • ufw Status: active / inactiveufw status verbose 첫 줄에서 Status: active인지 먼저 확인 — inactive면 방화벽이 비활성화 상태로 룰 자체가 적용되지 않음, ufw enable로 활성화 필요
  • 허용 포트 목록에서 대상 포트 존재 여부ufw status numbered 출력에서 대상 포트(예: 22, 80, 443)가 ALLOW IN으로 나오는지 확인 — 없으면 해당 포트로의 외부 접근이 전부 차단됨
  • firewall-cmd zones와 services 조합firewall-cmd --list-all 출력에서 services: 줄에 http, https, ssh가 있는지 확인 — zone이 public이어도 services에 없으면 차단, 포트 직접 허용과 서비스 허용은 별개로 동작

3. Ubuntu — ufw 사용법

💡개념

ufw 기본 명령어와 규칙 관리

Ubuntu 서버에 포트를 열어야 합니다. iptables 명령은 너무 복잡하고, firewalld는 Ubuntu에서 기본이 아닙니다. Ubuntu에서는 ufw가 표준입니다. ufw allow 80처럼 직관적인 명령어로 방화벽 규칙을 관리할 수 있는데, 기본 사용법을 모르면 매번 검색해야 합니다.

ufw 기본 명령어와 규칙 관리 — Ubuntu 표준 방화벽 ufw는 복잡한 iptables를 감싼 직관적 인터페이스. ufw allow 80(포트 열기)·ufw deny·ufw status(규칙 확인)·ufw enable로 관리하며, 기본 정책(deny incoming/allow outgoing)에 필요한 포트만 allow로 추가하는 최소 허용 방식확대

ufw(Uncomplicated Firewall)는 Ubuntu에서 사용하는 사용하기 쉬운 방화벽 관리 도구입니다.

주요 명령어

위험 명령어

이 명령은 방화벽 정책을 변경해 현재 접속 중인 세션이나 운영 트래픽에 즉시 영향을 줄 수 있습니다. 적용 전 허용 대상 IP·포트와 롤백 명령을 확인하세요.

로컬 터미널
# ufw 상태 확인
ufw status

# 상세 상태 확인 (규칙 포함)
ufw status verbose

# ufw 활성화/비활성화
ufw enable
ufw disable

# 번호와 함께 규칙 목록 확인 (삭제 시 유용)
ufw status numbered

# 포트 허용
ufw allow 8080/tcp
ufw allow 8080/udp
ufw allow 8080          # TCP+UDP 모두 허용

# 포트 거부
ufw deny 8080/tcp

# 특정 IP에서만 특정 포트 허용
ufw allow from 192.168.1.100 to any port 3306

# 특정 IP 대역에서 허용
ufw allow from 192.168.1.0/24 to any port 3306

# 규칙 삭제 (번호로)
ufw status numbered
ufw delete 3  # 3번 규칙 삭제

# 규칙 삭제 (규칙 내용으로)
ufw delete allow 8080/tcp

# ufw 규칙 전체 초기화
ufw reset

서비스 이름으로 허용

위험 명령어

이 명령은 방화벽 정책을 변경해 현재 접속 중인 세션이나 운영 트래픽에 즉시 영향을 줄 수 있습니다. 적용 전 허용 대상 IP·포트와 롤백 명령을 확인하세요.

로컬 터미널
# 서비스 이름으로 허용 (사전 정의된 서비스)
ufw allow ssh
ufw allow http
ufw allow https

# 사용 가능한 서비스 목록
ls /etc/ufw/applications.d/
ufw app list
호스트 방화벽 운영 판단 — 영속성·순서·규모
firewalld 규칙이 재부팅 후 사라짐--permanent 없이 추가했기 때문 — 런타임에만 적용됨. firewall-cmd --add-port=... --permanent 후 --reload. '두 번 적용(런타임+permanent)' 또는 --permanent+--reload
ufw enable 했더니 SSH 끊김기본 deny incoming인데 SSH 허용 규칙을 먼저 안 넣음. 반드시 ufw allow 22(또는 OpenSSH) → 그 다음 enable. 'enable 전에 내 길부터'
firewalld vs ufw vs iptables 직접RHEL계는 firewalld, Ubuntu는 ufw가 기본·관리 쉬움. 둘 다 내부적으로 nftables/iptables. 같은 호스트에서 여러 개 동시 사용 금지 — 규칙이 충돌·중복
규칙이 수십~수백 개로 늘어남개별 포트·IP 나열은 가독성·성능 저하. firewalld는 zone·service·ipset, ufw는 app profile로 묶어라. '대량 IP는 ipset 한 줄'
변경이 즉시 안 먹는다firewalld는 --reload, ufw는 자동 적용이지만 reload 필요시 ufw reload. 적용 후 firewall-cmd --list-all / ufw status verbose로 실제 상태 확인 — '설정≠적용'
특정 출발지만 허용firewalld rich rule(source address), ufw allow from <IP> to any port <p>. 전체 개방 후 좁히지 말고 처음부터 출발지 한정 — '기본 차단, 명시 허용'

4. 실습: 웹 애플리케이션 포트 열기

1단계: CentOS에서 8080 포트 열기 (firewalld)

8080 포트에서 실행되는 웹 애플리케이션에 외부 접속을 허용합니다.

위험 명령어

이 명령은 방화벽 정책을 변경해 현재 접속 중인 세션이나 운영 트래픽에 즉시 영향을 줄 수 있습니다. 적용 전 허용 대상 IP·포트와 롤백 명령을 확인하세요.

로컬 터미널
# 현재 방화벽 상태 확인
firewall-cmd --list-all
# public (active)
#   target: default
#   ...
#   ports:  22/tcp
#   ...

# 8080 포트 추가 (영구 + 즉시 적용)
firewall-cmd --zone=public --add-port=8080/tcp --permanent
firewall-cmd --reload

# 추가 확인
firewall-cmd --list-ports
# 22/tcp 8080/tcp

# 또는 전체 확인
firewall-cmd --list-all
# public (active)
#   ...
#   ports: 22/tcp 8080/tcp  ← 추가됨

# 외부에서 연결 테스트
curl -v --connect-timeout 5 http://서버IP:8080

여러 포트 한번에 추가

위험 명령어

이 명령은 방화벽 정책을 변경해 현재 접속 중인 세션이나 운영 트래픽에 즉시 영향을 줄 수 있습니다. 적용 전 허용 대상 IP·포트와 롤백 명령을 확인하세요.

로컬 터미널
# 3000-3010 범위 포트 열기
firewall-cmd --zone=public --add-port=3000-3010/tcp --permanent

# 여러 포트 동시에
firewall-cmd --zone=public --add-port=8080/tcp --add-port=8443/tcp --permanent
firewall-cmd --reload
2단계: Ubuntu에서 8080 포트 열기 (ufw)

Ubuntu 서버에서 ufw로 동일한 작업을 수행합니다.

위험 명령어

이 명령은 방화벽 정책을 변경해 현재 접속 중인 세션이나 운영 트래픽에 즉시 영향을 줄 수 있습니다. 적용 전 허용 대상 IP·포트와 롤백 명령을 확인하세요.

로컬 터미널
# ufw 상태 확인
ufw status verbose
# Status: active (또는 inactive)

# ufw가 비활성화라면 활성화
# 먼저 실제 SSH 포트를 확인합니다(22가 아닐 수 있음).
sudo ss -tlnp | grep sshd
SSH_PORT=22  # /etc/ssh/sshd_config의 Port 값으로 교체
ufw allow "${SSH_PORT}/tcp"     # 실제 관리 포트를 먼저 허용
ufw enable        # 활성화

# 8080 포트 허용
ufw allow 8080/tcp

# 상태 확인
ufw status verbose
# Status: active
#
# To                         Action      From
# --                         ------      ----
# 22/tcp                     ALLOW IN    Anywhere
# 8080/tcp                   ALLOW IN    Anywhere  ← 추가됨

# 외부에서 연결 테스트
curl -v --connect-timeout 5 http://서버IP:8080

주의: ufw enable 전 SSH 허용 필수

위험 명령어

이 명령은 방화벽 정책을 변경해 현재 접속 중인 세션이나 운영 트래픽에 즉시 영향을 줄 수 있습니다. 적용 전 허용 대상 IP·포트와 롤백 명령을 확인하세요.

로컬 터미널
# 원격 서버에서 작업할 때 이 순서를 반드시 지키세요!
ufw allow "${SSH_PORT}/tcp"   # ← 실제 SSH 포트 먼저!
ufw enable         # ← 그 다음!
# 순서 바꾸면 SSH 세션이 끊기고 서버 접근 불가
3단계: --permanent 옵션 누락 실수 재현 및 수정

--permanent 없이 추가한 규칙이 재부팅 후 사라지는 것을 확인합니다.

위험 명령어

이 명령은 방화벽 정책을 변경해 현재 접속 중인 세션이나 운영 트래픽에 즉시 영향을 줄 수 있습니다. 적용 전 허용 대상 IP·포트와 롤백 명령을 확인하세요.

로컬 터미널
# [잘못된 예] --permanent 없이 포트 추가
firewall-cmd --zone=public --add-port=9090/tcp
# success

# 현재는 적용됨
firewall-cmd --list-ports
# 22/tcp 8080/tcp 9090/tcp

# 재부팅 시뮬레이션 — firewalld 재시작
systemctl restart firewalld

# 재시작 후 확인
firewall-cmd --list-ports
# 22/tcp 8080/tcp   ← 9090이 사라짐!

# [올바른 방법] --permanent와 --reload
firewall-cmd --zone=public --add-port=9090/tcp --permanent
firewall-cmd --reload

# 다시 확인
firewall-cmd --list-ports
# 22/tcp 8080/tcp 9090/tcp

# 재시작해도 유지 확인
systemctl restart firewalld
firewall-cmd --list-ports
# 22/tcp 8080/tcp 9090/tcp  ← 유지됨!

런타임 vs 영구 설정 차이

위험 명령어

이 명령은 방화벽 정책을 변경해 현재 접속 중인 세션이나 운영 트래픽에 즉시 영향을 줄 수 있습니다. 적용 전 허용 대상 IP·포트와 롤백 명령을 확인하세요.

로컬 터미널
# 런타임 설정만 확인 (현재 실행 중)
firewall-cmd --list-ports

# 영구(permanent) 저장된 설정 확인
firewall-cmd --permanent --list-ports

# 두 결과가 다르면 --reload로 동기화
4단계: 포트 열어도 안 될 때 단계별 추가 점검

방화벽에서 포트를 열었음에도 접속이 안 되는 경우 추가로 확인해야 할 항목들을 점검합니다.

로컬 터미널
# [점검 1] 프로세스가 해당 포트에서 리스닝하는지 확인
ss -tulnp | grep 8080
# 출력이 없으면 → 애플리케이션이 8080에서 실행되지 않는 것

# [점검 2] SELinux 포트 정책 (CentOS/RHEL)
# SELinux가 활성화된 경우 별도 포트 허용 필요
sestatus
# SELinux status: enabled
# Current mode: enforcing  ← 활성화 상태

# SELinux에서 허용된 http 포트 확인
semanage port -l | grep http_port
# http_port_t  tcp  80, 81, 443, 488, 8008, 8009, 8080, 8443

# 8080이 없다면 추가
semanage port -a -t http_port_t -p tcp 8080

# [점검 3] 상위 네트워크 방화벽 확인
# 클라우드라면 Security Group/NACL 확인
# 온프레미스라면 네트워크팀에 상위 방화벽 규칙 요청

# [점검 4] 애플리케이션 바인딩 주소 확인
ss -tulnp | grep 8080
# 127.0.0.1:8080 → 루프백 바인딩 → 외부 접속 불가

# [점검 5] 실제 패킷이 오고 있는지 tcpdump로 확인
tcpdump -i eth0 port 8080 -n
# 패킷이 도달하는지 확인

5. 장애 사례 분석

증상

배포 후 테스트에서는 잘 됐는데,
다음 날 서버 재부팅(정기 패치) 후 갑자기 서비스 전면 장애 발생

원인 확인

위험 명령어

이 명령은 방화벽 정책을 변경해 현재 접속 중인 세션이나 운영 트래픽에 즉시 영향을 줄 수 있습니다. 적용 전 허용 대상 IP·포트와 롤백 명령을 확인하세요.

로컬 터미널
# 현재 포트 확인
firewall-cmd --list-ports
# 22/tcp   ← 8080이 없음!

# 영구 설정 확인
firewall-cmd --permanent --list-ports
# 22/tcp   ← 여기도 없음 → --permanent 없이 추가했던 것

# 언제 추가했는지 로그 확인
journalctl -u firewalld --since "2024-01-01" | grep 8080

즉각 조치 (서비스 복구)

위험 명령어

이 명령은 방화벽 정책을 변경해 현재 접속 중인 세션이나 운영 트래픽에 즉시 영향을 줄 수 있습니다. 적용 전 허용 대상 IP·포트와 롤백 명령을 확인하세요.

로컬 터미널
# 즉시 포트 열기 (서비스 복구 우선)
firewall-cmd --zone=public --add-port=8080/tcp

# 서비스 접속 확인 후 영구 적용
firewall-cmd --zone=public --add-port=8080/tcp --permanent
firewall-cmd --reload

# 최종 확인
firewall-cmd --permanent --list-ports
# 22/tcp 8080/tcp   ← 이제 영구 저장됨

재발 방지

위험 명령어

이 명령은 방화벽 정책을 변경해 현재 접속 중인 세션이나 운영 트래픽에 즉시 영향을 줄 수 있습니다. 적용 전 허용 대상 IP·포트와 롤백 명령을 확인하세요.

로컬 터미널
# 방화벽 변경 작업 후 반드시 실행하는 검증 스크립트
verify_firewall() {
  local port=$1
  echo "런타임 설정:"
  firewall-cmd --list-ports | grep -o "${port}/tcp" && echo "OK" || echo "MISSING"
  echo "영구 설정:"
  firewall-cmd --permanent --list-ports | grep -o "${port}/tcp" && echo "OK" || echo "MISSING"
}
verify_firewall 8080

교훈: 방화벽 포트 추가 후 항상 --permanent --list-ports로 영구 설정까지 저장됐는지 확인하는 습관을 들이세요.

증상

위험 명령어

이 명령은 방화벽 정책을 변경해 현재 접속 중인 세션이나 운영 트래픽에 즉시 영향을 줄 수 있습니다. 적용 전 허용 대상 IP·포트와 롤백 명령을 확인하세요.

로컬 터미널
ufw enable
# Firewall is active and enabled on system startup
# (갑자기 SSH 세션 연결 끊김)

원인 분석

ufw enable 실행 시 기본 정책이 DENY(모든 인바운드 차단) 이기 때문에, 먼저 SSH 포트를 허용하지 않은 상태에서 ufw enable을 실행하면 현재 SSH 세션을 포함한 모든 인바운드가 차단됩니다.

ufw 기본 정책:
  INPUT: DENY    ← SSH 포트 미허용 상태로 활성화 → 세션 차단!
  OUTPUT: ALLOW
  FORWARD: DENY

복구 방법 (콘솔/VNC 접근 필요)

위험 명령어

이 명령은 방화벽 정책을 변경해 현재 접속 중인 세션이나 운영 트래픽에 즉시 영향을 줄 수 있습니다. 적용 전 허용 대상 IP·포트와 롤백 명령을 확인하세요.

로컬 터미널
# 물리 콘솔 또는 클라우드 콘솔(AWS EC2 Session Manager 등)로 접속 후

# ufw 즉시 비활성화
ufw disable

# 올바른 순서로 재설정
ufw allow 22/tcp        # SSH 먼저 허용
ufw allow 80/tcp        # HTTP
ufw allow 443/tcp       # HTTPS
ufw enable              # 그 다음 활성화

# 확인
ufw status verbose

예방 방법

위험 명령어

이 명령은 방화벽 정책을 변경해 현재 접속 중인 세션이나 운영 트래픽에 즉시 영향을 줄 수 있습니다. 적용 전 허용 대상 IP·포트와 롤백 명령을 확인하세요.

로컬 터미널
# ufw enable 전 체크리스트:
echo "1. SSH 포트 허용 여부 확인:"
ufw show added | grep "22\|ssh"

# 확인 후 없으면 추가
ufw allow ssh
ufw status numbered  # 규칙 확인
ufw enable           # 최종 활성화

교훈: ufw는 enable 전에 반드시 SSH 포트를 허용해야 합니다. 원격 서버에서 작업할 때 이 순서를 지키지 않으면 접속이 끊깁니다.


심화 — 호스트 방화벽을 우회하는 트래픽

💡개념

심화: firewalld/ufw의 사각지대 — FORWARD 경로와 Docker

firewall-cmd --list-ports에 22만 있는데도 컨테이너 포트가 외부에 뚫려 있다면, 방화벽이 고장 난 게 아니라 그 트래픽이 방화벽이 검사하는 경로로 오지 않은 것입니다. firewalld·ufw가 실제로 무엇을 보는지 알아야 이 사각지대를 이해할 수 있습니다.

  • firewalld/ufw는 주로 INPUT 체인을 다룹니다: 이 도구들이 '포트를 연다/막는다'고 할 때 대상은 대개 호스트 자신에게 들어오는 트래픽(netfilter의 INPUT 체인)입니다. 반면 호스트를 거쳐 다른 목적지로 전달되는 트래픽은 FORWARD 체인을 타며, 여기에는 INPUT 규칙이 적용되지 않습니다.
  • Docker는 iptables를 직접 건드립니다: 컨테이너를 -p 8080:80으로 띄우면 Docker가 nat 테이블 PREROUTING에 DNAT 규칙을, filter 테이블 FORWARD(DOCKER 체인)에 허용 규칙을 스스로 삽입합니다. published 포트로 온 패킷은 DNAT되어 FORWARD로 컨테이너에 전달되므로 firewalld/ufw의 포트 목록과 무관하게 열립니다. 'ufw가 Docker를 못 막는다'는 유명한 함정이 바로 이것입니다.
  • 백엔드가 섞이면 추론이 어렵습니다: RHEL 8+에서 firewalld 백엔드는 nftables지만 Docker는 iptables(-nft) 규칙을 넣습니다. 같은 커널 위에 두 규칙 집합이 공존하면 어느 규칙이 먼저 평가되는지 눈으로 따라가기 어렵습니다.
  • conntrack 때문에 '지금 막아도' 기존 연결은 살아 있습니다: netfilter는 상태 추적(conntrack)을 하므로 이미 ESTABLISHED된 연결은 새로 넣은 차단 규칙과 무관하게 유지될 수 있습니다. 규칙을 바꾼 뒤 기존 세션이 안 끊긴다고 '규칙이 안 먹었다'고 오해하기 쉽습니다 — 새 연결부터 정책이 적용됩니다.

그래서 'firewall-cmd --list-ports에 없으니 닫혀 있다'는 컨테이너·포워딩 앞에서는 거짓일 수 있습니다. 컨테이너 포트를 실제로 통제하려면 DOCKER-USER 체인에 규칙을 넣거나, published 포트를 127.0.0.1:8080:80처럼 루프백에만 바인딩해야 합니다.

상황: 보안 점검에서 firewall-cmd --list-ports 결과가 22/tcp뿐이라 '8080은 닫혀 있다'고 보고했는데, 외부에서 http://서버IP:8080 접속이 멀쩡히 됩니다. ufw를 쓰는 다른 서버도 ufw status에는 8080이 없는데 뚫려 있습니다.

원인: -p 8080:80은 Docker가 직접 iptables의 nat PREROUTING(DNAT)과 filter FORWARD(DOCKER 체인)에 규칙을 삽입한 것입니다. 이 트래픽은 호스트의 INPUT 체인을 타지 않고 FORWARD로 컨테이너에 전달되므로, INPUT을 검사하는 firewalld/ufw의 포트 목록과 무관하게 열립니다. 방화벽이 뚫린 게 아니라, 방화벽이 보는 경로 밖으로 트래픽이 흐른 것입니다.

진단: iptables -t nat -L DOCKER -n으로 DNAT 규칙을, iptables -L FORWARD -niptables -L DOCKER-USER -n으로 포워딩 허용 규칙을 확인합니다. ss -tlnp | grep 8080에는 docker-proxy가 0.0.0.0:8080으로 리스닝합니다. firewalld 포트 목록은 비어 있는데 실제 접속은 열려 있다면 컨테이너 우회를 의심합니다.

해결: 외부 노출이 필요 없으면 published 포트를 -p 127.0.0.1:8080:80처럼 루프백에만 바인딩합니다. 외부 노출은 필요하되 출발지를 제한하려면 firewalld/ufw의 INPUT 규칙이 아니라 DOCKER-USER 체인에 규칙을 넣어야 합니다(이 체인은 Docker 자신의 허용 규칙보다 먼저 평가됨). ufw라면 /etc/ufw/after.rules에 DOCKER-USER 필터를 추가하는 방식이 표준입니다. '호스트 방화벽에 안 보이니 안전하다'는 가정을 컨테이너 앞에서 버리는 것이 핵심입니다.


6. 실무 현장 관점

💼
실무 맥락
현업 패턴

신규 서비스 배포 시 방화벽 작업 체크리스트

위험 명령어

이 명령은 방화벽 정책을 변경해 현재 접속 중인 세션이나 운영 트래픽에 즉시 영향을 줄 수 있습니다. 적용 전 허용 대상 IP·포트와 롤백 명령을 확인하세요.

로컬 터미널
#!/bin/bash
# 신규 서비스 방화벽 설정 표준 절차

SERVICE_PORT=$1
SERVICE_NAME=$2
OS=$(grep -oP '(?<=^ID=).+' /etc/os-release | tr -d '"')

echo "=== 방화벽 설정: ${SERVICE_NAME}:${SERVICE_PORT} ==="

if [[ "$OS" == "centos" || "$OS" == "rhel" || "$OS" == "rocky" ]]; then
  # CentOS/RHEL/Rocky
  firewall-cmd --zone=public --add-port=${SERVICE_PORT}/tcp --permanent
  firewall-cmd --reload
  echo "[확인] $(firewall-cmd --permanent --list-ports | grep ${SERVICE_PORT})"

elif [[ "$OS" == "ubuntu" || "$OS" == "debian" ]]; then
  # Ubuntu/Debian
  ufw allow ${SERVICE_PORT}/tcp
  echo "[확인]"
  ufw status | grep ${SERVICE_PORT}
fi

# 서비스 리스닝 확인
echo "[프로세스 확인]"
ss -tulnp | grep ${SERVICE_PORT}

사용 예시

로컬 터미널
bash firewall-setup.sh 8080 "MyApp"
bash firewall-setup.sh 3306 "MySQL"

실무 환경별 고려사항

  1. 클라우드 환경 (AWS/GCP/Azure)

    • OS 방화벽 외에 Security Group / 방화벽 규칙도 함께 설정 필요
    • OS 방화벽을 비활성화하고 Security Group만 사용하는 팀도 있음
    • 그러나 심층 방어를 위해 OS 방화벽도 유지하는 것을 권장
  2. Kubernetes 환경

    • NodePort 서비스라면 노드의 OS 방화벽에서 해당 포트 허용 필요
    • CNI 플러그인(Calico 등)이 iptables 규칙을 자동 생성하므로 충돌 주의
  3. 방화벽 변경 이력 관리

    • 어떤 포트를, 왜, 언제 열었는지 변경 이력을 관리해야 함
    • 불필요한 포트가 누적되지 않도록 주기적으로 감사(Audit)

인프라 담당자 vs 개발자 역할 분리

개발자: "8080 포트를 열어주세요" → 티켓 요청
인프라: 목적, 출발지 IP, 기간 확인 후 허용
→ 변경 관리 시스템에 기록
→ 불필요해지면 제거

7. 핵심 명령어 요약

CentOS — firewalld

목적명령어
포트 추가 (영구)firewall-cmd --zone=public --add-port=8080/tcp --permanent && firewall-cmd --reload
포트 제거 (영구)firewall-cmd --zone=public --remove-port=8080/tcp --permanent && firewall-cmd --reload
포트 목록 확인firewall-cmd --list-ports
영구 설정 확인firewall-cmd --permanent --list-ports
전체 규칙 확인firewall-cmd --list-all

Ubuntu — ufw

목적명령어
포트 허용ufw allow 8080/tcp
특정 IP에서만 허용ufw allow from 192.168.1.100 to any port 3306
포트 거부ufw deny 8080/tcp
상태 확인ufw status verbose
번호로 규칙 삭제ufw delete 규칙번호

정리

  • OS 방화벽은 네트워크 방화벽과 독립적으로 동작하는 별도 레이어
  • CentOS: firewall-cmd --add-port=포트/tcp --permanent && firewall-cmd --reload
  • Ubuntu: ufw allow 포트/tcp (enable 전 SSH 허용 필수)
  • --permanent 누락 시 재부팅 후 규칙이 사라지는 실수 주의
  • 포트 열어도 안 되면: 프로세스 리스닝 여부 → SELinux → 상위 방화벽 순서로 점검
  • 방화벽 설정 후 --permanent --list-ports로 영구 저장 여부 반드시 확인

관련 모듈로 더 깊이:

다음 모듈에서는 iptables 규칙 체인 구조와 ACCEPT/DROP/REJECT 동작을 직접 작성하고 적용하는 방법을 다룹니다.

지식 확인

퀴즈 — 8문제

Q1

클라우드 보안그룹(Security Group)에서 8080 포트를 열었지만 외부에서 접속이 안 됩니다. 서버에서 `ss -tlnp | grep 8080`을 보면 프로세스가 정상 리스닝 중입니다. 다음으로 확인해야 할 것은?

Q2

CentOS에서 `firewall-cmd --add-port=8080/tcp` 명령 실행 후 서버를 재부팅하면 어떻게 되는가?

Q3

새 Ubuntu 서버에 `ufw allow 22/tcp && ufw allow 8080/tcp`를 실행하고 `ufw enable`을 했습니다. 이후 SSH가 끊기고 재접속이 안 됩니다. 원인은?

Q4

firewalld에서 --permanent와 --reload를 순서대로 실행하는 이유는?

Q5

포트를 방화벽에서 열었는데도 외부 접속이 안 될 때 다음으로 확인해야 할 것은?

Q6

클라우드 보안그룹(SG)과 서버 안의 OS 방화벽(firewalld/ufw)이 모두 있을 때, 외부 접속이 되려면 패킷이 어떻게 통과해야 하나?

Q7

[심화] firewall-cmd --list-ports에는 22/tcp만 있는데 docker run -p 8080:80으로 띄운 컨테이너가 외부에서 접속됩니다. firewalld가 이 포트를 못 막는 근본 이유는?

Q8

[심화] ufw status에 8080이 없는데 컨테이너 포트 8080이 외부에서 열려 있습니다. 가장 먼저 확인·조치할 것은?

0 / 8 답변

🧪 실습으로 확인하기

포트는 열렸다는데 왜 안 되지? — ss/netstat/telnet으로 TCP 진단

초급

"포트 8080 열었는데요?"와 "왜 안 돼요?" 사이의 간극을 메우는 실습. ss로 바인딩 상태를 확인하고, telnet/nc으로 원격 연결을 테스트하고, iptables 방화벽을 진단하고, 바인딩 주소(0.0.0.0 vs 127.0.0.1)까지 수정하는 4단계 TCP 포트 진단 플로우를 완성한다.

35📋 4단계💻 직접 환경
실습 시작하기 →

이것도 배워보세요