nftables 방화벽 규칙 설정

Linux 서버를 위한 완전한 nftables 방화벽 룰셋입니다. SSH/HTTP/HTTPS 허용, 속도 제한, NAT 마스커레이드, 로깅을 포함합니다.

Gist
#!/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
    }
}