HarryMuscle
Senior Member
For those that might be interested in doing the same thing, here's my final solution:
services-start script file copied to /jffs/scripts and made executable:
service-event-end script file copied to /jffs/scripts and made executable:
ControlD ctrld utitlity copied to /jffs/scripts and made executable:
ctrld.toml file copied to /jffs/configs
The scripts above redirect the 3 custom DNS Filter/Director entries and send them to the ctrld utility for processing. They also make DNS Filter/Director optional by only redirecting DNS traffic directed to the router ... if someone doesn't want that "feature" then simply take out a few lines of code and remove the "-d $lan_ip" portions of the modified iptables rules. It's also pretty trivial to redirect the various other preset DNS Filter/Director entries to ctrld if one wants to do that. Lastly the ctrld utility has additional functionality that can be specified in its config file. The config file shown is just a basic setup using the Google servers as examples.
services-start script file copied to /jffs/scripts and made executable:
Code:
#!/bin/ash
# Wait 2.5 minutes for router and nodes to fully initialize
logger -t "services-start" "Waiting 2.5 minutes for router and node(s) to fully initialize ..."
sleep 150
# Start ctrld DNS server and restart it after 2 seconds if it exits with a non zero exit code
logger -t "services-start" "Starting ctrld DNS server ..."
until /jffs/scripts/ctrld run --config "/jffs/configs/ctrld.toml"
do
logger -t "services-start" "ctrld DNS server stopped unexpectedly"
sleep 2
logger -t "services-start" "Restarting ctrld DNS server ..."
done &
service-event-end script file copied to /jffs/scripts and made executable:
Bash:
#!/bin/ash
# Check if the DNSFilter is being started or restarted
if [[ "$2" == "dnsfilter" ]] && [[ "$1" == "start" || "$1" == "restart" ]]
then
# Update the log
logger -t "service-event-end" "DNSFilter was started or restarted ..."
# Declare and define variables
lan_ip="$(nvram get lan_ipaddr)"
custom_1="$(nvram get dnsfilter_custom1)"
custom_2="$(nvram get dnsfilter_custom2)"
custom_3="$(nvram get dnsfilter_custom3)"
# Loop through the iptables rules in the nat table in the DNSFILTER chain
# Note: some of the rule changes below could be done more efficiently by changing rules in the
# PREROUTING chain, however, it is safer to only change rules in the DNSFILTER chain which
# should get modified by the router only during the dnsfilter start or restart events
rule_number=0
iptables --table nat --list-rules DNSFILTER | while IFS="" read -r rule
do
# Add the table to the rule
rule="-t nat $rule "
# Check (by removing the substring being searched for from the rule and comparing the result
# against the original rule) if this rule is the new chain rule
if [[ "${rule/ -N DNSFILTER}" != "$rule" ]]
then
# Increase the rule number counter
rule_number=$(( rule_number + 1 ))
# Continue to the next rule
continue
fi
# Check (by removing the substring being searched for from the rule and comparing the result
# against the original rule) if this rule points to one of the DNSFilter custom DNS servers
if [[ "${rule/ --to-destination $custom_1}" != "$rule" || \
"${rule/ --to-destination $custom_2}" != "$rule" || \
"${rule/ --to-destination $custom_3}" != "$rule" ]]
then
# Update the log
logger -t "service-event-end" "Found iptables rule pointing to DNSFilter custom DNS server ..."
# Modify the rule destination
if [[ "${rule/ --to-destination $custom_1}" != "$rule" ]]
then
rule="${rule/ --to-destination $custom_1/ --to-destination $lan_ip:54}"
fi
if [[ "${rule/ --to-destination $custom_2}" != "$rule" ]]
then
rule="${rule/ --to-destination $custom_2/ --to-destination $lan_ip:55}"
fi
if [[ "${rule/ --to-destination $custom_3}" != "$rule" ]]
then
rule="${rule/ --to-destination $custom_3/ --to-destination $lan_ip:56}"
fi
# Replace the rule with a modified rule for the TCP protocol and for traffic destined to the
# router's LAN IP address
# Note: specifying a protocol is required in order to use a port number and specifying a
# traffic destination allows a client to use a different DNS server and bypass this rule
logger -t "service-event-end" \
"Replacing rule with modified iptables tcp rule pointing to local ctrld DNS server ..."
iptables ${rule/ -A DNSFILTER/ -R DNSFILTER $rule_number -p tcp -d $lan_ip}
# Increase the rule number counter
rule_number=$(( rule_number + 1 ))
# Insert a modified rule for the UDP protocol and for traffic destined to the router's LAN IP
# address
# Note: specifying a protocol is required in order to use a port number and specifying a
# traffic destination allows a client to use a different DNS server and bypass this rule
logger -t "service-event-end" \
"Replacing rule with modified iptables udp rule pointing to local ctrld DNS server ..."
iptables ${rule/ -A DNSFILTER/ -I DNSFILTER $rule_number -p udp -d $lan_ip}
# Increase the rule number counter
rule_number=$(( rule_number + 1 ))
# Continue to the next rule
continue
fi
# Update the log
logger -t "service-event-end" "Found iptables rule pointing to DNSFilter preset DNS server ..."
# Replace the rule with a modified rule for traffic destined to the router's LAN IP address
# Note: specifying a traffic destination allows a client to use a different DNS server and
# bypass this rule
logger -t "service-event-end" "Replacing rule with modified iptables rule ..."
iptables ${rule/ -A DNSFILTER/ -R DNSFILTER $rule_number -d $lan_ip}
# Increase the rule number counter
rule_number=$(( rule_number + 1 ))
done
fi
exit 0
ControlD ctrld utitlity copied to /jffs/scripts and made executable:
GitHub - Control-D-Inc/ctrld: A highly configurable, multi-protocol DNS forwarding proxy
A highly configurable, multi-protocol DNS forwarding proxy - Control-D-Inc/ctrld
github.com
ctrld.toml file copied to /jffs/configs
Code:
[service]
log_level = "warn"
[listener]
[listener.0]
ip = "192.168.50.1"
port = 54
[listener.1]
ip = "192.168.50.1"
port = 55
[listener.2]
ip = "192.168.50.1"
port = 56
[upstream]
[upstream.0]
bootstrap_ip = "8.8.8.8"
endpoint = "dns.google"
timeout = 0
type = "dot"
[upstream.1]
bootstrap_ip = "8.8.8.8"
endpoint = "dns.google"
timeout = 0
type = "dot"
[upstream.2]
bootstrap_ip = "8.8.8.8"
endpoint = "dns.google"
timeout = 0
type = "dot"
The scripts above redirect the 3 custom DNS Filter/Director entries and send them to the ctrld utility for processing. They also make DNS Filter/Director optional by only redirecting DNS traffic directed to the router ... if someone doesn't want that "feature" then simply take out a few lines of code and remove the "-d $lan_ip" portions of the modified iptables rules. It's also pretty trivial to redirect the various other preset DNS Filter/Director entries to ctrld if one wants to do that. Lastly the ctrld utility has additional functionality that can be specified in its config file. The config file shown is just a basic setup using the Google servers as examples.