Apache 2.4 設定ファイルの記述例

導入
====
[CentOS 7]の公式[Yum]リポジトリから提供されている[Apache]で動作を確認しています。それ以外のOSでは、[設定ファイルが置かれている場所] _(英語)_ や[ドキュメントルート]の初期値が異なる場合があるのでご注意ください。

[CentOS 7]: https://ja.wikipedia.org/wiki/CentOS "CentOS（セントオーエス）は、Red Hat Enterprise Linux（RHEL）との完全互換を目指したフリーのLinuxディストリビューションである。"
[Yum]: https://ja.wikipedia.org/wiki/Yellowdog_Updater_Modified "Yellowdog Updater Modified (Yum ヤム)はLinuxのRPM Package Managerのパッケージを管理するメタパッケージ管理システムである。"
[Apache]: https://ja.wikipedia.org/wiki/Apache_HTTP_Server "Apache HTTP Server（アパッチ エイチティーティーピー サーバ）は、世界中でもっとも多く使われているWebサーバソフトウェアであり、大規模な商用サイトから自宅サーバまで幅広く利用されている。単にApacheとも称されている。開発は、Apacheソフトウェア財団のApache HTTPサーバプロジェクトで行われている。Apache Licenseの下でソースコードが公開および配布されており、代表的なオープンソースソフトウェアの一つである。"
[設定ファイルが置かれている場所]: https://httpd.apache.org/docs/current/getting-started.html#configuration "Getting Started — Apache HTTP Server Version 2.4"
[ドキュメントルート]: https://httpd.apache.org/docs/current/urlmapping.html#documentroot "URL からファイルシステム上の位置へのマップ — Apache HTTP サーバ バージョン 2.4"

Apache設定ファイル (*.conf) のシンタックスハイライト
====================================================
CentOS標準のYumリポジトリで提供されているテキストエディタのうち[Vim]・[Emacs]以外のエディタは、初期状態で`.conf`ファイルのシンタックスハイライトが機能しません。以下のように設定ファイルの編集などを行い、シンタックスハイライトを有効にします。

[Vim]: https://ja.wikipedia.org/wiki/Vim "Vim（ヴィムまたはヴィアイエム）は、vi から派生し、発展した高機能なテキストエディタである。"
[Emacs]: https://ja.wikipedia.org/wiki/Emacs "Emacs（イーマックス）とは高機能でカスタマイズ性の高いテキストエディタである。スクリーン・エディタとしての人気が高く、特にUNIXのプログラマを中心としたコンピュータ技術者に愛用者が多い。"

[gedit]
-------
[Bug 612368 – Language definition for Apache configuration files](https://bugzilla.gnome.org/show_bug.cgi?id=612368#attachment_table)で公開されているファイルを利用します。

```sh
# Apache設定ファイル用の言語設定ファイルをダウンロード
wget https://bug612368.bugzilla-attachments.gnome.org/attachment.cgi?id=195525 --output-document=apache.lang
# 言語設定ファイル中のclass属性、class-disabled属性を削除。「*.conf」をハイライトするように
sed --in-place --regexp-extended --expression 's/\sclass(-disabled)?="[^"]+"//g' --expression 's/httpd\.conf;httpd2\.conf;apache\.conf;apache2\.conf/*.conf/' apache.lang
# GtkSourceViewのユーザー定義ディレクトリに移動
sudo mv apache.lang /usr/share/gtksourceview-*/language-specs/
```

[gedit]: https://ja.wikipedia.org/wiki/Gedit "gedit（ジーエディット）は、GNOMEデスクトップの標準テキストエディタ。通常のテキストエディタとしての機能に加え、複数のプログラミング言語に対応したハイライト表示、コードスニペットの追加といった、プログラム開発者向けの機能も有している。キー操作はWindows系でWindowsに慣れたユーザーにも使いやすい。"

[nano]
------
[Arch Linux]の[nano-syntax-highlighting-git]パッケージを利用します。[^nano] [^nanorc]

```sh
# INIファイルのシンタックスハイライトを行う設定ファイルをダウンロード
wget https://raw.githubusercontent.com/scopatz/nanorc/master/apacheconf.nanorc
# .conf で終わるファイルをApache設定ファイルとして扱うようにする
sed --in-place 's/httpd\\\.conf/.conf$/' apacheconf.nanorc
# シンタックスハイライトを行う設定ファイル保管場所に移動
sudo mv apacheconf.nanorc /usr/share/nano/
# nanoの個人設定ファイルから読み込むようにする
echo $'\n\n'## INI files$'\n'include "/usr/share/nano/apacheconf.nanorc" >> ~/.nanorc
```

[^nano]: [シンタックスハイライト | 設定 | nano — ArchWiki](https://wiki.archlinuxjp.org/index.php/nano#.E3.82.B7.E3.83.B3.E3.82.BF.E3.83.83.E3.82.AF.E3.82.B9.E3.83.8F.E3.82.A4.E3.83.A9.E3.82.A4.E3.83.88)
[^nanorc]: [37.nanoエディタの設定ファイル、nanorcをいじる — Linuxゲリラ戦記](http://www.garunimo.com/program/linux/linux37.xhtml)

[nano]: https://ja.wikipedia.org/wiki/Nano_%28%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88%E3%82%A8%E3%83%87%E3%82%A3%E3%82%BF%29 "nanoは、UNIXを中心としたシステムで使われる、cursesを使ったテキストエディタの一種である。スクリーンエディタの一種でありながら、CUIを用いて編集を行なうことが可能である。スクリーンエディタとして有名なものは既に多数存在するが、このエディタの特色は、その操作方法がWYSIWYGに慣れたユーザにとって分かりやすいため、初心者でも比較的容易に扱うことが可能という点にある。"
[Arch Linux]: https://ja.wikipedia.org/wiki/Arch_Linux "Arch Linux（アーチ・リナックス、ˈɑrtʃ）は、Linuxディストリビューションの1つであり、「シンプリシティ」、ミニマリズム、エレガンスさ、コードの正しさに焦点を当てて開発されている。「シンプリシティ」(Simplicity、簡潔さ) とは、Arch Linuxの言うところでは「…不必要な追加・修正、あるいは複雑化を伴わない…」ことであり、それは初心者の立場よりも開発者の立場からの見たものだとしている。Arch Linuxは、ローリング・リリースと呼ばれるリリースモデルを採用しており、他のLinuxディストリビューションで見られるような明確な「バージョン番号」や「リリース・スケジュール」を持たない。リポジトリ上のソフトウェアパッケージは日々新しいバージョンへと更新されており、定期的にソフトウェアアップデートを行うことで、システムを常に最新の状態に保つことができる。インストール用のイメージファイルは定期的に更新されているが、これは基本的にシステムパッケージ群の最新スナップショットに過ぎない。"
[nano-syntax-highlighting-git]: https://aur.archlinux.org/packages/nano-syntax-highlighting-git/ "nanoのシンタックスハイライト機能を強化する"

[Kate]
------
ファイル名が`.conf`で終わるファイルをApache設定ファイルとして開くようにします。

```xml:/usr/share/kde*/apps/katepart/syntax/.xml
<language name="Apache Configuration" section="Configuration"
          version="1.11" kateversion="2.0"
          extensions="*.conf;.htaccess*;.htpasswd*"
          mimetype=""
          author="Jan Janssen (medhefgo@googlemail.com)" license="LGPL">
<!-- ↑extensions属性値の「httpd.conf;httpd2.conf;apache.conf;apache2.conf」を「*.conf」に置換 -->

                    <!--##############
                        ## 以下省略 ##
                        ##############-->
```

[Kate]: https://ja.wikipedia.org/wiki/Kate "Kate とは KDE のテキストエディタである。頭字語 “Kate” は “KDE advanced text editor” の略である。Kate は KDE リリース 2.2（2002年8月15日）から kdebase パッケージの一部となっている。KDE の一部となっている KParts の機能により、他の KDE アプリケーションに編集コンポーネントとして Kate を組み込むことができる。統合開発環境 KDevelop やウェブ開発環境 Quanta Plus は編集コンポーネントとして Kate を利用している主要な KDE アプリケーションである。"

基本設定
========
```apache:/etc/httpd/conf/httpd.conf
                        ##############
                        ## 以上省略 ##
                        ##############

<IfModule unixd_module>
#
# If you wish httpd to run as a different user or group, you must run
# httpd as root initially and it will switch.  
#
# User/Group: The name (or #number) of the user/group to run httpd as.
# It is usually good practice to create a dedicated user and group for
# running httpd, as with most system services.
#
User apache
Group apache
## ↑両方とも daemon から apache に変更する (CentOS7標準のApacheでは設定済み) ##

</IfModule>

# 'Main' server configuration
#
# The directives in this section set up the values used by the 'main'
# server, which responds to any requests that aren't handled by a
# <VirtualHost> definition.  These values also provide defaults for
# any <VirtualHost> containers you may define later in the file.
#
# All of these directives may appear inside <VirtualHost> containers,
# in which case these default settings will be overridden for the
# virtual host being defined.
#

#
# ServerAdmin: Your address, where problems with the server should be
# e-mailed.  This address appears on some server-generated pages, such
# as error documents.  e.g. admin@your-domain.com
#
ServerAdmin webmaster@example.jp
## ↑サーバー管理者への問い合わせ先メールアドレスに変更する ##

#
# ServerName gives the name and port that the server uses to identify itself.
# This can often be determined automatically, but we recommend you specify
# it explicitly to prevent problems during startup.
#
# If your host doesn't have a registered DNS name, enter its IP address here.
#
ServerName example.jp:80
## ↑サーバーのホスト名を指定する ##

                        ##############
                        ##   中略   ##
                        ##############
#
# Relax access to content within /var/www.
#
#<Directory "/var/www">
#    AllowOverride None
#    # Allow open access:
#    Require all granted
#</Directory>
## ↑<Directory "/var/www"> セクションをコメントアウトする (CentOS7標準のApacheの場合) ##

## ↓一つ上のディレクトリに変更する ##
<Directory "/var/www">
    #
    # Possible values for the Options directive are "None", "All",
    # or any combination of:
    #   Indexes Includes FollowSymLinks SymLinksifOwnerMatch ExecCGI MultiViews
    #
    # Note that "MultiViews" must be named *explicitly* --- "Options All"
    # doesn't give it to you.
    #
    # The Options directive is both complicated and important.  Please see
    # https://httpd.apache.org/docs/2.4/mod/core.html#options
    # for more information.
    #
    Options FollowSymLinks
    ## ↑ Indexes を削除する ##

    #
    # AllowOverride controls what directives may be placed in .htaccess files.
    # It can be "All", "None", or any combination of the keywords:
    #   AllowOverride FileInfo AuthConfig Limit
    #
    AllowOverride None
    
    #
    # Controls who can get stuff from this server.
    #
    #Require all granted
    ## ↑コメントアウトする ##
</Directory>

#
# DirectoryIndex: sets the file that Apache will serve if a directory
# is requested.
#
<IfModule dir_module>
    DirectoryIndex index.html
</IfModule>

                        ##############
                        ##   中略   ##
                        ##############
#
# LogLevel: Control the number of messages logged to the error_log.
# Possible values include: debug, info, notice, warn, error, crit,
# alert, emerg.
#
#LogLevel warn
## ↑コメントアウトする ##

                        ##############
                        ##   中略   ##
                        ##############
#
# Customizable error responses come in three flavors:
# 1) plain text 2) local redirects 3) external redirects
#
# Some examples:
#ErrorDocument 500 "The server made a boo boo."
#ErrorDocument 404 /missing.html
#ErrorDocument 404 "/cgi-bin/missing_handler.pl"
#ErrorDocument 402 http://www.example.com/subscription_info.html
#
ErrorDocument 403 /not-found
ErrorDocument 404 /not-found
ErrorDocument 503 /internal-server-error
## ↑それぞれのエラーコードに対応するファイルを指定する ##

                        ##############
                        ## 以下省略 ##
                        ##############
```

&#x20;
<dl><dt>[User ディレクティブ]　\([旧バージョンの翻訳][user-old])</dt><dt>[Group ディレクティブ]　\([旧バージョンの翻訳][group-old])</dt><dd>`User apache`<br />`Group apache`</dd><dd>root権限で起動したApacheの親プロセスが子プロセスを生成する際に使用するユーザー名とグループ名を指定します。ここでは、`daemon`から、Apacheインストール時に自動作成されたユーザー (グループ) `apache`に変更します。</dd>

<dt>[ServerAdmin ディレクティブ]</dt><dd>`ServerAdmin webmaster@example.jp`</dd><dd>サーバー管理者への問い合わせ先メールアドレス (または別サーバーのURL) を指定します。 **`webmaster@example.jp`は例示用のアドレスなので、自分が管理するメールアドレスに置き換えてください。** </dd>

<dt>[ServerName ディレクティブ]</dt><dd>`ServerName example.jp:80`</dd><dd>サーバーのホスト名とポート番号を指定します。サーバーのIPアドレスに対して、DNSのPTRレコード (逆引きレコード) で設定したホスト名を指定しておくと良いでしょう。このディレクティブが欠けていると、「正確なホスト名を決定できなかった」という旨のエラーが発生します。 **`example.jp`は例示用のホスト名なので、自分のサーバーのホスト名に置き換えてください。** このディレクティブは、後述する[&lt;VirtualHost&gt; セクション]内でも設定します。</dd>

<dt>[Option ディレクティブ]</dt><dd>利用できる機能の制限を強化、または緩和します。最初から記述されている`Options Indexes FollowSymLinks`は、<i>Indexes機能</i>と<i>FollowSymLinks機能</i>が有効です。スラッシュで終わるURLにアクセスがあった場合、 [DirectoryIndex ディレクティブ]で指定したファイルがディレクトリに存在しなければ、ディレクトリ内のファイル一覧を返すのが<i>Indexes機能</i>です。このディレクティブが欠けていると、デフォルト値である`Options All`に設定されるので注意してください。</dd>

<dt>[Require ディレクティブ]　\(リンク先英語)</dt><dd>サーバーのディレクトリに接続してくるクライアントについて、許可・拒否する条件を指定するディレクティブです。昔は[Allow ディレクティブやDeny ディレクティブ]を利用していました。`Require all granted`は、すべてのクライアントからの接続を許可します。`Require all denied`は、すべてのクライアントからの接続を拒否します。</dd>

<dt>[&lt;Directory&gt; セクション]</dt><dd>ディレクティブを適用するディレクトリを指定します。<i>ファイルシステムのパス絶対URL</i> (ドキュメントルートではなくOSのルートディレクトリをルートとするスラッシュで始まるURL) で指定します。`*` `?` `[` `]`をワイルドカードとして使用できます。<i>パス区分</i> (ディレクトリ名など) を`/`以外 (Windowsの`\\`など) で区切るOSであっても、このセクションの引数では`/`を用います。</dd><dd>記述できるディレクティブの制限などはありますが、`<Directory /var/www/html>`内に記述するのと、`/var/www/html/.htaccess`に記述するのは同義です。</dd><dd>最初は`<Directory "/var/www/html">`にドキュメントルートの設定が記述されています。`html`以外のディレクトリへのアクセスがあるなら、`<Directory "/var/www">`に変更し、`Require all granted`をコメントアウトしておきます。</dd>

<dt>[Redirect ディレクティブ]</dt><dd>第2引数で指定したURLを、第3引数で指定したURLにリダイレクトします。第1引数にはHTTPステータスコードを指定します。第1引数は省略可能で、省略した場合`302`になります。URLは前方一致で、`Redirect /foo /bar`と記述すると、https://example.com/foo/test が https://example.com/bar/test にリダイレクトされます。この場合、https://example.com/foo2 などには一致しません。</dd><dd>第1引数に[300〜399]以外の数値を指定することもでき、この場合第3引数は指定しません。</dd><dd>第1引数において、`301` `302` `303` `410`は、それぞれ`permanent` `temp` `seeother` `gone`とキーワードで指定することもできます。なお、古いHTTP仕様で`302`はこのキーワード通り`Moved Temporarily`でしたが、仕様が変更され[302 (Found)]となっており、<i>一時的なリダイレクト</i>には現在[307 (Temporary Redirect)]を使うことになっています。</dd>

<dt>[RedirectMatch ディレクティブ]</dt><dd>第2引数に正規表現を指定すること以外は、[Redirect ディレクティブ]と同じです。正規表現内の後方参照は、第3引数で`$1`などと数字に`$`を前置して利用できます。たとえば、`RedirectMatch ^/foo(/.*)?$ /bar$1`は`Redirect /foo /bar`と同じ意味になります。</dd>

<dt>[ErrorDocument ディレクティブ]</dt><dd>`ErrorDocument 404 /not-found`</dd><dd>エラーが発生したときに返す文書等を指定します。第2引数でファイルを指定する場合は、<i>パス絶対URL</i> (ドキュメントルートをルートとするスラッシュで始まるパス) で指定する必要があります。</dd><dd>ここでは、[ファイルの存在自体を隠蔽するなどの理由で、エラーコードが403の場合でも404の場合と同じ文書を返す]ようにしています。この場合第2引数に、<i>`404`を返すプログラム</i>を指定したり、[RewriteRule ディレクティブ]の[\[R|redirect\]フラグ][R]で`404`を返したりする必要があります。</dd>
</dl>

[User ディレクティブ]: https://httpd.apache.org/docs/current/mod/mod_unixd.html#user "The userid under which the server will answer requests"
[user-old]: https://httpd.apache.org/docs/2.2/mod/mpm_common.html#user "リクエストに応答する際に用いるユーザ ID"
[Group ディレクティブ]: https://httpd.apache.org/docs/current/mod/mod_unixd.html#group "Group under which the server will answer requests"
[group-old]: https://httpd.apache.org/docs/2.2/mod/mpm_common.html#group "リクエストに応答する際に所属するグループ"
[ServerAdmin ディレクティブ]: https://httpd.apache.org/docs/current/mod/core.html#serveradmin "サーバがクライアントに送るエラーメッセージに含める電子メールの アドレス"
[ServerName ディレクティブ]: https://httpd.apache.org/docs/current/mod/core.html#servername "サーバが自分自身を示すときに使うホスト名とポート"
[&lt;VirtualHost&gt; セクション]: https://httpd.apache.org/docs/current/mod/core.html#virtualhost "特定のホスト名や IP アドレスのみに適用されるディレクティブを 囲む"
[Option ディレクティブ]: https://httpd.apache.org/docs/current/mod/core.html#options "ディレクトリに対して使用可能な機能を設定する"
[DirectoryIndex ディレクティブ]: https://httpd.apache.org/docs/current/mod/mod_dir.html#directoryindex "クライアントがディレクトリをリクエストしたときに調べる リソースのリスト"
[Require ディレクティブ]: https://httpd.apache.org/docs/current/mod/mod_authz_core.html#require "Tests whether an authenticated user is authorized by an authorization provider."
[Allow ディレクティブやDeny ディレクティブ]: https://httpd.apache.org/docs/current/mod/mod_access_compat.html "ホスト (名前もしくは IP アドレス) に基づいたグループ承認"
[&lt;Directory&gt; セクション]: https://httpd.apache.org/docs/current/mod/core.html#directory "指定のファイルシステムのディレクトリとサブディレクトリとのみに 適用されるディレクティブを囲む"
[Redirect ディレクティブ]: https://httpd.apache.org/docs/current/mod/mod_alias.html#redirect "クライアントが違う URL を取得するように外部へのリダイレクトを 送る"
[300〜399]: https://triple-underscore.github.io/RFC7231-ja.html#status.3xx "クラス 3xx (Redirection) の状態°コードは、[ 要請が履行されるためには, UA による更なる動作がとられる必要がある ] ことを指示する。"
[302 (Found)]: https://triple-underscore.github.io/RFC7231-ja.html#status.302 "状態°コード 302 (Found)は、[ ターゲットリソースが, 一時的に, 異なる URI の下に居る ] ことを指示する。 リダイレクトは, その時々で改められ得るので、クライアントは, 未来の要請に対しては 実効要請 URI を利用し続けるべき.である。"
[307 (Temporary Redirect)]: https://triple-underscore.github.io/RFC7231-ja.html#status.307 "状態°コード 307 (Temporary Redirect)は、[ ターゲットリソースが, 一時的に異なる URI の下に居る ] ことに加えて, [ UA は、[ その URI への自動リダイレクトを遂行する ] ときに, 要請メソッドを変更してはならない ] ことを指示する。 リダイレクトは, 時経過に伴って変化し得るので、クライアントは, 未来の要請においても, 元の実効要請 URI を利用し続けるべき.である。"
[RedirectMatch ディレクティブ]: https://httpd.apache.org/docs/current/mod/mod_alias.html#redirectmatch "mod_alias — Apache HTTP サーバ"
[ErrorDocument ディレクティブ]: https://httpd.apache.org/docs/current/mod/core.html#errordocument "core — Apache HTTP サーバ"
[ファイルの存在自体を隠蔽するなどの理由で、エラーコードが403の場合でも404の場合と同じ文書を返す]: https://triple-underscore.github.io/RFC7231-ja.html#status.403 "生成元サーバは、禁止されたターゲットリソースの現在の存在を “隠し” たいと望むときは, 代わりに [ 404 (Not Found) ] で応答してよい。"
[R]: https://httpd.apache.org/docs/current/rewrite/flags.html#flag_r "Use of the [R] flag causes a HTTP redirect to be issued to the browser. If a fully-qualified URL is specified (that is, including http://servername/) then a redirect will be issued to that location. Otherwise, the current protocol, servername, and port number will be used to generate the URL sent with the redirect."

TLS (俗称: SSL) の設定
======================
サーバー証明書をインストール済みであればこの項は読み飛ばしてください。この記事では、無料でDV証明書を取得できる[Let’s Encrypt]を利用する場合について解説します。[Let’s Encrypt]は証明書を自動発行する[ACMEプロトコル]を採用しており、[Certbot]などのACMEクライアントで簡単に導入できます。

[Let’s Encrypt]: https://letsencrypt.jp/about/ "Let’s Encrypt は、無料で利用できる自動化されていてオープンな認証局（CA）です。公共の利益を図る目的で Internet Security Research Group (ISRG) が運営しています。"
[ACMEプロトコル]: http://jxck.hatenablog.com/entry/letsencrypt-acme "Let’s Encrypt を支える ACME プロトコル — Block Rockin’ Codes"
[Certbot]: https://letsencrypt.jp/command/ "Certbot クライアントを使用することで、HTTPS / TLS / SSL の証明書を、取得したりインストールしたりすることができます。"

Certbotのインストール
---------------------
この記事では、サーバー設定も自動で行える[Certbot]をACMEクライアントとして使用します。

[Let’s Encrypt の使い方 — Let’s Encrypt 総合ポータル](https://letsencrypt.jp/usage/ "Let’s Encrypt は、クライアントソフトウェア「Certbot」を使用することで、SSL/TLS サーバ証明書の取得・更新作業を自動化できる仕組みになっています。")

各OSごとの取得方法は上記ページをご覧ください。以下はCentOS7の場合における例です。

```sh
# 【インストールしていない場合】EPELリポジトリとmod_sslのインストール
sudo yum install epel-release mod_ssl

# Certbotのインストール
sudo yum install certbot python-certbot-apache
# ↑EPEL7のGPG公開鍵を取り込んでも良いか訊ねられた場合、
#   Fingerprintが https://getfedora.org/ja/keys/ の指紋と大文字小文字無視で一致するか確認します。

# 【未設定の場合】443ポートを開ける
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload
```

証明書の取得・インストール
--------------------------
途中でApacheが再起動される際にエラーが出るため、先にApacheを起動しておきます。

```sh
sudo apachectl start
sudo certbot --apache --must-staple --hsts --redirect
```

途中で証明書を発行するドメイン名の入力 (複数の場合は空白かカンマ区切り)、緊急連絡などに使うメールアドレスの入力、およびLet’s Encrypt利用規約への同意を求められます。また、設定の保存先として `ssl.conf` (CentOSの場合) が提示されるので、そのままそれを <kbd><samp>&lt;Select&gt;</samp></kbd> します。

[後述の設定で複数のドメインを扱う]場合、`--redirect` の代わりに一旦 `--no-redirect` を指定しておきます。

[後述の設定で複数のドメインを扱う]: #一つのapacheで複数のドメインを扱う仮想ホスト

Apacheの設定
------------

```apache:/etc/httpd/conf.d/ssl.conf
                        ##############
                        ## 以上省略 ##
                        ##############

# Use separate log files for the SSL virtual host; note that LogLevel
# is not inherited from httpd.conf.
#ErrorLog logs/ssl_error_log
#TransferLog logs/ssl_access_log
#LogLevel warn
## ↑3行ともコメントアウトする ##

#   SSL Engine Switch:
#   Enable/Disable SSL for this virtual host.
#SSLEngine on
## ↑コメントアウトする ##

                        ##############
                        ##   中略   ##
                        ##############

#   Server Certificate:
# Point SSLCertificateFile at a PEM encoded certificate.  If
# the certificate is encrypted, then you will be prompted for a
# pass phrase.  Note that a kill -HUP will prompt again.  A new
# certificate can be generated using the genkey(1) command.
SSLCertificateFile /etc/letsencrypt/live/example.jp/cert.pem
## ↑CertbotのApacheプラグインによって自動的に修正された行 ##

#   Server Private Key:
#   If the key is not combined with the certificate, use this
#   directive to point at the key file.  Keep in mind that if
#   you've both a RSA and a DSA private key you can configure
#   both in parallel (to also allow the use of DSA ciphers, etc.)
SSLCertificateKeyFile /etc/letsencrypt/live/example.jp/privkey.pem
## ↑CertbotのApacheプラグインによって自動的に修正された行 ##

                        ##############
                        ##   中略   ##
                        ##############

#   Per-Server Logging:
#   The home of a custom SSL log file. Use this when you want a
#   compact non-error SSL logfile on a virtual host basis.
CustomLog logs/ssl_request_log \
          "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"

# TLSの基本設定を読み込み
Include /etc/letsencrypt/options-ssl-apache.conf
## ↑この行を追加 ##

## ↓これ以降の行が、CertbotのApacheプラグインによって追記された文字列 ##
ServerName example.jp
ServerAlias sub1.example.jp sub2.example.jp
Header always set Strict-Transport-Security "max-age=31536000"
SSLUseStapling on
SSLCertificateChainFile /etc/letsencrypt/live/example.jp/chain.pem
</VirtualHost>                                  

<IfModule mod_ssl.c>
SSLStaplingCache shmcb:/var/run/apache2/stapling_cache(128000)
</IfModule>
```

&#x20;
<dl><dt>[SSLProtocol ディレクティブ]　\(リンク先英語)</dt><dd>`SSLProtocol all -SSLv2 -SSLv3`</dd><dd>使用するSSL/TLSのバージョンを制御します。各引数の先頭に `+` `-` を付け、手前で指定したバージョンに追加するか除外するかを表します。</dd><dd>ここでは、サポートされるすべてのバージョンから、(SSL 2.0)、SSL 3.0 を除外しています。なお、CentOS 7 の `ssl.conf` には最初 `SSLProtocol all -SSLv2` と記述されているものの、Apache 2.4 では SSL 2.0 をすでにサポートしていないので、エラーこそ出ませんがこの指定は無意味です。</dd><dd>もともと SSL 3.0 は標準化されていませんでしたが、[RFC 7568によって使用が禁止されました]。TLS 1.0、およびTLS 1.1は、実装間でより新しいバージョンがある場合は使用すべきでないと[RFC 7525に書かれています]。NetReaderなどのIEコンポーネントブラウザは、Windows VistaだとTLS 1.1に対応していない[^vista]ので、2017年4月11日まではTLS 1.0を有効にしておく必要があるかと思います。[^NetReader]</dd>

<dt>[SSLCipherSuite ディレクティブ]　\(リンク先英語)</dt><dd>`SSLCipherSuite !DSS:EECDH+HIGH:EDH+HIGH:HIGH:MEDIUM:!aNULL:!MD5:!SEED:!IDEA`</dd><dd>使用する暗号化方式を制御します。各引数の先頭に `+` `-` `!` を付け、手前で指定したバージョンに追加するか除外するかを表します。引数の意味については、[ApacheでOpenSSLのセキュリティを強化する]をご覧ください。</dd>

<dt>[SSLHonorCipherOrder ディレクティブ]　\(リンク先英語)</dt><dd>`SSLHonorCipherOrder on`</dd><dd>使用する暗号化方式の決定について、クライアントよりサーバーのリストを優先します。既定では無効になっています。</dd>

<dt>[SSLCertificateFile ディレクティブ]　\(リンク先英語)</dt><dd>`SSLCertificateFile /etc/letsencrypt/live/example.jp/cert.pem`</dd><dd>Apache 2.4.7以下ではサーバー証明書 (Certbotで取得した場合は `cert.pem`) を、Apache 2.4.8以上ではサーバー証明書と中間証明書を結合したファイル (Certbotで取得した場合は `fullchain.pem`) のパスを指定します。 **2.4.7/2.4.8をまたいでバージョンを変更する際は修正する必要があるので注意してください。** </dd><dd>この例はApache 2.4.6のものなので、Certbotによってサーバー証明書のパスが設定されています。</dd>

<dt>[SSLCertificateKeyFile ディレクティブ]　\(リンク先英語)</dt><dd>`SSLCertificateKeyFile /etc/letsencrypt/live/example.jp/privkey.pem`</dd><dd>秘密鍵を指定します。</dd>

<dt>[SSLCertificateChainFile ディレクティブ]　\(リンク先英語)</dt><dd>`SSLCertificateChainFile /etc/letsencrypt/live/example.jp/chain.pem`</dd><dd>Apache 2.4.7以下において、中間証明書 (Certbotで取得した場合は `chain.pem`) を指定します。Apache 2.4.8以降、[SSLCertificateFile ディレクティブ]に統合する形で廃止されました。 **2.4.7/2.4.8をまたいでバージョンを変更する際は修正する必要があるので注意してください。** </dd><dd>この例はApache 2.4.6のものなので、Certbotによってこのディレクティブが追加されています。</dd>

<dt>[SSLUseStapling ディレクティブ]　\(リンク先英語)</dt><dd>`SSLUseStapling on`</dd><dd>[OCSP Stapling]を有効化します。</dd>

<dt>[SSLStaplingCache ディレクティブ]　\(リンク先英語)</dt><dd>`SSLStaplingCache shmcb:/var/run/apache2/stapling_cache(128000)`</dd><dd>[OCSP Stapling]におけるキャッシュの保存先と容量を指定します。</dd>
</dl>

[^vista]: [ウェブブラウザ | 実装 | Transport Layer Security — Wikipedia](https://ja.wikipedia.org/wiki/Transport_Layer_Security#.E3.82.A6.E3.82.A7.E3.83.96.E3.83.96.E3.83.A9.E3.82.A6.E3.82.B6 "TLS 1.1、1.2に未対応：Internet Explorer 9（Windows Vista / Server 2008向け）")
[^NetReader]: [Kazzさんのツイート: “NetMarketShareによれば2015年12月時点でのVistaのシェアは1.62% 同じように視覚障碍者のVista利用者が減っていると仮定しても、今IE9を切り捨てると視覚障害者100人のうち2人くらいに対して全くアクセス不能にさせる可能性があるということになる”](https://twitter.com/asamuzakjp/statuses/687878739976294400)

[SSLProtocol ディレクティブ]: https://httpd.apache.org/docs/current/mod/mod_ssl.html#sslprotocol "Configure usable SSL/TLS protocol versions"
[RFC 7568によって使用が禁止されました]: https://wiki.suikawiki.org/n/Transport%20Layer%20Security#section-歴史 SSL-3.0-の廃止 "2015年6月に出版された RFC 7568 は、 SSL 3.0 を使ってはならないと規定しています。禁止しているのになぜか非推奨と称しており、 廃止ではありません。 SSL 3.0 の RFC である RFC 6101 も廃止はされていませんが、これは元々 Historic で発行されたものなので廃止は必要ないという判断なのでしょうか。"
[RFC 7525に書かれています]: http://blog.livedoor.jp/k_urushima/archives/1768181.html "2015年5月7日に「RFC 7525 TLSとDTLSの安全な利用に関する推奨事項(Recommendations for Secure Use of Transport Layer Security (TLS) and Datagram Transport Layer Security (DTLS))」が公開されました。"
[SSLCipherSuite ディレクティブ]: https://httpd.apache.org/docs/current/mod/mod_ssl.html#sslciphersuite "Cipher Suite available for negotiation in SSL handshake"
[ApacheでOpenSSLのセキュリティを強化する]: //qiita.com/sion_cojp/items/99fee211ceace3f76cff
[SSLHonorCipherOrder ディレクティブ]: https://httpd.apache.org/docs/current/mod/mod_ssl.html#sslhonorcipherorder "Option to prefer the server’s cipher preference order"
[SSLCertificateFile ディレクティブ]: https://httpd.apache.org/docs/current/mod/mod_ssl.html#sslcertificatefile "Server PEM-encoded X.509 certificate data file"
[SSLCertificateKeyFile ディレクティブ]: https://httpd.apache.org/docs/current/mod/mod_ssl.html#sslcertificatekeyfile "Server PEM‐encoded private key file"
[SSLCertificateChainFile ディレクティブ]: https://httpd.apache.org/docs/current/mod/mod_ssl.html#sslcertificatechainfile "File of PEM‐encoded Server CA Certificates"
[SSLUseStapling ディレクティブ]: https://httpd.apache.org/docs/current/mod/mod_ssl.html#sslusestapling "Enable stapling of OCSP responses in the TLS handshake"
[OCSP Stapling]: //qiita.com/harukasan/items/fe37f3bab8a5ca3f4f92#ocsp-stapling "OCSP Stapling(ステープリング)では、クライアントがOCSP要求を行うのではなく、サーバがOCSP要求を行い、その応答をキャッシュする。サーバはキャッシュしたOCSP応答を、サーバ証明書と一緒にクライアントに送信する。"
[SSLStaplingCache ディレクティブ]: https://httpd.apache.org/docs/current/mod/mod_ssl.html#sslstaplingcache "Configures the OCSP stapling cache"

証明書の自動更新例 (systemd)
----------------------------
`certbot renew` で期限切れが近い証明書を更新できます。[systemd]を採用しているCentOS 7などでは、certbotパッケージに同梱のcertbot-renew.timerを利用します。[^certbot-renew]

```sh
# certbot.timerの有効化 (OS起動時に自動的に起動させる) と起動
sudo systemctl enable --now certbot-renew.timer
```

直近のログは次のようなコマンドで調べます。

- `sudo cat /var/log/letsencrypt/letsencrypt.log`
- `systemctl status certbot-renew --full --lines 50`
- `systemctl status certbot-renew.timer --full`

[^certbot-renew]: [let’s Encryptの証明書更新 CentOS7編 — Qiita](https://qiita.com/mogya/items/f43334fd531888c4774f "CentOS 7をはじめとして、パッケージでcertbotをインストールするようなディストリビューションでは、certbotと一緒に、証明書を更新するための設定ファイルが一緒に配布されています。")

[systemd]: https://ja.wikipedia.org/wiki/Systemd "systemdはシステム管理デーモン、ライブラリおよびユーティリティの一式であり、管理および設定における中心的プラットフォームとしてLinuxコンピュータオペレーティングシステム用に設計されている。"

HTTP応答ヘッダの設定
====================
```apache:/etc/httpd/conf/httpd.conf
# XHTMLに対応していないブラウザ
SetEnvIfExpr "!(%{HTTP_ACCEPT} -strcmatch '*application/xhtml+xml*') || %{HTTP_USER_AGENT} =~ m#UP\\.Browser/6\\.2|Nintendo 3DS| NX/1\\.|Trident/5\\.#" LEGACY_BROWSER
## ↑ファイルの先頭に挿入 ##

                        ##############
                        ##   中略   ##
                        ##############

<IfModule mime_module>

                        ##############
                        ##   中略   ##
                        ##############

    #
    # Filters allow you to process content before it is sent to the client.
    #
    # To parse .shtml files for server-side includes (SSI):
    # (You will also need to add "Includes" to the "Options" directive.)
    #
    #AddType text/html .shtml
    #AddOutputFilter INCLUDES .shtml
    ## ↑この2行をコメントアウトする (CentOS7標準のApacheの場合) ##
    
    ## ↓<IfModule mime_module> セクションの末尾に追記 ##
    <If "-n reqenv('LEGACY_BROWSER')">
        # XHTMLに対応していなければ
        AddType text/html .xhtml
    </If>
</IfModule>

#
# Specify a default charset for all content served; this enables
# interpretation of all content as UTF-8 by default.  To use the 
# default browser choice (ISO-8859-1), or to allow the META tags
# in HTML content to override this choice, comment out this
# directive:
#
#AddDefaultCharset UTF-8
## ↑コメントアウトする ##

# content-typeヘッダにcharsetパラメータを付加する
AddCharset utf-8 .xhtml .html .css .es .js .txt .json .xml .csv
## ↑この行を追加 ##

# content-languageヘッダを送出する
AddLanguage ja .xhtml .html
## ↑この行を追加 ##

                        ##############
                        ##   中略   ##
                        ##############

## ↓ファイルの末尾に追記 ##
ServerTokens ProductOnly
Header always set x-content-type-options nosniff
<If "%{HTTP_USER_AGENT} =~ m#Trident/5\\.#">
    # Internet Explorer 9 の互換表示ボタンを消す
    Header always set x-ua-compatible IE=edge
</If>
```

```apache:/etc/httpd/conf.d/ssl.conf
                        ##############
                        ## 以上省略 ##
                        ##############

ServerName example.jp
ServerAlias sub1.example.jp sub2.example.jp
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
## ↑「includeSubDomains」「preload」パラメータを追加 ##
SSLUseStapling on
SSLCertificateChainFile /etc/letsencrypt/live/example.jp/chain.pem
</VirtualHost>                                  

<IfModule mod_ssl.c>
SSLStaplingCache shmcb:/var/run/apache2/stapling_cache(128000)
</IfModule>
```

```apache:/etc/httpd/conf.d/autoindex.conf　(CentOS7標準のApacheの場合)
#
# Directives controlling the display of server-generated directory listings.
#
# Required modules: mod_authz_core, mod_authz_host,
#                   mod_autoindex, mod_alias
#
# To see the listing of a directory, the Options directive for the
# directory must include "Indexes", and the directory must not contain
# a file matching those listed in the DirectoryIndex directive.
#

#
# IndexOptions: Controls the appearance of server-generated directory
# listings.
#
#IndexOptions FancyIndexing HTMLTable VersionSort
## ↑コメントアウトする ##

# We include the /icons/ alias for FancyIndexed directory listings.  If
# you do not use FancyIndexing, you may comment this out.
#
#Alias /icons/ "/usr/share/httpd/icons/"
## ↑コメントアウトする ##

                        ##############
                        ## 以下省略 ##
                        ##############
```

```apache:/etc/httpd/conf.d/welcome.conf　(CentOS7標準のApacheの場合)
# 
# This configuration file enables the default "Welcome" page if there
# is no default index page present for the root URL.  To disable the
# Welcome page, comment out all the lines below. 
#
# NOTE: if this file is removed, it will be restored on upgrades.
#
#<LocationMatch "^/+$">
#    Options -Indexes
#    ErrorDocument 403 /.noindex.html
#</LocationMatch>

#<Directory /usr/share/httpd/noindex>
#    AllowOverride None
#    Require all granted
#</Directory>

#Alias /.noindex.html /usr/share/httpd/noindex/index.html
#Alias /css/bootstrap.min.css /usr/share/httpd/noindex/css/bootstrap.min.css
#Alias /css/open-sans.css /usr/share/httpd/noindex/css/open-sans.css
#Alias /images/apache_pb.gif /usr/share/httpd/noindex/images/apache_pb.gif
#Alias /images/poweredby.png /usr/share/httpd/noindex/images/poweredby.png
## ↑すべてコメントアウトする ##
```

&#x20;
<dl><dt>[SetEnvIfExpr ディレクティブ]　\([SetEvnIf ディレクティブの日本語訳])</dt><dd>`SetEnvIfExpr "!(%{HTTP_ACCEPT} -strcmatch '*application/xhtml+xml*') || %{HTTP_USER_AGENT} =~ m#UP\\.Browser/6\\.2|Nintendo 3DS| NX/1\\.|Trident/5\\.#" LEGACY_BROWSER`</dd><dd>第1引数の条件式が真なら、第2引数の環境変数を設定します。条件式の構文は[Expressions in Apache HTTP Server]に載っています。この構文は[&lt;If&gt; セクション]や[RewriteCond ディレクティブ]でも利用できます。`LEGACY_BROWSER`のように変数値を省略することは、`LEGACY_BROWSER=1`のように変数値として`1`を指定することと同義です。</dd><dd>[accept要求ヘッダ]に`application/xhtml+xml`が含まれていれば、基本的にそれはXHTML文書に対応しているWebブラウザからのアクセスです。しかしその中には、XHTML文書を正常に扱えず、HTML文書を返した方が良いブラウザもあります。httpd.confの先頭に上記のような[SetEnvIfExpr ディレクティブ]を記述することで、XHTML文書に対応していないブラウザからのアクセスに対し、`LEGACY_BROWSER`という環境変数が設定されるようにしています。ここでXHTML文書に対応していないブラウザとして扱っているのは、[accept要求ヘッダ]に`application/xhtml+xml`が含まれないブラウザ、Openwave Mobile Browser 6.2 (古い[EZブラウザ])、[NetFront Browser NX 1] \([ニンテンドー3DS用インターネットブラウザー])[^3ds]、Internet Explorer 9[^ie9-xhtml] [^ie9] です。</dd>

<dt>[AddType ディレクティブ]</dt><dd>`AddType image/vnd.microsoft.icon .ico .cur`</dd><dd>どの拡張子がどのファイル形式に対応するか指定します。`mime.types`ファイルに登録されている情報を元に[content-type応答ヘッダ][content-type]が返されるので、基本的には必要はありません。登録されていなかったり、登録されていても情報が古かったりする場合に、このディレクティブを使用して`mime.types`の設定を上書きします。</dd>

<dt>[&lt;If&gt; セクション]</dt><dt>[&lt;ElseIf&gt; セクション]　\(リンク先英語)</dt><dt>[&lt;Else&gt; セクション]　\(リンク先英語)</dt><dd>`<If "-n reqenv('LEGACY_BROWSER')">`〜`</If>`</dd><dd>ディレクティブを適用する条件式を指定します。ドキュメンテーションにそのような説明がなくエラーも出ませんが、 **これらのセクションを入れ子にすると、内側のセクションが中身ごと無視されます** 。（Apache 2.4.7 現在）</dd><dd>`-n reqenv('LEGACY_BROWSER')`は、<i>`LEGACY_BROWSER`という環境変数が空でなければ</i>真を返す式です。</dd>

<dt>[Include ディレクティブ]<br>[IncludeOptional ディレクティブ]　\(リンク先英語)</dt><dd>`Include /etc/httpd/conf/extra/httpd-languages.conf`</dd><dd>サーバー設定ファイルから他の設定ファイルを読み込みます。ファイル、またはディレクトリを<i>ファイルシステムのパス絶対URL</i>か、[サーバールート] \(CentOS7標準のApacheの場合、デフォルトでは`ServerRoot "/etc/httpd"`が記述されている) からのパス相対URLで指定します。ワイルドカードも使用可能です。<br>[IncludeOptional ディレクティブ]はほぼ[Include ディレクティブ]と同じですが、ファイル、またはディレクトリが存在しない場合でもエラーが発生しません。</dd>

<dt>[ServerTokens ディレクティブ]</dt><dd>[server応答ヘッダ][server]とサーバーが生成するドキュメントのフッターに表示されるサーバー情報を制御します。デフォルト値は`ServerTokens Full`で、`Server: Apache/2.4.7 (Unix)`のように出力されます。`ServerTokens ProductOnly`を指定すると、`Server: Apache`と出力されます。</dd>

<dt>[Header ディレクティブ]</dt><dd>`Header always set x-content-type-options nosniff`</dd><dd>HTTP応答ヘッダを制御します。内部ヘッダテーブルにはヘッダの一覧が格納されており、[2xxレスポンス]の場合のみ利用される<i>onsuccessテーブル</i>と、2xxレスポンスを含むすべての場合で利用される<i>alwaysテーブル</i>のどちらを書き換えるか、第1引数で指定します。第1引数は省略可能で、省略した場合`onsuccess`になります。第2引数で内部ヘッダテーブルに対してどのような操作を行うか指定します。</dd><dd>第2引数について、`set`は新しくヘッダを設定しますが、同じ名前のヘッダが既に存在すればそれを置き換えます。`edit`は既存のヘッダの置換を行う設定で、第3引数に正規表現、第4引数に置換後の文字列を指定します。</dd>

<dt>[AddLanguage ディレクティブ]</dt><dd>`AddLanguage ja .xhtml .html`</dd><dd>どの拡張子がどの言語に対応するか指定します。上記の指定では、拡張子が`.xhtml` `.html`であるファイルが、HTTP応答ヘッダで`Content-Language: ja`を送出するようになります。</dd>

<dt>[AddCharset ディレクティブ]</dt><dd>`AddCharset UTF-8 .xhtml .html .css .es .js .txt .json .csv .xml`</dd><dd>どの拡張子がどの文字コードに対応するか指定します。上記の指定では、拡張子が`.xhtml` `.html` `.css` `.es` `.txt` `.json` `.csv`であるファイルの応答ヘッダに、`Content-Type: application/xhtml+xml; charset=UTF-8`のように`charset`パラメータが付加されます。`.htm`や`.xht`等、これ以外の拡張子を持つテキストファイルが自分のサーバーに存在していれば、それらも追加しておきましょう。文字化けは[XSS]につながる可能性もあるので、設定漏れが無いように注意してください。</dd><dd>なお、`application/json` に `charset` パラメータは存在せず、例の通り記述した場合 `Content-Type: application/json; charset=UTF-8` のような不正なヘッダが出力されます。しかしながら、`Content-Type: application/json` を出力すると、ファイルの中身とブラウザの組み合わせによっては文字化けします。[^json]</dd>
</dl>

| HTTP応答ヘッダフィールド名  |   |
|-----------------------------|---|
| [content-type]              | `application/xhtml+xml`や`text/css`などのファイルの種類と、文字コードを示します。このヘッダが間違っていると、[XSS]の発生につながります。 |
| [content-language]          | HTML文書、XHTML文書 (以下、HTML) では、このヘッダや[lang属性]によって文章や単語の言語が決定されます。これらの指定が間違っていると、意図したフォントで表示されないといった弊害も起きます。なお、これらの値に指定する[言語タグ]について、`ja-JP` (言語と地域を`-`で繋いでいる) は正しい値ですが、`ja_JP` (言語と地域を`_`で繋いでいる) と書くのは誤りです。 |
| [link]                      | HTMLの[link要素]と同じ意味を持ちます。例えば、`link: </common/development>; rel=stylesheet`は、head要素内に記述した`<link href="/common/development" rel="stylesheet" />`と同じ効果があります。2013年11月現在、Firefoxのみ`rel=stylesheet`に対応しており、HTML以外のファイルを開いた場合にもスタイルシートが適用されます。`rel=icon`には対応していません。 |
| [x-content-type-options]    | Internet Explorerの[content-type応答ヘッダ][content-type]無視を防ぎます。[XSS]を防止するためにも、このヘッダは必ず送出しなければなりません。 |
| [x-ua-compatible]           | **本来はmeta要素で使う属性値で、HTTPヘッダとしては非標準です。** Internet Explorer 9[^ie9] の互換表示ボタンを消します。 |
| [strict-transport-security] | HTTPS接続を強制する [HTTP Strict Transport Security (HSTS)][strict-transport-security] を有効化します。この指定は、同一ドメインに対し `max-age` パラメータで指定した秒数だけ記憶されます。`includeSubDomains` を指定すると、サブドメインに対してもHTTPS接続を強制できます。次のような条件を満たせば、ブラウザが初めてアクセスするときもHTTPSを矯正する[HSTS Preload]が利用できます。<ul><li>http://〜 から https://〜 にリダイレクトしている</li><li>すべてのサブドメインにHTTPS接続できる</li><li>`max-age` パラメータの値が18週間 (10886400秒) 以上</li><li>`includeSubDomains` パラメータを指定している</li><li>非標準の `preload` パラメータを指定している</li></ul> [HSTS Preload List Submission]から[HSTS Preload]を利用するドメインを登録します。リストはGoogleが管理しています。 |
| [content-security-policy]<br>[x-frame-options] | (後述) |

[^3ds]: [NetFront Browser NX 1] \([ニンテンドー3DS用インターネットブラウザー]) は、XHTML文書において、属性値が空の属性を削除してしまう不具合がある。
[^ie9-xhtml]: [条件付きコメント]はHTML文書を Internet Explorer 9 で開いた場合のみ機能する。
              <ul><li>[asamuzaK.jp : IE9と条件コメント](http://asamuzak.jp/html/ua/315 "IE9と条件コメント 〜IE9の条件コメントの振る舞い〜")</li></ul>
[^json]: JSONファイルをブラウザで直接開いたとき、Firefox、Opera、Google Chromeで文字化けするJSONファイルがあることを確認 (2016年10月〜11月現在)。
[^ie9]: Internet Explorer 9 は Windows Vista でしか利用できないが、Windows Vista のセキュリティアップデートは2017年4月11日で終了する。
        <ul><li>[Internet Explorerサポートポリシー変更の重要なお知らせ — Microsoft]</li><li>[Windows デスクトップ製品のライフサイクル]</li></ul>

[SetEnvIfExpr ディレクティブ]: https://httpd.apache.org/docs/current/en/mod/mod_setenvif.html#setenvifexpr "Sets environment variables based on an ap_expr expression"
[SetEvnIf ディレクティブの日本語訳]: https://httpd.apache.org/docs/current/mod/mod_setenvif.html#setenvif "リクエストの属性に基づいて環境変数を設定する"
[Expressions in Apache HTTP Server]: https://httpd.apache.org/docs/current/expr.html "Historically, there are several syntax variants for expressions used to express a condition in the different modules of the Apache HTTP Server. There is some ongoing effort to only use a single variant, called ap_expr, for all configuration directives. This document describes the ap_expr expression parser."
[accept要求ヘッダ]: https://triple-underscore.github.io/RFC7231-ja.html#header.accept "UA は、[ 応答の媒体型として受容可能なもの ] を指定するために,  Accept ヘッダを利用できる。 Accept ヘッダは、[ 要請が, 欲される型からなる小さな集合に特に制限される ] ことを指示するときに利用できる — 例えば, インライン画像に対する要請など。"
[EZブラウザ]: https://ja.wikipedia.org/wiki/EZweb "EZweb（イージーウェブ）は、KDDI・沖縄セルラー電話の携帯電話ブランドauが提供している携帯電話IP接続サービスの名称である。"
[NetFront Browser NX 1]: https://ja.wikipedia.org/wiki/NetFront_Browser "NetFront Browser（ネットフロントブラウザ）とは、株式会社ACCESSが開発している組込機器用のウェブブラウザである。"
[ニンテンドー3DS用インターネットブラウザー]: https://ja.wikipedia.org/wiki/%E3%83%8B%E3%83%B3%E3%83%86%E3%83%B3%E3%83%89%E3%83%BC3DS#.E3.82.BD.E3.83.95.E3.83.88.E3.82.A2.E3.82.A4.E3.82.B3.E3.83.B3.E4.BB.A5.E5.A4.96.E3.81.AE.E5.86.85.E8.94.B5.E6.A9.9F.E8.83.BD "インターネットを接続して、Webサイトなどを見ることができる機能。"
[AddType ディレクティブ]: https://httpd.apache.org/docs/current/mod/mod_mime.html#addtype "ファイル名の拡張子を指定されたコンテントタイプにマップ"
[&lt;If&gt; セクション]: https://httpd.apache.org/docs/current/mod/core.html#if "実行時、リクエストが条件を満たした場合にのみ適用される ディレクティブを包含する"
[&lt;ElseIf&gt; セクション]: https://httpd.apache.org/docs/current/en/mod/core.html#elseif "Contains directives that apply only if a condition is satisfied by a request at runtime while the condition of a previous <If> or <ElseIf> section is not satisfied"
[&lt;Else&gt; セクション]: https://httpd.apache.org/docs/current/en/mod/core.html#else "Contains directives that apply only if the condition of a previous <If> or <ElseIf> section is not satisfied by a request at runtime"
[Include ディレクティブ]: https://httpd.apache.org/docs/current/mod/core.html#include "サーバ設定ファイル中から他の設定ファイルを取り込む"
[IncludeOptional ディレクティブ]: https://httpd.apache.org/docs/current/en/mod/core.html#includeoptional "Includes other configuration files from within the server configuration files"
[サーバールート]: https://httpd.apache.org/docs/current/mod/core.html#serverroot "インストールされたサーバのベースディレクトリ"
[ServerTokens ディレクティブ]: https://httpd.apache.org/docs/current/mod/core.html#servertokens "Server HTTP 応答ヘッダを設定する"
[Header ディレクティブ]: https://httpd.apache.org/docs/current/mod/mod_headers.html#header "HTTP 応答ヘッダの設定"
[2xxレスポンス]: https://triple-underscore.github.io/RFC7231-ja.html#status.2xx "クラス 2xx (Successful) の状態°コードは、クライアントの要請が, 成功裡に [ 受信され, 解され, 受容された ] ことを指示する。"
[AddLanguage ディレクティブ]: https://httpd.apache.org/docs/current/mod/mod_mime.html#addlanguage "ファイル名を指定された言語にマップ"
[AddCharset ディレクティブ]: https://httpd.apache.org/docs/current/mod/mod_mime.html#addcharset "ファイル名の拡張子を指定された文字セットにマップする"
[XSS]: https://ja.wikipedia.org/wiki/%E3%82%AF%E3%83%AD%E3%82%B9%E3%82%B5%E3%82%A4%E3%83%88%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0 "クロスサイトスクリプティング（英: cross site scripting）とは、ウェブページの部分をユーザからの入力をそのままエコーバック（おうむ返し）することによって生成しているアプリケーションのセキュリティ上の不備を利用して、サイト間を横断して悪意のあるスクリプトを注入する攻撃のことをいう。また経緯上、それを許してしまう脆弱性についても、このように呼ばれている。"
[content-type]: https://triple-underscore.github.io/RFC7231-ja.html#header.content-type "Content-Type ヘッダは、結び付けられている表現 — メッセージ意味論に従って決定された, [ メッセージペイロード内に同封された表現, または 選定された表現 ] — の, 媒体型を指示する。 指示された媒体型は、[ Content-Encoding により指示される内容符号法（たち）が復号された後 ] における, [ データ形式, および [ 受信されたメッセージ意味論の視野の中で, 受信者がそのデータをどう処理するものと意図されているか ] ] を定義する。"
[server]: https://triple-underscore.github.io/RFC7231-ja.html#header.server "Server ヘッダは、[ 生成元サーバが, 要請を取り扱うために利用しているソフトウェア ] についての情報を包含する"
[content-language]: https://triple-underscore.github.io/RFC7231-ja.html#header.content-language "Content-Language ヘッダは、表現に意図される視聴者の自然言語（たち）を述べる。 これは、[ 表現の中で利用される どの言語にも等価にならない ] 場合もあることに注意。"
[lang属性]: https://triple-underscore.github.io/HTML-dom-ja.html#the-lang-and-xml:lang-attributes "どの名前空間にも属さない lang 属性 — 以下、 素の lang 属性 と略記する — は、[ 要素の内容, および テキストを包含するような要素の属性 ] に対する第一言語を指定する。 その値は妥当な BCP 47 言語タグか, 空文字列でなければならない。 空文字列は、第一言語が未知であることを指示する。"
[言語タグ]: https://ja.wikipedia.org/wiki/IETF%E8%A8%80%E8%AA%9E%E3%82%BF%E3%82%B0 "IETF言語タグ（英語: IETF language tag）は、BCP 47（現在は RFC 5646 と RFC 4647）により定義される技術仕様である。これは HTTP、HTML、XML、PNG、のような多くの技術標準において使われている。"
[link]: //qiita.com/mpyw/items/203012d8b9e5386e6f0b "スタイルシートといえば<link>要素を使うのが一般的ですが, 実はRFC的にはHTTPヘッダにLink:を使うことも出来るようになっています. ところがブラウザの対応状況が意外にも芳しく無く…"
[link要素]: https://triple-underscore.github.io/HTML-metadata-ja.html#the-link-element "link 要素により、作者は, 自身の文書から他のリソースへのリンクをあてがえるようになる。"
[x-content-type-options]: https://triple-underscore.github.io/Fetch-ja.html#x-content-type-options-header "‘X-Content-Type-Options’ 応答ヘッダを利用して、[ 応答の ‘Content-Type’ ヘッダを, 要請の種別に対し検査する ] ことを要求できる。"
[x-ua-compatible]: https://triple-underscore.github.io/HTML-metadata-ja.html#attr-meta-http-equiv-x-ua-compatible "この pragma は、実施においては, Internet Explorer に対し より仕様に近くふるまうことを奨励する。"
[strict-transport-security]: https://developer.mozilla.org/docs/Web/Security/HTTP_Strict_Transport_Security "HTTP Strict Transport Security（しばしば HSTS と略されます）は、HTTP の代わりに HTTPS を用いて通信を行うよう、Web サイトからブラウザにに伝達するためのセキュリティ機能です。"
[HSTS Preload]: //qiita.com/takoratta/items/fb6b3486257eb7b9f12e#preloaded-hsts "HSTSを用いても、最初の接続にHTTPを用いる限り、完全なセキュリティは実現されない。これを解決するために、ChromeではPreloaded HSTS、すなわち最初からブラウザにHSTSを組み込めば良い。これはブラウザ本体にHSTSで接続するドメインのリストを持つことにより実現できる。"
[HSTS Preload List Submission]: https://hstspreload.appspot.com/ "This form is used to submit domains for inclusion in Chrome’s HTTP Strict Transport Security (HSTS) preload list. This is a list of sites that are hardcoded into Chrome as being HTTPS only."
[content-security-policy]: https://triple-underscore.github.io/CSP3-ja.html "この文書は、ある特定のページが どのリソースを fetch あるいは実行できるか, および セキュリティに関連する数々のポリシー決定について, ウェブ開発者が制御できる仕組みを定義する。"
[x-frame-options]: https://developer.mozilla.org/docs/Web/HTTP/X-Frame-Options "X-Frame-Options HTTP レスポンスヘッダは、ブラウザがページを <frame> または <iframe> の内部に表示することを許可するかを示すことができます。"
[条件付きコメント]: https://ja.wikipedia.org/wiki/%E6%9D%A1%E4%BB%B6%E4%BB%98%E3%81%8D%E3%82%B3%E3%83%A1%E3%83%B3%E3%83%88 "条件付きコメント（じょうけんつきコメント）とは、Microsoft Internet Explorerに対して、コードを渡したり隠したりするのに使用できるHTMLソースコード中にある条件付きのステートメントである。Internet Explorer 5で初めて登場し、バージョン9までサポートされた。"
[Internet Explorerサポートポリシー変更の重要なお知らせ — Microsoft]: https://www.microsoft.com/ja-jp/windows/lifecycle/iesupport/ "米国時間の 2014 年 8 月 7 日、マイクロソフトは Internet Explorer のサポートポリシーについて、重要なお知らせ 別ウィンドウが立ち上がりますを致しました。これにより、2016 年 1 月 12 日 (米国時間) を過ぎると、使用しているオペレーティング システムでサポートされる、最新バージョンの Internet Explorer だけが、技術サポートとセキュリティ アップデートを受けられることになります。米国時間の 2014 年 8 月 7 日、マイクロソフトは Internet Explorer のサポートポリシーについて、重要なお知らせ 別ウィンドウが立ち上がりますを致しました。これにより、2016 年 1 月 12 日 (米国時間) を過ぎると、使用しているオペレーティング システムでサポートされる、最新バージョンの Internet Explorer だけが、技術サポートとセキュリティ アップデートを受けられることになります。"
[Windows デスクトップ製品のライフサイクル]: https://www.microsoft.com/ja-jp/windows/lifecycle/ "Windows クライアント OS の製品サポートライフサイクル ポリシー更新について (2012 年 2 月)"

Content Security Policy
-----------------------
サイト製作者の意図しないスクリプトの実行などをブラウザ側でブロックし、[XSS]などを防ぎます。

Internet Explorer は対応していません。

以下に[content-security-policy応答ヘッダ][content-security-policy]の設定例を示します。

```apache:/etc/httpd/conf/httpd.conf
                        ##############
                        ## 以上省略 ##
                        ##############

# サーバー全体で共通のポリシー
Header always set content-security-policy "default-src 'none'; disown-opener; frame-ancestors 'none'; style-src 'self'; img-src 'self'; upgrade-insecure-requests; report-uri [レポートの送信先URL]"
<If "%{HTTP_USER_AGENT} -strmatch '*Trident/*'">
    # Internet Explorer で frame-ancestors 'none' を機能させる
    Header always set x-frame-options DENY
</If>

<DirectoryMatch ^/var/www/html/index$>
    # トップページへのSVG画像の埋め込み
    Header always edit content-security-policy $ "; object-src 'self'; frame-src 'self'"
</DirectoryMatch>
<DirectoryMatch ^/var/www/html/chat/index$>
    # チャットのstyle属性、スクリプト、EventSource、XMLHttpRequest、およびベル音
    Header always edit content-security-policy "style-src 'self'" "style-src 'self' 'unsafe-inline'; script-src 'self'; connect-src 'self'; media-src 'self'"
</DirectoryMatch>
<Directory /var/www/html/link>
    # リンク集のバナー
    Header always edit content-security-policy "img-src 'self'" "img-src 'self' example.com example.jp example.co.jp example.ne.jp"
</Directory>
<Directory /var/www/html/phpMyAdmin>
    # phpMyAdmin
    Header always edit content-security-policy "style-src 'self'" "style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; connect-src 'self'"
</Directory>
<DirectoryMatch ^/var/www/html/phpinfo$>
    # phpinfo()関数の結果を表示するページ
    Header always edit content-security-policy "style-src 'self'" "style-src 'self' 'unsafe-inline'"
    Header always edit content-security-policy "img-src 'self'" "img-src 'self' data:"
</DirectoryMatch>
```

以上のコード例のcontent-security-policy応答ヘッダ値は、以下のような意味になります (`disown-opener` `frame-ancestors` `upgrade-insecure-requests` `report-to` 省略)。

&#x20;
<dl><dt>`default-src 'none'; style-src 'self'; img-src 'self'`</dt><dd>サーバー全体に適用するポリシー。同一生成元のスタイルシートと同一生成元の画像のみ許可している。</dd>

<dt>`default-src 'none'; style-src 'self'; img-src 'self'; object-src 'self'; frame-src 'self'`</dt><dd>object要素でSVG画像を埋め込む場合。Firefoxは<i>object</i>、OperaとGoogle Chromeは<i>frame</i>と認識するため、両方のディレクティブで許可している。</dd>

<dt>`default-src 'none'; style-src 'self' 'unsafe-inline'; script-src 'self'; connect-src 'self'; media-src 'self'; img-src 'self'`</dt><dd>同一生成元のスタイルシート、style要素とstyle属性による指定を許可。同一生成元のスクリプトを許可。XMLHttpRequestやEventSourceからの同一生成元に対するアクセスを許可。audio要素とvideo要素で同一生成元のファイルを許可。同一生成元の画像を許可。</dd>

<dt>`default-src 'none'; style-src 'self'; img-src 'self' example.com example.jp example.co.jp example.ne.jp`</dt><dd>リンク集に適用するポリシー。同一生成元と直リンクしているバナーの生成元の画像を許可している。</dd>

<dt>`default-src 'none'; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; connect-src 'self'; img-src 'self'`</dt><dd>[phpMyAdmin]に適用するポリシー。phpMyAdminではインラインスクリプトやeval関数が使用されているため、Content Security Policyが有効に活用できない。</dd>

<dt>`default-src 'none'; style-src 'self' 'unsafe-inline'; img-src 'self' data:`</dt><dd>[PHPのphpinfo関数]の実行結果に適用するポリシー。同一生成元のスタイルシート、style要素とstyle属性による指定を許可。同一生成元と[dataスキーム]の画像を許可。</dd>

[phpMyAdmin]: https://ja.wikipedia.org/wiki/PhpMyAdmin "phpMyAdmin(ピーエイチピーマイアドミン)はMySQLサーバーをウェブブラウザで管理するためのデータベース接続クライアントツールで、PHPで実装されている。 phpMyAdminを用いることで、SQL文を記述することなく、MySQLのデータベースに対して様々な操作が行える。 また、ユーザが任意のSQL文を記述して実行することもできる。"
[PHPのphpinfo関数]: https://secure.php.net/manual/function.phpinfo.php "PHP の設定情報を出力する"
[dataスキーム]: https://ja.wikipedia.org/wiki/Data_URI_scheme "データURIスキーム（英語: data URI scheme）とは外部データ無しにウェブページにデータを埋めこむためのURIスキームである。例えば、通常画像データはHTMLやCSSに外部リンクとして記述され、ブラウザで表示する際には複数のHTTPリクエストが発生する。これは画像データが小さい場合などには非効率的である。データURIスキームを使用すれば内部データとして画像を埋め込むことができるので1つのHTTPリクエストで済み、効率化できる。RFC 2397で定義されている。"

### 主なディレクティブ (指令)

| ディレクティブ名              | 構文、作用 |
|-------------------------------|------------|
| [`default-src`]               | 以下のディレクティブが省略されていたときの既定値を指定します。<ul><li>`child-src`</li><li>`connect-src`</li><li>`font-src`</li><li>`img-src`</li><li>`media-src`</li><li>`object-src`</li><li>`script-src`</li><li>`style-src`</ul> これらのディレクティブでは、次のような値を空白区切りで指定します。<ul><li>`'none'` (何も許可しない)</li><li>`'self'` (生成元[^origin] が同じものを許可)</li><li>`https://maxcdn.bootstrapcdn.com/bootstrap/` ([ホストソース式])</li></ul> 以上のような値は[ソースリスト]と呼ばれます。 |
| [`style-src`]                 | スタイルシートの許可。`'unsafe-inline'`を指定すると、あらゆるstyle要素、style属性が許可されますが、[完全に避けるのが最善]とされています。style要素に関しては、[hash-source]を使えば決まった中身のstyle要素のみ許可できますが、2016年11月現在Microsoft Edgeが未対応です。[`'unsafe-hashed-attributes'`]を使えばstyle属性値も[hash-source]により制御できますが、2016年11月現在まだ仕様が不安定です。 |
| [`img-src`]                   | 画像の許可。 |
| [`media-src`]                 | 音声、動画、字幕の許可。 |
| [`script-src`]                | スクリプトの許可。`'unsafe-inline'` 周りの事情は、上記 `style-src` と大体同じです。[`'strict-dynamic'`] を指定すれば、(ライブラリなどによって) 後から挿入されたscript要素はブロックされなくなりますが、2016年11月現在ブラウザのサポートが進んでいません。 |
| [`connect-src`]               | 次のようなAPIにおける接続先の許可。<ul><li>[XMLHttpRquest]</li><li>[EventSource]</li><li>[WebSocket]</li><li>[Window#fetch()]</li><li>[a要素のping属性]</li><li>[Navigator#sendBeacon()]</li></ul> |
| [`frame-src`]                 | iframe要素などで埋め込むページの許可。[^frame] |
| [`font-src`]                  | フォントの許可。 |
| [`object-src`]                | SWFファイルなどのプラグイン内容の許可。 |
| [`plugin-types`]              | 許可するプラグインのMIME型を指定します。SWFファイルのMIME型は[application/vnd.adobe.flash-movie]ですがAdobe Flash Playerが対応していないので、同ファイルを埋め込む場合はとりあえず `plugin-types application/vnd.adobe.flash-movie application/x-shockwave-flash` のように指定しておきます。**このディレクティブを指定した場合、object要素などのtype属性が必須となります。**[^object] |
| [`disown-opener`]             | 移動先の[Window#opener]を `null` にします。フィッシング詐欺の手法である[Tabnabbing]対策になりますが、2016年11月現在まだ仕様が不安定です。a要素の場合は `rel=noopener` を付加することで、該当のリンクに対しては同様の効果を持たせられますが、2016年11月現在OperaとGoogle Chromeしか対応していません。そこで、`rel="noopener noreferrer"` と併記する必要があります。[^noopener] |
| [`frame-ancestors`]           | 現在のページを埋め込める先祖ウィンドウのURLを指定します。[クリックジャッキング]対策などに役立ちます。Internet Explorer は CSP 自体に対応していませんが、[x-frame-options応答ヘッダ][x-frame-options]で似たような対策が可能です。たとえば `frame-ancestors 'none'` に対応する値は `DENY` です。 |
| [`report-uri`]                | CSP違反が発生したときの報告先。[report-uri.ioというサービスが便利]です。 |
| [`upgrade-insecure-requests`] | [混在コンテンツ]になりそうな画像などに対して、自動的にセキュアなURLから取得します。たとえば `<link src="http://example.jp/lib.css" rel="stylesheet" />` のような記述があれば、`http://example.jp/lib.css` ではなく `https://example.jp/lib.css` にアクセスします。2016年11月現在、Firefox、Opera、Google Chromeが対応しており、Safariの開発版には実装されているようです。 |

[^origin]: `https`などの「スキーム」、`example.com`などの「ホスト」、「ポート番号」の組み合わせ。
[^frame]: `frame-src` は、[CSP2で`connect-src`に置き換える形で非推奨にされた]が、[CSP3で`connect-src`が`frame-src` `worker-src`に分割される形で非推奨ではなくなった]。
[^object]: `plugin-types` が指定されていない場合でも、Opera、Google Chromeはtype属性がないobject要素に `child-src` を適用しようとするため、どちらにしても必須である。
[^noopener]: [リンクのへの rel=noopener 付与による Tabnabbing 対策 | blog.jxck.io][Tabnabbing]

[`default-src`]: https://triple-underscore.github.io/CSP3-ja.html#directive-default-src "default-src 指令は、他の fetch 指令に対するフォールバックとして働く。"
[ホストソース式]: https://triple-underscore.github.io/CSP3-ja.html#grammardef-host-source
[ソースリスト]: https://triple-underscore.github.io/CSP3-ja.html#framework-directive-source-list "各種 指令のうち, 多くのものは、 ソースリスト （ serialized-source-list ）をその値にとる。"
[`style-src`]: https://triple-underscore.github.io/CSP3-ja.html#directive-style-src "style-src 指令は、[ どの所在からのスタイルを文書に適用してよいかどうか ] を制約する。"
[完全に避けるのが最善]: https://triple-underscore.github.io/CSP3-ja.html#csp-directives "CSP 指令 | Content Security Policy Level 3"
[hash-source]: https://triple-underscore.github.io/CSP3-ja.html#grammardef-hash-source
[`'unsafe-hashed-attributes'`]: https://triple-underscore.github.io/CSP3-ja.html#unsafe-hashed-attributes-usage "[ 旧来のサイト / 旧来の依存関係を伴うサイト ] では、イベントハンドラをまるごと外部化するのが困難なこともある。 これらのサイトは、その種のハンドラを 'unsafe-inline' で許容して可能化することもできるが、それは, 多数のリスクを抱える諸刃の剣である（また、ナンスやハッシュと共には利用できない）。ソース式 'unsafe-hashed-attributes' は、そのような状況下で, [ ハッシュを介して特定のハンドラを可能化できる ] ようにすることで、開発者が, CSP をより単純かつ安全に配備できるようにすることを目指している。"
[`img-src`]: https://triple-underscore.github.io/CSP3-ja.html#directive-img-src "img-src 指令は、[ どの URL から画像リソースを読み込んでよいか ] を制約する。"
[`media-src`]: https://triple-underscore.github.io/CSP3-ja.html#directive-media-src "media-src 指令は、[ どの URL から [ 動画, 音声 および 結び付けられているテキストトラック ] リソースを読み込んでよいか ] を制約する。"
[`script-src`]: https://triple-underscore.github.io/CSP3-ja.html#directive-script-src "script-src 指令は、[ どの所在からのスクリプトを実行してよいか ] を制約する。 これには、[ script 要素の中に直接的に読み込まれる URL ] のみならず, [ インラインスクリプトブロックや XSLT スタイルシートの様な, スクリプト実行を誘発し得るもの ] も含まれる。"
[`'strict-dynamic'`]: https://triple-underscore.github.io/CSP3-ja.html#strict-dynamic-usage "'strict-dynamic' ソース式は、既存のアプリが, 自身が直接的に読み込むスクリプトについては自信があるが, 前面に読み込まれるリソースのリスト を適度に提供する機能については自信がない場合に、 CSP をより単純に配備できるようにすることを目指している。"
[`connect-src`]: https://triple-underscore.github.io/CSP3-ja.html#directive-connect-src "connect-src 指令は、[ スクリプトインタフェースを利用して読み込める URL ] を制約する。"
[XMLHttpRquest]: https://triple-underscore.github.io/XHR-ja.html "XMLHttpRequest は、クライアントとサーバ間のデータ転送のための, クライアント側のスクリプト機能を提供する API を定義する。"
[EventSource]: https://developer.mozilla.org/docs/Web/API/EventSource "EventSource インターフェイスは、Server‐sent events を受け取るために使用します。HTTP でサーバと接続して、接続を切断せずに text/event-stream 形式でイベントを受信します。"
[WebSocket]: https://triple-underscore.github.io/WebSocket-ja.html "この仕様は、ウェブアプリがサーバ側プロセスとの双方向通信を可能化するための, WebSocket インタフェースを導入する。"
[Window#fetch()]: https://triple-underscore.github.io/Fetch-ja.html#fetch-api "fetch() メソッドは、リソースを fetch するための, 比較的 低レベルの API である。 XMLHttpRequest より少しばかり基盤的部分を対象にする"
[a要素のping属性]: https://triple-underscore.github.io/HTML-links-ja.html#ping "ping する URL を与える。"
[Navigator#sendBeacon()]: https://triple-underscore.github.io/beacon-ja.html "この仕様は、[ データの送達を, 非同期的かつ他を阻まない（ non-blocking ）ようにスケジュールする ] ためにサイト開発者が利用できるインタフェースを定義する。 それは、他の時間に厳しい演算との資源競合を最小限に抑えつつ, そのような要請が処理され, 宛先へ送達されることを確保する。"
[`frame-src`]: https://triple-underscore.github.io/CSP3-ja.html#directive-frame-src "frame-src 指令は、[ どの URL を入れ子の閲覧文脈内に読み込んでよいか ] を制約する。"
[`font-src`]: https://triple-underscore.github.io/CSP3-ja.html#directive-font-src "font-src 指令は、[ どの URL からフォントリソースを読み込んでよいか ] を制約する。"
[`object-src`]: https://triple-underscore.github.io/CSP3-ja.html#directive-object-src "object-src 指令は、[ どの URL からプラグイン内容を読み込んでよいか ] を制約する。"
[`plugin-types`]: https://triple-underscore.github.io/CSP3-ja.html#directive-plugin-types "plugin-types 指令は、読み込めるリソースの型を制限することにより, 文書の中に埋め込めるプラグインの集合を制約する。"
[application/vnd.adobe.flash-movie]: https://www.iana.org/assignments/media-types/application/vnd.adobe.flash-movie
[`disown-opener`]: https://triple-underscore.github.io/CSP3-ja.html#directive-disown-opener "disown-opener 指令は、[ ナビゲートされたリソースの onener を null 化する ] ことを確保する。"
[Window#opener]: https://triple-underscore.github.io/browsers-ja.html#dom-opener
[Tabnabbing]: https://blog.jxck.io/entries/2016-06-12/noopener.html "本サイト以下全ての target=_blank 付きのリンクに rel="noopener noreferrer" の付与を実施した。このプロパティの意味と、これが無い場合のフィッシング詐欺攻撃の可能性について解説する。"
[`frame-ancestors`]: https://triple-underscore.github.io/CSP3-ja.html#directive-frame-ancestors "frame-ancestors 指令は、[ frame / iframe / object / embed / applet ] 要素を利用して埋め込めるリソースの URL を制約する。 この指令を利用すれば、敵対的になり得る文脈の中にリソースが埋め込まれるリスクを避けることで、多くの UI Redressing 【 UI の着せ替え】 攻撃避けることができる。"
[クリックジャッキング]: https://ja.wikipedia.org/wiki/%E3%82%AF%E3%83%AA%E3%83%83%E3%82%AF%E3%82%B8%E3%83%A3%E3%83%83%E3%82%AD%E3%83%B3%E3%82%B0 "クリックジャッキング（クリックジャック攻撃、Clickjacking、User Interface redress attack、UI redress attack、UI redressing）は、ウェブページの利用者に対し悪意をもって使用される技術の一種で、リンクやボタンなどの要素を隠蔽・偽装してクリックを誘い、利用者の意図しない動作をさせようとする手法である。"
[`report-uri`]: https://triple-underscore.github.io/CSP3-ja.html#directive-report-uri "report-uri 指令は、報告先 — ある特定のふるまいが防止されたとき, 違反報告の送信先になるネットワーク端点 — の集合を定義する。"
[report-uri.ioというサービスが便利]: https://blog.jxck.io/entries/2016-03-30/content-security-policy.html#report-uri.io "このレポートの収集と解析を行うサービスとして、 report-uri.io というサービスが最近登場した。"
[`upgrade-insecure-requests`]: https://triple-underscore.github.io/webappsec-upgrade-insecure-requests-ja.html#delivery "サーバは、[ upgrade-insecure-requests 指令を包含する Content-Security-Policy ヘッダ ] を送信することにより, [ ある特定の被保護リソースに対する非セキュア要請 ] を昇格するよう, UA に指図してよい。"
[混在コンテンツ]: https://developer.mozilla.org/docs/Security/%E6%B7%B7%E5%9C%A8%E3%82%B3%E3%83%B3%E3%83%86%E3%83%B3%E3%83%84 "もし HTTPS のページの中に通常の平文の HTTP で送られてくるコンテンツが含まれる場合、その接続は部分的に暗号化されたものにすぎなくなります。すなわち、暗号化されていないコンテンツは盗聴可能であり、中間者攻撃の攻撃者によってコンテンツの中身は操作可能となり、もはや接続は保護されません。そのような web ページは「混在コンテンツ」を含むページと呼ばれます。"
[CSP2で`connect-src`に置き換える形で非推奨にされた]: https://triple-underscore.github.io/CSP-ja.html#changes-from-level-1 "child-src は、 frame-src を非推奨にして, それを置き換える — それは、[ 被保護リソースが フレームを埋め込む / worker を読み込む ] 機能を制御する。"
[CSP3で`connect-src`が`frame-src` `worker-src`に分割される形で非推奨ではなくなった]: https://triple-underscore.github.io/CSP3-ja.html#changes-from-level-2 "CSP Level 2 で非推奨にされた frame-src 指令は, 非推奨でなくなり、 worker-src が追加された。 両者とも無い場合は child-src に先送りする（それも無い場合は default-src に先送りする）。"

一つのApacheで複数のドメインを扱う&nbsp;(仮想ホスト)
====================================================
```apache:/etc/httpd/conf.modules.d/00-base.conf
                        ##############
                        ## 以上省略 ##
                        ##############

#LoadModule request_module modules/mod_request.so
#LoadModule sed_module modules/mod_sed.so
#LoadModule speling_module modules/mod_speling.so
LoadModule macro_module modules/mod_macro.so
# ↑ファイルの末尾にこの行を追記
```

`/etc/httpd/conf/httpd.conf`に`#LoadModule macro_module lib64/httpd/modules/mod_macro.so`のような行があれば、`/etc/httpd/conf.modules.d/00-base.conf`に追記する代わりにそちらのコメントアウトを外してください。

&#x20;
<dl>
<dt>[LoadModule ディレクティブ]</dt><dd>`LoadModule macro_module modules/mod_macro.so`</dd><dd>指定した動的共有モジュールをApache起動時に読み込みます。</dd>
</dl>

```apache:/etc/httpd/conf.d/ssl.conf
                        ##############
                        ## 以上省略 ##
                        ##############

##
## SSL Virtual Host Context
##

#<VirtualHost _default_:443>
## ↑この行をコメントアウト ##

# General setup for the virtual host, inherited from global configuration
#DocumentRoot "/var/www/html"
#ServerName www.example.com:443

                        ##############
                        ##   中略   ##
                        ##############

#   Per-Server Logging:
#   The home of a custom SSL log file. Use this when you want a
#   compact non-error SSL logfile on a virtual host basis.
CustomLog logs/ssl_request_log \
          "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"

# TLSの基本設定を読み込み
#Include /etc/letsencrypt/options-ssl-apache.conf
## ↑この行をコメントアウト ##

#ServerName example.jp
#ServerAlias sub1.example.jp sub2.example.jp
## ↑この2行をコメントアウト ##
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
SSLUseStapling on
SSLCertificateChainFile /etc/letsencrypt/live/example.jp/chain.pem
#</VirtualHost>                       
## ↑この行をコメントアウト ##           

<IfModule mod_ssl.c>
SSLStaplingCache shmcb:/var/run/apache2/stapling_cache(128000)
</IfModule>
```

```apache:/etc/httpd/conf.d/vhosts.conf
# すべての仮想ホストから読み込まれるファイル
AliasMatch ^/((?:common|polyfill)/.+) /var/www/common/$1
<DirectoryMatch ^/var/www/common/(?:common|polyfill)/.+$>
    Require all granted
</DirectoryMatch>

# すべての仮想ホストで共通の設定
<Macro CommonHost $subdomain $directory>
    ServerName $subdomainexample.jp
    Include /etc/letsencrypt/options-ssl-apache.conf
    DocumentRoot /var/www/$directory
    <Directory /var/www/$directory>
        Require all granted
    </Directory>
</Macro>

<VirtualHost *:80>
    # 80番ポートへのアクセス
    ServerName default-virtual-host.invalid

    # 正規のサブドメインに一致するなら、https://%{HTTP_HOST}/ にリダイレクト
    RewriteEngine on
    RewriteCond %{HTTP_HOST} ^(?:sub1|sub2).example.jp$
    RewriteRule .* https://%{HTTP_HOST}$0 [redirect=permanent,last]

    # それ以外の場合は、https://example.jp/ にリダイレクト
    RewriteRule .* https://example.jp$0 [redirect=permanent,last]
</VirtualHost>

<VirtualHost *:443>
    Use CommonHost " " html
    # アップロードされたデータ
    Alias /oekaki/data /var/www/share/html/uploader/data
    <Directory /var/www/share/html/uploader/data>
        Require all granted
    </Directory>
</VirtualHost>

<VirtualHost *:443>
    Use CommonHost sub1. sub1
    AliasMatch ^/((?:index|style)(?:\.[^/]+)?)$ /var/www/share/sub1/core/$1
    <Directory /var/www/share/sub1/core>
        Require all granted
    </Directory>
</VirtualHost>

<VirtualHost *:443>
    Use CommonHost sub2. sub2
</VirtualHost>
```

`/etc/httpd/conf/httpd.conf`に`IncludeOptional conf.d/*.conf`のような行が無ければ、追記しておきます。

```apache:/etc/httpd/conf/httpd.conf
                        ##############
                        ## 以上省略 ##
                        ##############

<IfModule log_config_module>
    #
    # The following directives define some format nicknames for use with
    # a CustomLog directive (see below).
    #
    LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
    LogFormat "%h %l %u %t \"%r\" %>s %b" common

    <IfModule logio_module>
      # You need to enable mod_logio.c to use %I and %O
      LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio
    </IfModule>

    #
    # The location and format of the access logfile (Common Logfile Format).
    # If you do not define any access logfiles within a <VirtualHost>
    # container, they will be logged here.  Contrariwise, if you *do*
    # define per-<VirtualHost> access logfiles, transactions will be
    # logged therein and *not* in this file.
    #
    #CustomLog "logs/access_log" common

    #
    # If you prefer a logfile with access, agent, and referer information
    # (Combined Logfile Format) you can use the following directive.
    #
    #CustomLog "logs/access_log" combined
    ## ↑コメントアウトする ##
    CustomLog "logs/access_log" "%v %h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\""
    ## ↑この行を追加 ##
</IfModule>

                        ##############
                        ## 以下省略 ##
                        ##############
```

&#x20;
<dl><dt>[Alias ディレクティブ]</dt><dd>第1引数で指定したURLを、第2引数で指定した<i>ファイルシステムのパス絶対URL</i>と結び付けます。URLは[Redirect ディレクティブ]と同じく前方一致で、`Alias /foo /var/www/foo/bar`と記述すると、https://example.com/foo/test が`/var/www/foo/bar/test`と結び付けられます。</dd>

<dt>[AliasMatch ディレクティブ]</dt><dd>第1引数に正規表現を指定すること以外は、[Alias ディレクティブ]と同じです。正規表現内の後方参照は、第3引数で`$1`などと数字に`$`を前置して利用できます。`AliasMatch ^/((?:common|polyfill)/.*) /var/www/common/$1`は`Alias /common/ /var/www/common/common/` `Alias /polyfill/ /var/www/common/polyfill/`と同じ意味になります。</dd>

<dt>[&lt;DirectoryMatch&gt; セクション]</dt><dd>`<DirectoryMatch ^/var/www/common/(?:common|polyfill)/.+$>`〜`</DirectoryMatch>`</dd><dd>ディレクティブを適用する **ファイルを** 正規表現で指定します。[&lt;Directory&gt; セクション]と同じく<i>ファイルシステムのパス絶対URL</i>で指定します。[&lt;Directory&gt; セクション]よりは[&lt;FilesMatch&gt; セクション]に近く、[AllowOverride ディレクティブ]が使えず、[RewriteBase ディレクティブ]もエラーは出ませんが正しく機能しません。どのOSであっても、<i>パス区分</i>を区切る文字は必ず`/`であるものとして正規表現を記述します。</dd>

<dt>[DocumentRoot ディレクティブ]</dt><dd><i>ファイルシステムのパス絶対URL</i>、またはサーバールートからの相対パスでドキュメントルートを設定します。例えば、`ServerName example.jp`と`DocumentRoot /var/www/html`が指定されていた場合、https://example.jp/foo/bar.html にアクセスされたときに`/var/www/html/foo/bar.html`を返します。</dd>

<dt>[&lt;VirtualHost&gt; セクション]</dt><dd>`<VirtualHost *:443>`〜`</VirtualHost>`</dd><dd>サーバーのIPアドレスとポート番号の組み合わせごとにディレクティブを適用します。IPアドレスとポート番号の間には`:`を挟み、その組は第2引数以降で複数指定することもできます。ポート番号を省略した場合、どのポート番号にも一致するようになります。ポート番号を省略したセクションより、ポート番号が省略されていないセクションの方が優先されます。</dd><dd>値の同じ[&lt;VirtualHost&gt; セクション]を複数作成し、それぞれに[ServerName ディレクティブ]でドメインを設定すれば、ドキュメントルートなどをドメインごとに設定できます ([名前ベースのバーチャルホスト])。</dd><dd>サーバーにアクセスしたときのドメインが、どの[ServerName ディレクティブ]の設定とも一致しない場合は、IPアドレスとポート番号の条件が一致する[&lt;VirtualHost&gt; セクション]の中で最初に記述したもの (<i>デフォルトの仮想ホスト</i>) が適用されます。<i>デフォルトの仮想ホスト</i>の選択も、ポート番号が省略されていないセクションの方が優先されます。</dd>

<dt>[CustomLog ディレクティブ]</dt><dd>`"CustomLog logs/access_log" "%v %h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\""`</dd><dd>第1引数に保存先、第2引数に書式を指定します。</dd><dd>最初に記述されていた `CustomLog "logs/access_log" combined` は、直前の `LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined` から `CustomLog "logs/access_log" "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\""` と展開できます。つまり記述例で書き直した書式は、最初に記述されていた書式の先頭に `%v` を追加したものです。`%v` は、サーバーのホスト名に置き換えられます。</dd>

<dt>[&lt;Macro&gt; セクション]　\(リンク先英語)</dt><dd>`<Macro CommonHost $subdomain $directory>`〜`</Macro>`</dd><dd><i>設定ファイルマクロ</i>を定義します。<i>設定ファイルマクロ</i>は、複数の箇所で同じ設定が必要な場合に使います。プログラミングにおける関数宣言のように、第1引数にマクロ名、第2引数以降に仮引数を記述します。引数の数の違いによる多重定義はできません。</dd>

<dt>[Use ディレクティブ]　\(リンク先英語)</dt><dd>定義しておいた<i>設定ファイルマクロ</i>を使用します。プログラミングにおける関数呼び出しのように、第1引数にマクロ名、第2引数以降に実引数を記述します。`Use ExampleMacro ""`のように、実引数に空文字列を指定すると、警告が発生します。</dd></dl>

例えば上記コードの最後の[&lt;VirtualHost&gt; セクション]は、<i>設定ファイルマクロ</i>によって以下のように置換されます。

```apache:置換前
<VirtualHost *:80>
    Use CommonHost sub2. sub2
</VirtualHost>
```

```apache:置換後
<VirtualHost *:80>
    ServerName sub2.example.jp
    DocumentRoot /var/www/sub2
    <Directory /var/www/sub2>
        Require all granted
    </Directory>
</VirtualHost>
```

[LoadModule ディレクティブ]: https://httpd.apache.org/docs/current/mod/mod_so.html#loadmodule "オブジェクトファイルやライブラリをリンクし、使用モジュールの リストに追加する"
[Alias ディレクティブ]: https://httpd.apache.org/docs/current/mod/mod_alias.html#alias "URL をファイルシステムの位置にマップする"
[AliasMatch ディレクティブ]: https://httpd.apache.org/docs/current/mod/mod_alias.html#aliasmatch "正規表現を使って URL をファイルシステムの位置にマップする"
[&lt;DirectoryMatch&gt; セクション]: https://httpd.apache.org/docs/current/mod/core.html#directorymatch "正規表現にマッチするファイルシステムのディレクトリと サブディレクトリとのみに適用されるディレクティブを囲む"
[&lt;FilesMatch&gt; セクション]: https://httpd.apache.org/docs/current/mod/core.html#filesmatch "正規表現にマッチするファイル名に適用される ディレクティブを囲む"
[AllowOverride ディレクティブ]: https://httpd.apache.org/docs/current/mod/core.html#allowoverride ".htaccess で許可されるディレクティブの種類"
[DocumentRoot ディレクティブ]: https://httpd.apache.org/docs/current/mod/core.html#documentroot "ウェブから見えるメインのドキュメントツリーになる ディレクトリ"
[&lt;VirtualHost&gt; セクション]: https://httpd.apache.org/docs/current/mod/core.html#virtualhost "特定のホスト名や IP アドレスのみに適用されるディレクティブを 囲む"
[名前ベースのバーチャルホスト]: https://httpd.apache.org/docs/current/vhosts/name-based.html "IP ベースのバーチャルホストでは、応答する バーチャルホストへのコネクションを決定するために IP アドレスを使用します。ですから、それぞれのホストに個々に IP アドレスが必要になります。これに対して名前ベースのバーチャルホストでは、 クライアントが HTTP ヘッダの一部としてホスト名を告げる、 ということに依存します。この技術で同一 IP アドレスを異なる多数のホストで共有しています。"
[CustomLog ディレクティブ]: https://httpd.apache.org/docs/current/mod/mod_log_config.html#customlog "ログファイルの名前と書式を設定する"
[&lt;Macro&gt; セクション]: https://httpd.apache.org/docs/current/mod/mod_macro.html#macro "Define a configuration file macro"
[Use ディレクティブ]: https://httpd.apache.org/docs/current/mod/mod_macro.html#use "Use a macro"

URLの末尾に拡張子を表示しない
=============================
ここでは[RewriteMap ディレクティブ]を利用していますが、[mod_negotiationモジュール]や[RewriteCond ディレクティブ]を利用して実現できる場合もあります。

```apache:/etc/httpd/conf.d/vhosts.conf
# Virtual Hosts
#
# If you want to maintain multiple domains/hostnames on your
# machine you can setup VirtualHost containers for them. Most configurations
# use only name-based virtual hosts so the server doesn't need to worry about
# IP addresses. This is indicated by the asterisks in the directives below.
#
# Please see the documentation at 
# <URL:https://httpd.apache.org/docs/2.4/vhosts/>
# for further details before you try to setup virtual hosts.
#
# You may use the command line option '-S' to verify your virtual host
# configuration.

## ↓ここから追記 ##
RewriteEngine on

# rewriteモジュールに関するログをすべて記録する
#LogLevel alert rewrite:trace8

# 標準入力の「フルパス,プレフィックスを取り除いたパス」から拡張子付きのファイルを探し、最初に見つかったファイルのパスからプレフィックスを取り除いて返す
RewriteMap adjust-extension "prg:/usr/bin/perl -e '$| = 1; while (<STDIN>) { chomp($_); my @params = split(/,/, $_); my $path; if ($#params == 1) { ($path) = glob(@params[0] . \\'.*\\'); if ($path) { $path = substr($path, length(@params[0]) - length(@params[1])); } } print(($path || \\'NULL\\') . \"\\\\x0A\"); }'"

<Directory /var/www>
    # 拡張子無しのURLでアクセスできるようにする
    RewriteOptions Inherit
    RewriteRule ^([^.]+)(?<!/)$ ${adjust-extension:%{REQUEST_FILENAME},$1|$1}
</Directory>

<If "unescape(%{THE_REQUEST}) =~ /\\..*\\s/">
    # 要求行の最後の空白より前にピリオドが含まれていれば
    # Favicon、robots.txt、phpMyAdminディレクトリを除く拡張子付きのURLを拡張子無しのURLにリダイレクト
    RedirectMatch permanent ^(/(?!(?:favicon\.ico|robots\.txt)$|phpMyAdmin/)[^.]+)\. $1
</If>
## ↑ここまで追記 ##

# すべての仮想ホストから読み込まれるファイル
AliasMatch ^/((?:common|polyfill)/.+) /var/www/common/$1
<Directory /var/www/common>
    RewriteBase /
</Directory>
## ↑この<Directory>セクションを追加 ##
<DirectoryMatch ^/var/www/common/(?:common|polyfill)/.+$>
    Require all granted
</DirectoryMatch>

# すべての仮想ホストで共通の設定
<Macro CommonHost $subdomain $directory>
    ServerName $subdomainexample.jp
    Include /etc/letsencrypt/options-ssl-apache.conf
    DocumentRoot /var/www/$directory
    RewriteOptions Inherit
    ## ↑この行を追加 ##
    <Directory /var/www/$directory>
        Require all granted
    </Directory>
</Macro>

<VirtualHost *:80>
    # 80番ポートへのアクセス
    ServerName default-virtual-host.invalid

    # 正規のサブドメインに一致するなら、https://%{HTTP_HOST}/ にリダイレクト
    RewriteEngine on
    RewriteCond %{HTTP_HOST} ^(?:sub1|sub2).example.jp$
    RewriteRule .* https://%{HTTP_HOST}$0 [redirect=permanent,last]

    # それ以外の場合は、https://example.jp/ にリダイレクト
    RewriteRule .* https://example.jp$0 [redirect=permanent,last]
</VirtualHost>

<VirtualHost *:443>
    Use " " html
    # アップロードされたデータ
    Alias /oekaki/data /var/www/share/html/uploader/data
    <Directory /var/www/share/html/uploader/data>
        RewriteBase /uploader/data/
        ## ↑この行を追加 ##
        Require all granted
    </Directory>
</VirtualHost>

<VirtualHost *:443>
    Use sub1. sub1
    AliasMatch ^/((?:index|style)(?:\.[^/]+)?)$ /var/www/share/sub1/core/$1
    <Directory /var/www/share/sub1/core>
        RewriteBase /
        ## ↑この行を追加 ##
        Require all granted
    </Directory>
</VirtualHost>

<VirtualHost *:443>
    Use sub2. sub2
</VirtualHost>
```

`/etc/httpd/conf/httpd.conf`に`#LoadModule rewrite_module lib64/httpd/modules/mod_rewrite.so`のような行があれば、コメントアウトを外しておきます。

&#x20;
<dl><dt>[RewriteEngine ディレクティブ]　\(リンク先英語)</dt><dd>`RewriteEngine on`</dd><dd>rewriteエンジンの有効と無効を切り替えます。初期設定では無効になっています。無効の場合、[RewriteRule ディレクティブ]などが無視されるだけで、エラーは発生しません。</dd>

<dt>[RewriteRule ディレクティブ]　\(リンク先英語)</dt><dd><code>RewriteRule ^([^.]+)(?&lt;!/)$ ${adjust-extension:%{REQUEST_FILENAME},$1|$1}</code></dd><dd>第1引数の正規表現に一致したパスを第2引数で指定した文字列に置き換えます。一度でも置き換えが行われていると、全てのRewriteRuleが処理された後、内部リダイレクトによってリクエスト処理がやり直されます。`%{REQUEST_URL}`等もURL書き換え後のものになっているので、無限ループが起こらないように注意する必要があります。</dd><dd>rewriteはファイルシステムのパスではなくURLを書き換える処理なので、[Alias ディレクティブ]のようにドキュメントルート外に書き換えることはできません。</dd><dd>引数にワイルドカードを含む[&lt;Directory&gt; セクション]では期待通りに動かないことがあります (<i>per-dir</i>にワイルドカードが含まれたままrewrite処理が行われるため)。</dd></dl>

上記コードのような設定をして https://example.jp/file にアクセスしたときのrewrite処理を、例として示します。この場合、<i>ReqriteRuleを記述したディレクトリのパス絶対URL</i>（<i>per-dir</i>）は`/var/www/`です。

|   | 処理前                          | 処理後                          | 処理内容                                                                                                                   |
|---|---------------------------------|---------------------------------|----------------------------------------------------------------------------------------------------------------------------|
| 1 |/var/www/html/file               | html/file                       | <i>ファイルシステムのパス絶対URL</i>から<i>per-dir</i>を取り除く                                                           |
| 2 | html/file                       | html/file.xhtml                 | <code>^([^.]+)(?&lt;!/)$</code>に一致するので、<code>${adjust-extension:%{REQUEST_FILENAME},$1&#x7C;$1}</code>に書き換える |
| 3 | html/file.xhtml                 | /var/www/html/file.xhtml        | <i>per-dir</i>を前置する                                                                                                   |
| 4 | /var/www/html/file.xhtml        | /file.xhtml                     | <i>ドキュメントルート</i>を取り除き、内部リダイレクト                                                                      |
| 5 | /var/www/html/file.xhtml        | html/file.xhtml                 | <i>ファイルシステムのパス絶対URL</i>から<i>per-dir</i>を取り除く                                                           |
| 6 | html/file.xhtml                 | html/file.xhtml                 | <code>^([^.]+)(?&lt;!/)$</code>に一致しないので、何もしない                                                                |
| 7 | html/file.xhtml                 | /var/www/html/file.xhtml        | 書き換えが行われなかったので、<i>ファイルシステムのパス絶対URL</i>を返してrewrite処理終了                                  |

&#x20;
<dl><dt>[RewriteBase ディレクティブ]　\(リンク先英語)</dt><dd>`RewriteBase /`</dd><dd>[Alias ディレクティブ]によってURLがドキュメントルート外のパスと結び付けられていると、そのままでは内部リダイレクト前のドキュメントルートを取り除く処理が行えません。そこで、ドキュメントルートの絶対パスを取り除く代わりに、<i>per-dir</i>を第1引数で指定した<i>基底URL</i>に置き換えます。[^qa@it-alias-rewrite]</dd></dl>

上記コードのような設定をして https://example.jp/polyfill/main にアクセスしたときのrewrite処理を、例として示します。この場合、<i>per-dir</i>は`/var/www/common`、<i>基底URL</i>は`/`です。

|   | 処理前                           | 処理後                           | 処理内容                                                                                                                   |
|---|----------------------------------|----------------------------------|----------------------------------------------------------------------------------------------------------------------------|
| 1 | /polyfill/main                   | /var/www/common/polyfill/main    | [AliasMatch ディレクティブ]によって、<i>絶対URL</i>と<i>ファイルシステムの絶対パス相対URL</i>が結び付けられている          |
| 2 | /var/www/common/polyfill/main    | polyfill/main                    | <i>ファイルシステムのパス絶対URL</i>から<i>per-dir</i>を取り除く                                                           |
| 3 | polyfill/main                    | polyfill/main.js                 | <code>^([^.]+)(?&lt;!/)$</code>に一致するので、<code>${adjust-extension:%{REQUEST_FILENAME},$1&#x7C;$1}</code>に書き換える |
| 4 | polyfill/main.js                 | /var/www/common/polyfill/main.js | <i>per-dir</i>を前置する                                                                                                   |
| 5 | /var/www/common/polyfill/main.js | /polyfill/main.js                | <i>per-dir</i>を<i>基底URL</i>に置き換え、内部リダイレクト                                                                 |
| 6 | /polyfill/main.js                | /var/www/common/polyfill/main.js | [AliasMatch ディレクティブ]によって、<i>絶対URL</i>と<i>ファイルシステムのパス絶対URL</i>が結び付けられている              |
| 7 | /var/www/common/polyfill/main.js | polyfill/main.js                 | <i>ファイルシステムのパス絶対URL</i>から<i>per-dir</i>を取り除く                                                           |
| 8 | polyfill/main.js                 | polyfill/main.js                 | <code>^([^.]+)(?&lt;!/)$</code>に一致しないので、何もしない                                                                |
| 9 | polyfill/main.js                 | /var/www/common/polyfill/main.js | 書き換えが行われなかったので、<i>ファイルシステムのパス絶対URL</i>を返してrewrite処理終了                                  |

&#x20;
<dl><dt>[RewriteCond ディレクティブ]　\(リンク先英語)</dt><dd>[RewriteRule ディレクティブ]を適用する条件を設定します。RewriteRule1つに付き、複数のRewriteCondを設定できます。RewriteCondは対象のRewriteRuleよりも前に記述しますが、RewriteCondよりも先にRewriteRuleの条件がチェックされます。</dd>

<dt>[RewriteMap ディレクティブ]　\(リンク先英語)</dt><dd>`RewriteMap adjust-extension "prg:/usr/bin/perl -e '$| = 1; while (<STDIN>) { chomp($_); my @params = split(/,/, $_); my $path; if ($#params == 1) { ($path) = glob(@params[0] . \\\\'.*\\\\'); if ($path) { $path = substr($path, length(@params[0]) - length(@params[1])); } } print(($path || \\\\'NULL\\\\') . \\"\\\\\\\\x0A\\"); }'"`</dd><dd>第1引数にマップ名 (関数名)、第2引数に<i>マップタイプ</i>と<i>マップソース</i>を`:`区切りで指定し、[RewriteCond ディレクティブ]と[RewriteRule ディレクティブ]で利用できるマッピング関数を定義します。[RewriteMap ディレクティブ]は、<i>サーバ設定ファイルコンテキスト</i> (設定ファイルの中で[&lt;Directory&gt; セクション]や[&lt;VirtualHost&gt; セクション]の外) か<i>仮想ホストコンテキスト</i> ([&lt;VirtualHost&gt; セクション]の中で[&lt;Directory&gt; セクション]などの外) にしか記述できません。[RewriteMap ディレクティブ]を記述した場所でrewriteエンジンが無効になっている場合、関数は定義されません。`${マップ名:引数|デフォルト値}`のように関数を呼び出します。`${関数名:引数}`のようにデフォルト値を書かなかった場合、引数に対応する戻り値が見つからなかった場合 (`map lookup FAILED`) は空文字列が返ります。</dd><dd><i>マップタイプ</i>が`prg`の場合、マップソースは標準入力から引数を受け取り標準出力へ戻り値を書きだすプログラムファイルへのパスです。[User ディレクティブ]で設定したユーザーが、このプログラムファイルの実行権限を持っている必要があります。このプログラムはApache起動時に一度だけ起動されるため、標準入力を受け取るまで処理をブロックし、戻り値を書きだした後はまた標準入力を受け取るまで処理をブロックする無限ループ構造にしておきます。入出力バッファの無効化も必要です。戻り値の末尾に改行 (LF) を1つだけ置きます。文字列`NULL` (+改行) を返せば、`map lookup FAILED`を示すことができます。</dd><dd>プログラムが期待通りの動作をしない場合、SELinuxによってブロックされている場合もあるので、[SELinuxのログの確認]もしてみてください。また、プログラムの標準エラー出力は無視され、Apacheのログには残りません。</dd><dd>第2引数全体を`"`で囲み、プログラムへのパスの後に空白区切りでコマンドライン引数を書いた場合、各コマンドライン引数は文字列としてプログラムに渡されます。シングルクォートで囲むことで、コマンドライン引数に空白を含めることができます。コマンドライン引数の中で`'` `"` `\\`を使う場合は、それぞれ`\\\\'` `\\"` `\\\\\\\\` とエスケープします。</dd>

<dt>[RewriteOptions ディレクティブ]　\(リンク先英語)</dt><dd>`RewriteOptions Inherit`</dd><dd>rewriteエンジンの追加設定を有効にします。この設定有効化は、サブディレクトリで[RewriteRule ディレクティブ]などを記述した場合にも引き継がれます。`Inherit`は、<i>現在のディレクトリのルールの後に、親ディレクトリのルールをコピーする</i>というオプションです。`Inherit`オプションを<i>仮想ホストコンテキスト</i>で有効にした場合は意味が変わり、<i>メインサーバ設定</i> ([&lt;VirtualHost&gt; セクション]の外) に記述したルールを継承するオプションとなります。[^qa@it-rewriterule]</dd>

<dt>[LogLevel ディレクティブ]</dt><dd>`LogLevel alert rewrite:trace8`</dd><dd>エラーログに記録するログの種類を指定します。<i>モジュール</i>と<i>レベル</i>を`:`区切りで指定します。第1引数以降で複数記述することができます。第1引数の<i>モジュール</i>は省略することができ、その場合すべてのモジュールについて同じレベルを指定したことになります。既定は `LogLevel warn` です。</dd>
</dl>

[^qa@it-alias-rewrite]: [【Apache 2.4】サーバー全体で共通のRewriteRuleとAliasを設定したい - QA@IT](http://qa.atmarkit.co.jp/q/3283#answer_16079)
[^qa@it-rewriterule]: [【Apache 2.4】サーバ設定ファイルに記述したRewriteRuleが動かない - QA@IT](http://qa.atmarkit.co.jp/q/3248#answer_16032)

[mod_negotiationモジュール]: https://httpd.apache.org/docs/current/content-negotiation.html "Apache は HTTP/1.1 の規格に記述されているコンテントネゴシエーションを サポートしています。 ブラウザにより提供されたメディアタイプ、 言語、文字セット、エンコーディングの優先傾向に基づいて、 最適なリソースの表現を選択できます。 また、不完全なネゴシエーション情報を送ってくるブラウザからのリクエストを もっと賢く取り扱えるよう、いくつか機能も実装してあります。"
[RewriteEngine ディレクティブ]: https://httpd.apache.org/docs/current/mod/mod_rewrite.html#rewriteengine "Enables or disables runtime rewriting engine"
[RewriteRule ディレクティブ]: https://httpd.apache.org/docs/current/mod/mod_rewrite.html#rewriterule "Defines rules for the rewriting engine"
[RewriteBase ディレクティブ]: https://httpd.apache.org/docs/current/mod/mod_rewrite.html#rewritebase "Sets the base URL for per-directory rewrites"
[RewriteCond ディレクティブ]: https://httpd.apache.org/docs/current/mod/mod_rewrite.html#rewritecond "Defines a condition under which rewriting will take place"
[RewriteMap ディレクティブ]: https://httpd.apache.org/docs/current/mod/mod_rewrite.html#rewritemap "Defines a mapping function for key-lookup"
[SELinuxのログの確認]: //qiita.com/100/items/f7f43994568836b4a453#違反ログから新しいルールを定義 "ポリシー違反のログは、`sudo grep avc: /var/log/messages`を実行、又はAuditが起動していた状態なら`sudo ausearch --message AVC`を実行することで確認できます。"
[RewriteOptions ディレクティブ]: https://httpd.apache.org/docs/current/mod/mod_rewrite.html#rewriteoptions "Sets some special options for the rewrite engine"
[LogLevel ディレクティブ]: https://httpd.apache.org/docs/current/mod/core.html#loglevel "ErrorLog の冗長性を制御する"

開発環境向けの設定
==================
```apache:/etc/httpd/conf/httpd.conf
                        ##############
                        ## 以上省略 ##
                        ##############

#
# EnableMMAP and EnableSendfile: On systems that support it, 
# memory-mapping or the sendfile syscall may be used to deliver
# files.  This usually improves server performance, but must
# be turned off when serving from networked-mounted 
# filesystems or if support for these functions is otherwise
# broken on your system.
# Defaults if commented: EnableMMAP On, EnableSendfile Off
#
#EnableMMAP off
#EnableSendfile on
## ↑仮想マシンで共有ディレクトリを使用している場合、この行をコメントアウトする ##

                        ##############
                        ##   中略   ##
                        ##############

# 開発環境

# 403と404を区別する
ErrorDocument 403 /forbidden

# 開発環境用のスタイルシート
Header always set link "</common/development>; rel=stylesheet"

# Faviconを変える
Alias /favicon.ico /var/www/html/favicon-development.ico

# 開発環境へのCSRFを防止する
<If "-n %{HTTP_REFERER} && !(%{HTTP_REFERER} -strmatch %{REQUEST_SCHEME} . '://' . %{SERVER_NAME} . '/*')">
    # リファラが存在し、かつリファラのホスト名がサーバーのホスト名と一致しなければ
    Require all denied
</If>
```

ブラウザでリファラを変更している場合は、ターゲットのホワイトリストに開発環境のドメインを追加しておきます。

&#x20;
<dl><dt>[EnableSendfile ディレクティブ]</dt><dd>「sendfile」というシステムコールを使って静的ファイルを返す時の性能を向上しようとする機能の有効と無効を切り替えます。<br>Apache 2.4の既定は`EnableSendfile Off`ですが、CentOS7標準のパッケージでは設定ファイルに`EnableSendfile On`が記述されており有効化されています。 **[VirtualBox]などで[仮想マシン]を作成して共有ディレクトリ機能を利用している場合、ファイルの更新が反映されないことがあります。** そのようなときは、`EnableSendfile On`をコメントアウトしてこの機能を無効化します。[^sf]</dd>
</dl>

```css:/var/www/common/common/development.css
/*====================================
	表示領域の右端に縦書きで文字を表示する
*/
body::after {
	font-size: 10vmin;
	width: 1em;
	line-height: 2.3;
	content: "開発環境";
	display: block;
	color: #FFFFFF;
	font-weight: bold;
	background: rgba(127, 127, 127, 0.7);
	border: solid #FFFFFF 0.2em;
	position: fixed;
	top: 0;
	bottom: 0;
	right: 0;
	opacity: 0.5;
}
```

[link応答ヘッダ][link]によるCSSの設定は、前述のようにFirefoxでしか使えません。開発環境を表すCSSの設定はユーザースタイルシートを使っても良いと思います。

[^sf]: [VagrantやVirtualBoxの共有フォルダ機能で静的ファイルが更新されない — SEEDS Creator’s Blog](http://blog.seeds-std.co.jp/entry/1227.html)

[EnableSendfile ディレクティブ]: https://httpd.apache.org/docs/current/mod/core.html#enablesendfile "ファイルのクライアントへの配送時にカーネルの sendfile サポートを 使うかどうか"
[VirtualBox]: https://ja.wikipedia.org/wiki/VirtualBox "Oracle VM VirtualBox （オラクル ブイエム バーチャルボックス）とは、x86仮想化ソフトウェア・パッケージの一つ。現在の開発は米国オラクルが行っている。"
[仮想マシン]: https://ja.wikipedia.org/wiki/%E4%BB%AE%E6%83%B3%E6%A9%9F%E6%A2%B0 "仮想機械（かそうきかい、仮想マシン、バーチャルマシン、英語: virtual machine、VM）とは、コンピュータの動作をエミュレートするソフトウェアやフレームワークである。また、エミュレートされた仮想のコンピュータそのものも仮想機械という。仮想機械によって、1つのコンピュータ上で複数のコンピュータやOSを動作させたり、別のアーキテクチャ用のソフトウェアを動作させることができる。"

参考ページ・脚注
================