콘텐츠로 이동

nftables Gateway Egress 통제 가이드

nftables는 Linux 커널의 최신 패킷 필터 프레임워크임.
본 문서에서는 Reverse Proxy Gateway 서버에서 내부망(192.168.0.0/24)으로 나가는 TCP 아웃바운드 트래픽을 최소 허용(allowlist) 방식으로 통제하는 정책을 정의함.

본 서버의 목적은 Nginx Reverse Proxy Gateway이며,
외부 트래픽은 Nginx가 수신하고 내부 서버로 proxy_pass 하여 중계함.

Internet
  ↓
공유기 (Port Forward)
  ↓
Gateway Server (Linux + Nginx)
  ↓
Internal Servers (192.168.0.0/24)

목적: Gateway 서버가 내부망 전체에 임의 접근하지 못하도록 제한하고,
실제 Reverse Proxy 대상 backend IP:port 만 허용함.


1. 왜 필요한가

Gateway 서버는 외부와 내부망 사이의 중간 지점이므로,
서버 침해 시 공격자가 내부망 전체로 이동(Pivoting / Lateral Movement)할 가능성이 존재함.

따라서 다음을 만족하도록 설계함.

  • 외부 인바운드는 firewalld 로 관리 (L3)
  • 내부망 아웃바운드는 nftables 로 관리 (L4)
  • 허용 대상은 Nginx가 실제 proxy_pass 하는 backend IP:port 등록
  • DB, SSH, Redis 등 내부 서비스 포트는 허용하지 않음

2. 전제 조건

본 정책은 다음 전제를 둠.

  • Nginx Reverse Proxy 사용
  • 내부망: 192.168.0.0/24
  • 내부 backend는 주로 80, 443, 3000, 3001 등의 HTTP/HTTPS 계열 포트 사용
  • MySQL(3306), Redis(6379), SSH(22) 등은 Gateway에서 직접 접근하지 않도록 함
  • localhost backend (127.0.0.1:3000 등)는 본 정책의 차단 대상이 아님

3. firewalld 와 nftables 병행 사용 주의

일반론적으로는

  • 단순/표준 정책 → firewalld
  • 복잡/고성능/정밀 정책 → nftables

다음과 같이 역할을 분리하여 운영함.

  • firewalld
    • 인바운드 정책
    • http, https
    • 내부망만 ssh
  • nftables
    • Gateway → Internal Network (192.168.0.0/24) 아웃바운드 allowlist

⚠️ 주의
firewalld 와 nftables 를 함께 운용하는 경우
규칙 충돌, reload 시점, 운영 절차를 명확히 관리해야 함.
특히 firewalld reload 이후에도 nftables 커스텀 rule 이 유지되는지 확인해야 함.

운영 원칙

  • firewalld 는 인바운드 제어 전용
  • nftables 는 내부망 egress 통제 전용
  • 두 정책이 서로 다른 chain/table 을 사용하도록 분리
  • 변경 시 반드시 테스트 후 반영

본 방식은 운영 난이도가 높은 고급(Advanced) 패턴임.
표준 환경에서는 firewalld 단독 또는 nftables 단독 운용이 일반적이며,
병행 운용 시에는 재적용 절차와 검증 절차를 반드시 표준화해야 함.


4. 보안 목표

허용할 트래픽:

  • loopback (lo)
  • established / related
  • Nginx가 실제로 proxy_pass 하는 내부 backend IP:port

차단할 트래픽:

  • 192.168.0.0/24 전체에 대한 임의 TCP 접근
  • DB 포트 접근
  • SSH 포트 접근
  • 내부망 포트 스캔 성격 접근

예:

  • 허용: 192.168.0.10:3000
  • 허용: 192.168.0.11:3001
  • 허용: 192.168.0.20:80
  • 허용: 192.168.0.21:443
  • 차단: 192.168.0.30:22
  • 차단: 192.168.0.40:3306
  • 차단: 192.168.0.50:6379

DNS outbound

시스템 패키지 업데이트, certbot 인증서 갱신, 외부 API 호출 등을 위해
Gateway 서버의 DNS outbound 트래픽은 허용됨.

일반적으로 다음 트래픽이 발생할 수 있음.

  • UDP 53
  • TCP 53

본 nftables 정책은 내부망(192.168.0.0/24) 접근 통제 목적이므로
외부 DNS 서버로의 트래픽에는 영향을 주지 않음.


5. nftables 설치

Rocky Linux 9 에서는 기본 포함되는 경우가 많지만, 명시적으로 설치 상태를 맞춤.

sudo dnf install -y nftables

설치 확인:

rpm -q nftables
nft --version

6. nftables 서비스 활성화 여부

운영 권장

본 문서에서는 firewalld 와의 병행 운용을 전제로 하므로
nftables.service 를 무조건 활성화하는 방식보다는
별도 rule 파일을 명시적으로 로드하는 방식을 권장함.

즉, 아래를 기본 원칙으로 함.

  • firewalld.service 는 활성화 유지
  • nftables.service 는 즉시 활성화하지 않음
  • 커스텀 egress rule 은 별도 파일로 관리
  • 테스트 완료 후 systemd unit 또는 운영 스크립트로 로드

7. 규칙 파일 경로

권장 경로:

/etc/nftables/gateway-egress.nft

디렉터리 생성:

sudo mkdir -p /etc/nftables

8. 규칙 설계 방식

nftables 의 setconcatenation(ipv4_addr . inet_service) 를 사용하여
IP:port 조합 allowlist 를 구성함.

192.168.0.10 . 3000
192.168.0.11 . 3001
192.168.0.20 . 80
192.168.0.21 . 443

장점:

  • 허용 목록이 명확함
  • Nginx proxy_pass 대상과 1:1 대응 가능
  • 신규 backend 추가 시 allowlist 만 추가하면 됨
  • DB / SSH / Redis 등은 등록하지 않는 한 접근 불가

운영 기준: allowlist 는 활성 Nginx proxy_pass 기준으로 관리

이 문서의 allowed_backend_tcp 는 임의로 작성하지 않음.
반드시 현재 운영 중인 Nginx 설정의 proxy_pass 대상 IP:port 를 기준으로 구성함.

즉 다음 원칙을 사용함.

  • Nginx에 없는 내부 IP:port 는 allowlist 에 넣지 않음
  • Nginx에 새 proxy_pass 가 추가되면 nftables allowlist 도 함께 반영함
  • Nginx에서 제거된 backend 는 nftables allowlist 에서도 제거함
  • 가능하면 domain 과 IP:port 매핑표를 함께 관리함

점검 예시:

sudo nginx -T 2>/dev/null | grep -n proxy_pass

출력 예시:

proxy_pass http://192.168.0.200:3001;
proxy_pass http://192.168.0.200:3002;
proxy_pass https://192.168.0.215;
proxy_pass http://127.0.0.1:3000;

위 결과를 nftables allowlist 로 반영하면 다음과 같음.

set allowed_backend_tcp {
    type ipv4_addr . inet_service
    elements = {
        192.168.0.200 . 3001,
        192.168.0.200 . 3002,
        192.168.0.215 . 443
    }
}

변환 기준:

  • http://192.168.0.200:3001192.168.0.200 . 3001
  • http://192.168.0.200:3002192.168.0.200 . 3002
  • https://192.168.0.215192.168.0.215 . 443
  • http://127.0.0.1:3000 은 내부망 192.168.0.0/24 통제 대상이 아니므로 본 allowlist 대상이 아님

운영 시에는 위 결과를 기준으로 /etc/nftables/gateway-egress.nft
allowed_backend_tcp 와 1:1로 대조하는 것을 표준 절차로 함.


9. 기본 규칙 예시

본 정책은 TCP backend 접근 통제 목적이므로 UDP 트래픽은 차단하지 않음. 또한 예시 규칙은 IPv4 내부망(192.168.0.0/24) 기준임.

내부망 전체 IPv4 트래픽을 차단하려면 다음 규칙을 사용함.

ip daddr 192.168.0.0/24 drop

TCP/UDP만 차단하려면 프로토콜별로 명시함.

meta l4proto tcp ip daddr 192.168.0.0/24 drop
meta l4proto udp ip daddr 192.168.0.0/24 drop

priority 100 은 firewalld rule 이후에 실행되도록 하기 위한 설정임.

table inet gateway_egress {

    set allowed_backend_tcp {
        type ipv4_addr . inet_service
        elements = {
            192.168.0.10 . 3000,
            192.168.0.11 . 3001,
            192.168.0.20 . 80,
            192.168.0.21 . 443
        }
    }

    chain output {
        type filter hook output priority 100; policy accept;

        oifname "lo" accept
        ct state established,related accept

        ip daddr . tcp dport @allowed_backend_tcp accept
        meta l4proto tcp ip daddr 192.168.0.0/24 drop
    }

}

의미

  • 이미 수립된 연결은 허용
  • loopback 은 허용
  • 허용 목록(allowed_backend_tcp)에 있는 내부 backend 만 허용
  • 그 외 내부망 TCP 접근은 차단

10. 검증 모드 권장

운영 서버에서는 처음부터 차단 정책을 적용하지 않고
검증 모드(log) 를 먼저 적용하는 것을 권장함.

meta l4proto tcp ip daddr 192.168.0.0/24 log prefix "GW_EGRESS_DENY " level warn

로그 확인:

sudo journalctl -k -f

검증 완료 후 logdrop 으로 변경함.


11. 규칙 파일 작성

파일 생성:

sudo vi /etc/nftables/gateway-egress.nft

내용:

table inet gateway_egress {

    set allowed_backend_tcp {
        type ipv4_addr . inet_service
        elements = {
            192.168.0.10 . 3000,
            192.168.0.11 . 3001,
            192.168.0.20 . 80,
            192.168.0.21 . 443
        }
    }

    chain output {
        type filter hook output priority 100; policy accept;

        oifname "lo" accept
        ct state established,related accept

        ip daddr . tcp dport @allowed_backend_tcp accept
        meta l4proto tcp ip daddr 192.168.0.0/24 drop
    }

}

12. 적용 전 점검 (필수)

현재 nftables 상태 확인.

sudo nft list ruleset

문법 검사.

sudo nft -c -f /etc/nftables/gateway-egress.nft

backend 연결 테스트.

sudo nginx -T 2>/dev/null | grep -n proxy_pass
curl http://192.168.0.10:3000
curl http://192.168.0.11:3001

적용 전에는 반드시 Nginx proxy_pass 목록과 allowed_backend_tcp 항목이 일치하는지 확인함.


13. nftables 적용 절차

13.1 문법 검증

sudo nft -c -f /etc/nftables/gateway-egress.nft

13.2 기존 table 정리 (재적용 안정성)

sudo nft list table inet gateway_egress >/dev/null 2>&1 && sudo nft delete table inet gateway_egress

13.3 규칙 적용

sudo nft -f /etc/nftables/gateway-egress.nft

14-nftables Gateway Egress 자동 로드 가이드 방식으로
nftables-gateway-egress.service 를 운영 중인 서버에서는
직접 nft -f 를 반복 실행하기보다 아래 방식으로 재적용하는 것을 운영 표준으로 함.

sudo systemctl restart nftables-gateway-egress.service

13.4 적용 확인

sudo nft list table inet gateway_egress

위 절차를 사용하면 동일 명령을 반복 실행해도 적용 결과를 일정하게 유지할 수 있음.


14. 테스트 방법

허용 대상 테스트:

curl http://192.168.0.10:3000
curl http://192.168.0.11:3001

차단 대상 테스트:

nc -zv 192.168.0.30 22
nc -zv 192.168.0.40 3306

15. 롤백 방법

sudo nft delete table inet gateway_egress

16. 운영 절차

신규 backend 추가 시

  1. Nginx 설정 추가
  2. proxy_pass 대상 확인
  3. nftables allowlist 추가
  4. 문법 검사
  5. 적용
  6. 테스트

17. 운영 정책 요약

  • firewalld: 인바운드 정책
  • nftables: 내부망 egress 정책
  • localhost backend 제외
  • 내부망은 allowlist 기반 통제

18. 참고 사항

sudo nft list ruleset

firewalld reload 이후 표준 점검/재적용 절차:

sudo firewall-cmd --reload
sudo nft list table inet gateway_egress >/dev/null 2>&1 || sudo nft -f /etc/nftables/gateway-egress.nft
sudo nft list table inet gateway_egress
  • firewalld reload 이후에도 커스텀 table 이 유지되는지 항상 확인함.
  • table 이 없으면 즉시 재적용하여 egress 정책 공백을 방지함.

19. 참고 문서

  • Red Hat firewalld Documentation
  • nftables 공식 문서