Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

remote_ip not overwritten from X-Forwarded-For #319

Closed
esdrasedu opened this issue Dec 2, 2015 · 8 comments
Closed

remote_ip not overwritten from X-Forwarded-For #319

esdrasedu opened this issue Dec 2, 2015 · 8 comments

Comments

@esdrasedu
Copy link

In the docs say:

screen shot 2015-12-02 at 12 13 12 pm

But it not doing that. I don know if if is change on Cowboy or if is implementation incomplete on Plug.Conn

Versions:
OS: Darwin 15.0.0
Elixir: 1.1.1
Erlang/OTP: 18
Plug: 1.0.3

@josevalim
Copy link
Member

It is meant to be overridden by plugs. We don't provide the feature that overrides it, it is up to you.

@micahwedemeyer
Copy link

In case anyone else is still looking for this, I found this project today: https://github.com/awetzel/plug_forwarded_peer

It looks like it's a plug to do exactly what is desired here.

@esdrasedu
Copy link
Author

Thanks @micahwedemeyer , I make plug too:

  import Plug.Conn

  def init(opts), do: opts

  def call(conn, _opts) do
    ip = case get_req_header(conn, "x-forwarded-for") do
       [proxy_ip] -> proxy_ip |> first_ip |> valid_ip
       _ -> conn.remote_ip |> Tuple.to_list |> Enum.join(".") |> valid_ip
    end
    conn |> assign(:ip, ip)
  end

  defp first_ip(ips) do
    case String.split(ips, ",") do
      [ip] -> ip
      [ip, _proxy_ip] -> ip
    end
  end

  defp valid_ip(ip) do
    re = ~r/^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$/
    case Regex.match?(re, ip) do
      true -> ip
      false -> nil
    end
  end

But need fixes, I will look is other plug! Thanks again

@MSch
Copy link
Contributor

MSch commented Sep 13, 2016

If anyone needs it, here's what we do:

defmodule RemoteIPPlug do
  @behaviour Plug
  import Plug.Conn

  def init([]), do: []

  def call(conn, []) do
    case get_req_header(conn, "x-real-ip") do
      [] -> conn
      [real_ip] ->
        case :inet_parse.address(to_char_list(real_ip)) do
          {:ok, real_ip} -> %{conn | remote_ip: real_ip}
          _ -> conn
        end
    end
  end
end

@ajvondrak
Copy link

I recently came across this issue and went down the rabbit hole of figuring out how to get this working, resulting in Yet Another Package™. For visibility / in case it helps anyone: https://github.com/ajvondrak/remote_ip

@josevalim
Copy link
Member

Btw, the reason we don't override remote_ip by default is because doing so without actually having a proxy in front of you is a security risk (it can lead to ip-spoofing for example).

@ajvondrak
Copy link

Yup. Noted that in my README.md. :)

@JustMikey
Copy link

Just wanted to point out that at least x-forwarded-for may have 2 or 3 values in the list, so be careful because it may break your pattern matching if it's not handling this case.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants