記事一覧
- AWS EC2でサーバを構築 1 - Amazon Linux 2 準備編
- AWS EC2でサーバを構築 2 - 各種インストール編
- AWS EC2でサーバを構築 3 - Apache + Let's Ecnrypt + PHP-FPM編 (脆弱性診断「A+」を狙う)
- AWS EC2でサーバを構築 4 - Nginx + Let's Ecnrypt + PHP-FPM編 (脆弱性診断「A+」を狙う)
- AWS EC2でサーバを構築 5 - MySQL + phpMyAdmin
- AWS EC2でサーバを構築 6 - PostfixとDovecot (SSL対応とSPAM対策)
- AWS EC2でサーバを構築 7 - セキュリティ対策
概要
ウェブサーバにApacheを使用する場合、本記事は読み飛ばしてください。
Nginx、SSL (Let's Ecnrypt)、PHP-FPMの設定を行います。また脆弱性診断で最高の「A+」を狙います。
Apacheを設定済みの場合は削除するか、
systemctl disable httpd
しておいてください。削除を推奨します。
脆弱性診断結果
結論から書いてしまいますが、以下の設定でSSL Labsの脆弱性診断を行ったところ最高の「A+」となりました。
当初は「A」でしたが、設定を見直して「A+」を達成できました。以下の通りの設定で「執筆時点では」「A+」になるはずです。
Nginx
エラー画面でバージョンを吐かないようにし、SSLに関するデフォルト設定を書いておきます。
ここが脆弱性診断「A+」のキモとなります。
注意:以下はserver
ではなくhttp
ディレクティブに追加してください。
/etc/nginx/nginx.conf
server_tokens off;
ssl_protocols TLSv1.2;
ssl_stapling on;
ssl_stapling_verify on;
ssl_session_cache shared:SSL:50m;
ssl_session_timeout 1d;
ssl_ciphers HIGH:MEDIUM:!aNULL:!MD5:!SEED:!IDEA:!3DES:!RC4:!DH;
ssl_prefer_server_ciphers on;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";
Amazon Linux 2のOpenSSLが1.0.2kなので、OpenSSL 1.1.1以降が必要となるTLSv1.3は設定できません。
バーチャルホスト
バーチャルホスト用に公開ディレクトリを作成しておきます。
Apacheとの互換を維持するため、var/www
で始まりpublic_html
で終わるようにしています。
mkdir -p /var/www/html/www.example1.com/public_html
mkdir -p /var/www/html/www.example2.com/public_html
chown -R nginx. /var/www/html
Let's Ecnryptの証明書取得時にはssl_certificate
とssl_certificate_key
の行はコメントアウトしておきます。
また設定ファイル内でドメイン正規化 (wwwありに統一) を行います。Apacheの.htaccess
が使えないためです。
/etc/nginx/conf.d/www.example1.com.conf
server {
listen 80;
listen 443 ssl http2;
server_name example1.com;
return 301 https://www.$host$request_uri;
ssl_certificate "/etc/letsencrypt/live/example1.com/fullchain.pem";
ssl_certificate_key "/etc/letsencrypt/live/example1.com/privkey.pem";
include /etc/nginx/default.d/*.conf;
}
server {
listen 80;
server_name www.example1.com;
root /var/www/html/www.example1.com/public_html;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name www.example1.com;
root /var/www/html/www.example1.com/public_html;
ssl_certificate "/etc/letsencrypt/live/www.example1.com/fullchain.pem";
ssl_certificate_key "/etc/letsencrypt/live/www.example1.com/privkey.pem";
include /etc/nginx/default.d/*.conf;
location / {
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
Aapcheの例と同じく、www.example2.comはBASIC認証を設定します。
生成サービスを利用して暗号化パスワードを生成しておきます。
/var/www/html/www.example2.com/.htpasswd
{ユーザー名}:{暗号化されたパスワード}
Apacheと異なり.htaccessが使えないため、設定ファイル内にBASIC認証の設定を記述します。
/etc/nginx/conf.d/www.example2.com.conf
server {
listen 80;
server_name www.example2.com;
root /var/www/html/www.example2.com/public_html;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name www.example2.com;
root /var/www/html/www.example2.com/public_html;
ssl_certificate "/etc/letsencrypt/live/www.example2.com/fullchain.pem";
ssl_certificate_key "/etc/letsencrypt/live/www.example2.com/privkey.pem";
include /etc/nginx/default.d/*.conf;
location / {
auth_basic "Enter your ID and Password";
auth_basic_user_file /var/www/html/www.example2.com/.htpasswd;
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
SSL証明書取得
Let's Ecnryptの証明書を取得します。
certbot certonly --webroot -w /var/www/html/www.example1.com/public_html/ -d example1.com -m root@example1.com
certbot certonly --webroot -w /var/www/html/www.example1.com/public_html/ -d www.example1.com -m root@example1.com
certbot certonly --webroot -w /var/www/html/www.example2.com/public_html/ -d www.example2.com -m root@example1.com
証明書の自動更新
月曜と木曜の4時0分に自動更新されるようにします。
Let's Ecnrypt証明書の期限は3ヶ月です。更新は週に5回までの制限があります。
crontab -e
0 4 * * 1,4 certbot renew --post-hook "systemctl restart nginx php-fpm postfix dovecot"
CAAレコード追加
脆弱性診断への対策のため、DNSサーバ (ネームサーバ) でCAAレコードを追加します。
できない場合やわからない場合は読み飛ばしてください。ただし診断結果に若干影響する可能性があります。
example1.com. 3600 IN CAA 0 issue "letsencrypt.org"
example2com. 3600 IN CAA 0 issue "letsencrypt.org"
PHP-FPM
まずはPHPそのものの設定を行います。環境によって調整してください。
/etc/php.ini
;expose_php = On
expose_php = Off
; max_execution_time = 30
max_execution_time = 120
; memory_limit = 128M
memory_limit = 256M
; post_max_size = 8M
post_max_size = 128M
; upload_max_filesize = 2M
upload_max_filesize = 128M
;date.timezone =
date.timezone = Asia/Tokyo
; session.gc_maxlifetime = 1440
session.gc_maxlifetime = 86400
チューニング
実行ユーザー/グループの設定とパフォーマンスチューニングの設定を行います。環境によって調整してください。
/etc/php-fpm.d/www.conf
; user = apache
user = nginx
; group = apache
group = nginx
;listen.owner = nobody
;listen.group = nobody
;listen.mode = 0660
listen.owner = nginx
listen.group = nginx
listen.mode = 0660
; pm.max_children = 50
pm.max_children = 30
; pm.start_servers = 5
pm.start_servers = 10
; pm.min_spare_servers = 5
pm.min_spare_servers = 10
; pm.max_spare_servers = 35
pm.max_spare_servers = 25
;pm.max_requests = 500
pm.max_requests = 30
NginxとPHP-FPMを再起動します。これは設定を変更するたびに行います。
systemctl restart nginx php-fpm
Composer
Laravel等で使用するcomposerをインストールしておきます。
curl -sS https://getcomposer.org/installer | php
mv composer.phar /usr/local/bin/composer
トラブルシューティング
/var/lib/php
内のセッションやキャッシュ用ディレクトリの所有グループがapacheになっている場合の対処法です。
chgrp nginx /var/lib/php/opcache
chgrp nginx /var/lib/php/session
chgrp nginx /var/lib/php/wsdlcache
セッションについては中のファイルがapache:apache
な状態になっている場合があるので修正。
chown nginx. /var/lib/php/sesion/*