mattintosh note

どこかのエンジニアモドキの備忘録

2024-06-05: 現在ホビー関連の記事を 新しいブログ に移行しています。

XserverとCloudflareの組み合わせでアクセス元のIPアドレスを記録する(Transform Rules編)

先日は PHP で IP アドレスを取得する方法を書いたんですがやはり Xserver(シンレンタルサーバー)純正のログで IP がわからないと困るので何か方法が無いかと考えました。

mattintosh-note.jp

まず、Xserver のログですが Nginx で出力していると思われるのでログフォーマットは恐らく下記のようになっていると思われます。

log_format compression '$host $remote_addr - $remote_user [$time_local] '
                       '"$request" $status $bytes_sent '
                       '"$http_referer" "$http_user_agent"';

www.xserver.ne.jp

で、この中で弄れるとしたら User-Agent で、これを Cloudflare の変換ルールでなんとかしようという話です。

Cloudflare の変換ルールには「スタティック設定(静的)」と「ダイナミック設定(動的)」があります。スタティック設定は名前の通りで値に書いた文字列がそのまま出力されるんですがダイナミック設定の方でなんと Field が使えるらしい。しかも調べたら Function まで使えるっぽい。というわけで User-Agent をカスタマイズすることにした。

最初に concat(http.user_agent, ", ", ip.src) なんて書いたらエラーが出て「あ〜やっぱり使えないのかぁ」と思ったんだけど string 型じゃないものは全部 string 型にしてあげないといけないみたい。リファレンスを見て型を確認しながら式を書く。

developers.cloudflare.com

concat(
    http.user_agent,
    ", ", to_string(ip.src),
    ", ", to_string(ip.src.asnum),
    ", ", ip.src.country,
    ", ", ip.src.region,
    ", ", ip.src.city,
    ", ", to_string(cf.threat_score),
    ", ", to_string(cf.client.bot)
)

| とかもう少しわかりやすいデリミタを使った方がパースし易いとも思ったんだけどとりあえずカンマ区切り。cf.client.bot はログを grep -iv bot とするよりも楽になりそうだったので入れていて、cf.treat_score は興味本位で入れている。cf.ray_id も入れてみたけど UA の集計をするときに一意になってしまうのでやめた。

設定を保存して数秒もすれば Cloudflare を通していても Xserver のログにクライアントの IP アドレスが記録されるようになる。

example.com 172.69.63.27 - - [03/Jul/2024:00:00:00 +0900] "GET /feed/ HTTP/2.0" 200 4388 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:127.0) Gecko/20100101 Firefox/127.0, XXX.XXX.XXX.XXX, 2516, JP, Tokyo, Tokyo, 0, false"

で、設定をしてイベントを見ていたらずっとマネージメントチャレンジに引っかかってる人がいることに気づいた。自分もシークレットウィンドウで試してみたらチャレンジがループする状態になっていた。

やっぱり無理なのかなぁと思ってリファレンスを読んでいたらどうも変換ルールを使うとチャレンジのループが発生してしまうことがあるらしい。

Using Cloudflare challenges along with Rules features such as Transform Rules may cause challenge loops. Refer to Rules troubleshooting for more information.
Cloudflare チャレンジを、Transform Rules などのルール機能と一緒に使用すると、チャレンジ ループが発生する可能性があります。詳細については、ルールのトラブルシューティングを参照してください。
https://developers.cloudflare.com/rules/transform/

解決方法は starts_with()/cdn-cgi/challenge-platform/ へのリクエストを除外することらしい。

If you are issuing a challenge for a given URI path that has one or more Rules features enabled, you should exclude URI paths starting with /cdn-cgi/challenge-platform/ in your rule expressions to avoid challenge loops.
https://developers.cloudflare.com/rules/reference/troubleshooting/

なので「すべての受信リクエスト」を止めて「カスタム フィルタ式」で /cdn-cgi/challenge-platform/ から始まるリクエストの場合は変換をしないようにする。

Cloudflare - Transform Rules
Cloudflare - Transform Rules

not starts_with(http.request.uri, "/cdn-cgi/challenge-platform/")

もう一度シークレットウィンドウで試してみたところ正常に検証が完了し、UA の書き換えも行われている状態になった。よかったよかった。