Add Cloudflare header support for real client IP
- Updated IP geolocation to check CF-Connecting-IP header first - Added support for X-Real-IP header as additional fallback - Updated rate limiter to use same header priority for consistency - Headers checked in order: CF-Connecting-IP > X-Forwarded-For > X-Real-IP > remote_ip This ensures proper client IP detection when the site is behind Cloudflare. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
31bd5f5749
commit
fb34553fe9
2 changed files with 36 additions and 7 deletions
|
|
@ -68,12 +68,22 @@ defmodule AprsmeWeb.Plugs.IPGeolocation do
|
|||
end
|
||||
|
||||
defp get_client_ip(conn) do
|
||||
# Check for forwarded IP first (when behind proxy/load balancer)
|
||||
# Check for Cloudflare header first (CF-Connecting-IP)
|
||||
cf_ip = get_req_header(conn, "cf-connecting-ip")
|
||||
|
||||
# Then check for standard forwarded headers
|
||||
forwarded_for = get_req_header(conn, "x-forwarded-for")
|
||||
real_ip = get_req_header(conn, "x-real-ip")
|
||||
|
||||
ip =
|
||||
case forwarded_for do
|
||||
[forwarded | _] ->
|
||||
case {cf_ip, forwarded_for, real_ip} do
|
||||
{[cf | _], _, _} ->
|
||||
# Cloudflare header takes precedence
|
||||
ip_from_cf = String.trim(cf)
|
||||
Logger.info("IP geolocation: Using Cloudflare CF-Connecting-IP: #{ip_from_cf}")
|
||||
ip_from_cf
|
||||
|
||||
{[], [forwarded | _], _} ->
|
||||
# Take the first IP from the X-Forwarded-For header
|
||||
ip_from_header =
|
||||
forwarded
|
||||
|
|
@ -84,7 +94,13 @@ defmodule AprsmeWeb.Plugs.IPGeolocation do
|
|||
Logger.info("IP geolocation: Using forwarded IP from X-Forwarded-For header: #{ip_from_header}")
|
||||
ip_from_header
|
||||
|
||||
[] ->
|
||||
{[], [], [real | _]} ->
|
||||
# Use X-Real-IP header
|
||||
ip_from_real = String.trim(real)
|
||||
Logger.info("IP geolocation: Using X-Real-IP header: #{ip_from_real}")
|
||||
ip_from_real
|
||||
|
||||
{[], [], []} ->
|
||||
# Fall back to remote_ip
|
||||
ip_from_remote =
|
||||
case conn.remote_ip do
|
||||
|
|
|
|||
|
|
@ -40,9 +40,22 @@ defmodule AprsmeWeb.Plugs.RateLimiter do
|
|||
end
|
||||
|
||||
defp get_key(conn, :ip) do
|
||||
case get_req_header(conn, "x-forwarded-for") do
|
||||
[ip | _] -> ip
|
||||
[] -> conn.remote_ip |> :inet.ntoa() |> to_string()
|
||||
# Check headers in order of preference
|
||||
cond do
|
||||
# Cloudflare header takes precedence
|
||||
cf_ip = get_req_header(conn, "cf-connecting-ip") != [] ->
|
||||
hd(cf_ip)
|
||||
|
||||
# Then standard forwarded headers
|
||||
forwarded = get_req_header(conn, "x-forwarded-for") != [] ->
|
||||
forwarded |> hd() |> String.split(",") |> List.first() |> String.trim()
|
||||
|
||||
real_ip = get_req_header(conn, "x-real-ip") != [] ->
|
||||
hd(real_ip)
|
||||
|
||||
# Fall back to remote_ip
|
||||
true ->
|
||||
conn.remote_ip |> :inet.ntoa() |> to_string()
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue