復習2日目_20251124

IT

今日のやったこと。

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番)とは?

設定:

ssl_certificate /etc/letsencrypt/live/k-stone.click/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/k-stone.click/privkey.pem;

これが 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導入