LoginSignup
6
4

More than 3 years have passed since last update.

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

Last updated at Posted at 2020-02-21

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

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

使い回すファイルたち

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

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

conf/httpd.conf

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

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 ciphers -v 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

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 されているサイトにあえてHTTPでアクセスするのは誰だ、というのを興味本位で知りたいだけです。普通は必要ないです。

_default_443.conf

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アドレスからホスト名が漏れる)で書きました。

バーチャルホストの定義

以下は、それぞれのバーチャルホストを定義するファイルです。これは、実際に私が使っているWebサーバのものです。

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

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のACMEクライアントには dehydrated を使っています)

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

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

6
4
0

Register as a new user and use Qiita more conveniently

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