🦍

Apacheちょっとだけチョットワカル

2022/11/18に公開約9,300字

はじめに

最近Apacheの設定をいじることが多くなってきて、そもそもほぼ触っていなかったので初歩的なところから、(自分的には)発展っぽいところまでざっと調べてみたのでこの機会にまとめてみる。誰かの参考になれば幸いです。

バーチャルホスト(VirtualHost)の設定

ここは公式ドキュメントを見るのが早いし正確だと思う。
https://httpd.apache.org/docs/2.4/ja/vhosts/examples.html

ここら辺は最初易しいかも
https://weblabo.oscasierra.net/apache24-centos7-virtualhost/
https://qiita.com/erik_t/items/63f079826a60aaa642d3

例として、example.com用のバーチャルホストを設定してみる。

# vi /etc/httpd/conf.d/domain.conf

// viエディタ
<VirtualHost *:80>
    # サーバが自分自身を示すときに使うホスト名(ポート番号はVirtualHostセクションで書いてる)
    ServerName example.com
    # ルートディレクトリを指定
    DocumentRoot /var/www/example
    # サーバがクライアントに送るエラーメッセージに含めるメールアドレス
    ServerAdmin engineer@example.com
    # エラーログの設定
    ErrorLog logs/example.com.error_log
    # アクセスログの設定(cssやjsなどのファイルアクセスはロギングしない)
    CustomLog logs/example.com.access_log combined env=!no_log
    SetEnvIf Request_URI "\.(gif)|(jpe?g)|(png)|(css)|(js)|(svg)$" no_log
    # 対象ディレクトリのアクセス制御など
    <Directory /var/www/example>
	# 全てのアクセスを許可
        Require all granted
	# "-Indexes"ファイルの一覧表示をしない、"+FollowSymLinks"シンボリックリンクを利用
        Options -Indexes +FollowSymLinks
	# .htaccessでの上書きを許可する
        AllowOverride All
    </Directory>
    # リダイレクトの設定
    RewriteEngine on
    RewriteCond %{SERVER_NAME} =domain
    RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>

mod_rewiteモジュールに関しては以下の記事が分かりやすい
https://koseki.hatenablog.com/entry/20090611/ModRewrite

IPアドレスによる制御

攻撃はいろんな場所から来るはずで、情報が漏洩とかが起こってからでは遅いので海外からのアクセスを制限する。具体的には日本のIPとブラウザのクローラーのみアクセスを許可したい。そこで参考にした記事や自分なりにつまづきポイントだったところをまとめる。

以下の記事を参考にすれば基本的には問題ないはず。
https://oopsoop.com/how-to-control-access-from-overseas-with-htaccess-apache24-compatible/
https://notepad-blog.com/content/196/
https://qiita.com/non0311/items/21516b8bdc0a0fca69fb

※補足:Apache2.4系ではRequireディレクティブでアクセス制御が可能。
https://www.javadrive.jp/apache/allow/index1.html#section1_1

以下リンクでで国別のIPアドレスのCIDRの取得ができる(Apache 2.4に対応) 
※これはRequire not ip xxx.xxx.xxx.xxx/xxになってるので、そこは注意
https://ipv4.fetus.jp/

海外からのアクセスが弾かれるかのテストは以下リンクで行なった。これ以外にもChrome拡張もあるらしい。
https://www.webpagetest.org/

自分がコケたポイント

最初アクセスログを見て、不正アクセスっぽいIPアドレスを特定しその国のIPアドレス範囲をごそっと拒否するみたいな書き方をしていた。つまり、以下のような記事をしていた

<Directory "/dev/html">
    Require all granted
    Require not ip xxx.xxx.xxx.xxx/xx
    ...
    Require not ip yyy.yyy.yyy.yyy/yy
</Direvtory>

systemctl restart httpd(Apacheの再起動)とやると構文エラーが出た。
restartをした理由は、今回の要求的に日本のIPアドレス範囲外のアクセスを拒否するというものだったので、現在走っているプロセスごと終了して設定ファイルを読み込みたかったためである。Apacheの起動、再起動、停止周りのサブコマンドなども調べてみたので詳細はこちら
systemctl status httpdでどこでこけているのかを確認し、いろいろ調べていたら以下の記事に辿り着いた。
https://www.nofuture.tv/20130813
記事の引用

  • 特定のホストやIPのみのアクセスを許可する場合は、 Require だけでOK。
  • 特定のホストやIPのアクセスを拒否する場合は、きちんと < RequireAll> ディレクティブを書いてから書く

Apacheのドキュメントの引用

When multiple Require directives are used in a single configuration section and are not contained in another authorization directive like <RequireAll>, they are implicitly contained within a <RequireAny> directive. Thus the first one to authorize a user authorizes the entire request, and subsequent Require directives are ignored.

つまり、
Requireディレクティブを複数条件記載する時、<RequireAll>で囲む必要がある模様。何もなしだと<RequireAny>と認識され1つ目以降が無視されるらしい。
ということで修正してみた。これで、Apacheを再起動が問題なくできた。

<Directory "/dev/html">
    <RequireAll>
        Require all granted
        Require not ip xxx.xxx.xxx.xxx/xx
        ...
        Require not ip yyy.yyy.yyy.yyy/yy
    </RequireAll>
</Direvtory>

設定ファイルの読み込み順について

この記事は自分が知りたかったところ(Include conf.d/*.confの読み込む順番知りたかった)的には割とドンピシャだった。アルファベット順らしい。
https://superuser.com/questions/705297/in-what-order-does-apache-load-conf-files-and-which-ones

公式ドキュメントの引用

Shell-style (fnmatch()) wildcard characters can be used to include several files at once, in alphabetical order. In addition, if Include points to a directory, rather than a file, Apache will read all files in that directory and any subdirectory. But including entire directories is not recommended, because it is easy to accidentally leave temporary files in a directory that can cause httpd to fail.

https://httpd.apache.org/docs/2.2/mod/core.html#include

https://teratail.com/questions/158545
https://www.go-next.co.jp/blog/server_network/4084/

設定は上書きされるのか?

What happens if you have two of the same directives in the config is complicated. It depends, at least, on the directive; some (e.g., Require) add to the previous ones. Some modify or overwrite them, depending on exact syntax used (e.g., Options). Similarly, global config and per-vhost config (and per-directory and per-location and...) combine in interesting ways. You have to check the Apache docs for details.

  • ざっくり日訳

同じディレクティブに関する記述が2つ設定されている場合は複雑です。ディレクティブ(apacheでのプロパティ的なもの)による、例えばRequireは後に追加するし、Optionsなら上書きます。グローバルな設定やホスト毎の設定などいろいろあるので(サボった)、詳細についてはApacheのドキュメントを見てください

https://unix.stackexchange.com/questions/456845/apache-config-files-order

どのファイルでアクセス制御するのが良いか?

httpd.conf/conf.d/*.conf.htaccessがあり、結局どのファイルでアクセス制御すれば良いのか?という疑問が出てきた。よくあるのは.htaccessでの制御はよく記事とかあるなーという印象。
これに関しては公式ドキュメントで言及されているので引用してみる。

一般的に、サーバの主設定ファイルにアクセスできない場合を除いて、 .htaccess ファイルの使用は極力避けてください。 世の中には、例えば、ユーザ認証は常に .htaccess ファイルで 行なわなければならない、という誤解が広まっていますが、まったくそんなことは ありません。ユーザ認証の設定はサーバ主設定ファイルに書くことができ、 実際、その方がより良い設定方法です。
.htaccess ファイルはコンテンツ提供者がディレクトリ毎の 設定を行ないたいけれど、サーバシステムの root アクセス権限を持っていない という場合にのみ使うべきものです。サーバ管理者が頻繁に設定変更を行ないたくは ない、というときには個々のユーザが .htaccess ファイルを使って 自分で設定の変更を行なうことを許可した方が良いときもあるでしょう。 これは特に、ISP が複数のユーザのサイトを一つのマシンでホストしていて、 各ユーザが設定の変更をできるようにしたいようなときにあてはまります。

https://httpd.apache.org/docs/2.4/ja/howto/htaccess.html

.htaccessは特に理由がない限り(このディレクトリはアクセス制御したいとか)は使わず主設定ファイルでアクセス制御を行うべき、と理解した。

アクセス制御にあたり、セクションのマージが起こることに注意したい。

The configuration sections are applied in a very particular order. Since this can have important effects on how configuration directives are interpreted, it is important to understand how this works.
The order of merging is:
1. <Directory> (except regular expressions) and .htaccess done simultaneously (with .htaccess, if allowed, overriding <Directory>)
2. <DirectoryMatch> (and <Directory "~">)
3. <Files> and <FilesMatch> done simultaneously
4. <Location> and <LocationMatch> done simultaneously
5.<If>

上記以外にも、以下のように結構大事なことが書いてあるので読んでおいた方が良さそう。

  • <Derectory>セクション以外は設定ファイルに表れた順に設定される(設定が競合した場合、後に読んだ方が適用される)
  • <Derectory>セクションはディレクトリパスが長いものから適用される
  • <VirtualHost>セクション中で扱うセクションは、同じセクションの設定が読み込まれた後にバーチャルホストの設定が読まれるので上書きすることができる
    https://httpd.apache.org/docs/2.4/en/sections.html#merging
    https://qiita.com/ngyuki/items/779ea21eec2ae6c450d5

Apacheコマンドオプション集

Apacheの設定ファイルの読み込み順序ってタイトルだが、オプションに関する説明の方が充実してる。
https://scrapbox.io/tech-notes/Apacheの設定ファイルの読み込み順序

構文エラーとかないかチェックできる。

# htppd -t
# apachectl -t

おまけ、小ネタ

Basic認証

ApacheでBasic認証を設定するのは以下記事を参考にしたらできるはず。ポイントは必須の作業ではないがhtpasswdの所有者、権限を変更しておくこと(最小権限を心掛ける)。
https://pointsandlines.jp/server-infra/basic-authorize

で、Basic認証をブラウザでログインするとキャッシュが残るため都度ログインが求められることはない。
https://oshiete.goo.ne.jp/qa/2001219.html
しかし、別ユーザーでのログインをしたい場合など何らかの理由でキャッシュをクリアしたい時があるはず。その時はホスト名の前に任意文字列@を付けると良いらしい、以下リンクを参考に。自分のブラウザ(Chrome)ではusername:password@hostnameで適当なユーザー名(hoge:fuga@hostname)で試したが、キャッシュはうまく消えなかった。なぜだろう、ブラウザの詳細設定とかそこまで見てる訳じゃないのでそこら辺が原因?
https://dev.classmethod.jp/articles/delete-cache-for-basic-authentication/

アクセスログの見方

記事の冒頭でApacheのアクセスログの見方について分かりやすかったので、載せておく。またこの記事はApacheだけでなくWebサーバー全体の不正アクセスなどの確認などについても書いてくれているのでssh接周りも見てみるといいかも。
https://knowledge.sakura.ad.jp/3424/

アクセスログの解析ツール(無料)
https://freesoft.tvbok.com/freesoft/web/apachelogviewer.html

本番環境用の設定

おまじない的な感じで以下3行は入れておいた方がいい。
ServerSignature:"no"でApacheが出す画面にサーバー情報を出さない
ServerTokens:"ProductOnly|Prod"でバージョン情報などを隠蔽する
Header unset X-Powered-By:PHPのバージョン情報を消す

ServerSignature Off
ServerTokens ProductOnly # Prodでも可
Header unset X-Powered-By

https://blog.katsubemakito.net/apache/disable-put-version
https://atmarkit.itmedia.co.jp/ait/articles/0707/19/news141_2.html

参考資料

他にApache周りで参考になる記事をまとめておく
https://www.rem-system.com/apache-security01/
https://qiita.com/DQNEO/items/2ab6062ec740068391a2

2.2系の方も参考にできそうなIPアドレスによるアクセス制御
https://qiita.com/beachWoooWoo/items/f1c8a1d9de16e1151ce1

Aliasディレクティブ

このモジュールのディレクティブはサーバにリクエストが到着したときに URL の操作や制御をすることを可能にします。Alias ディレクティブと ScriptAlias ディレクティブは URL とファイルシステムのパスをマップするために使用されます。これは DocumentRoot の下にないドキュメントをウェブのドキュメントツリーの一部として 送られるようにします。ScriptAlias ディレクティブにはマップ先のディレクトリが CGI スクリプトのみであることを示すという追加の効果があります。

https://httpd.apache.org/docs/current/en/mod/mod_alias.html
https://oki2a24.com/2013/11/18/apache-mod-alias-points/
https://www.javadrive.jp/apache/ini/index12.html

IfModuleディレクティブ

このディレクティブは特定のモジュールの 存在に関わらず設定ファイルが動作する必要がある場合にのみ使ってください。 常に動作して欲しいディレクティブを囲むために使うべきではありません。 存在しないモジュールに関する有用なエラーメッセージの発生を抑制してしまいますので。

https://httpd.apache.org/docs/2.4/ja/sections.html

SSL証明書を有効にする(Let's Encrypt)
https://weblabo.oscasierra.net/letsencrypt-2/
https://qiita.com/dolcano/items/4ad38ec85d0fd27a229c

自分は特に参考にしてはないが、誰かの参考になるかも。
https://ti-tomo-knowledge.hatenablog.com/entry/2018/05/29/144435

DirectoryとLocationの違い
https://hogem.hatenablog.com/entry/20070324/1174742327

Apacheのセクションについて
https://httpd.apache.org/docs/2.4/en/sections.html

Discussion

ログインするとコメントできます