タイトル: 常時SSL化
SEOタイトル: 常時 SSL 化(HTTPS 強制リダイレクト)の実装方法と HSTS / Mixed Content 対策
この本文には実行可能なタグ等が含まれるため、安全のためHTMLソースとして表示しています。本文データは変更していません。
<table border="1" cellpadding="6" cellspacing="0" style="border-collapse:collapse;background:#fffbea;border:1px solid #f4c430;margin:1em 0;width:100%"><tr><td style="background:#f4c430;color:#000;font-weight:bold;padding:8px">この記事の要点</td></tr><tr><td style="padding:10px"><ul><li><strong>常時 SSL 化</strong> = サイト全 URL を HTTPS で配信し、HTTP アクセスは 301 で HTTPS にリダイレクト</li><li><strong>Apache</strong>: <code>.htaccess</code> mod_rewrite または <code>Redirect permanent</code></li><li><strong>Nginx</strong>: <code>return 301 https://$host$request_uri;</code> を 80 番 server に</li><li><strong>HSTS (Strict-Transport-Security)</strong> でブラウザに HTTPS 強制を記憶させる</li><li><strong>Mixed Content 対策</strong>: 画像 / JS / CSS の URL を相対 or <code>https://</code> に統一</li><li><strong>Let's Encrypt</strong> + Certbot で SSL 証明書を無料・自動更新</li></ul></td></tr></table>
<h2>常時 SSL 化とは</h2>
<p>サイトの<strong>全ページ・全リソース</strong>を HTTPS(TLS)で配信し、HTTP アクセスを HTTPS に強制リダイレクトする運用方式です。「Always-on SSL」「HTTPS Everywhere」とも呼ばれます。</p>
<p><strong>導入メリット</strong>:</p>
<ul>
<li>通信の盗聴 / 改ざん防止(中間者攻撃対策)</li>
<li>SEO 評価: Google が HTTPS をランキング要因として明言(2014 年〜)</li>
<li>Chrome / Firefox の「保護されていない通信」警告を回避</li>
<li><strong>HTTP/2 / HTTP/3</strong> はブラウザ実装上 HTTPS 必須 → 体感速度向上</li>
<li>Service Worker / Geolocation / Camera API など最新 Web API は HTTPS 必須</li>
</ul>
<h2>Apache: .htaccess での HTTPS リダイレクト</h2>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-apache"># .htaccess(最も一般的)
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
# X-Forwarded-Proto を見るパターン(ロードバランサ / CDN 配下)
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
# www へ統一して HTTPS
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^(.*)$ https://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L,NE]</code></pre>
<h3>VirtualHost で書く場合</h3>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-apache"># /etc/httpd/conf.d/example.com.conf
<VirtualHost *:80>
ServerName example.com
Redirect permanent / https://example.com/
</VirtualHost>
<VirtualHost *:443>
ServerName example.com
DocumentRoot /var/www/html
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
# HSTS: 1 年間 HTTPS 強制 (max-age 秒)
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
</VirtualHost></code></pre>
<h2>Nginx: HTTPS リダイレクト</h2>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-nginx"># /etc/nginx/conf.d/example.com.conf
# 80 番: 全部 HTTPS に飛ばす
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
return 301 https://$host$request_uri;
}
# 443 番: 本体
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name example.com;
root /var/www/html;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
# 推奨設定(Mozilla SSL Config 生成)
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:...;
ssl_prefer_server_ciphers off;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
# HSTS
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
}</code></pre>
<h2>HSTS (Strict-Transport-Security)</h2>
<p>HSTS ヘッダを送ると、ブラウザは指定期間中<strong>そのドメインを必ず HTTPS で接続</strong>するようになります。HTTP リダイレクトすら省略され、中間者攻撃に対する耐性が向上します。</p>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-text">Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
max-age=31536000 最大有効期間 (秒): 1 年
includeSubDomains サブドメインにも適用
preload Chrome HSTS Preload List へ登録申請可能
→ 初回アクセスから HTTPS 強制</code></pre>
<p><strong>注意</strong>: HSTS は<strong>取り消しが難しい</strong>です。max-age を一度長く設定すると、ブラウザがキャッシュしている間 HTTPS でしか接続できなくなります。導入時はまず短期間 (例: <code>max-age=300</code>) で動作確認してから延長してください。</p>
<h2>Mixed Content(混在コンテンツ)対策</h2>
<p>HTTPS ページから <code><img src="http://..."></code> のように HTTP リソースを読み込むと<strong>Mixed Content 警告</strong>が出ます。多くは画像 / CSS / JS で発生:</p>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-html"><!-- ❌ 混在コンテンツ -->
<img src="http://example.com/logo.png">
<script src="http://cdn.example.com/lib.js"></script>
<!-- ✅ プロトコル相対 (今は非推奨、後述) -->
<img src="//example.com/logo.png">
<!-- ✅ HTTPS に統一 -->
<img src="https://example.com/logo.png">
<!-- ✅ 同一サイトなら絶対パス(ルート相対) -->
<img src="/images/logo.png"></code></pre>
<p>大量の HTTP URL を一括で書き換える Meta タグ:</p>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-html"><!-- すべての http:// リクエストを https:// に強制アップグレード -->
<meta http-equiv="Content-Security-Policy"
content="upgrade-insecure-requests">
<!-- HTTP リソースをブロック(より厳格) -->
<meta http-equiv="Content-Security-Policy"
content="block-all-mixed-content"></code></pre>
<h2>Let's Encrypt + Certbot(無料 SSL)</h2>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-bash"># Ubuntu / Debian
sudo apt install certbot python3-certbot-apache # Apache
sudo apt install certbot python3-certbot-nginx # Nginx
# 証明書取得 + 設定自動書き換え
sudo certbot --apache -d example.com -d www.example.com
sudo certbot --nginx -d example.com -d www.example.com
# 自動更新(cron / systemd timer)
sudo certbot renew --dry-run
sudo systemctl list-timers | grep certbot
# 90 日の証明書を 60 日でリニューする運用が標準</code></pre>
<h2>Laravel / 各種フレームワーク</h2>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-php">// Laravel: AppServiceProvider::boot()
public function boot(): void
{
if ($this->app->environment('production')) {
URL::forceScheme('https');
}
}
// または .env
// APP_URL=https://example.com
// CDN / ロードバランサ配下の場合は TrustProxies で
// app/Http/Middleware/TrustProxies.php
protected $proxies = '*';
protected $headers = Request::HEADER_X_FORWARDED_FOR
| Request::HEADER_X_FORWARDED_HOST
| Request::HEADER_X_FORWARDED_PORT
| Request::HEADER_X_FORWARDED_PROTO;</code></pre>
<h2>常時 SSL 化のチェックリスト</h2>
<ol>
<li>SSL 証明書取得・設定(Let's Encrypt 推奨)</li>
<li>HTTP → HTTPS の 301 リダイレクト設定</li>
<li>サイト内の HTTP リソース URL を全て HTTPS に書き換え(画像、CSS、JS、iframe、リンク)</li>
<li><code>upgrade-insecure-requests</code> CSP で残った HTTP リクエストをアップグレード</li>
<li>HSTS ヘッダを短期間で動作確認 → 1 年に延長</li>
<li>Google Search Console に HTTPS 版サイトを登録 / sitemap.xml 提出</li>
<li>サードパーティタグ(Google Analytics 等)が HTTPS 対応か確認</li>
<li><strong>SSL Labs テスト</strong> で A 以上を確認: <code>https://www.ssllabs.com/ssltest/</code></li>
<li>Lighthouse で「HTTPS」「Mixed Content」項目を確認</li>
</ol>
<h2>FAQ</h2>
<p><strong>Q: 301 と 302 のどちらでリダイレクトすべき?</strong><br />
A: <strong>301 (Permanent)</strong>。検索エンジンは 301 をシグナルとして HTTPS 版をインデックスし、HTTP 版の評価を引き継ぎます。302 だと「一時的」とみなされ評価が分散します。</p>
<p><strong>Q: 旧 HTTP ページのリンク評価は消える?</strong><br />
A: 301 リダイレクトを設定すれば、約 90% 以上の SEO 評価が新 URL に引き継がれます(Google 公式)。サイト全体の URL 変更で 1〜2 週間ランキングが変動するのは正常です。</p>
<p><strong>Q: 自己署名証明書ではだめ?</strong><br />
A: ブラウザが警告を出すため、公開サイトでは不可。Let's Encrypt が無料・自動更新で実用上ほぼ最強です。</p>