nftables 방화벽 규칙 설정
Linux 서버를 위한 완전한 nftables 방화벽 룰셋입니다. SSH/HTTP/HTTPS 허용, 속도 제한, NAT 마스커레이드, 로깅을 포함합니다.
#!/usr/sbin/nft -f
# /etc/nftables.conf
# nftables 방화벽 설정
# 적용: sudo nft -f /etc/nftables.conf
# 확인: sudo nft list ruleset
# 기존 규칙 초기화 (적용 전 클린 슬레이트 보장)
flush ruleset
# ============================================================
# inet 테이블: IPv4/IPv6 모두 처리하는 통합 테이블
# ============================================================
table inet filter {
# ----------------------------------------------------------
# SSH 브루트포스 방지용 집합 (동적 IP 차단 목록)
# timeout: 30분 후 자동 제거, maxelem: 최대 1000개 항목
# ----------------------------------------------------------
set ssh_ratelimit {
type ipv4_addr
flags dynamic, timeout
timeout 30m
size 1000
}
# ----------------------------------------------------------
# 수신 체인 (외부 → 서버로 들어오는 패킷)
# policy drop: 명시적으로 허용되지 않은 모든 패킷 차단
# ----------------------------------------------------------
chain input {
type filter hook input priority filter; policy drop;
# 루프백 인터페이스 전체 허용 (내부 프로세스 통신)
iif lo accept
# 비정상 패킷(invalid) 즉시 드롭 및 로깅
ct state invalid log prefix "[NFT-INVALID] " level warn drop
# 기존 연결 및 관련 패킷 허용 (상태 기반 방화벽)
ct state { established, related } accept
# ----------------------------------------------------------
# ICMP 처리 (ping, traceroute 등 네트워크 진단)
# 속도 제한으로 ICMP 플러드 공격 방어
# ----------------------------------------------------------
ip protocol icmp icmp type {
echo-request, # ping 요청
destination-unreachable,
time-exceeded,
parameter-problem
} limit rate 10/second accept
ip6 nexthdr icmpv6 icmpv6 type {
echo-request,
nd-neighbor-solicit, # NDP 이웃 탐색
nd-neighbor-advertise, # NDP 이웃 광고
nd-router-solicit,
nd-router-advertise,
mld-listener-query
} limit rate 10/second accept
# ----------------------------------------------------------
# SSH 포트 보호 (브루트포스 방어)
# 30초 내 5회 초과 시도 IP를 차단 목록에 추가
# ----------------------------------------------------------
tcp dport 2222 ct state new \
add @ssh_ratelimit { ip saddr limit rate over 5/minute } \
log prefix "[NFT-SSH-BLOCK] " drop
tcp dport 2222 ct state new \
ip saddr @ssh_ratelimit \
log prefix "[NFT-SSH-BLOCKED] " drop
# SSH 정상 접속 허용
tcp dport 2222 ct state new accept
# ----------------------------------------------------------
# 웹 서비스 허용
# ----------------------------------------------------------
# HTTP/HTTPS 허용 (IPv4, IPv6 모두)
tcp dport { 80, 443 } accept
# ----------------------------------------------------------
# 기타 서비스 허용 (필요에 따라 주석 해제)
# ----------------------------------------------------------
# DNS (권위 DNS 서버인 경우)
# tcp dport 53 accept
# udp dport 53 accept
# NTP (시간 동기화 서버인 경우)
# udp dport 123 accept
# ----------------------------------------------------------
# 드롭된 패킷 로깅 (디버깅 및 보안 감사)
# limit: 로그 과부하 방지 (분당 5개 제한)
# ----------------------------------------------------------
limit rate 5/minute log prefix "[NFT-DROP-INPUT] " level info
}
# ----------------------------------------------------------
# 수신 체인 (서버 → 외부로 나가는 패킷)
# policy accept: 아웃바운드는 기본 허용 (필요시 drop으로 변경)
# ----------------------------------------------------------
chain output {
type filter hook output priority filter; policy accept;
# 루프백 명시 허용
oif lo accept
# 기존 연결 허용
ct state { established, related } accept
# 비정상 패킷 차단
ct state invalid drop
}
# ----------------------------------------------------------
# 포워딩 체인 (라우터/게이트웨이 역할 시 사용)
# 단순 서버라면 policy drop 유지
# ----------------------------------------------------------
chain forward {
type filter hook forward priority filter; policy drop;
# 기존 연결 포워딩 허용
ct state { established, related } accept
# 내부 네트워크(192.168.1.0/24) → 외부 포워딩 허용
# iifname "eth1" ip saddr 192.168.1.0/24 oifname "eth0" accept
ct state invalid drop
}
}
# ============================================================
# NAT 테이블: 주소 변환 (게이트웨이/라우터 서버용)
# ============================================================
table inet nat {
# ----------------------------------------------------------
# PREROUTING: 목적지 NAT (DNAT) — 포트 포워딩
# 외부 80 포트를 내부 서버 8080으로 전달
# ----------------------------------------------------------
chain prerouting {
type nat hook prerouting priority dstnat; policy accept;
# 포트 포워딩 예시: 외부 8080 → 내부 서버 192.168.1.10:80
# ip daddr 203.0.113.1 tcp dport 8080 dnat to 192.168.1.10:80
}
# ----------------------------------------------------------
# POSTROUTING: 소스 NAT (SNAT/마스커레이드)
# 내부 네트워크가 인터넷을 사용할 수 있도록 IP 변환
# masquerade: 동적 IP 환경에서 자동으로 외부 IP 사용
# ----------------------------------------------------------
chain postrouting {
type nat hook postrouting priority srcnat; policy accept;
# 내부 192.168.1.0/24 → eth0 (WAN 인터페이스)로 마스커레이드
ip saddr 192.168.1.0/24 oifname "eth0" masquerade
}
}