先週に引き続き、今回もufwを使いこなすためのレシピを紹介します。今回は実践編となりますので、先週の基礎操作編とあわせて利用してください。
特定のIPアドレスからの接続を許可する
ネットワークの構成上、「 このIPアドレスからの接続は安全であると仮定してもいい」( そこには自分が普段使うマシンしかない)といったこともあるでしょう。このような場合は、次の構文を用います。
$ sudo ufw allow from 192.168.254.0/24
この設定は、「 192.168.254.*に属するホストからのすべての通信を許す」というものです。個別のホスト単位にしたい場合は、次のようにIPアドレスを指定してください。以下では、192.168.254.10からのすべての通信を受け付けるように設定しています。
$ sudo ufw allow from 192.168.254.10
さらに、以下のようにポート単位で「そのホストからの接続を許可する」設定を書くことができます。以下は、SSHが利用するポート(=22)を、192.168.254.20というホストに対して許しています。
$ sudo ufw allow from 192.168.254.20 to any port ssh
上記では/etc/servicesに書かれている「ssh」というサービス名での表記をしていますが、「 22/tcp」などとすることも可能です。さらに、ここで行う指定でapp構文を利用することもできます。
以下は、「 192.168.254.*のホストからのSamba関連の接続要求は許す」というものです。
$ sudo ufw allow from 192.168.254.0/24 to any app Samba
ルールの組み合わせと入れ替え
前掲のLIMITキーワードによる指定を行った場合、scpによるコピーなど、「 適切な通信にもかかわらず、ufwのLIMIT条件にマッチしてしまう」といった困った状態が起こりえます。
次のような環境を想定してみましょう。
SSHサーバーは、外部のネットワークと内部のネットワークの双方に接続されている。
外部からのSSHブルートフォースを防ぎたい。
内部からは、192.168.254.10からscpを用いてコンテンツをアップロードしている。
このscpは非常に頻繁に行われている。
このような環境では、そのままではsudo ufw limit sshを実行するわけにはいきません。scpによるコピーまでもLIMIT条件に引っかかってしまい、通信不能になってしまうおそれがあるからです。
このような場合は、「 特定のIPアドレスからの接続を許可」し、「 それ以外の接続はLIMIT」という設定が必要です。次のようにルールを組み合わせて設定します。
$ sudo ufw allow from 192.168.254.10 to any port ssh
$ sudo ufw limit ssh
このように設定することで、192.168.254.10からのssh(=scp)接続は自由に行える一方、それ以外のホストからの接続はLIMITにより制限される、という状態になります(図1 ) 。
図1 特定のホストだけ無制限にし、他をLIMITした状態
ここで重要なのは、ルールの設定順です。
上記の設定手順では、「 特定のIPアドレスからの接続を許可」した後に、「 全ての接続をLIMIT」という順番でルールを指定しています。ufwのルールは上からチェックされますので、この順番が逆になると、「 全ての接続をLIMIT」だけが有効になってしまいます。ufwは通常の動作では、「 登録した順番で」ルールを評価します。このため、以下のように「全てのSSH接続のLIMIT」を先に設定してしまった場合、そちらの方が優先されてしまいます。
・誤った例
$ sudo ufw limit ssh
$ sudo ufw allow from 192.168.254.10 to any port ssh
この状態でstatusを見ると、以下(図2 )のように、「 LIMIT」指定の方が上に来ているはずです。
図2 誤って先にLIMITを指定した状態
このような状況で、正しい設定に戻すにはどうすればいいのでしょうか?
一つの方法は、単純に、「 全てのSSH接続のLIMIT」指定を削除してから、再度追加することです。以下のように操作します。
$ sudo ufw delete limit ssh
$ sudo ufw limit ssh
この状態でstatusを見ると、正しい設定になっていることが確認できます(図3 ) 。
図3 delete後に再追加することで、順番が変化
ただし、必ずしも削除と追加だけで問題を解決できるわけではありません。より複雑な設定の場合、「 設定ルールのこの場所に、新しいルールを追加したい」といった要望もありえます。たとえば、「 192.168.254.10からのSSHは許し、192.168.254.20からのSSHはLIMITで限定的に許す。他のSSH接続は全て拒否」などといった場合です。
このような場合、sudo ufw status numberedとinsertキーワードを利用して、「 指定した箇所にルールを追加」する操作を行います。
最初に、ufw status numberedで、ルールのナンバーを表示する状態で一覧します(図4 ) 。
$ sudo ufw status numbered
図4 ufw status numbered
図4における、「 1」 、もしくは「2」の欄にLIMIT 192.168.254.20のルールが入れば良いわけです[1] 。ufwの「insert」を使うことで、「 1」の位置にルールを挿入することができます。insertで指定しない場合、常にルールの最後の位置に追加されることになります[2] 。
$ sudo ufw delete limit from 192.168.254.20 to any port ssh
$ sudo ufw insert 1 limit from 192.168.254.20 to any port ssh
この操作を実際に行った例は、図5 のようになります。
図5 delete後にinsertした結果
gufwの利用
コマンドによる操作に抵抗がある場合、ufwには「gufw」というGUIフロントエンドが存在します(注3) 。デフォルトではインストールされていませんが、Synapticからgufwパッケージをインストールするか、以下のコマンドで導入できます。
$ sudo apt-get install gufw
gufwは、[ システム] →[ システム管理] →[ ファイアウォールの設定]から起動できます(図6 ) 。
図6 gufwのメニュー
メインウインドウ(図7 )で、ufwの有効/無効の切り替え(ufw enable・disable) 、「 外部からのトラフィックを拒否・許可する」( ufw default deny・default allow) 、各種ルールの追加が可能です。
図7 gufwのメインウインドウ
また、[ 編集] →[ 設定]から、gufwそのものの設定を変更することが可能です(図8 ) 。
図8 gufwのメインウインドウ
設定のうち、「 ログイン時に自動起動する」には注意が必要です。これはufwの有効・無効の制御ではなく、「 gufwそのものをログイン時に起動するかどうか」を制御します。ufwそのものの制御は、メイン画面の有効・無効の切り替えを用いてください。
たいていの環境では、「 トレイアイコンを表示する」「 閉じたらトレイアイコンに最小化する」「 ログイン時に自動起動する」を有効にしておき、必要に応じてトレイアイコンから呼び出せるようにしておくと便利でしょう。
[3] ただし、ufwの基本的な概念を理解していないと設定しにくいので、コマンド構文を覚えなくて済む、というのが主なメリットとなります。「 よく分からないが、なんとなく設定すると動作する」というタイプのGUIではありません。
ufwによる設定のサンプル
ここまでに登場したものを含めて、ufwを利用したファイアウォール設定の実例(+サーバーソフトウェアの設定変更)を幾つか挙げておきます。
HTTPサービスを提供するマシン
Apache(apache2.2-*)を導入し、HTTPとHTTPSでコンテンツを配信するサーバーを考えてみましょう。日常的なメンテナンス作業にはSSHを利用するものとし、HTTPとHTTPS以外のサービスは存在しないものとします。
このような環境では、ufwを以下のように設定していきます。
まず、ufwのデフォルト指定はsudo ufw denyにしておきます。ポリシーによってはrejectにしても良いのですが、後述の理由でポートスキャンを容易に行われる状態を避けたいので[4] 、denyの方が妥当でしょう。
$ sudo ufw deny
[4] denyであれば、「 開いていないポートである」ことを確認するためにタイムアウト待ちが必要ですが、rejectの場合はすぐにConnection Refusedが返ってしまうため、ポートスキャンを行う攻撃者にとって有利です。
この状態ではサービスに利用するポートも閉じられた状態ですので、HTTP・HTTPS関連のポートを開放します。apache2.2-commonパッケージにはufwのアプリケーションプロファイルとなる/etc/ufw/applications.d/apache2.2-commonが含まれていますので、次のようにufw app操作を用いることで、容易に設定することができます。
$ sudo ufw app list | egrep -i apache
Apache
Apache Full
Apache Secure
$ sudo ufw allow 'Apache Full'
これでHTTP・HTTPSのそれぞれの待ち受けポートを開くことができました[5] 。さらにSSHのポートを、「 LIMIT」で開いておきましょう。
$ sudo ufw app list | egrep -i ssh
OpenSSH
$ sudo ufw limit OpenSSH
これで、「 HTTP・HTTPS・SSHだけを開いたサーバー」が設定できました。……が、これだけではやや危険な状態です。SSHをport 22で待ち受ける状態にするのではなく、SSHの待ち受けポートを変更しておきましょう。多くのSSHブルートフォースアタックはport 22を狙いますので、ポートを変更しておくことで、攻撃を受ける機会そのものを減らすことができます[6] 。
[5] 本文中では触れていませんが、「 Apache」はHTTP単独の、「 Apache Secure」はHTTPS単独、そして「Apache Full」がHTTP・HTTPS双方の有効化のためのプロファイルとなっています。
次のように設定を行います。
まず、SSHの設定ファイル/etc/ssh/sshd_configの、「 Port 22」という設定項目を、「 Port 4242」などに変更します。このポート番号はできるだけランダムな(推定しにくい)ものが良いでしょう。
$ gksu gedit /etc/ssh/sshd_config
設定を修正したら、SSHデーモンを再起動します。
$sudo /etc/init.d/ssh restart
これでSSHの待ち受けポートが、4242に変更されました。この状態のシステムにSSHでアクセスする場合、「 ssh -p 4242 サーバ名」という形で、「 -p 4242」をオプションとして追加します。また、scpの場合は「-P 4242」と、大文字Pで指定します。これにより、少なくともport 22を固定的に狙うSSHブルートフォースアタックについては回避することが可能です。
ただし、この状態では、ufwの「app」による指定が行えません。以下のようにポートを指定してLIMITを設定するのが一つの手です。
$ sudo ufw limit 4242
ですが、この状態でstatusを表示しても、以下のように表示されてしまいます。これでは、「 4242とは何のポートなのか」というのが、すぐには分からなくなってしまうででしょう。一人の管理者が利用するシステムでは良いのですが、複数の管理者で共同管理しているようなシステムの場合、これは致命的です。
$ sudo ufw status
Status: active
To アクションFrom
-- -------------------
Apache Full ALLOW Anywhere
4242 ALLOW Anywhere
このような場合には、ufwのアプリケーションプロファイルを書いて解決することができます。アプリケーションプロファイルは非常に単純な構造になっていますから、修正は容易です。以下はデフォルトのOpenSSHのプロファイルです。
[OpenSSH]
title=Secure shell server, an rshd replacement
description=OpenSSH is a free implementation of the Secure Shell protocol.
ports=22/tcp
これをコピーして、今回の修正に合わせた、別のSSHプロファイルを作成しましょう。
$ cd /etc/ufw/applications.d
$ sudo cp openssh-server openssh-server-another
$ gksu gedit openssh-server-another
エディタで「[OpenSSH]」の部分を「[OpenSSH Another]」へ、「 ports=22/tcp」の箇所を「ports=4242/tcp」に修正してください。
[OpenSSH Another]
title=Secure shell server, an rshd replacement
description=OpenSSH is a free implementation of the Secure Shell protocol.
ports=4242/tcp
この状態でアプリケーションプロファイルを確認すると、以下のように「OpenSSH Another」というプロファイルが追加されているはずです。
$ sudo ufw app list | egrep -i ssh
OpenSSH
OpenSSH Another
あとは、以下のように、「 OpenSSH Another」プロファイルを用いてLIMITを設定するだけです。
$ sudo ufw limit 'OpenSSH Another'
この状態でstatusを表示すると、以下のように「OpenSSH Another」と表示されます[7] 。複数の管理者が存在する場合でも、設定がそのまま意思表示になりますので、誤解による設定ミスが引き起こされる可能性を下げることができるでしょう。
$ sudo ufw status
Status: active
To アクションFrom
-- -------------------
Apache Full ALLOW Anywhere
OpenSSH Another LIMIT Anywhere
といったところで、今週はここまで。来週は、Ubuntu Japanese Teamのリーダーである小林さんが担当する予定です。
[7] ただ、現実的には「4242が何のポートなのかわからない」ということは、「 sshで接続する際、どのポートにつなげばいいのかわからない」ということと同義ですから、あまり望ましい状態ではありません。