트래픽이 많은 서버에서 연결이 간헐적으로 끊기고, dmesg에 이런 줄이 찍힙니다.
OUTPUT
nf_conntrack: table full, dropping packet
방화벽(netfilter)이 모든 연결을 추적하는 conntrack 테이블이 가득 차서 새 패킷을 버리고 있다는 뜻입니다. 애플리케이션 로그에는 원인이 안 보이고 커널 메시지에만 나타나기 때문에 놓치기 쉽습니다.
1단계 — 지금 얼마나 찼나
현재 추적 중인 연결 수와 최대치를 비교합니다.
로컬 터미널
sysctl net.netfilter.nf_conntrack_count # 현재 추적 중
sysctl net.netfilter.nf_conntrack_max # 최대 허용
count가 max에 거의 닿아 있으면 그게 원인입니다. 커널 메시지도 함께 확인합니다.
로컬 터미널
dmesg -T | grep -i conntrack
2단계 — 무엇이 테이블을 채우나
대부분 한도가 작거나, TIME_WAIT로 닫힌 연결이 timeout까지 오래 남아 쌓이는 경우입니다. 어떤 상태의 연결이 많은지 봅니다.
로컬 터미널
sudo conntrack -L | awk '{print $1, $4}' | sort | uniq -c | sort -rn | head
TIME_WAIT나 특정 출발지가 압도적으로 많다면 그쪽이 채우는 주범입니다.
3단계 — 한도 상향과 timeout 단축
| 항목 | 파라미터 | 방향 |
|---|---|---|
| 테이블 최대 크기 | nf_conntrack_max | 메모리 여유만큼 상향 |
| 해시 버킷 | nf_conntrack_buckets | max의 1/4 권장 |
| 닫힌 연결 잔류 | nf_conntrack_tcp_timeout_time_wait | 과도하게 길면 단축 |
즉시 적용(런타임) 후, 영구 반영합니다.
로컬 터미널
sudo sysctl -w net.netfilter.nf_conntrack_max=262144
로컬 터미널
# /etc/sysctl.d/conntrack.conf 에 기록 후
sudo sysctl --system
값은 무한정 올리지 말고 메모리와 트래픽 특성에 맞춰 단계적으로 키웁니다. 추적이 굳이 필요 없는 트래픽이라면 NOTRACK 규칙으로 conntrack 대상에서 제외하는 것도 근본 해결책입니다.
체크리스트
로컬 터미널
dmesg -T | grep -i conntrack # table full 확인
sysctl net.netfilter.nf_conntrack_count # 현재값
sysctl net.netfilter.nf_conntrack_max # 최대값
sysctl -w net.netfilter.nf_conntrack_max=262144 # 상향(런타임)
sysctl --system # 영구 반영
count와 max의 거리만 보면 이 문제는 즉시 판별됩니다. 핵심은 단순 상향이 아니라 "무엇이 테이블을 채우는가"까지 보는 것입니다.
conntrack·netfilter 같은 커널 네트워크 동작을 직접 관찰하는 실습은 네트워크 트랙에서 회원가입 없이 무료로 할 수 있습니다.