CallMeTechie
DE Login
Home Products Blog About Contact

Access Control

v1.x · Updated 3 weeks ago

Peer Access Control (ACL)

Restricts access to a route to selected WireGuard peers. Only devices connected through an allowed peer can reach the route — all other requests are blocked.

How does ACL work?

Without ACL:

Internet (any IP)   →  Caddy  →  nas.example.com  →  Backend  ✓
VPN Peer 10.8.0.3   →  Caddy  →  nas.example.com  →  Backend  ✓
VPN Peer 10.8.0.5   →  Caddy  →  nas.example.com  →  Backend  ✓

With ACL (only peer "Laptop" allowed):

Internet (any IP)   →  Caddy  →  nas.example.com  →  BLOCKED ✕
VPN Peer 10.8.0.3   →  Caddy  →  nas.example.com  →  Backend  ✓  (Laptop)
VPN Peer 10.8.0.5   →  Caddy  →  nas.example.com  →  BLOCKED ✕  (iPhone)

ACL effectively makes the route only accessible via VPN and additionally only for selected peers.

Technical Implementation

Caddy checks the client's IP address with the remote_ip matcher on every request:

  • VPN requests have a WireGuard IP (e.g. 10.8.0.3)
  • Internet requests have a public IP (e.g. 203.0.113.50)
  • The ACL list only contains WireGuard IPs of allowed peers
  • Public IPs are never in the list → always blocked

Use Cases

Admin Panel for Laptop Only

SourceIP at CaddyAccess
Office Laptop (VPN active)10.8.0.3Allowed
iPhone (VPN active)10.8.0.5Blocked
Any internet user203.0.113.xBlocked
Hacker / Bot45.33.x.xBlocked

Dev Server for the Dev Team Only

Route staging.example.com → Dev server on port 3000. ACL: Only peers "Dev-Laptop-1", "Dev-Laptop-2", "Dev-Laptop-3" allowed.

Different Services for Different Groups

RouteAllowed PeersPurpose
nas.example.comLaptop, SmartphoneFile access for admin
admin.example.comLaptop onlySensitive admin panel
public-api.example.comNo ACLPublic API without restrictions

Combination with Other Features

CombinationEffect
ACL + Route AuthVPN IP check first, then login with password/2FA
ACL + Rate LimitingVPN-only access with request limiting
ACL + IP Access ControlACL for VPN peers + IP filter for additional restriction
ACL aloneSimplest option: only selected VPN devices get through

Setup

Via UI

  1. Create or edit route
  2. Enable Peer Access Control toggle
  3. Select peers from checklist (multi-select possible)
  4. Save

Via API

# Enable ACL with selected peers (IDs: 1 and 3)
curl -X PUT https://gatecontrol.example.com/api/v1/routes/1 \
  -H "Authorization: Bearer gc_..." \
  -H "Content-Type: application/json" \
  -d '{"acl_enabled":true,"acl_peers":[1,3]}'

Important Notes on ACL

  • ACL only blocks access through Caddy (HTTP/HTTPS routes). Direct VPN access between peers is not restricted.
  • When a peer is disabled or deleted, it's automatically removed from the ACL.
  • ACL only works for HTTP routes, not L4 (TCP/UDP).
  • The ACL check is the first check Caddy performs — before auth, rate limiting, or other handlers.

IP Access Control (IP Filter)

Controls access to a route based on client IP address — via whitelist or blacklist with support for individual IPs, CIDR ranges, and country codes.

How does it work?

IP Access Control filters requests based on the client's IP address. Unlike Peer ACL (which only filters VPN peer IPs), the IP filter works with any IP address.

Whitelist mode (only allow these IPs):

203.0.113.50 (Office IP)    →  Caddy  →  Backend  ✓  (in whitelist)
198.51.100.10 (Home IP)     →  Caddy  →  BLOCKED ✕  (not in whitelist)
45.33.32.1 (Bot)            →  Caddy  →  BLOCKED ✕  (not in whitelist)

Blacklist mode (block these IPs):

203.0.113.50 (Office IP)    →  Caddy  →  Backend  ✓  (not in blacklist)
198.51.100.10 (Attacker)    →  Caddy  →  BLOCKED ✕  (in blacklist)
45.33.32.1 (CN Bot)         →  Caddy  →  BLOCKED ✕  (Country CN in blacklist)

Three Rule Types

TypeExampleCheck
Single IP203.0.113.50Exact match
CIDR range10.0.0.0/8Bitmask
Country codeDE, US, CNGeoIP lookup via ip2location.io API

Flow for Each Request

  1. Caddy forwards request to GateControl forward-auth
  2. GateControl extracts client IP (strips ::ffff: IPv6 prefix)
  3. Checks each rule sequentially (IP → CIDR → Country)
  4. Country lookup: API call to ip2location.io with 24h cache (max 10,000 entries)
  5. Whitelist: match → allowed, no match → blocked
  6. Blacklist: match → blocked, no match → allowed

Use Cases

Allow Office Network Only

Route internal.example.com → Internal app. Whitelist with CIDR 185.10.20.0/24 (office IP range).

Block Bot Traffic from Specific Countries

Route shop.example.com → Webshop. Blacklist with country codes CN, RU, KP.

Block Known Attacker IPs

Route api.example.com → API. Blacklist with individual IPs identified as attackers in logs.

Setup

Via UI

  1. Create or edit route
  2. Enable IP Access Control toggle
  3. Select mode: Whitelist or Blacklist
  4. Add rules: select type (IP, CIDR, Country), enter value
  5. Save

For country-based filtering: enter Settings → Advanced → ip2location.io API Key.

Via API

# Enable IP filter with whitelist
curl -X PUT https://gatecontrol.example.com/api/v1/routes/1 \
  -H "Authorization: Bearer gc_..." \
  -H "Content-Type: application/json" \
  -d '{"ip_filter_enabled":true,"ip_filter_mode":"whitelist","ip_filter_rules":[{"type":"cidr","value":"185.10.20.0/24"},{"type":"ip","value":"203.0.113.50"}]}'

# IP filter with country blacklist
curl -X PUT https://gatecontrol.example.com/api/v1/routes/1 \
  -H "Authorization: Bearer gc_..." \
  -H "Content-Type: application/json" \
  -d '{"ip_filter_enabled":true,"ip_filter_mode":"blacklist","ip_filter_rules":[{"type":"country","value":"CN"},{"type":"country","value":"RU"}]}'

Important Notes on IP Filter

  • Difference from Peer ACL: ACL only filters WireGuard peer IPs (10.8.0.x). IP Access Control filters any IP address.
  • Country lookup requires an ip2location.io API Key. Without a key, country rules are ignored.
  • The GeoIP cache stores up to 10,000 entries for 24 hours.
  • IPv6-mapped IPv4 addresses (::ffff:192.168.1.1) are automatically reduced to IPv4.
  • IP Access Control only works with Route Auth or as a standalone forward-auth check. With Basic Auth, the IP filter is not available.
  • An empty whitelist allows nobody. An empty blacklist blocks nobody.
  • Only available for HTTP routes, not L4.

Rate Limiting

Limits the number of requests per IP address within a time window — protects backends from overload, brute-force, and scraping.

How does it work?

Without Rate Limiting:

Bot sends 10,000 requests/minute  →  Backend processes all  →  Server overloaded

With Rate Limiting (100 requests/minute):

Bot sends 100 requests     →  Backend processes all  ✓
Bot sends request #101     →  Caddy: 429 Too Many Requests  ✕
... after 1 minute ...
Bot sends request #1       →  Backend processes  ✓  (new window)

Technical Details

{
  "handler": "rate_limit",
  "rate_limits": {
    "static": {
      "key": "{http.request.remote.host}",
      "window": "1m",
      "max_events": 100
    }
  }
}

Configurable Values

ParameterRangeDefaultDescription
Requests1 – 100,000100Maximum requests per time window
Window1s, 1m, 5m, 1h1mDuration of time window

Recommended Values

Use CaseRequestsWindow
Login page10–201m
REST API500–10005m
Webshop / Website60–1201m
Static assets1000–50001m
Webhook endpoint50–1001m

Combination with Other Features

CombinationEffect
Rate Limit + Route AuthRate limit after auth check — protects backend, not the login page
Rate Limit + Basic AuthRate limit before auth — also protects against brute-force on Basic Auth
Rate Limit + ACLOnly VPN peers get through, then rate-limited
Rate Limit + IP FilterIP filter blocks known IPs, rate limit slows down the rest

Setup

Via UI

  1. Create or edit route
  2. Enable Rate Limiting toggle
  3. Enter Requests (e.g. 100)
  4. Select Window (1s, 1m, 5m, 1h)
  5. Save

Via API

# Enable rate limiting: 100 requests per minute
curl -X PUT https://gatecontrol.example.com/api/v1/routes/1 \
  -H "Authorization: Bearer gc_..." \
  -H "Content-Type: application/json" \
  -d '{"rate_limit_enabled":true,"rate_limit_requests":100,"rate_limit_window":"1m"}'

Important Notes on Rate Limiting

  • Rate limiting is per IP address, not global. 100 requests/minute means each individual IP can make 100 requests.
  • Behind a NAT router, all clients share the same IP — the limit applies to all of them together.
  • Allowed window values: 1s, 1m, 5m, 1h. Other values are normalized to 1m.
  • HTTP 429 does not include a Retry-After header.
  • Only available for HTTP routes, not L4.
  • WebSocket connections only count the initial HTTP upgrade as one request.

Cookie Settings

We use cookies to improve your experience. Essential cookies are always active.

Privacy Policy
ESC
↑↓ navigate open esc close