Why remote_ip can not parse cloudflare or cloudfront ip which from a plugin

1. The problem I’m having:

when i use a cloudflare ip list (come from a plugin) after remote_ip ,it failed to parse,log said: loading matcher sets: module name ‘remote_ip’: provision http.matchers.remote_ip: invalid IP address: ‘cloudflare’: ParseAddr(“cloudflare”): unable to parse

2. Error messages and/or full log output:

loading matcher sets: module name ‘remote_ip’: provision http.matchers.remote_ip: invalid IP address: ‘cloudflare’: ParseAddr(“cloudflare”): unable to parse I


3. Caddy version:

2.10.2

4. How I installed and ran Caddy:

caddy:
    build:
        context: .
        dockerfile_inline: |
            FROM caddy:2.10.2-builder AS builder
            RUN xcaddy build \
                --with github.com/caddy-dns/cloudflare \
                --with github.com/xcaddyplugins/caddy-trusted-cloudfront \
                --with github.com/WeidiDeng/caddy-cloudflare-ip \
                --with github.com/fvbommel/caddy-combine-ip-ranges
            FROM caddy:2.10.2
            COPY --from=builder /usr/bin/caddy /usr/bin/caddy
    container_name: caddy
    restart: unless-stopped
    logging:
        options:
            max-size: "10m"
            max-file: "3"
    ports:
        - "80:80"
        - "443:443"
        - "443:443/udp"
    volumes:
        - ./caddy/config/Caddyfile:/etc/caddy/Caddyfile
        - ./caddy/data:/data
        - ./caddy/config:/config
        - ./site:/var/www
    environment:
        - CLOUDFLARE_API_TOKEN=xxxxxxxxxxxxxxxxxxx

My complete Caddy config:

{
        acme_dns cloudflare {env.CLOUDFLARE_API_TOKEN}
        log {
                output stdout
                format filter {
                        wrap json {
                                time_format wall_milli
                        }


                        request>headers>Referer replace XXXXXX
                        headers>X-Padding replace XXXXXX

                }
                level debug
        }

        servers {
                trusted_proxies combine {
                        cloudfront
                        cloudflare {
                                interval 12h
                                timeout 15s
                        }
                        static private_ranges
                }
                trusted_proxies_strict
        }
}


xxx.xxx.com {

        @denied not remote_ip cloudflare
        handle @denied {

                respond "Hello, you are not from cloudflare!"

        }

        file_server {
                root /var/www
        }
}

the setting in servers {} part works fine, log said that it can correctly get the real client ip from X-Forwarded-For after i set CDN ip list to trusted_proxies。

but those list dose not work LIKE this:
not remote_ip cloudflare

not remote_ip cloudfront

not remote_ip combine {xxxx }

log said “unable to parse“ ,so why the ip list produced by plugin worked in trusted_proxies, but they can not be used after “remote_ip“ , what should i do? please help me, thanks!

cloudflare is not an IP address. The remote_ip matcher does not take IP source plugins, it takes a literal list of IPs. You would need to use this plugin GitHub - tuzzmaniandevil/caddy-dynamic-clientip: http.matchers.dynamic_client_ip matches requests by the client IP address, the ip addresses to match against is provided my a module that implements IPRangeSource to have a matcher which takes an IP source plugin as input.

But if what you’re trying to do is reject requests if they aren’t from a trusted proxy, you can instead match whether vars.client_ip is set, and if it’s not then you know it wasn’t filled by trusted_proxies. Use the vars matcher for this. Request matchers (Caddyfile) — Caddy Documentation

thanks. yes, what i want is:reject requests if they aren’t from a trusted proxy , even the direct request from the client .

i tried several different way , but i found that {vars.client_ip} is never empty.

so my final solution is here:

        @not_from_trusted_proxy vars {vars.client_ip} {remote_host}

        handle @not_from_trusted_proxy {

                abort
        }

        file_server {
                root /var/www
        }
       
  • if request from a untrusted proxy: {vars.client_ip}={remote_host}, abort
  • if request from a direct connection : {vars.client_ip}={remote_host},abort
  • if request from the trust proxy (in this case, Cloudflare) {vars.client_ip}! ={remote_host} ,ok pass

bingo~


GitHub - tuzzmaniandevil/caddy-dynamic-clientip: http.matchers.dynamic_client_ip matches requests by the client IP address, the ip addresses to match against is provided my a module that implements IPRangeSource plugin is not suitable for my case, because it is the replacement of clientip not remoteip .

dynamic_client_ip cloudflare dose not work in this case.

if there is a dynamic_remote_ip plugin , dynamic_remote_ip cloudflare will work.

thanks a lot

Caddy is incredibly flexible — I can use variables just like I did above to achieve exactly what i need. It’s like a Lego-style web server. Absolutely amazing!

1 Like

You can slightly simplify, you don’t need the handle

@untrusted vars {vars.client_ip} {remote_host}
abort @untrusted