VagrantでUbuntuサーバ/UFW/Apache2
VagrantでUbuntuサーバの基本構成の練習をしようシリーズ、続きです。
これまでにやったこと:
- VirtualBoxにUbuntuサーバをインストール、openssh-serverをインストール、vagrantの使用するインセキュア・キーの設置、Guest Additionのインストール、VagrantでBase Boxを作成、Vagrantでアップしてssh
- デフォルトエディタをvim-noxに変更、etckeeper/git/tigのインストール、NTPのインストール
- IPアドレスの固定(Vagrantの場合Vagrantfileの書き換えで対応するため/etc/networkファイルをいじるということだけメモしました)、SSHポートの変更(これもVagrantだとややこしくなるのでメモだけにしました)
前回の記事から今日までにVagrantのアップデートがあったので更新しました。
環境:
- VirtualBox 4.3.8
- Vagrant 1.5.1
- Ubuntu Server 12.04
今日触れる項目:
パスワード認証の無効化
ブルートフォース攻撃は、ランダムに選ばれたあるいはターゲットにされた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か、その辺を考えています。