caddy-dynamicdns icon indicating copy to clipboard operation
caddy-dynamicdns copied to clipboard

provide option to include private IP addresses

Open tylervick opened this issue 1 year ago • 10 comments

Hello!

I use caddy-dynamicdns to enable ddns on my private network/VPN (via Tailscale). Unfortunately, the change in #61 regresses my use case since private IPs are no longer returned by ip_source interface.

I'm able to work around this with a custom caddy module to provide a new IPSource. However, after seeing @jm355 call out my exact use case https://github.com/mholt/caddy-dynamicdns/issues/59#issuecomment-1984940664_ I wanted to track this for posterity should anyone else run into this!

@Monviech's suggestion in #59 to include a include_private_ips flag sounds good to me. I'm happy to get started on a PR, unless maintainers have a better idea 🙂

tylervick avatar Sep 06 '24 16:09 tylervick

Heh, I guess that will work then. :+1: Want to submit a PR?

mholt avatar Sep 06 '24 17:09 mholt

I'm not sure what happens if both a public and private ip gets returned. Based on the name include_private_ips, I'm guessing it would return both, so maybe calling it something else like only_private_ips and only returning a private ip might be better? Just a minor nitpick/pointer, and it's been a while since I looked at this so I'm not sure

jm355 avatar Sep 06 '24 18:09 jm355

Good point. It's almost like you'd need to toggle public/private, but not have both.

mholt avatar Sep 06 '24 20:09 mholt

If I'm reading it correctly issue 59 describes situations where there may even be multiple private IPs assigned to an interface. In this scenario the user is probably only interested in one of them (or rather one ipv4, one ipv6), and so a flag to use private IPs doesn't necessarily solve the problem.

However I think that people looking to find a private IP will know the subnet it is expected to be in.

So how about a more general solution then: include_subnets which can take one or more ipv4/ipv6 CIDR ranges, and will discard IPs outside of those ranges. If include_subnets is not specified then we take the default behavior of ignoring private IPs. I think it's a nice bonus that this also acts as a bit of a sanity check on the sourced IP.

Either way I'd like to work on a PR, but let me know if I'd be stepping on your toes @tylervick as it's been a few months so I assume you haven't found the time.

eliasvasylenko avatar Feb 11 '25 21:02 eliasvasylenko

That sounds good to me but I haven't looked closely, it's been a while, and I'm no expert on ip addresses. Might also make sense to have an exclude_subnets option, if for example you want to explicitly exclude link-local addresses (fe80::/10) or any other subnet(s)

jm355 avatar Feb 11 '25 21:02 jm355

Yes that makes sense, and this also makes the default behaviour easily expressible with an explicit config which I think ties it together a bit more nicely.

I'm not super familiar with caddy and caddyfile syntax, but I assume the end result here wants to look something like:

ip_source interface lan {
  include_subnets "192.168.1.0/24" "whatever"
  exclude_subnets "blah"
}

Where the trailing block is optional? If that makes sense to you as a starting point then I'll just jump in.

Although now I'm wondering if this would make sense to lift out of the ip_source.interface config so that it could be applied to other IP sources too. Would that be useful... Well I'll take a closer look how everything works before I start to ask too many questions I don't have the context for.

eliasvasylenko avatar Feb 11 '25 21:02 eliasvasylenko

The other nice thing about having an exclude/include subnet option is that because the normal "permanent" ipv6 address postfix is based on your mac address iirc, but your prefix may come from your isp and be subject to change, you can explicitly use/not use the "static" address postfix by including/excluding ::1234:5678:9abc:def0/::ffff:ffff:ffff:ffff

Keep in mind this formatting could be way off, I'm having trouble finding info online about the proper syntax for filtering out the prefix but keeping the postfix

jm355 avatar Feb 11 '25 22:02 jm355

Ah that's interesting. I also am no expert on ipv6, but I can't find any reference to this syntax or any indication that it's at all standardised. In fact I see at least one alternative non-standard solution used by e.g. nftables here https://michael.kjorling.se/blog/2024/prefix-agnostic-ipv6-address-filtering-in-linux-nftables/

Your way is a bit nicer to use than that, but still perhaps non standard? In any case I can start by shooting for basic CIDR ranges and see where it goes.

eliasvasylenko avatar Feb 12 '25 20:02 eliasvasylenko

I don't remember the exact thread, but I think I first learned of that format from a forum thread on freshtomato which you can use to port forward for certain ipv6 addresses. I also think it's justified because I saw a lot of cidr things saying that the /<number> format is equivalent to something like ffff:ffff:: which makes sense if it's just bitmasks

jm355 avatar Feb 12 '25 20:02 jm355

For sure, the logic of it makes sense and I like the idea. But it's the difference between using the standard lib CIDR parser and writing a bunch of parsing & bitmasking logic. It's not the most complex thing in the world but I'd rather not lump so much into the same PR for a first pass.

eliasvasylenko avatar Feb 16 '25 11:02 eliasvasylenko