I've been testing Pangolin in an attempt to shift away from Cloudflare Tunnels.
Using the Target Rules based on IP Address (IPv4 or IPv6 - single or ranges) does not work.
However, the Target Rules based on path (for ex. /api/*) works fine on the same target, but this is a lot less secure than those based on IP addresses.
Debug logs: 2025-05-17T10:59:20.437Z [debug]: Verify session: Badger sent {"sessions":{},"originalRequestURL":"https://certs.example.com/","scheme":"","host":"certs.example.com","path":"/","method":"GET","tls":true,"requestIp":"[<correct-public-ipv6-host2>]:51002","headers":{"Accept":"*/*","User-Agent":"curl/7.88.1","X-Forwarded-Host":"certs.example.com","X-Forwarded-Port":"443","X-Forwarded-Proto":"https","X-Forwarded-Server":"amdvpn","X-Real-Ip":"<correct-public-ipv6-host2>"}} 2025-05-17T10:59:20.440Z [debug]: No more auth to check, resource not allowed 2025-05-17T10:59:20.440Z [debug]: {"data":{"valid":false,"redirectUrl":"https://pangolin.example.org/auth/resource/10?redirect=https%3A%2F%2Fcerts.example.com%2F"},"success":true,"error":false,"message":"Access denied","status":200} 2025-05-17T10:59:23.995Z [debug]: Verify session: Badger sent {"sessions":{},"originalRequestURL":"https://certs.example.com/","scheme":"","host":"certs.example.com","path":"/","method":"GET","tls":true,"requestIp":"[<correct-public-ipv6-host1>]:45430","headers":{"Accept":"*/*","User-Agent":"curl/7.88.1","X-Forwarded-Host":"certs.example.com","X-Forwarded-Port":"443","X-Forwarded-Proto":"https","X-Forwarded-Server":"amdvpn","X-Real-Ip":"<correct-public-ipv6-host1>"}} 2025-05-17T10:59:23.996Z [debug]: No more auth to check, resource not allowed 2025-05-17T10:59:23.996Z [debug]: {"data":{"valid":false,"redirectUrl":"https://pangolin.domain.com/auth/resource/10?redirect=https%3A%2F%2Fcerts.example.com%2F"},"success":true,"error":false,"message":"Access denied","status":200}
I did not use the installer but a manual docker compose and using HOST docker network_mode because using user mode pangolin network kept causing DNS 53 errors.
#networks:
# default:
# driver: bridge
# name: pangolin
services:
pangolin:
image: fosrl/pangolin:latest
container_name: pangolin
network_mode: host
restart: unless-stopped
volumes:
- ./config:/app/config
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3001/api/v1/"]
interval: "3s"
timeout: "3s"
retries: 15
gerbil:
image: fosrl/gerbil:latest
container_name: gerbil
network_mode: host
restart: unless-stopped
depends_on:
pangolin:
condition: service_healthy
command:
- --reachableAt=http://gerbil:3003
- --generateAndSaveKeyTo=/var/config/key
- --remoteConfig=http://pangolin:3001/api/v1/gerbil/get-config
- --reportBandwidthTo=http://pangolin:3001/api/v1/gerbil/receive-bandwidth
volumes:
- ./config/:/var/config
cap_add:
- NET_ADMIN
- SYS_MODULE
# ports:
# - 41820:41820/udp
# - 443:443/tcp # Port for traefik because of the network_mode
# - 80:80 # Port for traefik because of the network_mode
# - 443:443/udp # HTTP3/QUIC
traefik:
image: traefik:latest #v3.3.3
container_name: traefik
restart: unless-stopped
# network_mode: host
network_mode: service:gerbil # Ports appear on the gerbil service
depends_on:
pangolin:
condition: service_healthy
command:
- --configFile=/etc/traefik/traefik_config.yml
# Add the environment variables for your DNS provider.
environment:
CLOUDFLARE_DNS_API_TOKEN: "MyToken"
volumes:
- ./config/traefik:/etc/traefik:ro # Volume to store the Traefik configuration
- ./config/letsencrypt:/letsencrypt # Volume to store the Let's Encrypt certificates
#- ./config/traefik/rules:/rules # Non-functional/Breaking mount point from Middleware Manager container
I feel it's some wrong configuration somewhere, I'm unable to figure out.
Originally created by @dpurnam on GitHub (May 17, 2025).
Original GitHub issue: https://github.com/fosrl/pangolin/issues/741
Thank you very much for such a great thing.
I've been testing Pangolin in an attempt to shift away from Cloudflare Tunnels.
Using the Target Rules **based on IP Address** (IPv4 or IPv6 - single or ranges) does not work.
However, the Target Rules based **on path** (for ex. /api/*) works fine on the same target, but this is _a lot less secure_ than those based on IP addresses.
Debug logs:
`2025-05-17T10:59:20.437Z [debug]: Verify session: Badger sent {"sessions":{},"originalRequestURL":"https://certs.example.com/","scheme":"","host":"certs.example.com","path":"/","method":"GET","tls":true,"requestIp":"[<correct-public-ipv6-host2>]:51002","headers":{"Accept":"*/*","User-Agent":"curl/7.88.1","X-Forwarded-Host":"certs.example.com","X-Forwarded-Port":"443","X-Forwarded-Proto":"https","X-Forwarded-Server":"amdvpn","X-Real-Ip":"<correct-public-ipv6-host2>"}}
2025-05-17T10:59:20.440Z [debug]: No more auth to check, resource not allowed
2025-05-17T10:59:20.440Z [debug]: {"data":{"valid":false,"redirectUrl":"https://pangolin.example.org/auth/resource/10?redirect=https%3A%2F%2Fcerts.example.com%2F"},"success":true,"error":false,"message":"Access denied","status":200}
2025-05-17T10:59:23.995Z [debug]: Verify session: Badger sent {"sessions":{},"originalRequestURL":"https://certs.example.com/","scheme":"","host":"certs.example.com","path":"/","method":"GET","tls":true,"requestIp":"[<correct-public-ipv6-host1>]:45430","headers":{"Accept":"*/*","User-Agent":"curl/7.88.1","X-Forwarded-Host":"certs.example.com","X-Forwarded-Port":"443","X-Forwarded-Proto":"https","X-Forwarded-Server":"amdvpn","X-Real-Ip":"<correct-public-ipv6-host1>"}}
2025-05-17T10:59:23.996Z [debug]: No more auth to check, resource not allowed
2025-05-17T10:59:23.996Z [debug]: {"data":{"valid":false,"redirectUrl":"https://pangolin.domain.com/auth/resource/10?redirect=https%3A%2F%2Fcerts.example.com%2F"},"success":true,"error":false,"message":"Access denied","status":200}
`
I did not use the installer but a manual docker compose and using HOST docker network_mode because using user mode pangolin network kept causing DNS 53 errors.
```
#networks:
# default:
# driver: bridge
# name: pangolin
services:
pangolin:
image: fosrl/pangolin:latest
container_name: pangolin
network_mode: host
restart: unless-stopped
volumes:
- ./config:/app/config
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3001/api/v1/"]
interval: "3s"
timeout: "3s"
retries: 15
gerbil:
image: fosrl/gerbil:latest
container_name: gerbil
network_mode: host
restart: unless-stopped
depends_on:
pangolin:
condition: service_healthy
command:
- --reachableAt=http://gerbil:3003
- --generateAndSaveKeyTo=/var/config/key
- --remoteConfig=http://pangolin:3001/api/v1/gerbil/get-config
- --reportBandwidthTo=http://pangolin:3001/api/v1/gerbil/receive-bandwidth
volumes:
- ./config/:/var/config
cap_add:
- NET_ADMIN
- SYS_MODULE
# ports:
# - 41820:41820/udp
# - 443:443/tcp # Port for traefik because of the network_mode
# - 80:80 # Port for traefik because of the network_mode
# - 443:443/udp # HTTP3/QUIC
traefik:
image: traefik:latest #v3.3.3
container_name: traefik
restart: unless-stopped
# network_mode: host
network_mode: service:gerbil # Ports appear on the gerbil service
depends_on:
pangolin:
condition: service_healthy
command:
- --configFile=/etc/traefik/traefik_config.yml
# Add the environment variables for your DNS provider.
environment:
CLOUDFLARE_DNS_API_TOKEN: "MyToken"
volumes:
- ./config/traefik:/etc/traefik:ro # Volume to store the Traefik configuration
- ./config/letsencrypt:/letsencrypt # Volume to store the Let's Encrypt certificates
#- ./config/traefik/rules:/rules # Non-functional/Breaking mount point from Middleware Manager container
```
gerbil section in config.yml
```
gerbil:
start_port: 41820
# base_endpoint: "localhost"
use_subdomain: true
base_endpoint: "pangolin.domain.com"
# use_subdomain: false
block_size: 24
site_block_size: 30
subnet_group: 100.89.137.0/20
```
I feel it's some wrong configuration somewhere, I'm unable to figure out.
Why would badger treat a whitelisted IPv6 address defined under Resource Rules as an IPv4 Octet?
Error: Invalid IPv4 octet: [2402
at <unknown> (server/lib/ip.ts:26:26)
at Array.reduce (<anonymous>)
at Ad (server/lib/ip.ts:23:13)
at Ui (server/lib/ip.ts:206:21)
at vb (server/routers/badger/verifySession.ts:602:12)
at async DR (server/routers/badger/verifySession.ts:157:27)
24 | const num = parseInt(octet);
25 | if (isNaN(num) || num < 0 || num > 255) {
> 26 | throw new Error(`Invalid IPv4 octet: ${octet}`);
| ^
27 | }
28 | return BigInt.asUintN(64, (acc << BigInt(8)) + BigInt(num));
29 | }, BigInt(0));
Additionally, I get 'internal server' error upon browsing the resource, if a combination of Active IP rules exists which includes both - IPv4 address/range along with IPv6 address/range
Accessing the Resource redirects to Pangolin Auth (and not 'internal server' error page) either with only IPv4 rules activated or only IPv6 rules activated.
I can conclude that, in my setup:
Using IP based rules has no effect when Platform Auth is used
Even further only one type of IP (either IPv4 or IPv6) based rules redirects to the Auth Page, instead of redirecting to the Resource Page
<!-- gh-comment-id:2896673734 -->
@dpurnam commented on GitHub (May 21, 2025):
It gets weirder with IP based rules.
Why would badger treat a whitelisted IPv6 address defined under Resource Rules as an IPv4 Octet?
```
Error: Invalid IPv4 octet: [2402
at <unknown> (server/lib/ip.ts:26:26)
at Array.reduce (<anonymous>)
at Ad (server/lib/ip.ts:23:13)
at Ui (server/lib/ip.ts:206:21)
at vb (server/routers/badger/verifySession.ts:602:12)
at async DR (server/routers/badger/verifySession.ts:157:27)
24 | const num = parseInt(octet);
25 | if (isNaN(num) || num < 0 || num > 255) {
> 26 | throw new Error(`Invalid IPv4 octet: ${octet}`);
| ^
27 | }
28 | return BigInt.asUintN(64, (acc << BigInt(8)) + BigInt(num));
29 | }, BigInt(0));
```
Additionally, I get 'internal server' error upon browsing the resource, if a combination of Active IP rules exists which includes both - IPv4 address/range along with IPv6 address/range
Accessing the Resource redirects to Pangolin Auth (and not 'internal server' error page) either with only IPv4 rules activated or only IPv6 rules activated.
I can conclude that, in my setup:
1. Using IP based rules has no effect when Platform Auth is used
2. Even further only one type of IP (either IPv4 or IPv6) based rules redirects to the Auth Page, instead of redirecting to the Resource Page
@github-actions[bot] commented on GitHub (Jun 5, 2025):
This issue has been automatically marked as stale due to 14 days of inactivity. It will be closed in 14 days if no further activity occurs.
<!-- gh-comment-id:2942185018 -->
@github-actions[bot] commented on GitHub (Jun 5, 2025):
This issue has been automatically marked as stale due to 14 days of inactivity. It will be closed in 14 days if no further activity occurs.
After upgrading to latest versions as below, this issue doesn't exist anymore. Thank you so much.
Pangolin Image - 1.5.1 (from 1.4.0)
Badger Plugin - 1.2.0 (from 1.1.0)
<!-- gh-comment-id:3000043118 -->
@dpurnam commented on GitHub (Jun 24, 2025):
After upgrading to latest versions as below, this issue doesn't exist anymore. Thank you so much.
Pangolin Image - `1.5.1 (from 1.4.0)`
Badger Plugin - `1.2.0 (from 1.1.0)`
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Originally created by @dpurnam on GitHub (May 17, 2025).
Original GitHub issue: https://github.com/fosrl/pangolin/issues/741
Thank you very much for such a great thing.
I've been testing Pangolin in an attempt to shift away from Cloudflare Tunnels.
Using the Target Rules based on IP Address (IPv4 or IPv6 - single or ranges) does not work.
However, the Target Rules based on path (for ex. /api/*) works fine on the same target, but this is a lot less secure than those based on IP addresses.
Debug logs:
2025-05-17T10:59:20.437Z [debug]: Verify session: Badger sent {"sessions":{},"originalRequestURL":"https://certs.example.com/","scheme":"","host":"certs.example.com","path":"/","method":"GET","tls":true,"requestIp":"[<correct-public-ipv6-host2>]:51002","headers":{"Accept":"*/*","User-Agent":"curl/7.88.1","X-Forwarded-Host":"certs.example.com","X-Forwarded-Port":"443","X-Forwarded-Proto":"https","X-Forwarded-Server":"amdvpn","X-Real-Ip":"<correct-public-ipv6-host2>"}} 2025-05-17T10:59:20.440Z [debug]: No more auth to check, resource not allowed 2025-05-17T10:59:20.440Z [debug]: {"data":{"valid":false,"redirectUrl":"https://pangolin.example.org/auth/resource/10?redirect=https%3A%2F%2Fcerts.example.com%2F"},"success":true,"error":false,"message":"Access denied","status":200} 2025-05-17T10:59:23.995Z [debug]: Verify session: Badger sent {"sessions":{},"originalRequestURL":"https://certs.example.com/","scheme":"","host":"certs.example.com","path":"/","method":"GET","tls":true,"requestIp":"[<correct-public-ipv6-host1>]:45430","headers":{"Accept":"*/*","User-Agent":"curl/7.88.1","X-Forwarded-Host":"certs.example.com","X-Forwarded-Port":"443","X-Forwarded-Proto":"https","X-Forwarded-Server":"amdvpn","X-Real-Ip":"<correct-public-ipv6-host1>"}} 2025-05-17T10:59:23.996Z [debug]: No more auth to check, resource not allowed 2025-05-17T10:59:23.996Z [debug]: {"data":{"valid":false,"redirectUrl":"https://pangolin.domain.com/auth/resource/10?redirect=https%3A%2F%2Fcerts.example.com%2F"},"success":true,"error":false,"message":"Access denied","status":200}I did not use the installer but a manual docker compose and using HOST docker network_mode because using user mode pangolin network kept causing DNS 53 errors.
gerbil section in config.yml
I feel it's some wrong configuration somewhere, I'm unable to figure out.
@dpurnam commented on GitHub (May 21, 2025):
It gets weirder with IP based rules.
Why would badger treat a whitelisted IPv6 address defined under Resource Rules as an IPv4 Octet?
Additionally, I get 'internal server' error upon browsing the resource, if a combination of Active IP rules exists which includes both - IPv4 address/range along with IPv6 address/range
Accessing the Resource redirects to Pangolin Auth (and not 'internal server' error page) either with only IPv4 rules activated or only IPv6 rules activated.
I can conclude that, in my setup:
@github-actions[bot] commented on GitHub (Jun 5, 2025):
This issue has been automatically marked as stale due to 14 days of inactivity. It will be closed in 14 days if no further activity occurs.
@slimshizn commented on GitHub (Jun 5, 2025):
Still an issue.....
@miloschwartz commented on GitHub (Jun 5, 2025):
Will look into this
@dpurnam commented on GitHub (Jun 24, 2025):
After upgrading to latest versions as below, this issue doesn't exist anymore. Thank you so much.
Pangolin Image -
1.5.1 (from 1.4.0)Badger Plugin -
1.2.0 (from 1.1.0)