tmate-io / tmate-websocket

16 stars 13 forks source link

Please honor HTTP header "X-Real-IP" when it exists #5

Open pini-gh opened 3 years ago

pini-gh commented 3 years ago

HI,

My tmate instance sits behind an Nginx reverse proxy, and tmate-websocket reports the proxy's IP address instead of the client's.

I can't use proxy protocol, but the HTTP header X-Real-IP is set. It would be great if tmate-websocket could use it when available.

Looking at the code, it might be just a one line addition iinto lib/tmate/ws_api/websocket.ex:

diff --git a/lib/tmate/ws_api/websocket.ex b/lib/tmate/ws_api/websocket.ex
index 2d667fd..f502091 100644
--- a/lib/tmate/ws_api/websocket.ex
+++ b/lib/tmate/ws_api/websocket.ex
@@ -26,6 +26,7 @@ defmodule Tmate.WsApi.WebSocket do
               :ok ->
                 ip = case req do
                   %{proxy_header: %{src_address: ip}} -> ip
+                  %{headers: %{"x-real-ip" => ip}} -> ip
                   %{peer: {ip, _port}} -> ip
                 end
                 ip = :inet_parse.ntoa(ip) |> to_string

Please bear with me as I don't know Elixir, Phoenix, cowboy et al. I spent some time digging into the source code and reading documentation, but this patch proposal is just a wild guess. I don't even know how to build the app.

Anyway. In case this is something as simple as that, this fix would be very much appreciated.

Thanks in advance.

pini-gh commented 3 years ago

I've successfully tested this patch:

diff --git a/lib/tmate/ws_api/websocket.ex b/lib/tmate/ws_api/websocket.ex
index 2d667fd..2673f5d 100644
--- a/lib/tmate/ws_api/websocket.ex
+++ b/lib/tmate/ws_api/websocket.ex
@@ -26,6 +26,9 @@ defmodule Tmate.WsApi.WebSocket do
               :ok ->
                 ip = case req do
                   %{proxy_header: %{src_address: ip}} -> ip
+                  %{headers: %{"x-real-ip" => ipstring}} ->
+                    {_, ip} = :inet.parse_address(ipstring |> to_charlist)
+                    ip
                   %{peer: {ip, _port}} -> ip
                 end
                 ip = :inet_parse.ntoa(ip) |> to_string

Not sure this is the best way of doing it, but it works for me. Would you consider such a PR?