Secure OpenVPN Routing between Multiple Networks using DD-WRT

Description

I’ve created a secure routed VPN network between all of my family’s home networks.  Here’s what it looks like, followed by how I did it.

Here’s an overview of the components:

  • Home Network
    • OpenVPN concentrator
    • Netgear WNR3500L (480Mhz CPU, 8MB Flash, 64MB RAM)
    • DD-WRT Mega/Big (Includes OpenVPN), with jffs enabled
    • Local Network: 192.168.1.0/24
    • Dynamic DNS: xxxx.dyndns.org
  • Remote Client Networks 1 and 2
    • OpenVPN client
    • Linksys WRT54G (266Mhz CPU, 4MB Flash, 16MB RAM)
    • DD-WRT VPN (Includes OpenVPN), with jffs enabled
    • Client Network 1
      • Local Network: 192.168.2.0/24
      • Dynamic DNS: yyyy.dyndns.org
    • Client Network 2
      • Local Network: 192.168.3.0/24
      • Dynamic DNS: zzzz.dyndns.org

Generate the Certificates

First, install OpenVPN on your development machine

sudo apt-get install openvpn

Second, run this little script to create a server certificate and several client certificates. These certificates will be directly used in the OpenVPN concentrator and client configuration files.  You will need a single unique client certificate for every OpenVPN client that will connect to the OpenVPN server. When running this script, accept defaults for all of the prompts.

#!/bin/bash

mydir=`pwd`
mydate=`date +%Y%m%d%H%M`
mykeygendir="$mydir/${mydate}_keygen"

echo mykeysdir

cp -r /usr/share/doc/openvpn/examples/easy-rsa/2.0 $mykeygendir
pushd .
cd $mykeygendir
source ./vars
export KEY_COUNTRY="US"
export KEY_PROVINCE="CA"
export KEY_CITY="San Francisco"
export KEY_ORG="yourdomain.com"
export KEY_EMAIL="you@yourdomain.com"
export KEY_CN="yourdomain.com"
export KEY_OU="yourdomain.com"
export KEY_NAME="yourdomain.com"

yes "" | ./clean-all
yes "" | ./build-ca
./build-key client1
./build-key client2
./build-key client3
./build-key client4
./build-key client5
./build-key client6
./build-key client7
./build-key client8
./build-key client9
./build-key-server server
./build-dh

Home Network OpenVPN Concentrator

Add the following to DD-WRT -> Administration -> Commands -> Startup

sleep 15
cat /jffs/openvpn_server.txt | sh

Customize and copy the file contents under the DD-WRT flash path: /jffs/openvpn_server.txt.

mkdir -p /tmp/etc/openvpn/ccd
echo '
#!/bin/sh

#### Set all Variables

lan_network=192.168.1.0
vpn_network=192.168.100.0

#### Create the openvpn.conf file

echo "
# Tunnel options
mode server     # Set OpenVPN major mode
proto udp       # Setup the protocol
port 1194       # TCP/UDP port number
dev tun         # TUN/TAP virtual network device
keepalive 15 60 # Simplify the expression of --ping
daemon          # Become a daemon after all initialization
verb 3          # Set output verbosity to n
comp-lzo        # Use fast LZO compression                                                                                                                                                                                                                                

# vpn tun subnet info
server $vpn_network 255.255.255.0
push \"route $lan_network 255.255.255.0\"
push \"route 192.168.2.0 255.255.255.0\"
push \"route 192.168.3.0 255.255.255.0\"
route 192.168.2.0 255.255.255.0
route 192.168.3.0 255.255.255.0                                                                                                                                                                                                                                           

# OpenVPN server mode options
client-to-client # tells OpenVPN to internally route client-to-client traffic
duplicate-cn     # Allow multiple clients with the same common name                                                                                                                                                                                                       

# TLS Mode Options
tls-server       # Enable TLS and assume server role during TLS handshake
ca ca.crt        # Certificate authority (CA) file
dh dh1024.pem    # File containing Diffie Hellman parameters
cert server.crt  # Signed certificate of local peers
key server.key   # Private key of local peers                                                                                                                                                                                                                             

client-config-dir /tmp/etc/openvpn/ccd/
" > openvpn.conf

echo "
iroute 192.168.2.0 255.255.255.0
" > ccd/client1

echo "
iroute 192.168.3.0 255.255.255.0
" > ccd/client2

#### Create the key files

echo "-----BEGIN CERTIFICATE-----
<PASTE CA.CRT CONTENTS HERE>
-----END CERTIFICATE-----" > ca.crt

echo "-----BEGIN RSA PRIVATE KEY-----
<PASTE SERVER.KEY CONTENTS HERE>
-----END RSA PRIVATE KEY-----" > server.key

echo "-----BEGIN CERTIFICATE-----
<PASTE SERVER.CRT CONTENTS HERE>
-----END CERTIFICATE-----" > server.crt

echo "-----BEGIN DH PARAMETERS-----
<PASTE DH1024.PEM CONTENTS HERE>
-----END DH PARAMETERS-----" > dh1024.pem

#### Set the firewall rules

iptables -I INPUT -p udp --dport 1194 -j ACCEPT
iptables -I INPUT -i tun+ -j ACCEPT
iptables -I FORWARD -i tun+ -j ACCEPT
iptables -I INPUT -s $vpn_network/24 -j ACCEPT
iptables -I FORWARD -s $vpn_network/24 -j ACCEPT
iptables -I FORWARD -s 192.168.1.0/24 -j ACCEPT
iptables -I FORWARD -s 192.168.2.0/24 -j ACCEPT
iptables -I FORWARD -s 192.168.3.0/24 -j ACCEPT

#### Start the program

# The command [openvpn --config openvpn.conf --daemon] does not work so use the following
sleep 2
ln -s /usr/sbin/openvpn /tmp/etc/openvpn/openvpn
/tmp/etc/openvpn/openvpn --config /tmp/etc/openvpn/openvpn.conf
' > /tmp/etc/openvpn/openvpn.sh
chmod a+x /tmp/etc/openvpn/openvpn.sh
cd /tmp/etc/openvpn
./openvpn.sh

Remote Network OpenVPN Clients

Add the following to DD-WRT -> Administration -> Commands -> Startup

mkdir -p /tmp/etc/openvpn
echo '
#!/bin/sh

#### Set all Variables

lan_network=192.168.2.0
vpn_network=192.168.100.0

#### Create the openvpn.conf file

echo "
# Tunnel options
proto udp       # Setup the protocol
port 1194       # TCP/UDP port number
dev tun         # TUN/TAP virtual network device
keepalive 15 60 # Simplify the expression of --ping
daemon          # Become a daemon after all initialization
verb 3          # Set output verbosity to n
comp-lzo        # Use fast LZO compression                                                                                                                                                                                                                                

# vpn tun subnet info
pull            # Fetch the routes from the server                                                                                                                                                                                                                        

# TLS Mode Options
tls-client       # Enable TLS and assume client role during TLS handshake
ca ca.crt        # Certificate authority (CA) file
cert client.crt  # Signed certificate of local peers
key client.key   # Private key of local peers                                                                                                                                                                                                                             

remote aaaa.dyndns.org
resolv-retry infinite
nobind                                                                                                                                                                                                                                                                    

" > openvpn.conf

#### Create the key files

echo "-----BEGIN CERTIFICATE-----
<PASTE CA.CRT CONTENTS HERE>
-----END CERTIFICATE-----" > ca.crt

echo "-----BEGIN RSA PRIVATE KEY-----
<PASTE CLIENT.KEY CONTENTS HERE>
-----END RSA PRIVATE KEY-----" > client.key

echo "-----BEGIN CERTIFICATE-----
<PASTE CLIENT.CRT CONTENTS HERE>
-----END CERTIFICATE-----" > client.crt

#### Set the firewall rules

iptables -I INPUT -p udp --dport 1194 -j ACCEPT
iptables -I INPUT -i tun+ -j ACCEPT
iptables -I FORWARD -i tun+ -j ACCEPT
iptables -I INPUT -s /24 -j ACCEPT
iptables -I FORWARD -s /24 -j ACCEPT
iptables -I FORWARD -s 192.168.1.0/24 -j ACCEPT
iptables -I FORWARD -s 192.168.2.0/24 -j ACCEPT
iptables -I FORWARD -s 192.168.3.0/24 -j ACCEPT

#### Start the program

# The command [openvpn --config openvpn.conf --daemon] does not work so use the following
sleep 2
ln -s /usr/sbin/openvpn /tmp/etc/openvpn/openvpn
/tmp/etc/openvpn/openvpn --config /tmp/etc/openvpn/openvpn.conf
' > /tmp/etc/openvpn/openvpn.sh
chmod a+x /tmp/etc/openvpn/openvpn.sh
cd /tmp/etc/openvpn
./openvpn.sh
Posted in Technical | Leave a comment

My Home Network

I spend too much time on my home network infrastructure, but it is too much fun…  Components to brag about include:

  • Embedded linux on a wireless access point
  • Vpn concentrator and clients using certificate authentication to route between family member networks
  • Virtual server and multiple virtual guest machines
  • Fully automated backup process for all data
  • Fileserver for nfs and samba filesharing
  • Web servers which run wordpress, mediawiki
  • Reverse proxies

I used the Dia utility to draw a great-looking diagram of my home network. Dia seems to be a great Visio replacement, and it certainly is better than the old Xfig program I used to use years ago.

Posted in Technical | Comments Off

Cisco VPN Client on DD-WRT Wireless Router

If you connect to a network served by a Cisco VPN concentrator, then you can run the Cisco VPN client on a router, instead of your computer. Running Cisco VPN on a router creates several advantages:

  • Masquerades (NAT) the local network so that all computers behind the router can access the VPN network
  • Re-connects on dropped connections.
  • Splits and sends only traffic destined to the foreign network over the VPN connection.

Requirements:

  • Router that supports DD-WRT: Netgear WNR3500L
  • DD-WRT Firmware containing vpnc: dd-wrt.v24-14311_NEWD-2_K2.6_openvpn.bin
  • Journaling Flash Filesystem (JFFS) enabled on the router

Add the following to the startup script under Administration -> Commands -> Startup

sleep 15
cat /jffs/vpnc.txt | sh

Create the file /jffs/vpnc.txt on the router

mkdir -p /tmp/etc/vpnc
echo '
#!/bin/sh 

#### Set all Variables

vpn_concentrator="vpn.company.com"  # ip or hostname of ipsec vpn concentrator
vpn_keepalive_host="10.1.1.1" # the ip or hostname of a computer, reachable if vpn is established
vpn_groupname="group_name"         # group name hereconnection
vpn_grouppasswd="group_password" # group password here
vpn_username="user_name"             # your username here
vpn_password="user_password"     # your password here

#### Create a local script to split routes

echo "
CISCO_SPLIT_INC=1
CISCO_SPLIT_INC_0_ADDR=10.0.0.0  # IP range to go into first tunnel
CISCO_SPLIT_INC_0_MASK=255.0.0.0 # Subnet Mask for first tunnel
CISCO_SPLIT_INC_0_MASKLEN=8      # Mask length
CISCO_SPLIT_INC_0_PROTOCOL=0
CISCO_SPLIT_INC_0_SPORT=0
CISCO_SPLIT_INC_0_DPORT=0
. /etc/vpnc/vpnc-script
" > /tmp/etc/vpnc/vpnc-script-local
chmod a+x /tmp/etc/vpnc/vpnc-script-local

#### Create the vpnc.conf file

echo "
IPSec gateway $vpn_concentrator
IPSec ID $vpn_groupname
IPSec secret $vpn_grouppasswd
Xauth username $vpn_username
Xauth password $vpn_password
Script /tmp/etc/vpnc/vpnc-script-local  # points to the local script
" > /tmp/etc/vpnc/vpnc.conf

#### Create the vpnc.sh file

pingtest () {
 ping -q -c1 $1 >> /dev/null
 if [ "$?" == "0" ]; then
       echo 1 #reachable 

 else
       echo 0 #not reachable
 fi
}

while [ true ]; do
  # wait until the concentrator is reachable
  while [ "`pingtest $vpn_concentrator`" != "1" ]; do
    echo "Vpnc concentrator $vpn_concentrator is not reachable, sleeping 10"
    sleep 10;
  done

  if [ "`pingtest $vpn_keepalive_host`" == "1" ]; then
    echo "vpn connection active: $vpn_keepalive_host is alive"
    sleep 300;
  else
    echo "vpn connection down: $vpn_keepalive_host is unreachable"
    vpnc-disconnect
    echo "Attempting to start vpnc"
    vpnc /tmp/etc/vpnc/vpnc.conf --dpd-idle 0
    tundev="`ifconfig |grep tun |cut -b 1-4|tail -n 1`"
    iptables -A FORWARD -o $tundev -j ACCEPT
    iptables -A FORWARD -i $tundev -j ACCEPT
    iptables -t nat -A POSTROUTING -o $tundev -j MASQUERADE
  fi
  sleep 1;
done

return 0;
' > /tmp/etc/vpnc/vpnc.sh
chmod a+x /tmp/etc/vpnc/vpnc.sh
/tmp/etc/vpnc/vpnc.sh
Posted in Technical | Leave a comment

Tunneling pop3/smtp to gmail SSL pop3s/smtps using xinetd on Linux

Hi,

My Brother MFC-9840cdw multi-functional printer/scanner/coper/fax can scan to email. However gmail requires SSL, which the printer is not able to support. Using xinetd and openssl, my Linux machine is able to proxy local pop3 requests to gmail’s SSL pop3s service, and local smtp requests to gmail’s SSL smtps service.

Here are the basics on what you need. These ideas are not original.

Tunneling smtp to smtps

# xinetd: tunnel local smtp to gmail smtps

service smtp
{
  disable = no
  socket_type = stream
  wait = no
  user = root
  server = /etc/xinetd.d/extra/gmailsmtpstunnel.sh
  only_from = 0.0.0.0
}

#####################################################################
# Instructions
#
#
# 1) Copy this entire file to /etc/xinetd.d/gmailsmtpstunnel
#
# 2) Create the following script in:
#      /etc/xinetd.d/extra/gmailsmtpstunnel.sh
# --------------------------------------
# #!/bin/sh
# /usr/bin/openssl s_client -quiet -connect smtp.gmail.com:465 2>/dev/null
# --------------------------------------
# 3) Change the permissions
#     chmod 755 /etc/xinet.d/extra/gmailsmtpstunnel.sh
# 4) Restart xinetd
#      /etc/init.d/xinetd restart
# 5) Test the tunnel
#      telnet localhost 25
# 6) Point your mail smtp server to here

Tunneling pop3 to pop3s

# xinetd: tunnel local pop3 to gmail pop3s

service pop3
{
  disable = no
  socket_type = stream
  wait = no
  user = root
  server = /etc/xinetd.d/extra/gmailpop3stunnel.sh
  only_from = 0.0.0.0
}

#####################################################################
# Instructions
#
#
# 1) Copy this entire file to /etc/xinetd.d/gmailpop3stunnel
#
# 2) Create the following script in:
#      /etc/xinetd.d/extra/gmailpop3stunnel.sh
# --------------------------------------
# #!/bin/sh
# /usr/bin/openssl s_client -quiet -connect pop.gmail.com:995 2>/dev/null
# --------------------------------------
# 3) Change the permissions
#     chmod 755 /etc/xinet.d/extra/gmailpop3stunnel.sh
# 4) Restart xinetd
#      /etc/init.d/xinetd restart
# 5) Test the tunnel
#      telnet localhost 110
# 6) Point your mail smtp server to here
Posted in Technical | Leave a comment