サーバ構築・管理

AWS EC2でサーバを構築 4 – Nginx + Let’s Ecnrypt + PHP-FPM編 (脆弱性診断「A+」を狙う)

AWSのEC2でセキュアなサーバ構築をするシリーズその4です。NginxとLet’s Ecnrypt、PHP-FPMを設定し、脆弱性診断「A+」を目指します。

記事一覧

  1. Amazon Linux 2 準備編
  2. 各種インストール編
  3. Apache + Let's Ecnrypt + PHP-FPM編 (脆弱性診断「A+」を狙う)
  4. Nginx + Let's Ecnrypt + PHP-FPM編 (脆弱性診断「A+」を狙う)
  5. MySQL + phpMyAdmin
  6. PostfixとDovecot (SSL対応とSPAM対策)
  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_certificatessl_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/*
ABOUT ME
りゅう・д・
愛知のWeb系エンジニア/クリエイターです。 サーバ構築・管理からシステム開発、Webデザイン、WordPress構築からヘルプデスクまで、割と手広く手掛けています。

COMMENT

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です