Use ip_mask in Caddyfile V2

1. Caddy version (caddy version):

2. How I run Caddy:

v2.2.1 h1:Q62GWHMtztnvyRU+KPOpw6fNfeCD3SkwH7SfT1Tgt2c=

a. System environment:

Arch Linux x86_64 Kernel 5.9.1-arch1-1

b. Command:

$ caddy run -config Caddyfile

d. My complete Caddyfile or JSON config:

:3000 {
  log {
    output file /tmp/caddy/access.log
    format filter {
      wrap console
        fields {
          format ip_mask {
            ipv4_cidr "255.255.255.0"
          }
        }
    }
  }
  root * /tmp
    file_server
}

3. The problem I’m having:

Can’t quite work out how to use the ip_mask log field filter

4. Error messages and/or full log output:

With the config above, I get the following error:

2020/10/20 15:20:02.136 INFO    using provided configuration    {"config_file": "Caddyfile", "config_adapter": ""}
run: adapting config using caddyfile: parsing caddyfile tokens for 'log': Caddyfile:8 - Error during parsing: unrecognized subdirective ipv4_cidr

5. What I already tried:

Tried bunch of different combinations of the above config but I’m not able to work out how the whole format/wrap/filter/encoder thing is doing it’s work, and not finding any examples on how to use ip_mask in Caddyfile either. Found one JSON version but cannot figure out how that translates into Caddyfile syntax (Upgrading to v2 - #9 by conorlburns)

I’m trying to convert a Caddyfile I have for v1, into v2 format, but not having great luck. What I used to use:

  log stdout {
    ipmask 255.255.0.0 ffff:ffff:ffff:ff00::
  }

Looks like the docs I wrote for this haven’t yet been pushed to the website:

https://github.com/caddyserver/website/pull/90/files?short_path=adc9e31#diff-adc9e3188661e6571c1013eb6cbf382d182e38d3666415f3b4507d11589adef7

Specifically, the issue you’re running into is that you need to specify a field to manipulate. Also, the CIDR is actually “the number of bytes to retain, from the left”, so for your IPv4 CIDR, that should actually be 24, and I think for IPv6 it would be 56, according to this table? IPv6 – Charts and Explanations | CIDR/EU

log {
	output file /tmp/caddy/access.log
	format filter {
		wrap console
		fields {
			request>remote_addr ip_mask {
				ipv4 24
				ipv6 56
			}
		}
	}
}
1 Like

Thanks a lot! Didn’t search through the docs source, only docs website so doesn’t surprise me I didn’t find it! Checked the docs you linked and everything makes more sense now. Thanks a lot! :slight_smile:

Although, looking at the ip_mask JSON docs (JSON Config Structure - Caddy Documentation) and comparing it to how the Caddyfile ends up, how can I figure out that “ipv4_cidr” in JSON should be defined as “ipv4” in Caddyfile? (granted this wasn’t a typo)

1 Like

The Caddyfile adapter is essentially a usability wrapper over JSON config, so there will be differences. This is one of them, where I thought it would be easier to just type ipv4 instead.

The best place to look is in the code, ultimately, if something is missing from the docs (there shouldn’t be, typically, but this was just an issue with syncing the repo with the website, which I don’t control):

2 Likes

Awesome, thanks for pointing me to the right place in the code :slight_smile:

1 Like

I updated the log documentation. Sorry about that.

2 Likes

May I continue on this thread because I’m not able to set it up correctly or I understand the CIDR notation incorrectly. These are my settings:

localhost, customer1.company.local {
    reverse_proxy localhost:8091
    log {
        level INFO
        output file /Users/christophkluge/Development/github/christoph-kluge/caddy2-php-client/caddy-data/logs/access.log
        format filter {
        	wrap json
        	fields {
                common_log delete
                request>headers>Accept delete
                request>headers>Accept-Encoding delete
                request>headers>Accept-Language delete
                request>headers>Cache-Control delete
                request>headers>Pragma delete
                request>headers>Sec-Fetch-Mode delete
                request>headers>Sec-Fetch-Dest delete
                request>headers>Sec-Fetch-Site delete
                request>headers>Sec-Fetch-User delete
                request>headers>Upgrade-Insecure-Requests delete
        		request>remote_addr ip_mask {
                    ipv4 24
                    ipv6 58
                }
                request>tls delete
                resp_headers delete
        	}
        }
    }
}

And this is how each single log line looks like (pretty-print). Even on a staging server, connection from a real remote it’s the same.

Local logfile:

{
  "level": "error",
  "ts": 1603705413.134432,
  "logger": "http.log.access.log0",
  "msg": "handled request",
  "request": {
    "remote_addr": "[::]:51153",
    "proto": "HTTP/2.0",
    "method": "GET",
    "host": "localhost",
    "uri": "/",
    "headers": {
      "User-Agent": [
        "curl/7.64.1"
      ]
    }
  },
  "duration": 0.296409177,
  "size": 6341,
  "status": 404
}

Staging logfile:

{
	"level": "info",
	"ts": 1603705903.124576,
	"logger": "http.log.access.clients_log",
	"msg": "handled request",
	"request": {
		"remote_addr": "[::]:55335",
		"proto": "HTTP/2.0",
		"method": "GET",
		"host": "test2.caddy.example.net",
		"uri": "/",
		"headers": {
			"User-Agent": ["curl/7.64.1"]
		}
	},
	"duration": 0.000063582,
	"size": 0,
	"status": 301
}

My Expecatation would be to see at least 127.0.x.x or 91.65.x.x in the logs.

That seems to be working as expected, as far as I can tell. The request had an IPv6 address, so it applied that mask, I think. Is that not the case?

I was running curl explicitly via ipv4. I use an EC2 test-instance which I’m accessing directly (no ELB, ALB nor NLB is in place).

curl -k -v4 -X GET -I https://test2.caddy.example.net

Using -k because I’m testing with the staging acme server.

And if you remove the ip mask, you do see an IPv4 address?

I have a hunch… it might be that the IP mask filter needs to split the host and port before applying the mask, it might not be working correctly because remote_addr has the client port in that field as well, and isn’t simply an IP address.

// Update: I did adressed the ipv4 issue here: Fixes logging filter for ip_mask with ipv4 adresses by christoph-kluge · Pull Request #3821 · caddyserver/caddy · GitHub

Without the filter I see the full ipv4 adress as expected. Do you need more information?

Another small case which I have discovered: It’s possible to apply only ipv4 or ipv6 to the configfile. In this case the missing type is translated to "<nil>:57681". Not sure if this is intented.

Example:

request>remote_addr ip_mask {
    ipv4 24
}

OR

request>remote_addr ip_mask {
    ipv6 24
}

Looks like the code is already splitting the host and port. The relevant code is here if you want to try and find a fix. PRs welcome!

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