Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

EDNS0 MAC-Address support #105

Closed
cbuijs opened this issue Dec 5, 2020 · 13 comments
Closed

EDNS0 MAC-Address support #105

cbuijs opened this issue Dec 5, 2020 · 13 comments

Comments

@cbuijs
Copy link
Contributor

cbuijs commented Dec 5, 2020

Would it be possible to add the MAC-Address of the DNS Client (querier) to EDNS0 (Option code point 5, 65001 is also used)?

Similar like the IP-Address/Subnet EDNS0 ECS feature?

Equivalent of the add-mac feature in DNSMasq.

Some DNS Providers (Like NextDNS, OpenDNS etc) can use this as identifier and apply policies to. It is preferable to use when DHCP and or IPv4/IPv6-Dual-stack is used to have a better/unique ID to work with.

Also, in that light: Can the mac-address also be used in the source of router rules? That would make this one complete.

@folbricht
Copy link
Owner

Can do, but I'm not clear on which option that should be in. Option 5 seems to be used for DAU in https://tools.ietf.org/html/rfc6975, and 65001 is reserved. Is there a standards doc for it somewhere?

@folbricht
Copy link
Owner

Added a generic (low-level) edns0-modifier for this. I think this may work and allow the use of any option code since there doesn't seem to be agreement what code is used for MAC addresses. You can try it on the issue-105 branch. Should look like:

[groups.opendns-mac]
type = "edns0-modifier"
resolvers = ["opendns"]
edns0-op = "add" # "add" or "delete". Defaults to "" which does nothing.
edns0-code = 65001
edns0-data = [1, 2, 3, 4, 5, 6]

@cbuijs
Copy link
Contributor Author

cbuijs commented Dec 6, 2020

Awesome!

Each digit in edns0-data is a hexvalue to build up a string?

I'll test/use and report back on findings.

What about the ability to use the mac-address in a routers rule as source? This kind of circumvents the need to fiddle with the edns0 stuff to be honest. Which indeed is a hot mess :-). Now I think about this, it is probably a much cleaner/nicer way and makes it an option to avoid EDNS0 all together (just let routedns do the routing instead of relying on the service itself based on a crappy EDNS0 standard). Probably a bit more privacy sensitive as well, as less info is needed to sent to the end-point.

@cbuijs
Copy link
Contributor Author

cbuijs commented Dec 6, 2020

BTW, the only "clear" documentation I could find sits here:

https://blog.powerdns.com/2016/01/27/per-device-dns-settings-selective-parental-control/
https://lists.dns-oarc.net/pipermail/dns-operations/2016-January/014151.html

The community is divided. Seems that DNSMASQ uses 65001 when using add-mac feature and is generally taken as example. Nothing official of course. The NextDNS client can use it (65001) to forward DNS based on mac of the dns clients it serves (it needs dnsmasq sit in front, yech).

My thinking is to have something like routedns do this all together, I am okay not using EDNS0 at all, but use routers rules with mac-address source instead and do routing based on that. That will always work. EDNS0 and 65001 potentially will break or be standardized at some point.

Basically an dnsmasq-nextdns alternative with a mac-address feature and becomes protocol-familiy (IPV4 and IPV6) independant ;-).

@folbricht
Copy link
Owner

I can't actually get the client MAC from the connection details, and it wouldn't be reliable if there's an actual router between the client and routedns. edns0-modifier is a very low-level way of doing this. While it allows you to set any option with any content, it's not exactly convenient since TOML doesn't allow hex notation. I could make a dedicated MAC address piece that let's you provide the address in a more common format like data = "01:02:03:04:05:06" but you would still need to provide the option code since there doesn't appear to be a standard. Or I could change the format of the edns0-data so you can use that hex notation in a string with : as separator. Like this perhaps?

[groups.opendns-mac]
type = "edns0-modifier"
resolvers = ["opendns"]
edns0-op = "add"
edns0-code = 65001
edns0-data = "01:02:03:04:05:06"

Regarding routing by source, did you mean to allow routing based on the value of a given EDNS0 option code? (Since I can't get the client MAC from the network connection). Like this?

[routers.my-router]
routes = [
  { edns0code=65001, edns0value= "01:02:03:04:05:06", resolver="some-upstream-resolver" },
  { resolver="cloudflare-doh-1-1-1-1-get" },
]

@cbuijs
Copy link
Contributor Author

cbuijs commented Dec 6, 2020

No, the actual MAC-Address from the query/client.

@folbricht
Copy link
Owner

The client MAC isn't accessible with the network libraries, and even if it was it'd be unreliable since it changes with every hop (router).

@cbuijs
Copy link
Contributor Author

cbuijs commented Dec 6, 2020

Gotcha. It is for local DNS clients on the same/local subnet only, which is the original limitation with the other solutions as well. With IPV6 and address randomization (now also with mac-addresses randomization) for privacy concerns it becomes difficult as well.

@folbricht
Copy link
Owner

Can you explain the use-case a bit more? I would have thought that adding the MAC to EDNS0 would be sufficient for OpenDNS/NextDNS to identify the account. And in routedns you could route based on client IP subnets, only adding your MAC to EDNS0 for clients you know.

@cbuijs
Copy link
Contributor Author

cbuijs commented Dec 6, 2020

IPv6 Clients using Slaac and Privacy extensions change IP's a lot within a subnet, so pinning down a couple of IP's and rerouting them becomes easier doing it by mac-address.

Also you only need one rule for both IPv4 and IPv6 addresses of a particular client.

In my case, I have a couple of clients in a subnet I want to exclude from some filtering for auto-updates, or give them specific access to geo-blocked IP's to "unbreak" them due to filtering, and not doing it generally/globally to not expose other clients and such.

@folbricht
Copy link
Owner

Do the clients use DoH by any chance? It might be possible to use an identifier in the URL perhaps (https://someID.mydns.test/dns), which I believe is what Cloudflare uses to identify clients. Though depending on what OS that is, bootstrapping that name into an IP could be an issue.

@cbuijs
Copy link
Contributor Author

cbuijs commented Dec 6, 2020

That is an interesting thought for some other cases indeed. Certainly for privacy kind of features or routing.

But in this/my case it is all just plain Do53.

But routing on EDNS option as suggested earlier could work when I put dnsmasq with add-mac in front of RouteDNS for example, rather avoid using this ;-).

What about this:
https://github.com/mdlayher/arp
(Seems to be IPV4 only though)

Or this, utilizing the arp cache that sits on every system more or less:
https://github.com/mostlygeek/arp

Most of it looks clunky though.

@cbuijs
Copy link
Contributor Author

cbuijs commented Dec 7, 2020

I came-up with something else.

I created a little scipts to get all of the IP's of the MAC's I want to redirect from local arp-cache. Then create a little IPs list with the matching MACs (do-not-filter.cidr.list) every 5 mins via a cron-job.

In RouteDNS I use above (cidr/ip) list with client-blocklist and blocklist-reload of 120 seconds. Works perfectly.

BTW, to get all IPs/Macs on linux:
ip neigh show

The client-blocklist section:

[groups.filter]
type = "client-blocklist"
resolvers = ["filter"]
blocklist-refresh = 120
blocklist-resolver = "do-not-filter"
blocklist-source = [
        {format = "cidr", source = "do-not-filter.cidr.list"},
]

You can force-update the arp-cache by short-pinging the broadcast address of the subnet(s). Not advisable, and make sure use a short timeout. Can be a self-inflicted DDOS attack ;-).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants