[PR] 本記事にはプロモーションが含まれています。

【Apache】Cloudflare Tunnel経由のアクセスログに読者のIPアドレスを残す(mod_remoteip)|127.0.0.1になる理由と設定

Apache

【2026年7月6日時点の情報です】

 このブログは、Cloudflare Tunnelを使って、自宅サーバーのポートを開けずに公開しています。ただ、そのままだとApacheのアクセスログのIPアドレスがすべて 127.0.0.1 になり、誰がアクセスしてきたのか分かりません。

この記事では、AlmaLinux 9のApacheで mod_remoteip を使い、ログに読者のIPアドレスを残す設定と、その確かめ方をまとめます。Tunnelの設定は「Cloudflare Tunnelで自宅サーバーを公開する方法」で紹介しています。

ログが127.0.0.1になる理由

Cloudflare Tunnelでは、読者のアクセスは次の順に届きます。

Plaintext
【読者】 → 【Cloudflare】 → 【cloudflared(同じサーバーの中)】 → 【Apache】

Apacheに接続してくるのは、同じサーバーの中で動いている cloudflared だけです。そのため、Apacheから見ると接続元はいつも 127.0.0.1(IPv6なら ::1)になります。

Cloudflareは、読者のIPアドレスを CF-Connecting-IP というヘッダーに入れて渡してくれます。mod_remoteip は、このヘッダーの値を「本当の接続元」として扱うためのApacheのモジュールです。

設定の手順

1. mod_remoteip が読み込まれているか確かめる

AlmaLinux 9のApacheでは、mod_remoteip は最初から読み込まれています。念のため確かめます。

Bash
sudo httpd -M | grep remoteip

remoteip_module (shared) と表示されれば大丈夫です。

2. 設定ファイルを作る

Bash
sudo vi /etc/httpd/conf.d/remoteip.conf

次の内容を書きます。

Apache
<IfModule remoteip_module>
    # 読者のIPアドレスが入っているヘッダー
    RemoteIPHeader CF-Connecting-IP

    # このヘッダーを信じるのは、cloudflared(同じサーバー)から来たときだけ
    RemoteIPInternalProxy 127.0.0.1 ::1
</IfModule>

この2行で、「127.0.0.1 か ::1 から来たアクセスに限って、CF-Connecting-IP の値を接続元として扱う」という意味になります。

Tunnelを使わずにルーターのポートを開け、Cloudflareのサーバーから直接Apacheにつなぐ形の場合は、127.0.0.1 の代わりに CloudflareのIPアドレスの範囲を RemoteIPTrustedProxy で登録します。Tunnelでは、Apacheにつなぐのは cloudflared だけなので、登録する必要はありません。

3. ログの書式を %a にする

Apacheの初期設定のログの書式(LogFormat)は、先頭が %h になっています。mod_remoteip で書き換えたIPアドレスは %a で記録されるので、%h を %a に変えます。

Bash
sudo vi /etc/httpd/conf/httpd.conf

<IfModule log_config_module> の中にある LogFormat を、次のようにします。combinedio も忘れずに変えます。

Apache
<IfModule log_config_module>
    # 先頭の %h を %a に変える
    LogFormat "%a %l %u %t \"%!414r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
    LogFormat "%a %l %u %t \"%r\" %>s %b" common

    <IfModule logio_module>
      LogFormat "%a %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio
    </IfModule>
</IfModule>

先頭の %a 以外は、もとの書式のままです。combined の %!414r は、「URLが長すぎる(414)ときはリクエストの中身を記録しない」という意味で、異常に長いURLでログがふくらむのを防ぎます。

4. 設定を確かめて反映する

Bash
sudo httpd -t                  # Syntax OK と出れば設定の書き方は大丈夫
sudo systemctl restart httpd

動いているか確かめる

ログに読者のIPアドレスが残っているか

外からサイトを開いたあと、アクセスログの最後の数行を見ます。

Bash
sudo tail -n 5 /var/log/httpd/access_log

次のように、行の先頭が 127.0.0.1 ではなく、接続元のIPアドレスになっていれば成功です(アドレスは例です)。

Plaintext
2001:db8:1234:5678::abcd - - [20/Jun/2026:20:54:54 +0900] "GET / HTTP/1.1" 200 ...
203.0.113.25 - - [20/Jun/2026:20:56:48 +0900] "GET /feed/ HTTP/1.1" 200 ...

バーチャルホストごとにログを分けている場合は、そのファイルを見ます。

外からヘッダーを偽っても、だまされないか

CF-Connecting-IP はただのヘッダーなので、誰でも好きな値を付けて送れます。127.0.0.1 以外から来たときはこのヘッダーを信じない設定にしているのは、そのためです。

家のLANの別のパソコンから、サーバーのLANのIPアドレスに形だけのヘッダーを付けてアクセスしてみると、確かめられます。

Bash
# 別のパソコンから(192.168.x.x はサーバーのLANのIPアドレス)
curl -s -o /dev/null -H "CF-Connecting-IP: 203.0.113.99" http://192.168.x.x/

# サーバーでログを見る
sudo tail -n 1 /var/log/httpd/access_log

ログの先頭が 203.0.113.99 ではなく、そのパソコンのLANのIPアドレスになっていれば、偽のヘッダーは無視されています。

知っておきたいこと

  • Require ip も、書き換えたアドレスで判定される:
    mod_remoteip で書き換えたIPアドレスは、ログだけでなく、Apacheの Require ip によるアクセス制限でも使われます。このブログでは、phpMyAdminを家のLANからだけ開けるようにしていますが、Tunnel経由のアクセスが「127.0.0.1(内側)」として通ってしまわないのも、この設定のおかげです
  • サーバー側でIPアドレスをブロックしても止まらない:
    Tunnelでは実際の接続元はいつも cloudflared なので、サーバーのファイアウォールで相手のIPアドレスを止めても効きません。気になる相手を止めるときは、CloudflareのWAFで止めます(「WAFのカスタムルールで自宅サーバーのWordPressを守る」)
  • ブログにログを載せるときは、自分のIPアドレスを例に置き換える:
    読者のIPアドレスが残るようになると、自分のアクセスも自宅のIPアドレスで記録されます。記事に載せるときは、説明用の 203.0.113.x や 2001:db8: に置き換えておきます

読者のIPアドレスがログに残るようになると、GoAccessでのアクセス解析や、怪しいアクセスの調査ができるようになります(「Webアクセス解析(GoAccess)の設定」「レポートに見知らぬ海外のIPv6アドレス、正体はMJ12bot」)。Cloudflare全体の仕組みは「Cloudflareとは?仕組みと無料プランでできること」で紹介しています。

まとめ

  • Cloudflare Tunnelでは、Apacheにつなぐのは同じサーバーの cloudflared なので、そのままだとログは127.0.0.1になる
  • mod_remoteip で CF-Connecting-IP を読み、信頼するのは 127.0.0.1 と ::1 だけにする
  • LogFormat の先頭を %h から %a に変える。combinedio も忘れずに
  • ログに読者のIPアドレスが出ることと、LANから偽のヘッダーを送ってもだまされないことを確かめる
  • 気になる相手を止めるのは、サーバーではなくCloudflareのWAF

コメント