forked from AkkomaGang/akkoma
Add mediaproxy whitelist capability
This commit is contained in:
parent
8c9227c1f1
commit
24c3e2db2c
4 changed files with 43 additions and 20 deletions
|
@ -326,7 +326,8 @@
|
||||||
follow_redirect: true,
|
follow_redirect: true,
|
||||||
pool: :media
|
pool: :media
|
||||||
]
|
]
|
||||||
]
|
],
|
||||||
|
whitelist: []
|
||||||
|
|
||||||
config :pleroma, :chat, enabled: true
|
config :pleroma, :chat, enabled: true
|
||||||
|
|
||||||
|
|
|
@ -205,6 +205,7 @@ This section is used to configure Pleroma-FE, unless ``:managed_config`` in ``:i
|
||||||
* `enabled`: Enables proxying of remote media to the instance’s proxy
|
* `enabled`: Enables proxying of remote media to the instance’s proxy
|
||||||
* `base_url`: The base URL to access a user-uploaded file. Useful when you want to proxy the media files via another host/CDN fronts.
|
* `base_url`: The base URL to access a user-uploaded file. Useful when you want to proxy the media files via another host/CDN fronts.
|
||||||
* `proxy_opts`: All options defined in `Pleroma.ReverseProxy` documentation, defaults to `[max_body_length: (25*1_048_576)]`.
|
* `proxy_opts`: All options defined in `Pleroma.ReverseProxy` documentation, defaults to `[max_body_length: (25*1_048_576)]`.
|
||||||
|
* `whitelist`: List of domains to bypass the mediaproxy
|
||||||
|
|
||||||
## :gopher
|
## :gopher
|
||||||
* `enabled`: Enables the gopher interface
|
* `enabled`: Enables the gopher interface
|
||||||
|
|
|
@ -13,32 +13,44 @@ def url("/" <> _ = url), do: url
|
||||||
|
|
||||||
def url(url) do
|
def url(url) do
|
||||||
config = Application.get_env(:pleroma, :media_proxy, [])
|
config = Application.get_env(:pleroma, :media_proxy, [])
|
||||||
|
domain = URI.parse(url).host
|
||||||
|
|
||||||
if !Keyword.get(config, :enabled, false) or String.starts_with?(url, Pleroma.Web.base_url()) do
|
cond do
|
||||||
url
|
!Keyword.get(config, :enabled, false) or String.starts_with?(url, Pleroma.Web.base_url()) ->
|
||||||
else
|
|
||||||
secret = Application.get_env(:pleroma, Pleroma.Web.Endpoint)[:secret_key_base]
|
|
||||||
|
|
||||||
# Must preserve `%2F` for compatibility with S3
|
|
||||||
# https://git.pleroma.social/pleroma/pleroma/issues/580
|
|
||||||
replacement = get_replacement(url, ":2F:")
|
|
||||||
|
|
||||||
# The URL is url-decoded and encoded again to ensure it is correctly encoded and not twice.
|
|
||||||
base64 =
|
|
||||||
url
|
url
|
||||||
|> String.replace("%2F", replacement)
|
|
||||||
|> URI.decode()
|
|
||||||
|> URI.encode()
|
|
||||||
|> String.replace(replacement, "%2F")
|
|
||||||
|> Base.url_encode64(@base64_opts)
|
|
||||||
|
|
||||||
sig = :crypto.hmac(:sha, secret, base64)
|
Enum.any?(Pleroma.Config.get([:media_proxy, :whitelist]), fn pattern ->
|
||||||
sig64 = sig |> Base.url_encode64(@base64_opts)
|
String.equivalent?(domain, pattern)
|
||||||
|
end) ->
|
||||||
|
url
|
||||||
|
|
||||||
build_url(sig64, base64, filename(url))
|
true ->
|
||||||
|
encode_url(url)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def encode_url(url) do
|
||||||
|
secret = Application.get_env(:pleroma, Pleroma.Web.Endpoint)[:secret_key_base]
|
||||||
|
|
||||||
|
# Must preserve `%2F` for compatibility with S3
|
||||||
|
# https://git.pleroma.social/pleroma/pleroma/issues/580
|
||||||
|
replacement = get_replacement(url, ":2F:")
|
||||||
|
|
||||||
|
# The URL is url-decoded and encoded again to ensure it is correctly encoded and not twice.
|
||||||
|
base64 =
|
||||||
|
url
|
||||||
|
|> String.replace("%2F", replacement)
|
||||||
|
|> URI.decode()
|
||||||
|
|> URI.encode()
|
||||||
|
|> String.replace(replacement, "%2F")
|
||||||
|
|> Base.url_encode64(@base64_opts)
|
||||||
|
|
||||||
|
sig = :crypto.hmac(:sha, secret, base64)
|
||||||
|
sig64 = sig |> Base.url_encode64(@base64_opts)
|
||||||
|
|
||||||
|
build_url(sig64, base64, filename(url))
|
||||||
|
end
|
||||||
|
|
||||||
def decode_url(sig, url) do
|
def decode_url(sig, url) do
|
||||||
secret = Application.get_env(:pleroma, Pleroma.Web.Endpoint)[:secret_key_base]
|
secret = Application.get_env(:pleroma, Pleroma.Web.Endpoint)[:secret_key_base]
|
||||||
sig = Base.url_decode64!(sig, @base64_opts)
|
sig = Base.url_decode64!(sig, @base64_opts)
|
||||||
|
|
|
@ -177,4 +177,13 @@ defp decode_result(encoded) do
|
||||||
{:ok, decoded} = decode_url(sig, base64)
|
{:ok, decoded} = decode_url(sig, base64)
|
||||||
decoded
|
decoded
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "mediaproxy whitelist" do
|
||||||
|
Pleroma.Config.put([:media_proxy, :enabled], true)
|
||||||
|
Pleroma.Config.put([:media_proxy, :whitelist], ["google.com", "feld.me"])
|
||||||
|
url = "https://feld.me/foo.png"
|
||||||
|
|
||||||
|
unencoded = url(url)
|
||||||
|
assert unencoded == url
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue