Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/bin/sh
- export DEBUG= # uncomment/comment to enable/disable debug mode
- # ---------------------------------------------------------------------------- #
- # ddwrt-add-static-routes-by-domain.sh: v1.0.0, 07 February 2017, by eibgrad
- # dd-wrt ref: http://www.dd-wrt.com/phpBB2/viewtopic.php?p=1014263#1014263
- # install this script in the dd-wrt startup script
- # note: this should work w/ tomato as well, but install in the init script
- #
- # WARNING: This script WILL LIKELY NOT WORK if the OpenVPN client is active
- # and anything is specified in the policy based routing field. All
- # name resolution (using nslookup) will fail. The only way to resolve
- # the problem is to restart DNSMasq from a telnet/ssh session.
- #
- # stopservice dnsmasq; sleep3; startservice dnsmasq
- # ---------------------------------------------------------------------------- #
- SCRIPT_DIR="/tmp"
- SCRIPT="$SCRIPT_DIR/ddwrt-add-static-routes-by-domain.sh"
- mkdir -p $SCRIPT_DIR
- cat << "EOF" > $SCRIPT
- #!/bin/sh
- (
- [ ${DEBUG+x} ] && set -x
- # 0 = flush archived routes (if any) and start over
- # 1 = install archived routes (if any) and continue
- # 2 = install archived routes (if any) and exit
- OP_MODE="0" # 0|1|2
- # class B (/16), class C (/24), or (H)ost (/32)
- NET_CLASS="C" # B|C|H
- # specify your domains here, one per line
- DOMAINS="
- netflix.com
- nflxext.com
- nflximg.net
- nflxvideo.net
- "
- MAX_PASS=0 # max number of passes through domain list (0=infinite)
- MAX_PASS_NOCHANGE=0 # max number of consecutive passes w/ no change (0=infinite)
- SLEEP=0 # time (in secs) between each pass (0=incremental)
- # the following only apply to incremental sleep (SLEEP=0)
- SLEEP_INCR=10 # percentage increase (note: sleep starts @ 60 secs)
- MAX_SLEEP=$((60*60*4)) # max sleep time (in secs) between passes
- ARCHIVE_DIR="/jffs" # must be persistent (e.g., jffs, usb, mounted share)
- # ---------------------- DO NOT CHANGE BELOW THIS LINE ----------------------- #
- WANUP_IP="8.8.8.8" # Google DNS
- WAN_GW="$(nvram get wan_gateway)"
- ARCHIVE_OUT="$(dirname $0)/$(basename $0 .sh).out"
- ARCHIVE_SAV="$ARCHIVE_DIR/${ARCHIVE_OUT##*/}"
- _sleep=60
- # function min( number number )
- min() { echo $(( $1 < $2 ? $1 : $2 )); }
- # function to_upper( string ... )
- to_upper() { echo "$@" | awk '{print toupper($0)}'; }
- # function report_running_time()
- report_running_time() {
- [ "$START_TIME" == "" ] && START_TIME=$(date +%s)
- # calculate running time
- local diff=$(($(date +%s) - $START_TIME))
- # print running time
- printf "info: current running time: %0.2d:%0.2d:%0.2d:%0.2d\n" \
- $((diff/60/60/24)) $((diff/60/60%24)) $((diff/60%60)) $((diff%60))
- }
- # function cleanup_and_exit()
- cleanup_and_exit() {
- # sort the archive by domain name
- sort $ARCHIVE_OUT -k 1,1 -o $ARCHIVE_OUT
- # save archive to persistent storage
- [ -d $ARCHIVE_DIR ] && cp $ARCHIVE_OUT $ARCHIVE_SAV
- # report the number of archived routes
- echo "stat: total archived routes: $(cat $ARCHIVE_SAV | wc -l)"
- echo "info: done"
- exit 0
- }
- # wait for WAN to come up
- while ! ping -qc1 -w3 $WANUP_IP >/dev/null 2>&1; do sleep 10; done; sleep 3
- routes_added_total=0
- # adjust behavior according to operating mode
- if [ "$OP_MODE" == "0" ]; then
- # 0: flush archived routes (if any) and start over
- rm -f $ARCHIVE_SAV $ARCHIVE_OUT
- else
- # 1|2: install archived routes (if any) ...
- if [ -f $ARCHIVE_SAV ]; then
- while read line; do
- ip="$(echo $line | awk '{print $2}')"
- # avoid dups (from previous runs)
- if ! ip route show | grep -Eq "^$ip "; then
- # add the route to the routing table
- if ip route add $ip via $WAN_GW; then
- routes_added_total=$((routes_added_total + 1))
- fi
- fi
- done < $ARCHIVE_SAV
- # force routing system to recognize our changes
- ip route flush cache
- # report the number of routes added from archive
- echo "stat: routes added from archive: $routes_added_total"
- # initialize the new archive
- cp $ARCHIVE_SAV $ARCHIVE_OUT
- else
- rm -f $ARCHIVE_OUT
- fi
- # 1: and continue | 2: and exit
- [ "$OP_MODE" == "1" ] || { echo "info: done"; exit 0; }
- fi
- # initialize this run
- NSLOOKUP="$(dirname $0)/tmp.nslookup.$$"
- NET_CLASS="$(to_upper $NET_CLASS)"
- pass_count=0
- pass_nochange_count=0
- START_TIME=$(date +%s)
- # handle any interrupts by proceeding to cleanup and exit
- trap cleanup_and_exit SIGHUP SIGINT SIGTERM
- # periodically query DNS for our domain names
- while :; do
- # initialize this pass
- pass_count=$((pass_count + 1))
- route_added=false
- routes_added_this_pass=0
- # iterate over the domains and query DNS for their IPs
- for dom in $DOMAINS; do
- # ignore comments
- echo $dom | grep -Eq '^[[:space:]]*#' && continue
- # remove trailing comments and whitespace
- dom="$(echo $dom | grep -Eo '^[^#]*' | awk '{$1=$1}{print}')"
- # ignore failed name resolution on current domain
- if ! nslookup $dom > $NSLOOKUP; then
- echo "warning: domain not found, skipping: $dom"
- continue
- fi
- # resolve ip address(es) for the current domain
- for ip in $(cat $NSLOOKUP | \
- awk '/^Name:/,0 {if (/^Addr[^:]*: [0-9]{1,3}\./) print $3}'); do
- if [ "$NET_CLASS" == "B" ]; then
- # convert to class B network (/16)
- ip="$(echo $ip | cut -d . -f1-2).0.0/16"
- elif [ "$NET_CLASS" == "C" ]; then
- # convert to class C network (/24)
- ip="$(echo $ip | cut -d . -f1-3).0/24"
- fi
- # avoid dups (from previous runs/passes)
- if ! ip route show | grep -Eq "^$ip "; then
- # add the route to the routing table
- if ip route add $ip via $WAN_GW; then
- route_added=true
- routes_added_this_pass=$((routes_added_this_pass + 1))
- # archive the ip/network address
- echo "$dom $ip" >> $ARCHIVE_OUT
- fi
- fi
- done
- done
- # force routing system to recognize our changes
- [[ $route_added == true ]] && ip route flush cache
- # report the number of routes added this pass
- echo "stat: routes added this pass (#$pass_count): $routes_added_this_pass"
- # update the number of consecutive passes w/ no change
- if [ $routes_added_this_pass -eq 0 ]; then
- pass_nochange_count=$((pass_nochange_count + 1))
- else
- pass_nochange_count=0
- fi
- # update the running total of currently active routes
- routes_added_total=$((routes_added_total + $routes_added_this_pass))
- # report the number of currently active routes
- echo "stat: currently active routes: $routes_added_total"
- # report running execution time
- report_running_time
- # quit if we've reached any execution limits
- [ $MAX_PASS_NOCHANGE -gt 0 ] && \
- [ $pass_nochange_count -ge $MAX_PASS_NOCHANGE ] && break
- [ $MAX_PASS -gt 0 ] && [ $pass_count -ge $MAX_PASS ] && break
- # put it bed for a while
- if [ $SLEEP -gt 0 ]; then
- # fixed sleep
- echo "info: sleeping for $SLEEP seconds"
- sleep $SLEEP
- else
- _sleep=$(min $_sleep $MAX_SLEEP)
- echo "info: sleeping for $_sleep seconds"
- sleep $_sleep
- # incremental sleep (slowly increase over time)
- _sleep=$((_sleep + $((_sleep * $SLEEP_INCR / 100))))
- fi
- done
- cleanup_and_exit
- ) 2>&1 | logger -t $(basename $0)[$$]
- EOF
- chmod +x $SCRIPT
- nohup $SCRIPT >/dev/null 2>&1 &
Add Comment
Please, Sign In to add comment