Ubuntu Weekly Recipe

第76回Ubuntuのソフトウェアファイアウォール:UFWの利用(1)

ufw(Uncomplicated FireWall)は、Ubuntuで標準的に利用できる、⁠iptablesを簡単に設定するツール」です。ufwを利用することで、⁠外部からの接続は基本的に受け付けない」⁠sshだけは許す」などといった設定を、iptablesにくらべて格段に少ない操作で実現できます。

今回と次回の2回にわけて、ufwを使って、サーバーなどの設定を簡単に行うレシピを紹介します。

ufwの基本

ufwは、Canonicalの社員であり、Ubuntuのセキュリティ関連モジュールやセキュリティアップデートを主に担当しているJamie Strandboge氏が中心になって開発している、⁠iptablesのフロントエンド」となるツールです[1]⁠。Ubuntuには8.04で取り込まれています。過去に本レシピでも、第45回でごく軽く内容を紹介しています。

今回はコマンドラインからufwを使う方法のうち、基礎的な部分を紹介します。次回はより実践的な設定の例と、gufwによるGUI設定の手順を紹介する予定です。

実際にufwを体験する前に、ufwとiptablesの違いを把握しておきましょう。

iptablesは、Linuxでファイアウォールを設定するための標準的なツールです。iptablesの各種モジュールを利用してNetFilterを設定した場合、ファイアウォールとして求められる、ほぼありとあらゆる設定を行うことができます。また、多くの設定方法が存在し、さらにその設定の自由度も高いものです。

ですが、iptablesはその自由度と機能の豊富さから、設定を行うのに専門の知識が必要になります。少なくとも、いきなりiptablesを利用して自由自在に設定を行うことは困難でしょう。たとえば以下はiptablesを用い、⁠30秒に5回、sshアクセスを試みてきたホストからの接続は300秒間拒絶する」という設定を行ったものです[2]⁠。

$ sudo iptables -L 
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         
ssh        tcp  --  anywhere             anywhere            tcp dpt:ssh 

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         

Chain ssh (1 references)
target     prot opt source               destination         
ACCEPT     tcp  --  anywhere             anywhere            tcp flags:!FIN,SYN,RST,ACK/SYN state RELATED,ESTABLISHED 
REJECT     tcp  --  anywhere             anywhere            tcp flags:FIN,SYN,RST,ACK/SYN recent: UPDATE seconds: 300 name: ssh_block side: source reject-with icmp-port-unreachable 
ssh_brute  tcp  --  anywhere             anywhere            tcp flags:FIN,SYN,RST,ACK/SYN recent: CHECK seconds: 30 hit_count: 5 name: ssh_conn side: source 
           tcp  --  anywhere             anywhere            tcp flags:FIN,SYN,RST,ACK/SYN recent: SET name: ssh_conn side: source 
ACCEPT     tcp  --  anywhere             anywhere            tcp flags:FIN,SYN,RST,ACK/SYN 

Chain ssh_brute (1 references)
target     prot opt source               destination         
LOG        all  --  anywhere             anywhere            recent: SET name: ssh_block side: source LOG level notice prefix `Auto block: ssh-bruteforce: ' 
REJECT     all  --  anywhere             anywhere            reject-with icmp-port-unreachable 

正当な通信を通すための設定や、⁠sshへのアクセス回数をカウントする」⁠閾値を超えたらブロックする」⁠ログを残す」などといった機能が組み合わさり、すぐに読み取るのは困難なものとなっています。実現したいのは、単に「sshのポートへ一定回数接続が来たら拒否」ということだけですが、iptablesで実現しようとすると、非常に複雑な設定になってしまいます。

これをufwで設定するとどうなるのか、を端的に示すのが以下です。ufwで設定を行った場合、非常に単純に設定できることが分かるはずです[3]⁠。

$ sudo ufw status       
Status: active

To                         アクションFrom
--                         -------------------
OpenSSH                    LIMIT   Anywhere

ufwは「ソフトウェアファイアウォールとしての機能を、できるだけ単純なインターフェースで設定する」注4⁠、という設計思想に基づいたツールです。できないことも存在しますが、⁠できること」であれば、きわめて簡単に設定が可能です。ここからは実際にufwを用いて、接続の制限や許可を設定してみましょう。

ufwの基本的な使い方

前述の通り、ufwの一部の機能は第45回で紹介していますが、ここでは一からufwを使う方法を説明します。多くの場合はサーバーで役に立つ機能ですが、⁠デスクトップマシンにサーバー的な機能を導入しておき、それを他のマシンから利用する」などといった場合にはデスクトップ環境でも役に立つでしょう。

最初にすべての通信を無効にする

ufwの操作は、ターミナルから行います。⁠アプリケーション⁠⁠→⁠アクセサリ⁠⁠→⁠端末]を開いて操作を行ってください。ufwは基本的に、⁠デフォルトではあらゆる外部からの通信を拒否し、許可する通信を定義していく」形で設定を行います(⁠⁠sudo ufw default ALLOW」を実行することで、⁠デフォルトでは全て通すが、不要な通信のみを落とす」設定にすることも可能です。ただし、この設定を使うことはあまりないでしょう⁠⁠。

以下のように、⁠sudo ufw enable」と端末上で入力してください図1⁠。

$ sudo ufw enable
図1 ufwの有効化
図1 ufwの有効化

これでufwが有効になっています。ufwは一度有効化すると、システム起動時に自動的に有効になります。この状態を解除するには「sudo ufw disable」を行います(が、ほとんどの場合無効化する必要はないでしょう⁠⁠。

ここから設定を行っていくことになりますが、ufwが有効になった時点で、まっさきに外部からの通信を受け付けないように設定しておきましょう。以下のように操作します。

$ sudo ufw default DENY

この状態は、外部から見ると、接続を試みるとConnection Refusedが返るのではなく、単にタイムアウトする状態です。もしConnection Refusedを返したい場合は、⁠sudo ufw default REJECT」を実行してください。

これらの設定を行っても、⁠外部に出ていく」通信(アウトバウンド)は可能です。ufwはあくまで、⁠外からの」通信(インバウンド)だけを制御します[5]ので、たとえば、⁠トロイの木馬などに感染した場合に、想定していない通信をせき止める」といった用途に利用することはできません。

その時点でufwが動作しているかどうかは、⁠sudo ufw status」で確認できます図2⁠。何も設定していない場合、⁠状態:アクティブ」とだけ表示されるはずです。無効になっている場合は、⁠状態:非アクティブ」です。

図2 ufwのstatus
図2 ufwのstatus

また、ufwのコマンド一覧は「sudo ufw help」で出力することができます図3⁠。コマンドの引数を忘れてしまった場合は、これらを利用すると良いでしょう。

図3 ufwのhelp
図3 ufwのhelp

許可する通信を設定する

ufw enableを実行して全ての通信を遮断したら、⁠必要なポートを開く」作業を行います。以下ではSSHが利用する、TCP/UDPそれぞれのポート22を開いています。

$ sudo ufw allow 22

この状態でufw statusを実行すると、図4のように、ポート22に対する許可が行われているのが分かるでしょう。

図4 ポート22に対する許可を与えた状態
図4 ポート22に対する許可を与えた状態

必要であれば以下のようにすることで、TCPのみに許可を与えることもできます(SSHを利用するにはTCP/UDP双方が必要です。この例のようにTCPだけを許可することは望ましくありません⁠⁠。

$ sudo ufw allow 22/tcp

不要になったルールは、次のように、追加のためのコマンドの頭に「delete」をつけて実行すれば削除できます。

$ sudo ufw allow 22/tcp ←追加のためのコマンド
$ sudo ufw delete allow 22/tcp ←削除のためのコマンド

また、ポート番号ではなく、サービス名で指定することも可能です。サービス名とポート番号の対応は、/etc/servicesに書かれたものが利用されます。⁠delete」を頭につけることで削除もできます。例は次のようになります。

$ sudo ufw allow ssh

接続頻度を制限する

SSHやIMAP、HTTPSのBASIC認証などの、パスワードによる認証を用いるサービスでは、⁠でたらめなパスワードを打ち込み続け、偶然正しいものと一致することを期待する」⁠ブルートフォース)攻撃への対策が必要です。

SSHでは公開鍵による認証を行うことで、パスワードよりも強固な、事実上ブルートフォース攻撃では破れない設定にすることも可能ですが、鍵の管理が面倒など、パスワード認証に比べて不便な点もあり、すべての場合で利用できるわけでもありません。

すでにufwとiptablesの比較のところでも触れたように、このような場合はufwの「接続頻度を制限する」機能が便利です。この指定はLIMITキーワードを用いて行います。以下のように操作しておくことで、⁠執拗に接続してくるアクセス」を拒否することが可能です。

$ sudo ufw limit ssh

許可・拒否のログを取る

このようにして「allow」を設定したルールに基づいて通信が許可された場合や、⁠limit」で接続が制限された場合、/var/log/syslogに以下のようなログが記録されます。

Jun 14 18:55:28 eridanus kernel: [ 3063.760231] [UFW ALLOW] IN=eth0 OUT= MAC=ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff SRC=192.168.200.20 DST=192.168.200.102 LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=19614 DF PROTO=TCP SPT=36097 DPT=22 WINDOW=5840 RES=0x00 SYN URGP=0

これらのログの出力は、ufwのLOGGING設定に依存します。わざわざufw allowルールによる接続許可をロギングしたくない場合、以下のようにレベル指定を「low」にします。

$ sudo ufw logging low

lowは、⁠default以外のルールによるブロック」を、流量制御しつつ出力します。以外のログの出力レベルには、off(完全に無効⁠⁠、medium(流量制御ありでallow・denyにマッチしたもの+不正なパケット+新しいコネクションを出力。デフォルト値⁠⁠、high(mediumの流量制御なし版⁠⁠、full(すべてのログを記録)となっています。詳細は、man ufwかsudo ufw helpを参照してください。

ただし、ほとんどの場合はlowとmeduimを使い分ければ充分でしょう。また、highやfullを利用する場合、膨大なログが出力されるので、ディスク容量に注意してください。

「app」による指定

※この機能は、8.10以降のUbuntuで利用可能です。

ufwでは、ポート単位の指定だけでなく、⁠アプリケーションごと」に設定を行うことも可能になっています。たとえば、Sambaの接続許可を行う場合を考えてみましょう。

Samba Serverは名前解決やマスタブラウザの利用のために、4種類のポートを利用して動作します。これを8.04のufwを利用して許可する場合、以下のようにnetbios-ns(TCP/UDP 137⁠⁠・netbios-dgm(TCP/UDP 138⁠⁠・netbios-ssn・microsoft-ds(TCP/UDP 445)のそれぞれを許可する必要があります。

$ sudo ufw allow netbios-ns
$ sudo ufw allow netbios-dgm
$ sudo ufw allow netbios-ssn
$ sudo ufw allow microsoft-ds

しかし、本来の目的は、⁠Sambaのサービスを許可する」ことであり、これら4種類のサービスを許可するのはあくまで手段でしかありません。そこでufwでは、/etc/ufw/application.d/ディレクトリにアプリケーション定義ファイルを置くことで、アプリケーション単位で接続の可否を設定できるようになっています。このディレクトリにアプリケーション定義ファイルを配置するのは、サーバーアプリケーションのパッケージ(cupsやsamba・postfixパッケージ)の仕事となっており、ユーザーがこれらを意識する必要はありません。この機能は、以下のように利用します。

まず、登録されている「アプリケーション」の一覧を調べます。図5のようにアプリケーションごとの定義の一覧が表示されるはずです。

$ sudo ufw app list
図5 アプリケーションごとの定義の一覧
図5 アプリケーションごとの定義の一覧

あとは「allow」「deny」の引数としてアプリケーション名を与えるだけです。

$ sudo ufw allow Samba

これにより、サービス単位(=ポート単位)で接続許可を行わなくても、一度に設定を行うことができます。

なお、これらのアプリケーション名は、/etc/servicesに登録されているサービス名と区別するため、先頭が大文字で始まることになっています。

引き続き、次回はufwのより詳しい操作方法や、GUIからの利用について説明します。

おすすめ記事

記事・ニュース一覧