bokumin.org

Github

CloudflareでApacheログに実IPを記録する

Apache Real IP Logging with Cloudflare

 

はじめに

 

Cloudflareのレコードでプロキシを有効にすると、Cloudflareがリバースプロキシとして動作します。その結果、ApacheなどのWebサーバーログにはCloudflareのIPアドレスのみが記録されてしまい、fail2banやその他のアクセス制御が困難になります。

 

Cloudflare上でもブロック設定は可能ですが、本記事ではApache側で実際のクライアントIPアドレスを記録する設定方法を紹介します。

 

検証環境

 

OpenSUSE、Apacheのバージョンは以下になっています。

 

uname -a
Linux 6.17.0-2-default #1 SMP PREEMPT_DYNAMIC Thu Oct  2 08:12:40 UTC 2025 (190326b) x86_64 x86_64 x86_64 GNU/Linux

sudo apachectl -v
[sudo] password for root: 
Server version: Apache/2.4.65 (Linux/SUSE)
Server built:   2025-09-23 13:42:03.000000000 +0000

 

設定手順

 

まず、mod_remoteip モジュールを有効化します。

 

sudo a2enmod remoteip

sudo systemctl restart apache2

sudo apachectl -M | grep remoteip
 remoteip_module (shared)

 

/etc/apache2/conf.d/にcloudflare用の設定ファイルを作成します。

 

  • CF-Connecting-IP → Cloudflareが送信する実際のクライアントIPアドレスを取得するヘッダー
  • RemoteIPTrustedProxy → 信頼されたプロキシとして登録するIPアドレス範囲

 

# cat /etc/apache2/conf.d/cloudflare.conf 
<IfModule remoteip_module>
    RemoteIPHeader CF-Connecting-IP
    
    RemoteIPTrustedProxy 173.245.48.0/20
    RemoteIPTrustedProxy 103.21.244.0/22
    RemoteIPTrustedProxy 103.22.200.0/22
    RemoteIPTrustedProxy 103.31.4.0/22
    RemoteIPTrustedProxy 141.101.64.0/18
    RemoteIPTrustedProxy 108.162.192.0/18
    RemoteIPTrustedProxy 190.93.240.0/20
    RemoteIPTrustedProxy 188.114.96.0/20
    RemoteIPTrustedProxy 197.234.240.0/22
    RemoteIPTrustedProxy 198.41.128.0/17
    RemoteIPTrustedProxy 162.158.0.0/15
    RemoteIPTrustedProxy 104.16.0.0/13
    RemoteIPTrustedProxy 104.24.0.0/14
    RemoteIPTrustedProxy 172.64.0.0/13
    RemoteIPTrustedProxy 131.0.72.0/22
</IfModule>

 

mod_log_config.confを修正していきます。デフォルトが%hになっていると思いますので、そこを%aにしていきます。

 

  • %h → リモートホストネーム(または逆引きされたホスト名)
  • %a → クライアントのIPアドレス(mod_remoteip使用時は実IPになる)

 

cat /etc/apache2/mod_log_config.conf 
#
# The following directives define some format nicknames for use with
# a CustomLog directive.
#
# https://httpd.apache.org/docs/2.4/mod/mod_log_config.html
#

#
#         Format string:                                Nickname:
#
LogFormat "%a %l %u %t \"%r\" %>s %b"                   common
LogFormat "%v %a %l %u %t \"%r\" %>s %b"                vhost_common
LogFormat "%{Referer}i -> %U"                           referer
LogFormat "%{User-agent}i"                              agent
LogFormat "%a %l %u %t \"%r\" %>s %b \
\"%{Referer}i\" \"%{User-Agent}i\""                     combined
LogFormat "%v %a %l %u %t \"%r\" %>s %b \
\"%{Referer}i\" \"%{User-Agent}i\""                     vhost_combined

# To use %I and %O, you need to enable mod_logio
<IfModule mod_logio.c>
LogFormat "%h %a %u %t \"%r\" %>s %b \
\"%{Referer}i\" \"%{User-Agent}i\" %I %O"               combinedio
</IfModule>

# Use one of these when you want a compact non-error SSL logfile on a virtual
# host basis:`
<IfModule mod_ssl.c>
Logformat "%t %a %{SSL_PROTOCOL}x %{SSL_CIPHER}x \
\"%r\" %b"                                              ssl_common
Logformat "%t %a %{SSL_PROTOCOL}x %{SSL_CIPHER}x \
\"%r\" %b \"%{Referer}i\" \"%{User-Agent}i\""           ssl_combined
</IfModule>

 

設定変更後、Apacheのreloadを行います。
ログを確認し、実際のクライアントIPアドレスが記録されていれば成功です。

 

tail /var/log/apache2/access.log

xx.xx.x.xx - - [10/Nov/2025:11:21:57 +0900] "GET /robots.txt HTTP/1.1" 301 238 "-" "Mozilla/5.0 (compatible; MJ12bot/v1.4.8; http://mj12bot.com/)"
xx.xx.x.xx - - [10/Nov/2025:11:22:04 +0900] "GET /art-works/index.php?/search/psk-20250806-5eNDVvVRuC/created-weekly-list HTTP/1.1" 301 299 "-" "Mozilla/5.0 (compatible; MJ12bot/v1.4.8; http://mj12bot.com/)"
xx.xxx.xxx.xxx - - [10/Nov/2025:11:25:50 +0900] "GET /blog/2024/10/17/%E3%83%A1%E3%83%87%E3%82%A3%E3%82%A2%E3%82%B5%E3%83%BC%E3%83%90%E3%83%BC%EF%BC%88jellyfin%EF%BC%89%E3%82%92linux%E4%B8%8A%E3%81%A7%E6%A7%8B%E7%AF%89%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95/ HTTP/1.1" 301 429 "-" "Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm) Chrome/116.0.1938.76 Safari/537.36"
xx.xxx.xxx.xxx - - [10/Nov/2025:11:27:01 +0900] "GET /art-works/picture.php?%2F6%2Ftags%2F3-sleepy%2F6-wallpaper%2F8-illust%2Fposted-monthly-list-2024-10-17 HTTP/1.1" 301 330 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Brave Chrome/85.0.4183.83 Safari/537.36"

 

CloudflareのIPレンジは定期的に変更されるため、自動更新スクリプトを作成しておくと便利です。

 

 cat /root/bin/add_cloudflare.sh 
#!/bin/bash
# /usr/local/bin/update-cloudflare-ips.sh

CF_CONF="/etc/apache2/conf.d/cloudflare.conf"

IPV4=$(curl -s https://www.cloudflare.com/ips-v4)

cat > $CF_CONF << 'EOF'
<IfModule remoteip_module>
    RemoteIPHeader CF-Connecting-IP
    
EOF

for ip in $IPV4; do
    echo "    RemoteIPTrustedProxy $ip" >> $CF_CONF
done

echo "</IfModule>" >> $CF_CONF

apachectl configtest && systemctl reload apache2
Tomoko:/etc/apache2 # 

 

このスクリプトを月1回程度cronで実行するように設定しておけば、常に最新のCloudflare IPレンジを維持できます。

 

まとめ

 

以上、Cloudflare経由でもApacheログに実IPを記録する方法でした。

 

おわり

 

参考にした記事:
https://developers.cloudflare.com/fundamentals/reference/http-headers/
https://zenn.dev/muchoco/articles/7ea510e0c285a7