第 132 回関西 Debian 勉強会で ufw についての発表をしました。 その資料のファイル形式を変換したものです。
はじめに
ufw はバージョンアップに伴い、機能が追加されてできることが増えています。 そこで、現在の Debian の stable である stretch に入っている ufw 0.35-4 を元に基本的な機能やちょっと複雑なネットワークでの使用方法を紹介します。
ufw とは?
iptables のラッパーのようなもので、ファイアウォールの設定を簡単にできるようにするためのものです。 ちなみに名前の ufw は Uncomplicated Firewall の略で、Ubuntu Firewall ではありません。
使用開始
まず「ufw enable」で有効にします。 (「ufw disable」で戻せます。) 有効にするとすぐに反映されて、次回起動時からも有効になります。 ssh で接続している場合は、「ufw enable」の前に、そのポートを許可しておくと良いでしょう。 最近は大丈夫のようですが、昔は enable した直後に反応がなくなって切れてしまうことがあったので、再接続できるように許可しておいたり、他の接続手段も確保しておいたりしておく方が安全です。
$ sudo ufw allow 22/tcp
Rules updated
Rules updated (v6)
$ sudo ufw enable
Command may disrupt existing ssh connections. Proceed with operation (y|n)? y
Firewall is active and enabled on system startup
デフォルトの挙動
デフォルトでは外向きは許可、内向きは拒否という一般的に推奨される構成になっています。 許可などの設定は IP アドレスなどの指定がない場合、IPv4 と IPv6 の両方を同時に設定できるので、iptables と ip6tables を別々に設定して二度手間になるようなことがありません。
基本的な使い方
ポート番号のみを指定すると TCP/UDP 両方許可できます。 例えば DNS なら、以下のようになります。
$ sudo ufw allow 53
Rule added
Rule added (v6)
TCP のみ許可するには「ポート番号/tcp」と指定します。 例えば http なら、以下のようになります。
$ sudo ufw allow 80/tcp
Rule added
Rule added (v6)
UDP のみ許可するには「ポート番号/udp」と指定します。 ポート番号には「:」区切りで範囲を指定できます。 例えば mosh で使われる範囲を許可するなら、以下のようになります。
$ sudo ufw allow 60000:61000/udp
Rule added
Rule added (v6)
連続しないポート番号を「,」区切りでまとめて指定することもできます。 (「,」で区切られた中に範囲を指定することもできます。) 例えば SMTP などを許可するなら、以下のようになります。
$ sudo ufw allow 25,465,587/tcp
Rule added
Rule added (v6)
設定確認
「ufw status」で設定を確認できます。 「ufw status verbose」でデフォルトポリシーなどを含めた設定の確認ができます。 「ufw status numbered」で delete や insert で使う番号が確認できます。
$ sudo ufw status
Status: active
To Action From
-- ------ ----
22/tcp ALLOW Anywhere
53 ALLOW Anywhere
80/tcp ALLOW Anywhere
60000:61000/udp ALLOW Anywhere
25,465,587/tcp ALLOW Anywhere
22/tcp (v6) ALLOW Anywhere (v6)
53 (v6) ALLOW Anywhere (v6)
80/tcp (v6) ALLOW Anywhere (v6)
60000:61000/udp (v6) ALLOW Anywhere (v6)
25,465,587/tcp (v6) ALLOW Anywhere (v6)
$ sudo ufw status verbose
Status: active
Logging: on (low)
Default: deny (incoming), allow (outgoing), disabled (routed)
New profiles: skip
To Action From
-- ------ ----
22/tcp ALLOW IN Anywhere
53 ALLOW IN Anywhere
80/tcp ALLOW IN Anywhere
60000:61000/udp ALLOW IN Anywhere
25,465,587/tcp ALLOW IN Anywhere
22/tcp (v6) ALLOW IN Anywhere (v6)
53 (v6) ALLOW IN Anywhere (v6)
80/tcp (v6) ALLOW IN Anywhere (v6)
60000:61000/udp (v6) ALLOW IN Anywhere (v6)
25,465,587/tcp (v6) ALLOW IN Anywhere (v6)
$ sudo ufw status numbered
Status: active
To Action From
-- ------ ----
[ 1] 22/tcp ALLOW IN Anywhere
[ 2] 53 ALLOW IN Anywhere
[ 3] 80/tcp ALLOW IN Anywhere
[ 4] 60000:61000/udp ALLOW IN Anywhere
[ 5] 25,465,587/tcp ALLOW IN Anywhere
[ 6] 22/tcp (v6) ALLOW IN Anywhere (v6)
[ 7] 53 (v6) ALLOW IN Anywhere (v6)
[ 8] 80/tcp (v6) ALLOW IN Anywhere (v6)
[ 9] 60000:61000/udp (v6) ALLOW IN Anywhere (v6)
[10] 25,465,587/tcp (v6) ALLOW IN Anywhere (v6)
ルールの削除
「ufw delete 追加した時のルール」や「ufw delete ルール番号」でルールを削除できます。
$ sudo ufw delete allow 25,465,587/tcp
Rule deleted
Rule deleted (v6)
$ sudo ufw delete allow 60000:61000/udp
Rule deleted
Rule deleted (v6)
ルールの表記方法
今まで使ってきた「ufw [–dry-run] [delete] [insert NUM] allow|deny|reject|limit [in|out] [log|log-all] [ PORT[/PROTOCOL] | APP‐NAME ] [comment COMMENT]」という省略記法の他に、「ufw [–dry-run] [rule] [delete] [insert NUM] allow|deny|reject|limit [in|out [on INTERFACE]] [log|log-all] [proto PROTOCOL] [from ADDRESS [port PORT | app APPNAME ]] [to ADDRESS [port PORT | app APPNAME ]] [comment COMMENT]」という細かく指定する書き方もあります。 IP アドレスを指定するには後者の表記方法を使う必要があります。 詳細は man を参照してください。
特定 IP アドレスのみ拒否
前述のように IP アドレスを指定するには「ポート番号/プロトコル」という指定の仕方では無理なので、細かく指定していきます。 また、許可より前に拒否するルールがないといけないので、「insert」 を使います。ここで先ほどの「ufw status numbered」の出力をみると 3 より前にあれば良いとわかるので、「insert 3」と指定します。 ポート番号を指定するときは IP アドレスの指定は必須なので、特に制限する必要がないときは「any」を使います。
$ sudo ufw insert 3 deny from 192.0.2.0/24 to any port 80 proto tcp
Rule inserted
$ sudo ufw status numbered
Status: active
To Action From
-- ------ ----
[ 1] 22/tcp ALLOW IN Anywhere
[ 2] 53 ALLOW IN Anywhere
[ 3] 80/tcp DENY IN 192.0.2.0/24
[ 4] 80/tcp ALLOW IN Anywhere
[ 5] 22/tcp (v6) ALLOW IN Anywhere (v6)
[ 6] 53 (v6) ALLOW IN Anywhere (v6)
[ 7] 80/tcp (v6) ALLOW IN Anywhere (v6)
$ sudo ufw delete deny from 192.0.2.0/24 to any port 80 proto tcp
Rule deleted
$ sudo ufw insert 3 deny from 192.0.2.0/24 to any port 80 proto tcp
Rule inserted
$ sudo ufw delete 3
Deleting:
deny from 192.0.2.0/24 to any port 80 proto tcp
Proceed with operation (y|n)? y
Rule deleted
「from」で IPv4 アドレスを指定したので、ルールは自動的に IPv4 の方だけになって IPv6 には何も影響していません。
on INTERFACE
特定のネットワークインターフェイスを通るパケットだけ対象にしたい場合は「on INTERFACE」を使います。 例えばプロキシを必須にするなどで外部の 80,443 は直接繋がせない、とする場合は以下のようになります。 外部への通信なので「out」もつけています。
また、内部から外部への通信は「deny」で無視すると応答がなくなって、タイムアウト待ちなどでトラブルシューティングに時間がかかるので、すぐに拒否される「reject」を使うのがおすすめです。
インターフェイスは iptables と同様に「ppp+」で「ppp0」や「ppp1」などをまとめて指定できます。 そのため「enp0s3」だったり「ens3」だったりする stretch では「en+」でまとめて指定するとハードウェア構成に依存せずに設定を共有しやすくなると思います。
$ sudo ufw reject out on en+ to any port 80,443 proto tcp
Rule added
Rule added (v6)
$ sudo ufw status
Status: active
To Action From
-- ------ ----
22/tcp ALLOW Anywhere
53 ALLOW Anywhere
80/tcp ALLOW Anywhere
22/tcp (v6) ALLOW Anywhere (v6)
53 (v6) ALLOW Anywhere (v6)
80/tcp (v6) ALLOW Anywhere (v6)
80,443/tcp REJECT OUT Anywhere on en+
80,443/tcp (v6) REJECT OUT Anywhere (v6) on en+
$ curl --head www.debian.org
curl: (7) Failed to connect to www.debian.org port 80: Connection refused
$ sudo ufw delete reject out on en+ to any port 80,443 proto tcp
Rule deleted
Rule deleted (v6)
deny だと応答がなくなったので Ctrl+C で止めました。
$ sudo ufw deny out on en+ to any port 80,443 proto tcp
Rule added
Rule added (v6)
$ curl --head www.debian.org
^C
$ sudo ufw delete deny out on en+ to any port 80,443 proto tcp
Rule deleted
Rule deleted (v6)
アプリケーションで指定
「/etc/ufw/applications.d/」にアプリケーション名で設定するための情報が入っていて、「sudo ufw app list」で一覧できます。
$ sudo ufw app list
Available applications:
AIM
Bonjour
CIFS
DNS
Deluge
IMAP
IMAPS
IPP
KTorrent
Kerberos Admin
Kerberos Full
Kerberos KDC
Kerberos Password
LDAP
LDAPS
LPD
MSN
MSN SSL
Mail submission
NFS
OpenSSH
POP3
POP3S
PeopleNearby
SMTP
SSH
Socks
Telnet
Transmission
Transparent Proxy
VNC
WWW
WWW Cache
WWW Full
WWW Secure
XMPP
Yahoo
qBittorrent
svnserve
$ ls /etc/ufw/applications.d/
openssh-server ufw-chat ufw-dnsserver ufw-loginserver ufw-printserver ufw-webserver
ufw-bittorent ufw-directoryserver ufw-fileserver ufw-mailserver ufw-proxyserver
$ cat /etc/ufw/applications.d/openssh-server
[OpenSSH]
title=Secure shell server, an rshd replacement
description=OpenSSH is a free implementation of the Secure Shell protocol.
ports=22/tcp
$ cat /etc/ufw/applications.d/ufw-webserver
[WWW]
title=Web Server
description=Web server
ports=80/tcp
[WWW Secure]
title=Web Server (HTTPS)
description=Web Server (HTTPS)
ports=443/tcp
[WWW Full]
title=Web Server (HTTP,HTTPS)
description=Web Server (HTTP,HTTPS)
ports=80,443/tcp
[WWW Cache]
title=Web Server (8080)
description=Web Server (8080)
ports=8080/tcp
アプリ名をポート番号とプロトコルの組み合わせの代わりに使うことができます。 スペースが入っているアプリ名の場合はシェルで引数が分割されないようにクォートする必要があるので、注意が必要です。
$ sudo ufw reject out OpenSSH
Rule added
Rule added (v6)
$ sudo ufw reject out to 10.0.0.0/8 app 'WWW Full'
Rule added
$ sudo ufw status
Status: active
To Action From
-- ------ ----
22/tcp ALLOW Anywhere
53 ALLOW Anywhere
80/tcp ALLOW Anywhere
22/tcp (v6) ALLOW Anywhere (v6)
53 (v6) ALLOW Anywhere (v6)
80/tcp (v6) ALLOW Anywhere (v6)
OpenSSH REJECT OUT Anywhere
10.0.0.0/8 WWW Full REJECT OUT Anywhere
OpenSSH (v6) REJECT OUT Anywhere (v6)
$ sudo ufw delete reject out to 10.0.0.0/8 app WWW Full
ERROR: Wrong number of arguments
$ sudo ufw delete reject out to 10.0.0.0/8 app 'WWW Full'
Rule deleted
$ sudo ufw delete reject out OpenSSH
Rule deleted
Rule deleted (v6)
limit
拒否の仕方に deny と reject があるのと似た感じで、許可の方にも allow と limit の2種類があります。 limit は brute force attack の緩和に使えます。 30 秒間に 6 回までしか新規接続ができない、という設定になるようです。 正常な接続かどうかに関わらず、iptables の層で拒否してしまうので、例えば構成管理ツールなどで自分が短時間に頻繁に接続する可能性がある場合は避けた方が良いです。
$ sudo ufw limit 22/tcp
Rule updated
Rule updated (v6)
$ sudo ufw status
Status: active
To Action From
-- ------ ----
22/tcp LIMIT Anywhere
53 ALLOW Anywhere
80/tcp ALLOW Anywhere
22/tcp (v6) LIMIT Anywhere (v6)
53 (v6) ALLOW Anywhere (v6)
80/tcp (v6) ALLOW Anywhere (v6)
「/etc/ufw/user.rules」に設定されている内容は以下の通りです。
### tuple ### limit tcp 22 0.0.0.0/0 any 0.0.0.0/0 in
-A ufw-user-input -p tcp --dport 22 -m conntrack --ctstate NEW -m recent --set
-A ufw-user-input -p tcp --dport 22 -m conntrack --ctstate NEW -m recent --update --seconds 30 --hitcount 6 -j ufw-user-limit
-A ufw-user-input -p tcp --dport 22 -j ufw-user-limit-accept
コマンドラインで指定できない設定を入れる方法
「/etc/ufw/before.rules」と「/etc/ufw/before6.rules」が ufw のルールの前に読み込まれる iptables-restore と ip6tables-restore のルールファイルになっているので、 IPsec の ESP の許可などの ufw コマンドで設定できないルールはこのファイルを直接編集すれば良いでしょう。 ufw で設定したルールより後に読み込まれる「after.rules」と「after6.rules」もあるので、用途によってはこちらを使っても良いでしょう。
NAT 設定
ちょっと複雑なネットワークだと、例えば POSTROUTING の MASQUERADE 設定はよく使うと思うのですが、「ufw」のコマンドラインでは nat テーブルの設定はできないので、「before.rules」などに追加することになります。
以下のような設定を「*filter」より上 (または COMMIT より下) に追加すると NAT の設定ができます。 反映させるには「ufw reload」を実行する必要があります。 また、「-F」の行が重要で、入れていないと「ufw reload」を実行するたびに nat テーブルの設定が増えていくことになります。
# NAT table rules
*nat
:POSTROUTING ACCEPT [0:0]
-F
# Allow traffic from OpenVPN client to enp0s3
-A POSTROUTING -s 192.168.10.0/24 -o en+ -j MASQUERADE
# Allow traffic from 192.168.1.0/24 (server's LAN subnet) to OpenVPN client
-A POSTROUTING -s 192.168.1.0/24 -o tun0 -j MASQUERADE
COMMIT
iptables-restore で直接設定したものになるので、確認は「sudo iptables -t nat -nL」になります。
$ sudoedit /etc/ufw/before.rules
(-F がない場合)
$ sudo ufw reload
Firewall reloaded
$ sudo ufw reload
Firewall reloaded
$ sudo iptables -t nat -nL
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
MASQUERADE all -- 192.168.10.0/24 0.0.0.0/0
MASQUERADE all -- 192.168.1.0/24 0.0.0.0/0
MASQUERADE all -- 192.168.10.0/24 0.0.0.0/0
MASQUERADE all -- 192.168.1.0/24 0.0.0.0/0
$ sudoedit /etc/ufw/before.rules
(-F を追加)
$ sudo ufw reload
Firewall reloaded
$ sudo iptables -t nat -nL
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
MASQUERADE all -- 192.168.10.0/24 0.0.0.0/0
MASQUERADE all -- 192.168.1.0/24 0.0.0.0/0
routed の有効化
初期状態では disabled になっていますが、「/etc/ufw/sysctl.conf」でも「/etc/sysctl.conf」でも「/etc/sysctl.d/*.conf」でも良いので、カーネルの設定を有効にすると「disabled」ではなくなります。
$ sudo ufw status verbose | grep Default
Default: deny (incoming), allow (outgoing), disabled (routed)
$ sudo tee /etc/sysctl.d/50-local.conf
net.ipv4.ip_forward=1
net.ipv6.conf.all.forwarding=1
$ sudo sysctl -p /etc/sysctl.d/50-local.conf
net.ipv4.ip_forward = 1
net.ipv6.conf.all.forwarding = 1
$ sudo ufw status verbose | grep Default
Default: deny (incoming), allow (outgoing), deny (routed)
FORWARD チェインの設定
「ufw route」で iptables の FORWARD チェインの設定もできます。 「ufw route」は changelog によると ufw 0.34 から追加されているので、Debian だと jessie の 0.33-2 だと使えなくて stretch の 0.35-4 から使えるようです。
iptables の FORWARD チェインに対する設定になる以外は INPUT や OUTPUT チェインに対する操作と変わりません。
$ sudo ufw route allow from 192.168.10.0/24 to 10.0.0.0/8 port 80 proto tcp
Rule added
$ sudo ufw status
Status: active
To Action From
-- ------ ----
22/tcp LIMIT Anywhere
53 ALLOW Anywhere
80/tcp ALLOW Anywhere
22/tcp (v6) LIMIT Anywhere (v6)
53 (v6) ALLOW Anywhere (v6)
80/tcp (v6) ALLOW Anywhere (v6)
10.0.0.0/8 80/tcp ALLOW FWD 192.168.10.0/24
$ sudo ufw route delete allow from 192.168.10.0/24 to 10.0.0.0/8 port 80 proto tcp
Rule deleted
デフォルトポリシーの変更
「 ufw [--dry-run] default allow|deny|reject [incoming|outgoing|routed]
」でチェーンのデフォルトのポリシーを変更できます。
stretch の ufw では、「default reject」は「 ufw*-reject-*
」チェーンで reject していて、FORWARD チェインなどの指定した組み込みのチェーンの policy が REJECT に変わるわけではないようです。
$ sudo ufw status verbose | grep Default
Default: deny (incoming), allow (outgoing), deny (routed)
$ grep FORWARD /etc/default/ufw
DEFAULT_FORWARD_POLICY="DROP"
$ sudo iptables -nL | grep FORWARD
Chain FORWARD (policy DROP)
$ sudo iptables -nL | grep -A2 'Chain.*reject-forward'
Chain ufw-reject-forward (1 references)
target prot opt source destination
$ sudo ufw default reject routed
Default routed policy changed to 'reject'
(be sure to update your rules accordingly)
$ grep FORWARD /etc/default/ufw
DEFAULT_FORWARD_POLICY="REJECT"
$ sudo iptables -nL | grep FORWARD
Chain FORWARD (policy DROP)
$ sudo ufw status verbose | grep Default
Default: deny (incoming), allow (outgoing), reject (routed)
$ sudo iptables -nL | grep -A2 'Chain.*reject-forward'
Chain ufw-reject-forward (1 references)
target prot opt source destination
REJECT all -- 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable
$ sudo ufw default deny routed
Default routed policy changed to 'deny'
(be sure to update your rules accordingly)
コメント
今の ufw のルールにはコメントがつけられるようになっています。 コメントは ufw のルールに紐づいていて、 iptables の方には特に何も影響はないようです。
$ sudo ufw allow 60000:61000/udp comment "mobile shell"
Rule added
Rule added (v6)
$ sudo ufw status | grep 60000
60000:61000/udp ALLOW Anywhere # mobile shell
60000:61000/udp (v6) ALLOW Anywhere (v6) # mobile shell
$ sudo grep 60000 /etc/ufw/user*.rules
/etc/ufw/user6.rules:### tuple ### allow udp 60000:61000 ::/0 any ::/0 in comment=6d6f62696c65207368656c6c
/etc/ufw/user6.rules:-A ufw6-user-input -p udp -m multiport --dports 60000:61000 -j ACCEPT
/etc/ufw/user.rules:### tuple ### allow udp 60000:61000 0.0.0.0/0 any 0.0.0.0/0 in comment=6d6f62696c65207368656c6c
/etc/ufw/user.rules:-A ufw-user-input -p udp -m multiport --dports 60000:61000 -j ACCEPT
ufw show REPORT
ufw の man の REPORTS セクションで紹介されているように、「ufw show REPORT」で設定状態などを表示できます。 「sudo ufw show listening」は実際に待ち受けしているポートを ufw の設定状況と一緒に一覧できるので、便利そうです。
- sudo ufw show raw
- sudo ufw show builtins
- sudo ufw show before-rules
- sudo ufw show user-rules
- sudo ufw show after-rules
- sudo ufw show logging-rules
- sudo ufw show listening
- sudo ufw show added
$ sudo ufw show listening
tcp:
111 * (rpcbind)
22 * (sshd)
[ 1] allow 22/tcp
tcp6:
111 * (rpcbind)
22 * (sshd)
[ 2] allow 22/tcp
udp:
1015 * (rpcbind)
111 * (rpcbind)
68 * (dhclient)
udp6:
1015 * (rpcbind)
111 * (rpcbind)
ログレベル
デフォルトだと拒否された時のログが rate limit 付きで /var/log/ufw.log などに残りますが、「 ufw [--dry-run] logging on|off|LEVEL
」で、どのくらいログを残すのか設定できます。
設定できるのは on, off, low, medium, high, full のようです。 詳細は man を参照してください。