Caddy rate_limit whitelist

1. The problem I’m having:

I’m using the rate_limit mholt/caddy-ratelimit plugin for caddy. I want to be able to whitelist IP addresses for actual clients since we have some that all hop onto a single VPN IP. My current config looks like this. However, I’m not sure how I would update my config to “whitelist” certain IP addresses.

	rate_limit @not_accepted {
		distributed
		jitter 0.1
		zone bot_throttling {
			key {remote_host}
			events 100
			window 30s
		}
		sweep_interval 2m
	}

See below for full config.

2. Error messages and/or full log output:

No error, just need config help.

3. Caddy version:

Caddy 2.6 via Docker

4. How I installed and ran Caddy:

Dockerfile → docker-compose.yml

a. System environment:

Debian Linux

b. Command:

Config help needed, no commands.

c. Service/unit/compose file:

My docker file:

ARG CADDY_VERSION=2.6

FROM caddy:${CADDY_VERSION}-builder AS builder

RUN xcaddy build \
    --with github.com/mholt/caddy-ratelimit

FROM caddy:${CADDY_VERSION}

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

CMD ["caddy", "run", "--config", "/etc/caddy/Caddyfile"]

d. My complete Caddy config:

{
	order rate_limit before basicauth
}

(common) {
	header /* {
		-Server
	}
	on_demand_tls {
		ask "http://localhost:8080/domain/verify"
	}
}

http://localhost:8080 {
	header {
		-Server
	}
	root /domain/verify /data/apps/onboard-app/public
	try_files {path} index.php =404
	php_fastcgi 127.0.0.1:9000 {
		env APP_ENV prod
		dial_timeout 3s
		read_timeout 50s
		write_timeout 30s
		capture_stderr
	}
	encode gzip zstd
}

https:// {
	@not_accepted not path *.js *.css
	rate_limit @not_accepted {
		distributed
		jitter 0.1
		zone bot_throttling {
			key {remote_host}
			events 100
			window 30s
		}
		sweep_interval 2m
	}

	header {
		-Server
		X-Real-IP {remote}
		Content-Security-Policy: "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://www.google.com/recaptcha/ https://www.gstatic.com/recaptcha/ ; style-src 'self' 'unsafe-inline'; img-src 'self' *.amazonaws.com data:; font-src 'self'; object-src 'none'; frame-ancestors *; frame-src *; child-src *; form-action 'self' https://*.okta.com ;"
		Strict-Transport-Security "max-age=31536000; includeSubDomains"
		X-Content-Type-Options: nosniff
		Referrer-Policy no-referrer-when-downgrade
		Permissions-Policy interest-cohort=()
	}

	@hackers remote_ip 185.238.249.143/32 34.204.85.92/32 192.81.128.219/32
	respond @hackers "Ah ah ah.. you didn't say the magic word." 403

	tls ob2@mydev.site {
		on_demand
	}

	root * /data/apps/onboard-app/public
	try_files {path} index.php =404
	php_fastcgi 127.0.0.1:9000 {
		env APP_ENV prod
		dial_timeout 3s
		read_timeout 50s
		write_timeout 30s
		capture_stderr
	}
	encode gzip zstd
	file_server

	log {
		output file "/logs/caddy.log" {
			log_level INFO
			roll_size 2000
			roll_keep_for 30d
			roll_keep 1000
		}
	}
}

5. Links to relevant resources:

If I should reach out to that plugin dev let me know but I didn’t know if there was a caddy language construct I’m not aware of to pull this off. Like a “and not 1.2.3.4” sort of thing.

Have you tried to extend the matchers like this?

	@not_accepted {
	        not path *.js *.css
	        not remote_ip 1.2.3.4
	}
1 Like

This looks like exactly what I need, I’ll give that a shot. Thank you. I’ll report back for others.

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.