PR
Apache 301 Redirectバーチャルホスト

Apache の名前ベースのバーチャルホスト設定で https への 301リダイレクトを設定 | CentOS 7

301 Redirect Apache
スポンサーリンク

前回の記事 で Let’s Encrypt の ワイルドカード証明書 を無料で取得し、dns-rfc2136 で自動更新も行いました。今回はその証明書を使い、名前ベースのバーチャルホスト を利用して複数のドメインを 301リダイレクトし、HTTPSに転送 する設定を追加します。.htaccessでもできますが、ここでは名前ベースのバーチャルホストを利用することが前提です。

サーバ環境

[root@centos7 ~]# cat /etc/redhat-release
CentOS Linux release 7.6.1810 (Core)

[root@centos7 ~]# /usr/local/apache2/bin/httpd -v
Server version: Apache/2.4.39 (Unix)

[root@centos7 htdocs]# nghttp --version
nghttp nghttp2/1.38.0

[root@centos7 htdocs]# openssl version
OpenSSL 1.1.1b  26 Feb 2019

# その他
Brotli-1.0.7
apr-1.7.0
apr-util-1.6.1

前提

Let’s Encrypt のワイルドカード証明書を無料で取得し、dns-rfc2136 で自動更新の設定済みで、HTTP で稼働していた複数のホストを HTTPS に引っ越しする予定です。

Apache は yum ではなく、コンパイルしたため、ディレクトリ構造はコンパイルバージョンを使います。

  • ServerRoot:/usr/local/apache2 ( yum:/etc/httpd )
  • DocumentRoot:/usr/local/apache2/htdocs ( yum:/var/www/html )
  • Include ディレクトリ:/usr/local/apache2/conf/extra ( yum:/etc/httpd/conf.d )
  • Access Log:/usr/local/apache2/logs/access_log
  • mainhost.com : デフォルトディレクトリ ( /usr/local/apache2/htdocs ) を使うメインホス
  • example.com : /usr/local/apache2/htdocs/example.com ディレクトリを使うホスト。
  • 既存のウェブサービスは htaccess の Basic 認証をかけたまま設定を行う。

Apache の設定

このリンクの httpd.conf ファイルを /usr/local/apache2/conf/httpd.conf にコピベーしてください。

# 下記の項目を含め、適宜変更してください。
[root@centos7 conf]# vi /usr/local/apache2/conf/httpd.conf
...

ServerAdmin admin@example.com
ServerName www.example.com:80
...

Include conf/extra/httpd-ssl.conf
Include conf/extra/httpd-vhosts-10-service.conf
...

# 設定を確認
[root@centos7 conf]# /usr/local/apache2/bin/httpd -t
Syntax OK

httpd-vhosts-10-service.conf で 80 ポート & 301リダイレクト 設定を、httpd-ssl.conf で 443 ポート すなわち、HTTPS の設定を行います。

Apache では名前ベースのバーチャルホストを設定すると、httpd.conf で設定したメインホストの設定が消える仕様なので メインホストの ServerName と DocumentRoot が同様なバーチャルホストを生成しなければなりません。
また、バーチャルホストブロックは書かれた順に、またはファイルに分割した場合はファイル名順に適用されるため、メインホストを最も手前に配置させることが重要です。

80ポート & 301リダイレクト( Redirect ) 設定

httpd-vhosts-10-service.conf

ここから httpd-vhosts-10-service.conf をコピペしてください。
mainhost.com と example.com が設定された conf ファイルです。ドメイン名など適宜変更して使ってください。

[root@centos7 extra]# vi /usr/local/apache2/conf/extra/httpd-vhosts-10-service.conf

301リダイレクト( Redirect ) の設定内容

リダイレクトを設定するには httpd.conf で rewrite_module を有効にする必要があります。コピペした httpd.conf にはすでに有効になっています。

LoadModule rewrite_module modules/mod_rewrite.so

リダイレクトの最小限の設定は、エンジンを ON にして、必要なルールをを記述するだけです。実際には、変数の値を正しくインポートできない場合があったりするので、ご自身の環境と具合を観ながら条件を加減する必要があります。コピペで動作しなかったら他の設定を試してみてください。

作成 ( 動作 ) の流れは、
RewriteEngine を ON、Rule が動作する条件 ( RewriteCond ) を指定、条件に応じた Rule ( RewriteRule ) が実行される。

書式:RewriteCond %変数名(テスト文字列) 条件パターン(正規表現) [フラグ]

RewriteEngine     on
RewriteCond       %{HTTPS}        !on         [OR,NC]
RewriteCond       %{REQUEST_SCHEME}           !https  [OR,NC]
RewriteCond       %{SERVER_PORT}      !443   [NC]
RewriteCond       %{HTTP_HOST}    ^mainhost\.com$  [NC]
RewriteRule         ^(.*)$             https://www.%{HTTP_HOST}$1 [R=301,L]
RewriteRule         ^(.*)$             https://%{HTTP_HOST}$1 [R=301,L]
上記の設定を解釈
  • RewriteEngine を起動する。
  • [NC] フラグで URL に入力した文字は大文字小文字の区別をしない
  • RewriteCond を複数の条件を記述した場合、フラグはデフォルトで AND になる。
  • したがって、適用するリダイレクトは
    HTTPS ではないアクセスの中でwww をつけた場合はそのまま HTTPS へリダイレクトされるが、http://mainhost.com のように www がない場合は www をつけて HTTPS にリダイレクトされる。
# 設定を確認
[root@centos7 conf]# /usr/local/apache2/bin/httpd -t
Syntax OK

SSL を設定します。

SSL 証明書を指定して HTTPS を有効に

httpd-ssl.conf

ここから httpd-ssl.conf をコピペしてください。

[root@centos7 extra]# vi /usr/local/apache2/conf/extra/httpd-ssl.conf
# 設定を確認して httpd デーモンを再起動
[root@centos7 conf]# /usr/local/apache2/bin/httpd -t
Syntax OK

[root@centos7 conf]# systemctl restart httpd

リダイレクトの結果を確認

Macbook Pro で確認をしています。
curl コマンドの結果メッセージの中に「HTTP/1.1 301 Moved Permanently」と表示され、Location が http → https に変われば OK です。

main-host.com

http://main-host.com ▶︎ https://www.main-host.com

HTTP/1.1 301 Moved Permanently
Location: https://www.main-host.com/

try🐶everything ~$ curl -I http://main-host.com
HTTP/1.1 301 Moved Permanently
Date: Tue, 18 Jun 2019 08:20:05 GMT
Server: Apache
Location: https://www.main-host.com/
Content-Type: text/html; charset=iso-8859-1

try🐶everything ~$

http://www.main-host.com ▶︎ https://www.main-host.com

HTTP/1.1 301 Moved Permanently
Location: https://www.main-host.com/

try🐶everything ~$ curl -I http://www.main-host.com
HTTP/1.1 301 Moved Permanently
Date: Tue, 18 Jun 2019 08:20:10 GMT
Server: Apache
Location: https://www.main-host.com/
Content-Type: text/html; charset=iso-8859-1

try🐶everything ~$

example.com

http://example.com ▶︎ https://www.example.com

HTTP/1.1 301 Moved Permanently
Location: https://www.example.com/

try🐶everything ~$ curl -I http://example.com
HTTP/1.1 301 Moved Permanently
Date: Tue, 18 Jun 2019 09:58:21 GMT
Server: Apache
Location: https://www.example.com/
Content-Type: text/html; charset=iso-8859-1

try🐶everything ~$

http://www.example.com ▶︎ https://www.example.com

HTTP/1.1 301 Moved Permanently
Location: https://www.example.com/

try🐶everything ~$ curl -I http://www.example.com
HTTP/1.1 301 Moved Permanently
Date: Tue, 18 Jun 2019 09:58:26 GMT
Server: Apache
Location: https://www.example.com/
Content-Type: text/html; charset=iso-8859-1

try🐶everything ~$

以上、301 リダイレクト設定と動作確認ができました。

TIP

Rewrite モジュールで使うサーバー変数を確認する方法

index.php ファイルを作成します。

[root@centos7 htdocs]# vi example.com/index.php
<?php
phpinfo(INFO_MODULES);
?>
[root@centos7 htdocs]#

https://example.com へサクセスし、必要な変数を検索します。
例として REQUEST_SCHEME を検索して確認します。

php-variables-request-scheme
▲ サーバ変数を検索できます

Nginx の方は簡単にできますので、追記しておきます。

Nginx での 301 Redirect 設定

80ポートに対して、return 301 https://$host$request_uri;を追加するだけでリダイレクト設定は完了です。

[root@centos7 conf.d]# cat /etc/nginx/conf.d/default.conf
server {
    listen 80;
    server_name www.example.com;
    # 301 Redirect
    return 301 https://$host$request_uri;
}

server {
    listen              443 ssl;
    server_name         www.example.com;
...
}

conf ファイルを保存して Nginx をリロード ( systemctl restart nginx ) します。
Macbookなど、クライアントマシーンから動作確認をします。

# http://example.com ==> https://example.com
try🐶everything frontend$ curl -I http://example.com
HTTP/1.1 301 Moved Permanently    << 301リダイレクトされました
Server: nginx/1.14.0
Date: Mon, 09 Sep 2019 11:14:20 GMT
Content-Type: text/html
Content-Length: 185
Connection: keep-alive
Location: https://example.com/    << ここ!

# http://www.example.com ==> https://www.example.com
try🐶everything frontend$ curl -I http://www.example.com
HTTP/1.1 301 Moved Permanently    << 301リダイレクトされました
Server: nginx/1.14.0
Date: Mon, 09 Sep 2019 11:14:26 GMT
Content-Type: text/html
Content-Length: 185
Connection: keep-alive
Location: https://www.example.com/    << ここ!

try🐶everything frontend$ 

Nginx の方が確実に簡単ですね!!

もっと簡単な書き方があります(2026 年 7 月 追記)

本文の設定は今も動きますが、書いたあとに気づいたことがあります。順に補足します。

1. 本文の設定にタイプミスがあります

先に訂正させてください。設定側と確認側で、ホスト名が食い違っています。

RewriteCond %{HTTP_HOST} ^mainhost\.com$   ← ハイフンなし
curl -I http://main-host.com               ← ハイフンあり

このままコピーすると条件に一致しません。ご自身のドメインに置き換える際は、ドット同様ハイフンにもご注意ください。

2. 公式は mod_rewrite を使わない書き方をすすめています

Apache の公式ドキュメントには、HTTP から HTTPS へのリダイレクトについて「mod_rewrite のもっとも一般的な用途のひとつだが、たいていの場合はそれを使わないほうがうまくいく」と書かれています。

80 番ポート専用のバーチャルホストを立てて、そこに 1 行書くだけです。

<VirtualHost *:80>
    ServerName www.example.com
    Redirect permanent "/" "https://www.example.com/"
</VirtualHost>

<VirtualHost *:443>
    ServerName www.example.com
    # SSL の設定はこちらに
</VirtualHost>

Redirectmod_alias の機能なので、mod_rewrite を読み込む必要すらありません。パスもクエリもそのまま引き継がれます。

本文のように条件を並べる必要があるのは、設定ファイルを触れず .htaccess しか使えない場合です。その場合の公式の書き方はこれだけで足ります。

RewriteEngine On
RewriteCond "%{HTTPS}" !=on
RewriteRule "^(.*)" "https://%{SERVER_NAME}$1" [R=301,L]

本文では %{HTTPS}%{REQUEST_SCHEME}%{SERVER_PORT}[OR] でつないでいますが、同じことを 3 通りで確かめているだけです。条件が増えるほど読みにくくなり、意図しない挙動の温床になります。

3. Let’s Encrypt を使っているなら要注意

ここは実害が出る話です。すべてを HTTPS に飛ばすと、Let’s Encrypt の HTTP-01 認証が通らなくなります。認証用のファイルは平文の HTTP で読まれるためです。

証明書の更新時に突然失敗するので、原因が分かりにくい部類です。次のパスだけリダイレクトから除外してください。

/.well-known/acme-challenge/

mod_rewrite なら、リダイレクトのルールよりに次の 1 行を置きます。

RewriteRule "^\.well-known/acme-challenge/" - [L]

- は「書き換えない」という意味で、[L] でそこで処理を止めます。DNS-01 方式で認証している場合は、この対応は不要です。

4. HSTS もあわせて

301 リダイレクトだけでは、ユーザーの最初の 1 回は平文で接続します。そこを狙う攻撃があるため、HTTPS 側で次のヘッダを返しておくと、以後ブラウザが最初から HTTPS で接続してくれます。

Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"

ブラウザはこの指定を強く記憶します。HTTPS が完全に動いていることを確認してから入れてください。途中で HTTPS を止めると、しばらくサイトに繋がらなくなります。max-age を短くして試すのが安全です。

5. 環境について

本文の CentOS 7 は 2024 年 6 月にサポート終了、OpenSSL 1.1.1 も 2023 年 9 月にサポート終了しています。移行先についてはこちらの記事の追記にまとめています。設定の書き方自体は、そのまま新しい環境に持っていけます。

※ 2〜4 は 2026 年 7 月時点の Apache 公式ドキュメントおよび公開情報に基づく整理であり、当方の環境での再検証は行っていません。

参考文献

名前ベースのバーチャルホスト

コメント

タイトルとURLをコピーしました