The IP Policy provides comprehensive IP-based access control for your applications, supporting both IPv4 and IPv6 addresses, CIDR ranges, and proxy-aware client IP detection.
The IP Policy can operate in two modes:
ipPolicy := &gatekeeper.IPPolicyConfig{
Mode: gatekeeper.ModeBlacklist, // or ModeWhitelist
IPs: []string{"192.168.1.100", "10.0.0.50"},
CIDRs: []string{"192.168.1.0/24", "10.0.0.0/8"},
}
{
"ipPolicy": {
"mode": "BLACKLIST",
"ips": ["192.168.1.100", "203.0.113.45"],
"cidrs": ["192.168.1.0/24", "10.0.0.0/8"],
"trustProxyHeaders": true,
"trustedProxies": ["172.17.0.0/16"]
}
}
Option | Type | Required | Default | Description |
---|---|---|---|---|
mode |
PolicyMode |
Yes | - | BLACKLIST or WHITELIST |
ips |
[]string |
No | [] |
List of specific IP addresses |
cidrs |
[]string |
No | [] |
List of CIDR ranges |
trustProxyHeaders |
bool |
No | false |
Trust X-Forwarded-For headers |
trustedProxies |
[]string |
No | [] |
IPs/CIDRs of trusted proxies |
// Block specific IPs, allow everything else
ipPolicy := &gatekeeper.IPPolicyConfig{
Mode: gatekeeper.ModeBlacklist,
IPs: []string{"192.168.1.100", "203.0.113.45"},
CIDRs: []string{"10.0.0.0/8"},
}
Behavior:
ips
list or matching cidrs
ranges// Allow only specific IPs, block everything else
ipPolicy := &gatekeeper.IPPolicyConfig{
Mode: gatekeeper.ModeWhitelist,
IPs: []string{"192.168.1.10", "192.168.1.20"},
CIDRs: []string{"172.16.0.0/12"},
}
Behavior:
ips
list or matching cidrs
rangesWhen your application runs behind a proxy or load balancer:
ipPolicy := &gatekeeper.IPPolicyConfig{
Mode: gatekeeper.ModeBlacklist,
IPs: []string{"203.0.113.45"},
TrustProxyHeaders: true,
}
For enhanced security, specify which proxies to trust:
ipPolicy := &gatekeeper.IPPolicyConfig{
Mode: gatekeeper.ModeBlacklist,
IPs: []string{"203.0.113.45"},
TrustProxyHeaders: true,
TrustedProxies: []string{"172.17.0.0/16", "192.168.0.1"},
}
When TrustProxyHeaders
is enabled, the following headers are checked in order:
X-Forwarded-For
(first IP in chain)X-Real-IP
X-Client-IP
CF-Connecting-IP
(Cloudflare)True-Client-IP
(Akamai){
"ips": [
"192.168.1.100",
"203.0.113.45",
"10.0.0.1"
]
}
{
"ips": [
"2001:db8::1",
"::1",
"fe80::1%lo0"
]
}
{
"cidrs": [
"192.168.1.0/24", // IPv4 subnet
"10.0.0.0/8", // Large IPv4 range
"2001:db8::/32", // IPv6 subnet
"172.16.0.0/12" // Private IP range
]
}
// Block known bad actors
config := &gatekeeper.Config{
IPPolicy: &gatekeeper.IPPolicyConfig{
Mode: gatekeeper.ModeBlacklist,
IPs: []string{
"203.0.113.45", // Known bot
"198.51.100.100", // Malicious scanner
},
CIDRs: []string{
"192.0.2.0/24", // Suspicious network
},
},
}
// Allow only office IPs to access admin routes
config := &gatekeeper.Config{
IPPolicy: &gatekeeper.IPPolicyConfig{
Mode: gatekeeper.ModeWhitelist,
CIDRs: []string{
"203.0.113.0/24", // Office network
"198.51.100.0/24", // VPN range
},
IPs: []string{
"192.0.2.10", // CEO's home IP
},
},
}
// Behind AWS ALB or similar
config := &gatekeeper.Config{
IPPolicy: &gatekeeper.IPPolicyConfig{
Mode: gatekeeper.ModeBlacklist,
IPs: []string{"203.0.113.45"},
TrustProxyHeaders: true,
TrustedProxies: []string{
"172.31.0.0/16", // AWS VPC default range
"10.0.0.0/8", // Internal load balancers
},
},
}
// Trust Cloudflare proxy IPs
config := &gatekeeper.Config{
IPPolicy: &gatekeeper.IPPolicyConfig{
Mode: gatekeeper.ModeBlacklist,
IPs: []string{"203.0.113.45"},
TrustProxyHeaders: true,
TrustedProxies: []string{
// Cloudflare IPv4 ranges
"173.245.48.0/20",
"103.21.244.0/22",
"103.22.200.0/22",
"103.31.4.0/22",
// Add more Cloudflare ranges as needed
},
},
}
โ ๏ธ Important: Only enable TrustProxyHeaders
when you control the proxy layer.
// โ DANGEROUS: Trusting headers without validation
ipPolicy := &gatekeeper.IPPolicyConfig{
TrustProxyHeaders: true, // Anyone can spoof headers!
}
// โ
SAFE: Trusting headers only from known proxies
ipPolicy := &gatekeeper.IPPolicyConfig{
TrustProxyHeaders: true,
TrustedProxies: []string{"172.17.0.0/16"}, // Only trust Docker network
}
Ensure your blocklist includes both IPv4 and IPv6 versions:
ipPolicy := &gatekeeper.IPPolicyConfig{
Mode: gatekeeper.ModeBlacklist,
IPs: []string{
"203.0.113.45", // IPv4
"2001:db8::45", // IPv6 equivalent
},
}
Be careful with private IP ranges in production:
// Common private ranges
privateCIDRs := []string{
"10.0.0.0/8", // Class A private
"172.16.0.0/12", // Class B private
"192.168.0.0/16", // Class C private
"127.0.0.0/8", // Loopback
"169.254.0.0/16", // Link-local
}
// โ
Better
CIDRs: []string{"192.168.1.0/24"}
// โ Less efficient
IPs: []string{"192.168.1.1", "192.168.1.2", ..., "192.168.1.254"}
Cache Parsed Networks: The policy automatically caches parsed networks for better performance
func TestIPPolicy(t *testing.T) {
policy := &gatekeeper.IPPolicyConfig{
Mode: gatekeeper.ModeBlacklist,
IPs: []string{"192.168.1.100"},
CIDRs: []string{"10.0.0.0/8"},
}
// Test blocked IP
assert.True(t, policy.IsBlocked("192.168.1.100", nil))
// Test blocked CIDR
assert.True(t, policy.IsBlocked("10.0.0.50", nil))
// Test allowed IP
assert.False(t, policy.IsBlocked("203.0.113.45", nil))
}
# Test blocked IP
curl -H "X-Forwarded-For: 192.168.1.100" http://localhost:8080/
# Should return 403 Forbidden
# Test allowed IP
curl -H "X-Forwarded-For: 203.0.113.45" http://localhost:8080/
# Should return normal response