Posts Tagged ‘linux’

Vyatta to DD-WRT: OpenVPN Site to Site

Sunday, July 17th, 2011

I recently changed my site-to-site VPN configuration.  Previously, I had been running my remote OpenVPN endpoints on CentOS with Quagga and OpenVPN installed.  Now that I have a couple Vyatta VM’s routing traffic on the internal network I’ve been wanting to use those as the VPN endpoints.  This simplifies things a big, and lets me remove Quagga from the two CentOS boxes.  I’ve also been wanting to switch my OpenVPN to bridge mode as opposed to routed mode.  OpenVPN doesn’t currently support IPv6.  Using bridge mode allows me to configure the L3 aspects outside of OpenVPN.

Rather than bridged the OpenVPN interface directly to one of the VLAN’s on each end of the tunnel (which would result in broadcasts traversing the WAN, and hosts on both locations being on the same Layer 3 network, not desirable in this case) I’m not actually “bridging” the VPN tunnel interfaces to other interfaces.  Instead, I created a bridge interface on each end of the connection with only the OpenVPN tunnel interface included in it.  I assigned the IP addresses on the bridge interfaces.  Here’s a diagram on how the interfaces are set up:

diagram2

I hadn’t used OpenVPN on Vyatta before, or OpenVPN in bridged mode, so this was a little new for me.  I generated a static key and copied it to all of the devices.  I have the OSPF costs on my internal Vyatta routers set so that one is always preferred.  (I also have that router preferred in VRRP, though this is unrelated to OpenVPN).  The Vyatta VM’s aren’t directly connected to the Internet, so I have OpenVPN listening on an internal address instead.  That internal address is then NAT’ed to a public IP on my edge router.  Ignoring the edge router, here’s a simplified diagram of the tunnels:

diagram1

Here is the configuration I used on the two Vyatta endpoints.  The only OpenVPN feature I’m using that Vyatta doesn’t have a configuration option for is the compression.  Thankfully, Vyatta let’s you manually specify OpenVPN configuration that they don’t support with “openvpn-option”.

intra-rtr-1:

bridge br0 {
        address 172.16.5.1/30
        description "L3 IF for APT site to site VPN"
        hello-time 2
        ip {
            ospf {
                authentication {
                    md5 {
                        key-id 1 {
                            md5-key myospfkey
                        }
                    }
                }
                cost 51
                dead-interval 40
                hello-interval 10
                priority 1
                retransmit-interval 5
                transmit-delay 1
            }
        }
        max-age 20
        priority 0
        stp false
    }
openvpn vtun0 {
        bridge-group {
            bridge br0
        }
        local-host 192.168.1.21
        local-port 1501
        mode site-to-site
        openvpn-option --comp-lzo
        protocol udp
        shared-secret-key-file /root/apt-rtr.secret
    }

intra-rtr-2:

 bridge br0 {
        address 172.16.6.1/30
        description "L3 IF for APT site to site VPN"
        hello-time 2
        ip {
            ospf {
                authentication {
                    md5 {
                        key-id 1 {
                            md5-key myospfkey
                        }
                    }
                }
                cost 49
                dead-interval 40
                hello-interval 10
                priority 1
                retransmit-interval 5
                transmit-delay 1
            }
        }
        max-age 20
        priority 0
        stp false
    }
 openvpn vtun0 {
        bridge-group {
            bridge br0
        }
        local-host 192.168.1.22
        local-port 1502
        mode site-to-site
        openvpn-option --comp-lzo
        protocol udp
        shared-secret-key-file /root/apt-rtr.secret
    }

I’m still using DD-WRT on the endpoint in my apartment. I’ll soon be switching this over to Vyatta as well, but until then I’m relying on some somewhat messy methods of using OpenVPN. I don’t trust the OpenVPN setup that the DD-WRT web GUI uses (for one, they use NAT’ing in the site-to-site connection…which makes no sense whatsoever), so I have a shell script on an attached flash drive that runs on the OpenVPN daemons. The included version of Quagga also does not work on DD-WRT (apparently they compiled it wrong), so I had to find an old statically compiled version. That’s what I’m using for OSPF on the DD-WRT box right now. For this new VPN setup, I just added a few lines to the shell script I already use for OpenVPN.

Anyway, here is the OpenVPN config on my DD-WRT router. It’s fairly simple. I actually have two separate OpenVPN daemons on the DD-WRT system. One that connects to each of my two internal Vyatta routers. The only thing different between them is the port that they connect to.

dev tap0
proto udp
remote my.vpn.endpoint 1501
resolv-retry infinite
nobind
secret intra-rtr.secret
comp-lzo

Here is the script I’m using on the DD-WRT router. It creates the bridge interfaces, and adds the OpenVPN interfaces to the bridge groups. It also assigns the IP’s on the bridge interfaces, starts Quagga, and starts the OpenVPN daemons. When starting the OpenVPN daemons, it also calls DD-WRT’s route down script, to make sure the NAT’ing that DD-WRT tries to do by default is removed from iptables.

openvpn --mktun --dev tap0
openvpn --mktun --dev tap1
brctl addbr br10
brctl addif br10 tap0
brctl addbr br11
brctl addif br11 tap1
ifconfig tap0 up
ifconfig tap1 up

ifconfig br10 172.16.5.2 netmask 255.255.255.252
ifconfig br10 promisc
ifconfig br10 up
ifconfig br11 172.16.6.2 netmask 255.255.255.252
ifconfig br11 promisc
ifconfig br11 up

zebra --daemon --config_file /jffs/opt/zebra.conf
ospfd --daemon --config_file /jffs/opt/ospfd.conf

( sleep 2 ; killall openvpn ; /tmp/openvpncl/route-down.sh ;
    /jffs/opt/ovpn --config /jffs/opt/openvpn-intra-rtr-1.conf --daemon) &
( sleep 3 ; killall openvpn ; /tmp/openvpncl/route-down.sh ;
   /jffs/opt/ovpn --config /jffs/opt/openvpn-intra-rtr-2.conf --daemon) &



Here’s the relevant OSPF configuration in Quagga on my DD-WRT router. Most of it’s fairly straightforward:

interface br10
 description L3 IF for site to site VPN - intra-rtr-1
 ip ospf authentication message-digest
 ip ospf message-digest-key 1 md5 myospfkey
 ip ospf cost 51
!
interface br11
 description L3 IF for site to site VPN - intra-rtr-2
 ip ospf authentication message-digest
 ip ospf message-digest-key 1 md5 myospfkey
 ip ospf cost 49
router ospf
 ospf router-id 192.168.17.1
 network 192.168.5.0/24 area 0.0.0.0
 network 192.168.6.0/24 area 0.0.0.0
 network 192.168.16.0/21 area 0.0.0.0
 area 0.0.0.0 authentication message-digest

I haven’t fully set up IPv6 yet. I’m planning on waiting until I replace my DD-WRT router with Vyatta to set all of that up. The version of Quagga I found that would run on DD-WRT doesn’t support OSPFv3. Vyatta does though.

S3 Backup Scripts: Limiting Upload Rate

Tuesday, November 2nd, 2010

I’ve recently started toying around with Amazon S3 for doing some remote backups.  On Linux, I’ve been using S3 tools to access S3.  I’ve been fairly impressed with S3 and S3 tools so far.

There are a few extra things beyond what the s3cmd program (included in S3 tools) does that would be useful for me.  First, s3cmd will upload / download from S3 as fast as it can.  If you are transferring a large file, this can be problematic as it will saturate your connection for some time.  I was looking for an easy way to shape this traffic without doing traffic shaping at the network level (which could be tricky as S3 uses HTTP for transfers).  I found trickle, a pretty neat little app that does traffic shaping in userland.

Second, the ability to resume a failed transfer would be nice.  Last week I was in the middle of uploading a large file to S3 from the fairly limited speed connection I have here.  With trickle, it was going to take about 24 hours to upload the whole file.  Unfortunately, about 16 hours in to the transfer some bad storms here cut my connection off for a few minutes.  It was rather frustrating to have to start that transfer back at the beginning again.

I researched it a little bit, and it looks like S3 doesn’t really provide a mechanism to resume interrupted transfers.  The best way that I could think of to handle this and minimize the pain of a dropped connection is to split the larger archive into smaller pieces and upload them individually.  By doing this, if you have to start the transfer over, you only have to re-transfer the part of file.  I made my script split it into 20 MB pieces.  At the 20 KB/s rate that trickle lets through, this would only take 17 minutes or so to re-upload.  Splitting a file into smaller pieces reduces the amount of data that would have to be uploaded again if the connection is cut off.

I’ve put the scripts below.  s3-up.sh will first create a tar.gz (compressed archive) of the files specified for upload, then split the tar.gz file into 20 MB chunks and upload it at 20 KB/s.  s3-down.sh will download multiple files from S3, put them back together, and extract them.  It will try to decrypt them using the currently configured password for s3cmd.  You can specify a different decryption password (if you regularly change the encryption password you use for s3cmd for instance).

Feel free to tweak as needed.  You’ll need to have s3cmd installed, along with trickle to use these scripts.  If you are using CentOS, both of those are in the EPEL repositoryI make absolutely no guarantees that these scripts will work for you.  They have not been thoroughly tested.  They are not intended to be relied upon in a production environment.

s3-up.sh:

#!/bin/bash

DATE=`date +%Y-%m-%d`
if [ -z $1 ] || [ -z $2 ]
then
echo Arguments: files to upload, base name of file
else
mkdir /tmp/$$
tar -czf /tmp/$$/$2_$DATE.tar.gz $1
mkdir /tmp/$$/$2_$DATE
split -d -b 20m /tmp/$$/$2_$DATE.tar.gz /tmp/$$/$2_$DATE/$2_$DATE.tar.gz.
trickle -s -u 20 s3cmd put -e --recursive /tmp/$$/$2_$DATE s3://your-s3-bucket-name/backup/
fi

s3-down.sh:

if [ -z $1 ] || [ -z $2 ]
then
echo Arguments: file to get, like s3://your-s3-bucket-name/backup/bak1/*, where to extract, optional password
else
mkdir /tmp/$$
mkdir /tmp/$$/split
cd /tmp/$$/split

if [ -z $3 ]
then
s3cmd get $1
else
s3cmd get $1
for fn in /tmp/$$/split/*
do
mv $fn $fn-enc
gpg -d --verbose --no-use-agent --batch --yes --passphrase $3 -o $fn $fn-enc
rm $fn-enc
done
fi
cat  * > ../temp.tar.gz
cd ..
tar -xvzf temp.tar.gz -C $2
fi

Copyright 2009 Simpliciti Solutions