Compare commits
7 Commits
feature/sa
...
feat/mrf-d
Author | SHA1 | Date | |
---|---|---|---|
|
127c5ad253 | ||
|
617ec63483 | ||
|
00828731fb | ||
|
bf15a1c7f3 | ||
|
a55c6de32b | ||
|
f44e11c7ab | ||
|
c4701323dd |
@ -399,6 +399,11 @@ config :pleroma, :mrf_vocabulary,
|
|||||||
accept: [],
|
accept: [],
|
||||||
reject: []
|
reject: []
|
||||||
|
|
||||||
|
config :pleroma, :mrf_dnsrbl,
|
||||||
|
nameserver: "bl.pleroma.com",
|
||||||
|
port: 53,
|
||||||
|
rblzone: nil
|
||||||
|
|
||||||
# threshold of 7 days
|
# threshold of 7 days
|
||||||
config :pleroma, :mrf_object_age,
|
config :pleroma, :mrf_object_age,
|
||||||
threshold: 604_800,
|
threshold: 604_800,
|
||||||
|
113
lib/pleroma/web/activity_pub/mrf/dns_rbl_policy.ex
Normal file
113
lib/pleroma/web/activity_pub/mrf/dns_rbl_policy.ex
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Pleroma.Web.ActivityPub.MRF.DnsRblPolicy do
|
||||||
|
@moduledoc "Dynamic activity filtering based on public database"
|
||||||
|
@behaviour Pleroma.Web.ActivityPub.MRF
|
||||||
|
|
||||||
|
alias Pleroma.Config
|
||||||
|
|
||||||
|
defp check_rbl(%{host: actor_host} = _actor_info, object) do
|
||||||
|
rblconfig = Config.get([:mrf_dnsrbl])
|
||||||
|
|
||||||
|
# :nameserver is the RBL server we want to query
|
||||||
|
rblhost = rblconfig[:nameserver]
|
||||||
|
|
||||||
|
# We have to query the nameserver's by IP, so look it up if an IP address wasn't
|
||||||
|
# provided in the config.
|
||||||
|
# You may want this to be a hostname with round-robin A records for basic load
|
||||||
|
# balancing, so we try that.
|
||||||
|
{:ok, rblnsip} =
|
||||||
|
case rblhost |> String.to_charlist() |> :inet_parse.address() do
|
||||||
|
{:ok, _} -> rblhost |> String.to_charlist() |> :inet_parse.address()
|
||||||
|
_ -> {:ok, rblhost |> String.to_charlist() |> :inet_res.lookup(:in, :a) |> Enum.random()}
|
||||||
|
end
|
||||||
|
|
||||||
|
rblport = rblconfig[:port]
|
||||||
|
|
||||||
|
# If the provided nameserver was an IP, we also need to know the zone because we can't
|
||||||
|
# derive it from the hostname. If the DNSRBL server software is configured to use "bl.pleroma.com"
|
||||||
|
# -- irrespective of the actual hostname/IP used to reach it --
|
||||||
|
# we need the configured zone as queries are nested under the zone. e.g., if you're checking the
|
||||||
|
# status of pleroma.host you are querying for:
|
||||||
|
#
|
||||||
|
# dig @nameserverip pleroma.host.bl.pleroma.com. in A
|
||||||
|
#
|
||||||
|
rblzone = rblconfig[:rblzone] || rblhost
|
||||||
|
|
||||||
|
# concatenate the host we're checking with the zone, e.g., "pleroma.host" <> . <> "bl.pleroma.com" <> .
|
||||||
|
# trim off duplicate trailing period in case it was supplied in the config.
|
||||||
|
query =
|
||||||
|
(actor_host <> "." <> rblzone <> ".")
|
||||||
|
|> String.replace_suffix("..", ".")
|
||||||
|
|> String.to_charlist()
|
||||||
|
|
||||||
|
# Timeout of 1s, retry 1
|
||||||
|
# We will only be using UDP for queries, so if the DNSRBL server is > 500ms away it
|
||||||
|
# may not work. However you wouldn't want it to be this far away or it will slow things
|
||||||
|
# down. I think we should probably try to cache entries in cachex too, maybe 300s TTL ?
|
||||||
|
rbl_response =
|
||||||
|
:inet_res.lookup(query, :in, :a, nameservers: [{rblnsip, rblport}], timeout: 1000, retry: 1)
|
||||||
|
|
||||||
|
cond do
|
||||||
|
actor_host == Config.get([Pleroma.Web.Endpoint, :url, :host]) -> {:ok, object}
|
||||||
|
rbl_response != [] -> {:reject, "[DNSRBLPolicy]"}
|
||||||
|
true -> {:ok, object}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
def filter(%{"actor" => actor} = object) do
|
||||||
|
actor_info = URI.parse(actor)
|
||||||
|
|
||||||
|
with {:ok, object} <- check_rbl(actor_info, object) do
|
||||||
|
{:ok, object}
|
||||||
|
else
|
||||||
|
_ -> {:reject, "[DNSRBLPolicy]"}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
def filter(object), do: {:ok, object}
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
def describe do
|
||||||
|
mrf_dnsrbl =
|
||||||
|
Config.get(:mrf_dnsrbl)
|
||||||
|
|> Enum.into(%{})
|
||||||
|
|
||||||
|
{:ok, %{mrf_dnsrbl: mrf_dnsrbl}}
|
||||||
|
end
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
def config_description do
|
||||||
|
%{
|
||||||
|
key: :mrf_dnsrbl,
|
||||||
|
related_policy: "Pleroma.Web.ActivityPub.MRF.DnsRblPolicy",
|
||||||
|
label: "MRF DNSRBL",
|
||||||
|
description: "DNS RealTime Blackhole Policy",
|
||||||
|
children: [
|
||||||
|
%{
|
||||||
|
key: :nameserver,
|
||||||
|
type: {:string},
|
||||||
|
description: "DNSRBL NameServer to Query",
|
||||||
|
suggestions: ["bl.pleroma.com"]
|
||||||
|
},
|
||||||
|
%{
|
||||||
|
key: :port,
|
||||||
|
type: {:string},
|
||||||
|
description: "Nameserver port",
|
||||||
|
suggestions: ["53"]
|
||||||
|
},
|
||||||
|
%{
|
||||||
|
key: :rblzone,
|
||||||
|
type: {:string},
|
||||||
|
description:
|
||||||
|
"Zone for querying, if unable to detect because nameserver is an IP address",
|
||||||
|
suggestions: ["bl.pleroma.com"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in New Issue
Block a user