본문 바로가기
TYLER SONGBlog
← Blog index
CS7 min read

Firewall: 트래픽 허용 여부를 정책으로 결정하는 네트워크 경계

방화벽(Firewall)은 패킷의 주소, 포트, 프로토콜, 연결 상태를 검사해 네트워크 트래픽을 허용하거나 차단한다. 상태 비저장 방화벽(Stateless Firewall)은 개별 패킷만 판단하고, 상태 저장 방화벽(Stateful Firewall)은 연결 추적(Connection Tracking) 정보까지 활용한다. 기본 거부(Default Deny) 정

By 송민성

1. 개념

방화벽(Firewall)은 미리 정의된 규칙에 따라 들어오거나 나가는 네트워크 트래픽을 제어하는 시스템이다. 운영체제, 네트워크 장비, 클라우드 환경에서 각각 동작할 수 있다.

방화벽 규칙은 주로 다음 정보를 검사한다.

  • 출발지·목적지 인터넷 프로토콜 주소(IP Address)
  • 출발지·목적지 포트(Port)
  • 전송 제어 프로토콜(TCP), 사용자 데이터그램 프로토콜(UDP) 같은 전송 프로토콜
  • 입력·출력 네트워크 인터페이스(Network Interface)
  • 연결 상태(Connection State)
  • 패킷 진행 방향

방화벽은 동작 방식에 따라 구분할 수 있다.

  • 패킷 필터링(Packet Filtering): 패킷 헤더를 규칙과 비교한다.
  • 상태 저장 검사(Stateful Inspection): 연결 상태를 추적하며 패킷을 판단한다.
  • 애플리케이션 방화벽(Application Firewall): HTTP 메서드, URL, 헤더처럼 애플리케이션 계층 정보를 검사한다.
  • 웹 애플리케이션 방화벽(Web Application Firewall, WAF): SQL 삽입(SQL Injection), 사이트 간 스크립팅(XSS) 같은 웹 공격을 탐지하고 차단한다.

2. 왜 사용하는가

서버가 인터넷에 연결되면 실행 중인 서비스의 포트가 외부 공격 표면이 된다. 방화벽은 필요한 통신만 허용해 접근 범위를 줄인다.

예를 들어 웹 서버에 다음 정책을 적용할 수 있다.

  • 외부 사용자는 TCP 80번과 443번 포트에만 접근할 수 있다.
  • 관리용 TCP 22번 포트는 사내 인터넷 프로토콜 주소 대역에서만 접근할 수 있다.
  • 데이터베이스 TCP 5432번 포트는 애플리케이션 서버에서만 접근할 수 있다.
  • 서버가 먼저 시작한 연결의 응답 패킷은 허용한다.
  • 나머지 입력 트래픽은 차단한다.

방화벽은 인증(Authentication)을 대신하지 않는다. 허용된 포트의 애플리케이션에는 별도 인증, 권한 검사, 입력 검증이 필요하다.

3. 동작 원리

패킷이 방화벽을 통과하면 규칙 집합(Ruleset)과 비교된다. 순차 규칙 모델에서는 위에서 아래로 규칙을 검사하고 처음 일치한 규칙의 동작을 적용한다.

text
패킷 수신
  ↓
연결 추적 정보 조회
  ↓
출발지·목적지 주소, 포트, 프로토콜 검사
  ↓
규칙과 일치하는가?
  ├─ 예 → 허용(ACCEPT), 폐기(DROP), 거부(REJECT) 등 수행
  └─ 아니요 → 다음 규칙 검사
  ↓
일치 규칙 없음
  ↓
기본 정책 적용

주요 동작은 다음과 같다.

  • 허용(ACCEPT): 패킷을 통과시킨다.
  • 폐기(DROP): 응답 없이 패킷을 버린다.
  • 거부(REJECT): 패킷을 버리고 오류 응답을 보낸다.
  • 기록(LOG): 패킷 정보를 로그에 남긴다.

상태 저장 방화벽은 일반적으로 다음 연결 상태를 구분한다.

  • 신규(NEW): 새 연결을 시작하는 패킷
  • 설정됨(ESTABLISHED): 이미 성립된 연결에 속한 패킷
  • 연관됨(RELATED): 기존 연결과 관련된 별도 연결의 패킷
  • 유효하지 않음(INVALID): 정상 연결 상태로 분류할 수 없는 패킷

TCP 연결을 예로 들면 클라이언트가 서버의 443번 포트로 연결을 시작할 때 신규 상태가 만들어진다. 이후 같은 연결의 양방향 패킷은 설정됨 상태로 처리된다. 따라서 서버가 요청에 응답할 때마다 역방향 허용 규칙을 별도로 작성할 필요가 없다.

4. 코드 예제

다음 파이썬 코드는 위에서 아래로 규칙을 검사하는 간단한 상태 비저장 방화벽을 구현한다.

python
from dataclasses import dataclass from ipaddress import ip_address, ip_network from typing import Literal Action = Literal["ACCEPT", "DROP"] @dataclass(frozen=True) class Packet: source_ip: str protocol: str destination_port: int @dataclass(frozen=True) class Rule: source_network: str protocol: str destination_port: int action: Action def matches(self, packet: Packet) -> bool: return ( ip_address(packet.source_ip) in ip_network(self.source_network) and packet.protocol.lower() == self.protocol.lower() and packet.destination_port == self.destination_port ) def evaluate( packet: Packet, rules: list[Rule], default_action: Action = "DROP", ) -> Action: for rule in rules: if rule.matches(packet): return rule.action return default_action def main() -> None: rules = [ Rule("10.0.0.0/8", "tcp", 22, "ACCEPT"), Rule("0.0.0.0/0", "tcp", 443, "ACCEPT"), ] packets = [ Packet("10.20.30.40", "tcp", 22), Packet("203.0.113.10", "tcp", 22), Packet("203.0.113.10", "tcp", 443), ] results = [evaluate(packet, rules) for packet in packets] assert results == ["ACCEPT", "DROP", "ACCEPT"] for packet, result in zip(packets, results): print(f"{packet} -> {result}") if __name__ == "__main__": main()

리눅스의 넷필터(nftables)에서는 상태 저장 규칙을 다음처럼 작성할 수 있다.

shell
#!/bin/sh set -eu cat <<'EOF' | sudo nft --check --file - table inet example_firewall { chain input { type filter hook input priority filter; policy drop; iifname "lo" accept ct state invalid drop ct state established,related accept ip saddr 10.0.0.0/8 tcp dport 22 accept tcp dport { 80, 443 } accept } } EOF

--check 옵션은 규칙을 적용하지 않고 문법만 검사한다. 실제 서버에 적용하려면 기존 관리 연결과 복구 경로를 확인한 뒤 규칙 파일을 sudo nft --file 파일명으로 불러와야 한다.

5. 시간 복잡도 또는 성능 특성

규칙을 순서대로 검사하는 단순 모델에서 규칙 수를 n이라 하면 패킷 한 개의 최악 시간 복잡도는 O(n)이다. 첫 규칙이 일치하면 O(1)에 끝나지만, 마지막 규칙이 일치하거나 어떤 규칙에도 일치하지 않으면 최대 n개 규칙을 검사한다.

실제 방화벽 구현은 집합(Set), 해시 테이블(Hash Table), 트리(Tree) 같은 자료구조로 규칙 조회를 최적화할 수 있다.

  • 해시 기반 조회: 평균 O(1)
  • 균형 트리 기반 조회: O(log n)
  • 순차 규칙 탐색: 최악 O(n)

상태 저장 방화벽은 연결 추적 테이블을 위한 메모리를 추가로 사용한다. 동시 연결 수가 증가하면 테이블 크기와 조회 비용도 증가한다. 연결 추적 테이블이 가득 차면 새 연결이 실패할 수 있으므로 최대 항목 수와 만료 시간을 운영 환경에 맞게 설정해야 한다.

로깅은 저장 장치 입출력과 로그 처리 비용을 발생시킨다. 대량으로 차단되는 패킷을 제한 없이 기록하면 방화벽 자체가 성능 병목이 될 수 있다.

6. 실무 사용 사례

서버 호스트 방화벽

리눅스 서버에서 넷필터(nftables), 윈도우 서버에서 윈도우 디펜더 방화벽(Windows Defender Firewall)을 사용해 프로세스가 수신할 수 있는 포트를 제한한다.

클라우드 네트워크

보안 그룹(Security Group), 네트워크 접근 제어 목록(Network ACL)으로 가상 머신과 서브넷의 트래픽을 제어한다. 제품에 따라 상태 저장 여부와 규칙 적용 방향이 다르므로 동작 방식을 확인해야 한다.

데이터베이스 격리

PostgreSQL의 5432번 포트를 인터넷에 공개하지 않고 애플리케이션 서버가 속한 내부 네트워크에서만 허용한다. PostgreSQL 자체 접근 제어와 함께 적용해 방어 계층을 구성한다.

컨테이너와 쿠버네티스

쿠버네티스 네트워크 정책(NetworkPolicy)으로 파드(Pod) 간 통신을 제한한다. 네트워크 플러그인이 네트워크 정책을 지원하지 않으면 정책을 작성해도 실제 트래픽이 차단되지 않을 수 있다.

웹 애플리케이션 보호

웹 애플리케이션 방화벽은 HTTP 요청 내용을 검사한다. 일반 네트워크 방화벽이 443번 포트 접근을 허용한 뒤에도 악성 요청을 별도로 차단할 수 있다.

7. 주의할 점

  1. 기본 허용(Default Allow)보다 기본 거부(Default Deny)를 사용하고 필요한 통신만 명시적으로 허용한다.
  2. 원격 서버의 SSH 규칙을 변경할 때 현재 관리 연결을 먼저 허용한다. 잘못된 규칙은 원격 접근을 즉시 차단할 수 있다.
  3. 규칙 순서를 확인한다. 넓은 허용 규칙이 앞에 있으면 뒤의 세부 차단 규칙이 실행되지 않을 수 있다.
  4. DROP과 REJECT를 목적에 맞게 선택한다. DROP은 응답하지 않고, REJECT는 연결 실패를 즉시 알린다.
  5. 인터넷 프로토콜 버전 4(IPv4)만 설정하고 인터넷 프로토콜 버전 6(IPv6)을 방치하지 않는다. 두 프로토콜의 정책을 함께 관리해야 한다.

8. 핵심 정리

  • 방화벽은 주소, 포트, 프로토콜, 인터페이스, 연결 상태를 기준으로 트래픽을 제어한다.
  • 상태 저장 방화벽은 연결 추적 정보를 사용해 기존 연결의 응답 패킷을 식별한다.
  • 기본 거부 정책과 최소 권한 원칙으로 필요한 통신만 허용한다.
  • 순차 규칙 모델의 최악 조회 비용은 O(n)이며, 규칙 순서가 동작과 성능에 영향을 준다.
  • 방화벽은 인증과 애플리케이션 보안을 대체하지 않으며 여러 방어 계층 중 하나로 사용한다.