Linux command - iptables

sycho·2023년 12월 19일
0

Linux Commands

목록 보기
16/30

iptables

  • linux의 여러 table들을 관리하는 명령어이다.

  • 원래는 방화벽 뿐만이 아니라 여러개의 table을 담당을 한다. 기본으로 있는 table은 Filter, NAT, RAW, Mangle이다.

  • Ubuntu에서의 설치는 다음과 같다.

$ sudo apt install iptables

iptables 기본 원리

  • 각 table에는 여러개의 chain이 있다. 각 chain은 여러개의 rule을 또 포함한다. 계층 관계를 가지고 있다고 생각하면 된다. 여러개의 규칙이 모여 chain 형성, 그리고 여러개의 chain이 모여 하나의 table 형성.

  • packet은 처음에 table에 도달하면 특정 chain에 들어가 거기 안에서 어떤 rule을 만족하는지 확인을 한다. 만족하는 rule을 찾으면, target이 주어지게 된다. 이 target은

    • 다른 chain
    • ACCEPT : packet 통과 허용
    • DROP : packet 통과 불허
    • RETURN : 해당 chain에서 더 진행되지 못하게 하고 이전 chain으로 돌아가도록 강요.
    • REJECT : DROP과 같은데, 오류 메시지도 송신자에게 전달한다.
    • 또는 다른 여러 종류가 가능.
  • iptables 조작을 하려면 꼭, sudo 권한을 가지고 있어야 한다.

NAT table

  • Network Address Translation table의 약자다. packet이 새로운 연결을 형성하려고 하면 이 table에 오게 된다. chain 종류는
    • PREROUTING : routing이 본격적으로 이루어지기 전에 destination을 조작하는 것을 관여하는 chain이다.
    • POSTROUTING : routing이 이루어진 후 source를 수정할 때 사용하는 chain. masquerading에 쓰인다.
    • INPUT : 잘 안쓰인다. 보통 NAT가 routing 과정에 온 packet의 source/destination address를 변조시키는데 쓰이는데 본인의 host로 오는 packet에 대해서 이를 신경 쓸 이유는 별로 없기 때문.
    • OUTPUT : 반면 본인 host에서 온 packet이 다른곳에 전달되려고 할 때 destination을 수정하기 위해 자주 사용된다.

RAW table

  • 방화벽에서 connection tracking에 사용하지 않을 packet을 골라내는데 사용되는 table이다.
    • PREROUTING : 오고 있는 모든 종류의 connection에 대해서 골라내는데 사용되는 table
    • OUTPUT : 본인에게서 나가고 있는 모든 종류의 packet에 대해서 골라내는데 사용되는 table

MANGLE table

  • packet들의 IP header부분을 조절하는 table
    • INPUT : 본인으로 오는 packet에 대해 조작
    • OUTPUT : 본인에게서 나가는 packet에 대해 조작
    • FORWARD : linux box를 통해 routing되는 packet에 대해 조작
    • PREROUTING : 오고 있는 모든 종류의 connection에 대해 조작
    • POSTROUTING : 나가고 있는 모든 종류의 connection에 대해 조작

Filter table

  • 방화벽으로 쓰이며, 이번 글의 핵심 주제이기도 하다.
    • INPUT : host로 오는 packet들에 대해 관리를 하는 chain
    • FORWARD : 다른 곳으로 forwarding할 예정인데 이 host로 온 packet들에 대해 관리를 하는 chain
    • OUTPUT : host에서 밖으로 나가는 packet들에 대해 관리를 하는 chain

Options

-L, -v

  • 먼저 다음 command를 수행해보도록 하자.
$ sudo iptables -L -v
  • -L option은 모든 rule을 출력하는데 사용되며, -v는 verbose의 약자로 상세한 정보를 보여주는데 사용된다. 사용하면 초기에는 다음과 같다.
Chain INPUT (policy ACCEPT 438 packets, 476K 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 228 packets, 17560 bytes)
 pkts bytes target     prot opt in     out     source               destination
  • 일단 모든 chain이 그냥 ACCEPT로 되어 있는 것을 볼 수 있다. 그뿐만이 아니라 아무 rule도 지정된 것이 없다. 즉 filtering 없이 모든 packet들이 돌아다니는 것을 허용하는 것이다.

-A

  • chain의 맨 끝에다가 규칙을 추가하는데 사용된다. 이 때 다양한 추가 option들이 조합되어서 활용이 된다.
    • -i : filtering 대상 host의 interface
    • -p : filtering 대상 packet의 protocol. tcp, udp, udplite, icmp, sctp, icmpv6등 여러개가 가능하다.
    • -s : filtering 대상 source ip address
    • --dport : filtering 대상의 destination port number
    • -j : target 이름. 앞에서 본 ACCEPT, DROP, RETURN중 하나. Filter table의 경우 무조건 넣어야 한다.

-D

  • rule 제거에 사용된다. 먼저 어느 chain의 rule을 제거할지 명시하고, rule을 직접 명시하거나 rulenum을 입력하면 된다. 맨 위의 rule이 1번이라는 점을 활용하면 위의 table을 전부 비울거면 밑을 4번 실행하면 끝이다.
$ sudo iptables -D INPUT 1

--linenumbers

  • 다만 굳이 일일이 세지 말고, -L이랑 --line-numbers를 같이 활용해가지고 list를 볼 수 있도록 하자.
$ sudo iptables -L --line-numbers
Chain INPUT (policy ACCEPT)
num  target     prot opt source               destination
1    ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:ssh
2    ACCEPT     all  --  anywhere             anywhere
3    ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:ssh
4    ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:http
5    ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:https
6    DROP       all  --  anywhere             anywhere

-F

  • 이 option을 사용하면 특정 table의 모든 rule을 한번에 없앨 수 있다. chain 상관없이. chain을 명시해서 해당 chain에 대해서만 전부 없애는 것도 가능하다.
$ sudo iptables -F

-I

  • 특정 위치에 특정 rule을 집어넣을 때 사용된다. insert의 약자. 넣을 chain과 넣을 rule은 필수이며, 넣을 위치도 선택적으로 parameter로 제공을 하며 주어지지 않을 경우 맨 위에다가 insert를 한다.
$ sudo iptables -I INPUT 1 -p tcp --dport 22 -j ACCEPT

-t

  • 기본적으로 iptables는 filter table에 대해 작용한다. 다른 table에 대해서도 무언가를 하고 싶으면 -t를 사용하고 뒤에 nat, raw, mangle을 사용하면 된다.
$ sudo iptables -t raw -L -v

-N

  • 특정 table에 새로운 chain을 만든다. 뒤에 이름도 명시해야 하며, 해당 이름의 chain이 기존에 존재해서는 안된다.
$ sudo iptables -N WHACKAMOLE

-X

  • 특정 table의 지정된 이름의 chain을 지운다. 단 사용자가 만든 chain만 지우는게 가능하며, 해당 chain에 대한 reference가 없어야 한다. 만약 있을 경우, 관련 규칙들을 제거하거나 대체한 다음에 지워야 한다. chain에는 아무 규칙도 없어야 한다. 이름을 꼭 명시할 필요는 없는데, 이 경우 해당 table의 모든 사용자가 만든 chain을 지우는걸 시도한다.
$ sudo iptables -X WHACKAMOLE

종합 예시

  • local host traffic을 허용할거면 다음과 같이 하자. 여기서 lo interface는 loopback interface로 local host에서의 communication에서 사용된다. localhost 내 communication은 뭐든 신경 안쓰겠다는 뜻.
$ sudo iptables -A INPUT -i lo -j ACCEPT
$ sudo iptables -A INPUT -o lo -j ACCEPT
  • HTTP, HTTPS, SSH connection은 허용하겠다는 rule 추가
$ 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
  • 여기까지 했으면 다음과 같이 나온다.
$ sudo iptables -L -v
Chain INPUT (policy ACCEPT 564 packets, 486K bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0 ACCEPT     all  --  lo     any     anywhere             anywhere
    0     0 ACCEPT     tcp  --  any    any     anywhere             anywhere             tcp dpt:ssh
    0     0 ACCEPT     tcp  --  any    any     anywhere             anywhere             tcp dpt:http
    0     0 ACCEPT     tcp  --  any    any     anywhere             anywhere             tcp dpt:https

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain OUTPUT (policy ACCEPT 228 packets, 17560 bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0 ACCEPT     all  --  lo     any     anywhere             anywhere
  • 다음으로 다른 traffic은 전부 DROP 하도록 설정하자.
$ sudo iptables -A INPUT -j DROP
  • 이제... 갖고 노는건 많이 했으니 전부 없애보자.
$ sudo iptables -F
$ sudo iptables -vL
Chain INPUT (policy ACCEPT 687 packets, 496K 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 228 packets, 17560 bytes)
 pkts bytes target     prot opt in     out     source               destination
  • 특정 ip주소의 tcp connection만 를 막는걸 이번에는 넣어보자.
$ sudo iptables -A INPUT -p tcp -s 1.2.3.4 -j DROP
  • 다음은 좀 고급 기술로, 특정 범위에서 온 IP 주소들을 reject하도록 해보자. iprange module이 필요하다. module을 사용할 때는 -m option을 사용하고 module 이름을 거기에 붙여넣는다.
$ sudo iptables -A INPUT -m iprange --src-range 192.168.0.128-192.168.0.255 -j REJECT
  • 다음은 multiport module을 사용해가지고 여러개의 destination/source port에 대한 rule을 한번에 추가하는 법을 알아볼 것이다. 이 때 -p option이 필수로 들어가야 한다.
$ sudo iptables -A INPUT -p tcp -m multiport --dport 22,80,443 -j ACCEPT
$ sudo iptables -A OUTPUT -p tcp -m multiport --sport 22,80,443 -j ACCEPT
  • 다음은 특정 subnet에 대해 규칙을 넣는 방법을 알아보자. 여기서 -d option은 destination ip address를 의미한다. host에서 나가는 packet중 저 특정 subnet을 destination으로, 22번 port를 목표로 하는 TCP packet들은 나가는 것을 허용하겠다는 뜻.
$ sudo iptables -A OUTPUT -p tcp -d 192.168.72.128/24 --dport 22 -j ACCEPT
  • ping request를 막고 싶으면 ICMP를 차단하면 되니...
$ iptables -A INPUT -p icmp -i eth0 -j DROP

table save

  • iptable 설정을 저장하는 방법이 있다.
$ sudo iptables-save > ~/rule1
  • load하려면 다음과 같이 하자.
$ sudo iptables-save < ~/rule1

방화벽 작동 유의사항

  • 맨 위의 rule부터 하나씩 아래로 내려가면서 확인을 한다는 것에 유의해야 한다.

  • 이 때문에, 만일 INPUT에서 본인이 통과시킬 애들을 다 적절히 설정했다 싶으면, 마지막에는 다음 rule을 추가하는 것이 맞다.

$ sudo iptables -A INPUT -j DROP
profile
CS 학부생, 핵심 관심 분야 : Embed/System/Architecture/SWE

0개의 댓글