Add logic return to bypass when IP is unfiltered, update documentation

This commit is contained in:
MathieuHa
2022-11-19 12:16:20 +01:00
parent 3742b6b540
commit 5b0d4b533f
9 changed files with 128 additions and 9 deletions
+4
View File
@@ -31,6 +31,9 @@ run_behindproxy:
run_cacheredis: run_cacheredis:
docker-compose -f exemples/redis-cache/docker-compose.redis.yml up -d --remove-orphans docker-compose -f exemples/redis-cache/docker-compose.redis.yml up -d --remove-orphans
run_trustedips:
docker-compose -f exemples/trusted-ips/docker-compose.redis.yml up -d --remove-orphans
run: run:
docker-compose -f docker-compose.yml up -d --remove-orphans docker-compose -f docker-compose.yml up -d --remove-orphans
@@ -55,6 +58,7 @@ show_dev_logs:
clean_all_docker: clean_all_docker:
docker-compose -f exemples/behind-proxy/docker-compose.cloudflare.yml down --remove-orphans docker-compose -f exemples/behind-proxy/docker-compose.cloudflare.yml down --remove-orphans
docker-compose -f exemples/redis-cache/docker-compose.redis.yml down --remove-orphans docker-compose -f exemples/redis-cache/docker-compose.redis.yml down --remove-orphans
docker-compose -f exemples/trusted-ips/docker-compose.redis.yml down --remove-orphans
docker-compose -f docker-compose.local.yml down --remove-orphans docker-compose -f docker-compose.local.yml down --remove-orphans
docker-compose -f docker-compose.yml down --remove-orphans docker-compose -f docker-compose.yml down --remove-orphans
+44 -4
View File
@@ -142,6 +142,8 @@ http:
forwardedHeadersTrustedIPs: forwardedHeadersTrustedIPs:
- 10.0.10.23/32 - 10.0.10.23/32
- 10.0.20.0/24 - 10.0.20.0/24
trustedIPs:
- 192.168.1.0/24
forwardedHeadersCustomName: X-Custom-Header forwardedHeadersCustomName: X-Custom-Header
redisCacheEnabled: false redisCacheEnabled: false
redisCacheHost: "redis:6379" redisCacheHost: "redis:6379"
@@ -181,8 +183,8 @@ docker-compose up -d
```bash ```bash
docker-compose up -d crowdsec docker-compose up -d crowdsec
docker exec crowdsec cscli decisions add --ip 10.0.0.10 # this will be effective 4h docker exec crowdsec cscli decisions add --ip 10.0.0.10 -d 10m # this will be effective 10min
docker exec crowdsec cscli decisions remove --ip 10.0.0.10 docker exec crowdsec cscli decisions remove --ip 10.0.0.10 -d 10m
``` ```
### Local Mode ### Local Mode
@@ -236,7 +238,7 @@ We configure the middleware to trust as well the IP:
- "traefik.http.middlewares.crowdsec1.plugin.bouncer.forwardedheaderstrustedips=172.21.0.5" - "traefik.http.middlewares.crowdsec1.plugin.bouncer.forwardedheaderstrustedips=172.21.0.5"
``` ```
To run the environnement run: To play the demo environnement run:
```bash ```bash
make run_behindproxy make run_behindproxy
``` ```
@@ -249,11 +251,49 @@ The plugin must be configured to connect to a redis instance
``` ```
Here **redis** is the hostname of a container located in the same network as Traefik and **6379** the default port of redis Here **redis** is the hostname of a container located in the same network as Traefik and **6379** the default port of redis
To run the demo environnement run: To play the demo environnement run:
```bash ```bash
make run_cacheredis make run_cacheredis
``` ```
3. Using Trusted IP (ex: LAN OR VPN) that won't get filtered by crowdsec
You need to configure your Traefik to trust Forwarded headers by your front proxy
FIXME
// In the exemple we use another instance of traefik with the container to simulate a front proxy
The "internal" Traefik instance is configured to trust the forward headers
```yaml
- "--entrypoints.web.forwardedheaders.trustedips=172.21.0.5"
```
We configure the middleware to trust as well the IP:
```yaml
- "traefik.http.middlewares.crowdsec.plugin.bouncer.forwardedheaderstrustedips=172.21.0.5"
```
Add your IP to the ban list
```bash
docker exec crowdsec cscli decisions add --ip 10.0.10.30 -d 10m
```
You should get a 403 on http://localhost/foo
> Replace *10.0.10.30* by your IP
And the IPS that will not be filtered by the plugin
```yaml
- "traefik.http.middlewares.crowdsec.plugin.bouncer.trustedips=10.0.10.30/32"
```
> Replace *10.0.10.30/32* by your IP or IP range, so it's not getting checked against ban cache of crowdsec
You should get a 200 on http://localhost/foo
To play the demo environnement run:
```bash
make run_trustedips
```
### About ### About
Me and [mathieuHa](https://github.com/mathieuHa) have been using traefik since 2020 at [Primadviz](https://primadviz.com). Me and [mathieuHa](https://github.com/mathieuHa) have been using traefik since 2020 at [Primadviz](https://primadviz.com).
+3 -2
View File
@@ -53,7 +53,7 @@ type Config struct {
func CreateConfig() *Config { func CreateConfig() *Config {
return &Config{ return &Config{
Enabled: false, Enabled: false,
LogLevel: "DEBUG", LogLevel: "INFO",
CrowdsecMode: liveMode, CrowdsecMode: liveMode,
CrowdsecLapiScheme: "http", CrowdsecLapiScheme: "http",
CrowdsecLapiHost: "crowdsec:8080", CrowdsecLapiHost: "crowdsec:8080",
@@ -162,7 +162,6 @@ func (bouncer *Bouncer) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
bouncer.next.ServeHTTP(rw, req) bouncer.next.ServeHTTP(rw, req)
return return
} }
logger.Debug(fmt.Sprintf("ServeHTTP ip:%v", remoteHost))
if bouncer.CheckerTrusted == nil { if bouncer.CheckerTrusted == nil {
logger.Debug("CheckerTrusted == nil") logger.Debug("CheckerTrusted == nil")
} else { } else {
@@ -173,7 +172,9 @@ func (bouncer *Bouncer) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
} }
// if our IP is in the trusted list we bypass the next checks // if our IP is in the trusted list we bypass the next checks
if trusted { if trusted {
logger.Debug(fmt.Sprintf("IP %v is trusted", remoteHost))
bouncer.next.ServeHTTP(rw, req) bouncer.next.ServeHTTP(rw, req)
return
} }
} }
+1 -1
View File
@@ -13,7 +13,7 @@ services:
- "--entrypoints.web.address=:80" - "--entrypoints.web.address=:80"
- "--experimental.plugins.bouncer.modulename=github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin" - "--experimental.plugins.bouncer.modulename=github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin"
- "--experimental.plugins.bouncer.version=v1.1.0" - "--experimental.plugins.bouncer.version=v1.1.2"
volumes: volumes:
- "/var/run/docker.sock:/var/run/docker.sock:ro" - "/var/run/docker.sock:/var/run/docker.sock:ro"
- "logs:/var/log/traefik" - "logs:/var/log/traefik"
@@ -34,7 +34,7 @@ services:
- "--entrypoints.web.forwardedheaders.trustedips=172.21.0.5" - "--entrypoints.web.forwardedheaders.trustedips=172.21.0.5"
- "--experimental.plugins.bouncer.modulename=github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin" - "--experimental.plugins.bouncer.modulename=github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin"
- "--experimental.plugins.bouncer.version=v1.1.0" - "--experimental.plugins.bouncer.version=v1.2.0"
volumes: volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro - /var/run/docker.sock:/var/run/docker.sock:ro
- logs-dev:/var/log/traefik - logs-dev:/var/log/traefik
@@ -33,7 +33,7 @@ services:
labels: labels:
- "traefik.enable=true" - "traefik.enable=true"
# Definition of the router # Definition of the router
- "traefik.http.routers.router1.rule=Host(`localhost`)" - "traefik.http.routers.router1.rule=Path(`/foo`)"
- "traefik.http.routers.router1.entrypoints=web" - "traefik.http.routers.router1.entrypoints=web"
- "traefik.http.routers.router1.middlewares=crowdsec1@docker" - "traefik.http.routers.router1.middlewares=crowdsec1@docker"
# Definition of the service # Definition of the service
+4
View File
@@ -0,0 +1,4 @@
filenames:
- /var/log/traefik/access.log
labels:
type: traefik
@@ -0,0 +1,66 @@
version: "3.8"
services:
traefik:
image: "traefik:v2.9.4"
container_name: "traefik"
command:
# - "--log.level=DEBUG"
- "--accesslog"
- "--accesslog.filepath=/var/log/traefik/access.log"
- "--api.insecure=true"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
- "--experimental.plugins.bouncer.modulename=github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin"
- "--experimental.plugins.bouncer.version=v1.1.2"
# - "--experimental.localplugins.bouncer.modulename=github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- logs-trustedips:/var/log/traefik
- ./../../:/plugins-local/src/github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin
ports:
- 80:80
- 8080:8080
depends_on:
- crowdsec
whoami1:
image: traefik/whoami
container_name: "simple-service1"
labels:
- "traefik.enable=true"
# Definition of the router
- "traefik.http.routers.router1.rule=Path(`/foo`)"
- "traefik.http.routers.router1.entrypoints=web"
- "traefik.http.routers.router1.middlewares=crowdsec@docker"
# Definition of the service
- "traefik.http.services.service1.loadbalancer.server.port=80"
# Definition of the middleware
- "traefik.http.middlewares.crowdsec.plugin.bouncer.enabled=true"
# crowdseclapikey must be uniq to the middleware attached to the service
- "traefik.http.middlewares.crowdsec.plugin.bouncer.crowdseclapikey=40796d93c2958f9e58345514e67740e5"
# Replace 10.0.10.30/32 by your IP range which is "trusted"
- "traefik.http.middlewares.crowdsec.plugin.bouncer.trustedips=10.0.10.30/32"
crowdsec:
image: crowdsecurity/crowdsec:v1.4.1
container_name: "crowdsec"
environment:
COLLECTIONS: crowdsecurity/traefik
CUSTOM_HOSTNAME: crowdsec
BOUNCER_KEY_TRAEFIK_DEV_1: 40796d93c2958f9e58345514e67740e5
volumes:
- ./acquis.yaml:/etc/crowdsec/acquis.yaml:ro
- logs-trustedips:/var/log/traefik:ro
- crowdsec-db-trustedips:/var/lib/crowdsec/data/
- crowdsec-config-trustedips:/etc/crowdsec/
labels:
- "traefik.enable=false"
volumes:
logs-trustedips:
crowdsec-db-trustedips:
crowdsec-config-trustedips:
+4
View File
@@ -6,6 +6,8 @@ import (
"net" "net"
"net/http" "net/http"
"strings" "strings"
"github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin/pkg/logger"
) )
// CHECKER // CHECKER
@@ -27,6 +29,7 @@ func NewChecker(trustedIPs []string) (*Checker, error) {
for _, ipMask := range trustedIPs { for _, ipMask := range trustedIPs {
if ipAddr := net.ParseIP(ipMask); ipAddr != nil { if ipAddr := net.ParseIP(ipMask); ipAddr != nil {
checker.authorizedIPs = append(checker.authorizedIPs, &ipAddr) checker.authorizedIPs = append(checker.authorizedIPs, &ipAddr)
logger.Debug(fmt.Sprintf("IP %v is trusted", ipAddr))
continue continue
} }
@@ -35,6 +38,7 @@ func NewChecker(trustedIPs []string) (*Checker, error) {
return nil, fmt.Errorf("parsing CIDR trusted IPs %s: %w", ipAddr, err) return nil, fmt.Errorf("parsing CIDR trusted IPs %s: %w", ipAddr, err)
} }
checker.authorizedIPsNet = append(checker.authorizedIPsNet, ipAddr) checker.authorizedIPsNet = append(checker.authorizedIPsNet, ipAddr)
logger.Debug(fmt.Sprintf("IP network %v is trusted", ipAddr))
} }
return checker, nil return checker, nil