Search

Netfilter & iptables

Tags
unix
netfilter
iptables
network
system
Created
2024/09/27 18:09
Created time
2024/09/27 09:09
category
unix

개요

Netfilter라는 커널 내부 프레임워크와 iptables 사용자 도구에 대해 탐색

사전 지식

커널 영역과 사용자 영역는 각 권한에 따라 메모리 영역이 분리
커널 영역은 운영 체제 실행을 위한 공간 (Netfilter)
사용자 영역은 애플리케이션 실행을 위한 공간 (iptables)

Netfilter

Netfilter는 리눅스 커널 내부에서 네트워크 관련 연산을 처리하는 엔진이자 프레임워크로 커널 영역에 위치
Netfilter는 시스템에서 처리하는 패킷들을 제어하기 위한 가장 강력한 제어 수단

Hook Type

연산들을 애플리케이션에서 핸들러 형태로 구현할 수 있도록 아래의 훅을 제공
- NF_IP_PRE_ROUTING: - 패킷이 네트워크 인터페이스에 도달하자마자 동작 - ip_rcv & ipv6_rcv() - NF_IP_LOCAL_IN: - 로컬 호스트로 라우팅 되어 도달하기 직전에 동작 - ip_local_deliver & ip6_input - NF_IP_FORWARD: - 네트워크 인터페이스에 도착하여 로컬 호스트를 거쳐가는 경우 동작 (Router & Gateway) - ip_forward & ip6_forward - NF_IP_LOCAL_OUT: - 로컬 호스트에서 생성된 패킷이 다른 호스트로 라우팅 되어 나가기 직전에 동작 - __ip_local_out & __ip6_local_out - NF_IP_POST_ROUTING: - 패킷이 네트워크 인터페이스에서 나갈 때 동작 - ip_output & ip6_finish_output2
YAML
복사

Callback Struct

제공되는 훅의 콜백을 등록할 때는 nf_hook_ops라는 구조체를 이용
struct nf_hook_ops { /* User fills in from here down. */ nf_hookfn *hook; struct net_device *dev; void *priv; u_int8_t pf; unsigned int hooknum; /* Hooks are ordered in ascending priority. */ int priority; };
C
복사
위 구조체 내부에 nf_hookfn이라는 함수 포인터가 콜백을 지칭하고, 아래와 같은 원형을 가짐
typedef unsigned int nf_hookfn(void *priv, struct sk_buff *skb, const struct nf_hook_state *state);
C
복사

Register / Unregister

콜백을 담은 구조체를 이용하여 훅에 등록 및 해제를 위해선 아래 함수들을 활용
// 하나의 Netfilter 훅을 ops 객체로 등록 int nf_register_hook(struct nf_hook_ops *reg); // 등록한 하나의 Netfilter 훅을 해제 void nf_unregister_hook(struct nf_hook_ops *reg); // 여러 개의 Netfilter 훅을 ops 객체 배열로 등록 int nf_register_hooks(struct nf_hook_ops *reg, unsigned int n); // 등록한 여러 개의 Netfilter 훅을 해제 void nf_unregister_hooks(struct nf_hook_ops *reg, unsigned int n);
C
복사

Call Hook

Netfilter 훅을 호출할 때는 NF_HOOK이라는 매크로를 이용
static inline int NF_HOOK(uint8_t pf, unsigned int hook, struct net *net, struct sock *sk, struct sk_buff *skb, struct net_device *in, struct net_device *out, int (*okfn)(struct net *, struct sock *, struct sk_buff *)) { int ret = nf_hook(pf, hook, net, sk, skb, in, out, okfn); if (ret == 1) ret = okfn(net, sk, skb); return ret; }
C
복사
NF_HOOK 매크로 내부에는 nf_hook 인라인 함수를 호출하는데, 이 때 인자로 받은 okfn이 훅 종료 후 호출할 콜백 함수로써 반드시 호출될 수 있어야 함
static inline int nf_hook(u_int8_t pf, unsigned int hook, struct net *net, struct sock *sk, struct sk_buff *skb, struct net_device *indev, struct net_device *outdev, int (*okfn)(struct net *, struct sock *, struct sk_buff *));
C
복사

iptables

iptables는 Netfilter로 구현된 사용자 영역의 애플리케이션
리눅스 커널 방화벽이 제공하는 체인, 테이블, 규칙들을 구성하고 조회할 수 있도록 기능을 제공
비슷한 프로그램으로 ip6tables (ipv6), arptables (arp), ebtables (ethernet), nftables, ipvs 등이 존재
용어 자체는 프로그램을 지칭하기도 하지만, ipv4, ipv6, arp, ethernet 구조 전반에 사용되는 xtables를 지칭하는데도 사용
/sbin/iptables로 위치하기도 하지만, 필수적인 이진 파일보다는 서비스에 더 가깝기 때문에 /usr/sbin/iptables에 주로 위치

Chains

Netfilter의 5개 훅과 밀접하게 관련되며, 패킷 제어를 위한 규칙을 적용할 단계를 지칭
- PREROUTING: - NF_IP_PRE_ROUTING 훅에 의해 트리거 되는 규칙들을 적용할 단계 - INPUT: - NF_IP_LOCAL_IN 훅에 의해 트리거 되는 규칙들을 적용할 단계 - FORWARD: - NF_IP_FORWARD 훅에 의해 트리거되는 규칙들을 적용할 단계 - OUTPUT: - NF_IP_LOCAL_OUT 훅에 의해 트리거되는 규칙들을 적용할 단계 - POSTROUTING: - NF_IP_POST_ROUTING 훅에 의해 트리거되는 규칙들을 적용할 단계
YAML
복사
Netfilter의 훅에 등록되지 않는 특수 목적의 체인을 사용자가 정의 가능 (User Defined Chains)
사용자가 직접 정의한 체인은 JUMP 액션에 의해서만 도달 가능

Tables

리눅스 커널에서 제공하는 테이블들은 5개로, iptables 명령어 상 -t 옵션으로 지정
- Filter: - 필터링을 위한 방화벽 역할의 테이블로 패킷의 Inbound / Outbound를 제어 - NAT: - 테이블에 존재하는 규칙에 따라 Source (sNAT) / Destination (dNAT)의 주소를 조작하는데 사용 - Mangle: - 패킷의 헤더를 조작할 떄 이용하는 테이블로, 대표적으로 TTL 등 패킷을 제어하는데 이용 - Raw: - iptables는 커넥션 추적 기능을 제공하는데, 모든 커넥션에 대한 상태를 마킹하고 상태에 따라 커넥션들을 제어할 수 있도록 도움 - Security: - 패킷에 Security Context를 마킹하는데 사용되는 테이블로 SELinux에서 패킷을 제어할 수 있도록 도움
YAML
복사
커넥션 추적을 위한 Raw에서 사용되는 상태
NEW: 기존 커넥션과 연관되지 않은 최초의 패킷을 받은 것으로 간주되는 새로운 커넥션에 붙는 레이블
ESTABLISHED: NEW에서 전환된 상태이며, NEW를 받은 방향과 반대 방향으로 응답을 정상적으로 받은 경우에 붙는 레이블 (TCP의 경우 SYN/ACK를 의미하고, UDP, ICMP의 경우 원래 주고 받은 패킷의 source 및 destination이 바뀐 것을 의미)
RELATED: 기존 커넥션에 속한 패킷은 아니지만 시스템에 있는 기존 커넥션과 관련이 있는 경우 붙는 레이블로 Helper 커넥션에서 주로 이용 (데이터 전송을 위한 FTP 커넥션, ICMP 외의 다른 프로토콜에서 사용된 커넥션에서 ICMP 응답을 하는 경우에 해당)
INVALID: 기존 커넥션과 연관이 없으면서 NEW로 커넥션을 열수도 없는 상태인 경우에 붙는 레이블로 식별이 안 되거나 라우팅이 안 되는 등의 상황에서 발생
UNTRACKED: 단순히 트래픽을 흘려보내기 위해 Raw 테이블에 마킹된 커넥션에 붙는 레이블
SNAT: 일종의 가상 상태이며, source의 주소를 바꿨을 때 붙는 레이블로 응답 패킷이 도착했을 때 source의 원래 주소로 교체
DNAT: 일종의 가상 상태이며, destination의 주소를 바꿨을 때 붙는 레이블로 응답 패킷이 도착했을 때 destination의 원래 주소로 교체

Compatibility

체인과 테이블은 주어진 도표 내용처럼 호환성을 가짐
체인은 정해진 순서에 따라 순회하게 되는데, 위 도표 기준으로 왼쪽에서 오른쪽 방향의 순서를 가짐
순회 순서
PREROUTING → INPUT → FORWARD → OUTPUT → POSTROUTING
제시된 도표에서 체인이 지원하는 테이블은 위에서 아래쪽의 순서로 규칙을 평가하여 액션을 수행
평가 순서
PREROUTING : raw → mangle → dNAT
INPUT: mangle → filter → security → sNAT
FORWARD: mangle → filter → security
OUTPUT: raw → mangle → dNAT → filter → security
POSTROUTING: mangle → sNAT

Rules

규칙은 체인에 따라 거쳐가는 테이블들에 적용된 조건들을 지칭
일치 여부를 판정 짓는 것을 평가된다고 표현하는데, 일치 여부에 사용되는 기준들은 아래와 같음
- protocol - source & destination addr - source & destination port - network interface - header - connection state ...
YAML
복사
기준을 만족한 규칙들은 매칭되었다고 표현하며, 매칭된 규칙들은 액션을 수행

Actions (Targets)

액션 혹은 타겟이라고 지칭하는데, 패킷이 규칙을 만족했을 경우 수행될 행동을 지칭
액션은 Terminating / Non-terminating으로 구분
Terminating은 NF_HOOK에 제어를 즉시 반환하는 방식이고, Non-terminating은 액션 수행 후 평가를 이어가고 체인이 종료 여부를 결정하여 제어를 반환하는 방식
대표적으로 아래와 같은 액션이 존재
- ACCEPT: - 패킷이 지나갈 수 있도록 허용 - DROP: - 패킷이 지나갈 수 없도록 버리며, source가 destination 존재 여부를 알 수 없게 조용히 처리 - REJECT: - 패킷이 지나갈 수 없도록 버리며, DROP과 달리 source에 응답 - RETURN: - 현재 진행 중인 체인에 대한 순회를 종료하고, 다음 규칙을 이전 체인부터 순회 - JUMP: - Non-terminating 액션이며 진행 중인 평가를 다른 체인으로 이동
YAML
복사

예시

1.
source addr이 192.168.0.111 인 모든 port 접속 차단
iptables -A INPUT -s 192.168.0.111 -j DROP
Shell
복사
2.
destination port 3838 이고 tcp 프로토콜인 패킷 거부
iptables -A INPUT -p tcp --dport 3838 -j DROP
Shell
복사
3.
localhost 접속 허가
iptables -A INPUT -i lo -j ACCEPT
Shell
복사
4.
모든 IP addr로부터 들어오는 패킷 허가
iptables --policy INPUT ACCEPT
Shell
복사
5.
ESTABLISH와 RELATED 상태 접속 허가
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
Shell
복사
6.
Null 패킷 거부
iptables -A INPUT -p tcp --tcp-flags ALL NONE -j DROP
Shell
복사
7.
11.11.11.0/24 대역으로 가는 패킷은 FORWARD 허가
iptables -A FORWARD -d 11.11.11.0/24 -j ACCEPT
Shell
복사
8.
br0 interface에 대하여 in/out FORWARD 허가
iptables -A FORWARD -i br0 -j ACCEPT iptables -A FORWARD -o br0 -j ACCEPT
Shell
복사

Reference