Web proxy for Mastodon that puts public profiles behind an auth layer
Go to file
2020-05-02 02:57:23 -04:00
paws add filters to instances page 2020-05-02 02:57:23 -04:00
.gitignore setup basic functionality 2020-01-13 08:10:48 -05:00
LICENSE Initial commit 2019-12-17 07:22:51 -05:00
paws.example.service update readme and create default config 2020-01-18 11:55:07 -05:00
production.example.env update readme and create default config 2020-01-18 11:55:07 -05:00
README.md fix logins 2020-02-06 12:33:37 -05:00
reload.cfg basic greylist functionality 2020-04-28 00:57:46 -04:00
requirements.txt use git master for IzzyLib in requirements 2020-04-28 01:00:25 -04:00
server.py fix logins 2020-02-06 12:33:37 -05:00

PAWS logo Protection Against Web Scrapers (PAWS)

Web proxy for Mastodon that puts public profiles behind an auth layer.

How it works

PAWS sits between Mastodon and your front-facing web proxy to intercept incoming requests. If a profile, toot, or any related json is requested, it will be blocked unless authenticated. If authenticated fetches on mastodon are disabled, PAWS will check signatures instead

Installation

Python 3.6.0+ (3.8.0 recommended)

python3 -m pip install -r requirements.txt --user

Configuration

data/production.env:

# Path to mastodon instance. Defaults to current working dir
MASTOPATH=/home/mastodon/glitch-soc

# The address to mastodon
MASTOHOST=localhost:3000

# Listen address and port for PAWS. Can safely be ignored if running on same host as web server
PAWS_HOST=127.0.0.1
PAWS_PORT=3001

# Domain to list in the actor. Only needed if you plan on using the whitelist
PAWS_DOMAIN=bappypaws.example.com

Extra environment variables (cannot be put in production.env):

  • LOGDATE: boolean (default: yes). Set to no to remove access times from the console log

If Mastodon is on a different host, you'll have to copy Mastodon's .env.production to the working directory or mount the Mastodon directory to make it accessible to PAWS

Caddy

Append this to caddy's mastodon config:

rewrite {
	if_op and
	if {path} starts_with /users
	if {path} not_ends_with inbox
	to {path} /auth/{path}
}

rewrite {
	if_op or
	if {path} starts_with /@
	if {path} starts_with /paws
	to {path} /auth/{path}
}

proxy /auth localhost:3001 {
	without /auth
	transparent
}

Config for PAWS domain:

paws.bappypaws.example.com {
	proxy / localhost:3001 {
		transparent
	}
}

Nginx

Append this to the mastodon config (Thanks to @finkeldoodle@transfur.online for the conversion)

## Note: Order of location blocks is IMPORTANT.
## Nginx matches longest non-regex location block, then **FIRST** matching regex block takes preference.
## (regex blocks are ones with ~ or ~* before the path)

## This file is designed to be dropped into the Mastodon server block, probably before all the location blocks.

## If starts with /users, ends with inbox, bypass filter
location ~* ^/users[\s\S]*inbox {
        try_files $uri @proxy;
}

## If starts with /users, /@, or /paws, enter filter
location ~* ^/(users|@|paws) {
        try_files '' @paws;
}


location @paws {
        proxy_set_header Host                   $host;
        proxy_set_header X-Real-IP              $remote_addr;
        proxy_set_header X-Forwarded-For        $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto      https;
        proxy_set_header Proxy                  "";
        proxy_pass_header                       Server;

        proxy_pass http://localhost:3001;
}

Config for PAWS domain:

server {
	listen 80;
	listen [::]:80;
	server_name paws.bappypaws.example.com;
	root /home/mastodon/live/public;
	location /.well-known/acme-challenge/ { allow all; }
	location / { return 301 https://$host$request_uri; }
}

server {
	listen 443 ssl http2;
	listen [::]:443 ssl http2;
	server_name paws.bappypaws.example.com;

	ssl_protocols TLSv1.2 TLSv1.3;
	ssl_ciphers HIGH:!MEDIUM:!LOW:!aNULL:!NULL:!SHA;
	ssl_prefer_server_ciphers on;
	ssl_session_cache shared:SSL:10m;

	# Uncomment these lines once you acquire a certificate:
	# ssl_certificate     /etc/letsencrypt/live/paws.bappypaws.example.com/fullchain.pem;
	# ssl_certificate_key /etc/letsencrypt/live/paws.bappypaws.example.com/privkey.pem;

	keepalive_timeout    70;
	sendfile             on;
	client_max_body_size 80m;

	gzip on;
	gzip_disable "msie6";
	gzip_vary on;
	gzip_proxied any;
	gzip_comp_level 6;
	gzip_buffers 16 8k;
	gzip_http_version 1.1;
	gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

	add_header Strict-Transport-Security "max-age=31536000";

	location / {
			proxy_set_header Host                   $host;
			proxy_set_header X-Real-IP              $remote_addr;
			proxy_set_header X-Forwarded-For        $proxy_add_x_forwarded_for;
			proxy_set_header X-Forwarded-Proto      https;
			proxy_set_header Proxy                  "";
			proxy_pass_header                       Server;

			proxy_pass http://localhost:3001;
	}
}

Mastodon

While it isn't necessary, I highly recommend turning on authorized fetches (v3.0+) to let PAWS pass json requests directly through to mastodon. Also upgrade to at least v3.0 to be able to properly interact with other instances that have auth fetches turned on.

.env.production:

AUTHORIZED_FETCH=true

Usage

Start the server with ./server.py. If you want to edit the config, just run ./server.py edit.

WebUI usage

If your account is an admin account according to Mastodon, you can manage the PAWS whitelist at {domain}/paws. Instances in this whitelist will have their fetches signed if they don't sign them themselves.