Journey to Security/리눅스

[방화벽] iptables Conntrack (1) 상태 기반 룰 설정

Cordilog 2026. 6. 3. 14:23

방화벽이 연결 상태 추적을 못하면 패킷이 새로운 연결 요청인지, 이미 허가된 세션의 일부인지, 아니면 아무 연결도 없는 상태에서 날아온 비정상 패킷인지 구분할 수 없다.

iptables의 conntrack 모듈은 이러한 문제를 해결하는 상태 추적 엔진이다.

 

1. conntrack이란?

conntrack(Connection Tracking)은 Linux 커널의 netfilter 프레임워크 안에 있는 상태 추적 모듈이다.

커널은 이 모듈을 통해 모든 네트워크 연결의 상태를 테이블에 기록하고, iptables 룰이 각 패킷의 "상태"를 기준으로 허용 / 차단 여부를 결정할 수 있도록 만든다.

iptables에서 상태 기반 필터링을 사용하려면 -m state 또는 -m conntrack 매칭 모듈을 지정한다.

 

# -m state 방식 (예전 방식)
iptables -A INPUT -m state --state ESTABLISHED -j ACCEPT

# -m conntrack 방식 (최근 방식)
iptables -A INPUT -m conntrack --ctstate ESTABLISHED -j ACCEPT

 

2. conntrack이 추적하는 연결 상태

1️⃣ NEW : 새로운 연결 시도

conntrack 테이블에 아직 등록되지 않은 첫 번째 패킷이다.

TCP의 경우 SYN 패킷이 해당된다.

방화벽은 이 상태의 패킷을 허용할지 거부할지 결정함으로써 외부에서 들어오는 새 접속을 통제한다.

2️⃣ ESTABLISHED : 이미 성립된 연결

양방향으로 패킷이 오간 연결, 핸드셰이크가 완료된 세션의 패킷이다.

이미 허용된 세션이므로 대부분의 방화벽 정책에서 별도 검사 없이 통과시킨다.

3️⃣ RELATED : 연관된 보조 연결

기존 ESTABLISHED 연결에서 파생된 새로운 연결이다.

FTP 데이터 채널, ICMP 에러 응답이 대표적이다.

4️⃣ INVALID : 추적 불가능한 비정상 패킷

conntrack 테이블에 매칭되는 세션이 없는데 비정상적으로 날아온 패킷이다.

연결 수립 없이 도착한 FIN, RST, 잘못된 플래그 조합 등이 여기에 해당한다.

공격 트래픽, 패킷 재조합 오류, 스캐닝 시도가 이 상태로 분류되는 경우가 많다.

 

3. TCP 핸드셰이크와 conntrack 상태 흐름

 

 

SYN이 도착하는 순간 conntrack은 해당 5-tuple(출발지 IP·포트, 도착지 IP·포트, 프로토콜)을 테이블에 NEW 상태로 등록한다. ACK까지 완료되면 ESTABLISHED로 전환하고, 이후 같은 세션에 속하는 모든 패킷은 ESTABLISHED로 매칭된다.

반대로 세션 테이블에 아무 정보도 없는 상태에서 FIN이 도착하면 conntrack은 이를 어떤 세션에도 귀속시킬 수 없어 INVALID 상태를 부여하고, 올바른 룰 구성 하에서 DROP된다.

 

4. 권장 룰 순서

iptables는 체인의 룰을 위에서 아래로 순서대로 평가하며, 첫 번째 매칭에서 결정이 내려지면 이후 룰은 건너뛴다.

[1] INVALID  먼저 차단    → 비정상 패킷을 가장 먼저 제거
[2] ESTABLISHED 허용      → 이미 허가된 세션 트래픽을 빠르게 통과
[3] NEW 허용              → 정책에 따라 새 접속 허용
[4] 나머지 전부 차단      → 묵시적 거부

 

ESTABLISHED를 NEW보다 앞에 두는 이유는 성능 때문이다.

실제 트래픽의 대부분은 이미 성립된 세션의 데이터 패킷이므로, ESTABLISHED 룰을 상단에 배치하면 대다수 패킷이 두 번째 룰에서 처리되어 불필요한 룰 평가를 줄인다.

 

5. 실습: 상태 기반 SSH 방화벽 구성

1️⃣ 환경 초기화 및 룰 적용

iptables -F
# 루프백 인터페이스 허용
iptables -A INPUT -i lo -j ACCEPT

# [1] INVALID 패킷 차단
iptables -A INPUT -m state --state INVALID -j DROP

# [2] ESTABLISHED,RELATED 패킷 허용
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

# [3] NEW 패킷 허용 (새 SSH 접속)
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -j ACCEPT

# [4] 나머지 전부 차단
iptables -A INPUT -j DROP

 

  • 환경 초기화: 프로덕션 환경에서는 적용 전 현재 룰을 반드시 백업한다. iptables-save > rules.bak
  • 루프백 인터페이스 허용: 127.0.0.1을 통해 통신하는 로컬 서비스들이 많으므로 방화벽 정책을 적용하기 전에 가장 먼저 처리한다. 빠뜨리면 데이터베이스 연결, 소켓 통신 등 로컬 프로세스 간 통신이 차단될 수 있다.
  • INVALID 패킷 차단: 세션 테이블에 귀속시킬 수 없는 비정상 패킷을 이후 룰 평가 없이 즉시 제거한다.
  • ESTABLISHED,RELATED 허용: ESTABLISHED와 RELATED를 하나의 룰로 묶어 처리한다. RELATED는 FTP처럼 제어 채널과 데이터 채널이 분리된 프로토콜에서 필요하다. 이 룰 없이는 FTP 데이터 전송이 차단된다. 실제 트래픽의 대부분이 이 룰에서 처리되므로 NEW보다 앞에 배치하는 것이 성능상 유리하다.

💡ESTABLISHED,RELATED에는 포트를 지정하지 않는 이유:

이미 NEW 단계에서 허용 결정이 끝난 세션의 트래픽이다.

여기서 다시 포트를 검사하는 건 이중 검사고, 오히려 문제가 생길 수 있다.

예를 들어 서버가 클라이언트에 응답을 보낼 때 출발지 포트가 22지만, 클라이언트 측에서 들어오는 ACK나 데이터 패킷의 목적지 포트는 클라이언트가 쓰는 임시 포트(ephemeral port, 보통 32768~60999)다.

룰에 --dport 22를 붙이면 이 패킷들이 매칭되지 않아서 정상적으로 수립된 SSH 세션도 데이터를 주고받을 수 없게 된다.

3️⃣ 결과 확인

iptables -nvL INPUT

-n: IP를 이름으로 역조회하지 않음 / -v: 패킷·바이트 카운터 포함 / -L INPUT: INPUT 체인만 출력