Skip to content

Commit

Permalink
Merge pull request #500 from WTTJ/use-x-forwarded-for-if-defined
Browse files Browse the repository at this point in the history
Use X-Forwarded-For header (if defined) to extract real client IP
  • Loading branch information
mitchellhenke authored Mar 27, 2022
2 parents 9114daa + c2c4608 commit 27f14cf
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 10 deletions.
42 changes: 32 additions & 10 deletions lib/sentry/plug_context.ex
Original file line number Diff line number Diff line change
Expand Up @@ -123,24 +123,46 @@ defmodule Sentry.PlugContext do
cookies: handle_data(conn, cookie_scrubber),
headers: handle_data(conn, header_scrubber),
env: %{
"REMOTE_ADDR" => remote_address(conn.remote_ip),
"REMOTE_PORT" => Plug.Conn.get_peer_data(conn).port,
"REMOTE_ADDR" => remote_address(conn),
"REMOTE_PORT" => remote_port(conn),
"SERVER_NAME" => conn.host,
"SERVER_PORT" => conn.port,
"REQUEST_ID" => Plug.Conn.get_resp_header(conn, request_id) |> List.first()
}
}
end

defp remote_address(address) do
address
|> :inet.ntoa()
|> case do
{:error, _} ->
""
defp remote_address(conn) do
if header_value = get_header(conn, "x-forwarded-for") do
header_value
|> String.split(",")
|> hd()
|> String.trim()
else
conn.remote_ip
|> :inet.ntoa()
|> case do
{:error, _} ->
""

address ->
to_string(address)
end
end
end

defp remote_port(conn) do
if get_header(conn, "x-forwarded-for") do
nil
else
Plug.Conn.get_peer_data(conn).port
end
end

address ->
to_string(address)
def get_header(conn, header) do
case Plug.Conn.get_req_header(conn, header) do
[] -> nil
[val | _] -> val
end
end

Expand Down
29 changes: 29 additions & 0 deletions test/plug_context_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ defmodule Sentry.PlugContextTest do
|> Map.take(["not-secret"])
end

defp add_x_forwarded_for(conn, ip_str) do
%{conn | req_headers: [{"x-forwarded-for", ip_str} | conn.req_headers]}
end

test "sets request context" do
Sentry.PlugContext.call(conn(:get, "/test?hello=world"), [])

Expand All @@ -38,6 +42,31 @@ defmodule Sentry.PlugContextTest do
} = Sentry.Context.get_all()
end

test "sets request context with real client ip if request is forwarded" do
Sentry.PlugContext.call(
conn(:get, "/test?hello=world") |> add_x_forwarded_for("10.0.0.1"),
[]
)

assert %{
request: %{
url: "http://www.example.com/test?hello=world",
method: "GET",
query_string: "hello=world",
data: %{
"hello" => "world"
},
env: %{
"REMOTE_ADDR" => "10.0.0.1",
"REMOTE_PORT" => _,
"REQUEST_ID" => _,
"SERVER_NAME" => "www.example.com",
"SERVER_PORT" => 80
}
}
} = Sentry.Context.get_all()
end

test "allows configuring body scrubber" do
Sentry.PlugContext.call(conn(:get, "/test?hello=world&foo=bar"),
body_scrubber: {__MODULE__, :body_scrubber}
Expand Down

0 comments on commit 27f14cf

Please sign in to comment.