mirror of
https://github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin.git
synced 2026-07-21 19:48:59 +02:00
✨ add redis ttl
This commit is contained in:
@@ -59,7 +59,7 @@ services:
|
|||||||
- "traefik.http.middlewares.crowdsec2.plugin.bouncer.enabled=true"
|
- "traefik.http.middlewares.crowdsec2.plugin.bouncer.enabled=true"
|
||||||
# crowdseclapikey must be uniq to the middleware attached to the service
|
# crowdseclapikey must be uniq to the middleware attached to the service
|
||||||
- "traefik.http.middlewares.crowdsec2.plugin.bouncer.crowdseclapikey=44c36dac5c4140af9f06f397508e82c7"
|
- "traefik.http.middlewares.crowdsec2.plugin.bouncer.crowdseclapikey=44c36dac5c4140af9f06f397508e82c7"
|
||||||
- "traefik.http.middlewares.crowdsec2.plugin.bouncer.rediscacheenabled=false"
|
- "traefik.http.middlewares.crowdsec2.plugin.bouncer.rediscacheenabled=true"
|
||||||
|
|
||||||
|
|
||||||
crowdsec:
|
crowdsec:
|
||||||
|
|||||||
Vendored
+12
-15
@@ -20,7 +20,6 @@ var redis simpleredis.SimpleRedis
|
|||||||
|
|
||||||
var redisEnabled = false
|
var redisEnabled = false
|
||||||
|
|
||||||
|
|
||||||
func getDecisionLocalCache(clientIP string) (bool, error) {
|
func getDecisionLocalCache(clientIP string) (bool, error) {
|
||||||
banned, isCached := cache.Get(clientIP)
|
banned, isCached := cache.Get(clientIP)
|
||||||
bannedString, isValid := banned.(string)
|
bannedString, isValid := banned.(string)
|
||||||
@@ -30,29 +29,28 @@ func getDecisionLocalCache(clientIP string) (bool, error) {
|
|||||||
return false, fmt.Errorf("no cache data")
|
return false, fmt.Errorf("no cache data")
|
||||||
}
|
}
|
||||||
|
|
||||||
func SetDecisionLocalCache(clientIP string, value string, duration int64) {
|
func setDecisionLocalCache(clientIP string, value string, duration int64) {
|
||||||
cache.Set(clientIP, value, duration)
|
cache.Set(clientIP, value, duration)
|
||||||
}
|
}
|
||||||
|
|
||||||
func DeleteDecisionLocalCache(clientIP string) {
|
func deleteDecisionLocalCache(clientIP string) {
|
||||||
cache.Del(clientIP)
|
cache.Del(clientIP)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getDecisionRedisCache(clientIP string) (bool, error) {
|
func getDecisionRedisCache(clientIP string) (bool, error) {
|
||||||
banned, err := redis.Do("GET", clientIP, nil)
|
banned, err := redis.Get(clientIP)
|
||||||
bannedString := string(banned)
|
bannedString := string(banned)
|
||||||
logger.Info(fmt.Sprintf("%v banned", bannedString))
|
|
||||||
if err == nil && len(bannedString) > 0 {
|
if err == nil && len(bannedString) > 0 {
|
||||||
return bannedString == cacheBannedValue, nil
|
return bannedString == cacheBannedValue, nil
|
||||||
}
|
}
|
||||||
return false, fmt.Errorf("no cache data")
|
return false, fmt.Errorf("no cache data")
|
||||||
}
|
}
|
||||||
|
|
||||||
func SetDecisionRedisCache(clientIP string, value string, duration int64) {
|
func setDecisionRedisCache(clientIP string, value string, duration int64) {
|
||||||
redis.Do("SET", clientIP, []byte(value))
|
redis.Set(clientIP, []byte(value), duration)
|
||||||
}
|
}
|
||||||
|
|
||||||
func DeleteDecisionRedisCache(clientIP string) {
|
func deleteDecisionRedisCache(clientIP string) {
|
||||||
// err := rdb.Del(ctx, clientIP).Err()
|
// err := rdb.Del(ctx, clientIP).Err()
|
||||||
// if err != nil {
|
// if err != nil {
|
||||||
// logger.Info("Error, could not delete in redis cache IP")
|
// logger.Info("Error, could not delete in redis cache IP")
|
||||||
@@ -60,15 +58,14 @@ func DeleteDecisionRedisCache(clientIP string) {
|
|||||||
// errors are not handled
|
// errors are not handled
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
func DeleteDecision(clientIP string) {
|
func DeleteDecision(clientIP string) {
|
||||||
if redisEnabled {
|
if redisEnabled {
|
||||||
DeleteDecisionRedisCache(clientIP)
|
deleteDecisionRedisCache(clientIP)
|
||||||
} else {
|
} else {
|
||||||
DeleteDecisionLocalCache(clientIP)
|
deleteDecisionLocalCache(clientIP)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetDecision check in the cache if the IP has the banned / not banned value.
|
// GetDecision check in the cache if the IP has the banned / not banned value.
|
||||||
// Otherwise return with an error to add the IP in cache if we are on.
|
// Otherwise return with an error to add the IP in cache if we are on.
|
||||||
func GetDecision(clientIP string) (bool, error) {
|
func GetDecision(clientIP string) (bool, error) {
|
||||||
@@ -88,14 +85,14 @@ func SetDecision(clientIP string, isBanned bool, duration int64) {
|
|||||||
value = cacheNoBannedValue
|
value = cacheNoBannedValue
|
||||||
}
|
}
|
||||||
if redisEnabled {
|
if redisEnabled {
|
||||||
SetDecisionRedisCache(clientIP, value, duration)
|
setDecisionRedisCache(clientIP, value, duration)
|
||||||
} else {
|
} else {
|
||||||
SetDecisionLocalCache(clientIP, value, duration)
|
setDecisionLocalCache(clientIP, value, duration)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func InitRedisClient(host string, password string) {
|
func InitRedisClient(host string, password string) {
|
||||||
logger.Debug("connect to redis")
|
|
||||||
redisEnabled = true
|
redisEnabled = true
|
||||||
redis.Init(host)
|
redis.Init(host)
|
||||||
|
logger.Debug("connect to redis")
|
||||||
}
|
}
|
||||||
|
|||||||
+27
-25
@@ -2,21 +2,19 @@ package simpleredis
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
"net"
|
"net"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/tehnerd/goUtils/netutils"
|
"github.com/tehnerd/goUtils/netutils"
|
||||||
|
|
||||||
logger "github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin/pkg/logger"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type RedisCmd struct {
|
type RedisCmd struct {
|
||||||
Command string
|
Command string
|
||||||
Name string
|
Name string
|
||||||
Data []byte
|
Data []byte
|
||||||
|
Duration int64
|
||||||
Error error
|
Error error
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -27,26 +25,17 @@ type SimpleRedis struct {
|
|||||||
redisCmd RedisCmd
|
redisCmd RedisCmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func GenRedisArray(params ...[]byte) []byte {
|
func genRedisArray(params ...[]byte) []byte {
|
||||||
CRLF := "\r\n"
|
|
||||||
MSG := ""
|
MSG := ""
|
||||||
for cntr := 0; cntr < len(params); cntr++ {
|
for cntr := 0; cntr < len(params); cntr++ {
|
||||||
MSG = strings.Join([]string{MSG, string(params[cntr])}, " ")
|
MSG = strings.Join([]string{MSG, string(params[cntr])}, " ")
|
||||||
}
|
}
|
||||||
MSG = strings.Trim(MSG, " ")
|
MSG = strings.Trim(MSG, " ")
|
||||||
MSG = strings.Join([]string{MSG, CRLF}, "")
|
MSG = strings.Join([]string{MSG, "\r\n"}, "")
|
||||||
return []byte(MSG)
|
return []byte(MSG)
|
||||||
}
|
}
|
||||||
|
|
||||||
func RedisSet(name string, data []byte) []byte {
|
func parseResponse(response []byte, dataBuf []byte, Len *int) ([]byte, []byte, error) {
|
||||||
return GenRedisArray([]byte("SET"), []byte(name), data)
|
|
||||||
}
|
|
||||||
|
|
||||||
func RedisGet(name string) []byte {
|
|
||||||
return GenRedisArray([]byte("GET"), []byte(name))
|
|
||||||
}
|
|
||||||
|
|
||||||
func ParseRedisResponse(response []byte, dataBuf []byte, Len *int) ([]byte, []byte, error) {
|
|
||||||
dataBuf = append(dataBuf, response...)
|
dataBuf = append(dataBuf, response...)
|
||||||
lenCRLF := 2
|
lenCRLF := 2
|
||||||
if *Len != 0 {
|
if *Len != 0 {
|
||||||
@@ -116,7 +105,7 @@ func ParseRedisResponse(response []byte, dataBuf []byte, Len *int) ([]byte, []by
|
|||||||
return nil, dataBuf, nil
|
return nil, dataBuf, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func RedisContext(hostnamePort string, redisCmdWrite, redisCmdRead chan RedisCmd) {
|
func initContext(hostnamePort string, redisCmdWrite, redisCmdRead chan RedisCmd) {
|
||||||
tcpRemoteAddress, err := net.ResolveTCPAddr("tcp", hostnamePort)
|
tcpRemoteAddress, err := net.ResolveTCPAddr("tcp", hostnamePort)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic("cant resolve remote redis address")
|
panic("cant resolve remote redis address")
|
||||||
@@ -131,23 +120,23 @@ func RedisContext(hostnamePort string, redisCmdWrite, redisCmdRead chan RedisCmd
|
|||||||
<-readChan
|
<-readChan
|
||||||
dataBuf := make([]byte, 0)
|
dataBuf := make([]byte, 0)
|
||||||
dataLen := 0
|
dataLen := 0
|
||||||
for true {
|
for {
|
||||||
select {
|
select {
|
||||||
case cmd := <-redisCmdWrite:
|
case cmd := <-redisCmdWrite:
|
||||||
switch cmd.Command {
|
switch cmd.Command {
|
||||||
case "SET":
|
case "SET":
|
||||||
data := RedisSet(cmd.Name, cmd.Data)
|
data := genRedisArray([]byte("SET"), []byte(cmd.Name), cmd.Data, []byte("EX"), []byte(fmt.Sprintf("%v", cmd.Duration)))
|
||||||
writeChan <- data
|
writeChan <- data
|
||||||
case "GET":
|
case "GET":
|
||||||
data := RedisGet(cmd.Name)
|
data := genRedisArray([]byte("GET"), []byte(cmd.Name))
|
||||||
writeChan <- data
|
writeChan <- data
|
||||||
}
|
}
|
||||||
case response := <-readChan:
|
case response := <-readChan:
|
||||||
data, dataBuf, err := ParseRedisResponse(response, dataBuf, &dataLen)
|
data, dataBuf, err := parseResponse(response, dataBuf, &dataLen)
|
||||||
if dataLen != 0 {
|
if dataLen != 0 {
|
||||||
for data == nil {
|
for data == nil {
|
||||||
response = <-readChan
|
response = <-readChan
|
||||||
data, dataBuf, err = ParseRedisResponse(response, dataBuf, &dataLen)
|
data, dataBuf, err = parseResponse(response, dataBuf, &dataLen)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -182,13 +171,13 @@ func (sr *SimpleRedis) Init(redisHost string) {
|
|||||||
sr.redisHost = redisHost
|
sr.redisHost = redisHost
|
||||||
sr.redisChanWrite = make(chan RedisCmd)
|
sr.redisChanWrite = make(chan RedisCmd)
|
||||||
sr.redisChanRead = make(chan RedisCmd)
|
sr.redisChanRead = make(chan RedisCmd)
|
||||||
go RedisContext(sr.redisHost, sr.redisChanWrite, sr.redisChanRead)
|
go initContext(sr.redisHost, sr.redisChanWrite, sr.redisChanRead)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sr *SimpleRedis) Do(cmd, name string, data []byte) ([]byte, error) {
|
func (sr *SimpleRedis) Get(name string) ([]byte, error) {
|
||||||
sr.redisCmd.Command = cmd
|
sr.redisCmd.Command = "GET"
|
||||||
sr.redisCmd.Name = name
|
sr.redisCmd.Name = name
|
||||||
sr.redisCmd.Data = data
|
sr.redisCmd.Data = nil
|
||||||
sr.redisChanWrite <- sr.redisCmd
|
sr.redisChanWrite <- sr.redisCmd
|
||||||
resp := <-sr.redisChanRead
|
resp := <-sr.redisChanRead
|
||||||
if resp.Error != nil {
|
if resp.Error != nil {
|
||||||
@@ -196,3 +185,16 @@ func (sr *SimpleRedis) Do(cmd, name string, data []byte) ([]byte, error) {
|
|||||||
}
|
}
|
||||||
return resp.Data, nil
|
return resp.Data, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (sr *SimpleRedis) Set(name string, data []byte, duration int64) error {
|
||||||
|
sr.redisCmd.Command = "SET"
|
||||||
|
sr.redisCmd.Name = name
|
||||||
|
sr.redisCmd.Data = data
|
||||||
|
sr.redisCmd.Duration = duration
|
||||||
|
sr.redisChanWrite <- sr.redisCmd
|
||||||
|
resp := <-sr.redisChanRead
|
||||||
|
if resp.Error != nil {
|
||||||
|
return resp.Error
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user