さくらVPS上でLAMP環境を構築した際の覚書です。
すでに、VPS上でUbuntu Server 18.04がインストールされた直後、という条件で設定をしていきます。

今回は、Apache2.4のインストールと、関連する部分の設定をします。

 

apache logo

 

ゴール

  • Apache2.4を使用する
  • 各種セキュリティ設定を実施する
  • デフォルトのサイトでSSLを使用(https)
  • 80番ポートへのアクセス(http)は、全てhttpsへリダイレクトする
  • 証明書は、デフォルトでインストールされている証明書(自己認証証明書)を仮に使用する

 

Apacheのインストール

Ubuntuのパッケージからインストールします。

$ sudo apt install apache2

 

セキュリティの設定

 

ApacheとOSのバージョン情報を隠蔽する

Apacheと、OSのバージョン情報が外部からは見えないようにします。

$sudo vi /etc/apache2/conf-enabled/security.conf
ServerSignature Off
ServerTokens Prod

 

IndexesとFollowSymLinksオプションを無効に

インストール直後は有効になっている、IndexesFollowSymlinks の2つのオプションを無効にします。

Indexes オプションは、有効なページがなかった場合に、そのディレクトリのファイルやディレクトリの一覧を表示するので、全体でOffにし、FollowSymLinks は、個別のロケーションで有効にします。

$ sudo vi /etc/apache2/apache2.conf
<Directory /var/www/>
        Options -Indexes -FollowSymLinks
        AllowOverride None
        Require all granted
</Directory>

 

mod_securityを利用する

https://www.linode.com/docs/web-servers/apache-tips-and-tricks/configure-modsecurity-on-apache/

オープンソースのウェブアプリケーションファイアウォール (WAF) である、mod_security をインストールします。

$ sudo apt install libapache2-mod-security2 -y
$ sudo cp /etc/modsecurity/modsecurity.conf-recommended /etc/modsecurity/modsecurity.conf
$ sudo vi /etc/modsecurity/modsecurity.conf
SecRuleEngine On

 

デフォルトのルールセットを、GitHubから取得する

  • 既存のディレクトリの名前を変更する
$ sudo mv /usr/share/modsecurity-crs /usr/share/modsecurity-crs.bk
  • 新しいルールセットをGitHubからクローン
$ sudo git clone https://github.com/SpiderLabs/owasp-modsecurity-crs.git /usr/share/modsecurity-crs
  • サンプルのコンフィグファイルをコピー
$ sudo cp /usr/share/modsecurity-crs/crs-setup.conf.example /usr/share/modsecurity-crs/crs-setup.conf
  • これらのコンフィグを有効にするために、/etc/apache2/mods-enabled/security2.confに、次の項目を追加する
IncludeOptional /usr/share/modsecurity-crs/*.conf
IncludeOptional /usr/share/modsecurity-crs/rules/*.conf
  • Apacheを再起動させる
$ sudo systemctl restart apache2

 

テスト

/etc/apache2/sites-enabled/000-default.conf を編集して、次の <IfModule security2_module>...</IfModule> を追加する。

$ sudo vi /etc/apache2/sites-enabled/000-default.conf
<VirtualHost *:80>
    ServerAdmin webmaster@localhost

    DocumentRoot /var/www/html
            :
    <IfModule security2_module>
        # test
        SecRule ARGS:testparam "@contains test" "id:1234,deny,status:403,msg:'Our test rule has triggered'"
    </IfModule>
            :
</VirtualHost>
  • Apacheを再起動させる
$ sudo systemctl restart apache2
  • curlのインストール
$ sudo apt install curl
  • curlで次のように実行し、レスポンスに403が返ってくるか確認。
$ curl http://localhost?testparam=test
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>403 Forbidden</title>
</head><body>
<h1>Forbidden</h1>
<p>You don't have permission to access /
on this server.<br />
</p>
</body></html>

また、/var/log/apache2/errors.log に次のようなログが残っていることを確認する。

[Wed Feb 13 11:59:10.081578 2019] [:error] [pid 14878] [client ::1:60478] [client ::1] ModSecurity: Access denied with code 403 (phase 2). String match "test" at ARGS:testparam. [file "/etc/apache2/sites-enabled/default-ssl.conf"] [line "28"] [id "1234"] [msg "Our test rule has triggered"] [hostname "localhost"] [uri "/"] [unique_id "XGOH-kekkqfvPiKDe2Vz0AAAAAM"]

再度、curl で次のように実行し、同じく403が返ってくるのを確認。

$ curl http://localhost/index.html?exec=/bin/bash
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>403 Forbidden</title>
</head><body>
<h1>Forbidden</h1>
<p>You don't have permission to access /index.html
on this server.<br />
</p>
</body></html>

また、/var/log/apache2/errors.log には次のように記録されます。

[Wed Feb 13 12:14:18.788207 2019] [:error] [pid 14878] [client ::1:60488] [client ::1] ModSecurity: Warning. Operator GE matched 5 at TX:inbound_anomaly_score. [file "/usr/share/modsecurity-crs/rules/RESPONSE-980-CORRELATION.conf"] [line "86"] [id "980130"] [msg "Inbound Anomaly Score Exceeded (Total Inbound Score: 5 - SQLI=0,XSS=0,RFI=0,LFI=0,RCE=5,PHPI=0,HTTP=0,SESS=0): Remote Command Execution: Unix Shell Code Found; individual paranoia level scores: 5, 0, 0, 0"] [tag "event-correlation"] [hostname "localhost"] [uri "/index.html"] [unique_id "XGOLikekkqfvPiKDe2Vz0QAAAAM"]

一通りテストができたら、000-default.conf<IfModule security2_module>...</IfModule>は、削除しておいてください。

 

mod_evasiveを利用する

mod_evasive は、Apacheのモジュールで、DDoS/DoS 攻撃やブルートフォース攻撃を回避するための機能を提供しています。また、そういった攻撃を検知した場合、メールやsyslogで報告されます。

mod_evasive のインストール

$ sudo apt install libapache2-mod-evasive

途中、Postfix Configuration の画面が出てきたときは、[[No configuration]]を選択。

  • 動作を確認
$ sudo apachectl -M | grep evasive
 evasive20_module (shared)
  • /etc/apache2/mods-available/evasive.conf を編集し、コメントを解除します。
$ sudo vi /etc/apache2/mods-available/evasive.conf
<IfModule mod_evasive20.c>
    DOSHashTableSize    3097
    DOSPageCount        5
    DOSSiteCount        50
    DOSPageInterval     1
    DOSSiteInterval     1
    DOSBlockingPeriod   300

    DOSEmailNotify      you@yourdomain.com
    #DOSSystemCommand    "su - someuser -c '/sbin/... %s ...'"
    DOSLogDir           "/var/log/mod_evasive"
</IfModule>
  • ログを保存するディレクトリを作成
$ sudo mkdir /var/log/mod_evasive
$ chown www-data /var/log/mod_evasive
  • Apacheを再起動する
$ sudo systemctl restart apache2

 

各項目の説明

DOSHashTableSize
ハッシュテーブルのサイズ。大きければパフォーマンスがアップする代わりに、メモリ消費が多くなります。
DOSPageCount
PageIntervalの間に、同じページやURIにリクエストした回数の閾値。閾値を超えると、クライアントのIPアドレスがブロックリストに追加されます。
DOSSiteCount
SiteIntervalの間に、同じリスナーの同じクライアントによるリクエストの総数の閾値です。閾値を超えると、クライアントのIPアドレスがブロックリストに追加されます。
DOSPageInterval
ページカウントの閾値のための間隔。デフォルトは1秒
DOSSiteInterval
サイトカウントの閾値のための間隔。デフォルトは1秒
DOSBlockingPeriod
ブロックされたクライアントが接続をブロックされる期間(秒)。ブロックされている間は、403を返します。ブロック中に再度リクエストするとタイマーはさらに、指定された秒数にリセットされます。
DOSSystemCommand
IPアドレスがブラックリストに登録される度に、ここで指定されたコマンドを実行します。
DOSEmailNotify
IPアドレスがブラックリストに登録される度に、指定されたメールアドレスにメールを送信します。
DOSLogDir
ログの保存先。デフォルトは/tmp
DOSWhitelist
信頼されているクライアントのIPアドレス。

 

テスト

ネットで調べたとおりにテストを実行してみます。テストには、test.pl を使用します。

$ cd /usr/share/doc/libapache2-mod-evasive/examples/
$ sudo chmod +x test.pl
$ perl test.pl
HTTP/1.1 400 Bad Request
HTTP/1.1 400 Bad Request
HTTP/1.1 400 Bad Request
HTTP/1.1 400 Bad Request
HTTP/1.1 400 Bad Request
HTTP/1.1 400 Bad Request
HTTP/1.1 400 Bad Request
HTTP/1.1 400 Bad Request
        :
HTTP/1.1 400 Bad Request

ところが、このように期待した結果が出ません。

本来は、HTTP/1.1 200 OK が何行か表示された後に、HTTP/1.1 403 Forbidden が連続して表示されるのですが、この場合は 400 Bad Request となっています。

以下のようにするとテストできます(https://qiita.com/crazyhacks/items/2cfc36be38846d1406cf)。

$ yes 'exec 4<>/dev/tcp/127.0.0.1/80; printf "GET / HTTP/1.0\r\n\r\n" >&4; head -1 <&4' | head -100 | bash
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
    :
HTTP/1.1 403 Forbidden

最初に数回は、ステータス200番を返していたものが、途中から403番に変わっています。

次に、ブロックした際に作成されたログファイルを確認します。

$ ls -al /var/log/mod_evasive/
total 12
drwxr-xr-x 2 www-data www-data 4096 Feb 13 20:41 .
drwxrwxr-x 8 root     syslog   4096 Feb 13 20:09 ..
-rw-r--r-- 1 www-data www-data    4 Feb 13 20:41 dos-127.0.0.1

このようにdos-IPアドレスという形で残っています。

念の為、localhostからのアクセスは拒否しないように、/etc/apache2/mods-available/evasive.conf

DOSWhitelist 127.0.0.1

を追加しておきます。

 

TRACE リクエストの無効化

Cross-Site Tracing(XST) 対策のためにTRACEメソッドを無効にします。

sudo vi /etc/apache2/conf-enabled/security.conf
  • TraceEnableOffか確認する(デフォルトでOffのはずです)。
TraceEnable off
  • Apacheを再起動させる
  • TRACEが無効になっているのを確認

HTTPの場合は、curl -v -X TRACE [URL]

HTTPSの場合は、curl --insecure -v -X TRACE [URL]

$ curl --insecure -v -X TRACE https://www.example.jp/
  :
  :
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>405 Method Not Allowed</title>
</head><body>
<h1>Method Not Allowed</h1>
<p>The requested method TRACE is not allowed for the URL /.</p>
</body></html>

Method Not Allowedと出ていればOK

 

クリックジャッキング対策

  • mod_headers を有効にする。
$ sudo a2enmod headers
  • /etc/apache2/conf-available/security.confHeader set X-Frame-Options:の値を"sameorigins"にする(コメントを解除する)。
Header set X-Frame-Options: "sameorigin"

 

apache2 を再起動

$ sudo systemctl restart apache2

 

SSLを有効に

httpの通信をSSL/TLSで暗号化された経路でのみ受け付けるようにします。

 

モジュールを有効に

mod_rewirte

$ sudo a2enmod rewrite
Enabling module rewrite.
To activate the new configuration, you need to run:
  systemctl restart apache2

mod_ssl

$ sudo a2enmod ssl
Considering dependency setenvif for ssl:
Module setenvif already enabled
Considering dependency mime for ssl:
Module mime already enabled
Considering dependency socache_shmcb for ssl:
Module socache_shmcb already enabled
Enabling module ssl.
See /usr/share/doc/apache2/README.Debian.gz on how to configure SSL and create self-signed certificates.
To activate the new configuration, you need to run:
  systemctl restart apache2

 

httpへのリクエストをhttpsにリダイレクト

80番ポートへのhttpリクエストをすべて、443番にリダイレクトします。

/etc/apache2/sites-available/000-default.conf に、次のように変更する。

$ sudo vi /etc/apache2/sites-available/000-default.conf
<VirtualHost *:80>
    ServerAdmin webmaster@localhost
    DocumentRoot /var/www/html

    RewriteEngine On
    RewriteCond %{HTTPS} off
    RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

ここでは、RewriteEngine On でmod_rewriteモジュールを有効にしてURLの書き換えをできるようにしています。

意味は:

RewriteCond %{HTTPS} off で「コネクションがSSL/TLSを利用していない場合」に次の行に処理を渡します。

次の行、RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L] では、すべてのリクエスト(^(.*)$)を、R=301、要するにリダイレクトし、リダイレクト先を元のリクエストURLのhttp の部分を https に書き換えたURLにして、L で処理を終了、と読みます。

 

証明書とキーの指定

/etc/apache2/sites-available/default-ssl.conf の次の項目に、証明書とキーのファイルを指定します。

$ sudo vi /etc/apache2/sites-available/default-ssl.conf
SSLCertificateFile  /etc/ssl/certs/ssl-cert-snakeoil.pem
SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key
ここでは、インストール時に付属してくる自己認証の証明書とキーを使用していますが、本番サイトでは、正式な認証局から取得した証明書とキーを使用します。

 

サイトを有効化

000-default.conf と、default-ssl.conf を有効にする。( 000-default.conf はすでに有効になっているはず)

$ sudo a2ensite 000-default.conf
Site 000-default already enabled
$ sudo a2ensite default-ssl.conf
Enabling site default-ssl.
To activate the new configuration, you need to run:
  systemctl reload apache2

apacheを再起動します。

$ sudo systemctl restart apache2

 

リダイレクトをテスト

curl -I http://localhost/ として確認。

$ curl -I http://localhost/
HTTP/1.1 301 Moved Permanently
Date: Wed, 13 Feb 2019 04:22:09 GMT
Server: Apache
Location: https://localhost/
Content-Type: text/html; charset=iso-8859-1

HTTP/1.1 301 Moved Permanetly と表示されていればOK。

実際にリダイレクト出来たかどうかを確認する場合は、curl -IL --insecure http://localhost とします。

$ curl -IL --insecure http://localhost
HTTP/1.1 301 Moved Permanently
Date: Wed, 13 Feb 2019 10:54:10 GMT
Server: Apache/2.4.29 (Ubuntu)
Location: https://localhost/
Content-Type: text/html; charset=iso-8859-1

HTTP/1.1 200 OK
Date: Wed, 13 Feb 2019 10:54:10 GMT
Server: Apache/2.4.29 (Ubuntu)
Last-Modified: Wed, 13 Feb 2019 10:45:17 GMT
ETag: "2aa6-581c43cd62071"
Accept-Ranges: bytes
Content-Length: 10918
Vary: Accept-Encoding
Content-Type: text/html

で、まずhttpによるアクセスで、301 Moved Permanetry でリダイレクトされ、その次に 200 OK と出ています。

自己認証局の証明書等を使用している場合、curlはエラーを吐いて止まるので、--insecureオプションを付けて下さい

 

ファイアウォールの設定

ポートの 80/tcp443/tcp を開放します。

$ sudo ufw allow http
Rule added
Rule added (v6)
$ sudo ufw allow https
Rule added
Rule added (v6)
$ sudo ufw status
Status: active

To                         Action      From
--                         ------      ----
60022                      ALLOW       Anywhere
80/tcp                     ALLOW       Anywhere
443/tcp                    ALLOW       Anywhere
60022 (v6)                 ALLOW       Anywhere (v6)
80/tcp (v6)                ALLOW       Anywhere (v6)
443/tcp (v6)               ALLOW       Anywhere (v6)

最後に、実際のURLに接続してApache2 Ubuntu Default Pageが表示されるか確認します。


 
記事を共有する
カテゴリー: apacheLinuxubuntu

zaturendo

中小企業社内SE。

0件のコメント

コメントを残す

メールアドレスが公開されることはありません。