SSL/TLSとは
SSL/TLSは、クライアントとサーバー間の通信を暗号化するプロトコルです。HTTPS通信に必須であり、データの盗聴・改ざんを防ぎます。
Let’s Encrypt
Let’s Encryptは、無料でSSL証明書を発行する認証局です。Certbotを使って簡単に取得・更新できます。
Certbotのインストール
# Ubuntu/Debian
sudo apt update
sudo apt install certbot
# Nginxプラグイン
sudo apt install python3-certbot-nginx
# Apacheプラグイン
sudo apt install python3-certbot-apache
# CentOS/RHEL
sudo yum install epel-release
sudo yum install certbot python3-certbot-nginx
証明書の取得
# Nginx用(自動設定)
sudo certbot --nginx -d example.com -d www.example.com
# Apache用(自動設定)
sudo certbot --apache -d example.com -d www.example.com
# スタンドアロン(Webサーバー停止が必要)
sudo certbot certonly --standalone -d example.com
# Webroot(Webサーバー実行中に取得)
sudo certbot certonly --webroot -w /var/www/html -d example.com
自動更新の設定
# 更新テスト
sudo certbot renew --dry-run
# cronで自動更新(デフォルトで設定済みの場合が多い)
# /etc/cron.d/certbot
0 0,12 * * * root certbot renew --quiet
# systemdタイマーの確認
sudo systemctl status certbot.timer
ワイルドカード証明書
# DNS認証でワイルドカード取得
sudo certbot certonly \
--manual \
--preferred-challenges dns \
-d "*.example.com" \
-d example.com
# DNSにTXTレコードを追加
# _acme-challenge.example.com TXT "提示された値"
Nginx設定
# /etc/nginx/conf.d/ssl.conf
server {
listen 80;
server_name example.com www.example.com;
return 301 https://$server_name$request_uri;
}
server {
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;
# モダンなTLS設定
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_prefer_server_ciphers off;
# セッション設定
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;
# OCSP Stapling
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;
# セキュリティヘッダー
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
root /var/www/html;
index index.html;
}
Apache設定
# /etc/apache2/sites-available/example-ssl.conf
ServerName example.com
Redirect permanent / https://example.com/
ServerName example.com
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
# モダンな設定
SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256
SSLHonorCipherOrder off
# HSTS
Header always set Strict-Transport-Security "max-age=63072000"
DocumentRoot /var/www/html
# モジュール有効化
sudo a2enmod ssl
sudo a2enmod headers
sudo a2ensite example-ssl.conf
sudo systemctl restart apache2
Node.js / Express
import https from 'https';
import fs from 'fs';
import express from 'express';
const app = express();
const options = {
key: fs.readFileSync('/etc/letsencrypt/live/example.com/privkey.pem'),
cert: fs.readFileSync('/etc/letsencrypt/live/example.com/fullchain.pem'),
};
// HTTPSサーバー
https.createServer(options, app).listen(443);
// HTTPリダイレクト
import http from 'http';
http.createServer((req, res) => {
res.writeHead(301, { Location: `https://${req.headers.host}${req.url}` });
res.end();
}).listen(80);
セキュリティチェック
SSL Labs テスト
# オンラインテスト
# https://www.ssllabs.com/ssltest/
# コマンドラインツール
# sslyze
pip install sslyze
sslyze example.com
# testssl.sh
git clone https://github.com/drwetter/testssl.sh.git
./testssl.sh/testssl.sh example.com
OpenSSLでの確認
# 証明書情報の確認
openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null | openssl x509 -text -noout
# 有効期限確認
openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null | openssl x509 -noout -dates
# 証明書チェーン確認
openssl s_client -connect example.com:443 -servername example.com -showcerts </dev/null
# プロトコル・暗号スイート確認
openssl s_client -connect example.com:443 -tls1_3
よくあるエラーと対処
証明書チェーンエラー
# 中間証明書が不足している場合
# fullchain.pemを使用しているか確認
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
証明書の更新失敗
# ポート80が使用中
sudo lsof -i :80
# Webroot認証の確認
# .well-known/acme-challenge/ へのアクセスを確認
location ^~ /.well-known/acme-challenge/ {
root /var/www/html;
}
Mixed Content警告
<!-- HTTPリソースをHTTPSに変更 -->
<img src="https://example.com/image.jpg" />
<!-- または相対パス/プロトコル相対URL -->
<img src="/image.jpg" />
<img src="//example.com/image.jpg" />
クラウドサービスでのSSL
AWS (ACM)
# AWS Certificate Manager で無料SSL証明書
# CloudFront/ALB/API Gatewayで使用可能
aws acm request-certificate \
--domain-name example.com \
--validation-method DNS
Cloudflare
# Cloudflare設定
SSL/TLS:
encryption_mode: Full (strict)
always_use_https: true
min_tls_version: "1.2"
監視と更新通知
# 証明書期限監視スクリプト
#!/bin/bash
DOMAIN="example.com"
EXPIRY=$(echo | openssl s_client -servername $DOMAIN -connect $DOMAIN:443 2>/dev/null | openssl x509 -noout -enddate | cut -d= -f2)
EXPIRY_EPOCH=$(date -d "$EXPIRY" +%s)
NOW_EPOCH=$(date +%s)
DAYS_LEFT=$(( ($EXPIRY_EPOCH - $NOW_EPOCH) / 86400 ))
if [ $DAYS_LEFT -lt 30 ]; then
echo "Warning: $DOMAIN certificate expires in $DAYS_LEFT days"
fi
関連記事
- Nginx設定実践 - Webサーバー設定
- APIセキュリティ - API保護
- ゼロトラストアーキテクチャ - モダンセキュリティ
まとめ
SSL証明書はWebセキュリティの基本です。Let’s Encryptで無料証明書を取得し、自動更新を設定しましょう。定期的なセキュリティチェックも重要です。
← Back to list