Improved DNSCrypt-Proxy init script

This is an improvement on a previous version I posted.  Despite attempts to use pgrep to check for already running instances of DNSCrypt-Proxy, I was ending up with dozens of processes.  This solves the problem, and also adds function to update the resolver file.

#!/bin/sh

# Replaces /etc/config/dnscrypt-proxy
address='127.0.0.1'
port='5353'
resolver='fvz-anyone'
resolvers_list='/opt/usr/share/dnscrypt-proxy/dnscrypt-resolvers.csv'

PROG=/opt/usr/sbin/dnscrypt-proxy
PIDFILE=/tmp/var/run/dnscrypt-proxy.pid

start () {
  if [ -e "${PIDFILE}" ]; then
    PID=`pgrep dnscrypt-proxy`
    echo "DNSCrypt-Proxy is already running with PID ${PID}".
    logger "$0: DNSCrypt-Proxy already running with PID ${PID}."
    exit
  else
    echo "Starting DNSCrypt-Proxy."
    logger "$0: Starting DNSCrypt-Proxy."
    ${PROG} --local-address=${address}:${port} --resolvers-list=${resolvers_list} --resolver-name=${resolver} --pidfile=${PIDFILE} --ephemeral-keys --daemonize
    sleep 3
    PID=`pgrep dnscrypt-proxy`
    logger "$0: DNSCrypt-Proxy running with PID ${PID}."
  fi
}

stop () {
       echo "Stopping all DNSCrypt-proxy instances..."
       pgrep dnscrypt-proxy | xargs kill
       logger "$0: Stopping DNSCrypt-Proxy."
}

update () {
  # Download new resolvers file
  mv -f ${resolvers_list} ${resolvers_list}.bak
  curl -sk https://raw.githubusercontent.com/jedisct1/dnscrypt-proxy/master/dnscrypt-resolvers.csv -o ${resolvers_list}
}

if [ "$1" = "start" ]; then
   start
elif [ "$1" = "stop" ]; then
   stop
elif [ "$1" = "restart" ]; then
   stop
   sleep 2
   start
elif [ "$1" = "update" ]; then
   update
   stop
   sleep 2
   start
else
   echo "Usage: dnscrypt-proxy start/stop/restart/update"
fi

DNSCrypt on DD-WRT

Modified from OpenWrt Wiki

Install DNSCrypt-proxy

  1. opkg update
  2. opkg install dnscrypt-proxy

Configure DNSCrypt-proxy

  1. The init script that comes with the optware dnscrypt-proxy package relies on rc.common and function.sh to read config files. However, that didn’t seem to work in my hands. So I’m not using /etc/config/dnscrypt-proxy for configuration. Instead, the options are configured in the init.d script and passed as command line arguments to the binary.

Make a simple init.d script

  1. Updated init.d script

Start dnscrypt-proxy, enable autostart

Call the init.d script from one of the dd-wrt startup files. (I call it from /jffs/etc/config/dnscrypt-proxy.prewall)  However, it looks like the .prewall script gets called multiple times so you must make sure your init.d script doesn’t start multiple processes.

Set DNSMasq to run through DNSCrypt-proxy

Configure DNSMasq – all these options can be entered in the dd-wrt GUI. The address line for pool.ntp.org tells DNSMasq to use that IP for that domain, reducing a time delay that might be critical for DNScrypt’s functionality.

bogus-priv
no-resolv
no-poll
expand-hosts
server=127.0.0.1#5353
address=/pool.ntp.org/208.67.222.222

Restart dnsmasq

Selective (split) VPN routing for dd-wrt: Whitelisting servers and clients

All the traffic from my house goes through a VPN, using a dd-wrt flashed router at the client. However, I ran into two issues:

  1. Server Whitelisting: Certain hosts appear to blacklist VPN exit nodes. (e.g., Craigslist) I need to permit clients to connect to these using the ISP gateway, instead of the VPN.
  2. Client Whitelisting: I don’t need traffic from my Roku to go through the VPN. Likewise, my work laptop has a VPN provided by my employer, so it doesn’t need to go through my personal VPN as well.

Attempt 1

The dd-wrt firmware allows one to specify which clients (IP ranges) should use the VPN, using Policy Based Routing in the OpenVPN client setup. So I added an IP range to that window corresponding to the DHCP range used by the router, and assigned my Roku and work laptops static IPs outside that range.

Then I added the servers I wanted to whitelist to routes in the “Advanced Config” options in the OpenVPN tab of the dd-wrt firmware, like this:

route 208.82.237.0 255.255.255.0 net_gateway

However, this didn’t work. No new routes were added to the routing table, and there were no errors in the log.

I concluded that if there are entries in the Policy Based Routing box, they override any route commands in the “Advanced Config” or .ovpn file. (In other words, my client whitelist was preventing the server whitelist from being implemented.)

Attempt 2

On the assumption that Policy-Based Routing negates route rules in the dd-wrt OpenVPN client set up, I tried a different approach.

Instead of using Policy-Based routing to include certain IPs, I used source based routing to send certain traffic through the ISP gateway. You might need to adjust the ISP_GATEWAY line to suit your configuration. The netmasks below will cover from 192.168.1.50–192.168.1.99. My DHCP range starts at 192.168.1.100, so unless otherwise specified clients will use the VPN.  (IPConverterTools was very helpful for working out the netmasks.)

Save this shell script in non-volatile ram (for example, /jffs/openvpn-route-up.sh) and make it executable.

#!/bin/bash
ISP_GATEWAY=$(ip route show default | awk '/default/ {print $3}')
ip rule add from 192.168.1.50/255.255.255.254 table 200
ip rule add from 192.168.1.52/255.255.255.252 table 200
ip rule add from 192.168.1.56/255.255.255.248 table 200
ip rule add from 192.168.1.64/255.255.255.224 table 200
ip rule add from 192.168.1.96/255.255.255.252 table 200
ip route add default via ${ISP_GATEWAY} dev eth0 table 200
ip route flush cache

This script needs to be run after the VPN comes up. OpenVPN lets us script this easily. To your OVPN config, add:

route-up /jffs/openvpn-route-up.sh

Cleanup: update with newer version of this script that clears the table of existing entries if they exist.

This configuration has two advantages:

  1. If you want to have a host bypass the VPN, assign it a static IP in the range 192.168.1.50–192.168.1.99. I did this for my Roku Streaming Stick and work laptop.
  2. If the Policy-Based Routing box of the dd-wrt firmware can be emptied, the route options in the OpenVPN configuration will take effect. Now you can add sites to whitelist, such as Craigslist.

route 208.82.237.0 255.255.255.0 net_gateway