본문 바로가기

iptables

Ubuntu ufw & iptables & nftables

다음 글: nftables 이란 / The netfilter.org project

글을 쓰는 배경

본인은 네트웍 레벨의 방화벽 설정에 대해서는 적절한 수준에서 이해하고 설정하여 운영할 수 있는 수준입니다. 그러나 Ubuntu와 같은 시스템을 서비스 목적으로 운영한 경험은 없어, 이해 수준은 초중급정도일뿐 입니다. 그런데 가끔 Ubuntu 시스템을 설치하여 시험해 볼 상황이 있는데 그때마다 방화벽 설정에 대해 헷갈립니다. Google Search를 하여 필요한 것을 하나하나 해결은 해 가는데, 너무 오랫만에 하는 경우가 많아, 그때마다 시간을 많이 소비합니다. 따라서 이번 기회에 본인이 언제든 참조할 수 있는 수준으로 정리해 놓으려 합니다. 

헷갈리지 않게 핵심 정리

  • ufw는 iptables을 이용하며, chain을 잘 알지 못하더라도 이용할 수 있습니다만 이해하면 좋습니다. 
  • ufw를 활성화하면 시스템 자신으로 들어오는 것을 모두 차단하니 console에서 ssh 등은 허용하는 것이 좋습니다. 
  • ufw를 활성화하면 iptables에 많은 chain이 생깁니다만 chain ufw-user-input과 ufw-user-forward를  주로 이용합니다. 
  • iptables에서 시스템 자신으로 향하는 chain은 INPUT이며, 경유하는 chain은 FORWARD입니다. 시스템을 라우터(중간시스템)로 이용할 때 chain FORWARD에 있는 rule을 주로 추가/수정/삭제합니다. 

iptables vs ufw vs nftables

iptables은 kernel level의 tool이며, ufw는 내부에서는 iptables을 이용하며, 사용자가 좀 더 편리하게 사용할 수 있도록 만들어 놓은 tool 입니다. 즉 ufw는 iptables을 이용한 Frontend tool로 이해하면 됩니다. nftables (nework filter tables)은 iptables을 대신하는 차세대 tool 입니다. 

 

ufw는 Ubuntu 18, 20, 21에 설치되어 활성화(enabled) 되어 있습니다. 

 

Ubuntu 18

salsal@u1804base:~$ sudo systemctl is-enabled ufw
enabled

Ubuntu 20

salsal@u2004base:~$ sudo systemctl is-enabled ufw
enabled

Ubuntu 21

salsal@u2104base:~$ sudo systemctl is-enabled ufw
enabled

iptables는 Ubuntu 18, 20, 21에 설치되어 (installed) 되어 있습니다.

nftables 설치되어 있지 않습니다. 

 

Ubuntu 18

salsal@u1804base:~$ sudo apt policy iptables
iptables:
  설치: 1.6.1-2ubuntu2
  후보: 1.6.1-2ubuntu2
  버전 테이블:
 *** 1.6.1-2ubuntu2 500
        500 http://kr.archive.ubuntu.com/ubuntu bionic/main amd64 Packages
        100 /var/lib/dpkg/status
salsal@u1804base:~$ sudo apt policy nftables
nftables:
  설치: (없음)
  후보: 0.8.2-1
  버전 테이블:
     0.8.2-1 500
        500 http://kr.archive.ubuntu.com/ubuntu bionic/universe amd64 Packages

Ubuntu 20

salsal@u2004base:~$ sudo apt policy iptables
iptables:
  Installed: 1.8.4-3ubuntu2
  Candidate: 1.8.4-3ubuntu2
  Version table:
 *** 1.8.4-3ubuntu2 500
        500 http://kr.archive.ubuntu.com/ubuntu focal/main amd64 Packages
        100 /var/lib/dpkg/status
salsal@u2004base:~$ sudo apt policy nftables
nftables:
  Installed: (none)
  Candidate: 0.9.3-2
  Version table:
     0.9.3-2 500
        500 http://kr.archive.ubuntu.com/ubuntu focal/universe amd64 Packages

Ubuntu 21

salsal@u2104base:~$ sudo apt policy iptables
iptables:
  Installed: 1.8.7-1ubuntu2
  Candidate: 1.8.7-1ubuntu2
  Version table:
 *** 1.8.7-1ubuntu2 500
        500 http://kr.archive.ubuntu.com/ubuntu hirsute/main amd64 Packages
        100 /var/lib/dpkg/status
salsal@u2104base:~$ sudo apt policy nftables
nftables:
  Installed: (none)
  Candidate: 0.9.7-1
  Version table:
     0.9.7-1 500
        500 http://kr.archive.ubuntu.com/ubuntu hirsute/universe amd64 Packages

 

nftables은 iptables, ip6tables, arptables 기능을 모두 포함하는 tool 입니다. 문법이 iptables 보다 낫고 쉽습니다. iptables의 문법을 이용할 수도 있습니다. multiple action을 설정할 수도 있습니다. 

 

1. ufw

1.1. 종단 시스템에서 설정하기

실행 상태 확인

salsal@u1804base:~$ sudo systemctl is-enabled ufw
enabled
salsal@u1804base:~$ sudo systemctl status ufw
● ufw.service - Uncomplicated firewall
   Loaded: loaded (/lib/systemd/system/ufw.service; enabled; vendor preset: enabled)
   Active: active (exited) since Sat 2021-07-31 18:09:42 KST; 40min ago
     Docs: man:ufw(8)
  Process: 229 ExecStart=/lib/ufw/ufw-init start quiet (code=exited, status=0/SUCCESS
 Main PID: 229 (code=exited, status=0/SUCCESS)
 
salsal@u1804base:~$ sudo ufw status
Status: inactive

설정 상태 확인 

salsal@u1804base:~$ sudo ufw status verbose
Status: inactive

ufw 활성화 및 상태 확인

ufw enable을 이용하여 활성화합니다. 활성화 뒤에 상태를 살펴보면 Status:active, 기본적으로 이 시스템으로 들어오는 것을 차단 (deny (incoming))하는 것을 알 수 있습니다. 실제 이렇게 명령어를 실행하면 이 시스템으로 어떤 연결도 시도할 수 없습니다. 

salsal@u1804base:~$ sudo ufw enable
Command may disrupt existing ssh connections. Proceed with operation (y|n)? y
Firewall is active and enabled on system startup

salsal@u1804base:~$ sudo ufw status verbose
Status: active
Logging: on (low)
Default: deny (incoming), allow (outgoing), disabled (routed)
New profiles: skip

안전하게 끊거나 차단하지 않고 설정할 수 있는 방법은 먼저 deny (incoming)을 allow (incoming)으로 변경한 뒤에 필요한 rule을 설정한 후에 다시 마지막에 deny (incoming)로 수정하는 것입니다. 

 

default value를 allow 로 변경하기

salsal@u1804base:~$ sudo ufw status verbose
Status: active
Logging: on (low)
Default: deny (incoming), allow (outgoing), disabled (routed)
New profiles: skip

salsal@u1804base:~$ sudo ufw default allow
Default incoming policy changed to 'allow'
(be sure to update your rules accordingly)

salsal@u1804base:~$ sudo ufw status verbose
Status: active
Logging: on (low)
Default: allow (incoming), allow (outgoing), disabled (routed)
New profiles: skip

ufw rule 설정 예

설명을 위해 https://salsalchanchan.tistory.com/10 에서 이용한 다이어그램을 이용하여 설명하겠습니다. 

pc3에 방화벽 (ufw) 설정이 전혀 없습니다. 따라서 pc1, pc2에서 pc3로 ssh 접근이 가능합니다. 그러나 pc3에서 ufw를 활성화하면 incoming default value가 deny 이므로 pc1, pc2에서 pc3로 ssh를 시도할 수 없습니다. 

salsal@pc3:~$ sudo ufw status
Status: inactive
salsal@pc3:~$ sudo ufw enable
Command may disrupt existing ssh connections. Proceed with operation (y|n)? y
Firewall is active and enabled on system startup
salsal@pc3:~$ sudo ufw status verbose
Status: active
Logging: on (low)
Default: deny (incoming), allow (outgoing), disabled (routed)
New profiles: skip

pc1 -> pc3로 ssh 를 시도할 경우 가능하지 않습니다. 

salsal@pc1:~$ ssh salsal@192.168.3.2
ssh: connect to host 192.168.3.2 port 22: Connection timed out

pc2 -> pc3로 ssh 를 시도할 경우 가능하지 않습니다.

salsal@pc2:~$ ssh salsal@192.168.3.2
ssh: connect to host 192.168.3.2 port 22: Connection timed out

 

그러나 pc3에서 ufw default value를 allow로 변경하면 pc1, pc2에서 pc3로 ssh 접근이 가능합니다. 

salsal@pc3:~$ sudo ufw default allow
Default incoming policy changed to 'allow'
(be sure to update your rules accordingly)
salsal@pc3:~$ sudo ufw status verbose
Status: active
Logging: on (low)
Default: allow (incoming), allow (outgoing), disabled (routed)
New profiles: skip

pc1에서 pc3로 ssh 가능

salsal@pc1:~$ ssh salsal@192.168.3.2
salsal@192.168.3.2's password:
Welcome to Ubuntu 18.04.5 LTS (GNU/Linux 5.4.0-80-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

0 updates can be applied immediately.

New release '20.04.2 LTS' available.
Run 'do-release-upgrade' to upgrade to it.

Your Hardware Enablement Stack (HWE) is supported until April 2023.
Last login: Sat Jul 31 21:48:18 2021 from 192.168.2.2
salsal@pc3:~$ logout

pc2에서 pc3로 ssh 가능

salsal@pc2:~$ ssh salsal@192.168.3.2
salsal@192.168.3.2's password:
Welcome to Ubuntu 18.04.5 LTS (GNU/Linux 5.4.0-80-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

0 updates can be applied immediately.

New release '20.04.2 LTS' available.
Run 'do-release-upgrade' to upgrade to it.

Your Hardware Enablement Stack (HWE) is supported until April 2023.
Last login: Sat Jul 31 21:45:25 2021 from 10.0.2.2
salsal@pc3:~$ logout

 

ufw 기능 시험을 위해 pc3에서 ufw default allow로 설정합니다. 

salsal@pc3:~$ sudo ufw default allow
Default incoming policy changed to 'allow'
(be sure to update your rules accordingly)

salsal@pc3:~$ sudo ufw status verbose
Status: active
Logging: on (low)
Default: allow (incoming), allow (outgoing), disabled (routed)
New profiles: skip

 

이 상태에서 PC3에서 다음과 같이 설정합니다. 

  • pc1 (192.168.1.2) 에서 오는 ssh 접근은 허용
  • ssh 접근 요청을 모두 차단
salsal@pc3:~$ sudo ufw allow from 192.168.1.2 to any port ssh
Rule added
salsal@pc3:~$ sudo ufw status verbose
Status: active
Logging: on (low)
Default: allow (incoming), allow (outgoing), disabled (routed)
New profiles: skip

To                         Action      From
--                         ------      ----
22/tcp                     ALLOW IN    192.168.1.2

salsal@pc3:~$ sudo ufw deny ssh
Rule added
Rule added (v6)
salsal@pc3:~$ sudo ufw status verbose
Status: active
Logging: on (low)
Default: allow (incoming), allow (outgoing), disabled (routed)
New profiles: skip

To                         Action      From
--                         ------      ----
22/tcp                     ALLOW IN    192.168.1.2
22/tcp                     DENY IN     Anywhere
22/tcp (v6)                DENY IN     Anywhere (v6)

salsal@pc3:~$ sudo ufw status numbered
Status: active

     To                         Action      From
     --                         ------      ----
[ 1] 22/tcp                     ALLOW IN    192.168.1.2
[ 2] 22/tcp                     DENY IN     Anywhere
[ 3] 22/tcp (v6)                DENY IN     Anywhere (v6)

rule은 낮은 번호부터 적용되므로 ufw rule을 추가할 때 순서에 주의해야 합니다. 

 

ufw rule은 다음과 같이 삭제할 수 있습니다. 

salsal@pc3:~$ sudo ufw status numbered
Status: active

     To                         Action      From
     --                         ------      ----
[ 1] 22/tcp                     ALLOW IN    192.168.1.2
[ 2] 22/tcp                     DENY IN     Anywhere
[ 3] 22/tcp (v6)                DENY IN     Anywhere (v6)

salsal@pc3:~$ sudo ufw delete 3
Deleting:
 deny 22/tcp
Proceed with operation (y|n)? y
Rule deleted (v6)
salsal@pc3:~$ sudo ufw status numbered
Status: active

     To                         Action      From
     --                         ------      ----
[ 1] 22/tcp                     ALLOW IN    192.168.1.2
[ 2] 22/tcp                     DENY IN     Anywhere

 

pc3에서 icmp packet은 받는 것을 차단하는 방법은 아래와 같습니다. Google Search를 해 보았으나 ufw command로 하기에는 곤란하며, /etc/ufw/before.rules 에 있는 내용을 수정하고 ufw reload를 수행하는 것이 좋습니다. 아래 내용에서 ACCEPT를 DROP으로 변경하면 됩니다. 

 

salsal@pc3:~$ sudo grep ufw-before-input.*icmp /etc/ufw/before.rules
-A ufw-before-input -p icmp --icmp-type destination-unreachable -j ACCEPT
-A ufw-before-input -p icmp --icmp-type time-exceeded -j ACCEPT
-A ufw-before-input -p icmp --icmp-type parameter-problem -j ACCEPT
-A ufw-before-input -p icmp --icmp-type echo-request -j ACCEPT

salsal@pc3:~$ sudo sed -i '/ufw-before-input.*icmp/s/ACCEPT/DROP/g' /etc/ufw/before.rules

salsal@pc3:~$ sudo grep ufw-before-input.*icmp /etc/ufw/before.rules
-A ufw-before-input -p icmp --icmp-type destination-unreachable -j DROP
-A ufw-before-input -p icmp --icmp-type time-exceeded -j DROP
-A ufw-before-input -p icmp --icmp-type parameter-problem -j DROP
-A ufw-before-input -p icmp --icmp-type echo-request -j DROP

salsal@pc3:~$ sudo ufw reload
Firewall reloaded

 

pc1, pc2에서 ping을 시도하면 성공하지 못하는 것을 알 수 있습니다. 

salsal@pc1:~$ ping 192.168.3.2 -c 1
PING 192.168.3.2 (192.168.3.2) 56(84) bytes of data.

--- 192.168.3.2 ping statistics ---
1 packets transmitted, 0 received, 100% packet loss, time 0ms
salsal@pc2:~$ ping 192.168.3.2 -c 1
PING 192.168.3.2 (192.168.3.2) 56(84) bytes of data.

--- 192.168.3.2 ping statistics ---
1 packets transmitted, 0 received, 100% packet loss, time 0ms

/etc/ufw/before.rules 에 있는 rule을 원복(DROP -> ACCEPT)하고 pc1, pc2에서 ping을 시도하면 성공하는 것을 알 수 있습니다.

 

1.2. 중간 시스템(intermediate system) r3 에서 설정하기

r3에서 pc3로 가는/향하는(traverse, passing) packet을 차단/허용하는 방법을 알아보겠습니다. 

  • source: pc2 (192.168.2.2) 에서 destination pc3 (192.168.3.2)로 가는 http request는 허용
  • 나머지 source에서 destination pc3 (192.168.3.2)로 가는 http request는 차단
  • pc3로 향하는 ssh는 모두 허용합니다. 

r3에서 먼저 ufw 를 활성화합니다.

r3에서 ufw를 활성화하기 전에 iptables 상태를 살펴보면 아래와 같습니다. 

salsal@r3:~$ sudo iptables -S
-P INPUT ACCEPT
-P FORWARD ACCEPT
-P OUTPUT ACCEPT

iptables에서

  • INPUT은 시스템으로 들어오는 패켓에 대한 정책을 적용하는 Chain입니다. 
  • OUTPUT은 시스템에서 발생되어 밖으로 나가는 패켓에 대한 정책을 적용하는 Chain입니다. 
  • FORWARD는 시스템을 경유하는 패켓에 대한 정책을 적용하는 Chain입니다. 

즉 위 출력결과를 보면 들어오는 incoming 패켓, 밖으로 나가는 outgoing 패켓, 경유하는 routed 패켓을 모두 허용하는 정책이라는 것을 알 수 있습니다.  

 

이제 ufw enable을 합니다. 

salsal@r3:~$ sudo ufw status
Status: inactive
salsal@r3:~$ sudo ufw enable
Command may disrupt existing ssh connections. Proceed with operation (y|n)? y
Firewall is active and enabled on system startup

salsal@r3:~$ sudo ufw status verbose
Status: active
Logging: on (low)
Default: deny (incoming), allow (outgoing), deny (routed)
New profiles: skip

default rule이 deny (incoming), allow (outgoing), deny (routed) 이 되며 r3는 local console에서만 접근 가능하므로 remote에서 접근할 수 없으니 주의합니다.

 

이 상태에서 iptables rule을 확인해 보면 아래와 같습니다. 매우 많은 chain과 rule을 추가된 것을 볼 수 있습니다. 

salsal@r3:~$ sudo iptables -S
-P INPUT DROP
-P FORWARD DROP
-P OUTPUT ACCEPT
-N ufw-after-forward
-N ufw-after-input
-N ufw-after-logging-forward
-N ufw-after-logging-input
-N ufw-after-logging-output
-N ufw-after-output
-N ufw-before-forward
-N ufw-before-input
-N ufw-before-logging-forward
-N ufw-before-logging-input
-N ufw-before-logging-output
-N ufw-before-output
-N ufw-logging-allow
-N ufw-logging-deny
-N ufw-not-local
-N ufw-reject-forward
-N ufw-reject-input
-N ufw-reject-output
-N ufw-skip-to-policy-forward
-N ufw-skip-to-policy-input
-N ufw-skip-to-policy-output
-N ufw-track-forward
-N ufw-track-input
-N ufw-track-output
-N ufw-user-forward
-N ufw-user-input
-N ufw-user-limit
-N ufw-user-limit-accept
-N ufw-user-logging-forward
-N ufw-user-logging-input
-N ufw-user-logging-output
-N ufw-user-output
-A INPUT -j ufw-before-logging-input
-A INPUT -j ufw-before-input
-A INPUT -j ufw-after-input
-A INPUT -j ufw-after-logging-input
-A INPUT -j ufw-reject-input
-A INPUT -j ufw-track-input
-A FORWARD -j ufw-before-logging-forward
-A FORWARD -j ufw-before-forward
-A FORWARD -j ufw-after-forward
-A FORWARD -j ufw-after-logging-forward
-A FORWARD -j ufw-reject-forward
-A FORWARD -j ufw-track-forward
-A OUTPUT -j ufw-before-logging-output
-A OUTPUT -j ufw-before-output
-A OUTPUT -j ufw-after-output
-A OUTPUT -j ufw-after-logging-output
-A OUTPUT -j ufw-reject-output
-A OUTPUT -j ufw-track-output
-A ufw-after-input -p udp -m udp --dport 137 -j ufw-skip-to-policy-input
-A ufw-after-input -p udp -m udp --dport 138 -j ufw-skip-to-policy-input
-A ufw-after-input -p tcp -m tcp --dport 139 -j ufw-skip-to-policy-input
-A ufw-after-input -p tcp -m tcp --dport 445 -j ufw-skip-to-policy-input
-A ufw-after-input -p udp -m udp --dport 67 -j ufw-skip-to-policy-input
-A ufw-after-input -p udp -m udp --dport 68 -j ufw-skip-to-policy-input
-A ufw-after-input -m addrtype --dst-type BROADCAST -j ufw-skip-to-policy-input
-A ufw-after-logging-forward -m limit --limit 3/min --limit-burst 10 -j LOG --log-prefix "[UFW BLOCK] "
-A ufw-after-logging-input -m limit --limit 3/min --limit-burst 10 -j LOG --log-prefix "[UFW BLOCK] "
-A ufw-before-forward -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A ufw-before-forward -p icmp -m icmp --icmp-type 3 -j ACCEPT
-A ufw-before-forward -p icmp -m icmp --icmp-type 11 -j ACCEPT
-A ufw-before-forward -p icmp -m icmp --icmp-type 12 -j ACCEPT
-A ufw-before-forward -p icmp -m icmp --icmp-type 8 -j ACCEPT
-A ufw-before-forward -j ufw-user-forward
-A ufw-before-input -i lo -j ACCEPT
-A ufw-before-input -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A ufw-before-input -m conntrack --ctstate INVALID -j ufw-logging-deny
-A ufw-before-input -m conntrack --ctstate INVALID -j DROP
-A ufw-before-input -p icmp -m icmp --icmp-type 3 -j ACCEPT
-A ufw-before-input -p icmp -m icmp --icmp-type 11 -j ACCEPT
-A ufw-before-input -p icmp -m icmp --icmp-type 12 -j ACCEPT
-A ufw-before-input -p icmp -m icmp --icmp-type 8 -j ACCEPT
-A ufw-before-input -p udp -m udp --sport 67 --dport 68 -j ACCEPT
-A ufw-before-input -j ufw-not-local
-A ufw-before-input -d 224.0.0.251/32 -p udp -m udp --dport 5353 -j ACCEPT
-A ufw-before-input -d 239.255.255.250/32 -p udp -m udp --dport 1900 -j ACCEPT
-A ufw-before-input -j ufw-user-input
-A ufw-before-output -o lo -j ACCEPT
-A ufw-before-output -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A ufw-before-output -j ufw-user-output
-A ufw-logging-allow -m limit --limit 3/min --limit-burst 10 -j LOG --log-prefix "[UFW ALLOW] "
-A ufw-logging-deny -m conntrack --ctstate INVALID -m limit --limit 3/min --limit-burst 10 -j RETURN
-A ufw-logging-deny -m limit --limit 3/min --limit-burst 10 -j LOG --log-prefix "[UFW BLOCK] "
-A ufw-not-local -m addrtype --dst-type LOCAL -j RETURN
-A ufw-not-local -m addrtype --dst-type MULTICAST -j RETURN
-A ufw-not-local -m addrtype --dst-type BROADCAST -j RETURN
-A ufw-not-local -m limit --limit 3/min --limit-burst 10 -j ufw-logging-deny
-A ufw-not-local -j DROP
-A ufw-skip-to-policy-forward -j DROP
-A ufw-skip-to-policy-input -j DROP
-A ufw-skip-to-policy-output -j ACCEPT
-A ufw-track-output -p tcp -m conntrack --ctstate NEW -j ACCEPT
-A ufw-track-output -p udp -m conntrack --ctstate NEW -j ACCEPT
-A ufw-user-limit -m limit --limit 3/min -j LOG --log-prefix "[UFW LIMIT BLOCK] "
-A ufw-user-limit -j REJECT --reject-with icmp-port-unreachable
-A ufw-user-limit-accept -j ACCEPT

salsal@r3:~$ sudo iptables -L
[sudo] password for salsal: 
Chain INPUT (policy DROP)
target     prot opt source               destination         
ufw-before-logging-input  all  --  anywhere             anywhere            
ufw-before-input  all  --  anywhere             anywhere            
ufw-after-input  all  --  anywhere             anywhere            
ufw-after-logging-input  all  --  anywhere             anywhere            
ufw-reject-input  all  --  anywhere             anywhere            
ufw-track-input  all  --  anywhere             anywhere            

Chain FORWARD (policy DROP)
target     prot opt source               destination         
ufw-before-logging-forward  all  --  anywhere             anywhere            
ufw-before-forward  all  --  anywhere             anywhere            
ufw-after-forward  all  --  anywhere             anywhere            
ufw-after-logging-forward  all  --  anywhere             anywhere            
ufw-reject-forward  all  --  anywhere             anywhere            
ufw-track-forward  all  --  anywhere             anywhere            

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         
ufw-before-logging-output  all  --  anywhere             anywhere            
ufw-before-output  all  --  anywhere             anywhere            
ufw-after-output  all  --  anywhere             anywhere            
ufw-after-logging-output  all  --  anywhere             anywhere            
ufw-reject-output  all  --  anywhere             anywhere            
ufw-track-output  all  --  anywhere             anywhere            

Chain ufw-after-forward (1 references)
target     prot opt source               destination         

Chain ufw-after-input (1 references)
target     prot opt source               destination         
ufw-skip-to-policy-input  udp  --  anywhere             anywhere             udp dpt:netbios-ns
ufw-skip-to-policy-input  udp  --  anywhere             anywhere             udp dpt:netbios-dgm
ufw-skip-to-policy-input  tcp  --  anywhere             anywhere             tcp dpt:netbios-ssn
ufw-skip-to-policy-input  tcp  --  anywhere             anywhere             tcp dpt:microsoft-ds
ufw-skip-to-policy-input  udp  --  anywhere             anywhere             udp dpt:bootps
ufw-skip-to-policy-input  udp  --  anywhere             anywhere             udp dpt:bootpc
ufw-skip-to-policy-input  all  --  anywhere             anywhere             ADDRTYPE match dst-type BROADCAST

Chain ufw-after-logging-forward (1 references)
target     prot opt source               destination         
LOG        all  --  anywhere             anywhere             limit: avg 3/min burst 10 LOG level warning prefix "[UFW BLOCK] "

Chain ufw-after-logging-input (1 references)
target     prot opt source               destination         
LOG        all  --  anywhere             anywhere             limit: avg 3/min burst 10 LOG level warning prefix "[UFW BLOCK] "

Chain ufw-after-logging-output (1 references)
target     prot opt source               destination         

Chain ufw-after-output (1 references)
target     prot opt source               destination         

Chain ufw-before-forward (1 references)
target     prot opt source               destination         
ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED
ACCEPT     icmp --  anywhere             anywhere             icmp destination-unreachable
ACCEPT     icmp --  anywhere             anywhere             icmp time-exceeded
ACCEPT     icmp --  anywhere             anywhere             icmp parameter-problem
ACCEPT     icmp --  anywhere             anywhere             icmp echo-request
ufw-user-forward  all  --  anywhere             anywhere            

Chain ufw-before-input (1 references)
target     prot opt source               destination         
ACCEPT     all  --  anywhere             anywhere            
ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED
ufw-logging-deny  all  --  anywhere             anywhere             ctstate INVALID
DROP       all  --  anywhere             anywhere             ctstate INVALID
ACCEPT     icmp --  anywhere             anywhere             icmp destination-unreachable
ACCEPT     icmp --  anywhere             anywhere             icmp time-exceeded
ACCEPT     icmp --  anywhere             anywhere             icmp parameter-problem
ACCEPT     icmp --  anywhere             anywhere             icmp echo-request
ACCEPT     udp  --  anywhere             anywhere             udp spt:bootps dpt:bootpc
ufw-not-local  all  --  anywhere             anywhere            
ACCEPT     udp  --  anywhere             224.0.0.251          udp dpt:mdns
ACCEPT     udp  --  anywhere             239.255.255.250      udp dpt:1900
ufw-user-input  all  --  anywhere             anywhere            

Chain ufw-before-logging-forward (1 references)
target     prot opt source               destination         

Chain ufw-before-logging-input (1 references)
target     prot opt source               destination         

Chain ufw-before-logging-output (1 references)
target     prot opt source               destination         

Chain ufw-before-output (1 references)
target     prot opt source               destination         
ACCEPT     all  --  anywhere             anywhere            
ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED
ufw-user-output  all  --  anywhere             anywhere            

Chain ufw-logging-allow (0 references)
target     prot opt source               destination         
LOG        all  --  anywhere             anywhere             limit: avg 3/min burst 10 LOG level warning prefix "[UFW ALLOW] "

Chain ufw-logging-deny (2 references)
target     prot opt source               destination         
RETURN     all  --  anywhere             anywhere             ctstate INVALID limit: avg 3/min burst 10
LOG        all  --  anywhere             anywhere             limit: avg 3/min burst 10 LOG level warning prefix "[UFW BLOCK] "

Chain ufw-not-local (1 references)
target     prot opt source               destination         
RETURN     all  --  anywhere             anywhere             ADDRTYPE match dst-type LOCAL
RETURN     all  --  anywhere             anywhere             ADDRTYPE match dst-type MULTICAST
RETURN     all  --  anywhere             anywhere             ADDRTYPE match dst-type BROADCAST
ufw-logging-deny  all  --  anywhere             anywhere             limit: avg 3/min burst 10
DROP       all  --  anywhere             anywhere            

Chain ufw-reject-forward (1 references)
target     prot opt source               destination         

Chain ufw-reject-input (1 references)
target     prot opt source               destination         

Chain ufw-reject-output (1 references)
target     prot opt source               destination         

Chain ufw-skip-to-policy-forward (0 references)
target     prot opt source               destination         
DROP       all  --  anywhere             anywhere            

Chain ufw-skip-to-policy-input (7 references)
target     prot opt source               destination         
DROP       all  --  anywhere             anywhere            

Chain ufw-skip-to-policy-output (0 references)
target     prot opt source               destination         
ACCEPT     all  --  anywhere             anywhere            

Chain ufw-track-forward (1 references)
target     prot opt source               destination         

Chain ufw-track-input (1 references)
target     prot opt source               destination         

Chain ufw-track-output (1 references)
target     prot opt source               destination         
ACCEPT     tcp  --  anywhere             anywhere             ctstate NEW
ACCEPT     udp  --  anywhere             anywhere             ctstate NEW

Chain ufw-user-forward (1 references)
target     prot opt source               destination         

Chain ufw-user-input (1 references)
target     prot opt source               destination         

Chain ufw-user-limit (0 references)
target     prot opt source               destination         
LOG        all  --  anywhere             anywhere             limit: avg 3/min burst 5 LOG level warning prefix "[UFW LIMIT BLOCK] "
REJECT     all  --  anywhere             anywhere             reject-with icmp-port-unreachable

Chain ufw-user-limit-accept (0 references)
target     prot opt source               destination         
ACCEPT     all  --  anywhere             anywhere            

Chain ufw-user-logging-forward (0 references)
target     prot opt source               destination         

Chain ufw-user-logging-input (0 references)
target     prot opt source               destination         

Chain ufw-user-logging-output (0 references)
target     prot opt source               destination         

Chain ufw-user-output (1 references)
target     prot opt source               destination

현재 상태에서 r3를 경유하는 패켓에 적용되는 Chain FORWARD만 살펴 봅니다. 

아래 내용을 보면 Chain FORWARD 의 기본 정책은 DROP입니다. r3를 경유하는 패켓에 대해 Chain FORWARD 밑에 있는 chain 6개를 차례 (ufw-before-logging-forward -> ufw-before-forward -> ufw-after-forward -> ufw-after-logging-forward -> ufw-reject-forward -> ufw-track-forward)로 검사합니다. chain 안의 rule과 일치하는 것이 없으면 다음 chain의 rule을 검사하는 방식입니다. 마지막 chain의 마지막 rule과 일치하는 것이 없으면 default policy인 DROP 즉 차단을 합니다. 

salsal@r3:~$ sudo iptables -Z		# counter를 모두 0으로 초기화

salsal@r3:~$ sudo iptables -L FORWARD -v
Chain FORWARD (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0 ufw-before-logging-forward  all  --  any    any     anywhere             anywhere
    0     0 ufw-before-forward  all  --  any    any     anywhere             anywhere
    0     0 ufw-after-forward  all  --  any    any     anywhere             anywhere
    0     0 ufw-after-logging-forward  all  --  any    any     anywhere             anywhere
    0     0 ufw-reject-forward  all  --  any    any     anywhere             anywhere
    0     0 ufw-track-forward  all  --  any    any     anywhere             anywhere

아래는 pc2에서 pc3로 http request를 보내고 차단되었을 때 chain FORWARD를 살펴본 것입니다. 즉 http request packet 4개가 chain 6개를 차례로 지나고 차단  (DROP 4 packets)되었다는 것을 알 수 있습니다. 

salsal@r3:~$ sudo iptables -L FORWARD -v
Chain FORWARD (policy DROP 4 packets, 240 bytes)
 pkts bytes target     prot opt in     out     source               destination
    4   240 ufw-before-logging-forward  all  --  any    any     anywhere             anywhere
    4   240 ufw-before-forward  all  --  any    any     anywhere             anywhere
    4   240 ufw-after-forward  all  --  any    any     anywhere             anywhere
    4   240 ufw-after-logging-forward  all  --  any    any     anywhere             anywhere
    4   240 ufw-reject-forward  all  --  any    any     anywhere             anywhere
    4   240 ufw-track-forward  all  --  any    any     anywhere             anywhere

salsal@r3:~$ sudo grep 'DPT=80' /var/log/ufw.log    
Aug  1 16:55:24 r3 kernel: [ 1723.814562] [UFW BLOCK] IN=enp0s10 OUT=enp0s8 MAC=08:00:27:f2:19:0d:08:00:27:6a:e2:a9:08:00 SRC=192.168.2.2 DST=192.168.3.2 LEN=60 TOS=0x00 PREC=0x00 TTL=62 ID=27957 DF PROTO=TCP SPT=37264 DPT=80 WINDOW=64240 RES=0x00 SYN URGP=0
Aug  1 16:55:25 r3 kernel: [ 1724.837564] [UFW BLOCK] IN=enp0s10 OUT=enp0s8 MAC=08:00:27:f2:19:0d:08:00:27:6a:e2:a9:08:00 SRC=192.168.2.2 DST=192.168.3.2 LEN=60 TOS=0x00 PREC=0x00 TTL=62 ID=27958 DF PROTO=TCP SPT=37264 DPT=80 WINDOW=64240 RES=0x00 SYN URGP=0
Aug  1 16:55:27 r3 kernel: [ 1726.853261] [UFW BLOCK] IN=enp0s10 OUT=enp0s8 MAC=08:00:27:f2:19:0d:08:00:27:6a:e2:a9:08:00 SRC=192.168.2.2 DST=192.168.3.2 LEN=60 TOS=0x00 PREC=0x00 TTL=62 ID=27959 DF PROTO=TCP SPT=37264 DPT=80 WINDOW=64240 RES=0x00 SYN URGP=0
Aug  1 16:55:31 r3 kernel: [ 1730.946724] [UFW BLOCK] IN=enp0s10 OUT=enp0s8 MAC=08:00:27:f2:19:0d:08:00:27:6a:e2:a9:08:00 SRC=192.168.2.2 DST=192.168.3.2 LEN=60 TOS=0x00 PREC=0x00 TTL=62 ID=27960 DF PROTO=TCP SPT=37264 DPT=80 WINDOW=64240 RES=0x00 SYN URGP=0

아래는 Chain FORWARD에 있는 chain 6개를 살펴본 내용입니다. 

  • Chain ufw-before-logging-forward: 기본으로 정의한 rule이 없습니다. 따라서 다음 Chain ufw-before-forward 을 검사합니다. 
  • Chain ufw-before-forward: 이미 연결되어 있는 것과 icmp message를 통과(ACCEPT)시킵니다. 이용자 정의 chain ufw-user-forward를 검사합니다. 일치하는 것이 없으면 다음 Chain ufw-after-forward 을 검사합니다. 
  • Chain ufw-after-forward: 기본으로 정의한 rule이 없습니다. 따라서 다음 Chain ufw-after-logging-forward를 검사합니다. 
  • Chain ufw-after-logging-forward: log 파일에 기록을 남깁니다. 그리고 나서 다음 Chain ufw-reject-forward를 검사합니다. 
  • Chain ufw-reject-forward: 기본으로 정의한 rule이 없습니다. 따라서 다음 Chain ufw-track-forward를 검사합니다. 
  • Chain ufw-track-forward: 기본으로 정의한 rule이 없습니다. 따라서 다음 Chain 이 없으므로 default policy인 DROP에 따라 차단을 합니다. 
salsal@r3:~$ sudo iptables -L ufw-before-logging-forward -v
Chain ufw-before-logging-forward (1 references)
 pkts bytes target     prot opt in     out     source               destination

salsal@r3:~$ sudo iptables -L ufw-before-forward -v
Chain ufw-before-forward (1 references)
 pkts bytes target     prot opt in     out     source               destination
    0     0 ACCEPT     all  --  any    any     anywhere             anywhere             ctstate RELATED,ESTABLISHED
    0     0 ACCEPT     icmp --  any    any     anywhere             anywhere             icmp destination-unreachable
    0     0 ACCEPT     icmp --  any    any     anywhere             anywhere             icmp time-exceeded
    0     0 ACCEPT     icmp --  any    any     anywhere             anywhere             icmp parameter-problem
    0     0 ACCEPT     icmp --  any    any     anywhere             anywhere             icmp echo-request
    0     0 ufw-user-forward  all  --  any    any     anywhere             anywhere
   
salsal@r3:~$ sudo iptables -L ufw-after-forward -v
Chain ufw-after-forward (1 references)
 pkts bytes target     prot opt in     out     source               destination

salsal@r3:~$ sudo iptables -L ufw-after-logging-forward -v
Chain ufw-after-logging-forward (1 references)
 pkts bytes target     prot opt in     out     source               destination
    4   240 LOG        all  --  any    any     anywhere             anywhere             limit: avg 3/min burst 10 LOG level warning prefix "[UFW BLOCK] "

salsal@r3:~$ sudo iptables -L ufw-reject-forward -v
Chain ufw-reject-forward (1 references)
 pkts bytes target     prot opt in     out     source               destination

salsal@r3:~$ sudo iptables -L ufw-track-forward -v
Chain ufw-track-forward (1 references)
 pkts bytes target     prot opt in     out     source               destination
 
 salsal@r3:~$ sudo iptables -L ufw-user-forward -v
Chain ufw-user-forward (1 references)
 pkts bytes target     prot opt in     out     source               destination

눈여겨 봐야 할 FORWARD chain은 ufw-user-forward 입니다. ufw 로 이용자가 설정한 내용이 여기에 추가됩니다. 

salsal@r3:~$ sudo ufw route allow http
Rule added
Rule added (v6)

salsal@r3:~$ sudo iptables -L ufw-user-forward -v
Chain ufw-user-forward (1 references)
 pkts bytes target     prot opt in     out     source               destination
    1    60 ACCEPT     tcp  --  any    any     anywhere             anywhere             tcp dpt:http

마찬가지로 눈여겨 봐야 할 INPUT chain은 ufw-user-input 입니다. ufw 로 이용자가 설정한 내용이 여기에 추가됩니다. 

salsal@r3:~$ sudo ufw allow ssh
Rule added
Rule added (v6)

salsal@r3:~$ sudo iptables -L ufw-user-input -v
Chain ufw-user-input (1 references)
 pkts bytes target     prot opt in     out     source               destination
    2    88 ACCEPT     tcp  --  any    any     anywhere             anywhere             tcp dpt:ssh

 

ip forwarding를 활성화합니다. 

먼저 현재 상태를 확인합니다. net.ipv4.ip_forward = 0은 비활성 상태를 의미합니다. 이것을 1로 변경해야 합니다. sysctl 명령어를 이용해 확인합니다. 

salsal@r3:~$ sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 0

salsal@r3:~$ sysctl -a --pattern net.ipv4.ip_forward$
net.ipv4.ip_forward = 0

sysctl 명령어를 이용해 값을 바꿉니다. 

salsal@r3:~$ sudo sysctl -w net.ipv4.ip_forward=0
net.ipv4.ip_forward = 0

salsal@r3:~$ sudo sysctl -w net.ipv4.ip_forward=1
net.ipv4.ip_forward = 1

※ r3를 리부팅하면 net.ipv4.ip_forward = 0 으로 다시 돌아갑니다. net.ipv4.ip_forward = 1 을 계속 유지하려면 파일 /etc/sysctl.conf 에서 net.ipv4.ip_forward=1 을 추가하거나 # 을 삭제해 주면 됩니다. 

 

현재 값을 확인합니다. 

salsal@r3:~$ sudo grep net.ipv4.ip_forward /etc/sysctl.conf
#net.ipv4.ip_forward=1

sed를 이용해 수정합니다. 

salsal@r3:~$ sudo sed -i '/#net.ipv4.ip_forward/s/#//g' /etc/sysctl.conf
salsal@r3:~$ sudo grep net.ipv4.ip_forward /etc/sysctl.conf
net.ipv4.ip_forward=1

참고사항 (비활성화하는 방법)

salsal@r3:~$ sudo sed -i '/net.ipv4.ip_forward/s/^/#/g' /etc/sysctl.conf
salsal@r3:~$ sudo grep net.ipv4.ip_forward /etc/sysctl.conf
#net.ipv4.ip_forward=1

ufw를 활성화하면 iptables 이 변합니다. 

salsal@r3:~$ sudo ufw status verbose
Status: active
Logging: on (low)
Default: deny (incoming), allow (outgoing), deny (routed)
New profiles: skip

 

pc2 (192.168.2.2) 에서 destination pc3 (192.168.3.2)로 가는 http request는 허용합니다. 

r3에서 ufw enable 하고 r3에 연결하기 위한 ssh만 허용하고, 다른 rule은 설정하지 않았다고 가정합니다. 

salsal@r3:~$ sudo ufw status numbered
Status: active

     To                         Action      From
     --                         ------      ----
[ 1] 22/tcp                     ALLOW IN    Anywhere
[ 2] 22/tcp (v6)                ALLOW IN    Anywhere (v6)

salsal@r3:~$ sudo iptables -L FORWARD -v
Chain FORWARD (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0 ufw-before-logging-forward  all  --  any    any     anywhere             anywhere
    0     0 ufw-before-forward  all  --  any    any     anywhere             anywhere
    0     0 ufw-after-forward  all  --  any    any     anywhere             anywhere
    0     0 ufw-after-logging-forward  all  --  any    any     anywhere             anywhere
    0     0 ufw-reject-forward  all  --  any    any     anywhere             anywhere
    0     0 ufw-track-forward  all  --  any    any     anywhere             anywhere

salsal@r3:~$ sudo iptables -L INPUT -v
Chain INPUT (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
  148  8144 ufw-before-logging-input  all  --  any    any     anywhere             anywhere
  148  8144 ufw-before-input  all  --  any    any     anywhere             anywhere
    0     0 ufw-after-input  all  --  any    any     anywhere             anywhere
    0     0 ufw-after-logging-input  all  --  any    any     anywhere             anywhere
    0     0 ufw-reject-input  all  --  any    any     anywhere             anywhere
    0     0 ufw-track-input  all  --  any    any     anywhere             anywhere
    
salsal@r3:~$ sudo iptables -L ufw-user-input -v
Chain ufw-user-input (1 references)
 pkts bytes target     prot opt in     out     source               destination
    0     0 ACCEPT     tcp  --  any    any     anywhere             anywhere             tcp dpt:ssh

Chain FORWARD에서 192.168.2.2 -> 192.168.3.2/http를 허용하는 rule을 추가합니다. 

salsal@r3:~$ sudo iptables -L ufw-user-forward -v
Chain ufw-user-forward (1 references)
 pkts bytes target     prot opt in     out     source               destination

salsal@r3:~$ sudo ufw route allow from 192.168.2.2 to 192.168.3.2 port http
Rule added

salsal@r3:~$ sudo iptables -L ufw-user-forward -v
Chain ufw-user-forward (1 references)
 pkts bytes target     prot opt in     out     source               destination
    0     0 ACCEPT     tcp  --  any    any     192.168.2.2          192.168.3.2   tcp dpt:http
    
salsal@r3:~$ sudo ufw status numbered
Status: active

     To                         Action      From
     --                         ------      ----
[ 1] 22/tcp                     ALLOW IN    Anywhere
[ 2] 192.168.3.2 80/tcp         ALLOW FWD   192.168.2.2
[ 3] 22/tcp (v6)                ALLOW IN    Anywhere (v6)

192.168.2.2 에서 192.168.3.2로 http request를 시도하면 성공하며, chain을 확인해 봅니다. 

salsal@r3:~$ sudo iptables -L FORWARD -v
Chain FORWARD (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
   12 12007 ufw-before-logging-forward  all  --  any    any     anywhere             anywhere
   12 12007 ufw-before-forward  all  --  any    any     anywhere             anywhere
    0     0 ufw-after-forward  all  --  any    any     anywhere             anywhere
    0     0 ufw-after-logging-forward  all  --  any    any     anywhere             anywhere
    0     0 ufw-reject-forward  all  --  any    any     anywhere             anywhere
    0     0 ufw-track-forward  all  --  any    any     anywhere             anywhere

salsal@r3:~$ sudo iptables -L ufw-before-forward -v
Chain ufw-before-forward (1 references)
 pkts bytes target     prot opt in     out     source               destination
   15 12155 ACCEPT     all  --  any    any     anywhere             anywhere             ctstate RELATED,ESTABLISHED
    0     0 ACCEPT     icmp --  any    any     anywhere             anywhere             icmp destination-unreachable
    0     0 ACCEPT     icmp --  any    any     anywhere             anywhere             icmp time-exceeded
    0     0 ACCEPT     icmp --  any    any     anywhere             anywhere             icmp parameter-problem
    0     0 ACCEPT     icmp --  any    any     anywhere             anywhere             icmp echo-request
    1    60 ufw-user-forward  all  --  any    any     anywhere             anywhere

salsal@r3:~$ sudo iptables -L ufw-user-forward -v
Chain ufw-user-forward (1 references)
 pkts bytes target     prot opt in     out     source               destination
    1    60 ACCEPT     tcp  --  any    any     192.168.2.2          192.168.3.2          tcp dpt:http

 

나머지 source에서 destination pc3 (192.168.3.2)로 가는 http request는 자동으로 차단됩니다. 

 

경유하는 ssh를 모두 허용합니다. 

salsal@r3:~$ sudo ufw route allow to any port ssh
Rule added
Rule added (v6)
salsal@r3:~$ sudo ufw status numbered
Status: active

     To                         Action      From
     --                         ------      ----
[ 1] 22/tcp                     ALLOW IN    Anywhere
[ 2] 192.168.3.2 80/tcp         ALLOW FWD   192.168.2.2
[ 3] 22/tcp                     ALLOW FWD   Anywhere
[ 4] 22/tcp (v6)                ALLOW IN    Anywhere (v6)
[ 5] 22/tcp (v6)                ALLOW FWD   Anywhere (v6)

이제 pc2에서 pc3로 ssh 를 할 수 있습니다. 

salsal@pc2:~$ ssh salsal@192.168.3.2
salsal@192.168.3.2's password:

salsal@pc2:~$ ssh salsal@192.168.3.2
salsal@192.168.3.2's password:
Welcome to Ubuntu 18.04.5 LTS (GNU/Linux 5.4.0-80-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

0 updates can be applied immediately.

New release '20.04.2 LTS' available.
Run 'do-release-upgrade' to upgrade to it.

Your Hardware Enablement Stack (HWE) is supported until April 2023.
Last login: Sun Aug  1 12:09:14 2021 from 10.0.2.2
salsal@pc3:~$

r3에서 chain을 확인해 보면 일치한 pkts count (2)가 증가한 것을 확인할 수 있습니다. 

salsal@r3:~$ sudo iptables -L ufw-user-forward -v
Chain ufw-user-forward (1 references)
 pkts bytes target     prot opt in     out     source               destination
    1    60 ACCEPT     tcp  --  any    any     192.168.2.2          192.168.3.2          tcp dpt:http
    2   120 ACCEPT     tcp  --  any    any     anywhere             anywhere             tcp dpt:ssh

 

2. iptables

※ IPTABLES란 무엇일까요? 를 먼저 읽고 table, chain 개념을 먼저 이해해야 합니다. 

 

Ubuntu 시스템은 Kernel에 iptables 기능을 기본으로 포함하고 있습니다. 아무 설정도 하지 않으면 다음과 같은 기본 상태로 들어오고(INPUT), 나가고(OUTPUT), 전달하는(FORWARD) 모든 패켓에 대해 허용(ACCEPT)하는 상태입니다. 

 

PC2

salsal@pc2:~$ sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 0

salsal@pc2:~$ sudo iptables -S
-P INPUT ACCEPT
-P FORWARD ACCEPT
-P OUTPUT ACCEPT

R2

salsal@r2:~$ sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 1          # zebra에서 ip forwarding을 설정해서 1. 0이라면 1로 수정

salsal@r2:~$ sudo iptables -S
-P INPUT ACCEPT
-P FORWARD ACCEPT
-P OUTPUT ACCEPT

R3

salsal@r3:~$ sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 1		# zebra에서 ip forwarding을 설정해서 1. 0이라면 1로 수정

salsal@r3:~$ sudo iptables -S
-P INPUT ACCEPT
-P FORWARD ACCEPT
-P OUTPUT ACCEPT

PC3

salsal@pc3:~$ sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 0

salsal@pc3:~$ sudo iptables -S
-P INPUT ACCEPT
-P FORWARD ACCEPT
-P OUTPUT ACCEPT

sysctl 명령어를 이용해 net.ipv4.ip_forward 값을 변경하는 방법입니다. 

salsal@r3:~$ sudo sysctl -w net.ipv4.ip_forward=0
net.ipv4.ip_forward = 0

salsal@r3:~$ sudo sysctl -w net.ipv4.ip_forward=1
net.ipv4.ip_forward = 1

 

pc2, pc3, r2, r3에서 ufw disable을 하고 reboot 하고 시작합니다. reboot하고 나니 iptables에 default chain 3개 (INPUT, FORWARD, OUTPUT)만 있는 것을 알 수 있고, default policy마저 ACCEPT인 것을 알 수 있습니다. 

salsal@pc2:~$ sudo iptables -L -v
Chain INPUT (policy ACCEPT 7 packets, 409 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 5 packets, 473 bytes)
 pkts bytes target     prot opt in     out     source               destination
 
 salsal@r2:~$ sudo iptables -L -v
Chain INPUT (policy ACCEPT 6 packets, 336 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 12 packets, 912 bytes)
 pkts bytes target     prot opt in     out     source               destination
 
salsal@r3:~$ sudo iptables -L -v
Chain INPUT (policy ACCEPT 50 packets, 2864 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 26 packets, 2064 bytes)
 pkts bytes target     prot opt in     out     source               destination

salsal@pc3:~$ sudo iptables -L -v
Chain INPUT (policy ACCEPT 17 packets, 952 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 11 packets, 1092 bytes)
 pkts bytes target     prot opt in     out     source               destination

 

여기에서는 ufw를 이용하지 않고 (disable 상태) iptables 명령어를 이용하여 Chain에 필요한 rule을 추가/삭제하는 것을 해 보겠습니다. 설정은 r3에서 다음과 같은 것을 하는 것입니다.

  • 목적지가 r3인 ssh는 허용합니다. 
  • 이미 연결되어 있는 connection은 유지합니다. 
  • r3를 경유하는 icmp는 허용합니다. 
  • ssh에 대해서만 pc2가 pc3에 접근하게 합니다.  
  • pc3에 대해서는 http만 허용합니다.  
salsal@r3:~$ sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT
salsal@r3:~$ sudo iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
salsal@r3:~$ sudo iptables -A INPUT -i lo -j ACCEPT
salsal@r3:~$ sudo iptables -A INPUT -p icmp -j ACCEPT
salsal@r3:~$ sudo iptables -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
salsal@r3:~$ sudo iptables -A FORWARD -s 192.168.2.2/32 -d 192.168.3.2/32 -p tcp --dport 22 -j ACCEPT
salsal@r3:~$ sudo iptables -A FORWARD -d 192.168.3.2/32 -p tcp --dport 80 -j ACCEPT
salsal@r3:~$ sudo iptables -A FORWARD -p icmp -j ACCEPT
salsal@r3:~$ sudo iptables -P INPUT DROP
salsal@r3:~$ sudo iptables -P FORWARD DROP

salsal@r3:~$ sudo iptables -S
-P INPUT DROP
-P FORWARD DROP
-P OUTPUT ACCEPT
-A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -s 192.168.2.2/32 -d 192.168.3.2/32 -p tcp -m tcp --dport 22 -j ACCEPT
-A FORWARD -d 192.168.3.2/32 -p tcp -m tcp --dport 80 -j ACCEPT
-A FORWARD -p icmp -j ACCEPT

 

하나하나 의미를 살펴보겠습니다. 

 

chain INPUT을 이용하므로 r3로 향하는 패켓에 대해 적용하는 것입니다. r3로 향하는 tcp/22 (ssh)를 허용합니다. 

salsal@r3:~$ sudo iptables -A INPUT -p tcp -m tcp --dport 22 -j ACCEPT

 

r3에서 외부에 연결한 것에 대한 응답 패켓을 허용합니다. 

salsal@r3:~$ sudo iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT

 

r3의 loopback interface로 향하는 패켓을 허용합니다. 

salsal@r3:~$ sudo iptables -A INPUT -i lo -j ACCEPT

 

r3로 향하는 icmp 패켓을 허용합니다. 

salsal@r3:~$ sudo iptables -A INPUT -p icmp -j ACCEPT

 

r3를 경유하는 패켓중에 response 패켓을 허용합니다. r3가 session table을 관리한다면 유효한 rule입니다. 

salsal@r3:~$ sudo iptables -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT

 

pc2에서 pc3로 향하는 ssh를 허용합니다. 

salsal@r3:~$ sudo iptables -A FORWARD -s 192.168.2.2/32 -d 192.168.3.2/32 -p tcp --dport 22 -j ACCEPT

 

pc3로 향하는 http를 허용합니다. 

salsal@r3:~$ sudo iptables -A FORWARD -d 192.168.3.2/32 -p tcp --dport 80 -j ACCEPT

 

r3를 경유하는 icmp를 허용합니다. 

salsal@r3:~$ sudo iptables -A FORWARD -p icmp -j ACCEPT

 

Chain INPUT과 FORWARD의 default policy를 DROP으로 설정합니다. 

salsal@r3:~$ sudo iptables -P INPUT DROP
salsal@r3:~$ sudo iptables -P FORWARD DROP

 

iptables은 리부팅을 하면 사라집니다. 따라서 애써 설정한 rule을 리부팅 뒤에도 유지할 수 있게 해야 합니다. 그 과정은 "Ubuntu iptables 저장, 리부팅 뒤 자동 복구"를 참고하면 됩니다. 

 

3. nftables

nftables 이란 / The netfilter.org project 을 참고합니다. 

 

다만 아래 글은 왜 필자가 nftables에 관심을 가지게 되었는지 알려주는 글입니다. 

http://linforum.kr/bbs/board.php?bo_table=security&wr_id=103 

 

iptables 대신 nftables 사용하기

웹의 많은 공격 유형은 서버가 처리할 수 있는 한계점을 넘어서게 하는 DoS 공격을 수행하는 것입니다. 하지만 우리가 간과하고 넘어갈 수 있는 부분 중에 하나에는 iptables의 사용이 있습니다. ipt

linforum.kr

 

 

 

다음 글: nftables 이란 / The netfilter.org project

'iptables' 카테고리의 다른 글

Ubuntu에서 iptables을 이용한 NAT  (0) 2021.08.11
ipset  (0) 2021.08.11
Ubuntu iptables 저장, 리부팅 뒤 자동 복구  (0) 2021.08.01