UFW는 iptables를 감싸는 편의 도구입니다. 더 세밀한 제어가 필요하거나 스크립트로 방화벽을 관리할 때는 iptables를 직접 다루는 것이 효과적입니다.

iptables 체인 구조

인터넷 → [PREROUTING] → 라우팅 결정
                          ↓              ↓
                       [INPUT]      [FORWARD]
                          ↓
                        서버 프로세스
                          ↓
                       [OUTPUT] → [POSTROUTING] → 인터넷
  • INPUT: 서버로 들어오는 패킷
  • OUTPUT: 서버에서 나가는 패킷
  • FORWARD: 서버를 경유하는 패킷

현재 규칙 확인

# 규칙 목록 (줄 번호 포함)
sudo iptables -L -n -v --line-numbers

# NAT 테이블 확인
sudo iptables -t nat -L -n -v

기본 정책 설정

# 기본 정책: 입력은 차단, 출력은 허용
sudo iptables -P INPUT DROP
sudo iptables -P FORWARD DROP
sudo iptables -P OUTPUT ACCEPT

주의: 기본 정책을 DROP으로 바꾸기 전에 반드시 SSH 포트를 허용 규칙으로 추가하세요. 순서가 바뀌면 서버에 접속할 수 없게 됩니다.

필수 허용 규칙

# 루프백 인터페이스 허용
sudo iptables -A INPUT -i lo -j ACCEPT

# 기존 연결의 응답 패킷 허용 (ESTABLISHED, RELATED)
sudo iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

# SSH 허용 (포트를 변경했다면 22 대신 변경한 포트 번호 입력)
sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT

# HTTP, HTTPS 허용
sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT

특정 IP 또는 대역 허용/차단

# 특정 IP만 허용
sudo iptables -A INPUT -s 203.0.113.10 -j ACCEPT

# IP 대역 허용 (CIDR 표기)
sudo iptables -A INPUT -s 203.0.113.0/24 -j ACCEPT

# 특정 IP 차단
sudo iptables -A INPUT -s 192.0.2.100 -j DROP

# 특정 IP에서 오는 SSH만 허용 (더 엄격한 제어)
sudo iptables -A INPUT -s 203.0.113.10 -p tcp --dport 22 -j ACCEPT

포트 범위 및 다중 포트

# 포트 범위 허용 (예: 8000~9000)
sudo iptables -A INPUT -p tcp --dport 8000:9000 -j ACCEPT

# 여러 포트를 한 번에 (multiport 모듈)
sudo iptables -A INPUT -p tcp -m multiport --dports 80,443,8080 -j ACCEPT

연결 수 제한 (브루트포스 방어)

# SSH 포트 연결 속도 제한 (1분에 4회 초과 시 차단)
sudo iptables -A INPUT -p tcp --dport 22 -m state --state NEW \
    -m recent --set --name SSH

sudo iptables -A INPUT -p tcp --dport 22 -m state --state NEW \
    -m recent --update --seconds 60 --hitcount 4 --name SSH -j DROP

ICMP (ping) 제어

# ping 차단
sudo iptables -A INPUT -p icmp -j DROP

# ping 속도 제한 허용 (DDoS 방어)
sudo iptables -A INPUT -p icmp --icmp-type echo-request \
    -m limit --limit 1/s --limit-burst 5 -j ACCEPT

규칙 삭제

# 줄 번호로 삭제
sudo iptables -D INPUT 3

# 규칙 내용으로 삭제 (-A 대신 -D)
sudo iptables -D INPUT -p tcp --dport 8080 -j ACCEPT

# 모든 규칙 초기화
sudo iptables -F INPUT

규칙 영구 저장

재부팅하면 iptables 규칙이 초기화됩니다. 영구 적용하려면:

# Debian/Ubuntu
sudo apt install iptables-persistent
sudo netfilter-persistent save

# 또는 수동 저장
sudo iptables-save > /etc/iptables/rules.v4
sudo ip6tables-save > /etc/iptables/rules.v6

# 부팅 시 자동 로드 확인
sudo systemctl enable netfilter-persistent

로깅 설정

# 차단된 패킷 로그 기록
sudo iptables -A INPUT -j LOG --log-prefix "IPT DROP: " --log-level 4
sudo iptables -A INPUT -j DROP

# 로그 확인
sudo tail -f /var/log/kern.log | grep "IPT DROP"

완성된 방화벽 스크립트 예시

#!/bin/bash
# /etc/iptables/setup.sh

# 기존 규칙 초기화
iptables -F
iptables -X

# 기본 정책
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT

# 루프백
iptables -A INPUT -i lo -j ACCEPT

# 기존 연결 허용
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

# SSH (포트 22, 필요시 변경)
iptables -A INPUT -p tcp --dport 22 -j ACCEPT

# 웹 서버
iptables -A INPUT -p tcp -m multiport --dports 80,443 -j ACCEPT

# 저장
iptables-save > /etc/iptables/rules.v4

iptables를 이해하면 방화벽 동작을 정확히 제어할 수 있습니다. 복잡한 환경에서는 fail2ban과 함께 사용하면 더욱 효과적입니다.