Merge pull request #18 from AstralDestiny/main

Add Proxy Protocol help
This commit is contained in:
Owen Schwartz
2025-10-11 14:29:42 -07:00
committed by GitHub
2 changed files with 378 additions and 213 deletions

429
docs.json
View File

@@ -1,216 +1,219 @@
{
"$schema": "https://mintlify.com/docs.json",
"theme": "aspen",
"name": "Pangolin Docs",
"description": "Pangolin is a self-hosted alternative to Cloudflare Tunnels, designed to provide secure and highly-available ingress access to applications.",
"colors": {
"primary": "#F36117",
"light": "#F36117",
"dark": "#F36117"
},
"banner": {
"content": "We're hiring software engineers! [Click here](https://click.fossorial.io/L0OXr) to get in touch.",
"dismissible": true
},
"favicon": "/favicon.svg",
"navigation": {
"tabs": [
{
"tab": "Docs",
"groups": [
{
"group": "About",
"pages": [
"about/how-pangolin-works",
"about/pangolin-vs-traditional-reverse-proxy",
"about/pangolin-vs-vpn"
"$schema": "https://mintlify.com/docs.json",
"theme": "aspen",
"name": "Pangolin Docs",
"description": "Pangolin is a self-hosted alternative to Cloudflare Tunnels, designed to provide secure and highly-available ingress access to applications.",
"colors": {
"primary": "#F36117",
"light": "#F36117",
"dark": "#F36117"
},
"banner": {
"content": "We're hiring software engineers! [Click here](https://click.fossorial.io/L0OXr) to get in touch.",
"dismissible": true
},
"favicon": "/favicon.svg",
"navigation": {
"tabs": [
{
"tab": "Docs",
"groups": [
{
"group": "About",
"pages": [
"about/how-pangolin-works",
"about/pangolin-vs-traditional-reverse-proxy",
"about/pangolin-vs-vpn"
]
},
{
"group": "Pangolin",
"pages": [
"manage/nodes",
"manage/managed",
{
"group": "Sites",
"pages": [
"manage/sites/add-site",
"manage/sites/install-site",
"manage/sites/install-kubernetes",
"manage/sites/configure-site",
"manage/sites/update-site"
]
},
{
"group": "Resources",
"pages": [
"manage/resources/targets",
"manage/resources/tcp-udp-resources",
"manage/resources/client-resources"
]
},
"manage/healthchecks-failover",
"manage/geoblocking",
"manage/blueprints",
{
"group": "Clients",
"pages": [
"manage/clients/add-client",
"manage/clients/install-client",
"manage/clients/configure-client"
]
},
{
"group": "Access Control",
"pages": [
"manage/access-control/rules",
"manage/access-control/forwarded-headers",
"manage/access-control/login-page"
]
},
{
"group": "Identity Providers",
"pages": [
"manage/identity-providers/add-an-idp",
"manage/identity-providers/auto-provisioning",
"manage/identity-providers/openid-connect",
"manage/identity-providers/google",
"manage/identity-providers/azure",
"manage/identity-providers/pocket-id",
"manage/identity-providers/zitadel"
]
},
"manage/domains",
"manage/integration-api"
]
},
{
"group": "Self-host Managed Pangolin",
"pages": [
"self-host/quick-install-managed",
{
"group": "Manual Installation",
"pages": [
"self-host/manual/managed"
]
},
"self-host/choosing-a-vps",
"self-host/how-to-update"
]
},
{
"group": "Community Edition",
"pages": [
"self-host/quick-install",
{
"group": "Manual Installation",
"pages": [
"self-host/manual/docker-compose",
"self-host/manual/unraid"
]
},
"self-host/dns-and-networking",
"self-host/convert-managed",
"self-host/supporter-program",
"self-host/system-architecture",
{
"group": "Advanced Configuration",
"pages": [
"self-host/advanced/config-file",
"self-host/advanced/wild-card-domains",
"self-host/advanced/cloudflare-proxy",
"self-host/advanced/without-tunneling",
"self-host/advanced/container-cli-tool",
"self-host/advanced/database-options",
"self-host/advanced/integration-api"
]
},
{
"group": "Community Guides",
"pages": [
"self-host/community-guides/overview",
"self-host/community-guides/proxyprotocol",
"self-host/community-guides/geoblock",
"self-host/community-guides/crowdsec",
"self-host/community-guides/metrics",
"self-host/community-guides/homeassistant",
"self-host/community-guides/middlewaremanager",
"self-host/community-guides/traefiklogsdashboard"
]
},
"self-host/telemetry"
]
},
{
"group": "Development",
"pages": [
"development/contributing",
"development/feature-requests-and-bug-reports"
]
}
]
},
{
"tab": "Blog",
"href": "https://digpangolin.com/blog"
}
],
"global": {
"anchors": [
{
"anchor": "GitHub",
"href": "https://github.com/fosrl/pangolin",
"icon": "github"
},
{
"anchor": "Slack",
"href": "https://digpangolin.com/slack",
"icon": "slack"
},
{
"anchor": "Discord",
"href": "https://digpangolin.com/discord",
"icon": "discord"
},
{
"anchor": "Support Plans",
"href": "https://digpangolin.com/support",
"icon": "life-ring"
}
]
},
{
"group": "Pangolin",
"pages": [
"manage/nodes",
"manage/managed",
{
"group": "Sites",
"pages": [
"manage/sites/add-site",
"manage/sites/install-site",
"manage/sites/install-kubernetes",
"manage/sites/configure-site",
"manage/sites/update-site"
]
},
{
"group": "Resources",
"pages": [
"manage/resources/targets",
"manage/resources/tcp-udp-resources",
"manage/resources/client-resources"
]
},
"manage/healthchecks-failover",
"manage/geoblocking",
"manage/blueprints",
{
"group": "Clients",
"pages": [
"manage/clients/add-client",
"manage/clients/install-client",
"manage/clients/configure-client"
]
},
{
"group": "Access Control",
"pages": [
"manage/access-control/rules",
"manage/access-control/forwarded-headers",
"manage/access-control/login-page"
]
},
{
"group": "Identity Providers",
"pages": [
"manage/identity-providers/add-an-idp",
"manage/identity-providers/auto-provisioning",
"manage/identity-providers/openid-connect",
"manage/identity-providers/google",
"manage/identity-providers/azure",
"manage/identity-providers/pocket-id",
"manage/identity-providers/zitadel"
]
},
"manage/domains",
"manage/integration-api"
]
},
{
"group": "Self-host Managed Pangolin",
"pages": [
"self-host/quick-install-managed",
{
"group": "Manual Installation",
"pages": ["self-host/manual/managed"]
},
"self-host/choosing-a-vps",
"self-host/how-to-update"
]
},
{
"group": "Community Edition",
"pages": [
"self-host/quick-install",
{
"group": "Manual Installation",
"pages": [
"self-host/manual/docker-compose",
"self-host/manual/unraid"
]
},
"self-host/dns-and-networking",
"self-host/convert-managed",
"self-host/supporter-program",
"self-host/system-architecture",
{
"group": "Advanced Configuration",
"pages": [
"self-host/advanced/config-file",
"self-host/advanced/wild-card-domains",
"self-host/advanced/cloudflare-proxy",
"self-host/advanced/without-tunneling",
"self-host/advanced/container-cli-tool",
"self-host/advanced/database-options",
"self-host/advanced/integration-api"
]
},
{
"group": "Community Guides",
"pages": [
"self-host/community-guides/overview",
"self-host/community-guides/geoblock",
"self-host/community-guides/crowdsec",
"self-host/community-guides/metrics",
"self-host/community-guides/homeassistant",
"self-host/community-guides/middlewaremanager",
"self-host/community-guides/traefiklogsdashboard"
]
},
"self-host/telemetry"
]
},
{
"group": "Development",
"pages": [
"development/contributing",
"development/feature-requests-and-bug-reports"
]
}
]
},
{
"tab": "Blog",
"href": "https://digpangolin.com/blog"
}
],
"global": {
"anchors": [
{
"anchor": "GitHub",
"href": "https://github.com/fosrl/pangolin",
"icon": "github"
},
{
"anchor": "Slack",
"href": "https://digpangolin.com/slack",
"icon": "slack"
},
{
"anchor": "Discord",
"href": "https://digpangolin.com/discord",
"icon": "discord"
},
{
"anchor": "Support Plans",
"href": "https://digpangolin.com/support",
"icon": "life-ring"
}
]
}
},
"logo": {
"light": "/logo/light.png",
"dark": "/logo/dark.png",
"href": "https://docs.digpangolin.com"
},
"navbar": {
"links": [
{
"label": "Contact Us",
"href": "mailto:numbat@fossorial.io"
}
],
"primary": {
"type": "button",
"label": "Pangolin Dashboard",
"href": "https://pangolin.fossorial.io"
}
},
"footer": {
"socials": {
"github": "https://github.com/fosrl/pangolin",
"linkedin": "https://linkedin.com/company/digpangolin"
}
},
"integrations": {
"posthog": {
"apiKey": "phc_RIHQ7o2Y2hf8qms2nP62vpoJHEvsrw6TieflQGQO7yI",
"apiHost": "https://digpangolin.com/relay-O7yI"
}
},
"redirects": [
{
"source": "/telemetry",
"destination": "/self-host/telemetry"
}
]
}
},
"logo": {
"light": "/logo/light.png",
"dark": "/logo/dark.png",
"href": "https://docs.digpangolin.com"
},
"navbar": {
"links": [
{
"label": "Contact Us",
"href": "mailto:numbat@fossorial.io"
}
],
"primary": {
"type": "button",
"label": "Pangolin Dashboard",
"href": "https://pangolin.fossorial.io"
}
},
"footer": {
"socials": {
"github": "https://github.com/fosrl/pangolin",
"linkedin": "https://linkedin.com/company/digpangolin"
}
},
"integrations": {
"posthog": {
"apiKey": "phc_RIHQ7o2Y2hf8qms2nP62vpoJHEvsrw6TieflQGQO7yI",
"apiHost": "https://digpangolin.com/relay-O7yI"
}
},
"redirects": [
{
"source": "/telemetry",
"destination": "/self-host/telemetry"
}
]
}

View File

@@ -0,0 +1,162 @@
---
title: "Proxy Protocol"
description: "Using Proxy Protocol to Preserve Client IPs for TCP/UDP backends"
---
Did you ever want to get the real ip instead of newt's IP or traefik's IP for TCP/UDP applications? Then follow below, Just be warned this is not a begineer guide.
This guide shows how to enable Proxy Protocol manually until a GUI option becomes available.
⚠️ Its an advanced setup, so youll be editing configuration files and running cli commands. ⚠️
In Pangolin, make a TCP resource or UDP resource.
> **Note:** Not all applications support Proxy Protocol. If you send Proxy Protocol headers to an application that isn't configured for it or doesn't support it, the connection will fail entirely.
---
## Creating the Resource
In Pangolin, go into **Resources** and create a TCP or UDP route like you normally would — pointing it to your resource which accepts Proxy Protocol.
Say I'm using `tcp-8888` with Pangolin.
I configure it to hit my Proxy Protocolenabled service such as Minecraft Paper or Velocity.
It'll give you a **port** to put into the compose file and an **entryPoint** to add into the `traefik_config.yml`.
Only do the second, not the first.
---
## Add the EntryPoint
Add an entrypoint in `traefik_config.yml` for the port you intend to use.
```yaml
entryPoints:
tcp-22000:
address: ":22000/tcp"
```
I'm going to use `tcp-22000` for this, and in Traefik under **Gerbil**, I'm going to add the same mapping:
```yaml
gerbil:
image: fosrl/gerbil
container_name: gerbil
restart: unless-stopped
ports:
- 51820:51820/udp
- 21820:21820/udp
- 443:443/tcp
- 80:80/tcp
- 22000:22000/tcp
```
---
## Find the Service Address
Run the following command:
```bash
docker exec pangolin curl http://localhost:3001/api/v1/traefik-config | jq
```
Look for the entry that resembles:
```json
"tcp": {
"routers": {
"43-router": {
"entryPoints": [
"tcp-8888"
],
"service": "43-service",
"rule": "HostSNI(`*`)"
```
Follow this down further until you reach the service line — `43-service` in this example:
```json
"services": {
"43-service": {
"loadBalancer": {
"servers": [
{
"address": "100.89.128.4:58655"
}
]
}
},
```
Make a note of the address there. Keep in mind that _this address will change if you update the site on the target or change information about the target like the port or IP address or delete the target._
---
## Update Dynamic Configuration
Go into `config/traefik_dynamic.yml` and add:
### TCP Example
```yaml
tcp:
routers:
minecraft-rtr:
rule: "HostSNI(`*`)"
entryPoints:
- "tcp-22000"
service: minecraft-svc
services:
minecraft-svc:
loadBalancer:
serversTransport: proxy-protocol-v1 # Can be named anything really as long as it matches the defined transport.
servers:
- address: "100.89.128.4:58655"
serversTransports:
proxy-protocol-v1:
proxyProtocol:
version: 1 # Velocity can handle v2 also but in in doubt use version over version 2.
```
### UDP Example
```yaml
udp:
routers:
servicename-rtr:
entryPoints:
- "udp-22000"
service: servicename-svc
services:
servicename-svc:
loadBalancer:
serversTransport: proxyprotocol-udp
servers:
- address: "100.89.128.4:58655"
serversTransports:
proxyprotocol-udp:
proxyProtocol:
version: 1
```
---
Also do note.. If you change the dummy (8888) info at all for the destination or the port or the site.. you will need to repopulate the info all over again. Starting from the JQ line above.
---
## Downstream Applications
For downstream applications, you'll need to configure them to trust Proxy Protocol connections originating from the system where **Newt** connects to the service.
For example:
If the Newt is running on **Host B** at `192.168.1.5`,
your service on **Host A** at `192.168.1.4` needs to trust `192.168.1.5` as a trusted Proxy Protocol source.
Once Proxy Protocol is in play, the connection between Traefik and the backend **must** speak Proxy Protocol — otherwise it will refuse to connect.