From 433b56d2f900bb53596b7a5965adfe6d93e6385b Mon Sep 17 00:00:00 2001 From: Daenney Date: Tue, 13 Jun 2023 16:30:09 +0200 Subject: [PATCH] [docs] Add certificates and firewalling to advanced (#1888) * [docs] Add a certificates guide in Advanced This adds some documentation about the process of getting certificates through ACME in general. It also provides a number of links to alternative clients and certbot deployment guides that are up to date. Slightly restructure the NGINX and Apache reverse proxy documentation and insert mentions to the Provisioning TLS certificates advanced documentation in them. * [docs] Add firewall section in Advanced * [docs] Add new guides to section indexes * [docs] Fix spelling issue * [docs] Fix a few typos --- docs/advanced/certificates.md | 108 ++++++++++++++++++ docs/advanced/index.md | 2 + docs/advanced/security/firewall.md | 84 ++++++++++++++ docs/advanced/security/index.md | 3 +- docs/getting_started/index.md | 2 +- .../reverse_proxy/apache-httpd.md | 60 +++++----- docs/getting_started/reverse_proxy/nginx.md | 41 +++---- mkdocs.yml | 2 + 8 files changed, 244 insertions(+), 58 deletions(-) create mode 100644 docs/advanced/certificates.md create mode 100644 docs/advanced/security/firewall.md diff --git a/docs/advanced/certificates.md b/docs/advanced/certificates.md new file mode 100644 index 000000000..cc506bdbd --- /dev/null +++ b/docs/advanced/certificates.md @@ -0,0 +1,108 @@ +# Provisioning TLS certificates + +As explained in the [deployment considerations](../getting_started/index.md), federation requires the use of TLS as most instances refuse to federate over unencrypted transports. + +GoToSocial comes with built-in support for provisioning and renewing its own TLS certificates through Lets Encrypt. This guide looks at how you can provision your own certificates independently from GoToSocial. This can be useful if you want full control over how the certificates are provisioned, or because you're using a [reverse proxy](../getting_started/reverse_proxy/index.md) which is doing TLS termination. + +There are a few different ways you can get TLS certificates: + +* Buy them from a vendor, typically valid for 2 years +* Get them from your cloud provider, validity depends on their product constraints +* Get them from an [ACME](https://en.wikipedia.org/wiki/Automatic_Certificate_Management_Environment)-compatible provider like Lets Encrypt, typically valid for 3 months at a time + +In this guide we'll only look at option 3, an ACME-compatible vendor. + +## General approach + +The way you'll provision certificates through Lets Encrypt is: + +* Install an ACME client on your server +* Configure the ACME client to provision your certificates +* Configure a piece of software to use those certificates +* Enable a timer/cron to regularly renew the certificates +* Signal to the necessary applications they need to reload or restart to pick up the new certificates + +Certificates are provisioned [using a challenge](https://letsencrypt.org/sv/docs/challenge-types/), a way to verify that you're requesting a certificate for a domain you control. You'll typically use one of: + +* HTTP challenge +* DNS challenge + +The HTTP challenge requires serving certain files on port 80 on the domains you're requesting a certificate for under the `/.well-known/acme/` path. This is the default challenge type. + +The DNS challenge happens entirely out of band but requires you to update a DNS TXT record. This approach is only feasible if your DNS registrar provides an API through which you can modify DNS records so that your ACME client can complete this challenge. + +## Clients + +The official Lets Encrypt client is [certbot](https://certbot.eff.org/) and it's usually packaged in [your (Linux) distribution](https://repology.org/project/certbot/versions) of choice. Certain reverse proxies like Caddy and Traefik have built-in support for provisioning certificates using the ACME protocol. + +A couple of other clients of note that you can consider using: + +* [acme-client](https://man.openbsd.org/acme-client.1) for OpenBSD using the privilege separation features of the platform +* [lacme](https://git.guilhem.org/lacme/about/), which is built with process isolation and minimal privileges in mind in the same vein as acme-client but for Linux +* [Lego](https://github.com/go-acme/lego), an ACME client and library written in Go +* [mod_md](https://httpd.apache.org/docs/2.4/mod/mod_md.html), when using Apache 2.4.30+ + +### DNS challenge + +For the DNS challenge, the API of your registrar needs to be supported by your ACME client. Though certbot has a few plugins for popular providers, you probably want to look at the [dns-multi](https://github.com/alexzorin/certbot-dns-multi) plugin instead. It leverages [Lego](https://github.com/go-acme/lego) under the hood which supports a much wider array of providers. + +## Configuration + +There are 3 configuration options that are important: + +* [`letsencrypt-enabled`](../configuration/tls.md) controls if GoToSocial will try to provision its own certificates +* [`tls-certificate-chain`](../configuration/tls.md) filesystem path where GoToSocial can find the TLS certificate chain + the public key +* [`tls-certificate-key`](../configuration/tls.md) filesystem path where GoToSocial can find the associated TLS private key + +### Without reverse proxy + +When running GoToSocial directly exposed to the internet, but you still want to use your own certificates you can set the following options: + +```yaml +letsencrypt-enabled: false +tls-certificate-chain: "/path/to/combined-certificate-chain-public.key" +tls-certificate-key: "/path/to/private.key" +``` + +This disables the built-in provisioning of certificates through Lets Encrypt and tells GoToSocial where to find the certificates on disk. + +!!! tip + Restart GoToSocial after renewing your certificates. It won't pick up on certificate rotation by itself when they are provided like this. + +### With reverse proxy + +When running GoToSocial behind a [reverse proxy](../getting_started/reverse_proxy/index.md) which you also use for TLS termination, you'll need the following instead: + +```yaml +letsencrypt-enabled: false +tls-certificate-chain: "" +tls-certificate-key: "" +``` + +It's important to ensure the `tls-certificate-*` options are unset or set to the empty string. Otherwise GoToSocial will attempt to handle TLS itself. + +!!! danger "Protocol configuration option" + Do **not** change the [`protocol`](../configuration/general.md) configuration option to `http`. This should only ever by set to `http` for development purposes. It needs to be set to `https` even when running behind a TLS-terminating reverse proxy. + +You'll also want to change the [`port`](../configuration/general.md) GoToSocial binds on, so it no longer tries to use port 443. + +To configure TLS in your reverse proxy, please refer to their documentation: + +* [nginx](https://docs.nginx.com/nginx/admin-guide/security-controls/terminating-ssl-http/) +* [apache](https://httpd.apache.org/docs/2.4/ssl/ssl_howto.html) +* [Traefik](https://doc.traefik.io/traefik/https/tls/) +* [Caddy](https://caddyserver.com/docs/caddyfile/directives/tls) + +!!! tip + When configuring TLS in your reverse proxy, ensure you configure a reasonably modern set of compatible versions and ciphers. You can use the "Intermediate" configuration from the [Mozilla SSL Configuration Generator](https://ssl-config.mozilla.org/). + + Check the documentation of your reverse proxy on whether you have to reload or restart it after certificates have changed. Not all reverse proxies detect this. + +## Guides + +There are a number of good resources on the internet explaining how to set all of this up. + +* [ArchWiki entry](https://wiki.archlinux.org/title/certbot) on certbot +* [Gentoo wiki entry](https://wiki.gentoo.org/wiki/Let%27s_Encrypt) on Lets Encrypt +* [Linode guide](https://www.linode.com/docs/guides/enabling-https-using-certbot-with-nginx-on-fedora/) on certbot for Fedora, RHEL/CentOS, Debian and Ubuntu +* Digital Ocean guides on Lets Encrypt on Ubuntu 22.04 with [nginx](https://www.digitalocean.com/community/tutorials/how-to-secure-nginx-with-let-s-encrypt-on-ubuntu-22-04) or [apache](https://www.digitalocean.com/community/tutorials/how-to-secure-apache-with-let-s-encrypt-on-ubuntu-22-04) diff --git a/docs/advanced/index.md b/docs/advanced/index.md index f196b191b..351190227 100644 --- a/docs/advanced/index.md +++ b/docs/advanced/index.md @@ -8,7 +8,9 @@ We consider these topics advanced because applying them incorrectly does have th * [Split-domain deployment (API vs. account domain)](host-account-domain.md) * [Using an HTTP proxy for client/outgoing requests](outgoing-proxy.md) +* [Provisioning TLS certificates](certificates.md) * [Caching API responses](caching/api.md) * [Serving and caching assets and media from local storage](caching/assets-media.md) * [Process sandboxing](security/sandboxing.md) +* [Firewall configuration](security/firewall.md) * [Tracing](tracing.md) diff --git a/docs/advanced/security/firewall.md b/docs/advanced/security/firewall.md new file mode 100644 index 000000000..c94dce75a --- /dev/null +++ b/docs/advanced/security/firewall.md @@ -0,0 +1,84 @@ +# Firewall + +You should deploy a firewall on your instance to close off any open ports and give you a mechanism to ban potentially misbehaving clients. Many firewall frontends will also automatically install some rules that block obvious malicious packets. + +It can be helpful to deploy tools that monitor your log files for certain patterns and automatically ban clients exhibiting certain behaviour. This can be use to monitor your SSH and web server access logs for things like SSH brute-force attacks. + +## Ports + +For GoToSocial, you'll want to ensure port `443` remains open. Without it, nobody will be able to reach your instance. Federation will fail and client apps won't be able to work at all. + +If you [provision TLS certificates](../certificates.md) using ACME or GoToSocial's built-in Lets Encrypt support, you'll also need port `80` to be open. + +In order to access your instance over SSH, you'll need to keep the port your SSH daemon is bound on open too. By default this is port `22`. + +## ICMP + +[Internet Control Message Protocol](https://en.wikipedia.org/wiki/Internet_Control_Message_Protocol) are exchanged between machines in order to detect certain network conditions or troubleshoot things. Many firewalls have a tendency of blocking ICMP entirely but this is undesirable. A few ICMP types should be allowed and you can use your firewall to configure rate limiting for them instead. + +### IPv4 + +In order for things to work reliably, your firewall must allow: + +* ICMP Type 3: "Destination Unreachable" and also aids in Path-MTU Discovery +* ICMP Type 4: "Source Quench" + +If you want to be able to ping things or be pinged, you should also allow: + +* ICMP Type 0: "Echo Reply" +* ICMP Type 8: "Echo Request" + +For traceroute to work, it can be helpful to also allow: + +* ICMP Type 11: "Time Exceeded" + +### IPv6 + +ICMP is heavily relied on by all parts of the IPv6 stack and things will break in exciting and hard to debug ways if you block it. [RFC 4890](https://www.rfc-editor.org/rfc/rfc4890) was specifically written to address this and is worthwhile to review. + +Roughly speaking, you must always allow: + +* ICMP Type 1: "Destination Unreachable" +* ICMP Type 2: "Packet Too Big" +* ICMP Type 3, code 0: "Time Exceeded" +* ICMP Type 4, code 1, 2: "Parameter Problem" + +For ping, you should allow: + +* ICMP Type 128: "Echo Request" +* ICMP Type 129: "Echo Response" + +## Firewall configuration + +On Linux, firewalling is typically done using either [iptables](https://en.wikipedia.org/wiki/Iptables) or the more modern and faster [nftables](https://en.wikipedia.org/wiki/Nftables) as the backend. Most distributions are switching to nftables and many firewall frontends can be configured to use nftables instead. You'll need to refer to your distribution's documentation on the matter, but typically there will be an `iptables` or `nftables` service your init-system can start with a predefined location to load firewall rules from. + +Doing this by hand using raw iptables or nftables rules offers the most control but can be challenging if you're not familiar with these systems. In order to help with that, a number of configuration frontends exist that you can use. + +On the Debian and Ubuntu as well as openSUSE family of distributions, UFW is commonly used. It's a simple firewall front-end and many tutorials targeting those distributions will be using it. + +For the Red Hat/CentOS family of distributions, firewalld is typically used. It's a much more advanced firewall configuration utility which also has a desktop GUI and [Cockpit integration](https://cockpit-project.org/). + +Despite distribution preferences, you can use UFW, firewalld or something else entirely with any Linux distribution. + +* [Ubuntu Wiki](https://wiki.ubuntu.com/UncomplicatedFirewall?action=show&redirect=UbuntuFirewall) on UFW +* [ArchWiki](https://wiki.archlinux.org/title/Uncomplicated_Firewall) on UFW +* Digital Ocean guide on [using UFW with Ubuntu 22.04](https://www.digitalocean.com/community/tutorials/how-to-set-up-a-firewall-with-ufw-on-ubuntu-22-04) +* [firewalld](https://firewalld.org/) project homepage and documentation +* [ArchWiki](https://wiki.archlinux.org/title/firewalld) on firewalld +* [Using and configuring firewalld](https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/9/html/configuring_firewalls_and_packet_filters/using-and-configuring-firewalld_firewall-packet-filters) from Red Hat +* Linode guide [on using firewalld](https://www.linode.com/docs/guides/introduction-to-firewalld-on-centos/) + +## Brute-force protection + +[fail2ban](https://www.fail2ban.org) and [SSHGuard](https://www.sshguard.net/) can be set up to monitor your log files for attempts to brute-force logins and other malicious behaviour. They can be configured to automatically insert firewall rules to block malicious IP addresses, either for a specific period of time or even indefinitely. + +SSHGuard was initially designed just for SSH, but nowadays supports a variety of services. Fail2ban tends to support anything you can generate consistent log lines for, whereas SSHGuard's signature approach can catch more sophisticated or stealthy attacks as it computes an attack score over time. + +Both SSHGuard and fail2ban ship with "backends" that can target iptables and nftables directly, or work with your frontend of choice like UFW or firewalld on Linux or pf on \*BSD. Make sure you review their documentation on how to correctly configure it. + +* [ArchWiki](https://wiki.archlinux.org/title/Fail2ban) on fail2ban +* DigitalOcean guide on how to protect SSH with [fail2ban on Ubuntu](https://www.digitalocean.com/community/tutorial_collections/how-to-protect-ssh-with-fail2ban) +* Linode guide on how to [secure your server with fail2ban](https://www.linode.com/docs/guides/using-fail2ban-to-secure-your-server-a-tutorial/) +* [ArchWiki](https://wiki.archlinux.org/title/sshguard) on sshguard +* [FreeBSD manual](https://man.freebsd.org/cgi/man.cgi?query=sshguard&sektion=8&manpath=FreeBSD+13.2-RELEASE+and+Ports) for sshguard +* [SSHGuard setup](https://manpages.ubuntu.com/manpages/lunar/en/man7/sshguard-setup.7.html) manual for Ubuntu diff --git a/docs/advanced/security/index.md b/docs/advanced/security/index.md index 63ee73c9a..2ff47284a 100644 --- a/docs/advanced/security/index.md +++ b/docs/advanced/security/index.md @@ -3,8 +3,9 @@ These guides cover improving the security posture of your GoToSocial deployment. They don't involve tweaking settings in GoToSocial, but rather additional things you can do to better lock down your instance. !!! note - Anything in these guides is meant to ehance the security of your GoToSocial deployment; they are not a replacement for good security practices like keeping your systems patched and up to date. + Anything in these guides is meant to enhance the security of your GoToSocial deployment; they are not a replacement for good security practices like keeping your systems patched and up to date. ## Guides * [Sandboxing the GoToSocial binary](sandboxing.md) +* [Firewall configuration](firewall.md) diff --git a/docs/getting_started/index.md b/docs/getting_started/index.md index b9224b62c..0f42c5128 100644 --- a/docs/getting_started/index.md +++ b/docs/getting_started/index.md @@ -72,4 +72,4 @@ GoToSocial needs ports `80` and `443` open. If you can't leave `443` and `80` open on the machine, don't worry! You can configure these ports in GoToSocial, but you'll have to also configure port forwarding to properly forward traffic on `443` and `80` to whatever ports you choose. !!! tip - You should configure a firewall on your machine, as well as some protection against brute-force SSH login attempts and the like. A simple frontend to help you configure your firewall is [UFW](https://www.digitalocean.com/community/tutorials/how-to-set-up-a-firewall-with-ufw-on-ubuntu-18-04). You should also consider a tool like [Fail2Ban](https://linuxize.com/post/install-configure-fail2ban-on-ubuntu-20-04/) in order to automatically block malicious users. + You should configure a firewall on your machine, as well as some protection against brute-force SSH login attempts and the like. Take a look at our [firewall documentation](../advanced/security/firewall.md) for pointers on what to configure and tools that can help you out. diff --git a/docs/getting_started/reverse_proxy/apache-httpd.md b/docs/getting_started/reverse_proxy/apache-httpd.md index 9522a0001..c9446ff87 100644 --- a/docs/getting_started/reverse_proxy/apache-httpd.md +++ b/docs/getting_started/reverse_proxy/apache-httpd.md @@ -1,36 +1,10 @@ # Apache HTTP Server -## Requirements +In order to use Apache as a reverse proxy for GoToSocial you'll need to have it installed on your server. If you intend for the Apache instance to also handle TLS, you'll need to [provision TLS certificates](../../advanced/certificates.md) too. -For this you will need the Apache HTTP Server. +Apache is [packaged for many distributions](https://repology.org/project/apache/versions). It's very likely you can install it with your distribution's package manager. You can also run Apache using a container runtime with the [official Apache image](https://hub.docker.com/_/httpd) that's published to the Docker Hub. -That is a fairly popular package so your distro will probably have it. - -### Ubuntu - -```bash -sudo apt install apache2 -``` - -### Arch - -```bash -sudo pacman -S apache -``` - -### OpenSuse - -```bash -sudo zypper install apache2 -``` - -### Install modules - -You'll also need to install additional modules for Apache HTTP Server. You can do that with the following command: - -```bash -sudo a2enmod proxy_http md ssl headers rewrite -``` +In this guide we'll also show how to use certbot to provision the TLS certificates. It too is [packaged in many distributions](https://repology.org/project/certbot/versions) but many distributions tend to ship fairly old versions of certbot. If you run into trouble it may be worth considering using the [container image](https://hub.docker.com/r/certbot/certbot) instead. ## Configure GoToSocial @@ -54,7 +28,28 @@ sudo systemctl restart gotosocial.service Or if you don't have a systemd service just restart it manually. -## Set up Apache HTTP Server with SSL managed using MD module +## Set up Apache + +### Required Apache modules + +You need to ensure you have a number of Apache modules installed and enabled. All these modules *should* ship with your distribution's Apache package, but they may have been split out into separate packages. + +You can check which modules you have installed with `apachectl -M`. + +You'll need to have the following modules loaded: + +* `proxy_http` to proxy HTTP requests to GoToSocial +* `ssl` to handle SSL/TLS +* `headers` to manipulate HTTP request and response headers +* `rewrite` to rewrite HTTP requests +* `md` for Lets Encrypt, available since 2.4.30 + +On Debian, Ubuntu and openSUSE, you can use the [`a2enmod`](https://manpages.debian.org/bookworm/apache2/a2enmod.8.en.html) utility to load any additional modules. For the Red Hat/CentOS family of distributions, you'll need to add a [`LoadModule` directive](https://httpd.apache.org/docs/2.4/mod/mod_so.html#loadmodule) to your Apache configuration instead. + +### TLS with mod_md + +!!! note + `mod_md` is only available since Apache 2.4.30 and still considered experimental. It works well enough in practice and is the most convenient method. Now we'll configure Apache HTTP Server to serve GoToSocial requests. @@ -169,7 +164,10 @@ If this happens, you'll need to do one (or all) of the below: 1. Update `/etc/apache2/sites-enabled/000-default.conf` and change the `ServerAdmin` value to a valid email address (then reload Apache HTTP Server). 2. Add the line `MDContactEmail your.email.address@whatever.com` below the `MDomain` line in `/etc/apache2/sites-available/example.com.conf`, replacing `your.email.address@whatever.com` with a valid email address, and `example.com` with your GtS host name. -## Set up Apache HTTP Server with SSL managed manually or by an external software (e.g. Certbot or acme.sh) +### TLS with externally managed certificates + +!!! note + We have additional documentation on how to [provision TLS certificates](../../advanced/certificates.md) that also provides links to additional content and tutorials for different distributions that may be good to review. If you prefer to have a manual setup or setting SSL using a different service to manage it (Certbot, etc), then you can use a simpler setup for your Apache HTTP Server. diff --git a/docs/getting_started/reverse_proxy/nginx.md b/docs/getting_started/reverse_proxy/nginx.md index fd9a42941..2cfd9020a 100644 --- a/docs/getting_started/reverse_proxy/nginx.md +++ b/docs/getting_started/reverse_proxy/nginx.md @@ -1,28 +1,10 @@ # NGINX -## Requirements +In order to use NGINX as a reverse proxy for GoToSocial you'll need to have it installed on your server. If you intend for the NGINX instance to also handle TLS, you'll need to [provision TLS certificates](../../advanced/certificates.md) too. -For this you will need [Certbot](https://certbot.eff.org/), the Certbot NGINX plugin and of course [NGINX](https://www.nginx.com/) itself. +NGINX is [packaged for many distributions](https://repology.org/project/nginx/versions). It's very likely you can install it with your distribution's package manager. You can also run NGINX using a container runtime with the [official NGINX image](https://hub.docker.com/_/nginx) that's published to the Docker Hub. -These are popular packages so your distro will probably have them. - -### Ubuntu - -```bash -sudo apt install certbot python3-certbot-nginx nginx -``` - -### Arch - -```bash -sudo pacman -S certbot certbot-nginx nginx -``` - -### OpenSuse - -```bash -sudo zypper install nginx python3-certbot python3-certbot-nginx -``` +In this guide we'll also show how to use certbot to provision the TLS certificates. It too is [packaged in many distributions](https://repology.org/project/certbot/versions) but many distributions tend to ship fairly old versions of certbot. If you run into trouble it may be worth considering using the [container image](https://hub.docker.com/r/certbot/certbot) instead. ## Configure GoToSocial @@ -34,11 +16,17 @@ sudo systemctl stop gotosocial Or if you don't have a systemd service just stop it manually. -In your GoToSocial config turn off letsencrypt by setting `letsencrypt-enabled` to `false`. +Tweak your GoToSocial configuration like so: -If you we running GoToSocial on port 443, change the `port` value back to the default `8080`. +```yaml +letsencrypt-enabled: false +port: 8080 +bind-address: 127.0.0.1 +``` -If the reverse proxy will be running on the same machine, set the `bind-address` to `"localhost"` so that the GoToSocial server is only accessible via loopback. Otherwise it may be possible to bypass your proxy by connecting to GoToSocial directly, which might be undesirable. +The first setting disables the built-in provisioning of TLS certificates. Since NGINX will now be handling that traffic GoToSocial no longer needs to be bound to port 443, or any privileged port. + +By setting the `bind-address` to `127.0.0.1` GoToSocial will no longer be accessible directly from the outside. If your NGINX and GoToSocial instance aren't running on the same server you'll need to bind to an IP address that lets your reverse proxy reach your GoToSocial instance. By binding to a private IP address you can be sure GoToSocial can't be accessed except through NGINX. ## Set up NGINX @@ -119,7 +107,10 @@ Everything working? Great! Then restart nginx to load your new config file. sudo systemctl restart nginx ``` -## Setting up SSL with certbot +## Set up TLS + +!!! note + We have additional documentation on how to [provision TLS certificates](../../advanced/certificates.md) that also provides links to additional content and tutorials for different distributions that may be good to review. You should now be able to run certbot and it will guide you through the steps required to enable https for your instance. diff --git a/mkdocs.yml b/mkdocs.yml index fe419c2eb..593cb6526 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -91,9 +91,11 @@ nav: - "advanced/caching/index.md" - "advanced/caching/api.md" - "advanced/caching/assets-media.md" + - "advanced/certificates.md" - "Enhanced security": - "advanced/security/index.md" - "advanced/security/sandboxing.md" + - "advanced/security/firewall.md" - "advanced/tracing.md" - "Admin":