自分のApache httpdの設定はいけてるのかなあ？

# 自分が使い回している設定をさらしてみます

結構がんばって作ったのですが、まだまだできることがありそうです。「こうしたらいいよ！」というご指摘、お待ちしております。

# 使い回すファイルたち

なにかに依存することを避けて、どの環境でも使えるようにしたファイルたちです。書き換えることはありません。

（ただ Amazon Linux 2 を対象にしているので、場合によってはモジュールが足りないと言われるかもしれません。あと、想定している環境は 2.4 系のみです）

## conf/httpd.conf

```apache:conf/httpd.conf
Listen 80

Include conf.modules.d/*.conf

User apache
Group apache

ServerName localhost

<Directory "/">
    Require all denied
</Directory>

<Files ".ht*">
    Require all denied
</Files>

<IfModule mod_http2.c>
    Protocols h2 h2c http/1.1
</IfModule>

TypesConfig /etc/mime.types

LogLevel warn
ErrorLog logs/error_log

IncludeOptional conf.d/*.conf
IncludeOptional conf.d/vhosts/*.conf
```

もともとのファイルからコメントを削っただけのような。

追加の設定は最後の2行で include しているように `conf.d/` に書いて、バーチャルホストの定義は `cond.d/vhosts/` に書きます。

## conf.d/ssl.conf

```config:conf.d/ssl.conf
Listen 443 https

#SSLPassPhraseDialog exec:/usr/libexec/httpd-ssl-pass-dialog
SSLSessionCache         shmcb:/run/httpd/sslcache(512000)
SSLSessionCacheTimeout  300

SSLStaplingCache shmcb:/tmp/stapling_cache(128000)

SSLRandomSeed startup file:/dev/urandom  256
SSLRandomSeed connect builtin

SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
SSLCipherSuite ECDSA+AESGCM
SSLHonorCipherOrder Off
```

どこかからいろいろコピーしてきて作ったような。

`SSLProtocol` は TLSv1.2 しか対応していなくても `all -SSLv3 -TLSv1 -TLSv1.1` と書いておくと、この先 TLSv1.3 に対応したときでも安心です。

`SSLCipherSuite` は、セキュリティ事情でいつか変える日が来ると思いますが、2020年7月3日現在では `ECDSA+AESGCM` だけで問題ないと思います。

```:openssl&nbsp;ciphers&nbsp;-v&nbsp;ECDSA+AESGCM
TLS_AES_256_GCM_SHA384  TLSv1.3 Kx=any      Au=any  Enc=AESGCM(256) Mac=AEAD
TLS_CHACHA20_POLY1305_SHA256 TLSv1.3 Kx=any      Au=any  Enc=CHACHA20/POLY1305(256) Mac=AEAD
TLS_AES_128_GCM_SHA256  TLSv1.3 Kx=any      Au=any  Enc=AESGCM(128) Mac=AEAD
ECDHE-ECDSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH     Au=ECDSA Enc=AESGCM(256) Mac=AEAD
ECDHE-ECDSA-AES128-GCM-SHA256 TLSv1.2 Kx=ECDH     Au=ECDSA Enc=AESGCM(128) Mac=AEAD
```

`SSLHonorCipherOrder` は、`On` にするよう書いてあるページが多いですが、[**ここは `Off` のままにしています**](https://qiita.com/keys/items/62ed6b571112a457e560)。`Off` だとブラウザが Cipher を選ぶことになりますが、サーバ側で指定するより日々更新されるブラウザに任せた方が、セキュリティを十分考慮しつつパフォーマンスよくハンドリングしてくれるでしょう。

（`SSLPassPhraseDialog` をコメントアウトしてあるのは、[私はTLSv1.3対応のmod_sslを自前でbuildしているので](https://qiita.com/keys/items/61eb02bd7396cda0d548)、mod_ssl パッケージに含まれているスクリプトが入っていないからです。鍵の passphrase は気にしない方向で…）

## conf.d/vhosts/\_default\_\*.conf

リクエストしたバーチャルホストがないときに使われる定義です。分かりやすいよう、HTTP用とHTTPS用の2つに分けています。

2.4 系では `NameVirtualHost` は何も処理をしないようになったので書いていません[^namevirtualhost]。（それにともなって `_default_` が `*` のエイリアス扱いになった[^defaultasterisk]、という変更もありますが、あえて `*` に変える必要はないと思っています）

[^namevirtualhost]: [This directive currently has no effect.](https://httpd.apache.org/docs/2.4/en/mod/core.html#namevirtualhost) 

[^defaultasterisk]: [The string `_default_`, which is an alias for `*`](https://httpd.apache.org/docs/2.4/en/mod/core.html#virtualhost)

### \_default\_80.conf

```apache:conf.d/vhosts/_default_80.conf
<VirtualHost _default_:80>
    DocumentRoot /var/www/_default
    <Directory "/var/www/_default">
        Require all granted
    </Directory>
    <If "-f '/var/www/%{HTTP_HOST}/index.html'">
        <If "%{REQUEST_URI} !~ m#^/.well-known/acme-challenge/#">
            RewriteEngine on
            RewriteRule ^.*$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
        </If>
    </If>
    <Else>
        Redirect 403 /
    </Else>

    LogFormat "%{Host}i %h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" http_combined
    CustomLog logs/access_log http_combined
</VirtualHost>
```

HTTP(port 80)は以下のように処理します。

* `HTTP_HOST` に該当するバーチャルホストがない場合、すべてのリクエストに `403 Forbidden` を返します
* Let's Encrypt のACMEプロトコルで使うパスだった場合は何もせず、それ以外ならリクエストをそのままHTTPSにリダイレクトします

ACMEプロトコルで使うパスに対応するディレクトリは `/var/www/_default/.well-known/acme-challenge` になるなので `/var/www/_default` はアクセスできるようにします。

ここまでやる必要があるのかな、という気は、まあ、あります……。
`mod_rewrite` の負荷を少しは減らして、全体のレイテンシをあげられるかも……？

log に `Host` ヘッダを記録しているのは、[HSTS preload](https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/Strict-Transport-Security) されているサイトにあえてHTTPでアクセスするのは誰だ、というのを興味本位で知りたいだけです。普通は必要ないです。

### \_default\_443.conf

```apache:conf.d/vhosts/_default_443.conf

<VirtualHost _default_:443>
    LogFormat "%{Host}i %h [%{%Y/%m/%d %T}t] %>s %b %{SSL_PROTOCOL}x \"%r\" \"%{Referer}i\" \"%{User-Agent}i\"" all_host_ssl
    CustomLog logs/keys_ssl_access_log all_host_ssl

    LogFormat "%{Host}i %h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" https_combined
    CustomLog logs/ssl_access_log https_combined

    Redirect 403 /

    SSLEngine on
    SSLCertificateFile conf.d/dummy.crt
    SSLCertificateKeyFile conf.d/dummy.key
</VirtualHost>
```

？？？　という感じの設定ですが、こうしている理由は[別の記事（SSL証明書でIPアドレスからホスト名が漏れる）](https://qiita.com/keys/items/187a9e028b2b9dcbc1c6)で書きました。


# バーチャルホストの定義

以下は、それぞれのバーチャルホストを定義するファイルです。これは、[実際に私が使っているWebサーバ](https://devel.keys.jp/)のものです。

HTTP(port 80)は独自のものは設定せず、デフォルトのものを使います。

```apache:conf.d/vhosts/devel.keys.jp.conf
<VirtualHost *:443>
    ServerName devel.keys.jp
    ServerAdmin admin@devel.keys.jp
    DocumentRoot /var/www/devel.keys.jp

    <Directory "/var/www/devel.keys.jp">
        Options All -Indexes
        AllowOverride All
        Require all granted
        SSLOptions +StdEnvVars +StrictRequire
        AddHandler cgi-script .cgi .pl .py
    </Directory>

    LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combine_by_host
    CustomLog logs/devel.keys.jp/ssl_access_log combine_by_host

    Header set X-XSS-Protection "1; mode=block"
    Header set X-Content-Type-Options nosniff
    Header append X-Frame-Options SAMEORIGIN
    Header set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"

    SSLEngine on
    SSLUseStapling on
    SSLCertificateFile /opt/dehydrated/certs/devel.keys.jp/fullchain.pem
    SSLCertificateKeyFile /opt/dehydrated/certs/devel.keys.jp/privkey.pem
</VirtualHost>
```

アクセスログをバーチャルホスト単位で保存するように変更しているほかは、とくに珍しいことはしていないと思います。
（[Let's Encrypt](https://letsencrypt.org/ja/)のACMEクライアントには [dehydrated](https://github.com/dehydrated-io/dehydrated) を使っています）

今はただ静的コンテンツを提供しているだけなので、これで十分にやれています。重いコンテンツを提供しだすとどうなのかな……。

みなさまは、どういった工夫をされていますか？