How to drop request completely based on IP

1. Caddy version (caddy version):

v2.0.0

2. How I run Caddy:

docker

a. System environment:

docker

b. Command:

docker-compose up

d. My complete Caddyfile or JSON config:

  @ipfilter {
    not remote_ip {$BLOCKED}
  }
route @ipfilter {
    # redirect
    redir https://example.com/
    # or respond
    # respond "Access denied" 403 {
    #   close
    # }
  }

3. The problem I’m having:

How could I make the above route simply drop requests from the blocked IPs, instead of returning a response?

Hi @dadatuputi, welcome to the Caddy community!

Caddy’s HTTP server is fundamentally designed to accept connections and produce a response.

I can’t think of any method to configure Caddy to accept a HTTP request, inspect its remote IP, and then do nothing. All the directives and handlers that are configurable are configurable, generally, towards producing some kind of response.

The best you can do is not configure it to do anything for those requests. This will produce an empty response, but it isn’t the same as dropping the connection.

If you want to block connections based on remote IP, a firewall is the best tool for the job.

2 Likes

Yeah, once we get to the HTTP request it’s too late to reject the connection. You can close it using the close subdirective of the respond handler, but that will still write at least an empty response.

You could use a firewall as @Whitestrake suggested, or there’s also a layer 4 app for Caddy I’m building that operates a little lower in the stack and can drop connections immediately based on IP, without any HTTP communication: GitHub - mholt/conncept: Project Conncept: A layer 4 app for Caddy that multiplexes raw TCP/UDP streams

But, a firewall that operates at level 3 would probably be the most efficient, lowest-level solution – it could drop actual packets without any notion of a connection. A Caddy module could be written to do this, or the Linux kernel can be configured for this too, I believe.

2 Likes

Thanks for the replies. I am running a docker-compose in gcloud’s free tier, which is free except for egress traffic to China and Australia. To block those two countries, I’m generating a list of subnets to block. It would be easiest to add the list of subnets to my Caddyfile as an env variable, but if it’s still generating a response then that’s still egress traffic that gcloud will charge for. I agree, a firewall solution is best, if not the easiest. Thanks again.

ufw is a pretty easy firewall if it comes to blocking subnets. Btw each machine connected to the internet should have an active firewall. And as good as caddy is it’s never a replacement for a firewall

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