如何从凤凰框架中的套接字获取remote_ip?

czi*_*mba 5 sockets ip elixir phoenix-framework

如何从phoenixframework中的套接字获取remote_ip?我可以从View中的conn中获得它,但不能从Channel中获得它。

非常感谢您的帮助!

Vic*_*nov 5

此处提供的答案副本: https: //elixirforum.com/t/phoenix-socket-channels-security-ip-identification/1463/3(所有功劳都归于https://elixirforum.com/u/arjan

凤凰1.4更新:

从 Phoenix 1.4 开始,您可以从底层传输获取连接信息。您获得的信息类型取决于传输,但通过 WebSocket 传输,可以检索对等信息(IP 地址)和 x- 标头列表(用于 x-forwarded-for 解析)。

在你的endpoint.ex中像这样配置你的套接字:

socket("/socket", MyApp.Web.UserSocket,
  websocket: [connect_info: [:peer_data, :x_headers]],
  longpoll: [connect_info: [:peer_data, :x_headers]]
)
Run Code Online (Sandbox Code Playgroud)

然后你的 UserSocket 模块必须公开一个 connect/3 函数,如下所示:

def connect(_params, socket, connect_info) do
  {:ok, socket}
end
Run Code Online (Sandbox Code Playgroud)

连接时,connect_info 参数现在包含来自传输的信息:

info: %{
  peer_data: %{address: {127, 0, 0, 1}, port: 52372, ssl_cert: nil},
  x_headers: []
}
Run Code Online (Sandbox Code Playgroud)

更新

如果您的 Phoenix 应用程序不直接处理流量,而是从反向代理(如 nginx)接收流量,那么peer_data将拥有 nginx IP 地址,而不是客户端的 IP 地址。要解决此问题,您可以告诉 nginx(或您使用的任何代理)在标头中传递原始 IP,然后稍后读取它。

所以你的凤凰城位置应该是这样的:

location /phoenix/ {
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_redirect off;
    proxy_pass http://phoenix/;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "Upgrade";
}
Run Code Online (Sandbox Code Playgroud)

你的套接字代码应该有这样的:

defp get_ip_address(%{x_headers: headers_list}) do
  header = Enum.find(headers_list, fn {key, _val} -> key == "x-real-ip" end)

  case header do
    nil ->
      nil

    {_key, value} ->
      value

    _ ->
      nil
  end
end

defp get_ip_address(_) do
  nil
end
Run Code Online (Sandbox Code Playgroud)

并改变连接到这样的东西

def connect(params, socket, connect_info) do
  socket = assign(socket, :ip_address, get_ip_address(connect_info))
  {:ok, socket}      
end
Run Code Online (Sandbox Code Playgroud)


Jos*_*lim 4

现在的答案是:你不能。您无法访问通道中的连接,因为通道与传输无关。在 Phoenix 中提出一个问题,详细说明您的用户案例,以便 Phoenix 团队可以采取行动。