Vyatta to DD-WRT: OpenVPN Site to Site
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:
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:
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.