orangeProse別館

orangeProse(本ブログ)の補助

VagrantでUbuntuサーバ/UFW/Apache2

VagrantUbuntuサーバの基本構成の練習をしようシリーズ、続きです。

これまでにやったこと:

前回の記事から今日までにVagrantのアップデートがあったので更新しました。

環境:

今日触れる項目:

  • パスワード認証を無効にする
  • UFWの設定
  • Apache2のインストール
  • Apache2に対するUFWの設定
  • a2ensite/a2dissite

パスワード認証の無効化

ブルートフォース攻撃は、ランダムに選ばれたあるいはターゲットにされたIPアドレス(サーバ)の待ち受けポートに対し、ランダムなあるいは辞書にあるユーザ名と、ランダムなあるいは辞書にあるパスワードを組み合わせてログインしようとすることで成立します。

前回、SSHポートの変更に触れたのは、一般的にデフォルトとして知られている22番ポートを塞ぐためです。

また、下二桁が22である1022・10022・2222なども狙われやすいので、避けるべきだということも述べました。

ブルートフォース攻撃が成り立たなくなるように、そもそもパスワード認証を無効にし、公開鍵認証のみ可能にするように設定することも有効な対策として一般的です。

パスワード認証を無効にするには、/etc/ssh/sshd_configファイル内の次の箇所を書き換えます:

$ cd /etc/ssh
$ sudo vi sshd_config

PasswordAuthentication no
UsePam no

PasswordAuthenticationはデフォルトではコメントアウトされていてyesで、UsePamはyesになっていると思います。そこを修正します。

/etc以下のファイルをいじったので、etckeeperでコミットしておきます:

$ sudo etckeeper commit

PassAuth -> no, UsePam -> no

$ cd /etc
$ sudo tig

UFWの設定

Linuxにはiptablesというファイアウォールが標準でインストールされています。

CentOSなどの入門書的解説ではいきなりiptablesをオフにするところからはじまったりしますが、これは操作が難しいからです。

Ubuntuには操作を容易にするUFWというフロントエンドがあるので、これを使います。

基本的には、UFWを常時オンにして、開けたいポートがあるときに、そのつど、UFWでポートを個別に開ける、という方針でサーバ構築するべきかと思います。

$ sudo ufw status
状態: 非アクティブ
$ sudo ufw enable
(ここでyes/noを聞かれるので、「y」で応える)
ファイアウォールはアクティブかつシステムの起動時に有効化されます。
$ sudo ufw status
状態: アクティブ

UFWがデフォルトで有効化されました。UFWは外部からのアクセス(インバウンド)をすべて遮断し、内部からのアクセス(アウトバウンド)を通します。

SSH接続アプリケーション(WindowsならTeraTarm、Macならコンソールなど)で、認証キーを使ったSSH接続を試してみます。タイムアウトで接続できなければ成功です。

Vagrantで使う秘密鍵は.vagrant.d/insecure_private_keyです(PuTTYだとこのキーが使えないみたいなので、WindowsではTeraTermなどを使ってみてください)。

このままでは次回のSSHログインができなくなるので、OpenSSHに許可を与えます。

まず、現在UFWで利用可能なアプリケーションを見ます:

$ sudo ufw app list
利用可能なアプリケーション:
  OpenSSH

いまのところopenssh-serverしか外部からのアクセスにかかわるサービスがないので、ひとつだけリストされています。

アプリケーション単位で許可してみます:

$ sudo ufw allow OpenSSH
ルールを追加しました
ルールを追加しました(v6)

もう一度、SSH接続アプリケーションで接続しようと試みて、接続できるようであれば成功です。

vagant sshでも接続可能かどうか、exitしてから試してみてください。

UFWの操作方法はsudo ufw helpを見れば、おおよそわかるように容易です。

UFWのルール

UFWでの許可/禁止といった設定を「ルール」といいます。

上述したのはアプリケーションごとの設定方法ですが、特定のポートへの設定を追加することもできます:

$ sudo ufw allow 20/tcp

ポート20のTCP接続の受付を許可しました。ルールの状態を確認します:

$ sudo ufw status
状態: アクティブ

To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere
20/tcp                     ALLOW       Anywhere
OpenSSH (v6)               ALLOW       Anywhere (v6)
20/tcp                     ALLOW       Anywhere (v6)

拒否する設定はdenyで追加します:

$ sudo ufw deny 20/tcp
ルールを更新しました
ルールを更新しました(v6)
$ sudo ufw status
状態: アクティブ

To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere
20/tcp                     DENY        Anywhere
OpenSSH (v6)               ALLOW       Anywhere (v6)
20/tcp                     DENY        Anywhere (v6)

denyの場合は、パケットを落とすだけで通信元に通知をせず、タイムアウトするだけです。もし通知が必要な場合はdenyの代わりにrejectを使います:

$ sudo ufw reject 20/tcp

ポートスキャンを行う攻撃者への対策としては、即座に通知を送るよりも、タイムアウトさせるほうが有利なので、denyを使うべきでしょう。

一度設定したルールを削除するには、deleteを使います:

$ sudo ufw delete deny 20/tcp
$ sudo ufw delete allow OpenSSH

SSHポートには、完全にallowにするのではなく、limitにせよ、という解説がなされることが多いようです:

$ sudo ufw limit OpenSSH

デフォルトでは、30秒に6回の接続が行われたら、それ以上のアクセスを禁止します。ただ、scpでファイル転送などを行うのであれば、30秒に6回以上の接続を行うことになります。現実的には、特定のIPアドレスからの接続をallowし、それ以外にはlimitをかける、ということになります。

いま、次のようなルールになっているとします:

$ sudo ufw status
状態: アクティブ

To                         Action      From
--                         ------      ----
OpenSSH                    LIMIT       Anywhere

IPv6ではlimitがサポートされないので、sudo ufw delete 2で2番めにあったIPv6のルールを削除しました)

ここで

$ sudo ufw allow from 192.168.33.0/24 to any app OpenSSH

とすると、ルールの最後尾に「192.168.33.*からのOpenSSHへのアクセスは許可する」というルールが追加されます。ですが、ルールは先頭から優先されて適用されるので、すべてのアクセスをLIMITするという条件で特定IPをALLOWする(ということは特定IPにもLIMITがかかる)という不適切なルールになります。

そこで、ルールの1番目にinsertすることにします:

$ sudo ufw insert 1 allow from 192.168.33.0/24 to any app OpenSSH

ルールを挿入しました
$ sudo ufw status
状態: アクティブ

To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       192.168.33.0/24
OpenSSH                    LIMIT       Anywhere

もちろん、resetコマンドでいったんルールを全部破棄して、順番にルールを適用してもかまいません:

$ sudo ufw reset

ちなみにUFWの基本設定ファイルは/etc/default/ufw、ユーザがufwコマンドで設定した内容は/lib/ufw/user.rulesに格納されています。ユーザによるルール設定は/etc以下にも反映されます。

ルールの設定が終わったら、etckeeperでcommitしておきましょう。

Apache2のインストール

WEBサーバへブラウザでアクセスできて、やっと「サーバができたー!」という気分になるのは確かなので、この段階で入れておきます。

なにはともあれ、とりあえずインストールしてみます:

$ sudo aptitude install apache2
$ echo $?

先にUFWを有効化しているので、apache2へのアクセスを許可するためにポートを開放します:

$ sudo ufw allow 'Apache Full'

ufwコマンドで、Apache Fullのようにスペースが入っている引数をわたすときはクォーテーションマークで囲みます。

ローカル(ホストOS)のブラウザを開いてhttp://192.168.33.20にアクセスします。"It works!"と表示されれば成功です。

ブラウザを開いたまま、

$ tail -f /var/log/apache2/access.log

と実行し、ブラウザで再読込すると、アクセスログも更新されます。Ctrl+Cで監視を止めます。

とりあえずステータスを確認し、プロセスを確認し、LISTEN状態を確認します:

$ sudo service apache2 status
Apache2 is running (pid 2210).
$ ps -fe | grep 2210
root      2210     1  0 00:27 ?        00:00:00 /usr/sbin/apache2 -k start
www-data  2213  2210  0 00:27 ?        00:00:00 /usr/sbin/apache2 -k start
www-data  2214  2210  0 00:27 ?        00:00:00 /usr/sbin/apache2 -k start
www-data  2215  2210  0 00:27 ?        00:00:00 /usr/sbin/apache2 -k start
vagrant   2511  1406  0 00:40 pts/0    00:00:00 grep --color=auto 2210
$ sudo ss -lpn | grep apache2
LISTEN     0      128                       *:80                       *:*      users:(("apache2",2215,3),("apache2",2214,3),("apache2",2210,3))

Apache2のUFW設定

上では'Apache Full'に許可を与えましたが、Apacheには3つのプロファイルがあります。

$ sudo ufw app list
利用可能なアプリケーション:
  Apache
  Apache Full
  Apache Secure

Apacheはhttpのみ(ポート80)、Apache Fullはhttpとhttps(ポート443)、Apache Secureはhttpsのみを表しています。

SSL接続が必要なければ、ufwでallowするのはApacheのみでかまいません。

Apache2の設定その1

Apache2の設定については知っておくべきことがたくさんあるので、ここでは「その1」としておきます。いずれ「その2」も書きます。

Ubuntuで稼働させるApacheサーバについて、前提として知っておくべきことは

  • Ubuntuではパッケージ名はhttpdではなくapache2である
  • Ubuntuでは設定ファイルが/etc/apache2以下のapache2.confなど多数ある
  • Ubuntuではデフォルトのドキュメントルートが/var/wwwである
  • Ubuntuではログファイルは/var/log/apache2に格納される
  • デフォルトではMPM(Multi Processing Module)にworkerが導入される
  • 設定には、モジュールを有効化/無効化するa2enmod/a2dismod、サイトを有効化/無効化するa2ensite/a2dissiteを使う

MPMはデフォルトでworkerが導入されます。MPMには他にeventとpreforkがあります。

eventは実験的なモジュールで、Apache2.4で採用されるモジュールです(Ubuntuのパッケージ版では、現時点では2.2が採用されている)。

preforkはマルチスレッドに正しく対応していないApacheモジュールを使うときに使用するMPMです。たとえばPHPはpreforkを前提にしているので、PHPを使うときはpreforkにするべきです。Apache2がインストールされている状態で、PHPをインストールすると、自動的にpreforkが導入されます(workerは削除される)。

PHPを動かす目的でなければ、worker版が適しているでしょう。

次に、サイトの有効化を使ってみます。

設定ファイルは/etc/apache2/sites-availableにあります。デフォルトではdefaultとdefault-sslの2つのファイルがあります。

このデフォルトファイルをコピーして、サイトごとの設定を行います。

$ cd /etc/apache2/sites-available
$ sudo cp default www

ここでは、defaultファイルのコピーとしてwwwを作りました(名前はなんでもよい)。wwwファイルをsudo viで開いて、次の箇所を変更します:

  • DocumentRootを/var/wwwから/vagrant
  • <Directory /var/www/>から<Directory /vagrant/>へ
  • ※もしホスト名の指定があれば、ServerAdminの次の行あたりにServerAlias www.domain.comのように挿入

ファイルを修正したら保存して閉じます。

/vagrantディレクトリはすでにあるはずなので、mkdirする必要はないです。

$ cd /vagrant
$ echo "hello vagrant" > index.html

と仮のhtmlファイルを作っておきます。

サイトを有効化します:

$ sudo a2ensite www
Enabling site www.
To activate the new configuration, you need to run:
  service apache2 reload

先のwwwファイルがsites-enabledにコピーされました。現時点では、先にsites-enabledにある000-defaultがensiteされており、192.168.33.20にアクセスしたときに、アルファベット順で先にくる000-defaultが読まれてしまうので、これをdissiteします。

$ sudo a2dissite 000-default
Site default disabled.
To activate the new configuration, you need to run:
  service apache2 reload

apache2サービスをリロードすると、設定が有効になります。

$ sudo service apache2 reload

ホスト側のブラウザでhttp://192.168.33.20にアクセスして、「hello vagrant」と表示されれば、成功です。

ゲストの/vagrantディレクトリはホストのVagrantfileがあるディレクトリと共有フォルダになっているので、ホストで開発して、ゲストのサーバを使って挙動確認する、ということができるようになりました。

etckeeper commitしておきます。


次回はどうするか、決めてません。Apache2設定その2にするか、rbenvか、phpか、その辺を考えています。