Add Custom header usage to find the user IP

This commit is contained in:
MathieuHa
2022-10-15 18:49:41 +02:00
parent 552b30a9ef
commit 8eec1c5656
3 changed files with 14 additions and 11 deletions
+5
View File
@@ -74,6 +74,10 @@ At each start of synchronisation, the middleware will wait a random number of se
- []string - []string
- default: [] - default: []
- List of IPs of trusted Proxies that are in front of traefik (ex: Cloudflare) - List of IPs of trusted Proxies that are in front of traefik (ex: Cloudflare)
- ForwardedHeadersCustomName
- string
- default: X-Forwarded-For
- Name of the header where the real IP of the client should be retrieved
### Configuration ### Configuration
@@ -123,6 +127,7 @@ http:
forwardedHeadersTrustedIPs: forwardedHeadersTrustedIPs:
- 10.0.10.23/32 - 10.0.10.23/32
- 10.0.20.0/24 - 10.0.20.0/24
forwardedHeadersCustomName: X-Custom-Header
``` ```
These are the default values of the plugin except for LapiKey. These are the default values of the plugin except for LapiKey.
+6 -1
View File
@@ -28,6 +28,7 @@ const (
crowdsecLapiStreamRoute = "v1/decisions/stream" crowdsecLapiStreamRoute = "v1/decisions/stream"
cacheBannedValue = "t" cacheBannedValue = "t"
cacheNoBannedValue = "f" cacheNoBannedValue = "f"
xForwardedFor = "X-Forwarded-For"
) )
// Config the plugin configuration. // Config the plugin configuration.
@@ -40,6 +41,7 @@ type Config struct {
UpdateIntervalSeconds int64 `json:"updateIntervalSeconds,omitempty"` UpdateIntervalSeconds int64 `json:"updateIntervalSeconds,omitempty"`
DefaultDecisionSeconds int64 `json:"defaultDecisionSeconds,omitempty"` DefaultDecisionSeconds int64 `json:"defaultDecisionSeconds,omitempty"`
ForwardedHeadersTrustedIPs []string `json:"forwardedheaderstrustedips,omitempty"` ForwardedHeadersTrustedIPs []string `json:"forwardedheaderstrustedips,omitempty"`
ForwardedHeadersCustomName string `json:"forwardedheaderscustomheader,omitempty"`
} }
// CreateConfig creates the default plugin configuration. // CreateConfig creates the default plugin configuration.
@@ -53,6 +55,7 @@ func CreateConfig() *Config {
UpdateIntervalSeconds: 60, UpdateIntervalSeconds: 60,
DefaultDecisionSeconds: 60, DefaultDecisionSeconds: 60,
ForwardedHeadersTrustedIPs: []string{}, ForwardedHeadersTrustedIPs: []string{},
ForwardedHeadersCustomName: xForwardedFor,
} }
} }
@@ -70,6 +73,7 @@ type Bouncer struct {
crowdsecMode string crowdsecMode string
updateInterval int64 updateInterval int64
defaultDecisionTimeout int64 defaultDecisionTimeout int64
customHeader string
poolStrategy *ip.PoolStrategy poolStrategy *ip.PoolStrategy
client *http.Client client *http.Client
cache *ttl_map.Heap cache *ttl_map.Heap
@@ -96,6 +100,7 @@ func New(ctx context.Context, next http.Handler, config *Config, name string) (h
crowdsecHost: config.CrowdsecLapiHost, crowdsecHost: config.CrowdsecLapiHost,
crowdsecKey: config.CrowdsecLapiKey, crowdsecKey: config.CrowdsecLapiKey,
updateInterval: config.UpdateIntervalSeconds, updateInterval: config.UpdateIntervalSeconds,
customHeader: config.ForwardedHeadersCustomName,
defaultDecisionTimeout: config.DefaultDecisionSeconds, defaultDecisionTimeout: config.DefaultDecisionSeconds,
poolStrategy: &ip.PoolStrategy{ poolStrategy: &ip.PoolStrategy{
Checker: checker, Checker: checker,
@@ -198,7 +203,7 @@ func contains(source []string, target string) bool {
// It returns the first IP that is not in the pool, or the empty string otherwise. // It returns the first IP that is not in the pool, or the empty string otherwise.
func getRemoteIP(bouncer *Bouncer, req *http.Request) (string, error) { func getRemoteIP(bouncer *Bouncer, req *http.Request) (string, error) {
remoteIP := bouncer.poolStrategy.GetIP(req) remoteIP := bouncer.poolStrategy.GetIP(req, bouncer.customHeader)
if len(remoteIP) != 0 { if len(remoteIP) != 0 {
return remoteIP, nil return remoteIP, nil
} }
+3 -10
View File
@@ -80,16 +80,8 @@ func parseIP(addr string) (net.IP, error) {
return userIP, nil return userIP, nil
} }
// STRATEGY // STRATEGY
const (
xForwardedFor = "X-Forwarded-For"
)
// PoolStrategy is a strategy based on an IP Checker. // PoolStrategy is a strategy based on an IP Checker.
// It allows to check whether addresses are in a given pool of IPs. // It allows to check whether addresses are in a given pool of IPs.
type PoolStrategy struct { type PoolStrategy struct {
@@ -99,12 +91,13 @@ type PoolStrategy struct {
// GetIP checks the list of Forwarded IPs (most recent first) against the // GetIP checks the list of Forwarded IPs (most recent first) against the
// Checker pool of IPs. It returns the first IP that is not in the pool, or the // Checker pool of IPs. It returns the first IP that is not in the pool, or the
// empty string otherwise. // empty string otherwise.
func (s *PoolStrategy) GetIP(req *http.Request) string { func (s *PoolStrategy) GetIP(req *http.Request, customHeader string) string {
if s.Checker == nil { if s.Checker == nil {
return "" return ""
} }
xff := req.Header.Get(xForwardedFor) xff := req.Header.Get(customHeader)
xffs := strings.Split(xff, ",") xffs := strings.Split(xff, ",")
for i := len(xffs) - 1; i >= 0; i-- { for i := len(xffs) - 1; i >= 0; i-- {