Skip to content

Instantly share code, notes, and snippets.

@proofrock
Last active November 18, 2025 11:05
Show Gist options
  • Select an option

  • Save proofrock/082c3c6343572f6aaec3856a7afd813d to your computer and use it in GitHub Desktop.

Select an option

Save proofrock/082c3c6343572f6aaec3856a7afd813d to your computer and use it in GitHub Desktop.

This adds IP filtering for the Pangolin console; it will work normally for the Pangolin resources, but access to the console will be restricted to connections coming from a given IP.

I tested it with the following versions; it should work with several other too.

  • Pangolin 1.12.1
  • Gerbil 1.2.2
  • Traefik 3.5.4
  • Badger 1.2.1

Things to replace in the instructions below:

  • base URL of the console (below, look for pan.example.com)
  • IP address to allow (below, look for 123.456.789.123)

Step 1 - install haproxy and configure gerbil

  1. Edit the docker-compose.yaml you already have, adding the haproxy service and disabling port 80/443 for gerbil.
services:
  haproxy:
    image: haproxy:alpine
    container_name: haproxy
    depends_on:
      pangolin:
        condition: service_healthy
    restart: unless-stopped
    networks:
      - default
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro
  
  [...]
  
  gerbil:
    [...]
    ports:
      - 51820:51820/udp
# Commented out as they're managed by haproxy
#      - 443:443 # Port for traefik because of the network_mode
#      - 80:80 # Port for traefik because of the network_mode
    [...]

Step 2 - enable proxy protocol for traefik

  1. Get the internal CIDR of the pangolin (also called default) subnet in Pangolin
$ docker network inspect pangolin | grep Subnet
                    "Subnet": "172.18.0.0/16",
  1. Edit the traefik config file, config/traefik/traefik_config.yml:
[...]
entryPoints:
  web:
    address: ":80"
    proxyProtocol: # Add this block
      trustedIPs:
        - "172.18.0.0/16"
  websecure:
    address: ":443"
    proxyProtocol: # Add this block
      trustedIPs:
        - "172.18.0.0/16"
[...]

Step 3 - define the haproxy.cfg config file for haproxy

  1. Put this in the same path as docker-compose.yaml and replace the placeholder values (pan.example.com and 123.456.789.123) in the acl lines
global
    log stdout format raw local0
    maxconn 4096

defaults
    log global
    mode tcp
    option tcplog
    timeout connect 5s
    timeout client 50s
    timeout server 50s

frontend http_in
    bind *:80
    mode tcp
    default_backend pangolin_http

frontend https_in
    bind *:443
    mode tcp
    tcp-request inspect-delay 5s

    # Define ACLs
    acl is_ip_limited req.ssl_sni -i pan.example.com
    acl allowed_ip src 123.456.789.123

    # Block limited endpoint unless from allowed IP
    tcp-request content reject if is_ip_limited !allowed_ip

    # Else accept SSL traffic
    tcp-request content accept if { req_ssl_hello_type 1 }

    default_backend pangolin_https

backend pangolin_http
    mode tcp
    server pangolin gerbil:80 send-proxy-v2 check

backend pangolin_https
    mode tcp
    server pangolin gerbil:443 send-proxy-v2 check

Step 4 - apply everything

$ docker compose pull
$ docker compose up -d
$ docker restart traefik
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment