Hey there, is there a function in phoenix where I can get the users ip address? I’d like to build a clone of whatsmyip
Conn.remote_ip will give you the goods.
Also recommend you use remote_ip | Hex
You should inspect conn, because You can get ip from multiple attributes.
remote_ip, as mentionned in the previous response, but also x-forwarded-for, x-real-ip
But these are just good old HTTP headers. Everyone can proxy through a VPS and spoof the headers so they frame somebody else’s IP.
I wouldn’t use them unless they can be cryptographically verified to come from they’re claiming to come.
Yes it can be spoofed, but I meant relying on remote_ip only might give You the address of a proxy
so when the user enters I page, I do something like conn.send_resp(200, “…”), how can I display the users IP there? instead of the string message just put conn
in there? or bind it to a variable and use that instead?
Maybe like this to debug the conn…
You might also check if You use a proxy in front of the application.
conn.send_resp(200, inspect conn)
Get the IP as mentioned above, convert it to a string and send it.
2 things.
-
Are you using a LiveView or a simple Controller+Template? If using a LiveView, you should copy the remote_ip from conn to socket assigns.
-
Are you going to deploy this? Depending on what deployment service you use (Fly, Gigalixir, Heroku, etc) you might need to find the IP address some other way. Often these services see
conn.remote_ip
as something in their private network, but the real public IP of the request will be in some special header. For example, Fly uses"Fly-Client-IP
.
yea fly, most likely, how do I have to do that then?
Well, a nice simple way is:
-
add
remote_ip
to your deps -
mix deps.get
-
Add this to your
endpoint.ex
module:
plug RemoteIp, headers: ["fly-client-ip"]
Update: if you’re using live view, you will have to get this remote IP from the conn
into your socket assigns
. If that doesn’t make sense to you, then you need to read about the on_mount
function in LiveView. That will be your friend for this job.
here: Phoenix.LiveView — Phoenix LiveView v0.18.2
I think that the following post is a must-read, especially for the project in question:
One question, wouldn’t the live view peer data solve it?
https://hexdocs.pm/phoenix_live_view/Phoenix.LiveView.html#get_connect_info/2-examples
I currently have an application on google cloud run, but my socket.assigns.peer_data.address is returning an IP from the internal network ex: 169.169.1.1
How would you get the user’s real IP?
I even found something here Cloud Run Client Request IP address gets overridden by proxy Python Fast API - Stack Overflow, saying to change the code to return the X-Forwarded-For?
Has anyone ever experienced this?
I was able to identify a cause.
I was getting the wrong key.
In case I need to get the x_headers
The problem is that every proxy in front does its own magic and there is no real “standard”. And you could (theoretically) have multiple layers of proxies in front. RemoteIp
tries the common cases for you so you don’t have to go nuts, but it’s not 100% bullet-proof. In general, if you see anything strange, you have to dump conn and see what’s in there.
During the first mount/3
call (for the server-side render before a websocket is established), that works.
However, for the second call to mount/3
(when the actual LiveView socket is established), that fails, with get_connect_info(socket, :peer_data)
returning nil
. (And it seems that the socket assigns are cleared at some point between these calls…)
Did you adjust the socket line, so it retains the peer_data?
https://hexdocs.pm/phoenix_live_view/Phoenix.LiveView.html#get_connect_info/2-examples