4d7daca56230152b8a26caa5335a493f9b82f518
[akkoma] / lib / pleroma / web / plugs / remote_ip.ex
1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
4
5 defmodule Pleroma.Web.Plugs.RemoteIp do
6 @moduledoc """
7 This is a shim to call [`RemoteIp`](https://git.pleroma.social/pleroma/remote_ip) but with runtime configuration.
8 """
9
10 alias Pleroma.Config
11 import Plug.Conn
12
13 @behaviour Plug
14
15 def init(_), do: nil
16
17 def call(%{remote_ip: original_remote_ip} = conn, _) do
18 if Config.get([__MODULE__, :enabled]) do
19 %{remote_ip: new_remote_ip} = conn = RemoteIp.call(conn, remote_ip_opts())
20 assign(conn, :remote_ip_found, original_remote_ip != new_remote_ip)
21 else
22 conn
23 end
24 end
25
26 defp remote_ip_opts do
27 headers = Config.get([__MODULE__, :headers], []) |> MapSet.new()
28 reserved = Config.get([__MODULE__, :reserved], [])
29
30 proxies =
31 Config.get([__MODULE__, :proxies], [])
32 |> Enum.concat(reserved)
33 |> Enum.map(&maybe_add_cidr/1)
34
35 {headers, proxies}
36 end
37
38 defp maybe_add_cidr(proxy) when is_binary(proxy) do
39 proxy =
40 cond do
41 "/" in String.codepoints(proxy) -> proxy
42 InetCidr.v4?(InetCidr.parse_address!(proxy)) -> proxy <> "/32"
43 InetCidr.v6?(InetCidr.parse_address!(proxy)) -> proxy <> "/128"
44 end
45
46 InetCidr.parse(proxy, true)
47 end
48 end