iptables 그림보면서 이해하기

입질쾌감 물때표

리눅스에서의 iptables

내가 처음 iptables을 이해 하려고 했을때가 10년전이였던것 같은데 기초적인 지식이 부족해서 그 당시에는 외계어를 읽는 듯한 기분이였다. 그리고도 계속 어떻게 사용해야 하는지 모르다가 일을 하는 와중에 하나씩 해보면서 깨우쳐 갔다. 그래서 아래의 글은 틀린내용이 다소 있을 수 있으며 그 부분을 지적해 준다면 감사할 따름이다. 이론적인 부분은 배제하고 아래의 그림을 보고 자신의 상황에 따라 어떻게 체인을 걸어야 할지를 판단해서 적용하면 될 것 같다.

IP_CHANE_구성도

여러분의 Linux box를 도착지로 삼는 모든패킷은 INPUT Chain을 통과하게 되며 여러분의 Linux box에서 생성되 외부로 보내지는 모든패킷은 OUTPUT Chain을 통과하게 된다.

NAT Packet의 주소변환 영역

패킷이 로컬에 통과하게 되고 패킷을 다시 쓰려고 한다면 NAT 체인을 거친다. 우선적으로 iptables의 PREROUTING을 거친다. 이때 로컬로 받을 것인지 그대로 포워딩을 할것인지 결정하면 된다. 만약 포워딩을 한다면 PREROUTING -> POSTROUTING 체인으로 바로 건너가게 된다. 그런데 PREROUTING에서 만약 로컬 프로세스로 보내게 된다면 POSTROUTING의 역할을 하는 것이 OUTPUT 체인이 될 것이다. 중요한 것은 ‘NAT’이란 영단어를 보면 당황하지 말고 패킷을 다시 쓴다는 이야기로 이해하면 빠를것이다.

# iptables -P PREROUTING
As the name implies, the PREROUTING chain is responsible for packets that just arrived at the network interface. (즉, 장치에 패킷이 도달했을때 시점이다. 위의 그림을 보아도 패킷이 가장 먼저 만나는 체인이 된다고 보면 된다.)
So far no routing decision has taken place, therefore it is not yet known whether the packet would be interpreted locally or whether it would be forwarded to another machine located at another network interface.
# iptables -P POSTROUTING
Just before are forwarded packet leaves the machine it passes the POSTROUTING chain and then leaves through the network interface. (즉, 장치에 패킷이 밖으로 나가는 시점이다.)
For locally generated packets there is a small difference: Instead of passing the PREROUTING chain it passes the OUTPUT chain and then moves on to the POSTROUTING chain.

% 참고 : [INPUT -> OUTPUT]에 체인이 걸리면 로컬 프로세스에 걸려있다고 생각하자. 즉, 어플리케이션에 들어왔다가 처리되는 패킷이기에 관련 어플리케이션의 프로세스가 살아있을 거라는 이야기다 ]

예제

59999포트를 로컬의 80포트로 리다이렉트 시킴

sudo iptables -t nat -A PREROUTING -p tcp --dport 59999 -j REDIRECT --to-port 80

[유용] 아이피 loopback 호스트의 폐쇄성 포트와 외부포트와 연결해 포워딩 하기

어렵게 구글링을 통해 알게 된것인데, 아래의 예제는 다음과 같은 경우에 활용하면 좋다.
예) MySQL을 설치했는데, 서버가 로컬호스트로만 Bind 되어 있어 서버가 127.0.0.1:3306으로 동작하고 있는 상황이다. 따라서 로컬에서 직접 연결하지 않는 한 다른 곳에서는 연결을 할수가 없게 된다. (물론 my.cnf에서 쉽게 해결할수 있다) 그래서 이러한 상황을 해결하기 위해 외부에서 59999 포트로 접속하면 이 포트를 포워딩해서 로컬의 3306포트로 붙이고 싶다는 것이다. 그러면 아래와 같이 해결하면 된다. (우분투기준이다, 커널에 어떤 플래그를 줘야 하는지는 플랫폼 마다 다를 수 있으니 미리 언급한다)

sudo sh -c "echo 1 > /proc/sys/net/ipv4/conf/eth0/route_localnet" # 커널에 로컬호스트를 라우팅할것이라고 알려줘야 한다.
sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 59999 -j DNAT --to 127.0.0.1:17355

[TIP] IPTABLES 체인 한꺼번에 전부지우기

for i in $( iptables -t nat --line-numbers -L | grep ^[0-9] | awk '{ print $1 }' | tac ); do iptables -t nat -D PREROUTING $i; done

[TIP] 목적지 아이피 바꾸기

# 나가는 패킷 다시 쓰기
webterror@webterror:~$ sudo iptables -t nat -A OUTPUT -d 211.45.70.13 -j DNAT --to 192.168.255.151
# 들어오는 패킷 다시쓰기
webterror@webterror:~$ sudo iptables -t nat -A PREROUTING -d 211.45.70.13 -j DNAT --to 192.168.255.151

[ 이해 ]

INPUT은 자신의 호스트를 목적지로 오는 모든 타켓 패킷에 대해 체인을 건다.
OUTPUT은 자신의 호스트가 생성한 패킷에 대해 체인을 건다.

INPUT으로 들어오는 것은 SOURCE PORT를 지정해서 라우팅을 해야 하기 때문에 특정 서비스에 대해서만 체인을 걸어야 한다.
만일 도착지가 로컬인것에 대해서 체인을 건다면 OUTPUT에 기록해야 할 것이다.
# 로컬에 80포트의 웹포트가 있을 경우 1111포트로도 로컬에서 접속이 가능하게 하려면 다음과 같이 한다.
sudo iptables -t nat -A OUTPUT -p tcp –dport 1111 -j DNAT –to-destination 127.0.0.1:80

PREROUTING은 라우팅이 결정되기 전, POSTROUTING은 라우팅이 결정된 후 입니다.
따라서 DNAT은 반드시 PREROUTING에서 해 줘야 하고, (라우팅은 목적지ip에 따라 달라질 수 있습니다)
SNAT은 POSTROUTING에서 해 줘야 합니다. (라우팅이 결정된 후에 src ip가 바뀌는 경우, 그리고 masquerading을 생각해보세요)
POSTROUTING : 라우팅이 끝나고 난 다음 주소를 변경할수 있는 사슬 (SNAT) 이라고 책에는 나오는데
이건 아마 클라이언트가 라우팅배정을 끝내고 패킷이 갈곳은 정해졌다 = 라우팅이 끝났다는 의미인지
이미 목적지가 정해진 패킷에 대해 소스아피를 변경하겠다는 의미인듯 하다.

@@ incoming rules

iptables -t nat -I PREROUTING 1 -d 9.9.9.1 -i ETH00.771 -j DNAT --to-destination 10.55.0.62 
iptables -t nat -I PREROUTING 1 -d 9.9.9.2 -i ETH00.771 -j DNAT --to-destination 10.55.0.57 
iptables -t nat -I PREROUTING 1 -d 9.9.9.3 -i ETH00.771 -j DNAT --to-destination 10.55.0.172 

@@ Outgoing rules

iptables -t nat -I POSTROUTING 1 -s 10.55.0.62 -o ETH00.771 -j SNAT --to-source 9.9.9.1 
iptables -t nat -I POSTROUTING 1 -s 10.55.0.57 -o ETH00.771 -j SNAT --to-source 9.9.9.2 
iptables -t nat -I POSTROUTING 1 -s 10.55.0.172 -o ETH00.771 -j SNAT --to-source 9.9.9.3

How-To: Redirecting Network Traffic To A New IP Using IPtables

While doing a server migration, it happens that some traffic still go to the old machine because the DNS servers are not yet synced or simply because some people are using the IP address instead of the domain name….
By using iptables and its masquerade feature, it is possible to forward all traffic to the old server to the new IP.
This tutorial will show which command lines are required to make this possible.

In this article, it is assumed that you do not have iptables running, or at least no nat table rules for chain PREROUTING and POSTROUTING.
The first thing to do is do enable IP forwarding. This is done either by using:

# echo "1" > /proc/sys/net/ipv4/ip_forward
or
# sysctl net.ipv4.ip_forward=1

Then, we will add a rule telling to forward the traffic on port 1111 to ip 2.2.2.2 on port 1111:

# iptables -t nat -A PREROUTING -p tcp --dport 1111 -j DNAT --to-destination 2.2.2.2:1111

and finally, we ask IPtables to masquerade:

iptables -t nat -A POSTROUTING -j MASQUERADE

Optionally, you could only redirect the traffic from a specific source/network with, for a host only:

# iptables -t nat -A PREROUTING -s 192.168.1.1 -p tcp --dport 1111 -j DNAT --to-destination 2.2.2.2:1111

or for a whole network

# iptables -t nat -A PREROUTING -s 192.168.1.0/24 -p tcp --dport 1111 -j DNAT --to-destination 2.2.2.2:1111

that’s it, now the traffic to port 1111 will be redirected to IP 2.2.2.2 .
If you go on host 2.2.2.2, you should see a lot of traffic coming from the host doing the redirection.

5 thoughts on “iptables 그림보면서 이해하기

  1. 그동안 iptables의 개념을 정확하게 이해 못하고 사용 중이었는데 작성해 주신 IP Chain 구성도를 통해서 많은 부분을 이해하게 되었습니다. 감사합니다.

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다