this is a fork of the original: https://github.com/acouvreur/traefik-modsecurity-plugin
This fork introduces alpine images, and a custom http.transport, and a caching layer once mod-security has processed a request
see: https://github.com/traefik/plugindemo#troubleshooting
Traefik plugin to proxy requests to owasp/modsecurity-crs:apache
Demo with WAF intercepting relative access in query param.
- docker-compose up
- Go to http://localhost/website, the request is received without warnings
- Go to http://localhost/website?test=../etc, the request is intercepted and returned with 403 Forbidden by owasp/modsecurity
- You can you bypass the WAF and check attacks at http://localhost/bypass?test=../etc
This is a very simple plugin that proxies the query to the owasp/modsecurity apache container.
The plugin checks that the response from the waf container hasn't an http code > 400 before forwarding the request to the real service.
If it is > 400, then the error page is returned instead.
The dummy service is created so the waf container forward the request to a service and respond with 200 OK all the time.
NEW: Caching modsecurity responses helps to minimize the overhead of processing every request and improves performance. By generating cache keys based on various factors like the request method, host, request URI, headers, and remote address, we can ensure that different requests are treated uniquely, while similar requests can be served from the plugins modsecurity response cache. This approach helps in reducing the load on the modsecurity instance and improves response times for requests. You can tune this to your liking but we recommend the following options:
This plugin supports these configuration:
-
modSecurityUrl
: (mandatory) it's the URL for the owasp/modsecurity container. -
timeoutMillis
: (optional) timeout in milliseconds for the http client to talk with modsecurity container. (default 2 seconds) -
maxBodySize
: (optional) it's the maximum limit for requests body size. Requests exceeding this value will be rejected usingHTTP 413 Request Entity Too Large
. The default value for this parameter is 10MB. Zero means "use default value". -
cacheConditionsMethods
: (optional) An array of HTTP methods for which caching is allowed. (default ["GET"]) -
cacheConditionsNoBody
: (optional) Specifies if requests with no body (content-length of 0) should be cached. ( default true) -
cacheKeyIncludeHost
: (optional) Specifies if the host should be included in the cache key. (default true) -
cacheKeyIncludeRemoteAddress
: (optional) Speifics if the remote request address should be included in the cache key (default true) -
cacheKeyIncludeHeaders
: (optional) Specifies if the headers should be included in the cache key. (default true) -
cacheKeyHeaders
: (optional) An array of specific headers to be included in the cache key when CacheKeyIncludeHeaders is true. (ie: the default ["User-Agent"])
Note: some headers are ALWAYS blacklisted, and even if you list them here, they will still not be cached:
Authorization: *, Set-Cookie: *, Cache-Control: no-store, Pragma: no-cache, Expires: -1 (date in the past)
Note: body of every (non-cached) request will be buffered in memory while the request is in-flight (i.e.: during the
security
check and during the request processing by traefik and the backend), so you may want to tune maxBodySize
depending on
how much RAM you have.
docker-compose -f docker-compose.local.yml up
to load the local plugin