parent
92d08d4113
commit
f9380289eb
@ -0,0 +1,54 @@ |
||||
# Pleroma: A lightweight social networking server |
||||
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/> |
||||
# SPDX-License-Identifier: AGPL-3.0-only |
||||
|
||||
defmodule Pleroma.Plugs.RemoteIp do |
||||
@moduledoc """ |
||||
This is a shim to call [`RemoteIp`](https://git.pleroma.social/pleroma/remote_ip) but with runtime configuration. |
||||
""" |
||||
|
||||
@behaviour Plug |
||||
|
||||
@headers ~w[ |
||||
forwarded |
||||
x-forwarded-for |
||||
x-client-ip |
||||
x-real-ip |
||||
] |
||||
|
||||
# https://en.wikipedia.org/wiki/Localhost |
||||
# https://en.wikipedia.org/wiki/Private_network |
||||
@reserved ~w[ |
||||
127.0.0.0/8 |
||||
::1/128 |
||||
fc00::/7 |
||||
10.0.0.0/8 |
||||
172.16.0.0/12 |
||||
192.168.0.0/16 |
||||
] |
||||
|
||||
def init(_), do: nil |
||||
|
||||
def call(conn, _) do |
||||
config = Pleroma.Config.get(__MODULE__, []) |
||||
|
||||
if Keyword.get(config, :enabled, false) do |
||||
RemoteIp.call(conn, remote_ip_opts(config)) |
||||
else |
||||
conn |
||||
end |
||||
end |
||||
|
||||
defp remote_ip_opts(config) do |
||||
headers = config |> Keyword.get(:headers, @headers) |> MapSet.new() |
||||
reserved = Keyword.get(config, :reserved, @reserved) |
||||
|
||||
proxies = |
||||
config |
||||
|> Keyword.get(:proxies, []) |
||||
|> Enum.concat(reserved) |
||||
|> Enum.map(&InetCidr.parse/1) |
||||
|
||||
{headers, proxies} |
||||
end |
||||
end |
@ -0,0 +1,72 @@ |
||||
# Pleroma: A lightweight social networking server |
||||
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/> |
||||
# SPDX-License-Identifier: AGPL-3.0-only |
||||
|
||||
defmodule Pleroma.Plugs.RemoteIpTest do |
||||
use ExUnit.Case, async: true |
||||
use Plug.Test |
||||
|
||||
alias Pleroma.Plugs.RemoteIp |
||||
|
||||
test "disabled" do |
||||
Pleroma.Config.put(RemoteIp, enabled: false) |
||||
|
||||
%{remote_ip: remote_ip} = conn(:get, "/") |
||||
|
||||
conn = |
||||
conn(:get, "/") |
||||
|> put_req_header("x-forwarded-for", "1.1.1.1") |
||||
|> RemoteIp.call(nil) |
||||
|
||||
assert conn.remote_ip == remote_ip |
||||
end |
||||
|
||||
test "enabled" do |
||||
Pleroma.Config.put(RemoteIp, enabled: true) |
||||
|
||||
conn = |
||||
conn(:get, "/") |
||||
|> put_req_header("x-forwarded-for", "1.1.1.1") |
||||
|> RemoteIp.call(nil) |
||||
|
||||
assert conn.remote_ip == {1, 1, 1, 1} |
||||
end |
||||
|
||||
test "custom headers" do |
||||
Pleroma.Config.put(RemoteIp, enabled: true, headers: ["cf-connecting-ip"]) |
||||
|
||||
conn = |
||||
conn(:get, "/") |
||||
|> put_req_header("x-forwarded-for", "1.1.1.1") |
||||
|> RemoteIp.call(nil) |
||||
|
||||
refute conn.remote_ip == {1, 1, 1, 1} |
||||
|
||||
conn = |
||||
conn(:get, "/") |
||||
|> put_req_header("cf-connecting-ip", "1.1.1.1") |
||||
|> RemoteIp.call(nil) |
||||
|
||||
assert conn.remote_ip == {1, 1, 1, 1} |
||||
end |
||||
|
||||
test "custom proxies" do |
||||
Pleroma.Config.put(RemoteIp, enabled: true) |
||||
|
||||
conn = |
||||
conn(:get, "/") |
||||
|> put_req_header("x-forwarded-for", "173.245.48.1, 1.1.1.1, 173.245.48.2") |
||||
|> RemoteIp.call(nil) |
||||
|
||||
refute conn.remote_ip == {1, 1, 1, 1} |
||||
|
||||
Pleroma.Config.put([RemoteIp, :proxies], ["173.245.48.0/20"]) |
||||
|
||||
conn = |
||||
conn(:get, "/") |
||||
|> put_req_header("x-forwarded-for", "173.245.48.1, 1.1.1.1, 173.245.48.2") |
||||
|> RemoteIp.call(nil) |
||||
|
||||
assert conn.remote_ip == {1, 1, 1, 1} |
||||
end |
||||
end |
Loading…
Reference in new issue