unifi-utilities / unifios-utilities

A collection of enhancements for UnifiOS based devices
GNU General Public License v3.0
3.84k stars 415 forks source link

Can't get hardcoded DNS redirection to work #253

Open PsychoRS opened 2 years ago

PsychoRS commented 2 years ago

Hi,

I can't ge all my DNS traffic (including hardcoded ones, like in some of my smartphones) redirected trough my Pi-Hole. Running UDM Base, firmware 1.10.0, never worked before on 1.9.3

Network: untagged VLAN: 192.168.1.x (this is my main network) IOT network (VLAN 2): 192.168.2.x (this is my IOT network) Pi (VLAN 3): 192.168.3.x (PiHole is set at 192.168.3.2)

PiHole is working mint if I set its address as DNS server on the devices, including DHCP automatic configuration, but I want to redirect all DNS traffic trough my hole too, but its not working.

This is my 10-dns.sh:

#!/bin/sh

## configuration variables:
VLAN=3
IPV4_IP="192.168.3.2"
# This is the IP address of the container. You may want to set it to match
# your own network structure such as 192.168.5.3 or similar.
IPV4_GW="192.168.3.1/24"
# As above, this should match the gateway of the VLAN for the container
# network as above which is usually the .1/24 range of the IPV4_IP

# if you want IPv6 support, generate a ULA, select an IP for the dns server
# and an appropriate gateway address on the same /64 network. Make sure that
# the 20-dns.conflist is updated appropriately. It will need the IP and GW
# added along with a ::/0 route. Also make sure that additional --dns options
# are passed to podman with your IPv6 DNS IPs when deploying the container for
# the first time. You will also need to configure your VLAN to have a static
# IPv6 block.

# IPv6 Also works with Prefix Delegation from your provider. The gateway is the
# IP of br(VLAN) and you can pick any ip address within that subnet that dhcpv6
# isn't serving
IPV6_IP=""
IPV6_GW=""

# set this to the interface(s) on which you want DNS TCP/UDP port 53 traffic
# re-routed through the DNS container. separate interfaces with spaces.
# e.g. "br0" or "br0 br1" etc.
FORCED_INTFC="br0 br2"

# container name; e.g. nextdns, pihole, adguardhome, etc.
CONTAINER=pihole

if ! test -f /opt/cni/bin/macvlan; then
    echo "Error: CNI plugins not found. You can install it with the following command:" >&2
    echo "       curl -fsSLo /mnt/data/on_boot.d/05-install-cni-plugins.sh https://raw.githubusercontent.com/boostchicken/udm-utilities/master/cni-plugins/05-install-cni-plugins.sh && /bin/sh /mnt/data/on_boot.d/05-install-cni-plugins.sh" >&2
    exit 1
fi

CNI_PATH=/mnt/data/podman/cni
for file in "$CNI_PATH"/*.conflist
do
    if [ -f "$file" ]; then
        ln -fs "$file" "/etc/cni/net.d/$(basename "$file")"
    fi
done

# set VLAN bridge promiscuous
ip link set br${VLAN} promisc on

# create macvlan bridge and add IPv4 IP
ip link add br${VLAN}.mac link br${VLAN} type macvlan mode bridge
ip addr add ${IPV4_GW} dev br${VLAN}.mac noprefixroute

# (optional) add IPv6 IP to VLAN bridge macvlan bridge
if [ -n "${IPV6_GW}" ]; then
  ip -6 addr add ${IPV6_GW} dev br${VLAN}.mac noprefixroute
fi

# set macvlan bridge promiscuous and bring it up
ip link set br${VLAN}.mac promisc on
ip link set br${VLAN}.mac up

# add IPv4 route to DNS container
ip route add ${IPV4_IP}/32 dev br${VLAN}.mac

# (optional) add IPv6 route to DNS container
if [ -n "${IPV6_IP}" ]; then
  ip -6 route add ${IPV6_IP}/128 dev br${VLAN}.mac
fi

# Make DNSMasq listen to the container network for split horizon or conditional forwarding
if ! grep -qxF interface=br$VLAN.mac /run/dnsmasq.conf.d/custom.conf; then
    echo interface=br$VLAN.mac >> /run/dnsmasq.conf.d/custom.conf
    kill -9 `cat /run/dnsmasq.pid`
fi

if podman container exists ${CONTAINER}; then
  podman start ${CONTAINER}
else
  logger -s -t podman-dns -p ERROR Container $CONTAINER not found, make sure you set the proper name, you can ignore this error if it is your first time setting it up
fi

# (optional) IPv4 force DNS (TCP/UDP 53) through DNS container
for intfc in ${FORCED_INTFC}; do
  if [ -d "/sys/class/net/${intfc}" ]; then
    for proto in udp tcp; do
      prerouting_rule="PREROUTING -i ${intfc} -p ${proto} ! -s ${IPV4_IP} ! -d ${IPV4_IP} --dport 53 -j DNAT --to ${IPV4_IP}"
      iptables -t nat -C ${prerouting_rule} || iptables -t nat -A ${prerouting_rule}

      # (optional) IPv6 force DNS (TCP/UDP 53) through DNS container
      if [ -n "${IPV6_IP}" ]; then
        prerouting_rule="PREROUTING -i ${intfc} -p ${proto} ! -s ${IPV6_IP} ! -d ${IPV6_IP} --dport 53 -j DNAT --to ${IPV6_IP}"
        ip6tables -t nat -C ${prerouting_rule} || ip6tables -t nat -A ${prerouting_rule}
      fi
    done
  fi
done

br0 and br2 matches my network interfaces that I want to redirect (untagged and VLAN2). This is what I get when executing 10-dns.sh script:

# ./10-dns.sh
RTNETLINK answers: File exists
RTNETLINK answers: File exists
RTNETLINK answers: File exists
2c6f2ba4630c06e4f8d012e553567f9e4841ede261ac2c6df698d645812e5888

Any ideas?

joeblack2k commented 2 years ago

Same as: https://github.com/boostchicken/udm-utilities/issues/245

PsychoRS commented 2 years ago

Updated my UDM-Base to latest Early-Access firmware (1.11.0-19) and now it's working like a charm.

EntropySmoke commented 2 years ago

Can the UDM Utilities DNS script be applied to UDM WAN?

alekslyse commented 1 year ago

Is this script making a upstream of the local dns? I mean dont we want local first, then forced into pihole/adguard etc. I get major issues with unifi itself if it doesnt get access to the local dns, eg no hostname lookup in pihole/adguard and issues loading the unifi app and webui

thebassy commented 10 months ago

So I know this is an older issue but I ran into this when using the guide to install pihole using nspawn-container. Before upgrading OS3 I was using podman. The error I was getting was from:

/data/on_boot.d/10-setup-network.sh
RTNETLINK answers: File exists
RTNETLINK answers: File exists
RTNETLINK answers: File exists

I left everything with the vlan5 (same as the steps in the guide) but after changing the network in the console to use vlan3 instead and then just replacing br5 with br3 in places as well as the IP that the container should use, running the script again and killing/starting the container it fixed it.

I suspect there's likely a cleaner solution but I'm by no means a linux guru. Hope this helps anyone who might stumble across it like I did :)