Fix agent IP detection to use real client IP from proxy headers
The agent's last_seen IP was showing the Docker container IP (10.244.x.x) because conn.remote_ip returns the proxy/load balancer IP. Changes: - Added get_client_ip/1 helper that checks X-Forwarded-For first - Falls back to X-Real-IP if X-Forwarded-For not present - Falls back to conn.remote_ip as last resort - Applied to both AgentAuth plug and AgentController heartbeat endpoint Now correctly shows the actual external IP of the remote agent.
This commit is contained in:
parent
0ed82c47b9
commit
31b906b0fa
2 changed files with 52 additions and 2 deletions
|
|
@ -91,7 +91,7 @@ defmodule ToweropsWeb.Api.AgentController do
|
|||
"""
|
||||
def heartbeat(conn, params) do
|
||||
agent_token = conn.assigns.current_agent_token
|
||||
ip = to_string(:inet_parse.ntoa(conn.remote_ip))
|
||||
ip = get_client_ip(conn)
|
||||
|
||||
# Parse metadata based on content type
|
||||
metadata =
|
||||
|
|
@ -320,4 +320,29 @@ defmodule ToweropsWeb.Api.AgentController do
|
|||
defp convert_metadata_to_proto(metadata) when is_map(metadata) do
|
||||
Map.new(metadata, fn {k, v} -> {to_string(k), to_string(v)} end)
|
||||
end
|
||||
|
||||
# Get the real client IP, checking forwarded headers first
|
||||
defp get_client_ip(conn) do
|
||||
# Check X-Forwarded-For header first (set by load balancers/proxies)
|
||||
case get_req_header(conn, "x-forwarded-for") do
|
||||
[forwarded | _] ->
|
||||
# X-Forwarded-For can have multiple IPs (client, proxy1, proxy2...)
|
||||
# Take the first one (original client)
|
||||
forwarded
|
||||
|> String.split(",")
|
||||
|> List.first()
|
||||
|> String.trim()
|
||||
|
||||
[] ->
|
||||
# Fall back to X-Real-IP
|
||||
case get_req_header(conn, "x-real-ip") do
|
||||
[real_ip | _] ->
|
||||
String.trim(real_ip)
|
||||
|
||||
[] ->
|
||||
# Fall back to conn.remote_ip
|
||||
to_string(:inet_parse.ntoa(conn.remote_ip))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ defmodule ToweropsWeb.Plugs.AgentAuth do
|
|||
end
|
||||
|
||||
defp update_heartbeat(conn, agent_token) do
|
||||
ip = to_string(:inet_parse.ntoa(conn.remote_ip))
|
||||
ip = get_client_ip(conn)
|
||||
|
||||
# In test environment, update synchronously to avoid DB ownership issues
|
||||
# In production, update asynchronously for better performance
|
||||
|
|
@ -55,6 +55,31 @@ defmodule ToweropsWeb.Plugs.AgentAuth do
|
|||
conn
|
||||
end
|
||||
|
||||
# Get the real client IP, checking forwarded headers first
|
||||
defp get_client_ip(conn) do
|
||||
# Check X-Forwarded-For header first (set by load balancers/proxies)
|
||||
case get_req_header(conn, "x-forwarded-for") do
|
||||
[forwarded | _] ->
|
||||
# X-Forwarded-For can have multiple IPs (client, proxy1, proxy2...)
|
||||
# Take the first one (original client)
|
||||
forwarded
|
||||
|> String.split(",")
|
||||
|> List.first()
|
||||
|> String.trim()
|
||||
|
||||
[] ->
|
||||
# Fall back to X-Real-IP
|
||||
case get_req_header(conn, "x-real-ip") do
|
||||
[real_ip | _] ->
|
||||
String.trim(real_ip)
|
||||
|
||||
[] ->
|
||||
# Fall back to conn.remote_ip
|
||||
to_string(:inet_parse.ntoa(conn.remote_ip))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
defp update_heartbeat_async(agent_token_id, ip) do
|
||||
parent = self()
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue