레이블이 iptables인 게시물을 표시합니다. 모든 게시물 표시
레이블이 iptables인 게시물을 표시합니다. 모든 게시물 표시

iptables 와 netfilter 이해


!!! Caution 잘못된 번역이나 이해로 틀릴 수 있음!!! ^^;;

[iptables, netfilter 은 뭘까?]

netfilter 는 네트워킹의 모든 패킷들에 의해 트리거되는 패킷 필터링 hook 이다.
iptables 는 커널의 netfilter(패킷 필터 프레임워크) 인터페이스를 사용해 방화벽 규칙을 구성한다.


[netfilter Hooks]

프로그램에 등록할 수 있는 netfilter hook 에는 아래 5개가 있다.
네트워크 스택을 통과할때 아래 5개의 hook 들을 등록한 커널 모듈에 의해서 트리거 된다.
incoming/outgoing 패킷에 따라 트리거 되거나 되지 않는다.
그리고 이전 지점에선 dropped 되거나 rejected 된다.

NF_IP_PRE_ROUTING: 이 hook 은 네트워크 스택에서 들어오고 나서 바로 incoming 트래픽에 의해 트리거된다. 라우팅 결정되기전에 처리된다.
NF_IP_LOCAL_IN: 이 hook 은 incoming 패킷이 라우팅된 후, 라우팅 목적지가 로컬 시스템인 경우 트리거 된다.
NF_IP_FORWARD: 이 hook 은 incomming 패킷이 라우팅된 후, 라우팅 목적지가 로컬이 아닌 다른 호스트인 경우 트리거 된다.
NF_IP_LOCAL_OUT: 이 hook 은 로컬에서 생성된 outbound(외부로 나가는) 트래픽이 네트워크 스택을 만나면 트리거 된다.
NF_IP_POST_ROUTING: 이 hook 은 outgoing,fowrard 트래픽이 네티워트에 위치하기 직전에 트리거 된다.

커널 모듈은 이 hook 들이 트리거 됐을때 우선순위를 결정하기 위해 priority number 를 제공해야 한다.
이는 멀티 모듈(또는 모듈 하나의 멀티 인스턴스)에서도 각각의 hook 의 우선순위 결정을 의미한다.
각 모듈은 순서대로 호출되고 패킷 어떻게 처리되어야 하는지 나타낸 결정이 netfilter 에 리턴된다.


netfilter hook 그림을 보는게 이해하기에 좋다.



[iptables 테이블과 체인]
iptables 방화벽은 rule(규칙)을 구성하기 위해 테이블을 사용한다.
이 테이블은 만들고자 하는 형태에 따라 구분된다.
예를 들어 network address translation 관련한것이라면, nat 테이블에 놓여진다.
만약 패킷이 목적지까지 허용할지 말지를 결정하기 위해서는 filter 테이블에도 추가된다.

iptables 테이블 내에서 규칙은 chain(체인) 으로 나뉘어져 조직화된다.
테이블들이 일반적인 규칙의 목적에 따라 정의 되는 반면, built-in(빌트인) 체인은 규칙들을 트리거하는 netfilter hook 을 나타낸다.
기본적으로 체인은 언제 evalute(평가)될지 결정한다.

아래는 빌트인 체인 이름으로 netfilter hook 과 연관된 이름을 반영한다.

PREROUTING : NF_IP_PRE_ROUTING hook 에 의해 트리거
INPUT : NF_IP_LOCAL_IN hook 에 의해 트리거
FORWARD : NF_IP_FORWARD hook 에 의해 트리거
OUTPUT : NF_IP_LOCAL_OUT hook 에 의해 트리거
POSTROUTING : NF_IP_POST_ROUTING hook 에 의해 트리거

체인들은 관리자가 패킷의 delivery path 에 규칙이 어디로 평가되어질지를 컨트롤할 수 있도록 허용한다.
때문에 각 멀티 체인을 갖는 테이블은 처리중 여러 지점에서 영향을 받을 수 있다.
왜냐하면 결정의 특정 타입은 오직 네티워크 스택의 특정 지점에서 의미가 있기 때문에 모든 테이블은 각 커널 hook 에 등록된 체인을 갖지 못 할 수 있다.

5개의 netfilter kernel hook 있고 멀티 테이블을 가진 체인들은 각각 hook 에 등록된다.
예를 들어 3개의 테이블이 PREROUTING 을 가지고 있고, 이 체인들이 NF_IP_PRE_ROUTING hook 으로 등록되어 있으면� 이 체인들은 각 테이블의 PREROUTING 체인이 호출될 때의 우선순위를 명시한다.
우선 순위가 가장 높은 PREROUTING 체인내의 각 규칙 들은 다음 PREROUTING 체인으로 이동하기 전에 순차적으로 평가된다.
잠시 각 체인들의 구체적인 순서를 살펴보자.


[사용 가능한 테이블과 각 테이블에서 구현된 체인]

각 chain 에 맞는 다음과 같은 성격의 규칙 테이블이 있다.
THE FILTER TABLE: iptables 에서 가장 많이 사용되는 테이블로, 패킷을 목적지로 보내는것을 허용할지 여부를 판단한다.
방화벽 용어로 'filtering' 패킷 으로 알려져 있다.패킷 필터링에 사용하는 테이블, INTPUT,FORWARD,OUTPUT chain 에서 사용
THE NAT TABLE: 출발지, 목적지 변경시 사용하는 테이블, PREROUTING,POSTROUTING chain 에서 사용
THE MANGLE TABLE: 패킷 변조시 사용하는 테이블�, 5개 chain 모두에서 사용
THE RAW TABLE: 주로 netfilter 에서 추적하지 않도록 NOTRACK 설정하는데 사용하는 테이블, PREROUTING,OUTPUT chain 에서 사용
THE SECURITY TABLE: SELinux 보안 사용시 사용하는 테이블, INPUT,FORWARD,OUTPUT chain 에서 사용


[체인 순회 순서]

방화벽이 전송을 허용한다면 다음 흐름은 각각에 상황에서 traverse(순회�) path 를 나타낸다.

incoming 패킷이 목적기자 로컬인 경우: PREROUTING -> INPUT
incoming 패킷이 목적지가 다른 호스트인 경우: PREROUTING -> FORWARD -> POSTROUTING
로컬에서 생성된 패킷: OUTPUT -> POSTROUTING


[iptables 규칙]

규칙은 특정 테이블안애 특정 체인에 놓인다.
각 체인은 호출될때 패킷은 체인 순서대로 각 규칙에 대해 체크한다.
각 규칙은 matching 와 action 구성 요소를 가진다.

matching(매칭)
매칭은 패킷이 액션(또는 target)과 순서대로 만나야 하는 기준을 명시한다.
매칭 시스템은 매우 유연하고 시스템의 사용가능한 iptables 로 확장될 수 있다.
규칙들은 프로토콜타입,출발/목적지 주소/포트,input/output 인터페이스, 헤더, 연결 상태등의 기준으로 구성된다.
다른 트래픽들과 구분하기 위해 규칙 집합(rule sets)으로 결합될 수 있도 있다

targets
타겟은 패킷인 규칙의 매칭을 만났을때 트리거 되는 액션이다.
타겟은 다음 2개의 카테고리로 나뉜다.
- terminating targets: 체인내 평가를 끝내고 netfilter 제어권을 리턴한다. 리턴된 값에 따라 drop 또는 allow 후 다튼 단계로 처리를 이어간다.
- non-terminating targets: 체이내 평가가를 계속 수행한다.

[사용자 정의 체인으로 점프]

non-terminating target 중 jmp target은 추가 처리를 위해 다른 체인으로 이동하는 액션이다.
규칙들은 빌트인 체인이 놓여지는 방식 처럼 사용자 정의 체인에 놓여질 수 있다.
사용자 정의 체인은 빌트인 체인과는 다르게 규칙으로 부터 jumping 으로만 접근할 수 있다.
(사용자 정의 체인은 netfilter hook 에 등록되어 있지 않다.)

사용자 정의 체인들은 이를 호출하는 체인의 단순한 확장 방식으로 동작한다.
예를 들어 사용자 정의 체인에서 규칙 리스트의 끝에 도달하거나 리턴 대상이 매칭 규칙에 의해 활성화되면 평가는 체인을 호출해 통과한다.
평가는 추가적인 사용자 정의 체인들로 점프할 할 수 있다.


[iptables 과 connection tracking(추적)]

connection tracking 은 iptables 이 ongoing connection 의 context 에 보여진는 패킷들 대해서 결정하도록 허용한다.
connection tracking system 은 stateful 한 오퍼레이션을 수행하는데 필요한 기능을 제공한다.

connection tracking 은 패킷이 네트워크 스택에 들어온 후 바로 적용된다.
raw table 체인과 기본적인 체크들은 패킷과 하나의 connection 을 연결하기 전에 패킷에 수행되는 유일한 로직이다.

시스템은 각 패킷들을 존재하는 connection 들 집합과 체크한다.
만약 새로운 connections 이 필요하다면 connection의 상태를 업데이트한다.
raw 체인의 NOTRACK 으로 마크된 패킷들은 connection tracking 라우팅으로 바이패스된다.

시스템은 각각의 패킷들을 현재 존재하는 connection들의 집합과 체크하고, 그것은 connection의 state를 업데이트 한다. 필요할 때 시스템에 새로운 connection을 추가한다. 패킷들은 하나의 raw 체인에서  NOTRACK tarket으로 표시된다. 그리고 connection tracking 경로를 bypass 한다.

Available States
connections tracking 시스템에 의해 connection tracked 는 다음 상태중 하나가 된다.

NEW: 존재하는 connection 연결되지 않는 패킷이 도착할때, 유효하지 않는 첫번째 패킷일때, 새로운 connection 은 NEW label이 추가된다. TCP(커넥션인지),UDP(비연결적인) 프로토콜 모두에서 발생한다.

ESTABLISHED: 유효한 응답을 받았을때 NET->ESTABLISHED 로 변한다. TCP 에서는 SYN/ACK, UDP와ICMP 에서는 트랙픽으로 원래 패킷의 출발지와 목적지가 바뀌는 응답을 의미한다.

RELATED: 패킷이 존재하는 connection 의 일부가 아니지만 시스팀에서 이미 connection 에 연결되어 있따면 RELATED label 이 된다. 이 상태는 helper connection 으로 FTP 데이터 전송 connection 이나 ICMP 응답 connections 시도하는 케이스 이다.

INVALID: 존재하는 connection 과 연결되지 않고 새 connection 을 open 하기에도 적절하지 않은 경우, indentified 될 수도 없고 다른 이유로 라우팅 되지 않는 경우, INVALID 로 마크된다.

UNTRACKED: raw table chain 에 트래킹(추적)을 바이패스하는 타겟으로 된경우 UNTRACKED로 마크된다.

SNAT: 출발 주소가 NAT 연산에 의해서 변경되면 가상 상태가 설정된다. connection tracking system 에 의해 사용되어지며, 출발지 주소가 응답 패킷에서 변경되는지를 알 수 있다.

DNAT: 목적지 주소가 NAT 연산에 의해 변경되면 가상 상태가 설정된다.  tracking system 에 의해 사용되어지며, 목적지 주소가 응답 패킷에서 변경되는지를 알 수 있다.

connection tracking system 은 관리자가 connection의 lifetime 에 있어 특정 시점을 타겟으로 하는 규칙을 만들 수 있도록 허용하고 state 들을 추적한다.


[결론]
netfilter 패킷 필터링 프레임워크가 와 iptables 방화벽은 리눅스 서버에서 대부분의 방화벽 솔루션의 기본이다.
netfilter kernel hook 은 시스템에서 처리되는 패킷들의 강력한 제어를 제공하는 네트워킹 스택에 가깝다.
iptables 방화벽은 유연하고 확장가능한 통신 정책 요구사항 방법을 커널에 제공하는 netfilter 기능을 기반으로 한다.
이 글을 같이 보면서 여러분은 netfilter와 iptables을 보다 잘 다룰 수 있어 여러분의 시스템을 보다 안전하게 할 수 있을 겁니다.

container 에 없는 iptables 커맨드 실행하기

# container 에 없는 iptables 커맨드 실행하기

# 방법1
# container 시작시 호스트 볼륨 연결하기
# 이미 컨테이너가 존재하면 삭제(--rm)
# 호스트의 root path 를 컨테이너의 /host 로 연결하고, (--volume /:/new_root)
# 컨테이너에게 확장권한을 부여한다.(--privileged)
# 컨테이너 실행시 /new_root 로 root 를 변경한다.
docker run -it \
--name=ysoftman
--hostname=ysoftman \
--rm \
--volume /:/new_root \
--privileged  \
busybox \
chroot /new_root

# 이제 컨테이너 내에서 호스트의 커맨드가 실행된다.
iptables -t filter -S


# 방법2
# 컨테이너 내에서 --pid=host 로 호스트 PID namespace 를 사용한다.
# 호스트의 pid 1(system) 대상으로(-t) -m(--mount[=file], 파일을 명시하지 않으면 target process 의 mount namespace 조인)
docker run -it \
--name=ysoftman \
--hostname=ysoftman \
--rm \
--privileged \
--pid=host \
busybox \
nsenter -t 1 -m sh

# 이제 컨테이너 내에서 호스트의 mount 정보로 호스트의 커맨드가 실행된다.
iptables -t filter -S


# 방법3
# 그냥 컨테이너 실행
docker run -it --name=ysoftman --hostname=ysoftman busybox

# 터미널을 하나 더 열고 호스트에서
# 위 컨테이너의 pid 의 network namespace 조인해 iptables 명령 실행한다.
# -t(--target) pid -n(--net[=file], 파일을 명시하지 않으면 target process의 네트워크 네임스페이스로 조인)
nsenter -t $(docker inspect --format {{.State.Pid}} ysoftman) -n iptables -t filter -S

linux ip iptables 사용하기

# linux 에서 자주 사용되는 ip 명령 예제들
# 참고로 다음과 같이 각 명령에 대한 도움말을 볼 수 있다.
ip addr help 
ip link help 

# 네트워크 장치�ipv4, ipv6 주소 정보
ip addr

# ip 주소할당, dev(device)로 eth0 를 사용
ip addr add 10.10.10.2/24 dev eth0

# ip 주소 삭제
ip addr add 10.10.10.10/24 dev eth0
ip addr delete 10.10.10.10/24 dev eth0

# 장치별 링크 정보 
ip link

# 라우터 정보
ip route

# 연결된 이웃 장치 정보
ip neighbor


##### 네트워크 네임스페이스 구분해서 통신하기 #####


# veth(virtual Ethernet devices) 타입으로
# lemon_eth0 apple_eth0 를 생성하고 연결한다.
ip link add lemon_eth0 type veth peer name apple_eth0

# namespace 확인
ip netns

# LEMON namespace(네트워크가 호스트 네트워크와 격리됨) 생성
# /var/run/netns/LEMON 파일이 생성된다.
ip netns add LEMON
ip netns add APPLE

# lemon_eth0 의 네임스페이스를 LEMON 으로 설정
ip link set lemon_eth0 netns LEMON
ip link set apple_eth0 netns APPLE

# LEMON 네임스페이스에 접속해서 lemon_eth0 장치 시작하기 
ip netns exec LEMON ip link set lemon_eth0 up
ip netns exec APPLE ip link set apple_eth0 up

# LEMON 네임스페이스에 접속해서 lemon_eth0 장치에 ip 설정하기
ip netns exec LEMON ip addr add 10.10.10.2/24 dev lemon_eth0
ip netns exec APPLE ip addr add 10.10.10.3/24 dev apple_eth0

# APPLE apple_eth0 의 패킷을 모니터링 하고
ip netns exec APPLE tcpdump -l -i apple_eth0
# LEMON(lemon_eth0) --> APPLE(apple_eth0) 로 핑을 보내 확인 할 수 있다.
ip netns exec LEMON ping 10.10.10.3

# 참고로 매번 네임스페이스 exec 를 명시하지 않고,
# nsenter 명령으로 네임스페이스 들어가 있을 수 있다.
# 들어간 네임스페이스에 exit 를 하면 빠져나온다.
nsenter --net=/var/run/netns/LEMON
ping 10.10.10.3

# 통신시 ARP 로 매번 브로드캐스팅은 비효율적이라 캐싱하게 된다.
# LEMON 네임스페이스 상에서 이웃을 조회하면 10.10.10.3(apple_eth0)가 캐싱되있다.
ip neighbor

# 현재 네임스페이스를 빠져나온다.(호스트(루트) 네임스페이스로 이동)
exit

# 이제 LEMON, APPLE 네임스페이스 삭제하면 LEMON, BLUE 네임스페이스 안의 이더넷도 모두 삭제된다.
ip netns del LEMON
ip netns del APPLE


##### iptables(netfilter) 설정하기 #####


# iptables 은 커널의 netfilter(프레임워크)에 rules를 설정하고 실제로는 netfilter 로 방화벽 기능이 동작한다.
# netfilter 는 다음 5개의 chain 을 hook 하고 룰에 따라 패킷을 필터링한다.
# PREROUTING: 외부로부터 들어오는 패킷
# INPUT: PREROUTING -> 로컬에서 받아야 하는 패킷
# FORWARD: PREROUTING -> FORWARD -> POSTROUTING 으로 로컬을 거치지 않고 외부로 부터 들어온 패킷을 다른 외부로 가야하는 패킷
# OUTPUT: 로컬 -> POSTROUTING 으로 로컬에서 외부로 가는 패킷
# POSTROUTING: FORWARD 또는 로컬에서 외부로 나가야하는 패킷

# 각 chain 에 맞는 다음과 같은 성격의 룰 테이블이 있다.
# filter:  패킷 필터링에 사용하는 테이블, INTPUT,FORWARD,OUTPUT 에서 사용
# nat: 출발지, 목적지 변경시 사용하는 테이블, PREROUTING,POSTROUTING 에서 사용
# mangle: 패킷 변조시 사용하는 테이블�, 5개 chain 모두에서 사용
# raw: 주로 netfilter 에서 추적하지 않도록 NOTRACK 설정하는데 사용하는 테이블, PREROUTING,OUTPUT 에서 사용
# security: SELinux 보안 사용시 사용하는 테이블, INPUT,FORWARD,OUTPUT 에서 사용

# filter 테이블 -S(list-rules) 룰 리스트 보기
iptables -t filter -S 
# -t 명시하지 않으면 filter 가 기본값이다.
iptables -S

# FOWARD chain에 설정된 rule들 보기 -v(가 없으면 in,out 이더넷 장치가 보인다) 
iptables -L FORWARD -v
iptables -L INPUT -v

# 10.10.10.3 으로 부터 들어오는(INPUT chain) -j(--jump) DROP(패킷 차단) 룰 추가(-A, --append)
iptables -A INPUT -s 10.10.10.3/32 -j DROP

# 10.10.10.3 으로 부터 들어오는(INPUT chain) -j(--jump) ACCEPT(패킷 허용) 룰 추가(-A, --append)
iptables -A INPUT -s 10.10.10.3/32 -j ACCEPT

# 룰 삭제(-D, --delete)
iptables -D INPUT -s 10.10.10.3/32 -j ACCEPT

# -A 같은 내용의 룰이 계속 추가 되 때문에
# -D 같은 내용이라도 마지막 룰만 삭제되어 모두 삭제하려면 N번 실행해야 한다.

# 외부(인터넷) 통신을 위해서는
# POSTROUTING 에 nat 추가
iptables -t nat -A POSTROUTING -s 10.10.10.0/24 -j MASQUERADE
# 패킷을 내 사설IP 에서 받을 수 있도록 -d(--destination) 허용
iptables -t filter -A FORWARD -d 10.10.10.3/24 -j ACCEPT

# nat 설정 상태 확인
iptables -t nat -S

mac pfctl 로 ip 블럭

# 특정 ip 를 블럭해 disconnection test 를 하려고 한다.
# mac 같은 BSD 계열에서는 iptables 대신
# pfctl (packet filter control)을 사용할 수 있다.

# pfctl 활성
sudo pfctl -e

# pfctl 비활성
sudo pfctl -d

# vi /etc/pf.conf 에 직접 블럭할 ip 를 명시한다.
block drop from any to 10.10.10.2
block drop from any to 10.10.10.3
block drop from any to 10.10.10.4

# 또는 ip 그룹을 테이블로 만들고 다음과 같이 지정할 수도 있다.
table <ysoftmantable> persist { 10.10.10.2, 10.10.10.3, 10.10.10.4}
block drop from any to { <ysoftmantable> }

# pf.conf 로딩
sudo pfctl -f /etc/pf.conf

# 이제 위에 명시된 ip 로 outbound 되는 패킷은 모두 블럭된다.

# ysoftmantable 테이블 상태보기
sudo pfctl -t ysoftmantable -vT show

# ysoftmantable 테이블에 ip 추가
sudo pfctl -t ysoftmantable -T add 10.10.10.10
sudo pfctl -t ysoftmantable -T add 10.10.10.11

# ysoftmantable 테이블에서 ip 제거
sudo pfctl -t ysoftmantable -T delete 10.10.10.11

# 생성한 테이블 모두 지우기(T대문자)
sudo pfctl -F Tables

# nat,info,queue,table ... 등 전체지우기
sudo pfctl -F all

# 참고 
man pfctl
man pf.conf