復習2日目_20251124
今日のやったこと。
Day 2:Nginx & HTTPS(セキュリティ強化)
ゴール: HTTPS化と各種セキュリティヘッダを理解し強化する
やること:
– nginx.conf の構造(server / location / proxy_pass)を理解
– HTTP→HTTPS リダイレクトを確認
– Let’s Encrypt / certbot の仕組みを復習
– HSTS / CSP / X-Content-Type-Options など主要ヘッダを導入・確認
0. まず全体像:Nginx 設定は3階建ての構造
イメージは以下:
-
-
1階:
http { ... }
→ サーバー全体の共通設定 -
2階:
server { ... }
→ ドメインごとの設定(=「このサイト」の設定)
-
-
3階:
location { ... }
→ URL パスごとの設定(/ , /images/ , /php など)
1. server ブロックって何をしてる場所?
コンテナ名:wordpress-nginx-1 に入って中をみる。
これは docker-compose が自動で付けた名前で、プロジェクト名:wordpress、サービス名:nginx、個体番号:1という名前
コンテナ名のしらべかた
- docker ps
- docker exec -it (nginxコンテナ名) bash
- 具体的には、docker exec -it wordpress-nginx-1 bash
- ls /etc/nginx/
- conf.d fastcgi_params mime.types modules nginx.conf scgi_params uwsgi_paramsがあったその役割は下線ない。
nginx.conf… メイン設定ファイル(入口)conf.d/… サイトごとの設定ファイルが入るフォルダmime.types… 拡張子 → MIMEタイプの対応表fastcgi_params/scgi_params/uwsgi_params… バックエンドに渡す共通パラメータ
- ls /etc/nginx/conf.d
ai-http.conf default.confbak-2025-11-09-0635 wp-http.conf
ai-https.conf default.conf.bak-2025-11-09-0638 wp-https.conf
default.conf default.conf.bak-2025-11-09-0644 wp-https.conf.bak-1762945186
default.conf.bak-2025-11-08-142510 default.conf.bak-2025-11-09-0650 wp-https.conf.bak.2025-11-12-1257
default.conf.bak-2025-11-09-0436 force-kstone.conf.disabled zz-gzip.conf
default.conf.bak-2025-11-09-0613 force-restore.conf.disabled
🎯 WordPress の設定ファイル
✅ wp-http.conf(HTTP 用 / 80)
✅ wp-https.conf(HTTPS 用 / 443
🔍 他のファイルの意味(区別しておく)
ai-http.conf / ai-https.conf
→ 別サービス (AI サービス用)
default.conf
→ nginx のデフォルト設定( WordPress とは別)
force-kstone.conf.disabled
→ 一時的 or テスト用
zz-gzip.conf
→ gzip 圧縮設定(共通設定なので触らない)
- cat /etc/nginx/conf.d/wp-http.conf
- cat /etc/nginx/conf.d/wp-https.conf
サーバーブロックが二つある。
①80番(HTTP)→ 443番(HTTPS)にリダイレクトするだけの server
server {
listen 80;
server_name k-stone.click www.k-stone.click ;
location /.well-known/acme-challenge/ { root /var/www/certbot; }
return 301 https://$host$request_uri;
}
→ 「HTTP で来た人を全部 HTTPS に飛ばす」
②443番(HTTPS)で WordPress と /kaiga/(Flask)を動かす server
server {
listen 443 ssl;
http2 on;
server_name k-stone.click www.k-stone.click;
ssl_certificate /etc/letsencrypt/live/k-stone.click/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/k-stone.click/privkey.pem;
…
基本情報
listen 443 ssl;
→ 443番ポート(HTTPS)を SSL 付きで待ち受け
2. snginx.conf の構造は?
Nginx の設定は、大ざっぱにこういう“入れ子”
①server ブロック
②2. location ブロック
②-1. location /(メイン)
②-2. location /kaiga/(Flask
②-3. location ~ .php$(PHP 用)
①server ブロック
具体的にはhttp ブロックの中に server が複数入る
-
-
server= 「このドメイン+ポートのサイト」
-
-
server の中に location が入る
-
location= 「このパスのリクエストの扱い方」
-
私の環境は以下
/etc/nginx/nginx.conf
└── http {
include /etc/nginx/conf.d/*.conf;
}
/etc/nginx/conf.d/
├── wp-http.conf
├── wp-https.conf
├── ai-http.conf
├── ai-https.conf
├── default.conf
└── その他 *.conf
nginx.conf は全体の入口(include しか書いていない)
各サイト(WordPress / AI / Flask)の server 設定は conf.d に分割
この理由は、複数サイト(WordPress、AI、Flask)があるため、server ブロックを分割しないと管理しづらいためです。
② location ブロック
location ブロックがやっていることは?
-1 .location /(メイン、WordPress ルーティング)
URL「/」「/about」「/blog/xxx」など
→ WordPress が処理する
→ 静的ファイルがある場合はそのまま返す。
-2. location /kaiga/(Flask の reverse proxy)
URL が「/kaiga/」ではじまる場合
→ Flask アプリに渡す(別コンテナ)
→ WordPress は関係なし。
-3.location ~ .php$(PHP 専用レーン)
URL が「something.php」の場合
→ PHP-FPM に渡して PHP を実行
具体的には、
location / {
try_files $uri $uri/ /index.php?$args;
}
「指定したパスを順番に探して、見つかったらそれを返す。なければ最後のものを使う」という意味です。
① $uri を探す(実ファイルを探す)
無ければ
② $uri/ を探す(ディレクトリを探す)
それでも無ければ
③ /index.php?$args に渡す(WordPress 本体にバトン)
「WordPress の index.php に、この URL を処理してもらう」
3. fastcgi_pass と proxy_pass の違いは?
| 機能 | 使う命令 | 誰に渡す? | 用途 |
|---|---|---|---|
| PHP の実行 | fastcgi_pass | PHP-FPM(php-fpm コンテナ) | WordPress などの PHP |
| HTTP リクエストの中継 | proxy_pass | 別の Webサーバー(Flask / Node / API) | /kaiga/ の Flask アプリ |
✔ WordPress(PHP)は fastcgi_pass
✔ Flask アプリ(Python)は proxy_pass
4. HTTPS(443番)とは?
設定:
これが HTTPS の心臓。
fullchain.pemは、サーバー証明書(Let’s Encrypt が発行したもの)中には、自分の証明書と中間証明書がひとまとめに入っている。
🔐 HTTPS の流れ
ブラウザが https://k-stone.click にアクセス
Nginx(443番)が待ち受ける
Nginx が fullchain.pem をブラウザに送る
→ ブラウザ:「OK。このサイトは証明された正規のサイトだ」
→ ブラウザと Nginx が「共通の暗号鍵」を作り、(握手)暗号化された通信が始まる。(パスワードやクレジット情報も安全)
ここまで述べたように、構造はこのように👇なっているんので、HTTPS の server は WordPress の本体処理をすべて含んでると言える。
server {
← サーバーブロック(サイト全体の設定)
location / { … }
location /kaiga/ { … }
location ~ .php$ { … }
← ロケーションブロック(URLごとの設定)
}
5. Certbot(Let’s Encrypt)の役割?
ACME 用の location もある👇
location ^~ /.well-known/acme-challenge/ {
root /var/www/certbot;
try_files $uri =404;
}
Certbot(Let’s Encrypt)が証明書更新を行うときに使う特別なパス。
✔ ここにあるファイルを Let’s Encrypt が読み取れれば
→ サイトが自分のドメインを本当に所有していることを証明できる
✔ これが通らないと更新できない
→ 証明書が失効(HTTPSが死ぬ)可能性あり
Let’s Encrypt(レッツ・エンクリプト)とは
→ “無料で SSL 証明書を発行してくれるサービス”
ACME(アクミー)とは?
→ “Let’s Encrypt が証明書を自動発行・更新するための仕組み(プロトコル)”
私のnginxは Certbot を使って
→ Let’s Encrypt と ACME プロトコルで会話
→ SSL 証明書をもらう&更新する
という流れで HTTPS が成立しています。
Let’s Encrypt の証明書は 90日で期限切れ になるため、
Cron が certbot を定期実行し、certbot が ACME プロトコルを使って証明書を更新することが必要です。
Cron(毎日実行)
↓
certbot renew
↓
ACME(ドメイン所有者の確認・証明書更新)
↓
Let’s Encrypt(証明書発行)
備忘録
WordPress、Flask、個人・中小企業サイト、ブログ、Web サービス、API
で使う場合は Let’s Encrypt で 十分なことが多い。
6. 主要セキュリティヘッダを導入へ
| 攻撃/問題 | 防げる? | 使用ヘッダ | どのように防ぐのか(しくみを一言で) |
|---|---|---|---|
| クリックジャッキング | ◎ | X-Frame-Options | 他ドメインから iframe 埋め込みを禁止し、偽装ボタンを押させる攻撃を阻止 |
| MIME偽装攻撃(画像に見せかけたJS実行) | ◎ | X-Content-Type-Options | ブラウザによる “勝手なMIME推測” を禁止し、不正スクリプトの実行を防止 |
| Referrer情報の漏洩(URLの詳細が他ドメインに渡る) | ◎ | Referrer-Policy | 外部サイトに送る Referrer を最小限にし、内部URLやクエリを保護 |
| ブラウザ機能悪用(カメラ/マイク/位置情報) | ◎ | Permissions-Policy | このサイトではカメラやマイク等を使わせないと宣言し、JSからの悪用を防止 |
| HTTP にダウングレードされるリスク(MITM攻撃) | ◎ | HSTS(Strict-Transport-Security) | ブラウザに「このドメインは絶対 HTTPS!」と記憶させ、平文通信を禁止 |
① まず nginx の設定ファイルを開く
nano /etc/nginx/conf.d/wp-https.conf
② server { の直後に 主要セキュリティヘッダを導入する
なんのために、
-
XSS 攻撃 → 強化
-
クリックジャッキング → 防止
-
MIME Type なりすまし → 防止
-
リファラ漏洩 → 抑制
-
HTTPS 強制(HSTS) → 最重要のセキュリティ強化
方法は?
ssl_certificate_key /etc/letsencrypt/live/k-stone.click/privkey.pem;の後ろに下をいれる。
=== Security Headers ===
add_header X-Content-Type-Options “nosniff”;
add_header X-Frame-Options “SAMEORIGIN”;
add_header Referrer-Policy “strict-origin-when-cross-origin”;
add_header Permissions-Policy “camera=(), microphone=(), geolocation=()”;
add_header Strict-Transport-Security “max-age=31536000; includeSubDomains” always;
③保存(ctrl+O→Enter→xtrl+x)
④テスト nginx -t
# 今後やることはCSP導入