DNS forwarder interfaces binding - GUI does not show real configuration
-
Before save (what I wanted to configure)
After save (what's shown as configured)
The bindings that get really assigned per config.xml backup are correct:
<dnsmasq><enable><custom_options><interface>lan,fe80::20d:b9ff:fe2c:f47c,opt1,fe80::20d:b9ff:fe2c:f47e,opt2,fe80::20b:6bff:fe23:a22d,lo0</interface></custom_options></enable></dnsmasq>
fe80::20d:b9ff:fe2c:f47c = LAN IPv6 Link-Local
opt1 = fe80::20d:b9ff:fe2c:f47e = MGMT IPv6 Link-Local
opt2 = fe80::20b:6bff:fe23:a22d = WLAN IPv6 Link-LocalThe GUI seems somewhat confused. :)
-
Don't believe this is a problem with the GUI (services_dnsmasq.php). Its how IPv6 Link Local addresses are being assigned to VLAN interfaces.
Check Status | Interfaces. I bet you all the IPv6 interfaces that show as being selected that you originally did not select have the same IPv6 Link Local address.
-
Well, there's no VLAN. Why's the IPv6 tunnel assigned the same link-local IP as LAN goes beyond me.
-
IPv6 link-local addresses can be the same on different interfaces. Often the link-local address will be auto-generated based on the MAC address of the interface. For VPNs, I guess it is generating from the MAC address of something "real" underneath, just in order to get a number to use. There is no inherent problem with a system having the same link-local address on multiple interfaces. I suspect that there will be some routers configured with a static link-local address fe80::1 on every LAN interface. Those addresses are not routed, they are only used for packets on the link, so no actual conflict arises.
The dnsmasq code is saving the IP addresses on which it should listen, and specifying them in the –listen-address= parameter to dnsmasq. So that has a fundemental design issue - how can dnsmasq know what to do when the specified IPv6 link-local address exists on multiple interfaces?
There is a --interface parameter. The code could specify interface names instead of IP addresses to listen on. That would need some investigation about:
a) When an interface is specified, does dnsmasq automatically listen on all the IPv4 and IPv6 addresses of that interface?
b) Do users sometimes want it to just listen on the IPv4 or IPv6 address of an interface, and not both? If so, how would it be possible to specify that on the command line?
Then code an appropriate solution... -
a) When an interface is specified, does dnsmasq automatically listen on all the IPv4 and IPv6 addresses of that interface?
I believe so, yes. If an interface is specified then dnsmasq will listen on all IPs bound to that interface regardless of if the IP is specified in the listen-address or not.
b) Do users sometimes want it to just listen on the IPv4 or IPv6 address of an interface, and not both? If so, how would it be possible to specify that on the command line?
Don't think there are any real world applications where you would want to listen on IPv4 and not on IPv6 address of the same interface or vice versa. If there was such a requirement then creating a firewall rule to block one or the other would do the trick.
The issue here is that dnsmasq will be replying to queries on interfaces that it shouldn't be just because those interfaces have the same Link Local address as another interface that it is set to listen on.
One way to get around this would be to use the except-interface parameter. if any of the interfaces in the list are selected then any interface that exists in the system but is not selected in dnsmasq should be included in the except-interface parameter. In config.xml the IPv6 Local Link would have to be saved as the address+if pair.
Here is the except-interface parameter from the manpage:
-I, –except-interface=<interface name=""></interface>
Do not listen on the specified interface. Note that the order of –listen-address --interface and –except-interface options does not matter and that –except-interface options always override the others. -
b) Do users sometimes want it to just listen on the IPv4 or IPv6 address of an interface, and not both? If so, how would it be possible to specify that on the command line?
Don't think there are any real world applications where you would want to listen on IPv4 and not on IPv6 address of the same interface or vice versa. If there was such a requirement then creating a firewall rule to block one or the other would do the trick.
Ditto. Interface is just enough granular.
The –except-interface option sounds good.
-
It sounds like the full functionality can (almost) be retained, in case someone does want to listen on just an IPv4 or IPv6 address on an interface. The current selection list displays the "pfSense names" of the various IP addresses of each interface. Keep asking the user for and storing this information in the config. Generate a –listen-address= parameter list like the code does now, but also add --except-interface= for any interfaces which are not selected at all.
A case for which this does not work is:
a) LAN with IPv4 and IPv6 address - user wants to listen on both
b) OpenVPN with IPv4 and IPv6 address, IPv6 link-local address is same as LAN - user wants to listen only for IPv4. The OpenVPN interface can't be put in the --except-interface list.
The user can block IPv6 DNS on the OpenVPN interface to fix this. But not if they want to run a different DNS service that listens there - I am struggling to think of why someone would want to have DNSmasq listening for IPv4 and some other DNServer listening for the IPv6 on the same interface. But having weird use cases that don't quite work is asking for Murphy to come along and invoke his law.