Code Monkey home page Code Monkey logo

caddy-crowdsec-bouncer's Introduction

CrowdSec Bouncer for Caddy

A Caddy module that blocks malicious traffic based on decisions made by CrowdSec.

Description

This repository is currently a WIP. Things may change a bit.

CrowdSec is a free and open source security automation tool that uses local logs and a set of scenarios to infer malicious intent. In addition to operating locally, an optional community integration is also available, through which crowd-sourced IP reputation lists are distributed.

The architecture of CrowdSec is very modular. At its core is the CrowdSec Agent, which keeps track of all data and related systems. Bouncers are pieces of software that perform specific actions based on the decisions of the Agent.

This repository contains a custom CrowdSec Bouncer that can be embedded as a Caddy module. It consists of the follwing three main pieces:

  • A Caddy App
  • A Caddy HTTP Handler
  • A Caddy Layer 4 Connection Matcher

The App is responsible for communicating with a CrowdSec Agent via the CrowdSec Local API and keeping track of the decisions of the Agent. The HTTP Handler checks client IPs of incoming requests against the decisions stored by the App. This way, multiple independent HTTP Handlers or Connection Matchers can use the storage exposed by the App. The App can be configured to use either the StreamBouncer, which gets decisions via a HTTP polling mechanism, or the LiveBouncer, which sends a request on every incoming HTTP request or Layer 4 connection setup.

Usage

Get the module

# get the http handler
go get github.com/hslatman/caddy-crowdsec-bouncer/http

# get the layer4 connection matcher (only required if you need support for TCP/UDP level blocking)
go get github.com/hslatman/caddy-crowdsec-bouncer/layer4

Create a (custom) Caddy server (or use xcaddy)

package main

import (
  cmd "github.com/caddyserver/caddy/v2/cmd"
  _ "github.com/caddyserver/caddy/v2/modules/standard"
  // import the http handler
  _ "github.com/hslatman/caddy-crowdsec-bouncer/http"
  // import the layer4 matcher (in case you want to block connections to layer4 servers using CrowdSec)
  _ "github.com/hslatman/caddy-crowdsec-bouncer/layer4"
)

func main() {
  cmd.Main()
}

Example Caddyfile:

{
    debug
    crowdsec {
        api_url http://localhost:8080
        api_key <api_key>
        ticker_interval 15s
        #disable_streaming
        #enable_hard_fails
    }
}

localhost {
    route {
        crowdsec
        respond "Allowed by CrowdSec!"
    }
}

Configuration using a Caddyfile is only supported for HTTP handlers. You'll also need to use a recent version of Caddy (i.e. 2.7.3 and newer) and Go 1.20 (or newer). In case you want to use the CrowdSec bouncer on TCP or UDP level, you'll need to configure Caddy using the native JSON format. An example configuration is shown below:

{   
    "apps": {
      "crowdsec": {
        "api_key": "<insert_crowdsec_local_api_key_here>",
        "api_url": "http://127.0.0.1:8080/",
        "ticker_interval": "10s",
        "enable_streaming": true,
        "enable_hard_fails": false,
      },
      "http": {
        "http_port": 9080,
        "https_port": 9443,
        "servers": {
          "example": {
            "listen": [
              "127.0.0.1:9443"
            ],
            "routes": [
              {
                "group": "example-group",
                "match": [
                  {
                    "path": [
                      "/*"
                    ]
                  }
                ],
                "handle": [
                  {
                    "handler": "crowdsec"
                  },
                  {
                    "handler": "static_response",
                    "status_code": "200",
                    "body": "Hello World!"
                  },
                  {
                    "handler": "headers",
                    "response": {
                      "set": {
                        "Server": ["caddy-cs-bouncer-example-server"]
                      }
                    }
                  }
                ]
              }
            ],
            "logs": {}
          }
        }
      },
      "layer4": {
        "servers": {
          "https_proxy": {
            "listen": ["localhost:8443"],
            "routes": [
              {
                "match": [
                  {
                    "crowdsec": {},
                    "tls": {}
                  }
                ],
                "handle": [
                  {
                    "handler": "proxy",
                    "upstreams": [
                      {
                        "dial": ["localhost:9443"]
                      }
                    ]
                  }
                ]
              }
            ]
          }
        }
      },
    }
  }

Run the Caddy server

# with a Caddyfile
go run main.go run -config Caddyfile 

# with JSON configuration
go run main.go run -config config.json

Demo

This repository also contains an example using Docker. Steps to run this demo are as follows:

# run CrowdSec container
$ docker compose up -d crowdsec

# add the Caddy bouncer, generating an API key
$ docker compose exec crowdsec cscli bouncers add caddy-bouncer

# copy and paste the API key in the ./docker/config.json file
# below is the git diff after changing the appropriate line:
$ git diff

- "api_key": "<api_key>",
+ "api_key": "9e4ac94cf9aebaa3625a1d51951230a9",

# run Caddy; at first run a custom build will be created using xcaddy
$ docker compose up -d caddy

# tail the logs
$ docker compose logs -tf

You can then access https://localhost:9443 and https://localhost:8443. The latter is an example of using the Layer 4 App and will simply proxy to port 9443 in this case.

Client IP

If your Caddy server with this bouncer is deployed behind a proxy, a CDN or another system fronting the web server, the IP of the client requesting a resource is masked by the system that sits between the client and your server. Starting with v0.3.1, the HTTP handler relies on Caddy to determine the actual client IP of the system performing the HTTP request. The new logic was implemented as part of caddy#5104, and released with Caddy v2.7.0. The IP that Caddy determines is used to check against the CrowdSec decisions to see if it's allowed in or not.

Caddy determines the actual client IP from the X-Forwarded-For header by default, but it is possible to change this using the client_ip_headers directive in the global settings. The setting depends on the trusted_proxies directive to be set, so that the IP reported in the X-Forwarded-For (or one of the headers you configure as override) can be trusted.

For older versions of this Caddy module, and for older versions of Caddy (up to v2.4.6), the realip module can be used instead.

Things That Can Be Done

  • Add integration tests for the HTTP and L4 handlers
  • Tests with IPv6
  • Test with project conncept (Caddy layer 4 app; TCP seems to work; UDP to be tested)
  • Add captcha action (currently works the same as a ban)?
  • Add support for custom actions (defaults to blocking access now)?
  • Add Caddy metrics integration?
  • Add Caddy profiling integration?
  • Caching the LiveBouncer (for the duration of the decision)?
  • ...

caddy-crowdsec-bouncer's People

Contributors

hslatman avatar ignaigna avatar laurencejjones avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

caddy-crowdsec-bouncer's Issues

How can I tell if it's working?

I tried running cscli decisions add --ip <MY_PUBLIC_IP> to test, and I can still access all of my sites, so I'm assuming it's not working.

Here's my Caddyfile:

(crowdsec) {
    crowdsec
    log
}

(auth) {
    forward_auth authelia-pod:9091 {
        uri /api/verify?rd=https://auth.haddock.cc
        copy_headers Remote-User Remote-Groups Remote-Name Remote-Email
    }
}

# Global configuration
{
    # Cloudflare
    acme_dns cloudflare {env.CLOUDFLARE_API_TOKEN}
    email {env.PERSONAL_EMAIL}

    # Directive ordering
    # order webdav before file_server
    order crowdsec before forward_auth
    order crowdsec before reverse_proxy

    # Logging
    log stdout_logger {
        output stdout
        format console
        exclude http.log.access
    }
    log file_logger {
        output file /var/log/caddy/access.log
        include http.log.access
    }

    # CrowdSec bouncer
    crowdsec {
        api_url http://crowdsec:8080
        api_key {env.CROWDSEC_BOUNCER_API_KEY}
        ticker_interval 15s
    }
}

haddock.cc {
    import crowdsec
    respond "Hello, world!"
}

# Authelia
auth.haddock.cc {
    import crowdsec
    reverse_proxy authelia-pod:9091
}

# Jellyfin
media.haddock.cc {
    import crowdsec
    import auth
    reverse_proxy jellyfin-pod:8096
}

# Mealie
food.haddock.cc {
    import crowdsec
    import auth
    reverse_proxy mealie-pod:9000
}

# qBittorrent
torrent.haddock.cc {
    import crowdsec
    import auth
    reverse_proxy qbittorrent-pod:8080
}

# Prowlarr
prowl.haddock.cc {
    import crowdsec
    import auth
    reverse_proxy arr-pod:9696
}

# Sonarr
tv.haddock.cc {
    import crowdsec
    import auth
    reverse_proxy arr-pod:8989
}

# Radarr
movies.haddock.cc {
    import crowdsec
    import auth
    reverse_proxy arr-pod:7878
}

# Nextcloud
cloud.haddock.cc {
    import crowdsec
    reverse_proxy nextcloud-pod:80 {
        header_down Strict-Transport-Security "max-age=15552000; includeSubDomains"
    }
    rewrite /.well-known/carddav /remote.php/dav
    rewrite /.well-known/caldav /remote.php/dav
}

# FreshRSS
news.haddock.cc {
    import crowdsec
    import auth
    reverse_proxy freshrss-pod:80
}

# File Browser
drive.haddock.cc {
    import crowdsec
    import auth
    reverse_proxy filebrowser-pod:80
   # webdav /dav/* {
   #     root /srv/files
   #     prefix /dav
   # }
}

I know my access.log is being parsed correctly because of the output of cscli metrics, and the bouncer is listed in cscli bouncers list.

Request: add support for {env.*} placeholder

Hi, when using Caddyfile, it seems like the crowdsec module configuration does not support {env.*} placeholder.
Considering there is a .env file containing CROWDSEC_BOUNCER_KEY variable:

  crowdsec {
    api_url http://host.docker.internal:8060
    api_key {env.CROWDSEC_BOUNCER_KEY}
    ticker_interval 15s
    # disable_streaming
    # enable_hard_fails
  }

Will result with a 403 - API error: access forbidden because crowdsec module is not providing the api_key from env variable as expected.

{"level":"error","ts":1699643960.8473945,"logger":"crowdsec","msg":"API error: access forbidden","address":"http://host.docker.internal:8060/","error":"API error: access forbidden"}

It could be tricky for the user to understand what's going on. The current solution is to hard-code de key in the Caddyfile which is not great for security reason.

Cant get it to run

trying to get this to work but i keep getting this error when i add order crowdsec first

Error during parsing: crowdsec is not a registered directive

if i comment it out then i get the error

Error: adapting config using caddyfile: /etc/caddy/Caddyfile:47: unrecognized directive: crowdsec

My DockerFile:

ARG VERSION=2

FROM caddy:${VERSION}-builder AS builder

RUN xcaddy build \
    --with github.com/caddy-dns/cloudflare \
    --with github.com/hslatman/caddy-crowdsec-bouncer/crowdsec \
    --with github.com/RussellLuo/caddy-ext/layer4 \
    --with github.com/mholt/caddy-l4

FROM caddy:${VERSION}

COPY --from=builder /usr/bin/caddy /usr/bin/caddy

My Caddyfile:
https://pastebin.com/vQ1y2VFz

Is there a way to see if the plugin was installed? Also Caddy is running as Docker

I cant make it work

Hi.
Im trying to use this bouncer.
I install it, also crowdsec, enroll the server, etc.
I see this in crowdsec:
image

So, it seems crowdsec is fine.
I compile with xcaddy and also seems working:
caddy list-modules result:

  Standard modules: 106

crowdsec

  Non-standard modules: 1

I put this in my Caddyfile:

{
    crowdsec {
        api_url http://localhost:8080
        api_key 3xxx6xxxxxxxxxxxxxxxxx3fd
        ticker_interval 15s
        #disable_streaming
        #enable_hard_fails
    }

}

trilium.xxxxxxxxx.xyz {
        reverse_proxy crowdsec 192.168.0.10:8080

        log {
        output file /var/log/caddy/trilium-access.log {
        roll_size 10mb
        roll_keep 20
        roll_keep_for 720h
  }
}
}

But... when try to access i get an error:
{"level":"error","ts":1716596310.84049,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"185.23.45.80","remote_port":"53294","client_ip":"185.23.45.80","proto":"HTTP/2.0","method":"GET","host":"trilium.xxxxxx.xyz","uri":"/","headers":{"Sec-Fetch-Mode":["navigate"],"Sec-Fetch-User":["?1"],"Sec-Fetch-Dest":["document"],"Sec-Ch-Ua-Mobile":["?0"],"Upgrade-Insecure-Requests":["1"],"User-Agent":["Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36"],"Accept":["text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7"],"Sec-Fetch-Site":["none"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua":["\"Not-A.Brand\";v=\"99\", \"Chromium\";v=\"124\""],"Sec-Ch-Ua-Platform":["\"Linux\""],"Accept-Language":["en-US,en;q=0.9"],"Priority":["u=0, i"]},"tls":{"resumed":false,"version":772,"cipher_suite":4867,"proto":"h2","server_name":"trilium.xxxxxxxx.xyz"}},"bytes_read":0,"user_id":"","duration":0.004853857,"size":0,"status":502,"resp_headers":{"Server":["Caddy"],"Alt-Svc":["h3=\":443\"; ma=2592000"]}}

Hope you can help me.
Thanks!

Is using `route` required?

I was wondering, is it required to use this to have the CrowdSec bouncer actually work?

localhost {
    route {
        crowdsec
        respond "Allowed by CrowdSec!"
    }
}
```

[go-cs-bouncer] breaking change ahead

Hello,

A significant change was made in go-cs-bouncer (commit : crowdsecurity/go-cs-bouncer@5aef3b3)

the .Run method of go-cs-bouncer doesn't Fatal upon initialization failure (this failure would namely happen if the LAPI cannot be reached or cannot authenticate to LAPI).

The reason for this change is to allow bouncers/IPS to take advantage of defer statements for cleanup.

You can see reflected change in firewall-bouncer that uses this new version :

Configuration sample improvements

Hi,

Thks for this amazing works...
My firsts tests were successful.

I now wanna go further in my configuration and i think a few more explanations may be needed.

Default configuration is working, as bouncer out of box... but i now wanna add some nice 403 bouncing error pages... and the route http handler required to add the crowdsec call is disabling my default error pges handlers...

If you find some spare time, it'll be nice if tou could provide examples...

I also try to captcha instead of ban ... but doesn't see any difference. Any idea?

Caddy Restarting: invalid memory address or nil pointer dereference

Hi, over the last few weeks I've noticed short interruptions in connectivity when using application running on a Caddy server. After digging into the logs to figure out the issue I've come across the following. This appears to be causing Caddy to restart.

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x19b1923]

goroutine 2211 [running]:
github.com/hslatman/caddy-crowdsec-bouncer/internal/bouncer.(*crowdSecStore).delete(0x0, 0xc002a8dfa0?)
  github.com/hslatman/[email protected]/internal/bouncer/store.go:77 +0xa3
github.com/hslatman/caddy-crowdsec-bouncer/internal/bouncer.(*Bouncer).delete(...)
  github.com/hslatman/[email protected]/internal/bouncer/bouncer.go:152
github.com/hslatman/caddy-crowdsec-bouncer/internal/bouncer.(*Bouncer).Run.func1()
  github.com/hslatman/[email protected]/internal/bouncer/bouncer.go:95 +0x228
created by github.com/hslatman/caddy-crowdsec-bouncer/internal/bouncer.(*Bouncer).Run
  github.com/hslatman/[email protected]/internal/bouncer/bouncer.go:86 +0x6a

I'm running Caddy 2.5.2 in Docker with the following plugins enabled:

Any assistance would be appreciated.

Thanks

Error: loading initial config: loading new config: loading http app module: provision http: server server1: setting up route handlers: route 0: loading handler modules: position 0: loading module 'crowdsec': unknown module: http.handlers.crowdsec

When trying the demo, i get this below error on current verzion of go and caddy. not sure what happening

Error: loading initial config: loading new config: loading http app module: provision http: server server1: setting up route handlers: route 0: loading handler modules: position 0: loading module 'crowdsec': unknown module: http.handlers.crowdsec

Issue while adding Go module

Hi,
I can't add the go package/module on my Linux server (debian 10)
Go version : go1.11.6 linux/amd64

root@Caddy:~# go get github.com/hslatman/caddy-crowdsec-bouncer/http
package crypto/ed25519: unrecognized import path "crypto/ed25519" (import path does not begin with hostname)

Thanks :)

no API calls to pull decisions list after startup

Hi, I just spotted that caddy bouncer only makes one API call to pull decisions list (GET /v1/decisions/stream?startup=true), during startup sequence and that's it. After that initial call, there is no other calls made to the API. I'm wondering if this is the intended behavior?
In comparison, cs-firewall-bouncer is calling to /v1/decisions/stream at the regular interval set in its config.

It's like ticker_interval value is not used at all.

image

This is the crowdsec block I use in Caddyfile

  crowdsec {
    api_url http://host.docker.internal:8080
    api_key xxx
    ticker_interval 15s
    # disable_streaming
    # enable_hard_fails
  }
  order crowdsec first

Note: If I run in no-streaming mode (enabling disable_streaming) caddy calls the API as expected for each received request.

[Question] What should the API URL be?

I'm running both Caddy and CrowdSec in a Docker Compose project, so I'm not really sure what the api_url should be set to. Should it just be the hostname of the Caddy container, along with the HTTP port (i.e. caddy:80).

error: URL does not have a scheme

Hi, I'm currently trying to setup Caddy and CrowdSec (also fairly new to Caddy and CrowdSec) in Docker but stumble upon error message when applying crowdsec directive in Caddyfile.

Error: sending configuration to instance: caddy responded with error: HTTP 400: {"error":"loading config: loading new config: loading http app module: provision http: server srv0: setting up route handlers: route 1: loading handler modules: position 0: loading module 'subroute': provision http.handlers.subroute: setting up subroutes: route 0: loading handler modules: position 0: loading module 'subroute': provision http.handlers.subroute: setting up subroutes: route 0: loading handler modules: position 0: loading module 'crowdsec': provision http.handlers.crowdsec: getting crowdsec app: loading crowdsec app module: provision crowdsec: URL does not have a scheme (i.e https)"}

Any idea what went wrong?
If I remove the crowdsec directive, Caddy will reload with no error.

Caddyfile:

{
	acme_ca https://acme.zerossl.com/v2/DV90
	email [email protected]
	crowdsec {
		api_url http://crowdsec:8080
		api_key APIKEY
	}
}

https://www.example.com {
	route {
		crowdsec
		encode gzip
		root * /data/static-web
		file_server
	}
}

Working on Oracle arm?

Hi,
I using your docker (crowdsec + caddy) on oracle arm (ubuntu jammy) with docker (25.0) with your docker-comppose.yml (version 3.6):

  crowdsec:
    image: crowdsecurity/crowdsec
    ports:
      - "8080:8080"
    volumes:
      - logs:/var/log/nginx/

  caddy:
    build:
      context: ./docker
      target: caddy
    ports:
      - "9443:9443"
      - "8443:8443"
    volumes:
      - caddy-data:/data
      - caddy-config:/config
      - logs:/var/log/caddy
      - ./docker/config.json:/etc/caddy/config.json

And using your steps:

  • docker-compose up -d crowdsec
  • docker-compose exec crowdsec cscli bouncers add caddy-bouncer
    • And copy the api in /docker/config.json "api_key"
  • docker-compose up -d caddy

But with the las order have this error:

7.505 go: upgraded golang.org/x/tools v0.10.0 => v0.14.0
7.509 2024/02/07 21:22:05 [INFO] exec (timeout=0s): /usr/local/go/bin/go get -d -v github.com/caddyserver/format-encoder github.com/caddyserver/caddy/[email protected] 
7.715 go: downloading github.com/caddyserver/format-encoder v0.0.0-20231219065943-58ebafa572d5
7.730 go: github.com/caddyserver/[email protected] found: parsing go.mod:
7.730 	module declares its path as: github.com/caddyserver/transform-encoder
7.730 	       but was required as: github.com/caddyserver/format-encoder
7.730 go: github.com/caddyserver/format-encoder@upgrade (v0.0.0-20231219065943-58ebafa572d5) requires github.com/caddyserver/[email protected]: parsing go.mod:
7.730 	module declares its path as: github.com/caddyserver/transform-encoder
7.730 	       but was required as: github.com/caddyserver/format-encoder
7.731 2024/02/07 21:22:05 [FATAL] exit status 1
------
Dockerfile:11
--------------------
  10 |     
  11 | >>> RUN xcaddy build \
  12 | >>>     --with github.com/mholt/caddy-l4 \
  13 | >>>     --with github.com/caddyserver/format-encoder \
  14 | >>>     --with github.com/hslatman/caddy-crowdsec-bouncer/http@main \
  15 | >>>     --with github.com/hslatman/caddy-crowdsec-bouncer/layer4@main
  16 |     
--------------------
ERROR: failed to solve: process "/bin/sh -c xcaddy build     
--with github.com/mholt/caddy-l4    
--with github.com/caddyserver/format-encoder     
--with github.com/hslatman/caddy-crowdsec-bouncer/http@main     
--with github.com/hslatman/caddy-crowdsec-bouncer/layer4@main" did not complete successfully: exit code: 1
ERROR: Service 'caddy' failed to build : Build failed

This docker have a problem with arm? or where is the problem?

And if is possible to work, how next put a url (https://my.web.duckdns.org) go the correct docker, because on normal Caddyfile put this:

my.web.duckdns.org {
        header X-Robots-Tag "noindex, nofollow"
        reverse_proxy http://10.0.0.209:4000
}

Thanks a lot

[Feature] AppSec Integration

Hey @hslatman ๐Ÿ‘‹๐Ÿป We at CrowdSec have been working on a WAF component called AppSec, and whilst the component is within our preview stage, we would like to reach out to other web server bouncers to ask about a potential integration. (We would be willing to do the pull requests itself)

The first thing is to ask would you be interested in having this within this bouncer? or would you like this bouncer to solely handle just the IP checks?

Thank you for supporting our community with your bouncer!

Error: directive 'crowdsec' is not an ordered HTTP handler

Hi, I'm trying to use this module. But I got an error when I try to use the crowdsec directive:

Error: adapting config using caddyfile: directive 'crowdsec' is not an ordered HTTP handler, so it cannot be used here - try placing within a route block or using the order global option

This is how I build my custom caddy image:

FROM caddy:builder-alpine AS builder

RUN xcaddy build\
      --with github.com/caddy-dns/cloudflare\
      --with github.com/mholt/caddy-dynamicdns\
      --with github.com/hslatman/caddy-crowdsec-bouncer/http

FROM caddy:alpine

COPY --from=builder /usr/bin/caddy /usr/bin/caddy

This is my compose file (shortened)

{
  email [email protected]

  dynamic_dns {
    provider cloudflare {env.CLOUDFLARE_API_TOKEN}
    domains {
      mydomain.com
    }
    check_interval 10m
    versions ipv4
    dynamic_domains
  }

  crowdsec {
    api_url host.docker.internal:8080
    api_key xxx
    ticker_interval 15s
    # disable_streaming
    # enable_hard_fails
  }
}

# I have a wildcard domain setup
*.mydomain.com, mydomain.com {
  tls {
    dns cloudflare {env.CLOUDFLARE_API_TOKEN}
  }

  encode gzip
  crowdsec

  # MicroBin
  @microbin host bin.mydomain.com
  handle @microbin {
    reverse_proxy microbin:12345
  }

  // [...] other services handlers
}

Any idea about the issue?

cannot get bouncer to enforce bans

hi there and thank you for the great work with this!

I am running crowdsec and caddy via docker, and a series of locally-hosted domains reached both locally (/etc/hosts) and via a cloudflared tunnel. All latest versions.

I can access my containers fine on both LAN and externally, and if I enable and inspect Caddy's access logs I can see the correct X-Forwarded-For address in both cases. However, if I try and run docker exec crowdsec cscli decisions add --ip on that ip (and also /24 ranges) I can still access all domains fine.

I am guessing it has to do with the bouncer? Any idea what it could be?

As for my config, here's what have:

docker-compose:

  caddy:
    container_name: caddy
    image: caddy:latest
    build:
      context: ./caddy
      dockerfile: Dockerfile
    volumes:
      - ./caddy:/data
      - ./caddy/Caddyfile:/etc/caddy/Caddyfile:ro
    environment:
      - CADDY_INGRESS_NETWORKS=caddy
      - CLOUDFLARE_API_TOKEN=${CLOUDFLARE_API_TOKEN}
      - CROWDSEC_LOCAL_API_KEY=${CROWDSEC_LOCAL_API_KEY}
    ports:
      - 80:80
      - 443:443

  cloudflared:
    container_name: cloudflared
    image: cloudflare/cloudflared:latest
    command: tunnel --no-autoupdate run
    volumes:
      - ./cloudflared:/home/nonroot/.cloudflared:ro

  crowdsec:
    container_name: crowdsec
    image: crowdsecurity/crowdsec
    volumes:
      - ${DOCKER_CONFIG_DIR}/crowdsec/data:/var/lib/crowdsec/data
      - ${DOCKER_CONFIG_DIR}/crowdsec/config:/etc/crowdsec
    environment:
      - COLLECTIONS=crowdsecurity/caddy

  my-container:
    container_name: my-container
    image: some/image
    ports:
      - 1234:1234

Caddyfile:

{
	crowdsec {
		api_url http://crowdsec:8080
		api_key {$CROWDSEC_LOCAL_API_KEY}
	}
	email [email protected]
        acme_dns cloudflare {$CLOUDFLARE_API_TOKEN}
}

my.domain.com {
	route {
		crowdsec
		reverse_proxy my-container:1234
	}
}

Caddy Dockerfile:

FROM caddy:builder AS builder

RUN xcaddy build \
	# Use Cloudflare for ACME DNS challenge
	--with github.com/caddy-dns/cloudflare \
	# for crowdsec bouncer
    --with github.com/hslatman/caddy-crowdsec-bouncer/http

FROM caddy:latest

COPY --from=builder /usr/bin/caddy /usr/bin/caddy

Cloudflared config.yml:

tunnel: my-tunnel-id
credentials-file: /home/nonroot/.cloudflared/my-tunnel-id.json

ingress:
  - hostname: my.domain.com
    service: https://caddy:443
    originRequest:
      originServerName: "my.domain.com"
  - service: http_status:404

thanks!

caddy-logs parser not working, but apache2-logs parser works

Hello,

Environment:

crowdsec v1.2.1 (docker)
caddy v2.4.6 (docker xcaddy build includes:  caddy-l4 , format-encoder , realip , caddy2-proxyprotocol , caddy-crowdsec-bouncer/http@main , caddy-crowdsec-bouncer/layer4@main)

I'm having trouble getting this to parse my caddy access.log. I am using the suggested config from the example, but crowdsec is unable to parse the file. I apologize in advance for being a github/devops newbie -- if there is something I missed or can provide more insight into, please let me know!

Caddy - config.json:

"logging": {
        "logs": {
            "default": {
                "level": "DEBUG",
                "writer": {
                  "output": "stderr"
                }
            },
            "access": {
              "level": "DEBUG",
              "writer": {
                "output": "file",
                "filename": "/var/log/caddy/access.log"
              },
              "encoder": {
                "format": "formatted",
                "template": "{common_log} \"{request>headers>Referer>[0]}\" \"{request>headers>User-Agent>[0]}\""
              },
              "include": [
                "http.log.access.access"
              ]
          }
        }
    },

Failed grok parse via caddy-logs:

# crowdsec -dsn file:///var/log/caddy/access.log -type caddy -no-api -trace
---snip---
TRAC[15-12-2021 11:58:22] INPUT '176.53.221.38 - - [15/Dec/2021:17:39:52 +0000] "GET / HTTP/1.1" 308 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.61 Safari/537.36"'
TRAC[15-12-2021 11:58:22] node stage : s00-raw, current stage : s00-raw
TRAC[15-12-2021 11:58:22] Processing node 0/12 -> sparkling-waterfall   node-name=sparkling-waterfall stage=s00-raw
TRAC[15-12-2021 11:58:22] Event entering node                           id=sparkling-waterfall name=crowdsecurity/docker-logs stage=s00-raw
DEBU[15-12-2021 11:58:22] Event leaving node : ko (failed filter)       id=sparkling-waterfall name=crowdsecurity/docker-logs stage=s00-raw
TRAC[15-12-2021 11:58:22] node (sparkling-waterfall) ret : false        node-name=sparkling-waterfall stage=s00-raw
TRAC[15-12-2021 11:58:22] Processing node 1/12 -> dawn-feather          node-name=dawn-feather stage=s00-raw
TRAC[15-12-2021 11:58:22] Event entering node                           id=dawn-feather name=crowdsecurity/syslog-logs stage=s00-raw
DEBU[15-12-2021 11:58:22] Event leaving node : ko (failed filter)       id=dawn-feather name=crowdsecurity/syslog-logs stage=s00-raw
TRAC[15-12-2021 11:58:22] node (dawn-feather) ret : false               node-name=dawn-feather stage=s00-raw
TRAC[15-12-2021 11:58:22] Processing node 2/12 -> little-hill           node-name=little-hill stage=s00-raw
TRAC[15-12-2021 11:58:22] Event entering node                           id=little-hill name=crowdsecurity/non-syslog stage=s00-raw
TRAC[15-12-2021 11:58:22] ! No grok pattern : 0x0                       id=little-hill name=crowdsecurity/non-syslog stage=s00-raw
TRAC[15-12-2021 11:58:22] State after nodes : true                      id=little-hill name=crowdsecurity/non-syslog stage=s00-raw
DEBU[15-12-2021 11:58:22] + Processing 4 statics                        id=little-hill name=crowdsecurity/non-syslog stage=s00-raw
DEBU[15-12-2021 11:58:22] .Parsed[message] = '176.53.221.38 - - [15/Dec/2021:17:39:52 +0000] "GET / HTTP/1.1" 308 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.61 Safari/537.36"'  id=little-hill name=crowdsecurity/non-syslog stage=s00-raw
DEBU[15-12-2021 11:58:22] .Parsed[program] = 'caddy'                    id=little-hill name=crowdsecurity/non-syslog stage=s00-raw
DEBU[15-12-2021 11:58:22] .Meta[datasource_path] = '/var/log/caddy/test.log'  id=little-hill name=crowdsecurity/non-syslog stage=s00-raw
DEBU[15-12-2021 11:58:22] .Meta[datasource_type] = 'file'               id=little-hill name=crowdsecurity/non-syslog stage=s00-raw
DEBU[15-12-2021 11:58:22] Event leaving node : ok                       id=little-hill name=crowdsecurity/non-syslog stage=s00-raw
TRAC[15-12-2021 11:58:22] node is successful, check strategy
DEBU[15-12-2021 11:58:22] move Event from stage s00-raw to s01-parse    id=little-hill name=crowdsecurity/non-syslog stage=s00-raw
TRAC[15-12-2021 11:58:22] Node successful, continue                     id=little-hill name=crowdsecurity/non-syslog stage=s00-raw
TRAC[15-12-2021 11:58:22] node (little-hill) ret : true                 node-name=little-hill stage=s00-raw
DEBU[15-12-2021 11:58:22] node successful, stop end stage s00-raw       node-name=little-hill stage=s00-raw
TRAC[15-12-2021 11:58:22] node stage : s01-parse, current stage : s01-parse
TRAC[15-12-2021 11:58:22] Processing node 3/12 -> spring-water          node-name=spring-water stage=s01-parse
TRAC[15-12-2021 11:58:22] Event entering node                           id=spring-water name=crowdsecurity/apache2-logs stage=s01-parse
DEBU[15-12-2021 11:58:22] Event leaving node : ko (failed filter)       id=spring-water name=crowdsecurity/apache2-logs stage=s01-parse
TRAC[15-12-2021 11:58:22] node (spring-water) ret : false               node-name=spring-water stage=s01-parse
TRAC[15-12-2021 11:58:22] Processing node 4/12 -> patient-pond          node-name=patient-pond stage=s01-parse
TRAC[15-12-2021 11:58:22] Event entering node                           id=patient-pond name=crowdsecurity/caddy-logs stage=s01-parse
TRAC[15-12-2021 11:58:22] ! No grok pattern : 0x0                       id=patient-pond name=crowdsecurity/caddy-logs stage=s01-parse
TRAC[15-12-2021 11:58:22] Event entering node                           id=solitary-snow name=child-crowdsecurity/caddy-logs stage=s01-parse
TRAC[15-12-2021 11:58:22] Node has not filter, enter                    id=solitary-snow name=child-crowdsecurity/caddy-logs stage=s01-parse
TRAC[15-12-2021 11:58:22] ! No grok pattern : 0x0                       id=solitary-snow name=child-crowdsecurity/caddy-logs stage=s01-parse
TRAC[15-12-2021 11:58:22] Event entering node                           id=ancient-shape name=child-child-crowdsecurity/caddy-logs stage=s01-parse
TRAC[15-12-2021 11:58:22] Node has not filter, enter                    id=ancient-shape name=child-child-crowdsecurity/caddy-logs stage=s01-parse
TRAC[15-12-2021 11:58:22] Processing grok pattern :  : 0xc0006a8f70     id=ancient-shape name=child-child-crowdsecurity/caddy-logs stage=s01-parse
TRAC[15-12-2021 11:58:22] extract path [common_log]
DEBU[15-12-2021 11:58:22] [common_log] doesn't exist
DEBU[15-12-2021 11:58:22] + Grok '%{NOT...' didn't return data on ''    id=ancient-shape name=child-child-crowdsecurity/caddy-logs stage=s01-parse
TRAC[15-12-2021 11:58:22] State after nodes : false                     id=ancient-shape name=child-child-crowdsecurity/caddy-logs stage=s01-parse
DEBU[15-12-2021 11:58:22] Event leaving node : ko                       id=ancient-shape name=child-child-crowdsecurity/caddy-logs stage=s01-parse
TRAC[15-12-2021 11:58:22]       sub-node (ancient-shape) ret : false (strategy:)  id=solitary-snow name=child-crowdsecurity/caddy-logs stage=s01-parse
TRAC[15-12-2021 11:58:22] Event entering node                           id=black-dream name=child-child-crowdsecurity/caddy-logs stage=s01-parse
TRAC[15-12-2021 11:58:22] Node has not filter, enter                    id=black-dream name=child-child-crowdsecurity/caddy-logs stage=s01-parse
TRAC[15-12-2021 11:58:22] Processing grok pattern :  : 0xc0004251f0     id=black-dream name=child-child-crowdsecurity/caddy-logs stage=s01-parse
TRAC[15-12-2021 11:58:22] extract path [request remote_addr]
DEBU[15-12-2021 11:58:22] [request remote_addr] doesn't exist
DEBU[15-12-2021 11:58:22] + Grok '%{IPO...' didn't return data on ''    id=black-dream name=child-child-crowdsecurity/caddy-logs stage=s01-parse
TRAC[15-12-2021 11:58:22] State after nodes : false                     id=black-dream name=child-child-crowdsecurity/caddy-logs stage=s01-parse
DEBU[15-12-2021 11:58:22] Event leaving node : ko                       id=black-dream name=child-child-crowdsecurity/caddy-logs stage=s01-parse
TRAC[15-12-2021 11:58:22]       sub-node (black-dream) ret : false (strategy:)  id=solitary-snow name=child-crowdsecurity/caddy-logs stage=s01-parse
TRAC[15-12-2021 11:58:22] Event entering node                           id=wispy-dew name=child-child-crowdsecurity/caddy-logs stage=s01-parse
TRAC[15-12-2021 11:58:22] Node has not filter, enter                    id=wispy-dew name=child-child-crowdsecurity/caddy-logs stage=s01-parse
TRAC[15-12-2021 11:58:22] Processing grok pattern :  : 0xc000425840     id=wispy-dew name=child-child-crowdsecurity/caddy-logs stage=s01-parse
TRAC[15-12-2021 11:58:22] extract path [request headers User-Agent]
DEBU[15-12-2021 11:58:22] [request headers User-Agent] doesn't exist
DEBU[15-12-2021 11:58:22] + Grok '\["%{...' didn't return data on ''    id=wispy-dew name=child-child-crowdsecurity/caddy-logs stage=s01-parse
TRAC[15-12-2021 11:58:22] State after nodes : false                     id=wispy-dew name=child-child-crowdsecurity/caddy-logs stage=s01-parse
DEBU[15-12-2021 11:58:22] Event leaving node : ko                       id=wispy-dew name=child-child-crowdsecurity/caddy-logs stage=s01-parse
TRAC[15-12-2021 11:58:22]       sub-node (wispy-dew) ret : false (strategy:)  id=solitary-snow name=child-crowdsecurity/caddy-logs stage=s01-parse
TRAC[15-12-2021 11:58:22] State after nodes : false                     id=solitary-snow name=child-crowdsecurity/caddy-logs stage=s01-parse
DEBU[15-12-2021 11:58:22] Event leaving node : ko                       id=solitary-snow name=child-crowdsecurity/caddy-logs stage=s01-parse
TRAC[15-12-2021 11:58:22]       sub-node (solitary-snow) ret : false (strategy:next_stage)  id=patient-pond name=crowdsecurity/caddy-logs stage=s01-parse
TRAC[15-12-2021 11:58:22] State after nodes : false                     id=patient-pond name=crowdsecurity/caddy-logs stage=s01-parse
DEBU[15-12-2021 11:58:22] Event leaving node : ko                       id=patient-pond name=crowdsecurity/caddy-logs stage=s01-parse
TRAC[15-12-2021 11:58:22] node (patient-pond) ret : false               node-name=patient-pond stage=s01-parse
TRAC[15-12-2021 11:58:22] Processing node 5/12 -> cold-cherry           node-name=cold-cherry stage=s01-parse
TRAC[15-12-2021 11:58:22] Event entering node                           id=cold-cherry name=crowdsecurity/modsecurity stage=s01-parse
DEBU[15-12-2021 11:58:22] Event leaving node : ko (failed filter)       id=cold-cherry name=crowdsecurity/modsecurity stage=s01-parse
TRAC[15-12-2021 11:58:22] node (cold-cherry) ret : false                node-name=cold-cherry stage=s01-parse
TRAC[15-12-2021 11:58:22] Processing node 6/12 -> hidden-snowflake      node-name=hidden-snowflake stage=s01-parse
TRAC[15-12-2021 11:58:22] Event entering node                           id=hidden-snowflake name=crowdsecurity/nginx-logs stage=s01-parse
DEBU[15-12-2021 11:58:22] Event leaving node : ko (failed filter)       id=hidden-snowflake name=crowdsecurity/nginx-logs stage=s01-parse
TRAC[15-12-2021 11:58:22] node (hidden-snowflake) ret : false           node-name=hidden-snowflake stage=s01-parse
TRAC[15-12-2021 11:58:22] Processing node 7/12 -> young-waterfall       node-name=young-waterfall stage=s01-parse
TRAC[15-12-2021 11:58:22] Event entering node                           id=young-waterfall name=crowdsecurity/sshd-logs stage=s01-parse
DEBU[15-12-2021 11:58:22] Event leaving node : ko (failed filter)       id=young-waterfall name=crowdsecurity/sshd-logs stage=s01-parse
TRAC[15-12-2021 11:58:22] node (young-waterfall) ret : false            node-name=young-waterfall stage=s01-parse
DEBU[15-12-2021 11:58:22] Log didn't finish stage s01-parse
DEBU[15-12-2021 11:58:22] Discarding line {Type:0 ExpectMode:1 Whitelisted:false WhitelistReason: Stage:s01-parse Line:{Raw:176.53.221.38 - - [15/Dec/2021:17:39:52 +0000] "GET / HTTP/1.1" 308 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.61 Safari/537.36" Src:/var/log/caddy/test.log Time:2021-12-15 11:58:22.200949223 -0700 MST m=+4.603803966 Labels:map[type:caddy] Process:true Module:file} Parsed:map[message:176.53.221.38 - - [15/Dec/2021:17:39:52 +0000] "GET / HTTP/1.1" 308 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.61 Safari/537.36" program:caddy] Enriched:map[] Overflow:{Mapkey: BucketId: Whitelisted:false Reprocess:false Sources:map[] Alert:<nil> APIAlerts:[]} Time:2021-12-15 11:58:22.209799114 -0700 MST m=+4.612653893 StrTime: MarshaledTime: Process:false Meta:map[datasource_path:/var/log/caddy/test.log datasource_type:file]}
---snip---

I found that I can force crowdsec to use the apache2-logs parser by modifying /etc/crowdsec/parsers/s01-parse/apache2-logs.yaml to:

filter: "evt.Parsed.program startsWith 'caddy'"

...which then gets me this...

Successful grok parse via apache2-logs:

# crowdsec -dsn file:///var/log/caddy/access.log -type caddy -no-api -trace
---snip---
TRAC[15-12-2021 11:49:28] INPUT '176.53.221.38 - - [15/Dec/2021:17:39:52 +0000] "GET / HTTP/1.1" 308 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.61 Safari/537.36"'
TRAC[15-12-2021 11:49:28] node stage : s00-raw, current stage : s00-raw
TRAC[15-12-2021 11:49:28] Processing node 0/11 -> lingering-dew         node-name=lingering-dew stage=s00-raw
TRAC[15-12-2021 11:49:28] Event entering node                           id=lingering-dew name=crowdsecurity/docker-logs stage=s00-raw
DEBU[15-12-2021 11:49:28] Event leaving node : ko (failed filter)       id=lingering-dew name=crowdsecurity/docker-logs stage=s00-raw
TRAC[15-12-2021 11:49:28] node (lingering-dew) ret : false              node-name=lingering-dew stage=s00-raw
TRAC[15-12-2021 11:49:28] Processing node 1/11 -> silent-sea            node-name=silent-sea stage=s00-raw
TRAC[15-12-2021 11:49:28] Event entering node                           id=silent-sea name=crowdsecurity/syslog-logs stage=s00-raw
DEBU[15-12-2021 11:49:28] Event leaving node : ko (failed filter)       id=silent-sea name=crowdsecurity/syslog-logs stage=s00-raw
TRAC[15-12-2021 11:49:28] node (silent-sea) ret : false                 node-name=silent-sea stage=s00-raw
TRAC[15-12-2021 11:49:28] Processing node 2/11 -> polished-wood         node-name=polished-wood stage=s00-raw
TRAC[15-12-2021 11:49:28] Event entering node                           id=polished-wood name=crowdsecurity/non-syslog stage=s00-raw
TRAC[15-12-2021 11:49:28] ! No grok pattern : 0x0                       id=polished-wood name=crowdsecurity/non-syslog stage=s00-raw
TRAC[15-12-2021 11:49:28] State after nodes : true                      id=polished-wood name=crowdsecurity/non-syslog stage=s00-raw
DEBU[15-12-2021 11:49:28] + Processing 4 statics                        id=polished-wood name=crowdsecurity/non-syslog stage=s00-raw
DEBU[15-12-2021 11:49:28] .Parsed[message] = '176.53.221.38 - - [15/Dec/2021:17:39:52 +0000] "GET / HTTP/1.1" 308 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.61 Safari/537.36"'  id=polished-wood name=crowdsecurity/non-syslog stage=s00-raw
DEBU[15-12-2021 11:49:28] .Parsed[program] = 'caddy'                    id=polished-wood name=crowdsecurity/non-syslog stage=s00-raw
DEBU[15-12-2021 11:49:28] .Meta[datasource_path] = '/var/log/caddy/test.log'  id=polished-wood name=crowdsecurity/non-syslog stage=s00-raw
DEBU[15-12-2021 11:49:28] .Meta[datasource_type] = 'file'               id=polished-wood name=crowdsecurity/non-syslog stage=s00-raw
DEBU[15-12-2021 11:49:28] Event leaving node : ok                       id=polished-wood name=crowdsecurity/non-syslog stage=s00-raw
TRAC[15-12-2021 11:49:28] node is successful, check strategy
DEBU[15-12-2021 11:49:28] move Event from stage s00-raw to s01-parse    id=polished-wood name=crowdsecurity/non-syslog stage=s00-raw
TRAC[15-12-2021 11:49:28] Node successful, continue                     id=polished-wood name=crowdsecurity/non-syslog stage=s00-raw
TRAC[15-12-2021 11:49:28] node (polished-wood) ret : true               node-name=polished-wood stage=s00-raw
DEBU[15-12-2021 11:49:28] node successful, stop end stage s00-raw       node-name=polished-wood stage=s00-raw
TRAC[15-12-2021 11:49:28] node stage : s01-parse, current stage : s01-parse
TRAC[15-12-2021 11:49:28] Processing node 3/11 -> throbbing-field       node-name=throbbing-field stage=s01-parse
TRAC[15-12-2021 11:49:28] Event entering node                           id=throbbing-field name=crowdsecurity/apache2-logs stage=s01-parse
TRAC[15-12-2021 11:49:28] ! No grok pattern : 0x0                       id=throbbing-field name=crowdsecurity/apache2-logs stage=s01-parse
TRAC[15-12-2021 11:49:28] Event entering node                           id=weathered-fire name=child-crowdsecurity/apache2-logs stage=s01-parse
TRAC[15-12-2021 11:49:28] Node has not filter, enter                    id=weathered-fire name=child-crowdsecurity/apache2-logs stage=s01-parse
TRAC[15-12-2021 11:49:28] Processing grok pattern :  : 0xc000678000     id=weathered-fire name=child-crowdsecurity/apache2-logs stage=s01-parse
DEBU[15-12-2021 11:49:28] line 45.90.62.143 - - [15/Dec/2021:17:39:54 +0000] "GET / HTTP/1.1" 308 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.61 Safari/537.36"  oneshot=/var/log/caddy/test.log type="file:///var/log/caddy/test.log"
DEBU[15-12-2021 11:49:28] + Grok '(%{IP...' returned 13 entries to merge in Parsed  id=weathered-fire name=child-crowdsecurity/apache2-logs stage=s01-parse
DEBU[15-12-2021 11:49:28]       .Parsed['response'] = '308'                  id=weathered-fire name=child-crowdsecurity/apache2-logs stage=s01-parse
DEBU[15-12-2021 11:49:28]       .Parsed['bytes'] = '0'                       id=weathered-fire name=child-crowdsecurity/apache2-logs stage=s01-parse
DEBU[15-12-2021 11:49:28]       .Parsed['verb'] = 'GET'                      id=weathered-fire name=child-crowdsecurity/apache2-logs stage=s01-parse
DEBU[15-12-2021 11:49:28]       .Parsed['timestamp'] = '15/Dec/2021:17:39:52 +0000'  id=weathered-fire name=child-crowdsecurity/apache2-logs stage=s01-parse
DEBU[15-12-2021 11:49:28]       .Parsed['http_user_agent'] = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.61 Safari/537.36'  id=weathered-fire name=child-crowdsecurity/apache2-logs stage=s01-parse
DEBU[15-12-2021 11:49:29]       .Parsed['target_fqdn'] = ''                  id=weathered-fire name=child-crowdsecurity/apache2-logs stage=s01-parse
DEBU[15-12-2021 11:49:29]       .Parsed['request'] = '/'                     id=weathered-fire name=child-crowdsecurity/apache2-logs stage=s01-parse
DEBU[15-12-2021 11:49:29]       .Parsed['auth'] = '-'                        id=weathered-fire name=child-crowdsecurity/apache2-logs stage=s01-parse
DEBU[15-12-2021 11:49:29]       .Parsed['httpversion'] = '1.1'               id=weathered-fire name=child-crowdsecurity/apache2-logs stage=s01-parse
DEBU[15-12-2021 11:49:29]       .Parsed['referrer'] = '-'                    id=weathered-fire name=child-crowdsecurity/apache2-logs stage=s01-parse
DEBU[15-12-2021 11:49:29]       .Parsed['clientip'] = '176.53.221.38'        id=weathered-fire name=child-crowdsecurity/apache2-logs stage=s01-parse
DEBU[15-12-2021 11:49:29]       .Parsed['ident'] = '-'                       id=weathered-fire name=child-crowdsecurity/apache2-logs stage=s01-parse
DEBU[15-12-2021 11:49:29]       .Parsed['rawrequest'] = ''                   id=weathered-fire name=child-crowdsecurity/apache2-logs stage=s01-parse
TRAC[15-12-2021 11:49:29] event against holder 0/28                     cfg=red-butterfly file=/etc/crowdsec/scenarios/f5-big-ip-cve-2020-5902.yaml name=crowdsecurity/f5-big-ip-cve-2020-5902
DEBU[15-12-2021 11:49:29] Event leaving node : ko (filter mismatch)     cfg=red-butterfly file=/etc/crowdsec/scenarios/f5-big-ip-cve-2020-5902.yaml name=crowdsecurity/f5-big-ip-cve-2020-5902
TRAC[15-12-2021 11:49:29] event against holder 1/28                     cfg=lingering-shadow file=/etc/crowdsec/scenarios/http-generic-bf.yaml name=crowdsecurity/http-generic-bf
DEBU[15-12-2021 11:49:29] .Meta[log_type] = 'http_access-log'           id=weathered-fire name=child-crowdsecurity/apache2-logs stage=s01-parse
DEBU[15-12-2021 11:49:29] setting target StrTime to 15/Dec/2021:17:39:52 +0000
DEBU[15-12-2021 11:49:29] evt.StrTime = '15/Dec/2021:17:39:52 +0000'    id=weathered-fire name=child-crowdsecurity/apache2-logs stage=s01-parse
DEBU[15-12-2021 11:49:29] .Meta[service] = 'http'                       id=weathered-fire name=child-crowdsecurity/apache2-logs stage=s01-parse
DEBU[15-12-2021 11:49:29] .Meta[source_ip] = '176.53.221.38'            id=weathered-fire name=child-crowdsecurity/apache2-logs stage=s01-parse
DEBU[15-12-2021 11:49:29] .Meta[http_status] = '308'                    id=weathered-fire name=child-crowdsecurity/apache2-logs stage=s01-parse
DEBU[15-12-2021 11:49:29] .Meta[http_path] = '/'                        id=weathered-fire name=child-crowdsecurity/apache2-logs stage=s01-parse
TRAC[15-12-2021 11:49:29] State after nodes : true                      id=weathered-fire name=child-crowdsecurity/apache2-logs stage=s01-parse
TRAC[15-12-2021 11:49:29] ! No node statics                             id=weathered-fire name=child-crowdsecurity/apache2-logs stage=s01-parse
DEBU[15-12-2021 11:49:29] Event leaving node : ok                       id=weathered-fire name=child-crowdsecurity/apache2-logs stage=s01-parse
TRAC[15-12-2021 11:49:29] node is successful, check strategy
DEBU[15-12-2021 11:49:29] move Event from stage s01-parse to s02-enrich  id=weathered-fire name=child-crowdsecurity/apache2-logs stage=s01-parse
TRAC[15-12-2021 11:49:29] Node successful, continue                     id=weathered-fire name=child-crowdsecurity/apache2-logs stage=s01-parse
TRAC[15-12-2021 11:49:29]       sub-node (weathered-fire) ret : true (strategy:next_stage)  id=throbbing-field name=crowdsecurity/apache2-logs stage=s01-parse
DEBU[15-12-2021 11:49:29] child is success, OnSuccess=next_stage, skip  id=throbbing-field name=crowdsecurity/apache2-logs stage=s01-parse
TRAC[15-12-2021 11:49:29] State after nodes : true                      id=throbbing-field name=crowdsecurity/apache2-logs stage=s01-parse
TRAC[15-12-2021 11:49:29] ! No node statics                             id=throbbing-field name=crowdsecurity/apache2-logs stage=s01-parse
DEBU[15-12-2021 11:49:29] Event leaving node : ok                       id=throbbing-field name=crowdsecurity/apache2-logs stage=s01-parse
TRAC[15-12-2021 11:49:29] node is successful, check strategy
DEBU[15-12-2021 11:49:29] node reached the last stage : s02-enrich      id=throbbing-field name=crowdsecurity/apache2-logs stage=s01-parse
TRAC[15-12-2021 11:49:29] Node successful, continue                     id=throbbing-field name=crowdsecurity/apache2-logs stage=s01-parse
TRAC[15-12-2021 11:49:29] node (throbbing-field) ret : true             node-name=throbbing-field stage=s01-parse
DEBU[15-12-2021 11:49:29] node successful, stop end stage s01-parse     node-name=throbbing-field stage=s01-parse
---snip---

Did I configure something incorrectly?

Unable to build Caddy with Plugin

Hi I've been trying to get this plugin to build with xcaddy in docker but to no avail.

It fails no matter what I do.

My dockerfile is as such

FROM caddy:2.4.3-builder-alpine AS builder

RUN xcaddy build \
    --with github.com/ueffel/caddy-brotli \
    --with github.com/mholt/caddy-dynamicdns \
    --with github.com/hslatman/caddy-crowdsec-bouncer/http \
    --with github.com/caddyserver/caddy/v2/cmd \
    --with github.com/caddyserver/caddy/v2/modules/standard \
    --with github.com/hslatman/caddy-crowdsec-bouncer/layer4 \
    --with github.com/caddy-dns/cloudflare

FROM caddy:2.4.3-alpine

COPY --from=builder /usr/bin/caddy /usr/bin/caddy

I've tried as well just using these two but they failed as well so i tried with all 4 of the components but it made no difference.
--with github.com/hslatman/caddy-crowdsec-bouncer/layer4
--with github.com/hslatman/caddy-crowdsec-bouncer/http

This is the build error I receive.

2021/08/18 20:00:05 [INFO] exec (timeout=0s): /usr/local/go/bin/go build -o /usr/bin/caddy -ldflags -w -s -trimpath
# github.com/hslatman/caddy-crowdsec-bouncer/crowdsec
/go/pkg/mod/github.com/hslatman/[email protected]/crowdsec/crowdsec.go:44:37: cannot use parseCaddyfileGlobalOption (type func(*caddyfile.Dispenser) (interface {}, error)) as type httpcaddyfile.UnmarshalGlobalFunc in argument to httpcaddyfile.RegisterGlobalOption
2021/08/18 20:00:34 [INFO] Skipping cleanup as requested; leaving folder intact: /tmp/buildenv_2021-08-18-1958.477867331
2021/08/18 20:00:34 [FATAL] exit status 2
The command '/bin/sh -c xcaddy build     --with github.com/ueffel/caddy-brotli     --with github.com/mholt/caddy-dynamicdns     --with github.com/hslatman/caddy-crowdsec-bouncer/http     --with github.com/caddyserver/caddy/v2/cmd     --with github.com/caddyserver/caddy/v2/modules/standard     --with github.com/hslatman/caddy-crowdsec-bouncer/layer4     --with github.com/caddy-dns/cloudflare' returned a non-zero code: 1

rough roadmap?

Thanks for this plugin, it looks like something that could be very useful.
Would be nice to see a simple feature checklist/roadmap.

Do we need a separate crowdsec agent running?

I'm new to crowdsec, but my understanding is that I need an agent running on the same machine/vm/container to consume logs and send alerts to the LAPI.

Does this also handle that for Caddy logs or is it just the bouncer? Do we need Caddy's logs set to a certain mode or anything?

error: URL does not have a scheme

Hello,
Same issue as previously here : #17

Deleting the entire Caddy configuration in order to resolve this problem does not seem to me to be a viable solution.
Would it be possible to have more information on the origin of this error?

The exact error log in caddy:

{
  "level": "error",
  "ts": 1702530739.0322273,
  "logger": "admin.api",
  "msg": "request error",
  "error": "loading config: loading new config: loading http app module: provision http: server srv0: setting up route handlers: route 5: loading handler modules: position 0: loading module 'subroute': provision http.handlers.subroute: setting up subroutes: route 0: loading handler modules: position 0: loading module 'crowdsec': provision http.handlers.crowdsec: getting crowdsec app: loading crowdsec app module: provision crowdsec: URL  does not have a scheme (i.e https)",
  "status_code": 400
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.