chriscrowe / docker-pihole-unbound

Run Pi-Hole + Unbound on Docker
1.07k stars 279 forks source link

Pihole/Unbound not discoverable to host machine #10

Open Gh8st opened 4 years ago

Gh8st commented 4 years ago

Hi Chris,

I recently configured my network using your tutorial, and It has been working great thank you!

However, I ran into a problem today. I noticed the containers themselves Pihole and Unbound are not discoverable to the Synology NAS itself. Causing DNS timeout errors. I have added a manual DNS setting within Synology DSM though the network settings and have since resolved my issue.

Any thoughts as to why Synology DSM cannot route traffic within itself through the docker containers?

jmlingeman commented 3 years ago

I'm having the same issue with the container running on a Debian install. @Gh8st did you ever resolve this issue?

chriscrowe commented 3 years ago

@Gh8st Can you be a bit more specific? Is this a DNS issue or a routing issue?

If I'm understanding correctly, Synology is able to route to the containers using IP addresses but not hostnames? Which DNS server is the Synology itself pointing to? You can check this by SSHing to the NAS and executing this:

cat /etc/resolv.conf

You've actually just made me realize that mine wasn't assigned correctly 😂

Gh8st commented 3 years ago

Hi all (@chriscrowe @jmlingeman), I figured out the problem. I found some users referring to Docker's old documentation regarding macvlan's. Stating that:

When using macvlan, you cannot ping or communicate with the default namespace IP address. For example, if you create a container and try to ping the Docker host’s eth0, it will not work. That traffic is explicitly filtered by the kernel modules themselves to offer additional provider isolation and security. A macvlan subinterface can be added to the Docker host, to allow traffic between the Docker host and containers. The IP address needs to be set on this subinterface and removed from the parent address.

A macvlan subinterface can be added to the Docker host, to allow traffic between the Docker host and containers. The IP address needs to be set on this subinterface and removed from the parent address.

I have no idea why this was removed from the documentation if anyone knows why please inform me.

So by design containers on a macvlan interface are not able to access the host machine. To get around this we can enable container to host communication through a bridge interface.

Container to Host Communication

To do this, first, we need to create a new macvlan interface on the host.

sudo ip link add macvlan-to-host link ovs_eth0 type macvlan mode bridge

This will create a new macvlan interface named "macvlan-to-host" you can name yours whatever you like. Then we are going to assign the newly created interface to an unused IP address on your local network.

ip addr add 10.0.1.10/32 dev macvlan-to-host

So in my case, "10.0.1.10" is the unused IP address on my local network that I am assigning to my interface. Adding "/32" allows me to select only that IP address.

Now turn on the interface with:

ip link set macvlan-to-host up

Then we are going to route our pihole and unbound containers to the newly created macvlan interface. You can probably get away with just routing pihole, however, I have unbound as a DNS fallback on my network and if pihole was to fail I would want my host machine to still be able to resolve IP addresses. So if you have unbound as a fallback as-well, you are probably going to want to route it too, in case pihole fails.

ip route add 10.0.1.3/32 dev macvlan-to-host ip route add 10.0.1.4/32 dev macvlan-to-host

In my case "10.0.1.3" is my pihole address and "10.0.1.4" is my unbound address. You are going to want to change these to match those of your container's IP addresses.

That's it! Your host should now be able to access both pihole and unbound to resolve domain name's into an IP addresses.

Note that the interface and routing configuration is not persistent so in the event of a reboot you will lose the added container to host communication.

How to make a Persistent Script

Make a file called containerToHostCommunication.sh (you can name it whatever you like)

Edit the file and add the commands we just entered for container to host communication to it under "#!/bin/sh", so in my case:

#!/bin/sh ip link add macvlan-to-host link ovs_eth0 type macvlan mode bridge ip addr add 10.0.1.10/32 dev macvlan-to-host ip link set macvlan-to-host up ip route add 10.0.1.3/32 dev macvlan-to-host ip route add 10.0.1.4/32 dev macvlan-to-host

Save the file then make it run at boot. If you are using Synology an easy way to do this is by going to Control Panel -> Task Scheduler -> Create -> Triggered Task -> User-defined script Give it a name under task (mine is containerToHostCommunication), make sure: user "root" is selected, event "Boot-up" is selected and you checked the box "Enable" to enable this task. Then on the Task Settings tab under the "User-defined script" enter:

bash /volume2/docker/pihole-unbound/containerToHostCommunication.sh

Modifying it with your directory. Now, this script should run at boot and you are all done!

Freakaa commented 3 years ago

@Gh8st My PiHole one-container version is up running perfect the last weeks since yesterday....

I had this script running for the bridge:

ip link add mac0 link bond0 type macvlan mode bridge ip addr add 192.168.1.128/32 dev mac0 ip link set mac0 up ip route add 192.168.1.128/28 dev mac0

I use an ip-range, since I had more than one container running in the mcvlan.

Since yesterday I run into DNS issues with my iobroker, which is running in the mcvlan with ip 192.168.1.133. The cloud servers are not able to connect to the internet anymore. I can ping to the iobroker ip from the host, which shouldn't work, if the bridge wouldn't work, if I am right!?

When I change the local-DNS in my fritzbox to the default ip=192.168.1.1 iobroker runs without any issues.

Am I missing anything? Wondering, because it worked the last weeks and I was not touching anything.

Regards

HackXIt commented 1 year ago

I used a different setup for macvlan on the host:

cat /etc/network/interfaces.d/host_macvlan
# Configuration for mymacvlan interface
auto host_macvlan
iface host_macvlan inet static
    pre-up ip link add host_macvlan link eth0 type macvlan mode bridge
    post-up ip route del 10.1.0.0/24 dev host_macvlan
    address 10.1.0.241
    netmask 255.255.255.0
    up ip route add 10.1.0.240/32 dev host_macvlan
    post-down ip link delete host_macvlan type macvlan
    pre-down ip route del 10.1.0.0/24 dev host_macvlan

This will bring up a macvlan interface on boot, with default route disabled and static route set for the DNS server (10.1.0.240 in my case)

The reason I'm deleting the default route is due to it interferring with the general default route of the host, which also had an ip address in that range.

So now I can normally set the dns server address also on the host and it will be routed through the macvlan.

You could of course also script this, but I prefer using the interfaces, since they'll be available ASAP