Compare commits

...

7 Commits

Author SHA1 Message Date
Mark Felder
127c5ad253 Credo 2021-01-27 10:00:16 -06:00
Mark Felder
617ec63483 Makes more sense to call it rblzone 2021-01-26 14:00:04 -06:00
Mark Felder
00828731fb Need charlist for passing to :inet_res.lookup 2021-01-26 13:57:29 -06:00
Mark Felder
bf15a1c7f3 Tiny safety net 2021-01-26 13:54:23 -06:00
Mark Felder
a55c6de32b Credo, add some inline comments 2021-01-26 13:50:25 -06:00
Mark Felder
f44e11c7ab Credo 2021-01-26 13:35:12 -06:00
Mark Felder
c4701323dd Initial unoptimized version of using RBL in an MRF 2021-01-24 15:06:19 -06:00
2 changed files with 118 additions and 0 deletions

View File

@ -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,

View 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