Skip to content

Instantly share code, notes, and snippets.

@RichardBronosky
Last active March 12, 2019 15:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save RichardBronosky/5775326605043798ad7ddcaf0073bf87 to your computer and use it in GitHub Desktop.
Save RichardBronosky/5775326605043798ad7ddcaf0073bf87 to your computer and use it in GitHub Desktop.
Tools for masking/spoofing/proxying DNS
#dnsmasq config, for a complete example, see:
# http://oss.segetech.com/intra/srv/dnsmasq.conf
#log all dns queries
log-queries
#dont use host's hosts file
no-hosts
addn-hosts=./etc/hosts
#dont use host's nameservers
no-resolv
servers-file=./etc/servers
#!/bin/bash -eux
main(){
(
cd $(script_dir)
cmd="$1"
[[ $cmd == kill ]] && cmd="kill_dnsmasq"
shift
$cmd "$@"
)
}
update_hosts(){
mkdir -p etc
(
host_alias example.com dq1dnt4af4eyy.cloudfront.net
) > etc/hosts
}
run(){
if [[ ${1:-} == "background" ]]; then
cmd=start_dnsmasq
shift
else
cmd=start_dnsmasq_foreground
fi
$cmd "$@"
}
kill_dnsmasq(){
stop_dnsmasq
}
start(){
update_hosts
update_servers
if [[ ${1:-} == "background" ]]; then
run "$@" &&
use_local_dns
else
use_local_dns
trap 'restore_dns' EXIT
run "$@"
fi
}
stop(){
kill
restore_dns
}
reload(){
reload_dnsmasq
}
#############################
## Begin utility functions ##
#############################
ips_to_host(){
# for each line in stdin, format as an etc/hosts entry for arg1
# This simulates multiple A records
local host="$1"
awk -v host="$host" '{printf("%-16s %s\n",$0,host)}'
}
hostname_to_ips(){
local host="$1"
dig +short "$host"
}
host_alias(){
local src="$1"
local dst="$2"
hostname_to_ips $dst | ips_to_host $src
}
start_dnsmasq(){
sudo /usr/local/sbin/dnsmasq --conf-file=dnsmasq.conf --pid-file="$(get_pid_file)" "$@"
}
start_dnsmasq_foreground(){
# In dnsmasq -d is "no-daemon" mode which is backwards from many other apps
start_dnsmasq -d
# This is the production-ready way, but it doesn't respond to SIGINT
# start_dnsmasq --keep-in-foreground
}
signal_dnsmasq(){
local msg=""
if [[ -f $pid_file ]]; then
local pid="$(cat $pid_file)"
if ps -p $(cat $pid_file) >/dev/null; then
sudo /bin/kill "$@" $(cat $pid_file)
else
msg="The dnsmasq pid ($pid) is not running."
fi
else
msg="The dnsmasq pid file ($pid_file) is not present."
fi
if [[ -n $msg ]]; then
echo "$msg"
exit 255;
fi
}
stop_dnsmasq(){
signal_dnsmasq -TERM
}
reload_dnsmasq(){
signal_dnsmasq -HUP
}
get_networksetup_device(){
networksetup -listallnetworkservices | \
grep "$(
route -n get ${1:-8.8.8.8} | \
awk '$1=="interface:"{
iface=$2
}
END{
if(iface=="en0"){iface="Wi-Fi"}
print iface
}'
)"
}
uniq_ips(){
echo $(grep -oE "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b" | sort | uniq)
}
set_dns(){
networksetup -setdnsservers $(get_networksetup_device) "$@"
}
clear_dns(){
set_dns Empty
}
current_resolv(){
grep nameserver /etc/resolv.conf
}
update_servers(){
local servers_file="$(get_servers_file)"
current_resolv | uniq_ips | for ip in $(cat); do echo "server=$ip"; done > $servers_file
}
use_local_dns(){
current_resolv | uniq_ips > etc/resolv.ips.bak
set_dns 127.0.0.1
}
restore_dns(){
clear_dns
current_resolv | uniq_ips > etc/resolv.ips.tmp
if ! diff etc/resolv.ips.{bak,tmp} >/dev/null; then
set_dns $(cat etc/resolv.ips.bak)
fi
}
get_pid_file(){
#bash -c "$(sed -n 's/pid-file/pid_file/; /pid_file/p;' < dnsmasq.conf);"' echo $pid_file'
echo "$PWD/etc/dnsmasq.pid"
}
get_servers_file(){
bash -c "$(sed -n 's/servers-file/servers_file/; /servers_file/p;' < dnsmasq.conf);"' echo $servers_file'
}
script_dir(){
echo "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
}
################
## Always run ##
################
pid_file="$(get_pid_file)"
main "$@"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment