컴퓨터 구조 운영체제 네트워크 자료구조 알고리즘 데이터베이스 내 학습
network · 16

방화벽 패킷 필터링

보안패킷필터방화벽

서버를 인터넷에 연결하면 누구나 그 서버에 패킷을 보낼 수 있습니다. 그 가운데는 정상적인 사용자의 요청도 있지만, 열려 있는 모든 포트를 두드려 보는 스캔이나 공격 시도도 섞여 있습니다. 방화벽(firewall)은 네트워크의 경계나 서버 앞에서 들어오고 나가는 트래픽을 규칙에 따라 허용하거나 차단하는 장치(또는 소프트웨어)입니다. 건물의 출입문에서 출입증을 확인하는 경비와 비슷합니다. 가장 기본적인 방식인 패킷 필터링은 패킷 헤더의 출발지와 목적지 IP 주소, 포트 번호, 프로토콜 같은 값을 규칙과 비교해 통과 여부를 정합니다.

iptables나 네트워크 ACL처럼 규칙에 순서가 있는 방화벽은 위에서부터 차례로 비교해 처음 일치한 규칙을 적용하기 때문에 순서가 중요하고, 어느 규칙에도 일치하지 않는 패킷은 기본 정책이 정합니다. 또한 응답 패킷을 어떻게 통과시킬지에 따라 상태를 보지 않는 방식과 연결 상태를 추적하는 상태 기반(stateful) 방식으로 나뉩니다. 이 토픽에서는 규칙이 매칭되는 과정, 상태 추적이 응답을 처리하는 방식, 기본 거부와 기본 허용의 차이를 단계별로 봅니다.

핵심 개념

패킷 필터링

패킷 헤더의 출발지 · 목적지 IP, 포트 번호, 프로토콜(TCP, UDP 등)을 규칙과 비교해 허용하거나 차단합니다. 패킷의 내용(페이로드)은 보지 않는 것이 기본입니다.

핵심 개념

규칙과 매칭 순서

iptables, nftables, 네트워크 ACL처럼 순서가 있는 규칙은 위에서부터 차례로 비교해 처음 일치한 규칙의 동작을 적용합니다(AWS 보안 그룹은 허용 규칙만 있어 순서가 없습니다). 그래서 구체적인 규칙을 위에, 넓은 규칙을 아래에 두는 순서가 결과를 바꿉니다.

핵심 개념

기본 정책

어떤 규칙에도 일치하지 않는 패킷을 어떻게 할지 정하는 설정입니다. 기본 거부(default deny)는 허용한 것만 통과시키고, 기본 허용은 차단한 것만 막습니다.

핵심 개념

상태 기반 방화벽

연결 상태를 표로 추적해, 허용된 연결의 응답 패킷은 별도 규칙 없이 통과시킵니다. 표에 없는 패킷은 허용 규칙에 일치하지 않으면(보통 인바운드 기본 거부) 차단합니다.

핵심 개념

인바운드와 아웃바운드

밖에서 안으로 들어오는 방향이 인바운드, 안에서 밖으로 나가는 방향이 아웃바운드입니다. 보통 인바운드는 엄격하게, 아웃바운드는 비교적 느슨하게 정합니다.

핵심 개념

애플리케이션 계층 방화벽

헤더뿐 아니라 HTTP 요청 같은 응용 계층의 내용을 보고 판단하는 방화벽입니다. 웹 공격을 막는 웹 애플리케이션 방화벽(WAF)이 한 예입니다.

헤더만 봐도 많이 막습니다 — 어느 IP에서 어느 포트로 오는지만 따져도, 열어 둘 필요 없는 포트로 오는 접근을 걸러 낼 수 있습니다.
순서가 결과를 정합니다 — 순서가 있는 규칙에서는 처음 일치한 규칙에서 판단이 끝나므로, 넓은 허용 규칙이 위에 있으면 아래의 차단 규칙이 소용없어집니다.
응답은 상태가 돕습니다 — 상태를 추적하면 "안에서 시작한 연결의 응답"을 자동으로 허용해 규칙이 단순해지고 안전해집니다.
기본은 거부가 안전합니다 — 필요한 것만 허용하면 빠뜨린 트래픽은 저절로 차단되고, 기본 허용은 차단 규칙 하나를 놓치면 바로 구멍이 됩니다.
이 시각화에서 확인할 것 — "규칙 매칭" 탭에서 패킷이 규칙을 비교하는 과정을, "상태 추적" 탭에서 응답이 통과하는 이유를, "기본 정책" 탭에서 기본 거부와 기본 허용의 차이를 STEP으로 확인하세요.

방화벽의 배경

방화벽은 라우터 같은 장비에서 패킷을 걸러 내는 패킷 필터링으로 시작되었고, 이후 연결 상태를 추적하는 상태 기반 방식, 연결을 둘로 나눠 중계하며 내용을 검사하는 프록시 방식, 응용 계층까지 보는 방식이 등장했습니다. 개념과 설계 원칙은 NIST의 방화벽 가이드(SP 800-41)에 정리되어 있습니다. 오늘날에는 전용 장비뿐 아니라 운영체제 커널의 필터링 기능(리눅스의 netfilter 등), 클라우드의 보안 그룹처럼 소프트웨어로도 흔히 쓰입니다.

숫자로 확인하기

시각화의 규칙 — 허용 2개(출발지 10.0.0.0/8의 포트 22, 모든 출발지의 포트 443), 차단 1개(포트 23), 마지막에 기본 거부 1개로 규칙이 4개입니다.
패킷 5개의 결과 — 내부 SSH(22)와 외부 HTTPS(443)는 허용, 외부 SSH, 텔넷(23), UDP 53은 차단됩니다. 5개 가운데 2개가 허용, 3개가 차단입니다.
포트의 범위 — 포트 번호는 16비트로 0~65535입니다. 기본 허용에서는 이 중 막아 둔 포트를 뺀 나머지가 모두 통과하고, 기본 거부에서는 허용한 포트만 통과합니다.
응답 규칙의 차이 — 상태 없는 필터에서는 아웃바운드로 쓰는 서비스마다 그 응답이 돌아올 포트 범위를 허용하는 인바운드 규칙이 따로 필요하지만, 상태 기반에서는 연결 표가 이를 대신합니다.

자주 하는 오해

방화벽이 있으면 안전하다 — 허용한 포트로 들어오는 공격(예: 웹 서버의 취약점 공격)은 헤더만 보는 방화벽이 막지 못합니다. 방화벽은 여러 방어 수단 가운데 하나입니다.
패킷 필터링은 패킷 내용까지 검사한다 — 기본적인 패킷 필터링은 IP, 포트, 프로토콜 같은 헤더 정보만 봅니다. 내용을 보려면 응용 계층 방화벽이나 침입 방지 시스템이 필요합니다.
기본 허용이 편해서 낫다 — 편하긴 하지만 규칙에서 빠뜨린 트래픽이 그대로 통과합니다. 보안에서는 필요한 것만 허용하는 기본 거부를 권장합니다.
방화벽은 경계에만 둔다 — 네트워크 경계의 방화벽 외에 서버마다 호스트 방화벽을 두고 내부 구간도 나누는 구성이 흔합니다. 한 곳이 뚫려도 피해가 번지지 않게 합니다.

면접에서 이렇게 물어요

면접 질문

방화벽은 무엇이고 어떻게 동작하나요?

네트워크 트래픽을 규칙에 따라 허용하거나 차단하는 장치입니다. 패킷 필터링 방화벽은 패킷 헤더의 IP 주소, 포트, 프로토콜을 규칙과 위에서부터 비교해 처음 일치한 규칙을 적용합니다.

면접 질문

상태 기반 방화벽은 무엇이 다른가요?

연결 상태 표를 유지해, 허용된 연결에 대한 응답 패킷을 별도 규칙 없이 통과시킵니다. 상태를 보지 않는 필터보다 규칙을 단순하고 안전하게 만들 수 있습니다.

면접 질문

기본 정책은 어떻게 정하는 게 좋은가요?

기본 거부(default deny)가 권장됩니다. 필요한 트래픽만 명시적으로 허용하면 규칙에서 빠뜨린 트래픽이 자동으로 차단되어, 실수가 구멍이 되지 않습니다.

면접 질문

방화벽과 NAT는 어떻게 다른가요?

NAT는 주소를 바꾸는 기술이고 방화벽은 트래픽을 허용하거나 차단하는 정책 장치입니다. NAT 때문에 외부 접속이 막히는 효과가 있어도 접근 제어의 용도는 아닙니다.

실제 시스템에서는

리눅스 — 커널의 netfilter가 패킷을 걸러 내고, iptables나 nftables로 규칙을 설정합니다. ufw나 firewalld는 이를 쉽게 다루는 도구입니다.
클라우드 — AWS의 보안 그룹은 상태 기반이고 네트워크 ACL은 상태를 추적하지 않는 방식이어서, 응답 트래픽에 대한 규칙이 필요한지가 다릅니다.
호스트 방화벽 — 운영체제 자체에 방화벽이 있어 서버나 PC 단위로 열 포트를 정합니다. 윈도우는 기본으로 켜져 있고, 리눅스는 커널에 netfilter가 포함되어 있으며 켜져 있는지는 배포판과 설정에 따라 다릅니다.
웹 애플리케이션 방화벽 — HTTP 요청의 내용을 검사해 SQL 삽입 같은 웹 공격을 막는 응용 계층 방화벽으로, 일반 패킷 필터링과 목적이 다릅니다.

함께 보면 좋은 토픽

NAT — 연결 추적과 변환 표를 함께 쓰는 방식을 봅니다.
TCP/IP — 방화벽이 보는 IP 주소와 포트, 프로토콜을 봅니다.
VPN 터널링 — 방화벽과 함께 쓰는 접근 보호 방법을 봅니다.
로드 밸런서 — 서버 앞에 놓이는 또 다른 네트워크 장치를 봅니다.

참고 자료

iptables — 기본 거부와 상태 기반 규칙

# 확립된 연결과 관련 연결, 로컬 통신은 통과 (상태 기반)
sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
sudo iptables -A INPUT -i lo -j ACCEPT

# 필요한 것만 명시적으로 허용
sudo iptables -A INPUT -p tcp -s 10.0.0.0/8 --dport 22 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT

# 허용 규칙을 모두 넣은 뒤 마지막에 기본 정책을 차단으로 바꾼다
sudo iptables -P INPUT DROP

# 규칙을 순서대로 보기
sudo iptables -L INPUT -n -v --line-numbers

iptables -P INPUT DROP은 INPUT 사슬의 기본 정책을 차단으로 정해, 어느 규칙에도 일치하지 않는 패킷이 모두 버려지게 합니다. 규칙은 -A로 사슬의 끝에 차례로 추가되며 위에서부터 비교해 처음 일치한 규칙의 ACCEPT나 DROP 같은 종결 동작이 적용됩니다(LOG처럼 다음 규칙으로 넘어가는 동작도 있습니다). conntrack의 ESTABLISHED는 양방향 패킷이 확인된 연결의 패킷(서버가 시작한 연결의 응답 포함)을, RELATED는 FTP 데이터 연결이나 ICMP 오류처럼 기존 연결과 연관된 새 패킷을 통과시켜 상태 기반 방화벽이 되게 하는 핵심 규칙입니다. 이 규칙이 없으면 서버가 시작한 연결의 응답도 기본 정책에 막힙니다. 원격으로 접속 중인 서버에서는 SSH 허용 규칙을 먼저 넣고 기본 정책을 DROP으로 바꾸는 일을 마지막에 해야 접속이 끊기지 않으며(위 코드의 순서), 이 명령은 재부팅하면 사라집니다.

nftables — 같은 정책을 규칙 집합으로

table inet filter {
    chain input {
        type filter hook input priority 0; policy drop;

        ct state established,related accept
        iif lo accept
        ip saddr 10.0.0.0/8 tcp dport 22 accept
        tcp dport 443 accept
    }
}

nftables는 iptables를 잇는 리눅스의 패킷 필터링 프레임워크로, 규칙을 table 안의 chain에 계층 구조로 적습니다. policy drop은 기본 거부를, ct state established,related accept는 연결 추적 상태가 확립됨 또는 관련됨인 패킷의 허용을 뜻합니다. 나머지 두 줄은 앞의 iptables 예와 같은 허용 규칙(내부망의 SSH, 모든 곳의 HTTPS)입니다. 다만 iptables 예는 IPv4만 다루고, inet 테이블은 IPv4와 IPv6에 모두 적용되며 ip saddr 규칙은 IPv4 패킷만 일치시킵니다. 규칙은 위에서부터 평가되어 처음 일치한 것이 적용됩니다. 위 코드는 구조를 보이는 최소 예시이며, 실제 적용은 배포판의 nftables 설정 방법을 따라야 합니다.

Python — 규칙 평가기 흉내 내기

import ipaddress

RULES = [
    ("allow", "tcp", "10.0.0.0/8", 22),
    ("allow", "tcp", "0.0.0.0/0", 443),
    ("deny",  "tcp", "0.0.0.0/0", 23),
]

def decide(proto, src_ip, dst_port):
    for action, r_proto, r_src, r_port in RULES:
        if (proto == r_proto and dst_port == r_port
                and ipaddress.ip_address(src_ip) in ipaddress.ip_network(r_src)):
            return action             # 처음 일치한 규칙을 적용
    return "deny"                   # 일치하는 규칙이 없으면 기본 거부

print(decide("tcp", "10.0.0.7", 22))        # allow
print(decide("tcp", "198.51.100.9", 22))   # deny
print(decide("tcp", "198.51.100.9", 443))  # allow
print(decide("udp", "198.51.100.9", 53))   # deny (기본 거부)

이 함수는 시각화의 규칙 매칭 탭과 같은 판단을 합니다. 규칙 목록을 위에서부터 돌며 프로토콜, 출발지 주소 범위, 목적지 포트가 모두 일치하는 첫 규칙의 동작을 돌려주고, 어디에도 일치하지 않으면 기본 거부인 deny를 돌려줍니다. ipaddress.ip_network로 출발지 주소 범위를 표현하고 in 연산자로 어느 범위에 속하는지 확인하는 것은 서브네팅 토픽에서 본 접두사 비교와 같습니다. 실제 방화벽은 연결 상태, 방향, 인터페이스, 로그 같은 조건과 동작을 더 지원하므로 이 코드는 원리만 보이는 최소 예시입니다.

Q1

패킷 필터링 방화벽이 주로 검사하는 정보는?

"이 패킷이 어디서 어디로 가는가"를 봅니다.
패킷 필터링 방화벽은 패킷 헤더의 출발지/목적지 IP, 포트 번호, 프로토콜(TCP/UDP 등)을 규칙과 비교해 허용 또는 차단을 결정합니다.

Q2

상태 기반(Stateful) 방화벽의 특징은?

안에서 시작한 연결의 응답은 다시 들어올 수 있어야 합니다.
상태 기반 방화벽은 연결 상태 테이블을 유지해, 내부에서 허용된 연결에 대한 응답 트래픽을 자동으로 허용합니다. 상태를 보지 않는 필터보다 규칙을 단순하고 안전하게 만들 수 있습니다.

Q3

보안상 권장되는 방화벽의 기본 정책은?

"허용 목록(allowlist)" 방식이 더 안전합니다.
기본 거부 후 필요한 것만 허용하면, 규칙에서 빠뜨린 트래픽이 자동으로 차단되어 안전합니다. 반대로 기본 허용은 차단 규칙을 놓치면 곧바로 보안 구멍이 됩니다.