다음 글: 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' 카테고리의 다른 글
Ubuntu에서 iptables을 이용한 NAT (0) | 2021.08.11 |
---|---|
ipset (0) | 2021.08.11 |
Ubuntu iptables 저장, 리부팅 뒤 자동 복구 (0) | 2021.08.01 |