自分が使い回している設定をさらしてみます
結構がんばって作ったのですが、まだまだできることがありそうです。「こうしたらいいよ!」というご指摘、お待ちしております。
使い回すファイルたち
なにかに依存することを避けて、どの環境でも使えるようにしたファイルたちです。書き換えることはありません。
(ただ Amazon Linux 2 を対象にしているので、場合によってはモジュールが足りないと言われるかもしれません。あと、想定している環境は 2.4 系のみです)
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
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
だけで問題ないと思います。
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
のままにしています。Off
だとブラウザが Cipher を選ぶことになりますが、サーバ側で指定するより日々更新されるブラウザに任せた方が、セキュリティを十分考慮しつつパフォーマンスよくハンドリングしてくれるでしょう。
(SSLPassPhraseDialog
をコメントアウトしてあるのは、私はTLSv1.3対応のmod_sslを自前でbuildしているので、mod_ssl パッケージに含まれているスクリプトが入っていないからです。鍵の passphrase は気にしない方向で…)
conf.d/vhosts/_default_*.conf
リクエストしたバーチャルホストがないときに使われる定義です。分かりやすいよう、HTTP用とHTTPS用の2つに分けています。
2.4 系では NameVirtualHost
は何も処理をしないようになったので書いていません1。(それにともなって _default_
が *
のエイリアス扱いになった2、という変更もありますが、あえて *
に変える必要はないと思っています)
_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 されているサイトにあえてHTTPでアクセスするのは誰だ、というのを興味本位で知りたいだけです。普通は必要ないです。
_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アドレスからホスト名が漏れる)で書きました。
バーチャルホストの定義
以下は、それぞれのバーチャルホストを定義するファイルです。これは、実際に私が使っているWebサーバのものです。
HTTP(port 80)は独自のものは設定せず、デフォルトのものを使います。
<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のACMEクライアントには dehydrated を使っています)
今はただ静的コンテンツを提供しているだけなので、これで十分にやれています。重いコンテンツを提供しだすとどうなのかな……。
みなさまは、どういった工夫をされていますか?