Use upstream remote_ip package
This commit is contained in:
parent
2db3a9c04d
commit
c92d233233
7 changed files with 85 additions and 10 deletions
1
changelog.d/remote-ip-hex.change
Normal file
1
changelog.d/remote-ip-hex.change
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
Use upstream Hex releases for the `remote_ip` dependency and expose client IP ranges for remote IP resolution.
|
||||||
|
|
@ -738,6 +738,7 @@ config :pleroma, Pleroma.Workers.PurgeExpiredActivity, enabled: true, min_lifeti
|
||||||
config :pleroma, Pleroma.Web.Plugs.RemoteIp,
|
config :pleroma, Pleroma.Web.Plugs.RemoteIp,
|
||||||
enabled: true,
|
enabled: true,
|
||||||
headers: ["x-forwarded-for"],
|
headers: ["x-forwarded-for"],
|
||||||
|
clients: [],
|
||||||
proxies: [],
|
proxies: [],
|
||||||
reserved: [
|
reserved: [
|
||||||
"127.0.0.0/8",
|
"127.0.0.0/8",
|
||||||
|
|
|
||||||
|
|
@ -2910,7 +2910,7 @@ config :pleroma, :config_description, [
|
||||||
key: Pleroma.Web.Plugs.RemoteIp,
|
key: Pleroma.Web.Plugs.RemoteIp,
|
||||||
type: :group,
|
type: :group,
|
||||||
description: """
|
description: """
|
||||||
`Pleroma.Web.Plugs.RemoteIp` is a shim to call [`RemoteIp`](https://git.pleroma.social/pleroma/remote_ip) but with runtime configuration.
|
`Pleroma.Web.Plugs.RemoteIp` is a shim to call [`RemoteIp`](https://hex.pm/packages/remote_ip) but with runtime configuration.
|
||||||
**If your instance is not behind at least one reverse proxy, you should not enable this plug.**
|
**If your instance is not behind at least one reverse proxy, you should not enable this plug.**
|
||||||
""",
|
""",
|
||||||
children: [
|
children: [
|
||||||
|
|
@ -2926,6 +2926,12 @@ config :pleroma, :config_description, [
|
||||||
A list of strings naming the HTTP headers to use when deriving the true client IP. Default: `["x-forwarded-for"]`.
|
A list of strings naming the HTTP headers to use when deriving the true client IP. Default: `["x-forwarded-for"]`.
|
||||||
"""
|
"""
|
||||||
},
|
},
|
||||||
|
%{
|
||||||
|
key: :clients,
|
||||||
|
type: {:list, :string},
|
||||||
|
description:
|
||||||
|
"A list of client IPs or subnets in CIDR notation. These will not be treated as proxies or reserved ranges. Defaults to `[]`. IPv4 entries without a bitmask will be assumed to be /32 and IPv6 /128."
|
||||||
|
},
|
||||||
%{
|
%{
|
||||||
key: :proxies,
|
key: :proxies,
|
||||||
type: {:list, :string},
|
type: {:list, :string},
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
defmodule Pleroma.Web.Plugs.RemoteIp do
|
defmodule Pleroma.Web.Plugs.RemoteIp do
|
||||||
@moduledoc """
|
@moduledoc """
|
||||||
This is a shim to call [`RemoteIp`](https://git.pleroma.social/pleroma/remote_ip) but with runtime configuration.
|
This is a shim to call [`RemoteIp`](https://hex.pm/packages/remote_ip) but with runtime configuration.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
alias Pleroma.Config
|
alias Pleroma.Config
|
||||||
|
|
@ -17,15 +17,29 @@ defmodule Pleroma.Web.Plugs.RemoteIp do
|
||||||
|
|
||||||
def call(%{remote_ip: original_remote_ip} = conn, _) do
|
def call(%{remote_ip: original_remote_ip} = conn, _) do
|
||||||
if Config.get([__MODULE__, :enabled]) do
|
if Config.get([__MODULE__, :enabled]) do
|
||||||
%{remote_ip: new_remote_ip} = conn = RemoteIp.call(conn, remote_ip_opts())
|
new_remote_ip = remote_ip(conn) || original_remote_ip
|
||||||
|
|
||||||
|
conn = %{conn | remote_ip: new_remote_ip}
|
||||||
assign(conn, :remote_ip_found, original_remote_ip != new_remote_ip)
|
assign(conn, :remote_ip_found, original_remote_ip != new_remote_ip)
|
||||||
else
|
else
|
||||||
conn
|
conn
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp remote_ip(conn) do
|
||||||
|
opts = remote_ip_opts()
|
||||||
|
|
||||||
|
# Do not use RemoteIp.from/2 here: upstream remote_ip always applies its
|
||||||
|
# built-in reserved ranges. Pleroma keeps :reserved configurable, so reuse
|
||||||
|
# only the header parsing and apply Pleroma's own block classification.
|
||||||
|
conn.req_headers
|
||||||
|
|> RemoteIp.Headers.take(opts[:headers])
|
||||||
|
|> RemoteIp.Headers.parse()
|
||||||
|
|> Enum.reverse()
|
||||||
|
|> Enum.find(&client?(&1, opts))
|
||||||
|
end
|
||||||
|
|
||||||
defp remote_ip_opts do
|
defp remote_ip_opts do
|
||||||
headers = Config.get([__MODULE__, :headers], []) |> MapSet.new()
|
|
||||||
reserved = Config.get([__MODULE__, :reserved], [])
|
reserved = Config.get([__MODULE__, :reserved], [])
|
||||||
|
|
||||||
proxies =
|
proxies =
|
||||||
|
|
@ -33,6 +47,26 @@ defmodule Pleroma.Web.Plugs.RemoteIp do
|
||||||
|> Enum.concat(reserved)
|
|> Enum.concat(reserved)
|
||||||
|> Enum.map(&InetHelper.parse_cidr/1)
|
|> Enum.map(&InetHelper.parse_cidr/1)
|
||||||
|
|
||||||
{headers, proxies}
|
clients =
|
||||||
|
Config.get([__MODULE__, :clients], [])
|
||||||
|
|> Enum.map(&InetHelper.parse_cidr/1)
|
||||||
|
|
||||||
|
[
|
||||||
|
headers: Config.get([__MODULE__, :headers], []),
|
||||||
|
clients: clients,
|
||||||
|
proxies: proxies
|
||||||
|
]
|
||||||
|
end
|
||||||
|
|
||||||
|
defp client?(ip, opts) do
|
||||||
|
client_ip?(ip, opts[:clients]) || !proxy_ip?(ip, opts[:proxies])
|
||||||
|
end
|
||||||
|
|
||||||
|
defp client_ip?(ip, clients) do
|
||||||
|
Enum.any?(clients, &InetCidr.contains?(&1, ip))
|
||||||
|
end
|
||||||
|
|
||||||
|
defp proxy_ip?(ip, proxies) do
|
||||||
|
Enum.any?(proxies, &InetCidr.contains?(&1, ip))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
5
mix.exs
5
mix.exs
|
|
@ -182,9 +182,8 @@ defmodule Pleroma.Mixfile do
|
||||||
{:plug_static_index_html, "~> 1.0.0"},
|
{:plug_static_index_html, "~> 1.0.0"},
|
||||||
{:flake_id, "~> 0.1.0"},
|
{:flake_id, "~> 0.1.0"},
|
||||||
{:concurrent_limiter, "~> 0.1.1"},
|
{:concurrent_limiter, "~> 0.1.1"},
|
||||||
{:remote_ip,
|
{:remote_ip, "~> 1.2.0"},
|
||||||
git: "https://git.pleroma.social/pleroma/remote_ip.git",
|
{:inet_cidr, "~> 1.0"},
|
||||||
ref: "b647d0deecaa3acb140854fe4bda5b7e1dc6d1c8"},
|
|
||||||
{:captcha,
|
{:captcha,
|
||||||
git: "https://git.pleroma.social/pleroma/elixir-libraries/elixir-captcha.git",
|
git: "https://git.pleroma.social/pleroma/elixir-libraries/elixir-captcha.git",
|
||||||
ref: "e7b7cc34cc16b383461b966484c297e4ec9aeef6"},
|
ref: "e7b7cc34cc16b383461b966484c297e4ec9aeef6"},
|
||||||
|
|
|
||||||
4
mix.lock
4
mix.lock
|
|
@ -65,7 +65,7 @@
|
||||||
"http_signatures": {:hex, :http_signatures, "0.1.3", "19f26aee35b4684e37efdce3ac4638605e6e41a04368186bd39d2b6138a60ea9", [:mix], [{:plug, "~> 1.18", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "20313a65516db88006f85b090f6f76cc5b04e9609b45943657e6781eb91174f4"},
|
"http_signatures": {:hex, :http_signatures, "0.1.3", "19f26aee35b4684e37efdce3ac4638605e6e41a04368186bd39d2b6138a60ea9", [:mix], [{:plug, "~> 1.18", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "20313a65516db88006f85b090f6f76cc5b04e9609b45943657e6781eb91174f4"},
|
||||||
"httpoison": {:hex, :httpoison, "1.8.2", "9eb9c63ae289296a544842ef816a85d881d4a31f518a0fec089aaa744beae290", [:mix], [{:hackney, "~> 1.17", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "2bb350d26972e30c96e2ca74a1aaf8293d61d0742ff17f01e0279fef11599921"},
|
"httpoison": {:hex, :httpoison, "1.8.2", "9eb9c63ae289296a544842ef816a85d881d4a31f518a0fec089aaa744beae290", [:mix], [{:hackney, "~> 1.17", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "2bb350d26972e30c96e2ca74a1aaf8293d61d0742ff17f01e0279fef11599921"},
|
||||||
"idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"},
|
"idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"},
|
||||||
"inet_cidr": {:hex, :inet_cidr, "1.0.8", "d26bb7bdbdf21ae401ead2092bf2bb4bf57fe44a62f5eaa5025280720ace8a40", [:mix], [], "hexpm", "d5b26da66603bb56c933c65214c72152f0de9a6ea53618b56d63302a68f6a90e"},
|
"inet_cidr": {:hex, :inet_cidr, "1.0.9", "e0ef72a2942529da78c8e4147d53f2ef5f6f5293335c3637b0fdf83c012cc816", [:mix], [], "hexpm", "172da15ff7cf635b1feaf14f5818be28c811b37cc5fb7c5f7c01058c1c1066cc"},
|
||||||
"jason": {:hex, :jason, "1.4.4", "b9226785a9aa77b6857ca22832cffa5d5011a667207eb2a0ad56adb5db443b8a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "c5eb0cab91f094599f94d55bc63409236a8ec69a21a67814529e8d5f6cc90b3b"},
|
"jason": {:hex, :jason, "1.4.4", "b9226785a9aa77b6857ca22832cffa5d5011a667207eb2a0ad56adb5db443b8a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "c5eb0cab91f094599f94d55bc63409236a8ec69a21a67814529e8d5f6cc90b3b"},
|
||||||
"joken": {:hex, :joken, "2.6.2", "5daaf82259ca603af4f0b065475099ada1b2b849ff140ccd37f4b6828ca6892a", [:mix], [{:jose, "~> 1.11.10", [hex: :jose, repo: "hexpm", optional: false]}], "hexpm", "5134b5b0a6e37494e46dbf9e4dad53808e5e787904b7c73972651b51cce3d72b"},
|
"joken": {:hex, :joken, "2.6.2", "5daaf82259ca603af4f0b065475099ada1b2b849ff140ccd37f4b6828ca6892a", [:mix], [{:jose, "~> 1.11.10", [hex: :jose, repo: "hexpm", optional: false]}], "hexpm", "5134b5b0a6e37494e46dbf9e4dad53808e5e787904b7c73972651b51cce3d72b"},
|
||||||
"jose": {:hex, :jose, "1.11.10", "a903f5227417bd2a08c8a00a0cbcc458118be84480955e8d251297a425723f83", [:mix, :rebar3], [], "hexpm", "0d6cd36ff8ba174db29148fc112b5842186b68a90ce9fc2b3ec3afe76593e614"},
|
"jose": {:hex, :jose, "1.11.10", "a903f5227417bd2a08c8a00a0cbcc458118be84480955e8d251297a425723f83", [:mix, :rebar3], [], "hexpm", "0d6cd36ff8ba174db29148fc112b5842186b68a90ce9fc2b3ec3afe76593e614"},
|
||||||
|
|
@ -132,7 +132,7 @@
|
||||||
"quic": {:hex, :quic, "0.10.2", "4b390507a85f65ce47808f3df1a864e0baf9adb7a1b4ea9f4dcd66fe9d0cb166", [:rebar3], [], "hexpm", "7c196a66973c877a59768a5687f0a0610ff11817254d0a4e45cc4e3a16b1d00b"},
|
"quic": {:hex, :quic, "0.10.2", "4b390507a85f65ce47808f3df1a864e0baf9adb7a1b4ea9f4dcd66fe9d0cb166", [:rebar3], [], "hexpm", "7c196a66973c877a59768a5687f0a0610ff11817254d0a4e45cc4e3a16b1d00b"},
|
||||||
"ranch": {:hex, :ranch, "2.2.0", "25528f82bc8d7c6152c57666ca99ec716510fe0925cb188172f41ce93117b1b0", [:make, :rebar3], [], "hexpm", "fa0b99a1780c80218a4197a59ea8d3bdae32fbff7e88527d7d8a4787eff4f8e7"},
|
"ranch": {:hex, :ranch, "2.2.0", "25528f82bc8d7c6152c57666ca99ec716510fe0925cb188172f41ce93117b1b0", [:make, :rebar3], [], "hexpm", "fa0b99a1780c80218a4197a59ea8d3bdae32fbff7e88527d7d8a4787eff4f8e7"},
|
||||||
"recon": {:hex, :recon, "2.5.6", "9052588e83bfedfd9b72e1034532aee2a5369d9d9343b61aeb7fbce761010741", [:mix, :rebar3], [], "hexpm", "96c6799792d735cc0f0fd0f86267e9d351e63339cbe03df9d162010cefc26bb0"},
|
"recon": {:hex, :recon, "2.5.6", "9052588e83bfedfd9b72e1034532aee2a5369d9d9343b61aeb7fbce761010741", [:mix, :rebar3], [], "hexpm", "96c6799792d735cc0f0fd0f86267e9d351e63339cbe03df9d162010cefc26bb0"},
|
||||||
"remote_ip": {:git, "https://git.pleroma.social/pleroma/remote_ip.git", "b647d0deecaa3acb140854fe4bda5b7e1dc6d1c8", [ref: "b647d0deecaa3acb140854fe4bda5b7e1dc6d1c8"]},
|
"remote_ip": {:hex, :remote_ip, "1.2.0", "fb078e12a44414f4cef5a75963c33008fe169b806572ccd17257c208a7bc760f", [:mix], [{:combine, "~> 0.10", [hex: :combine, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "2ff91de19c48149ce19ed230a81d377186e4412552a597d6a5137373e5877cb7"},
|
||||||
"rustler": {:hex, :rustler, "0.30.0", "cefc49922132b072853fa9b0ca4dc2ffcb452f68fb73b779042b02d545e097fb", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:toml, "~> 0.6", [hex: :toml, repo: "hexpm", optional: false]}], "hexpm", "9ef1abb6a7dda35c47cfc649e6a5a61663af6cf842a55814a554a84607dee389"},
|
"rustler": {:hex, :rustler, "0.30.0", "cefc49922132b072853fa9b0ca4dc2ffcb452f68fb73b779042b02d545e097fb", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:toml, "~> 0.6", [hex: :toml, repo: "hexpm", optional: false]}], "hexpm", "9ef1abb6a7dda35c47cfc649e6a5a61663af6cf842a55814a554a84607dee389"},
|
||||||
"sleeplocks": {:hex, :sleeplocks, "1.1.3", "96a86460cc33b435c7310dbd27ec82ca2c1f24ae38e34f8edde97f756503441a", [:rebar3], [], "hexpm", "d3b3958552e6eb16f463921e70ae7c767519ef8f5be46d7696cc1ed649421321"},
|
"sleeplocks": {:hex, :sleeplocks, "1.1.3", "96a86460cc33b435c7310dbd27ec82ca2c1f24ae38e34f8edde97f756503441a", [:rebar3], [], "hexpm", "d3b3958552e6eb16f463921e70ae7c767519ef8f5be46d7696cc1ed649421321"},
|
||||||
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.7", "354c321cf377240c7b8716899e182ce4890c5938111a1296add3ec74cf1715df", [:make, :mix, :rebar3], [], "hexpm", "fe4c190e8f37401d30167c8c405eda19469f34577987c76dde613e838bbc67f8"},
|
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.7", "354c321cf377240c7b8716899e182ce4890c5938111a1296add3ec74cf1715df", [:make, :mix, :rebar3], [], "hexpm", "fe4c190e8f37401d30167c8c405eda19469f34577987c76dde613e838bbc67f8"},
|
||||||
|
|
|
||||||
|
|
@ -106,4 +106,38 @@ defmodule Pleroma.Web.Plugs.RemoteIpTest do
|
||||||
|
|
||||||
assert conn.remote_ip == {1, 1, 1, 1}
|
assert conn.remote_ip == {1, 1, 1, 1}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "reserved ranges are configurable" do
|
||||||
|
clear_config([RemoteIp, :reserved], [])
|
||||||
|
|
||||||
|
conn =
|
||||||
|
conn(:get, "/")
|
||||||
|
|> put_req_header("x-forwarded-for", "1.1.1.1, 10.0.0.3")
|
||||||
|
|> RemoteIp.call(nil)
|
||||||
|
|
||||||
|
assert conn.remote_ip == {10, 0, 0, 3}
|
||||||
|
end
|
||||||
|
|
||||||
|
test "clients override reserved ranges" do
|
||||||
|
clear_config([RemoteIp, :clients], ["10.0.0.0/8"])
|
||||||
|
|
||||||
|
conn =
|
||||||
|
conn(:get, "/")
|
||||||
|
|> put_req_header("x-forwarded-for", "1.1.1.1, 10.0.0.3")
|
||||||
|
|> RemoteIp.call(nil)
|
||||||
|
|
||||||
|
assert conn.remote_ip == {10, 0, 0, 3}
|
||||||
|
end
|
||||||
|
|
||||||
|
test "clients override proxies" do
|
||||||
|
clear_config([RemoteIp, :clients], ["10.0.0.3"])
|
||||||
|
clear_config([RemoteIp, :proxies], ["10.0.0.0/8"])
|
||||||
|
|
||||||
|
conn =
|
||||||
|
conn(:get, "/")
|
||||||
|
|> put_req_header("x-forwarded-for", "1.1.1.1, 10.0.0.3")
|
||||||
|
|> RemoteIp.call(nil)
|
||||||
|
|
||||||
|
assert conn.remote_ip == {10, 0, 0, 3}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue