Chuyển đến nội dung chính

第7課:NginxにおけるSSL/TLSとHTTPS

NginxにおけるSSL/TLSとHTTPSのレッスンーLet's EncryptによるSSL証明書の設定、 HTTPからHTTPSへのリダイレクト、SSLプロトコルと暗号の最適化、 HSTS、OCSPステープリング、HTTP/2。 接続の保護、パフォーマンス最適化、SSL Labs A+評価の取得ガイド。

🔒 DevSecOps — 第7課 第7課:NginxにおけるSSL/TLSとHTTPS Nginxの基礎から応用まで 第3部:セキュリティ & パフォーマンス xdev.asia

1. SSL証明書の設定(Let's Encrypt)

1.1. SSL/TLSの概要

SSL(Secure Sockets Layer)/ TLS(Transport Layer Security)は、クライアントとサーバー間の通信を暗号化するプロトコルです。

HTTPSが必要な理由:

  • データセキュリティ(暗号化)
  • サーバー認証
  • データ整合性
  • SEOメリット(Googleランキング)
  • ブラウザの信頼(警告なし)
  • HTTP/2に必要
  • PWA(プログレッシブウェブアプリ)に必要

認証局(CA):

  • Let's Encrypt - 無料、自動化
  • DigiCert、Comodo、GlobalSign - 商用
  • 自己署名 - 開発環境のみ

1.2. Certbotのインストール(Let's Encryptクライアント)

Ubuntu/Debian:

# パッケージリストを更新
sudo apt update

Certbotをインストール

sudo apt install certbot python3-certbot-nginx -y

インストールを確認

certbot --version

CentOS/RHEL:

# EPELリポジトリをインストール
sudo yum install epel-release -y

Certbotをインストール

sudo yum install certbot python3-certbot-nginx -y

CentOS 8+の場合

sudo dnf install certbot python3-certbot-nginx -y

1.3. SSL証明書の取得 — 自動方式

方法1:Certbot自動設定

# CertbotがNginxを自動設定
sudo certbot --nginx -d example.com -d www.example.com

プロンプトに従う:

- メールアドレスを入力

- 利用規約に同意

- 選択:HTTPをHTTPSにリダイレクト(推奨)

Certbotの処理:

  1. ドメイン所有権を確認
  2. 証明書を取得
  3. Nginxを自動設定
  4. 自動更新を設定

証明書を確認:

# 証明書一覧
sudo certbot certificates

出力例:

Certificate Name: example.com

Domains: example.com www.example.com

Expiry Date: 2024-03-01 10:30:00+00:00 (VALID: 89 days)

Certificate Path: /etc/letsencrypt/live/example.com/fullchain.pem

Private Key Path: /etc/letsencrypt/live/example.com/privkey.pem

1.4. SSL証明書の取得 — 手動方式

方法2:Certbot certonly(手動設定)

# 自動設定なしで証明書を取得
sudo certbot certonly --nginx -d example.com -d www.example.com

またはwebrootを使用

sudo certbot certonly --webroot -w /var/www/html -d example.com -d www.example.com

またはstandalone(Nginxを一時停止)

sudo systemctl stop nginx sudo certbot certonly --standalone -d example.com -d www.example.com sudo systemctl start nginx

手動Nginx設定:

server {
listen 80;
server_name example.com www.example.com;

# ACME challengeの場所
location /.well-known/acme-challenge/ {
    root /var/www/html;
}

# HTTPSにリダイレクト
location / {
    return 301 https://$server_name$request_uri;
}

}

server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name example.com www.example.com;

# SSL証明書ファイル
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

# SSL設定
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;

root /var/www/html;
index index.html;

location / {
    try_files $uri $uri/ =404;
}

}

1.5. 証明書の更新

Let's Encryptの証明書は90日で期限切れになります。Certbotは自動更新を設定します。

更新のテスト:

# ドライラン(実際に更新せずテスト)
sudo certbot renew --dry-run

手動更新:

# すべての証明書を更新
sudo certbot renew

特定の証明書を更新

sudo certbot renew --cert-name example.com

更新後にNginxをリロード

sudo certbot renew --deploy-hook "systemctl reload nginx"

自動更新(systemdタイマー):

# タイマーが有効か確認
sudo systemctl status certbot.timer

タイマーを有効化

sudo systemctl enable certbot.timer sudo systemctl start certbot.timer

1.6. ワイルドカード証明書

sudo certbot certonly --manual --preferred-challenges dns 
-d example.com -d *.example.com

DNSのTXTレコードを追加する手順に従う

_acme-challenge.example.com TXT "generated-token"

DNS伝播を確認

dig _acme-challenge.example.com TXT

1.7. 複数ドメイン

# 1つの証明書に複数ドメイン
sudo certbot --nginx 
-d example.com -d www.example.com
-d blog.example.com -d shop.example.com

2. HTTPからHTTPSへのリダイレクト

2.1. シンプルなリダイレクト

server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;

# すべてのHTTPをHTTPSにリダイレクト
return 301 https://$server_name$request_uri;

}

server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name example.com www.example.com;

ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

root /var/www/html;
index index.html;

}

2.2. ACME Challengeを含むリダイレクト

server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;

# ACME challengeを許可
location /.well-known/acme-challenge/ {
    root /var/www/html;
    allow all;
}

# それ以外はHTTPSにリダイレクト
location / {
    return 301 https://$server_name$request_uri;
}

}

2.3. wwwからnon-wwwへのリダイレクト(HTTPS)

# wwwをnon-wwwにリダイレクト
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name www.example.com;

ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

return 301 https://example.com$request_uri;

}

メインサイト

server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name example.com;

ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

# サイト設定...

}

2.4. 完全なリダイレクト設定

# HTTP - HTTPSにリダイレクト
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;

location /.well-known/acme-challenge/ {
    root /var/www/html;
}

location / {
    return 301 https://example.com$request_uri;
}

}

HTTPS www - non-wwwにリダイレクト

server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name www.example.com;

ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

return 301 https://example.com$request_uri;

}

メインHTTPSサーバー

server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name example.com;

ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;

root /var/www/html;
index index.html;

location / {
    try_files $uri $uri/ =404;
}

}


3. SSLプロトコルと暗号

3.1. SSL/TLSプロトコル

利用可能なプロトコル:

  • SSLv2 - 廃止、安全でない ❌
  • SSLv3 - 廃止、安全でない ❌
  • TLSv1.0 - 廃止、避けるべき ⚠️
  • TLSv1.1 - 廃止、避けるべき ⚠️
  • TLSv1.2 - 安全、広くサポート ✅
  • TLSv1.3 - 最も安全、最新 ✅

推奨設定:

server {
listen 443 ssl http2;
server_name example.com;

ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

# TLS 1.2と1.3のみ使用
ssl_protocols TLSv1.2 TLSv1.3;

# サーバー暗号を優先(TLS 1.2向け)
ssl_prefer_server_ciphers off;  # TLS 1.3は自動処理

}

3.2. SSL暗号

暗号は使用する暗号化アルゴリズムを決定します。

Mozilla中間設定(バランス):

server {
listen 443 ssl http2;
server_name example.com;

ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

# プロトコル
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;

# TLS 1.2向け暗号
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;

}

完全なSSL設定:

server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name example.com;

# 証明書ファイル
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

# プロトコル
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;

# 暗号
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;

# セッションキャッシュ
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_session_tickets off;

# DHパラメータ
ssl_dhparam /etc/nginx/dhparam.pem;

# OCSPステープリング
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;

}

3.3. DHパラメータの生成

Diffie-Hellmanパラメータはセキュリティを強化します。

# 2048ビットのDHパラメータを生成(数分かかる)
sudo openssl dhparam -out /etc/nginx/dhparam.pem 2048

または4096ビット(時間がかかるが、より安全)

sudo openssl dhparam -out /etc/nginx/dhparam.pem 4096

権限を設定

sudo chmod 644 /etc/nginx/dhparam.pem

3.4. SSLセッション設定

http {
# SSLセッションキャッシュ(ワーカー間で共有)
ssl_session_cache shared:SSL:10m;  # 10MB = 約40,000セッション

# セッションタイムアウト
ssl_session_timeout 10m;           # 10分

# セッションチケットを無効化(完全前方秘匿性)
ssl_session_tickets off;

}


4. HSTS(HTTP Strict Transport Security)

HSTSはブラウザに常にHTTPSを使用するよう指示します。

4.1. 基本HSTS

server {
listen 443 ssl http2;
server_name example.com;

# HSTSヘッダー
add_header Strict-Transport-Security "max-age=31536000" always;

}

max-age値:

# テスト - 1時間
add_header Strict-Transport-Security "max-age=3600" always;

短期 - 1週間

add_header Strict-Transport-Security "max-age=604800" always;

推奨 - 1年

add_header Strict-Transport-Security "max-age=31536000" always;

最大 - 2年

add_header Strict-Transport-Security "max-age=63072000" always;

4.2. includeSubDomainsを含むHSTS

server {
listen 443 ssl http2;
server_name example.com;

# すべてのサブドメインにHSTSを適用
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

}

警告: includeSubDomainsはすべてのサブドメインに影響します。すべてのサブドメインがHTTPSをサポートしていることを確認してください。

4.3. HSTSプリロード

server {
listen 443 ssl http2;
server_name example.com;

# preloadディレクティブを含むHSTS
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;

}

HSTSプリロードリストへの登録:

  1. https://hstspreload.org/ にアクセス
  2. ドメインを入力
  3. 要件を確認:
    • 有効な証明書を提供
    • HTTPをHTTPSにリダイレクト
    • ベースドメインでHSTSヘッダーを提供
    • max-age ≥ 31536000(1年)
    • includeSubDomainsディレクティブ
    • preloadディレクティブ

4.4. 完全なHSTS設定

# HTTP - HTTPSにリダイレクト
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;

location /.well-known/acme-challenge/ {
    root /var/www/html;
}

location / {
    return 301 https://example.com$request_uri;
}

}

HTTPSサーバー

server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name example.com www.example.com;

ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;

# HSTSヘッダー
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;

# セキュリティヘッダー
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;

root /var/www/html;
index index.html;

}


5. OCSPステープリング

OCSPステープリングはSSL/TLSハンドシェイクのパフォーマンスとプライバシーを向上させます。

5.1. OCSPステープリングとは?

OCSPステープリングなし:

クライアント → サーバー:SSLハンドシェイク
クライアント → CA:証明書は有効か?
CA → クライアント:はい、有効です
クライアント → サーバー:続行

OCSPステープリングあり:

サーバー → CA:私の証明書は有効か?(キャッシュ済み)
クライアント → サーバー:SSLハンドシェイク
サーバー → クライアント:証明書 + OCSPレスポンスを送信
クライアント:証明書有効!(CAへの追加リクエスト不要)

5.2. OCSPステープリングの有効化

server {
listen 443 ssl http2;
server_name example.com;

ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

# OCSPステープリングを有効化
ssl_stapling on;
ssl_stapling_verify on;

# 検証用の信頼できる証明書
ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;

# OCSPのDNSリゾルバー
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;

}

5.3. OCSPステープリングの確認

# OCSPステープリングをテスト
echo QUIT | openssl s_client -connect example.com:443 -status 2> /dev/null | grep -A 17 'OCSP response:'

期待される出力:

OCSP response:

======================================

OCSP Response Status: successful (0x0)

Response Type: Basic OCSP Response

...

Cert Status: good

5.4. 完全なOCSP設定

http {
resolver 8.8.8.8 8.8.4.4 1.1.1.1 valid=300s;
resolver_timeout 5s;

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name example.com;
    
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
    
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers off;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
    
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;
    ssl_session_tickets off;
    
    ssl_stapling on;
    ssl_stapling_verify on;
    
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-XSS-Protection "1; mode=block" always;
    
    root /var/www/html;
    index index.html;
}

}


6. HTTP/2設定

HTTP/2は多重化、サーバープッシュ、ヘッダー圧縮によりパフォーマンスを大幅に向上させます。

6.1. HTTP/2の有効化

server {
# http2パラメータでHTTP/2を有効化
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name example.com;

ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

# HTTP/2にはTLS 1.2以上が必要
ssl_protocols TLSv1.2 TLSv1.3;

root /var/www/html;

}

HTTP/2が有効か確認:

# curlでテスト
curl -I --http2 https://example.com

以下を確認:

HTTP/2 200

またはブラウザのDevToolsで確認

ネットワークタブ → プロトコル列が「h2」を表示

6.2. HTTP/2プッシュ

サーバープッシュにより、クライアントがリクエストする前にリソースを送信できます。

server {
listen 443 ssl http2;
server_name example.com;

ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

root /var/www/html;

location / {
    # HTMLリクエスト時にCSSとJSをプッシュ
    http2_push /css/style.css;
    http2_push /js/app.js;
    
    try_files $uri $uri/ =404;
}

}

警告: HTTP/2プッシュは誤用するとパフォーマンスが低下します。重要なリソースのみをプッシュしてください。

6.3. HTTP/2パラメータ

http {
# HTTP/2設定
http2_max_field_size 16k;        # ヘッダーフィールドの最大サイズ
http2_max_header_size 32k;       # ヘッダーの最大サイズ
http2_max_requests 1000;          # 接続あたりの最大リクエスト数
http2_recv_timeout 30s;           # クライアントのタイムアウト
}

7. 本番環境向け完全なSSL設定

7.1. 最適なSSL/TLS設定

# /etc/nginx/nginx.conf

user nginx; worker_processes auto; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid;

events { worker_connections 1024; }

http { include /etc/nginx/mime.types; default_type application/octet-stream;

log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                '$status $body_bytes_sent "$http_referer" '
                '"$http_user_agent" "$http_x_forwarded_for"';

access_log /var/log/nginx/access.log main;

sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
client_max_body_size 20M;

# Nginxバージョンを非表示
server_tokens off;

# SSLセッションキャッシュ
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_session_tickets off;

# OCSP設定
resolver 8.8.8.8 8.8.4.4 1.1.1.1 valid=300s;
resolver_timeout 5s;

# Gzip圧縮
gzip on;
gzip_vary on;
gzip_comp_level 6;
gzip_types text/plain text/css text/xml text/javascript 
           application/json application/javascript application/xml+rss;

# HTTP/2設定
http2_max_field_size 16k;
http2_max_header_size 32k;

include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;

}

7.2. サイト設定

# /etc/nginx/sites-available/example.com

HTTP - HTTPSにリダイレクト

server { listen 80; listen [::]:80; server_name example.com www.example.com;

location /.well-known/acme-challenge/ {
    root /var/www/html;
    allow all;
}

location / {
    return 301 https://example.com$request_uri;
}

}

HTTPS www - non-wwwにリダイレクト

server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name www.example.com;

ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;

return 301 https://example.com$request_uri;

}

メインHTTPSサーバー

server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name example.com;

root /var/www/example.com/public;
index index.html index.htm;

access_log /var/log/nginx/example.com.access.log;
error_log /var/log/nginx/example.com.error.log;

ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;

ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;

ssl_dhparam /etc/nginx/dhparam.pem;

ssl_stapling on;
ssl_stapling_verify on;

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
add_header Content-Security-Policy "default-src 'self' https:; script-src 'self' 'unsafe-inline' 'unsafe-eval' https:; style-src 'self' 'unsafe-inline' https:;" always;

location / {
    try_files $uri $uri/ =404;
    
    http2_push /css/style.css;
    http2_push /js/app.js;
}

location ~* \.(jpg|jpeg|png|gif|ico|svg|webp)$ {
    expires 1y;
    add_header Cache-Control "public, immutable";
    access_log off;
}

location ~* \.(css|js)$ {
    expires 1M;
    add_header Cache-Control "public";
    access_log off;
}

location ~ /\. {
    deny all;
    access_log off;
    log_not_found off;
}

error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;

}


8. テストと最適化

8.1. SSL Labsテスト

# SSL Labsにアクセス

https://www.ssllabs.com/ssltest/analyze.html?d=example.com

目標:A+評価

A+評価のチェックリスト:

  • ✅ TLS 1.2と1.3が有効
  • ✅ 強力な暗号
  • ✅ 有効で信頼された証明書
  • ✅ HSTSが有効(preload含む)
  • ✅ OCSPステープリングが機能
  • ✅ SSL/TLSの脆弱性なし

8.2. テストコマンド

# SSL接続をテスト
openssl s_client -connect example.com:443 -tls1_2

TLS 1.3をテスト

openssl s_client -connect example.com:443 -tls1_3

証明書を確認

echo | openssl s_client -connect example.com:443 2>/dev/null | openssl x509 -noout -dates

OCSPステープリングをテスト

echo QUIT | openssl s_client -connect example.com:443 -status 2> /dev/null | grep -A 17 'OCSP response:'

HTTP/2をテスト

curl -I --http2 https://example.com

8.3. パフォーマンステスト

# SSLハンドシェイク時間をテスト
time openssl s_client -connect example.com:443 </dev/null

abでベンチマーク

ab -n 1000 -c 10 https://example.com/

h2load(HTTP/2)でテスト

h2load -n 1000 -c 10 https://example.com/

8.4. セキュリティヘッダーの確認

# すべてのセキュリティヘッダーを確認
curl -I https://example.com

以下が含まれるべき:

Strict-Transport-Security: max-age=31536000; includeSubDomains; preload

X-Frame-Options: SAMEORIGIN

X-Content-Type-Options: nosniff

X-XSS-Protection: 1; mode=block

Referrer-Policy: no-referrer-when-downgrade


9. トラブルシューティング

9.1. 証明書エラー

問題:証明書が信頼されない

# 証明書チェーンを確認
openssl s_client -connect example.com:443 -showcerts

証明書ファイルを確認

sudo ls -la /etc/letsencrypt/live/example.com/

以下が必要:

cert.pem(証明書)

chain.pem(中間証明書)

fullchain.pem(証明書 + チェーン)

privkey.pem(秘密鍵)

修正:

# cert.pemではなくfullchain.pemを使用
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

9.2. 混在コンテンツの警告

問題: サイトは読み込まれるが「安全でない」と表示

原因: HTTPSで提供されているページがHTTPリソースを読み込んでいる

修正:

<!-- 悪い例 -->
<script src="http://example.com/js/app.js"&gt;&lt;/script>

<!-- 良い例 - HTTPS --> <script src="https://example.com/js/app.js"&gt;&lt;/script>

9.3. OCSPステープリングが機能しない

修正:

server {
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;

resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;

}

9.4. HTTP/2が機能しない

修正:

# http2パラメータが存在することを確認
listen 443 ssl http2;  # listen 443 ssl; だけでは不可

Nginxを再起動

sudo systemctl restart nginx

9.5. 証明書更新の失敗

修正1:ポート80にアクセスできない

sudo ufw allow 80

修正2:手動更新

# Nginxを停止
sudo systemctl stop nginx

standaloneを使用

sudo certbot certonly --standalone -d example.com

Nginxを起動

sudo systemctl start nginx


10. 練習問題

演習1:Let's EncryptでHTTPSを設定

  1. Certbotをインストール
  2. ドメインの証明書を取得
  3. NginxにHTTPSを設定
  4. 証明書をテスト

演習2:HTTPからHTTPSへのリダイレクト

  1. HTTPサーバー(ポート80)をセットアップ
  2. HTTPSサーバー(ポート443)をセットアップ
  3. HTTP → HTTPSへのリダイレクトを設定
  4. リダイレクトをテスト

演習3:HSTSの有効化

  1. HSTSヘッダーを追加
  2. ブラウザでテスト
  3. HSTSプリロードの要件を確認
  4. (任意)HSTSプリロードリストに申請

演習4:OCSPステープリングの設定

  1. OCSPステープリングを有効化
  2. リゾルバーを設定
  3. OCSPレスポンスをテスト
  4. SSL Labsで確認

演習5:HTTP/2の有効化

  1. listenディレクティブにhttp2パラメータを追加
  2. HTTP/2接続をテスト
  3. HTTP/2プッシュを実装
  4. HTTP/1.1とHTTP/2をベンチマーク比較

演習6:A+評価の取得

  1. 最適なSSL/TLS設定を行う
  2. すべてのセキュリティ機能を有効化
  3. SSL Labsでテスト
  4. 問題を修正してA+評価を取得

11. ベストプラクティス

11.1. セキュリティ

# 強力なプロトコルを使用
ssl_protocols TLSv1.2 TLSv1.3;

強力な暗号

ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;

セッションチケットを無効化

ssl_session_tickets off;

OCSPステープリングを有効化

ssl_stapling on; ssl_stapling_verify on;

HSTS

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;

11.2. パフォーマンス

# セッションキャッシュ
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;

HTTP/2

listen 443 ssl http2;

圧縮

gzip on; gzip_types text/plain text/css application/json application/javascript;

静的アセットのキャッシュ

location ~* .(jpg|png|css|js)$ { expires 1y; add_header Cache-Control "public, immutable"; }

11.3. メンテナンス

# 定期的な証明書更新
sudo certbot renew

証明書の有効期限を確認

sudo certbot certificates

ログを監視

sudo tail -f /var/log/letsencrypt/letsencrypt.log

証明書をバックアップ

sudo tar -czf letsencrypt-backup.tar.gz /etc/letsencrypt/


まとめ

このレッスンで学んだこと:

  • ✅ Let's EncryptによるSSL証明書の設定
  • ✅ HTTPからHTTPSへのリダイレクト
  • ✅ SSLプロトコルと暗号の最適化
  • ✅ HSTSの設定とプリロード
  • ✅ パフォーマンス向上のためのOCSPステープリング
  • ✅ HTTP/2の設定と最適化
  • ✅ セキュリティヘッダーとベストプラクティス
  • ✅ テストとトラブルシューティング

次のレッスン: パフォーマンスチューニング — ワーカープロセス、接続、バッファ、タイムアウト、圧縮、キャッシュの最適化によりNginxのパフォーマンスを最大化する方法について学びます。