goose-ws / bash-scripts

A collection of bash scripts I've hacked together over time
MIT License
9 stars 3 forks source link

captive-dns.env - Support for additional CIDRs to enable DNS on different subnets #14

Open velodromen opened 1 month ago

velodromen commented 1 month ago

Hi,

I just installed your script and I believe it works great (still haven't rebooted the UDM-Pro yet...). The Telegram notification works as well, absolutely awesome!!

That being said, I have 2 dns-servers on different VLAN:s. One is on 10.10.10.0/24 as the one in your example. The other one is located at 192.168.10.0/24. When trying to add the second one in the example below it throws out an error. Removing the second CIDR range fixes the issue. However I'm then reduced to only one DNS server.

# CIDR range for the Primary and Secondary DNS host(s)
allowedDNS="10.10.10.0/24 192.168.10.0/24"

It would be fantastic if you would be able to implement support for additional CIDR:s. Never the less, many thanks for this great script! 👍

goose-ws commented 1 month ago

A cursory google search seems to indicate that it is possible to have multiple addresses within a -s flag, so long as they are comma separated. But to support this, I think it would be better to convert that variable to an array, rather than a space separated string, as that would make it easier to sanity check.

I have some uncommitted changes to this script I should push anyways, but I've got a few other things on my plate this week. Give me a week or so and I'll get to this.

velodromen commented 1 month ago

Wow that was fast! My other option was to set up another rpi at the same subnet... So yeah, I'd be very happy to wait for a fix :)

I can also now confirm that a reboot of my UDM worked well with the script intact and working. Love the notification part to Telegram!

velodromen commented 1 month ago

I just recalled I had to fix one thing in the cron section... There was a missing " at the very end. It could have been me (not a huge fan of the vi editor). Might be worth checking out though since you are already on top of things.

goose-ws commented 1 month ago

Ok, I think I have completed work on this. I don't want to go through the effort of setting up a physical or virtual pihole on another VLAN to test that functionality myself. But the changes I've made haven't broken my setup of same VLAN.

Can you test your setup to see if it works as intended or not? I've only pushed the updates to the 'Testing' branch, not 'Main' yet.

New script in 'Testing' branch: https://raw.githubusercontent.com/goose-ws/bash-scripts/testing/captive-dns.bash

New .env file in 'Testing' branch: https://raw.githubusercontent.com/goose-ws/bash-scripts/testing/captive-dns.env.example

You don't really have to change your whole .env file, the only difference is that allowedDNS is now an array instead of a string. So for your use case, you would change that line to:

allowedDNS=("10.10.10.0/24" "192.168.10.0/24")

Let me know if it works for you, if so, I'll copy it over to the main branch and publish the changes more publicly.

velodromen commented 1 month ago

Thank you! I have installed the new script and changed the line in the .env file to your suggestion. No errors when running the script. Not sure yet whether it utilizes my second dns server but in order to test that I believe I need to also create a redirection of the DNS traffic in my UDM. Thanks once again!

./captive-dns.bash
captive-dns.bash   ::   2024-07-13 20:58:21   ::   [reqrd] A newer version is available
captive-dns.bash   ::   2024-07-13 20:58:21   ::   [info]  Verifying internet connectivity
captive-dns.bash   ::   2024-07-13 20:58:21   ::   [info]  Testing Primary DNS server: 10.10.10.10
captive-dns.bash   ::   2024-07-13 20:58:21   ::   [info]  DNS test attempt 1 succeded: 10.10.10.10
captive-dns.bash   ::   2024-07-13 20:58:21   ::   [info]  Primary DNS check succeeded
goose-ws commented 1 month ago

The simple way for you to test this would be:

Assuming your primary PiHole is 10.10.10.10 Assuming your secondary PiHole is 192.168.10.10

Testing should be done from a host that is in one of the VLAN's described in your vlanInterfaces array (So probably not your UDM-Pro, and probably not either of your PiHole's).

Preform a DNS lookup for a uniquely identifiable address (doesn't even have to be a real address) to the Primary PiHole. If you're using Windows, this can be done via command prompt/powershell and the nslookup command:

nslookup test-1.goose.ws 10.10.10.10

On Linux, it can be done via host command:

host test-1.goose.ws 10.10.10.10

Or the dig command:

dig test-1.goose.ws @10.10.10.10

Whatever tool you're using, preform the lookup, and then verify that the lookup occurred in the logs of your Primary PiHole:

image

Next, do the same thing with another uniquely identifiable (and non-cached) domain name, to your Secondary PiHole:

nslookup test-2.goose.ws 192.168.10.10

And verify that the lookup occured in the logs of your Secondary PiHole:

image

Finally, preform one last lookup with a third uniquely identifable (and non-cached) domain name, to a DNS server not allowed by your allowedDNS. I'll use Google's 8.8.8.8 for the example:

nslookup test-3.goose.ws 8.8.8.8

Note that the output of the command will appear to have come from Google's DNS servers, as it was intercepted/redirected by the UDM-P:

C:\Users\goose>nslookup test-3.goose.ws 8.8.8.8
Server:  dns.google
Address:  8.8.8.8

Non-authoritative answer:
Name:    goose.ws
Addresses:  2600:3c02::f03c:91ff:fe67:5b1f
          45.79.209.169
Aliases:  test-3.goose.ws
C:\Users\goose>

However, if everything is operating correctly, we should see in the logs of the Primary PiHole that the look up actually occurred there, not via Google's DNS servers:

image

velodromen commented 1 month ago

Apologies for the delay on my behalf. I had a power cut yesterday which resulted in Telegram notifications every minute. That was great since I then remembered to check here again. I performed the 3 tests you've suggested however I couldn't get the third to work as intended (the lookup never appeared in my pihole). I then ran your script manually and noticed an error message:

captive-dns.bash   ::   2024-07-22 09:51:07   ::   [reqrd] A newer version is available
captive-dns.bash   ::   2024-07-22 09:51:07   ::   [info]  Verifying internet connectivity
captive-dns.bash   ::   2024-07-22 09:51:07   ::   [info]  DNS test attempt 1 succeded: 10.10.10.10
captive-dns.bash   ::   2024-07-22 09:51:07   ::   [info]  Forcing interface br50 to 10.10.10.10:53
iptables v1.8.7 (legacy): ! not allowed with multiple source or destination IP addresses
Try `iptables -h' or 'iptables --help' for more information.
captive-dns.bash   ::   2024-07-22 09:51:07   ::   [info]  Forcing interface br112 to 10.10.10.10:53
iptables v1.8.7 (legacy): ! not allowed with multiple source or destination IP addresses
Try `iptables -h' or 'iptables --help' for more information.
captive-dns.bash   ::   2024-07-22 09:51:07   ::   [info]  Forcing interface br172 to 10.10.10.10:53
iptables v1.8.7 (legacy): ! not allowed with multiple source or destination IP addresses
Try `iptables -h' or 'iptables --help' for more information.
captive-dns.bash   ::   2024-07-22 09:51:07   ::   [info]  Forcing interface br222 to 10.10.10.10:53
iptables v1.8.7 (legacy): ! not allowed with multiple source or destination IP addresses
Try `iptables -h' or 'iptables --help' for more information.
captive-dns.bash   ::   2024-07-22 09:51:07   ::   [info]  Forcing interface br555 to 10.10.10.10:53
iptables v1.8.7 (legacy): ! not allowed with multiple source or destination IP addresses
Try `iptables -h' or 'iptables --help' for more information.
captive-dns.bash   ::   2024-07-22 09:51:07   ::   [info]  Forcing interface br999 to 10.10.10.10:53
iptables v1.8.7 (legacy): ! not allowed with multiple source or destination IP addresses
Try `iptables -h' or 'iptables --help' for more information.
captive-dns.bash   ::   2024-07-22 09:51:07   ::   [info]  Telegram bot API key authenticated: xxxxxx
captive-dns.bash   ::   2024-07-22 09:51:07   ::   [info]  Telegram channel authenticated: yyyyyy
captive-dns.bash   ::   2024-07-22 09:51:07   ::   [info]  Telegram message sent successfully

The quickfix to get the DNS redirection up and running again was to remove the added secondary DNS-server in the .env-file. It now works like before, though without my secondary DNS-server.

goose-ws commented 1 month ago

No worries for the delay, thanks for further testing.

As the error message suggests, I suppose that iptables doesn't like multiple IP addresses in a source/destination string, beyond a CIDR pattern. Off the cusp, I'm not sure how to solve this, as it seems to be an iptables limitation and not a limitation of the script.

The only thing I can think of would be adding multiple rules per each source/destination, but I don't know if iptables will allow that or not. At the time I wrote this script I had to depend heavily on other sources for the correct use of iptables, I'm handy with bash, but iptables is not so much my forte.

If you (or anyone) has any suggestions I'm open to implementing them. But short of any suggestions or feedback, there's not much more I can think of to do here.