📚 네트워크 · 패킷 분석 › 04. 네트워크 장비 실습 — 185편
이전 글: 184. Allow와 Deny · 다음 글: 186. Firewall NAT 정책
Stateful Firewall(상태 기반 방화벽) 은 통과를 허용한 연결을 세션(상태) 테이블에 기록해 두고, 이후 패킷이 그 연결에 속하는지를 보고 판단하는 방화벽입니다. ACL처럼 패킷 하나하나를 독립적으로 보는 방식(Stateless, 178. ACL)과 달리, "이 패킷은 누가 시작한 어떤 연결의 몇 번째 패킷인가" 를 압니다.
| 항목 | Stateless (ACL) | Stateful |
|---|---|---|
| 판단 단위 | 패킷 하나 | 연결(세션) |
| 응답 트래픽 허용 | 반대 방향 규칙을 따로 작성 (established는 플래그만 확인) | 세션 테이블로 자동 허용 |
| 세션 없이 도착한 ACK 패킷 | 규칙에 따라 통과할 수 있음 | 세션이 없으므로 새 연결로서 정책 평가 대상 |
| 장비 자원 | 규칙만 보관 | 세션마다 메모리 사용, 용량 한계 존재 |
| 이중화 | 규칙만 같으면 됨 | 세션 정보 동기화 필요 |
정책 설계 관점의 Stateful 방화벽은 254. Stateful Firewall에서 다루고, 이 글은 세션 테이블이라는 장비 자원과 그 운영에 집중합니다.
Linux netfilter의 연결 추적(conntrack)을 기준으로 한 처리 흐름입니다. 상용 방화벽도 구조는 비슷합니다.
패킷 도착
↓
[5-tuple(프로토콜, 출발지 IP·포트, 목적지 IP·포트)로 세션 테이블 조회]
├─ 있음 → 상태 갱신(ESTABLISHED 등) → 세션 허용 규칙으로 빠르게 통과
├─ 없음 + 새 연결 시작 가능한 패킷 → NEW → 정책 규칙 평가
│ ├─ 허용 → 세션 생성(응답 방향 튜플도 함께 기록)
│ └─ 거부 → 폐기 (세션 생성 안 함)
└─ 어떤 연결에도 맞지 않는 패킷 → INVALID → 보통 폐기
conntrack이 부여하는 상태 값입니다(nftables ct state, iptables --ctstate에서 사용).
| 상태 | 의미 | 예 |
|---|---|---|
| NEW | 새 연결의 첫 패킷 | TCP SYN, 새 UDP 흐름의 첫 패킷 |
| ESTABLISHED | 양방향 패킷이 확인된 연결에 속함 | 응답 SYN/ACK 이후의 패킷 |
| RELATED | 기존 연결과 관련된 새 흐름 | 기존 연결에 대한 ICMP 오류, 헬퍼가 인식한 FTP 데이터 연결 |
| INVALID | 어떤 연결로도 식별되지 않거나 비정상 | 시퀀스·윈도 범위를 벗어난 TCP 패킷, 잘못된 플래그 조합 |
| UNTRACKED | 추적 제외(notrack)로 지정된 패킷 | 대량 트래픽 서버의 예외 처리 |
TCP의 경우 conntrack은 SYN_SENT → SYN_RECV → ESTABLISHED → FIN_WAIT → TIME_WAIT 같은 TCP 세부 상태도 따로 추적해, 상태마다 다른 타임아웃을 적용합니다.
nf_conntrack_max가 상한이며, 가득 차면 새 연결의 패킷이 버려지고 커널 로그에 nf_conntrack: table full, dropping packet이 남습니다. 상용 방화벽도 모델별 최대 동시 세션 수가 있습니다.conntrackd가 이 역할을 합니다.실습 예시 — 방화벽 VM에서 세션 테이블을 관찰합니다. conntrack 도구 설치는 49. 사설 IP · 공인 IP와 NAT — 로그의 IP가 서로 다른 이유을 참고합니다(Rocky: conntrack-tools, Ubuntu: conntrack). 값은 예시(값은 환경마다 다름)입니다.
# 현재 세션 수 / 상한
cat /proc/sys/net/netfilter/nf_conntrack_count
sysctl net.netfilter.nf_conntrack_max
# 상태별 조회
sudo conntrack -L -p tcp --state ESTABLISHED
sudo conntrack -L -p tcp --state SYN_SENT
# CPU별 통계: insert_failed, drop, invalid 등 카운터
sudo conntrack -S
# 특정 연결 강제 삭제 (차단 정책 즉시 적용 시)
sudo conntrack -D -s 192.168.10.11 -d 10.20.0.10 -p tcp --dport 22
nftables에서 상태를 이용하는 규칙의 기본형입니다(180. DMZ의 forward 체인과 같음).
ct state established,related accept
ct state invalid counter log prefix "CT-INVALID " drop
tcp flags & (fin|syn|rst|ack) != syn ct state new counter drop # 새 TCP 연결은 SYN으로만
ct state new iifname "ens37" tcp dport 443 accept
conntrack -L 출력 형식 예시입니다.
tcp 6 431995 ESTABLISHED src=192.168.10.11 dst=10.20.0.10 sport=51514 dport=443 src=10.20.0.10 dst=192.168.10.11 sport=443 dport=51514 [ASSURED] mark=0 use=1
tcp 6 118 SYN_SENT src=192.168.10.11 dst=10.20.0.99 sport=51600 dport=443 [UNREPLIED] src=10.20.0.99 dst=192.168.10.11 sport=443 dport=51600 mark=0 use=1
두 번째 줄의 [UNREPLIED]는 응답을 한 번도 받지 못한 세션입니다. 이런 항목이 한 출발지에서 대량으로 보이면 존재하지 않는 목적지로의 연결 시도(스캔 등)를 의심할 수 있습니다.
📷 [실습 화면 삽입 위치] 클라이언트 VM에서 여러 포트로 연결을 시도하는 동안 방화벽 VM의
watch -n1 cat /proc/sys/net/netfilter/nf_conntrack_count값 증가와conntrack -L의 UNREPLIED 항목을 함께 보여 주는 화면
nf_conntrack_tcp_loose=1)에서 세션 중간의 ACK 패킷도 NEW로 받아들여 추적을 시작할 수 있으므로, 위 예시처럼 "새 TCP 연결은 SYN만" 규칙을 함께 두는 것이 일반적입니다.| 흔적 | 의미 |
|---|---|
세션 수 급증, table full 커널 로그 | Flood·대량 스캔, 또는 용량 부족 |
| INVALID 차단 로그 증가 | 비대칭 라우팅, 세션 동기화 실패, 위조 패킷 |
| UNREPLIED(미완성) 세션 다수 | 응답 없는 목적지로의 대량 시도 |
| 세션 종료 로그의 지속 시간·바이트 | 장시간 유지된 세션, 대용량 전송 |
관제자가 확인할 질문
오탐 주의: 방화벽 전환·재시작 직후에는 기존 연결이 세션 테이블에 없어 INVALID 차단이 일시적으로 늘어나는 것이 흔합니다. 장비 이벤트 시각과 함께 봅니다. NAT와 결합된 세션 처리는 186. Firewall NAT 정책, 세션 로그 형식은 187. Firewall Log에서 이어집니다.