리눅스 방화벽 설정: iptables 심층 분석 및 활용법
리눅스 환경에서 시스템 보안을 강화하는 데 있어 다양한 방법들이 존재합니다. 그중에서도 iptables
는 강력한 기능을 제공하는 명령줄 기반 방화벽 유틸리티입니다. 유연성과 뛰어난 보호 능력을 자랑하지만, 명령줄 인터페이스라는 특성상 어느 정도의 학습이 필요합니다.
이 글에서는 시스템 관리자뿐 아니라 리눅스를 배우는 초보자도 쉽게 이해할 수 있도록 iptables
의 기본 개념과 함께 실제 적용 가능한 다양한 예시를 제공하고자 합니다.
iptables란 무엇인가?
iptables
는 리눅스 커널에 내장된 소프트웨어 방화벽입니다. 사용자는 iptables
를 통해 네트워크 트래픽을 제어하는 규칙을 정의하고, 이를 통해 시스템의 보안 정책을 구현할 수 있습니다. 구체적으로, 특정 포트, 소스 IP 주소, 네트워크 인터페이스 등을 기준으로 트래픽을 허용하거나 차단하는 규칙을 설정할 수 있습니다.
iptables
는 들어오는 모든 트래픽에 대해 정의된 규칙을 검사합니다. 규칙과 일치하는 트래픽은 해당 규칙에 따라 처리되지만, 일치하는 규칙이 없을 경우 미리 설정된 기본 정책에 따릅니다.
iptables
명령어를 실행하기 위해서는 아래와 같은 형식을 사용합니다:
$ iptables -L -n -v
각 매개변수의 의미는 다음과 같습니다:
-L
: 모든 규칙을 나열합니다.-n
: 숫자 형태의 출력을 제공하여 속도를 향상시킵니다.-v
: 자세한 정보가 포함된 출력을 보여줍니다.
만약 매개변수 없이 iptables
명령어를 실행하면, 아래와 같은 메시지가 나타납니다.
iptables v1.8.7 (nf_tables): no command specified Try `iptables -h' or 'iptables --help' for more information.
만약 “iptables” 명령어를 찾을 수 없다는 오류 메시지가 표시된다면, iptables
를 설치해야 합니다. 대부분의 리눅스 배포판에서는 다음 명령어를 통해 설치할 수 있습니다.
$ sudo apt-get install iptables
이미 설치되어 있는 경우, 다음과 유사한 출력 메시지를 확인할 수 있습니다.
#output Reading package lists... Done Building dependency tree... Done Reading state information... Done iptables is already the newest version (1.8.7-1ubuntu5). iptables set to manually installed. 0 upgraded, 0 newly installed, 0 to remove, and 35 not upgraded.
방화벽의 역할
방화벽은 시스템, 네트워크, 개인 컴퓨터 등을 보호하는 기본적인 보안 수단입니다. 하드웨어 기반 또는 소프트웨어 기반으로 구현될 수 있으며, 사용자 정의 규칙에 따라 작동합니다. 대부분의 방화벽은 사용자가 직접 규칙을 생성하거나 편집할 수 있도록 기능을 제공합니다.
방화벽은 인터넷 패킷이 시스템에 진입할 때 포트를 사용하여 걸러낼 수 있습니다. 이외에도, 소스 IP 주소나 네트워크 인터페이스를 기준으로 특정 서비스를 허용하거나 차단할 수 있습니다. 리눅스 사용자는 기본적으로 iptables
를 이용할 수 있지만, 추가적인 방화벽 소프트웨어를 설치하여 보안을 더욱 강화할 수 있습니다.
iptables를 사용해야 하는 이유
다양한 명령줄 방화벽 유틸리티(예: ufw
, firewalld
)와 독립 실행형 방화벽이 있음에도 불구하고 iptables
를 선택해야 하는 이유는 무엇일까요? iptables
가 제공하는 주요 장점은 다음과 같습니다:
- 패킷 수준에서 규칙 설정이 가능한 뛰어난 유연성 제공
- 작동 원리를 이해하면 비교적 사용하기 쉬움
- 원치 않는 트래픽을 쉽게 차단
- 패킷을 다른 IP 주소로 리디렉션
- 서비스 거부(DoS) 공격으로부터 시스템 보호
iptables 구조 및 Netfilter와의 관계
iptables
를 효과적으로 사용하려면 그 구조를 이해해야 합니다. 먼저 iptables
의 구성 요소를 명확히 파악하고, 각 구성 요소가 어떻게 작동하는지 알아야 합니다. 이 과정은 사용자 정의 규칙을 생성하는 데 매우 중요합니다.
iptables
를 설명할 때 빠지지 않는 개념이 Netfilter
입니다. Netfilter
는 iptables
의 근간이 되는 커널 내 프레임워크이며, 방화벽 기능 구현에 필요한 다양한 기능을 제공합니다. iptables
는 Netfilter
를 제어하는 명령줄 도구입니다.
iptables
는 Netfilter
커널 수준의 후크에 연결되어 네트워크 스택의 가장 깊은 수준에 접근하여 패킷을 제어할 수 있습니다.
테이블 (Tables)
iptables
구조의 시작점은 테이블입니다. 테이블은 규칙을 분류하고, 각 테이블은 특정 유형의 의사 결정을 담당합니다. 테이블을 사용하면 패킷 처리 방식을 단순화할 수 있습니다.
iptables
는 다음과 같은 테이블을 제공합니다:
- 필터 테이블 (filter table): 패킷을 필터링하는 규칙을 포함합니다. 패킷을 허용할지, 차단할지 등을 결정합니다.
- NAT 테이블 (nat table): 네트워크 주소 변환(NAT)을 담당합니다. 패킷의 라우팅을 NAT 네트워크를 기반으로 결정합니다.
- 망글 테이블 (mangle table): 패킷의 헤더 정보를 변경하는 데 사용됩니다. TTL 값과 같은 패킷 정보를 수정할 수 있습니다.
- 로우 테이블 (raw table):
iptables
방화벽의 상태 저장 기능을 우회할 수 있도록 합니다. 상태 추적 전에 패킷을 처리할 수 있게 해줍니다.
체인 (Chains)
각 테이블 내부에는 체인이라는 구조가 있습니다. 체인은 패킷이 네트워크 경로를 따라 이동하면서 거쳐야 하는 여러 지점을 나타냅니다. 각 체인에서 패킷 검사를 수행하여 시스템 프로세스에 전달하기 전에 패킷 처리 여부를 결정합니다.
iptables
에서 제공하는 주요 체인은 다음과 같습니다:
- PREROUTING 체인: 네트워크 인터페이스에 도착한 패킷을 처리합니다.
- INPUT 체인: 시스템으로 들어오는 패킷을 처리합니다.
- OUTPUT 체인: 시스템에서 나가는 패킷을 처리합니다.
- FORWARD 체인: 로컬 시스템을 거쳐 다른 대상으로 전달되는 패킷을 처리합니다.
- POSTROUTING 체인: 네트워크 인터페이스를 통해 나가기 직전의 패킷을 처리합니다.
모든 체인이 모든 테이블에서 사용 가능한 것은 아닙니다. 예를 들어 FORWARD
체인은 망글, 필터, 보안 테이블에서만 사용 가능하고, POSTROUTING
체인은 망글과 NAT(SNAT) 테이블에서만 사용 가능합니다. OUTPUT
체인은 모든 테이블에서 사용 가능합니다.
타겟 (Targets)
패킷이 체인을 통과하면서 각 규칙의 설명과 비교됩니다. 규칙과 일치하면 해당 규칙에 정의된 작업이 수행되고, 타겟으로 이동하여 패킷의 최종 운명이 결정됩니다. 대부분의 경우 패킷은 어떤 규칙에도 부합하지 않으며, 이때 기본 정책(타겟)이 적용됩니다.
주요 타겟은 다음과 같습니다:
- ACCEPT: 패킷을 허용합니다.
- DROP: 패킷을 삭제하며, 발신자에게 어떠한 정보도 제공하지 않습니다.
- REJECT: 패킷을 거부하며, 발신자에게 거부 메시지를 보냅니다.
이외에도 패킷에 대한 정보를 저장하는 데 사용되는 종료되지 않는 타겟도 존재합니다.
일반적인 iptables 명령어 및 예시
iptables
명령어를 실행하기 전에 다음 사항을 확인해야 합니다:
- 명령어를 실행할 수 있는 관리자 권한을 가지고 있어야 합니다.
- 이 문서는 Ubuntu에서
iptables
를 설정하는 방법에 대한 튜토리얼이 아닙니다. - 여기서는 IPv4를 기반으로 작동하는
iptables
명령어를 사용합니다. IPv6 환경에서는ip6tables
를 사용해야 합니다.
iptables 상태 확인
현재 iptables
의 상태를 확인하려면 다음 명령어를 실행합니다.
$ iptables -L -n -v
#output Chain INPUT (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination Chain FORWARD (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination
위 출력에서 확인할 수 있듯이, 모든 체인이 ACCEPT
로 설정되어 있고, 규칙이 존재하지 않는다는 것은 방화벽이 비활성 상태임을 의미합니다. 방화벽을 활성화하려면 규칙을 추가해야 합니다.
체인에 규칙 추가
규칙을 추가할 때는 항상 체인에 추가해야 합니다. -A
(추가) 옵션을 사용하여 규칙을 추가할 수 있습니다. 기본 구문은 다음과 같습니다.
$ sudo iptables -A
하지만 위 명령어를 실행하면 다음과 같은 오류 메시지가 나타납니다.
iptables v1.8.7 (nf_tables): option "-A" requires an argument Try `iptables -h' or 'iptables --help' for more information.
규칙을 추가할 때 사용할 수 있는 주요 인수는 다음과 같습니다:
-i
: 인터페이스를 지정합니다. 규칙을 적용할 네트워크 인터페이스(예: ppp0, eth0)를 설정할 수 있습니다.-p
: 프로토콜을 지정합니다. 패킷을 필터링할 네트워크 프로토콜(예: ICMP, TCP, UDP)을 설정합니다.all
을 값으로 사용하면 모든 프로토콜에 규칙이 적용됩니다.-s
: 소스 IP 주소 또는 호스트 이름을 지정합니다.--dport
: 대상 포트를 지정합니다. 패킷의 목적지 포트 번호를 설정합니다.-j
: 타겟을 지정합니다.ACCEPT
,DROP
,RETURN
등의 타겟을 설정합니다.
규칙을 추가하는 명령어는 다음과 같은 순서로 작성해야 합니다.
$ sudo iptables -A <chain-name> -i <interface-name> - p <protocool-name> - s <source> --dport <port no.> -j <target>
iptables 변경 사항 저장
추가한 규칙은 iptables -save
명령어를 사용하여 저장할 수 있습니다.
$ sudo iptables -save
출력 예시는 다음과 같습니다.
[email protected]:~$ sudo iptables-save # Generated by iptables-save v1.8.7 on Sun May 14 13:37:34 2023 *filter :INPUT ACCEPT [0:0] :FORWARD ACCEPT [0:0] :OUTPUT ACCEPT [0:0] -A INPUT -p tcp -m tcp --dport 22 -j ACCEPT -A INPUT -p tcp -m tcp --dport 80 -j ACCEPT -A INPUT -p tcp -m tcp --dport 443 -j ACCEPT -A INPUT -p tcp -m tcp --dport 392 -j REJECT --reject-with icmp-port-unreachable -A OUTPUT -o lo -j ACCEPT COMMIT # Completed on Sun May 14 13:37:34 2023
수동으로 규칙 유지
기본적으로 iptables
는 규칙을 저장하지 않으므로, 시스템을 재시작하면 모든 규칙이 사라집니다. 규칙을 유지하려면 다음 명령어를 사용해야 합니다.
IPv4 규칙의 경우:
$ sudo iptables-save > /etc/iptables/rules.v4
IPv6 규칙의 경우:
$ sudo iptables-save > /etc/iptables/rules.v6
자동으로 규칙 유지
시스템 재시작 후에도 규칙을 자동으로 유지하려면 iptables-persistent
패키지를 설치해야 합니다.
$ sudo apt-get install iptables-persistent
설치 과정에서 아래와 같은 창이 나타나면 ‘예’를 선택하고 Enter 키를 누릅니다.
IPv4 테이블로 작업 중이므로 IPv4 규칙만 표시됩니다. IPv6로 작업 중이라면 관련 창이 표시됩니다.
주의: 이 패키지는 저장된 iptables
규칙만 로드합니다. 따라서 iptables
를 변경할 때마다 iptables -save
명령어를 사용하여 저장해야 합니다.
재시작 후 규칙 다시 로드
규칙이 저장되면 다음 명령어를 사용하여 복원할 수 있습니다.
$ sudo iptables-restore < /etc/iptables/rules.v4
IPv6 규칙의 경우:
$ sudo iptables-restore < /etc/iptables/rules.v6
Localhost에서 트래픽 활성화 (루프백 활성화)
Localhost에서 트래픽을 활성화하려면 다음 명령어를 사용합니다.
$ sudo iptables -A INPUT -i lo -j ACCEPT
여기서 lo
는 모든 localhost 통신을 위한 루프백 인터페이스를 나타냅니다.
마찬가지로 패킷이 루프백 인터페이스를 통해 나가도록 허용할 수 있습니다.
$ sudo iptables -A OUTPUT -o lo -j ACCEPT
규칙이 어떻게 변경되었는지 확인하려면 iptables -L -n -V
명령어를 실행합니다.
#output Chain INPUT (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination 0 0 ACCEPT all -- lo * 0.0.0.0/0 0.0.0.0/0 Chain FORWARD (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination
특정 포트에서 트래픽 활성화
특정 포트의 트래픽을 ACCEPT
하거나 REJECT
할 수 있습니다. SSL, HTTP, SSH 포트 등은 정상적인 앱 작동에 중요하므로 포트 번호를 통해 ACCEPT
패킷에 규칙을 추가할 수 있습니다.
SSL 포트 (22)를 허용하려면 다음 명령어를 실행합니다:
$ sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT
HTTP 포트 (80)를 허용하려면:
$ sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT
eth0 인터페이스에서 모든 HTTP 트래픽을 허용하려면:
$ iptables -A INPUT -i eth0 -p tcp --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT $ iptables -A OUTPUT -o eth0 -p tcp --sport 80 -m state --state ESTABLISHED -j ACCEPT
SSH 포트 (22)를 허용하려면:
$ sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT
eth0 인터페이스에서 모든 SSH 트래픽을 허용하려면:
$ iptables -A INPUT -i eth0 -p tcp --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT $ iptables -A OUTPUT -o eth0 -p tcp --sport 22 -m state --state ESTABLISHED -j ACCEPT
사용자 정의 앱의 특정 포트에서 트래픽을 활성화할 수도 있습니다. 예를 들어 포트 233에서 연결을 열려면 다음과 같이 명령어를 실행합니다.
$ sudo iptables -A INPUT -p tcp --dport 233 -j ACCEPT
마찬가지로 REJECT
타겟 옵션을 사용하여 특정 포트에서 연결을 비활성화할 수 있습니다.
포트 392에서 모든 연결을 차단하려면 다음 명령어를 사용합니다.
$ sudo iptables -A INPUT -p tcp --dport 392 -j REJECT
확인을 위해 iptables -L -n -v
명령어를 실행합니다.
#output Chain INPUT (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:80 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:443 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:233 0 0 REJECT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:392 reject-with icmp-port-unreachable Chain FORWARD (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination 0 0 ACCEPT all -- * lo 0.0.0.0/0 0.0.0.0/0
기존 규칙 삭제
기존 규칙을 삭제하려면 다음 명령어를 실행합니다.
$ iptables -F
또는
$ iptables --flush
주의: 규칙을 저장하지 않으면 영구적으로 손실되며, iptables -restore
명령어를 사용해도 복원할 수 없습니다.
줄 번호가 있는 규칙 삭제
특정 규칙을 삭제하려면 줄 번호와 함께 규칙 목록을 가져와야 합니다.
$ sudo iptables -L --line-numbers
#output Chain INPUT (policy ACCEPT) num target prot opt source destination 1 ACCEPT tcp -- anywhere anywhere tcp dpt:ssh 2 ACCEPT tcp -- anywhere anywhere tcp dpt:http 3 ACCEPT tcp -- anywhere anywhere tcp dpt:https 4 ACCEPT tcp -- anywhere anywhere tcp dpt:233 5 REJECT tcp -- anywhere anywhere tcp dpt:392 reject-with icmp-port-unreachable
INPUT
체인에서 규칙 번호 4를 제거하려면 다음 명령어를 실행합니다.
$ sudo iptables -D INPUT 4
iptables -n -v -L
명령어를 다시 실행하여 결과를 확인할 수 있습니다.
#output Chain INPUT (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:80 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:443 0 0 REJECT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:392 reject-with icmp-port-unreachable
INPUT 또는 OUTPUT 체인 규칙만 표시
INPUT
체인의 규칙만 표시하려면 다음 명령어를 실행합니다.
$ sudo iptables -L INPUT -n -v --line-numbers
#ouput Chain INPUT (policy ACCEPT 0 packets, 0 bytes) num pkts bytes target prot opt in out source destination 1 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 2 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:80 3 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:443 4 0 0 REJECT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:392 reject-with icmp-port-unreachable
OUTPUT
체인의 규칙만 보려면 다음 명령어를 실행합니다.
$ sudo iptables -L OUTPUT -n -v --line-numbers
#output Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes) num pkts bytes target prot opt in out source destination 1 0 0 ACCEPT all -- * lo 0.0.0.0/0 0.0.0.0/0
방화벽 시작/중지/다시 시작
RHEL/Fedora Linux 또는 CentOS를 사용 중인 경우 service
명령어를 사용하여 방화벽을 제어할 수 있습니다.
$ service iptables stop $ service iptables start $ service iptables restart
systemctl
명령어를 사용할 수도 있습니다.
하지만 우분투에서는 위 명령어들이 작동하지 않습니다.
특정 위치에 규칙 삽입
특정 위치에 규칙을 삽입하려면 다음 명령어를 사용해야 합니다. 먼저 현재 규칙을 확인합니다.
$ sudo iptables -L INPUT -n --line-numbers
#output Chain INPUT (policy ACCEPT) num target prot opt source destination 1 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 2 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:80 3 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:443 4