클라우드 컴퓨팅 & NoSQL/운영 & Devops

리눅스 방화벽과 NAT를 위한 ipTables

Terry Cho 2019. 11. 28. 22:28

리눅스 방화벽과 NAT를 위한 ipTables


서버에서 라우팅 설정을 하다보면, 다른 포트로 받아야 하는데, 로드밸런서나 방화벽등의 문제로 포트를 변경할 수 없는 경우가 있어서 A포트로 들어오는 트래픽을 B포트로 변경하고 싶을때가 있다.

또는 서버로 들어오는 트래픽을 IP등으로 선별적으로 받는 것과 같은 방화벽 역할이 필요한 경우가 있는데, 방화벽을 설치하지 않고 서버단에서 간단하게 하는 방법이 필요한 경우가 있는데, 이러한 용도를 위해서 사용할 수 있는 것이 ipTables이다. 


ipTables는 리눅스 firewall로 incoming & outgoing traffic을 rule에 따라 filtering 하는 기능을 가지고 있다. ipTables는 table이라는 단위를 가지고 있는데, 이 table 마다 룰을 정해서 룰에 매치되는 트래픽에 대해서 핸들링할 수 있는 기능이 있다. 

주로 사용되는 테이블은 다음과 같다

  • Filter table :  가장 많이 사용되는 테이블로, 트래픽에 대한 컨트롤을 하는 방화벽 역할로 사용된다.

  • NAT table :  들어오는 패킷을 다른 포트나 다른 호스트 서버로 라우팅 하는 역할을 한다.

  • Mangle table : 패킷의 헤더를 변경하는데 사용할 수 있다. (예 TTL 등)


각 테이블은 체인(CHAIN)으로 구성이 되는데, 각 단계별로 하는 역할이 다르다.


Filter table

먼저 Filter Table을 보면 다음과 같다. 

%iptabls -L -v

명령어를 이용하면 필터 테이블을 볼 수 있는데, 크게 Input,Forward,Output 체인으로 구성이 되어 있다. 

예를 들어 보면

%sudo iptables -A INPUT -i lo -j ACCEPT

는 모든 들어오는 트래픽에 대해서 Loopback interface는 모든 트래픽을 허용하도록 INPUT CHAIN을 설정한 것이다. 

만약 http,https,SSH 만 허용하려면 다음과 같이 사용하면 된다. 

%sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT

%sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT

%sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT


특정 IP에서 들어오는 트래픽을 허용하고자 하면 

sudo iptables -A INPUT -s 192.168.1.3 -j ACCEPT

게 설정하면 된다. 

반대로 특정 IP에서 들어오는 트래픽만 막고자 한다면 DROP을 하면 되는데, 

sudo iptables -A INPUT -s 192.168.1.3 -j DROP

명령을 사용하면 된다. 


등록된 rule을 삭제하려면

sudo iptables -L --line-numbers

명령을 사용하면, 등록된 룰이 번호와 함께 나오고 

sudo iptables -D INPUT 3

명령으로 3번째 룰을 삭제할 수 있다. 


iptables 명령어는 수정한 테이블과 룰은 메모리에만 남아 있기 때문에 재기동하면 삭제된다. 

그래서 영구 반영하기 위해서는

sudo /sbin/iptables-save

명령으로 저장해야 한다. 

NAT table

다음으로 유용하게 사용할 수 있는것이 NAT 테이블인데 들어온 트래픽을 다른 호스트로 라우팅 시키거나 또는 같은 호스트내의 다른 포트로 포워딩 시키는 것이 가능하다. 

패킷은 들어오면 아래와 같은 체인들을 거쳐가는데, 그림에서 보면 nat와 filter 체인이 섞여 있는 것을 볼 수 있다. 


트래픽은 들어오면 NAT의 PRE ROUTING을 거쳐, FILTER의 INPUT을 거쳐서 애플리케이션으로 들어갔다가 나올때 FILTER의 OUTPUT 체인과, NAT의 OUTPUT 체인을 거쳐서 최종적으로 NAT의 POSTROUTING 체인을 거쳐서 목적지로 라우팅 된다. 



그림 출처 : https://www.systutorials.com/816/port-forwarding-using-iptables/


이 과정에서 NAT 테이블의 체인 중 주로 사용되는 CHAIN을 보면

  • PREROUTING : 들어온 트래픽을 다른 호스트나 또는 같은 호스트의 다른포트로 포워딩 할때 사용된다.

  • POSTROUTING : 호스트에서 아웃바운드로 나가는 트래픽을 다른 IP나 포트로 포워딩 한다. 


예를 들어보면 아래는 80포트로 들어온 트래픽을 같은 호스트의 4000포트로 포워딩하는 설정이다. 


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


참고로 이렇게 하면 외부에서 80 포트로 들어오는 트래픽은 4000으로 라우팅 되지만, localhost:80 으로 호출을하면 이는 라우팅이 되지 않는데, 이유는 localhost는 PREROUTING CHAIN을 타지 않기 때문이다. 그래서 만약 localhost에도 동일하게 작동하게 하려면 Output chain을 아래와 같이 설정해줘야 한다.

iptables -t nat -A OUTPUT -o lo -p tcp --dport 80 -j REDIRECT --to-port 8080

참고 : https://askubuntu.com/questions/444729/redirect-port-80-to-8080-and-make-it-work-on-local-machine


그리드형