Compare commits

...
6 Commits
Author SHA1 Message Date
mathieuHaandMax Lerebourg 07c8fae927 🔧 Add conf variable: CrowdsecStreamTimeout (#110)
* 🔧 Add conf variable: CrowdsecStreamTimeout

* 🥅 catch error from sscan

*  fix ugly code

* 🐛 clean code

*  fix type + wrong type assertion

* 🚨 fix lint go simplify

* 📝 Update readme with new variable

* 🍱 fix variable naming

* 🍱 revert vendor file

* 🍱 fix lint

---------

Co-authored-by: Max Lerebourg <maxlerebourg@gmail.com>
2023-08-20 15:49:49 +02:00
mathieuHa 13c209be3f 📝 First version of doc update with single bouncer instance (#108) 2023-08-05 16:01:50 +02:00
maxlerebourg 93340ffa55 🍱 update dependencies redisclient to reduce memory consumption (#105)
* 🍱 update dependencies to avoid memory leak

* 🍱 update dep
2023-06-20 09:22:51 +02:00
maxlerebourg 0c2668d578 add redis database selection (#100)
*  add redis database selection

* 📝 update docs

* 📝 readme
2023-05-25 17:20:14 +02:00
maxlerebourg abae7ee028 📝 update version used (#97)
* 📝 update version used

* 📝 update doc

* 📝 documentation

* 📝 documentation

* 📝 versionning
2023-04-17 09:25:57 +02:00
maxlerebourg 1fcd4f4e2f remove down at start if crowdsec unavailable (#93)
*  remove down at start if crowdsec unavailable

* 🚨 fix lint
2023-03-12 20:49:00 +01:00
22 changed files with 198 additions and 169 deletions
+2
View File
@@ -30,4 +30,6 @@ Steps to reproduce the behavior:
3. Scroll down to '....'
4. See error
<!---
If you like the plugin, please consider starring it, so you can get updates and we get some more visibility ✨
-->
@@ -16,4 +16,6 @@ A clear and concise description of what you want to happen.
**Additional context**
Add any other context or screenshots about the feature request here.
<!---
If you like the plugin, please consider starring it, so you can get updates and we get some more visibility ✨
-->
+13 -1
View File
@@ -29,7 +29,7 @@ There are 4 operating modes (CrowdsecMode) for this plugin:
The `streaming mode` is recommended for performance, decisions are updated every 60 sec by default and that's the only communication between Traefik and Crowdsec. Every request that happens hits the cache for quick decisions.
The cache can be local to Traefik using the filesystem, or a separate Redis instance.
Support for Redis is currently in beta (requires version 7.0.X of Redis).
## Usage
@@ -44,6 +44,7 @@ make run
**/!\ Cache is shared by all services**
*This means if an IP is banned, all services which are protected by an instance of the plugin will deny requests from that IP*
Only one instance of the plugin is *possible*.
### Variables
- Enabled
@@ -107,6 +108,14 @@ make run
- string
- default: ""
- Password for the Redis service
- RedisCacheDatabase
- string
- default: ""
- Database selection for the Redis service
- HTTPTimeoutSeconds
- int64
- default: 10
- Default timeout in seconds for contacting Crowdsec LAPI
- UpdateIntervalSeconds
- int64
- default: 60
@@ -138,6 +147,7 @@ experimental:
plugins:
bouncer:
moduleName: github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin
version: vX.Y.Z # To update
```
```yaml
@@ -167,6 +177,7 @@ http:
logLevel: DEBUG
updateIntervalSeconds: 60
defaultDecisionSeconds: 60
httpTimeoutSeconds: 10
crowdsecMode: live
crowdsecLapiKey: privateKey-foo
crowdsecLapiKeyFile: /etc/traefik/cs-privateKey-foo
@@ -188,6 +199,7 @@ http:
redisCacheEnabled: false
redisCacheHost: "redis:6379"
redisCachePassword: password
redisCacheDatabase: "5"
crowdsecLapiTLSCertificateAuthority: |-
-----BEGIN CERTIFICATE-----
MIIEBzCCAu+gAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwgZQxCzAJBgNVBAYTAlVT
+18 -12
View File
@@ -137,14 +137,18 @@ func New(ctx context.Context, next http.Handler, config *configuration.Config, n
IdleConnTimeout: 30 * time.Second,
TLSClientConfig: tlsConfig,
},
Timeout: 10 * time.Second,
Timeout: time.Duration(config.HTTPTimeoutSeconds) * time.Second,
},
cacheClient: &cache.Client{},
}
config.RedisCachePassword, _ = configuration.GetVariable(config, "RedisCachePassword")
bouncer.cacheClient.New(config.RedisCacheEnabled, config.RedisCacheHost, config.RedisCachePassword)
bouncer.cacheClient.New(
config.RedisCacheEnabled,
config.RedisCacheHost,
config.RedisCachePassword,
config.RedisCacheDatabase,
)
//nolint:nestif
if (config.CrowdsecMode == configuration.StreamMode || config.CrowdsecMode == configuration.AloneMode) && ticker == nil {
if config.CrowdsecMode == configuration.AloneMode {
if err := getToken(bouncer); err != nil {
@@ -152,17 +156,10 @@ func New(ctx context.Context, next http.Handler, config *configuration.Config, n
return nil, err
}
}
if err := handleStreamCache(bouncer); err != nil {
return nil, err
}
handleStreamTicker(bouncer)
isStartup = false
ticker = startTicker(config, func() {
if err := handleStreamCache(bouncer); err != nil {
isCrowdsecStreamHealthy = false
logger.Error(err.Error())
} else {
isCrowdsecStreamHealthy = true
}
handleStreamTicker(bouncer)
})
}
logger.Debug(fmt.Sprintf("New initialized mode:%s", config.CrowdsecMode))
@@ -269,6 +266,15 @@ type Login struct {
Expire string `json:"expire"`
}
func handleStreamTicker(bouncer *Bouncer) {
if err := handleStreamCache(bouncer); err != nil {
isCrowdsecStreamHealthy = false
logger.Error(err.Error())
} else {
isCrowdsecStreamHealthy = true
}
}
func startTicker(config *configuration.Config, work func()) chan bool {
ticker := time.NewTicker(time.Duration(config.UpdateIntervalSeconds) * time.Second)
stop := make(chan bool, 1)
+2 -2
View File
@@ -2,7 +2,7 @@ version: "3.8"
services:
traefik:
image: "traefik:v2.9.6"
image: "traefik:v2.9.10"
container_name: "traefik"
restart: unless-stopped
command:
@@ -52,7 +52,7 @@ services:
- "traefik.http.middlewares.crowdsec-bar.plugin.bouncer.crowdseclapikey=44c36dac5c4140af9f06f397508e82c7"
crowdsec:
image: crowdsecurity/crowdsec:v1.4.1
image: crowdsecurity/crowdsec:v1.4.6
container_name: "crowdsec"
restart: unless-stopped
environment:
+3 -3
View File
@@ -2,7 +2,7 @@ version: "3.8"
services:
traefik:
image: "traefik:v2.9.6"
image: "traefik:v2.9.10"
container_name: "traefik"
restart: unless-stopped
command:
@@ -14,7 +14,7 @@ services:
- "--entrypoints.web.address=:80"
- "--experimental.plugins.bouncer.modulename=github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin"
- "--experimental.plugins.bouncer.version=v1.1.8"
- "--experimental.plugins.bouncer.version=v1.1.11"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock:ro"
- "logs:/var/log/traefik"
@@ -63,7 +63,7 @@ services:
- "traefik.http.middlewares.crowdsec-bar.plugin.bouncer.forwardedheaderstrustedips=172.21.0.5"
crowdsec:
image: crowdsecurity/crowdsec:v1.4.1
image: crowdsecurity/crowdsec:v1.4.6
container_name: "crowdsec"
restart: unless-stopped
environment:
@@ -2,7 +2,7 @@ version: "3.8"
services:
cloudflare:
image: "traefik:v2.9.6"
image: "traefik:v2.10.4"
container_name: "cloudflare"
restart: unless-stopped
command:
@@ -12,7 +12,6 @@ services:
- "--api.insecure=true"
- "--entrypoints.web.address=:80"
- "--providers.file.filename=/cloud.yaml"
- "--experimental.localplugins.bouncer.modulename=github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./cloudflare-exemple.yaml:/cloud.yaml:ro
@@ -22,7 +21,7 @@ services:
- 8080:8080
traefik:
image: "traefik:v2.9.6"
image: "traefik:v2.10.4"
container_name: "traefik"
restart: unless-stopped
command:
@@ -36,7 +35,7 @@ services:
- "--entrypoints.web.forwardedheaders.trustedips=172.21.0.5"
- "--experimental.plugins.bouncer.modulename=github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin"
- "--experimental.plugins.bouncer.version=v1.1.7"
- "--experimental.plugins.bouncer.version=v1.1.13"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- logs-traefik:/var/log/traefik
@@ -46,7 +45,7 @@ services:
depends_on:
- crowdsec
whoami1:
whoami-foo:
image: traefik/whoami
container_name: "simple-service-foo"
restart: unless-stopped
@@ -58,15 +57,14 @@ services:
- "traefik.http.routers.router-foo.middlewares=crowdsec-foo@docker"
# Definition of the service
- "traefik.http.services.service-foo.loadbalancer.server.port=80"
# Definitin of the middleware
- "traefik.http.middlewares.crowdsec-foo.plugin.bouncer.enabled=true"
# crowdseclapikey must be uniq to the middleware attached to the service
- "traefik.http.middlewares.crowdsec-foo.plugin.bouncer.crowdseclapikey=40796d93c2958f9e58345514e67740e5"
- "traefik.http.middlewares.crowdsec-foo.plugin.bouncer.crowdsecmode=live"
- "traefik.http.middlewares.crowdsec-foo.plugin.bouncer.forwardedheaderstrustedips=172.21.0.5"
- "traefik.http.middlewares.crowdsec-foo.plugin.bouncer.loglevel=DEBUG"
# Definition of the middleware
- "traefik.http.middlewares.crowdsec.plugin.bouncer.enabled=true"
- "traefik.http.middlewares.crowdsec.plugin.bouncer.crowdseclapikey=40796d93c2958f9e58345514e67740e5"
- "traefik.http.middlewares.crowdsec.plugin.bouncer.crowdsecmode=live"
- "traefik.http.middlewares.crowdsec.plugin.bouncer.forwardedheaderstrustedips=172.21.0.5"
- "traefik.http.middlewares.crowdsec.plugin.bouncer.loglevel=DEBUG"
whoami2:
whoami-bar:
image: traefik/whoami
container_name: "simple-service-bar"
restart: unless-stopped
@@ -78,24 +76,22 @@ services:
- "traefik.http.routers.router-bar.middlewares=crowdsec-bar@docker"
# Definition of the service
- "traefik.http.services.service-bar.loadbalancer.server.port=80"
# Definitin of the middleware
# Definition of the middleware
- "traefik.http.middlewares.crowdsec-bar.plugin.bouncer.enabled=true"
# crowdseclapikey must be uniq to the middleware attached to the service
- "traefik.http.middlewares.crowdsec-bar.plugin.bouncer.crowdseclapikey=44c36dac5c4140af9f06f397508e82c7"
- "traefik.http.middlewares.crowdsec-bar.plugin.bouncer.crowdsecmode=live"
- "traefik.http.middlewares.crowdsec-bar.plugin.bouncer.forwardedheaderstrustedips=172.21.0.5"
- "traefik.http.middlewares.crowdsec-bar.plugin.bouncer.loglevel=DEBUG"
- "traefik.http.middlewares.crowdsec.plugin.bouncer.crowdseclapikey=40796d93c2958f9e58345514e67740e5"
- "traefik.http.middlewares.crowdsec.plugin.bouncer.crowdsecmode=live"
- "traefik.http.middlewares.crowdsec.plugin.bouncer.forwardedheaderstrustedips=172.21.0.5"
- "traefik.http.middlewares.crowdsec.plugin.bouncer.loglevel=DEBUG"
crowdsec:
image: crowdsecurity/crowdsec:v1.4.3
image: crowdsecurity/crowdsec:v1.5.2
container_name: "crowdsec"
restart: unless-stopped
environment:
COLLECTIONS: crowdsecurity/traefik
CUSTOM_HOSTNAME: crowdsec
BOUNCER_KEY_TRAEFIK_DEV_1: 40796d93c2958f9e58345514e67740e5
BOUNCER_KEY_TRAEFIK_DEV_2: 44c36dac5c4140af9f06f397508e82c7
BOUNCER_KEY_TRAEFIK_DEV: 40796d93c2958f9e58345514e67740e5
volumes:
- ./acquis.yaml:/etc/crowdsec/acquis.yaml:ro
- logs-cloudflare:/var/log/traefik:ro
@@ -2,7 +2,7 @@
DEBIAN_FRONTEND=noninteractive sudo apt-get update && sudo apt-get install wget -y
# DEBIAN_FRONTEND=noninteractive sudo apt-get upgrade -y --assume-yes
wget -O traefik.tar.gz "https://github.com/traefik/traefik/releases/download/v2.9.6/traefik_v2.9.6_linux_amd64.tar.gz"
wget -O traefik.tar.gz "https://github.com/traefik/traefik/releases/download/v2.10.4/traefik_v2.10.4_linux_amd64.tar.gz"
tar -zxvf traefik.tar.gz
# inspired from https://gist.github.com/ubergesundheit/7c9d875befc2d7bfd0bf43d8b3862d85
sudo mv ./traefik /usr/local/bin/
+1 -1
View File
@@ -1,7 +1,7 @@
#!/bin/bash
DEBIAN_FRONTEND=noninteractive sudo apt-get update && apt-get install wget -y
wget -O whoami.tar.gz "https://github.com/traefik/whoami/releases/download/v1.8.7/whoami_v1.8.7_linux_amd64.tar.gz"
wget -O whoami.tar.gz "https://github.com/traefik/whoami/releases/download/v1.9.0/whoami_v1.9.0_linux_amd64.tar.gz"
tar -zxvf whoami.tar.gz
# inspired from https://gist.github.com/ubergesundheit/7c9d875befc2d7bfd0bf43d8b3862d85
sudo mv ./whoami /usr/local/bin/
+1 -1
View File
@@ -1,5 +1,5 @@
image:
tag: v1.4.4-rc1
tag: v1.5.2
agent:
acquisition:
+2 -2
View File
@@ -1,5 +1,5 @@
image:
tag: v2.9.6
tag: v2.10.4
logs:
general:
@@ -16,4 +16,4 @@ experimental:
additionalArguments:
- "--experimental.plugins.bouncer.modulename=github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin"
- "--experimental.plugins.bouncer.version=v1.1.7-beta1"
- "--experimental.plugins.bouncer.version=v1.1.13"
+39 -41
View File
@@ -2,7 +2,7 @@ version: "3.8"
services:
traefik:
image: "traefik:v2.9.8"
image: "traefik:v2.10.4"
container_name: "traefik"
restart: unless-stopped
command:
@@ -15,7 +15,7 @@ services:
- "--entrypoints.web.address=:80"
- "--experimental.plugins.bouncer.modulename=github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin"
- "--experimental.plugins.bouncer.version=v1.1.11-beta2"
- "--experimental.plugins.bouncer.version=v1.1.13"
# - "--experimental.localplugins.bouncer.modulename=github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
@@ -29,26 +29,26 @@ services:
- redis-insecure
- redis-secure
whoami-redis-insecure:
image: traefik/whoami
container_name: "simple-service-foo"
restart: unless-stopped
labels:
- "traefik.enable=true"
# Definition of the router
- "traefik.http.routers.router-foo.rule=Path(`/redis-insecure`)"
- "traefik.http.routers.router-foo.entrypoints=web"
- "traefik.http.routers.router-foo.middlewares=crowdsec-foo@docker"
# Definition of the service
- "traefik.http.services.service-foo.loadbalancer.server.port=80"
# Definition of the middleware
- "traefik.http.middlewares.crowdsec-foo.plugin.bouncer.enabled=true"
# crowdseclapikey must be uniq to the middleware attached to the service
- "traefik.http.middlewares.crowdsec-foo.plugin.bouncer.crowdseclapikey=40796d93c2958f9e58345514e67740e5"
- "traefik.http.middlewares.crowdsec-foo.plugin.bouncer.rediscacheenabled=true"
# Contact redis-unsecure without a password
- "traefik.http.middlewares.crowdsec-foo.plugin.bouncer.redisCacheHost=redis-insecure:6379"
- "traefik.http.middlewares.crowdsec-foo.plugin.bouncer.loglevel=DEBUG"
# Either use secure, or insecure but do not mix both
# whoami-redis-insecure:
# image: traefik/whoami
# container_name: "simple-service-foo"
# restart: unless-stopped
# labels:
# - "traefik.enable=true"
# # Definition of the router
# - "traefik.http.routers.router-foo.rule=Path(`/redis-insecure`)"
# - "traefik.http.routers.router-foo.entrypoints=web"
# - "traefik.http.routers.router-foo.middlewares=crowdsec-foo@docker"
# # Definition of the service
# - "traefik.http.services.service-foo.loadbalancer.server.port=80"
# # Definition of the middleware
# - "traefik.http.middlewares.crowdsec.plugin.bouncer.enabled=true"
# - "traefik.http.middlewares.crowdsec.plugin.bouncer.crowdseclapikey=40796d93c2958f9e58345514e67740e5"
# - "traefik.http.middlewares.crowdsec.plugin.bouncer.rediscacheenabled=true"
# # Contact redis-unsecure without a password
# - "traefik.http.middlewares.crowdsec.plugin.bouncer.rediscachehost=redis-insecure:6379"
# - "traefik.http.middlewares.crowdsec.plugin.bouncer.loglevel=DEBUG"
whoami-redis-secure:
image: traefik/whoami
@@ -63,25 +63,23 @@ services:
# Definition of the service
- "traefik.http.services.service-bar.loadbalancer.server.port=80"
# Definition of the middleware
- "traefik.http.middlewares.crowdsec-bar.plugin.bouncer.enabled=true"
# crowdseclapikey must be uniq to the middleware attached to the service
- "traefik.http.middlewares.crowdsec-bar.plugin.bouncer.crowdseclapikey=44c36dac5c4140af9f06f397508e82c7"
- "traefik.http.middlewares.crowdsec-bar.plugin.bouncer.rediscacheenabled=true"
- "traefik.http.middlewares.crowdsec-bar.plugin.bouncer.redisCachePassword=FIXME"
- "traefik.http.middlewares.crowdsec.plugin.bouncer.enabled=true"
- "traefik.http.middlewares.crowdsec.plugin.bouncer.crowdseclapikey=40796d93c2958f9e58345514e67740e5"
- "traefik.http.middlewares.crowdsec.plugin.bouncer.rediscacheenabled=true"
- "traefik.http.middlewares.crowdsec.plugin.bouncer.rediscachepassword=FIXME"
# Contact redis-secure with password
- "traefik.http.middlewares.crowdsec-bar.plugin.bouncer.redisCacheHost=redis-secure:6379"
- "traefik.http.middlewares.crowdsec-bar.plugin.bouncer.loglevel=DEBUG"
- "traefik.http.middlewares.crowdsec.plugin.bouncer.rediscachehost=redis-secure:6379"
- "traefik.http.middlewares.crowdsec.plugin.bouncer.loglevel=DEBUG"
crowdsec:
image: crowdsecurity/crowdsec:v1.4.6
image: crowdsecurity/crowdsec:v1.5.2
container_name: "crowdsec"
restart: unless-stopped
environment:
COLLECTIONS: crowdsecurity/traefik
CUSTOM_HOSTNAME: crowdsec
BOUNCER_KEY_TRAEFIK_DEV_1: 40796d93c2958f9e58345514e67740e5
BOUNCER_KEY_TRAEFIK_DEV_2: 44c36dac5c4140af9f06f397508e82c7
BOUNCER_KEY_TRAEFIK_DEV: 40796d93c2958f9e58345514e67740e5
volumes:
- ./acquis.yaml:/etc/crowdsec/acquis.yaml:ro
- logs-redis:/var/log/traefik:ro
@@ -91,7 +89,7 @@ services:
- "traefik.enable=false"
redis-secure:
image: "redis:7.0.9-alpine"
image: "redis:7.0.12-alpine"
container_name: "redis-secure"
hostname: redis-secure
restart: unless-stopped
@@ -99,14 +97,14 @@ services:
volumes:
- redis-secure-data:/data
redis-insecure:
image: "redis:7.0.9-alpine"
container_name: "redis-insecure"
hostname: redis-unsecure
restart: unless-stopped
command: "redis-server --save 60 1 --loglevel debug"
volumes:
- redis-unsecure-data:/data
# redis-insecure:
# image: "redis:7.0.12-alpine"
# container_name: "redis-insecure"
# hostname: redis-unsecure
# restart: unless-stopped
# command: "redis-server --save 60 1 --loglevel debug"
# volumes:
# - redis-unsecure-data:/data
volumes:
logs-redis:
@@ -2,7 +2,7 @@ version: "3.8"
services:
traefik:
image: "traefik:v2.9.6"
image: "traefik:v2.10.4"
container_name: "traefik"
restart: unless-stopped
command:
@@ -15,7 +15,7 @@ services:
- "--entrypoints.web.address=:80"
- "--experimental.plugins.bouncer.modulename=github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin"
- "--experimental.plugins.bouncer.version=v1.1.7"
- "--experimental.plugins.bouncer.version=v1.1.13"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
ports:
+27 -25
View File
@@ -2,7 +2,7 @@ version: "3.8"
services:
traefik:
image: "traefik:v2.9.6"
image: "traefik:v2.10.4"
container_name: "traefik"
restart: unless-stopped
command:
@@ -15,14 +15,14 @@ services:
- "--entrypoints.web.address=:80"
- "--experimental.plugins.bouncer.modulename=github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin"
- "--experimental.plugins.bouncer.version=v1.1.7"
- "--experimental.plugins.bouncer.version=v1.1.13"
# - "--experimental.localplugins.bouncer.modulename=github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./LAPIKEY:/etc/traefik/LAPIKEY:ro
- logs-tls-auth:/var/log/traefik
- crowdsec-certs-tls-auth:/etc/traefik/crowdsec-certs
- ./../../:/plugins-local/src/github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin
# - ./../../:/plugins-local/src/github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin
ports:
- 80:80
@@ -30,22 +30,24 @@ services:
depends_on:
- crowdsec
whoami-foo:
image: traefik/whoami
container_name: "simple-service-foo"
restart: unless-stopped
labels:
- "traefik.enable=true"
- "traefik.http.routers.router-foo.rule=Path(`/foo`)"
- "traefik.http.routers.router-foo.entrypoints=web"
- "traefik.http.routers.router-foo.middlewares=crowdsec-foo@docker"
- "traefik.http.services.service-foo.loadbalancer.server.port=80"
- "traefik.http.middlewares.crowdsec-foo.plugin.bouncer.enabled=true"
- "traefik.http.middlewares.crowdsec-foo.plugin.bouncer.loglevel=DEBUG"
- "traefik.http.middlewares.crowdsec-foo.plugin.bouncer.crowdseclapikey=40796d93c2958f9e58345514e67740e5"
- "traefik.http.middlewares.crowdsec-foo.plugin.bouncer.crowdseclapischeme=https"
- "traefik.http.middlewares.crowdsec-foo.plugin.bouncer.crowdsecLapiTLSCertificateAuthorityFile=/etc/traefik/crowdsec-certs/inter.pem"
# Use HTTPS scheme but with lapikey authentication
# whoami-foo:
# image: traefik/whoami
# container_name: "simple-service-foo"
# restart: unless-stopped
# labels:
# - "traefik.enable=true"
# - "traefik.http.routers.router-foo.rule=Path(`/foo`)"
# - "traefik.http.routers.router-foo.entrypoints=web"
# - "traefik.http.routers.router-foo.middlewares=crowdsec-foo@docker"
# - "traefik.http.services.service-foo.loadbalancer.server.port=80"
# - "traefik.http.middlewares.crowdsec.plugin.bouncer.enabled=true"
# - "traefik.http.middlewares.crowdsec.plugin.bouncer.loglevel=DEBUG"
# - "traefik.http.middlewares.crowdsec.plugin.bouncer.crowdseclapikey=40796d93c2958f9e58345514e67740e5"
# - "traefik.http.middlewares.crowdsec.plugin.bouncer.crowdseclapischeme=https"
# - "traefik.http.middlewares.crowdsec.plugin.bouncer.crowdsecLapiTLSCertificateAuthorityFile=/etc/traefik/crowdsec-certs/inter.pem"
# Use HTTPS scheme with TLS cert authentication
whoami-bar:
image: traefik/whoami
container_name: "simple-service-bar"
@@ -56,15 +58,15 @@ services:
- "traefik.http.routers.router-bar.entrypoints=web"
- "traefik.http.routers.router-bar.middlewares=crowdsec-bar@docker"
- "traefik.http.services.service-bar.loadbalancer.server.port=80"
- "traefik.http.middlewares.crowdsec-bar.plugin.bouncer.enabled=true"
- "traefik.http.middlewares.crowdsec-bar.plugin.bouncer.loglevel=DEBUG"
- "traefik.http.middlewares.crowdsec-bar.plugin.bouncer.crowdseclapischeme=https"
- "traefik.http.middlewares.crowdsec-bar.plugin.bouncer.crowdsecLapiTLSCertificateAuthorityFile=/etc/traefik/crowdsec-certs/inter.pem"
- "traefik.http.middlewares.crowdsec-bar.plugin.bouncer.crowdsecLapiTLSCertificateBouncerFile=/etc/traefik/crowdsec-certs/bouncer.pem"
- "traefik.http.middlewares.crowdsec-bar.plugin.bouncer.crowdsecLapiTLSCertificateBouncerKeyFile=/etc/traefik/crowdsec-certs/bouncer-key.pem"
- "traefik.http.middlewares.crowdsec.plugin.bouncer.enabled=true"
- "traefik.http.middlewares.crowdsec.plugin.bouncer.loglevel=DEBUG"
- "traefik.http.middlewares.crowdsec.plugin.bouncer.crowdseclapischeme=https"
- "traefik.http.middlewares.crowdsec.plugin.bouncer.crowdsecLapiTLSCertificateAuthorityFile=/etc/traefik/crowdsec-certs/inter.pem"
- "traefik.http.middlewares.crowdsec.plugin.bouncer.crowdsecLapiTLSCertificateBouncerFile=/etc/traefik/crowdsec-certs/bouncer.pem"
- "traefik.http.middlewares.crowdsec.plugin.bouncer.crowdsecLapiTLSCertificateBouncerKeyFile=/etc/traefik/crowdsec-certs/bouncer-key.pem"
crowdsec:
image: crowdsecurity/crowdsec:v1.4.3
image: crowdsecurity/crowdsec:v1.5.2
container_name: "crowdsec"
restart: unless-stopped
environment:
+13 -16
View File
@@ -2,7 +2,7 @@ version: "3.8"
services:
traefik:
image: "traefik:v2.9.6"
image: "traefik:v2.10.4"
container_name: "traefik"
restart: unless-stopped
command:
@@ -15,12 +15,12 @@ services:
- "--entrypoints.web.address=:80"
- "--experimental.plugins.bouncer.modulename=github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin"
- "--experimental.plugins.bouncer.version=v1.1.7"
- "--experimental.plugins.bouncer.version=v1.1.13"
# - "--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
# - ./../../:/plugins-local/src/github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin
ports:
- 80:80
- 8080:8080
@@ -40,12 +40,11 @@ services:
# Definition of the service
- "traefik.http.services.service-foo.loadbalancer.server.port=80"
# Definition of the middleware
- "traefik.http.middlewares.crowdsec-foo.plugin.bouncer.enabled=true"
# crowdseclapikey must be uniq to the middleware attached to the service
- "traefik.http.middlewares.crowdsec-foo.plugin.bouncer.crowdseclapikey=40796d93c2958f9e58345514e67740e5"
- "traefik.http.middlewares.crowdsec.plugin.bouncer.enabled=true"
- "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-foo.plugin.bouncer.clienttrustedips=10.0.10.30/32"
- "traefik.http.middlewares.crowdsec-foo.plugin.bouncer.loglevel=DEBUG"
- "traefik.http.middlewares.crowdsec.plugin.bouncer.clienttrustedips=10.0.10.30/32"
- "traefik.http.middlewares.crowdsec.plugin.bouncer.loglevel=DEBUG"
whoami2:
image: traefik/whoami
@@ -60,23 +59,21 @@ services:
# Definition of the service
- "traefik.http.services.service-bar.loadbalancer.server.port=80"
# Definition of the middleware
- "traefik.http.middlewares.crowdsec-bar.plugin.bouncer.enabled=true"
# crowdseclapikey must be uniq to the middleware attached to the service
- "traefik.http.middlewares.crowdsec-bar.plugin.bouncer.crowdseclapikey=44c36dac5c4140af9f06f397508e82c7"
- "traefik.http.middlewares.crowdsec.plugin.bouncer.enabled=true"
- "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-bar.plugin.bouncer.clienttrustedips=10.0.10.30/32"
- "traefik.http.middlewares.crowdsec-bar.plugin.bouncer.loglevel=DEBUG"
- "traefik.http.middlewares.crowdsec.plugin.bouncer.clienttrustedips=10.0.10.30/32"
- "traefik.http.middlewares.crowdsec.plugin.bouncer.loglevel=DEBUG"
crowdsec:
image: crowdsecurity/crowdsec:v1.4.3
image: crowdsecurity/crowdsec:v1.5.2
container_name: "crowdsec"
restart: unless-stopped
environment:
COLLECTIONS: crowdsecurity/traefik
CUSTOM_HOSTNAME: crowdsec
BOUNCER_KEY_TRAEFIK_DEV_1: 40796d93c2958f9e58345514e67740e5
BOUNCER_KEY_TRAEFIK_DEV_2: 44c36dac5c4140af9f06f397508e82c7
BOUNCER_KEY_TRAEFIK_DEV: 40796d93c2958f9e58345514e67740e5
volumes:
- ./acquis.yaml:/etc/crowdsec/acquis.yaml:ro
- logs-trustedips:/var/log/traefik:ro
+1 -1
View File
@@ -4,5 +4,5 @@ go 1.19
require (
github.com/leprosus/golang-ttl-map v1.1.7
github.com/maxlerebourg/simpleredis v1.0.6
github.com/maxlerebourg/simpleredis v1.0.9
)
+2 -2
View File
@@ -1,4 +1,4 @@
github.com/leprosus/golang-ttl-map v1.1.7 h1:cF4AAFDDnJTFSV+/42sKLhmMluvLdRlCGS2UaifH6UM=
github.com/leprosus/golang-ttl-map v1.1.7/go.mod h1:4QWHJPeVBbrkhOhXdhCv9IEiyj/YzkO04/iexy4vSe0=
github.com/maxlerebourg/simpleredis v1.0.6 h1:dKd0hgKk7uGKjujWUMuPTVOAONYdlCys5Iqh6w3dOU4=
github.com/maxlerebourg/simpleredis v1.0.6/go.mod h1:/DH8zOK6kDskSqoX/m5CJJdNGfkIQZd/ERBJgytDDSk=
github.com/maxlerebourg/simpleredis v1.0.9 h1:aj1hKaYPeOVE4Ksu3TV/zsreUDDWOpKXBAvoFysiqII=
github.com/maxlerebourg/simpleredis v1.0.9/go.mod h1:/DH8zOK6kDskSqoX/m5CJJdNGfkIQZd/ERBJgytDDSk=
+2 -2
View File
@@ -82,9 +82,9 @@ type Client struct {
}
// New Initialize cache client.
func (client *Client) New(isRedis bool, host string, pass string) {
func (client *Client) New(isRedis bool, host, pass, database string) {
if isRedis {
redis.Init(host, pass)
redis.Init(host, pass, database)
client.cache = &redisCache{}
} else {
client.cache = &localCache{}
+5
View File
@@ -50,6 +50,7 @@ type Config struct {
CrowdsecCapiScenarios []string `json:"crowdsecCapiScenarios,omitempty"`
UpdateIntervalSeconds int64 `json:"updateIntervalSeconds,omitempty"`
DefaultDecisionSeconds int64 `json:"defaultDecisionSeconds,omitempty"`
HTTPTimeoutSeconds int64 `json:"httpTimeoutSeconds,omitempty"`
ForwardedHeadersCustomName string `json:"forwardedheaderscustomheader,omitempty"`
ForwardedHeadersTrustedIPs []string `json:"forwardedHeadersTrustedIps,omitempty"`
ClientTrustedIPs []string `json:"clientTrustedIps,omitempty"`
@@ -57,6 +58,7 @@ type Config struct {
RedisCacheHost string `json:"redisCacheHost,omitempty"`
RedisCachePassword string `json:"redisCachePassword,omitempty"`
RedisCachePasswordFile string `json:"redisCachePasswordFile,omitempty"`
RedisCacheDatabase string `json:"redisCacheDatabase,omitempty"`
}
func contains(source []string, target string) bool {
@@ -80,12 +82,14 @@ func New() *Config {
CrowdsecLapiTLSInsecureVerify: false,
UpdateIntervalSeconds: 60,
DefaultDecisionSeconds: 60,
HTTPTimeoutSeconds: 10,
ForwardedHeadersCustomName: "X-Forwarded-For",
ForwardedHeadersTrustedIPs: []string{},
ClientTrustedIPs: []string{},
RedisCacheEnabled: false,
RedisCacheHost: "redis:6379",
RedisCachePassword: "",
RedisCacheDatabase: "",
}
}
@@ -239,6 +243,7 @@ func validateParamsRequired(config *Config) error {
requiredInt := map[string]int64{
"UpdateIntervalSeconds": config.UpdateIntervalSeconds,
"DefaultDecisionSeconds": config.DefaultDecisionSeconds,
"HTTPTimeoutSeconds": config.HTTPTimeoutSeconds,
}
for key, val := range requiredInt {
if val < 1 {
+1 -1
View File
@@ -9,7 +9,7 @@ import simpleredis "github.com/maxlerebourg/simpleredis"
var redis simpleredis.SimpleRedis
redis.Init("redis:6379", "") // redisHost, redisPass
redis.Init("redis:6379", "", "") // redisHost, redisPass, redisDatabase
err := redis.Set("test", []bytes("whatever"), 60), // Set key "test" with "whatever" for 60 seconds
if err != nil {
+41 -32
View File
@@ -18,6 +18,7 @@ const (
RedisMiss = "redis:miss"
RedisTimeout = "redis:timeout"
RedisNoAuth = "redis:noauth"
RedisIssue = "redis:issue?"
)
// A redisCmd is used to communicate with redis at low level using commands.
@@ -33,6 +34,7 @@ type redisCmd struct {
type SimpleRedis struct {
host string
pass string
database string
}
func genRedisArray(params ...[]byte) []byte {
@@ -51,25 +53,7 @@ func send(wr *textproto.Writer, method string, data []byte) {
}
}
func askRedis(sr *SimpleRedis, cmd redisCmd, channel chan redisCmd) {
dialer := net.Dialer{Timeout: 2 * time.Second}
conn, err := dialer.Dial("tcp", sr.host)
if err != nil {
channel <- redisCmd{Error: fmt.Errorf(RedisUnreachable)}
return
}
defer func() {
if err := conn.Close(); err != nil {
fmt.Printf("redis:connClose %s", err.Error())
}
}()
writer := textproto.NewWriter(bufio.NewWriter(conn))
reader := textproto.NewReader(bufio.NewReader(conn))
if sr.pass != "" {
data := genRedisArray([]byte("AUTH"), []byte(sr.pass))
send(writer, "auth", data)
func (sr *SimpleRedis) waitRedis(reader *textproto.Reader, channel chan redisCmd) {
for {
select {
case <-time.After(time.Second * 1):
@@ -85,6 +69,33 @@ func askRedis(sr *SimpleRedis, cmd redisCmd, channel chan redisCmd) {
// breaks out of for
break
}
}
func (sr *SimpleRedis) askRedis(cmd redisCmd, channel chan redisCmd) redisCmd {
dialer := net.Dialer{Timeout: 2 * time.Second}
conn, err := dialer.Dial("tcp", sr.host)
if err != nil {
return redisCmd{Error: fmt.Errorf(RedisUnreachable)}
}
defer func() {
if err := conn.Close(); err != nil {
fmt.Printf("redis:connClose %s", err.Error())
}
}()
writer := textproto.NewWriter(bufio.NewWriter(conn))
reader := textproto.NewReader(bufio.NewReader(conn))
if sr.pass != "" {
data := genRedisArray([]byte("AUTH"), []byte(sr.pass))
send(writer, "auth", data)
sr.waitRedis(reader, channel)
}
if sr.database != "" {
data := genRedisArray([]byte("SELECT"), []byte(sr.database))
send(writer, "select", data)
sr.waitRedis(reader, channel)
}
switch cmd.Command {
@@ -100,30 +111,29 @@ func askRedis(sr *SimpleRedis, cmd redisCmd, channel chan redisCmd) {
for {
select {
case <-time.After(time.Second * 1):
channel <- redisCmd{Error: fmt.Errorf(RedisTimeout)}
return
return redisCmd{Error: fmt.Errorf(RedisTimeout)}
default:
read, _ := reader.ReadLineBytes()
str := string(read)
if strings.Contains(str, "-NOAUTH") {
channel <- redisCmd{Error: fmt.Errorf(RedisNoAuth)}
return
return redisCmd{Error: fmt.Errorf(RedisNoAuth)}
} else if str != "$1" {
channel <- redisCmd{Error: fmt.Errorf(RedisMiss)}
return
return redisCmd{Error: fmt.Errorf(RedisMiss)}
}
read, _ = reader.ReadLineBytes()
channel <- redisCmd{Data: read}
return
return redisCmd{Data: read}
}
}
}
return redisCmd{Error: fmt.Errorf(RedisIssue)}
}
// Init sets the redisHost used to connect to redis.
func (sr *SimpleRedis) Init(host string, pass string) {
func (sr *SimpleRedis) Init(host, pass, database string) {
sr.host = host
sr.pass = pass
sr.database = database
}
// Get fetches the value for key name in redis.
@@ -133,8 +143,7 @@ func (sr *SimpleRedis) Get(name string) ([]byte, error) {
Name: name,
}
channel := make(chan redisCmd)
go askRedis(sr, cmd, channel)
resp := <-channel
resp := sr.askRedis(cmd, channel)
if resp.Error != nil {
return nil, resp.Error
}
@@ -149,7 +158,7 @@ func (sr *SimpleRedis) Set(name string, data []byte, duration int64) error {
Data: data,
Duration: duration,
}
go askRedis(sr, cmd, nil)
sr.askRedis(cmd, nil)
return nil
}
@@ -159,6 +168,6 @@ func (sr *SimpleRedis) Del(name string) error {
Command: "DEL",
Name: name,
}
go askRedis(sr, cmd, nil)
sr.askRedis(cmd, nil)
return nil
}
+1 -1
View File
@@ -1,6 +1,6 @@
# github.com/leprosus/golang-ttl-map v1.1.7
## explicit; go 1.15
github.com/leprosus/golang-ttl-map
# github.com/maxlerebourg/simpleredis v1.0.6
# github.com/maxlerebourg/simpleredis v1.0.9
## explicit; go 1.19
github.com/maxlerebourg/simpleredis