Skip to content

Instantly share code, notes, and snippets.

@ngerakines
Created December 15, 2020 20:13
Show Gist options
  • Save ngerakines/2a0cb5ca8c871cb661a1c81b3f3e4fcc to your computer and use it in GitHub Desktop.
Save ngerakines/2a0cb5ca8c871cb661a1c81b3f3e4fcc to your computer and use it in GitHub Desktop.
Integrate your Pleroma blocklist with nginx (replace _ with / for original filenames)
# Your main nginx config file.
http {
# Existing configuration…
# Enable blocks based on IPs used by Fediverse instance domain names.
include /etc/nginx/blocklist-ip.conf;
}
# Or whatever your site config file is for Pleroma.
# Your main Pleroma server config
server {
# Existing configuration…
# Enable blocks based on Fediverse instance user agent header.
include /etc/nginx/blocklist-ua.conf;
}
# Your MediaProxy server config
server {
# Existing configuration…
# Enable blocks based on Fediverse instance user agent header.
include /etc/nginx/blocklist-ua.conf;
}
# Instance blocklist.
# Enables MRF stuff.
use Mix.Config
blocklist = [
"chuds.example.org"
]
# Config key specific to nginx.ex.
config :pleroma, :blocklist,
blocklist: blocklist
# Don't send non-public messages to these servers.
# TODO: not sure if there's a way to not send *any* messages yet.
config :pleroma, :instance,
quarantined_instances: blocklist
# Don't accept incoming messages from these servers.
config :pleroma, :mrf_simple,
reject: blocklist
use Mix.Config
# Include blocklist.
import_config "blocklist.exs"
# Normal configuration follows…
defmodule Mix.Tasks.Pleroma.Nginx do
use Mix.Task
@shortdoc "Nginx filters"
@moduledoc """
Nginx filters
## Print an nginx config file blocking IPs from the Pleroma config blocklist
``mix pleroma.nginx ip``
## Print an nginx config file blocking user agents from the Pleroma config blocklist
``mix pleroma.nginx ua``
"""
# TODO: parallelize resolver
def resolve(hostname) do
timeout = 5000 # ms
family = :inet # TODO: IPv6 support
with {:ok, {:hostent, _, _, _, _, ips}} <- :inet_res.gethostbyname(String.to_charlist(hostname), family, timeout) do
ips
else
{:error, reason} -> Mix.shell().error("Error resolving #{hostname}: #{inspect(reason)}")
[]
end
end
def run(["ip"]) do
hostnames = Pleroma.Config.get!([:blocklist, :blocklist])
resolved = Enum.sort(Enum.uniq(Enum.flat_map(hostnames, &resolve/1)))
nginx_config = Enum.join(Enum.map(resolved, fn(ip) -> "deny #{:inet.ntoa(ip)};\n" end))
Mix.shell().info(nginx_config)
end
def run(["ua"]) do
hostnames = Pleroma.Config.get!([:blocklist, :blocklist])
regex = "(#{Enum.join(Enum.map(hostnames, &Regex.escape/1), "|")})"
nginx_config = """
if ( $http_user_agent ~ #{regex} ) {
return 444; # close connection immediately
}
"""
Mix.shell().info(nginx_config)
end
end

Initial setup:

  • Create pleroma/config/blocklist.exs
  • Edit pleroma/config/prod.secret.exs to include blocklist.exs
  • Move nginx.ex into pleroma/lib/mix/tasks/pleroma/
  • Restart Pleroma

Every time blocklist.exs is updated:

  • Restart Pleroma
  • Generate nginx blocklist files:
    • Run MIX_ENV=prod mix pleroma.nginx ip > /tmp/blocklist-ip.conf
    • Run MIX_ENV=prod mix pleroma.nginx ua > /tmp/blocklist-ua.conf
  • Install nginx blocklist files:
    • Run sudo chown root:root /tmp/blocklist-*.conf
    • Run sudo mv /tmp/blocklist-*.conf /etc/nginx/
  • Test config syntax before using it: sudo nginx -t
    • If dependencies have changed since last run, sometimes one of the blocklist files will contain a few info messages from Mix. You'll need to delete these manually.
  • Reload nginx config: sudo nginx -s reload
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment