HTTPからのリダイレクト

両方で見えている状態は、中途半端

いまサイトは 80 番でも 443 番でも同じ内容を返します。訪問者は http:// でも https:// でも開けてしまいます。

これは望ましくありません。理由は3つです。

  • 暗号化されない経路が残っている。フォームに書いた内容は平文で流れる
  • 同じ内容が2つの URL で見える。検索エンジンから見ると重複したページになる
  • どちらで見ているのかを訪問者が意識できない

アドレス欄に example.com とだけ打つと、ブラウザはまず http:// で繋ぎに行きます。だから 80 番を閉じるのではなく、来た人を 443 番へ案内するという形にします。

案内は 301 で返す

server { listen 80; server_name mysite.local; return 301 https://$host$request_uri; }

return は、そこで処理を打ち切って指定の応答を返す指定です。301 は「このページは恒久的にこちらへ移りました」を意味するステータスコードです。

似たものに 302 があり、こちらは一時的な移動を意味します。HTTPS への案内は当分変わらないので 301 を使います。ブラウザや検索エンジンは 301 を記憶して、次からは最初から新しいほうを見に行きます。逆に言うと、間違えて 301 を返すと訪問者の手元に長く残ります。試している間は 302 にしておく、という慎重なやり方もあります。

変数で行き先を組み立てる

https://$host$request_uri の2つは nginx が用意している変数です。

  • $host — 訪問者が指定したホスト名
  • $request_uri/works/index.html?page=2 のような、パスと問い合わせをまとめたもの

この2つを繋ぐことで、訪問者が見ようとしていたページにそのまま案内できます。行き先を https://mysite.local/ と直に書いてしまうと、深いページを開こうとした人まで全員トップページに飛ばされます。よくある失敗で、しかも動いてはいるので気づきにくい種類のものです。

server ブロックを2つに分ける

ここまで1つの server ブロックに listen 80listen 443 ssl を並べていました。転送を入れるなら、分けます。

server { listen 80; server_name mysite.local; return 301 https://$host$request_uri; } server { listen 443 ssl; server_name mysite.local; ssl_certificate /etc/ssl/certs/mysite.crt; ssl_certificate_key /etc/ssl/private/mysite.key; root /var/www/mysite; index index.html; ... }

1つ目は案内だけをする、中身を持たないブロックです。rootlocation も要りません。3章で書いた locationerror_page は、すべて 443 番のほうへ移します。

分ける理由は、同じブロックに両方を書くと「暗号化なしで来たときだけ転送する」という条件分岐が必要になり、書き方が回りくどくなるからです。番号ごとにブロックを分けたほうが、何をするブロックなのかが読んで分かります。

転送されたことを確かめる

curl -sI http://localhost/ # HTTP/1.1 301 Moved Permanently # Location: https://localhost/

-I はヘッダーだけを見る指定です。Location に行き先が入っています。

案内に従って最後まで追いかけたいときは、こう書きます。

curl -kL http://localhost/

-L が、返ってきた Location を追いかける指定です。自己署名なので -k も要ります。これでトップページの中身が返れば、転送の連なりが最後まで通っていると分かります。

手を動かす

server ブロックを2つに分け、80 番に来た訪問者を 443 番の同じページへ案内します。深いパスでも行き先が保たれることまで確かめます。

ヒント

  • 1. mysite.conf を、80 番用と 443 番用の2つの server ブロックに分ける
  • 2. 80 番のブロックには return 301 https://$host$request_uri; だけを書く
  • 3. 443 番のブロックに root や location、error_page を移す
  • 4. nginx -t のあと systemctl reload nginx で反映する
  • 5. curl -sI http://localhost/works/ > /root/redirect.txt で結果を保存する

10 項目で採点します