Created
April 14, 2023 09:04
-
-
Save will/d98519cd7e3d26e4f549994cf0b2e636 to your computer and use it in GitHub Desktop.
Revisions
-
will created this gist
Apr 14, 2023 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,134 @@ #!/bin/sh ### Generate a list of iptables rules to redirect port 53 traffic (tcp+udp) and echo to console. ### This version of the script does NOT apply anything to the iptables on the machine it is run on. ### IPv4 DNS traffic is redirected to $PRIMARYDNS_IPV4 on port 53 ### IPv6 DNS traffic is redirected to $PRIMARYDNS_IPV6 on port 53 # This is the DNS that you want clients to be forced to use on your network # If you have a secondary DNS, add it to the whitelist below and it will still work. PRIMARYDNS_IPV4="192.168.1.12" # Add ALL your whitelisted DNS servers to this variable, separated by a space # These are any name servers that will not be rerouted to the primary DNS. # Recommend you include your router address so that DNS for local machines will still work. # if left blank (""), PRIMARYDNS_IPV4 will still be whitelisted. # e.g. "192.168.1.1 192.168.1.2" etc. DNSWHITELIST_IPV4="192.168.1.12 192.168.1.1" # Leave this blank if you don't use IPv6. PRIMARYDNS_IPV6="" # Add ALL your whitelisted DNS servers to this variable, separated by a space. # In my experience it is best practice to include every ipv6 address that each # DNS server uses. I have observed packets sent to my pi-hole by all 3 ipv6 addresses it obtains # even though only one is listed in DHCP. # e.g. "ffff::1234 ffff:ffff:ffff:ffff::5678" etc. DNSWHITELIST_IPV6="" # Set this to add exception mac addresses that will not be forced to use the primary DNS server # Separate MAC addresses with spaces. EXCEPTION_MACS="" # Set this to the interfaces you want to force through the DNS IP. # Separate interfaces with spaces. # on most routers this is br0. # if you have multiple subnets you might need to add more bridge interfaces to this list. # e.g. "br0" or "br0 br1" etc. FORCED_INTFC="br0" # Enable this if your pihole is on the same subnet as the devices/interfaces # you are forwarding. This will allow the return traffic to work on the same # subnet, but will make the pihole think the requests are coming from the router. # You will lose client information in the pihole dashboard if you enable this. # It is preferable to put the pihole on a different subnet and disable this. ENABLE_MASQUERADE=1 ###IPV4 SECTION### #using ipsets to make whitelists lets us limit wasteful rerouting and reduce potential for DNS loops # create dnsv4 ipset echo "ipset create dnsv4 hash:ip family inet" echo "ipset add dnsv4 ${PRIMARYDNS_IPV4}" if [ -n "${DNSWHITELIST_IPV4}" ]; then for ip in ${DNSWHITELIST_IPV4}; do echo "ipset add dnsv4 ${ip}" done fi #create new DNSCONTROL chain with exceptions echo "iptables -t nat -N DNSCONTROL" #add exceptions that won't get forcibly routed - their DNS requests get routed based on their internal settings. if [ -n "${EXCEPTION_MACS}" ]; then for mac in ${EXCEPTION_MACS}; do dnscontrol_rule="DNSCONTROL -m mac --mac-source ${mac} -j RETURN" echo "iptables -t nat -A ${dnscontrol_rule}" done fi #Everything else is DNAT'd into the pihole. for proto in tcp udp; do dnscontrol_rule="DNSCONTROL -p ${proto} -j DNAT --to ${PRIMARYDNS_IPV4}:53" echo "iptables -t nat -A ${dnscontrol_rule}" done # rules to push DNS traffic into DNSCONTROL chain for intfc in ${FORCED_INTFC}; do for proto in tcp udp; do prerouting_rule="PREROUTING -i ${intfc} -p ${proto} --dport 53 -m set ! --match-set dnsv4 src -m set ! --match-set dnsv4 dst -j DNSCONTROL" echo "iptables -t nat -A ${prerouting_rule}" done done #MASQUERADE rules for ipv4 if [ "$ENABLE_MASQUERADE" = "1" ]; then for proto in udp tcp; do postrouting_rule="POSTROUTING -p ${proto} --dport 53 -m set ! --match-set dnsv4 src -m set --match-set dnsv4 dst -j MASQUERADE" echo "iptables -t nat -A ${postrouting_rule}" done fi ###IPV6 SECTION### # This section is skipped entirely if PRIMARYDNS_IPV6 is not set! if [ -n "${PRIMARYDNS_IPV6}" ]; then # create dnsv6 ipset echo "ipset create dnsv6 hash:ip family inet6" echo "ipset add dnsv6 ${PRIMARYDNS_IPV6}" if [ -n "${DNSWHITELIST_IPV6}" ]; then for ip in ${DNSWHITELIST_IPV6}; do echo "ipset add dnsv6 ${ip}" done fi # create new DNSCONTROL chain with exceptions echo "ip6tables -t nat -N DNSCONTROL" # add exceptions that won't get forcibly routed - their DNS requests get routed based on their internal settings. if [ -n "${EXCEPTION_MACS}" ]; then for mac in ${EXCEPTION_MACS}; do dnscontrol_rule="DNSCONTROL -m mac --mac-source ${mac} -j RETURN" echo "ip6tables -t nat -A ${dnscontrol_rule}" done fi # Everything else is DNAT'd into the pihole. for proto in tcp udp; do dnscontrol_rule="DNSCONTROL -p ${proto} -j DNAT --to [${PRIMARYDNS_IPV6}]:53" echo "ip6tables -t nat -A ${dnscontrol_rule}" done # rules to push DNS traffic into DNSCONTROL chain for intfc in ${FORCED_INTFC}; do if [ -d "/sys/class/net/${intfc}" ]; then for proto in tcp udp; do prerouting_rule="PREROUTING -i ${intfc} -p ${proto} --dport 53 -m set ! --match-set dnsv6 src -m set ! --match-set dnsv6 dst -j DNSCONTROL" echo "ip6tables -t nat -A ${prerouting_rule}" done fi done # MASQUERADE rules for ipv4 if [ "$ENABLE_MASQUERADE" = "1" ]; then for proto in udp tcp; do postrouting_rule="POSTROUTING -p ${proto} --dport 53 -m set ! --match-set dnsv6 src -m set --match-set dnsv6 dst -j MASQUERADE" echo "ip6tables -t nat -A ${postrouting_rule}" done fi fi