LoginSignup
1
2

More than 1 year has passed since last update.

httpからhttpsにリダイレクトさせたいんです

Last updated at Posted at 2022-10-26

私です。お母様と「httpからhttpsにリダイレクトさせたいのにどうするんだっけ?」を繰り返している皆々様、お元気ですか。
表題の件ですが、検索するとRewriteよるURL書き換えばかりです。令和になってもこの調子で良いのか疑問に思ったので自分で調べることにしました。

忘れちゃイケナイHSTS

HTTP Strict Transport Security、通称HSTS。

ブラウザに「このサイトはhttpsが実装してあるよ」と教えてあげるhttpヘッダー。強制力と信頼性は無いのでおまけのようなもの。
詳しいことはMDNの方で。

形式は次の通り。

Strict-Transport-Security: max-age=31536000

必須ディレクティブであるmax-ageではキャッシュ期間を指定する。31536000あれば良いかもしれない。

キャッシュ期間中はブラウザが自主的にリダイレクトを行う。

なぜ max-age=31536000 なのか?

※これは私の解釈です

ドメイン、あるいはSSL/TLS証明書やサーバーの更新はほぼ年単位で行われ、HSTSのキャッシュ期間も31536000 = 60 * 60 * 24 * 365、つまり1年(年単位)にして間違いないだろう。

どうせブラウザ側の都合でキャッシュクリアされる可能性がある上、キャッシュ期間をこれより短くして得られるメリットがあるのかよく考えてほしい。

実装

主要なApache、nginx、LSWSに限定する。LSWSは都合上「OpenLiteSpeed」の事を指す。

前提としてLet’s EncryptによるHTTP-01チャレンジ検証1で失敗しないよう、http://<YOUR_DOMAIN>/.well-known/acme-challenge/にアクセスしても強制リダイレクトが発生しない仕組みで実装する。

Apache 2.4+

Apache 2.4のコアモジュールには<If>が追加実装されている。mod_aliasと組み合わせることにより、シンプルに記述できる。

"example.conf" or ".htaccess"
Header onsuccess set Strict-Transport-Security "max-age=31536000"
<If "%{HTTPS} != 'on' && %{REQUEST_URI} !~ m#^/\.well-known/acme-challenge/.*#">
# <If "%{HTTPS} != 'on'">
	Redirect permanent "https://%{HTTP_HOST}%{REQUEST_URI}"
</If>

HTTPステータスが200ならHSTSヘッダーを上書き追加する。

HTTP-01チャレンジを使用してないならコメントアウトしている<If ...と差し替える。

【必須モジュール】mod_headers + mod_aliasが必要。どちらか欠けても500 Internal Server Errorを返す。

Apache 2.x

mod_rewriteを使った古典的なリダイレクト方式。

"example.conf" or ".htaccess"
Header onsuccess set Strict-Transport-Security "max-age=31536000"
RewriteEngine on
RewriteCond %{HTTPS} "!='on'"
RewriteCond %{REQUEST_URI} "!^/\.well-known/acme-challenge/.*"
RewriteRule .* "https://%{HTTP_HOST}/$0" [R=301]

上記で説明してるので端折るが、HTTP-01チャレンジ検証を利用してないなら4行目は削除して良い。

【必須モジュール】mod_headers + mod_rewriteが必要。どちらか欠けても500 Internal Server Errorを返す。

nginx

returnによる単純なリダイレクトで処理する。

example.conf
location ~ "^/(?!\.well-known/acme-challenge/)" {
# location / {
	add_header Strict-Transport-Security "max-age=31536000";
	if ($https != “on”) {
		return 301 "https://$http_host$request_uri";
	}
}

【必須モジュール】ngx_http_headers_module + ngx_http_rewrite_module

LiteSpeed Web Server

LSWSはApacheのRewriteの設定内容をほぼそのまま使える。RewriteRuleのパターンには、パッチ先頭に/を含むようで、一応修正する2

Rewriteの内容のみ.htaccessも利用可。どちらの方法でもリロード(再起動)は必要。


LiteSpeed WebAdmin コンソールから → バーチャルホスト → 対象ホストを編集 → コンテキスト より

  • URI: /(重複不可)
  • アクセス可能: はい
Header Operations
Strict-Transport-Security: max-age=31536000
  • Rewriteを有効にする: はい
Rewrite ルール
RewriteCond %{HTTPS} "!='on'"
RewriteCond %{REQUEST_URI} "!^/\.well-known/acme-challenge/.*"
RewriteRule ^/?(.*)$ "https://%{HTTP_HOST}/$1" [R=301]

lsws-context2.png

あとはリロードを実行することで適用される。


一応設定ファイルの一部内容を置いておきます。可能ならウェブコンソールから設定を行って欲しい。

設定ファイルのサンプル内容
example.conf
context / {
  allowBrowse             1
  extraHeaders            <<<END_extraHeaders
Strict-Transport-Security: max-age=31536000
  END_extraHeaders
  rewrite  {
    enable                1
RewriteCond %{HTTPS} "!='on'"
RewriteCond %{REQUEST_URI} "!^/\.well-known/acme-challenge/.*"
RewriteRule ^/?(.*)$ "https://%{HTTP_HOST}/$1" [R=301]
  }
}

後記

本来Rewrite系はURLの置換によるリダイレクトである。当時は条件式系のディレクティブが発達しておらず仕方なくRewriteを使う感じになっているがあまりにも定着しすぎている。Apache 2.4から<If> <ElseIf> <Else>ディレクティブの登場で単体で使う場面があまり少ないであろうRedirectも日の目を見ることができそうだ。

Apache 2.4は初版から10年経過しているので、置き換えの必要ないならシンプルなリダイレクトにするべき。

あとnginxのifがApacheほど使えない3ので最終的にlocationに頼りがちになる。個人的に比較演算子の考え方はApacheの方が好みで、正規表現で扱う文字数はなるべく減らしたいので不一致があるのはとても助かる。

  1. チャレンジの種類

  2. .htaccessとバーチャルホスト書き換えタブとバーチャルホストコンテキスト書き換えルールの書き換えルールの違い

  3. コアでは無く、ngx_http_rewrite_moduleに実装されてるおまけのような機能。公式Wikiでも酷評されがち → If is Evil… when used in location context

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2