[feature] Add warning about trusted-proxies to make config easier (#3675)

* [feature] Add warning about `trusted-proxies` to make config easier

* thank you linter, hugs and kisses to you
This commit is contained in:
tobi 2025-01-23 14:48:09 +00:00 committed by GitHub
parent 1472d92a8d
commit b42cb7a802
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 208 additions and 9 deletions

View file

@ -24,11 +24,11 @@ In case the rate limit is exceeded, an [HTTP 429 Too Many Requests](https://deve
### My rate limit keeps being exceeded! Why?
If you find that your rate limit is regularly being exceeded (both for yourself and other callers) during normal use of your instance, it may be that GoToSocial can't tell the clients apart by IP address. You can investigate this by viewing the logs of your instance. If (almost) all logged IP addresses appear to be the same IP address (something like `172.x.x.x`), then the rate limiting will cause problems.
If you find that your rate limit is regularly being exceeded (both for yourself and other callers) during normal use of your instance, it may be that GoToSocial can't tell the clients apart by IP address. You can investigate this by viewing the logs of your instance. If (almost) all logged client IP addresses appear to be the same IP address (something like `172.x.x.x`), then the rate limiting will cause problems.
This happens when your server is running inside NAT (port forwarding), or behind an HTTP proxy without the correct configuration, causing your instance to see all incoming IP addresses as the same address: namely, the IP address of your reverse proxy or gateway. This means that all incoming requests are *sharing the same rate limit*, rather than being split correctly per IP.
If you are using an HTTP proxy then it's likely that your `trusted-proxies` is not correctly configured. If this is the case, try adding the IP address of your reverse proxy to the list of `trusted-proxies`, and restarting your instance.
If you are using an HTTP proxy then it's likely that your `trusted-proxies` is not correctly configured. See the [trusted-proxies](../configuration/trusted_proxies.md) documentation for more info on how to resolve this.
If you don't have an HTTP proxy, then it's likely caused by NAT. In this case you should disable rate limiting altogether.

View file

@ -1,8 +1,6 @@
# General
The top-level configuration for GoToSocial, including basic things like host, port, bind address and transport protocol.
The only things you *really* need to set here are `host`, which should be the hostname where your instance is reachable, and probably `port`.
The top-level configuration for GoToSocial, including basic things like host, port, bind address, and trusted-proxies.
## Settings

View file

@ -0,0 +1,71 @@
# Trusted Proxies
To correctly enforce [rate limiting](../api/ratelimiting.md), GoToSocial relies on the concept of "trusted proxies" in order to accurately determine the IP address of clients accessing your server.
A "trusted proxy" is an intermediate network hop that GoToSocial can be instructed to trust to provide a correct client IP address.
For example, if you are running in a reverse proxy configuration with Docker + Nginx, then the Docker network address of Nginx should be configured as a trusted proxy, since all traffic from the wider internet will come into GoToSocial via Nginx.
Without setting `trusted-proxies` correctly, GoToSocial will see all incoming client IP addresses as the same address, which leads to rate limiting issues, since GoToSocial uses client IP addresses to bucket rate limits.
## tl;dr: How to set `trusted-proxies` correctly
If your `trusted-proxies` setting is not correctly configured, you may see the following warning on the web view of your instance (v0.18.0 and above):
> Warning! It looks like trusted-proxies is not set correctly in this instance's configuration. This may cause rate-limiting issues and, by extension, federation issues.
>
> If you are the instance admin, you should fix this by adding `SUGGESTED_IP_RANGE` to your trusted-proxies.
To resolve this, copy the IP range in the message, and edit your `config.yaml` file to add the IP range to your `trusted-proxies`.
!!! tip "You may be getting rate limited even if you don't see the above warning!"
If you're on a version of GoToSocial below v0.18.0, or you're running behind a CDN such as Cloudflare (not recommended), you won't see a warning message. Instead, you'll see in your GoToSocial logs that all client IPs are the same address. In this case, take the recurring client IP value as `SUGGESTED_IP_RANGE`.
In this example, we assume `SUGGESTED_IP_RANGE` to be `172.17.0.1/16` (the default Docker bridge network subnet).
Before (default config):
```yaml
trusted-proxies:
- "127.0.0.1/32"
- "::1"
```
After (new config):
```yaml
trusted-proxies:
- "172.17.0.1/16"
- "127.0.0.1/32"
- "::1"
```
If you are using [environment variables](../configuration/index.md#environment-variables) to configure your instance, you can configure `trusted-proxies` by setting the environment variable `GTS_TRUSTED_PROXIES` to a comma-separated list of IP ranges, like so:
```env
GTS_TRUSTED_PROXIES="172.17.0.1/16,127.0.0.1/32,::1"
```
If you are using docker compose, your docker-compose.yaml file should look something like this after the change (note that yaml uses `: ` and not `=`):
```yaml
################################
# BLAH BLAH OTHER CONFIG STUFF #
################################
environment:
############################
# BLAH BLAH OTHER ENV VARS #
############################
## For reverse proxy setups:
GTS_TRUSTED_PROXIES: "172.17.0.1/16,127.0.0.1/32,::1"
################################
# BLAH BLAH OTHER CONFIG STUFF #
################################
```
Once you have made the necessary configuration changes, restart your instance and refresh the home page. If the message is gone, then the problem is resolved!
If you still see the warning message but with a different suggested IP range to add to `trusted-proxies`, then follow the same steps as above again, including the new suggested IP range in your config in addition to the one you just added.
!!! tip "Cloudflare IP Addresses"
If you are running with a CDN/proxy such as Cloudflare in front of your GoToSocial instance (not recommended), then you may need to add one or more of the Cloudflare IP addresses to your `trusted-proxies` in order to have rate limiting work properly. You can find a list of Cloudflare IP addresses here: https://www.cloudflare.com/ips/

View file

@ -41,3 +41,7 @@ We have guides available for the following servers:
When using a reverse-proxy, special care must be taken to allow WebSockets to work too. This is necessary as many client applications use WebSockets to stream your timeline. WebSockets is not used as part of federation.
Make sure you read the [WebSocket](websocket.md) documentation and configure your reverse proxy accordingly.
## Trusted Proxies
When using a reverse-proxy, you may run into issues with rate limiting and `trusted-proxies`. Check the [trusted proxies](../../configuration/trusted_proxies.md) documentation if you have any problems.

View file

@ -1,5 +1,3 @@
version: "3.3"
services:
gotosocial:
image: superseriousbusiness/gotosocial:latest
@ -24,7 +22,7 @@ services:
# Wazero compilation cache will be stored.
GTS_WAZERO_COMPILATION_CACHE: /gotosocial/.cache
## For reverse proxy setups:
# GTS_TRUSTED_PROXIES: "172.x.x.x"
GTS_TRUSTED_PROXIES: "172.18.0.1/16"
## Set the timezone of your server:
#TZ: UTC
ports:
@ -47,3 +45,6 @@ networks:
gotosocial:
ipam:
driver: default
config:
- subnet: "172.18.0.0/16"
gateway: "172.18.0.1"

View file

@ -18,6 +18,7 @@
package util
import (
"net"
"net/http"
"github.com/gin-gonic/gin"
@ -63,6 +64,11 @@ type WebPage struct {
// ogMeta, stylesheets, javascript, and any extra
// properties will be provided to the template if
// set, but can all be nil.
//
// TemplateWebPage also checks whether the requesting
// clientIP is 127.0.0.1 or within a private IP range.
// If so, it injects a suggestion into the page header
// about setting trusted-proxies correctly.
func TemplateWebPage(
c *gin.Context,
page WebPage,
@ -74,13 +80,86 @@ func TemplateWebPage(
"javascript": page.Javascript,
}
// Add extras to template object.
for k, v := range page.Extra {
obj[k] = v
}
// Inject trustedProxiesRec to template
// object (or noop if not necessary).
injectTrustedProxiesRec(c, obj)
templatePage(c, page.Template, http.StatusOK, obj)
}
func injectTrustedProxiesRec(
c *gin.Context,
obj map[string]any,
) {
clientIP := c.ClientIP()
if clientIP == "127.0.0.1" {
// Suggest precise 127.0.0.1/32.
trustedProxiesRec := clientIP + "/32"
obj["trustedProxiesRec"] = trustedProxiesRec
return
}
// True if "X-Forwarded-For"
// or "X-Real-IP" were set.
var hasRemoteIPHeader bool
for _, k := range []string{
"X-Forwarded-For",
"X-Real-IP",
} {
if v := c.GetHeader(k); v != "" {
hasRemoteIPHeader = true
break
}
}
if !hasRemoteIPHeader {
// Upstream hasn't set a
// remote IP header, bail.
return
}
ip := net.ParseIP(clientIP)
if !ip.IsPrivate() {
// Upstream set a remote IP
// header but final clientIP
// isn't private, so upstream
// is probably already trusted.
// Don't inject suggestion.
return
}
// Private IP, guess if Docker.
if dockerSubnet.Contains(ip) {
// Suggest a CIDR that likely
// covers this Docker subnet,
// eg., 172.17.0.0 -> 172.17.255.255.
trustedProxiesRec := clientIP + "/16"
obj["trustedProxiesRec"] = trustedProxiesRec
return
}
// Private IP but we don't know
// what it is. Suggest precise CIDR.
trustedProxiesRec := clientIP + "/32"
obj["trustedProxiesRec"] = trustedProxiesRec
}
// dockerSubnet is a CIDR that lets one make hazy guesses
// as to whether an address is within the ranges Docker
// uses for subnets, ie., 172.16.0.0 -> 172.31.255.255.
var dockerSubnet = func() *net.IPNet {
_, subnet, err := net.ParseCIDR("172.16.0.0/12")
if err != nil {
panic(err)
}
return subnet
}()
// templateErrorPage renders the given
// HTTP code, error, and request ID
// within the standard error template.

View file

@ -98,6 +98,7 @@ nav:
- "Configuration":
- "configuration/index.md"
- "configuration/general.md"
- "configuration/trusted_proxies.md"
- "configuration/database.md"
- "configuration/web.md"
- "configuration/instance.md"

View file

@ -42,7 +42,26 @@
padding: 1.5rem;
gap: 1rem;
a {
.trusted-proxies-rec {
color: $info-fg;
background: $info-bg;
max-width: fit-content;
padding-left: 1rem;
padding-right: 1rem;
border-radius: $br;
text-align: center;
align-self: center;
code {
background: $info-bg;
}
a {
color: $info-fg;
}
}
& > a {
display: flex;
flex-wrap: wrap;
gap: 1rem;

View file

@ -17,6 +17,29 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ -}}
{{- define "trustedProxiesRec" -}}
{{- .with }}
<div class="trusted-proxies-rec">
<p>
<strong>Warning!</strong> It looks like <code>trusted-proxies</code> is not set correctly in this instance's configuration.
This may cause rate-limiting issues and, by extension, federation issues.
</p>
<p>
If you are the instance admin, you should fix this by adding <code>{{- .trustedProxiesRec -}}</code> to your <code>trusted-proxies</code>.
</p>
<p>
For more information, see
<a
href="https://docs.gotosocial.org/en/latest/configuration/trusted_proxies/"
rel="nofollow noreferrer noopener"
target="_blank"
>
the documentation
</a>.
</p>
</div>
{{- end -}}
{{- define "thumbnailDescription" -}}
{{- if .instance.ThumbnailDescription -}}
{{- .instance.ThumbnailDescription -}}
@ -56,6 +79,9 @@ Instance Logo
{{- end -}}
{{- with . }}
{{- if .trustedProxiesRec }}
{{- template "trustedProxiesRec" . }}
{{- end }}
<a aria-label="{{- .instance.Title -}}. Go to instance homepage" href="/" class="nounderline">
<picture>
{{- if .instance.ThumbnailStatic }}