Domain Sentinel
Overview
The domainSentinel plugin is a Traefik middleware designed to centrally manage access control based on source IP addresses, organized by domain and URL path. Instead of configuring access lists individually on routers, this plugin allows you to define and enforce those rules in one central location within Traefik.
It provides fine-grained control by allowing both domain-wide and path-specific whitelisting using individual IP addresses and CIDR blocks. This is especially useful for protecting administrative interfaces, staging environments, internal APIs, or other sensitive routes, ensuring only trusted sources can reach them.

Structs and Configuration Explanation
1. Config Struct
Purpose: Holds the entire plugin configuration, mapping domain names to their respective access rules.
Fields:
DomainPathRules
- Type:
map[string]DomainConfig
- Description: Maps each domain name to a
DomainConfig struct, which contains access rules for that domain and its paths.
2. DomainConfig Struct
Purpose: Contains source IP allowlists for a domain and its individual path rules.
Fields:
3. PathConfig Struct
Purpose: Defines access rules for a specific path pattern.
Fields:
-
Path
- Type:
string
- Description: The URL path to protect. Supports exact match or wildcard prefix (
/path/*).
- Example:
"/admin/*"
-
SourceIPs
How it Works
Middleware Flow
- Extracts the domain from the
Host header (ignoring any port).
- Looks up the domain config in
DomainPathRules.
- If no config is found → the request is allowed.
- Checks path-specific rules:
- If any rule’s
Path matches the request URL:
- Validates the request's source IP against the rule’s
SourceIPs.
- If the IP is allowed → the request proceeds.
- Else → the request is blocked with
403 Forbidden.
- Fallback to domain-wide IP rules if no path rule matches.
- Same logic applies using the
DomainConfig.SourceIPs.
IP Matching
- Supports both individual IPs (
203.0.113.5) and CIDR blocks (192.168.0.0/24).
- The client IP is derived from
req.RemoteAddr using net.SplitHostPort.
- All IP checks are done using Go's built-in
net.ParseIP and net.ParseCIDR.
Path Matching
- Paths can either:
- Match exactly:
/admin
- Use a wildcard:
/admin/* matches /admin/, /admin/settings, etc.
- If multiple path rules are defined, the first matching rule wins.
Example Configuration
http:
middlewares:
domain-sentinel:
plugin:
domainSentinel:
domainPathRules:
"www3.example.com":
sourceIPs:
- "192.168.1.0/24"
- "78.6.34.123"
- "10.10.3.112"
- "10.0.2.11"
"www4.example.com":
sourceIPs:
- "0.0.0.0/0"
pathRules:
- path: "/admin/*"
sourceIPs:
- "10.10.4.0/24"
- "192.168.1.2"
- "80.187.117.232"
- path: "/oai/*"
sourceIPs:
- "76.5.98.123"
Explanation
www3.example.com is protected globally, and all paths require IPs from the specified list.
www4.example.com allows all IPs (0.0.0.0/0) except for restricted paths:
/admin/* is restricted to specific internal and external IPs.
/oai/* only allows 76.5.98.123.
Code Highlights
ServeHTTP (Core Logic)
- Entry point for request handling.
- Extracts domain and path.
- Matches path rules or falls back to domain IP list.
- Validates IP → allows or blocks the request.
isPathAllowed
- Checks if request path matches a rule using exact or wildcard matching.
- Supports
/path/* pattern prefixing.
isIPAllowed
- Checks if client IP matches any allowed CIDR or exact IP.
- Uses
net.ParseIP, net.ParseCIDR and CIDR containment.
- Avoids misconfigured CIDRs by falling back to direct IP matching if needed.
Setup instructions
Step 1: Load/import the plugin into traefik
-
Edit your Traefik static configuration file (e.g., traefik.yml or traefik.toml), and add the plugin's Github repository:
Example: traefik.yml:
experimental:
plugins:
domainSentinel:
moduleName: "github.com/Rau-N/DomainSentinel"
version: "v1.0.0"
Ensure to use the current version tag.
Step 2: Configure Dynamic Configuration
-
Create a new or use an already existing dynamic configuration file (e.g., dynamic.yml) that defines how the plugin should behave:
Example dynamic.yml:
http:
middlewares:
domain-sentinel:
plugin:
domainSentinel:
domainPathRules:
"www3.example.com":
sourceIPs:
- "192.168.1.0/24"
- "78.6.34.123"
- "10.10.3.111"
"www4.example.com":
sourceIPs:
- "0.0.0.0/0"
pathRules:
- path: "/admin/*"
sourceIPs:
- "10.10.4.0/24"
- "192.168.1.2"
- path: "/oai/*"
sourceIPs:
- "76.5.98.123"
"www5.example.com":
sourceIPs:
- "10.10.3.0/24"
- "64.2.120.12"
- This configuration defines the global rules for the
domain-sentinel middleware, consisting of any combination of domain names, requested paths, and source IP addresses.
Step 3: Associate the middleware plugin to the entrypoint
-
Edit your Traefik static configuration file traefik.yml:
Example traefik.yml:
entryPoints:
webinsecure:
address: ":80"
http:
middlewares:
- domain-sentinel@file
- This configuration ensures that the
domain-sentinel middleware can analyze and intervene in the whole network traffic passing through the traefik proxy.
Step 4: Restart Traefik
-
Start or restart traefik to load the plugin and apply the new configuration
docker compose down && docker compose up -d