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設定の手順を紹介する予定です。
[1] 厳密に言うのであれば、ufwは「NetFilterの設定フロントエンド」となるユーザーランドツールです。ufwが提供する機能はあくまでもNetFilterの設定であり、必ずしもiptablesとは関係ありません。ただし、現時点でのufwの実装はiptables・ip6tablesコマンドを実行することで行われていること(ufw/src/backend_iptables.py)と、NetFilterとiptablesの関連を厳密に区分けする必要も微妙なことから、ここでは「iptablesのフロントエンド」としています。
実際に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
[2] この設定は「TCP port 22への接続回数」が5回に達したら拒否、という動作になっています。注意すべきは、「 sshによるパスワード認証の試行」は、「 1回のTCP接続で複数回行うことができる」ということです。パスワード認証の場合、1回のTCP接続で3回のチャレンジが可能ですので、この設定では、でたらめなパスワードを30回試すと接続が拒絶される、ということになります。
正当な通信を通すための設定や、「 sshへのアクセス回数をカウントする」「 閾値を超えたらブロックする」「 ログを残す」などといった機能が組み合わさり、すぐに読み取るのは困難なものとなっています。実現したいのは、単に「sshのポートへ一定回数接続が来たら拒否」ということだけですが、iptablesで実現しようとすると、非常に複雑な設定になってしまいます。
これをufwで設定するとどうなるのか、を端的に示すのが以下です。ufwで設定を行った場合、非常に単純に設定できることが分かるはずです[3] 。
$ sudo ufw status
Status: active
To アクションFrom
-- -------------------
OpenSSH LIMIT Anywhere
ufwは「ソフトウェアファイアウォールとしての機能を、できるだけ単純なインターフェースで設定する」( 注4 ) 、という設計思想に基づいたツールです。できないことも存在しますが、「 できること」であれば、きわめて簡単に設定が可能です。ここからは実際にufwを用いて、接続の制限や許可を設定してみましょう。
[4] ここではファイアウォールを、ハードウェア型のファイアウォールと「ソフトウェアファイアウォール」の二種類に分けています。ハードウェア型のファイアウォールはルータやスイッチと同じように動作し、ネットワークの途中に「はさむ」ことで、不要な通信を抑制する機能を提供するネットワーク機器の一種です。言い換えると、「 他のホストに、不要な通信をせき止めるもの」です。一方でソフトウェアファイアウォールはサーバーなどのホスト上で動作し、「 自ホストにたどり着いたもののうち、不要な通信をせき止めるもの」で、その名の通り、サーバー上で動作する1ソフトウェアです。LinuxのNetFilter/iptablesはソフトウェアファイアウォールとして機能するものですが、ブリッジ機能などを併用することで、他のホストへの通信をせき止める目的で利用することも可能です。
ufwの基本的な使い方
前述の通り、ufwの一部の機能は第45回 で紹介していますが、ここでは一からufwを使う方法を説明します。多くの場合はサーバーで役に立つ機能ですが、「 デスクトップマシンにサーバー的な機能を導入しておき、それを他のマシンから利用する」などといった場合にはデスクトップ環境でも役に立つでしょう。
最初にすべての通信を無効にする
ufwの操作は、ターミナルから行います。[ アプリケーション] →[ アクセサリ] →[ 端末]を開いて操作を行ってください。ufwは基本的に、「 デフォルトではあらゆる外部からの通信を拒否し、許可する通信を定義していく」形で設定を行います(「 sudo ufw default ALLOW」を実行することで、「 デフォルトでは全て通すが、不要な通信のみを落とす」設定にすることも可能です。ただし、この設定を使うことはあまりないでしょう) 。
以下のように、「 sudo ufw enable」と端末上で入力してください(図1 ) 。
$ sudo ufw enable
図1 ufwの有効化
これでufwが有効になっています。ufwは一度有効化すると、システム起動時に自動的に有効になります。この状態を解除するには「sudo ufw disable」を行います(が、ほとんどの場合無効化する必要はないでしょう) 。
ここから設定を行っていくことになりますが、ufwが有効になった時点で、まっさきに外部からの通信を受け付けないように設定しておきましょう。以下のように操作します。
$ sudo ufw default DENY
この状態は、外部から見ると、接続を試みるとConnection Refusedが返るのではなく、単にタイムアウトする状態です。もしConnection Refusedを返したい場合は、「 sudo ufw default REJECT」を実行してください。
これらの設定を行っても、「 外部に出ていく」通信(アウトバウンド)は可能です。ufwはあくまで、「 外からの」通信(インバウンド)だけを制御します[5] ので、たとえば、「 トロイの木馬などに感染した場合に、想定していない通信をせき止める」といった用途に利用することはできません。
[5] Windows環境向けの統合セキュリティソフトが提供する「ソフトウェアファイアウォール」の多くは、「 内側から外側に出て行く通信」( アウトバウンド)と「外側から内側に入ってくる通信」( インバウンド)の双方を制御することができますが、( 今のところ)ufwはあくまでインバウンド通信の制御に特化しています。
その時点でufwが動作しているかどうかは、「 sudo ufw status」で確認できます(図2 ) 。何も設定していない場合、「 状態:アクティブ」とだけ表示されるはずです。無効になっている場合は、「 状態:非アクティブ」です。
図2 ufwのstatus
また、ufwのコマンド一覧は「sudo ufw help」で出力することができます(図3 ) 。コマンドの引数を忘れてしまった場合は、これらを利用すると良いでしょう。
図3 ufwのhelp
許可する通信を設定する
ufw enableを実行して全ての通信を遮断したら、「 必要なポートを開く」作業を行います。以下ではSSHが利用する、TCP/UDPそれぞれのポート22を開いています。
$ sudo ufw allow 22
この状態でufw statusを実行すると、図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 アプリケーションごとの定義の一覧
あとは「allow」や「deny」の引数としてアプリケーション名を与えるだけです。
$ sudo ufw allow Samba
これにより、サービス単位(=ポート単位)で接続許可を行わなくても、一度に設定を行うことができます。
なお、これらのアプリケーション名は、/etc/servicesに登録されているサービス名と区別するため、先頭が大文字で始まることになっています。
引き続き、次回はufwのより詳しい操作方法や、GUIからの利用について説明します。