Tag Archive: Vyatta


Site-to-site VPNs part IV: Vyatta

A free version of the new Vyatta 6.4 with a remarkable straight-forward configuration for VPN if you’re getting familiar with the concepts (which, if you’ve read the first three parts of this series, should be the case now). Just like the previous example, this will use 3DES, MD5, PFS, DH Group 2, and some default lifetimes. Vyatta also supports SHA and AES-128 and AES-256. Strange but true: AES-192 does not seem to be an option. If anything is unclear, Part I may have the answer.

On to the config. To cover it completely, first the interface configuration and a default route, as the VPN relies on routes to decide where to route traffic before encryption (just like the Cisco devices).

set interfaces ethernet eth0 address ip-address/netmask
set protocols static route 0.0.0.0/0 next-hop gateway-address

Phase 1 parameters:

set vpn ipsec ike-group IKE lifetime 86400
set vpn ipsec ike-group IKE proposal 1 encryption 3des
set vpn ipsec ike-group IKE proposal 1 hash md5
set vpn ipsec ike-group IKE proposal 1 dh-group 2

Just like with Cisco, the proposal number is for the order in which the different proposals are examined. Phase 2 is no different from that:

set vpn ipsec esp-group ESP lifetime 3600
set vpn ipsec esp-group ESP mode tunnel
set vpn ipsec esp-group ESP proposal 1 encryption 3des
set vpn ipsec esp-group ESP proposal 1 hash md5
set vpn ipsec esp-group ESP pfs dh-group2

PFS is optional, of course. Now, IPsec has to be activated on a per-interface basis. Again, a simple command for the outgoing interface:

set vpn ipsec ipsec-interfaces interface eth0

Finally, the definition of a VPN peer, it’s parameters, shared key, local and remote subnets, and Phase 1 and Phase 2 proposals:

set vpn ipsec site-to-site peer peer-ip-address
set vpn ipsec site-to-site peer peer-ip-address local-ip local-address
set vpn ipsec site-to-site peer peer-ip-address authentication pre-shared-secret key
set vpn ipsec site-to-site peer peer-ip-address ike-group IKE
set vpn ipsec site-to-site peer peer-ip-address tunnel 1 esp-group ESP
set vpn ipsec site-to-site peer peer-ip-address tunnel 1 local subnet source-network/mask
set vpn ipsec site-to-site peer peer-ip-address tunnel 1 remote subnet destination-network/mask

That’s it. In fact, I’ve found this to be one of the most simply CLI-based VPN configurations I’ve come across so far. The only thing slightly different from most configurations is the requirement of the local-ip parameter. Usually, this is set to the IP address of the outgoing interface, but it can be interesting to set this to a loopback address for which a route is known, so failure of a physical interface does not terminate the VPN connection.

Yes, I’m really fond of using Vyatta these days. Easy command line, not a resource-hungry system, runs in a VM,… Loving it. I do have to point out that my success with it is mostly from online tutorials and a lot of trail-and-error, as I find the official documentation is unclear about a lot of details. But ‘basic’ network stuff, like setting up a VPN server, works fine. Too bad I haven’t quite figured out yet how to use Vyatta (or any other software) as an IPv6 VPN server, so the following tutorial covers IPv4 only.

First thing to check when deploying a client-server VPN is making sure there’s no subnet overlap. Earlier experiments with VPN and a remote connection behind NAT, both in the same subnet, did not work. For this reason I migrated my own network to the 192.168.168.0/24 subnet a month ago.

Second thing is making sure a remote VPN connection is possible. I’m behind a NAT device so port forwarding is needed. I’m setting up a standard Windows PPTP VPN, which uses TCP port 1723 for control, and a GRE tunnel for the actual transport. In this case, forwarding port 1723 usually is sufficient.

Once this is done, the actual configuration of the VPN server on the Vyatta:

reggle@vyatta# set vpn pptp
[edit]
reggle@vyatta# set vpn pptp remote-access authentication mode local
[edit]
reggle@vyatta# set vpn pptp remote-access authentication local-users username reggle password 123
[edit]
reggle@vyatta# set vpn pptp remote-access client-ip-pool start 192.168.168.10
[edit]
reggle@vyatta# set vpn pptp remote-access client-ip-pool stop 192.168.168.29
[edit]
reggle@vyatta# commit

This is the minimum configuration. It configures the VPN server and allows one user to log in. You can add as many users as you like by repeating the command with the username and password, or you can configure a remote RADIUS server:

reggle@vyatta# set vpn pptp remote-access authentication mode radius
[edit]
reggle@vyatta# set vpn pptp remote-access authentication radius-server 192.168.168.5 key 456
[edit]

Also, you can define a DNS server with ‘set vpn pptp remote-access dns-servers server-1 192.168.168.2’. Don’t forget to exclude the addresses used for VPN on your network’s DHCP server to avoid duplicate IPs.

To set up a Windows 7 client computer, go to ‘Network and Sharing Center’, next ‘Set up a new connection’, and enter the details asked (type VPN, IP, username, password). Sometimes, this does not work. If this is the case, go to the VPN properties in the ‘Network Connections’ page, and under the tab ‘Security’ choose PPTP instead of Automatic for the Type of VPN.

One thing to keep in mind now is that, when dialing in from a Windows computer, by default all traffic including internet access, will flow through the VPN. You can change this on the client only: go to the VPN properties, tab ‘Networking’, select ‘Internet Protocol Version 4’ and choose ‘Properties’ again, next ‘Advanced…’, and there should be a check box ‘Use default gateway on remote network’. Unchecking it makes sure the local internet connection is used.

VPN Gateway

That enables proper VPN connectivity, but if you don’t have a business-grade internet connection like me, you’ll most likely have a dynamic IP that changes from time to time. It’s possible to bind that dynamic IP to a DNS record using a public free dynamic DNS service. I used dnsdynamic.org and registered a free subdomain of dnsdynamic.com. You can always log in on the website to change the IP to your current IP, or install an automatic updating tool. This way, you don’t have to write down your IP every time you want remote access to your home network.

IPv6 firewalling on Vyatta.

A while ago, I described how to set up an IPv6 Tunnel, so you could experiment with IPv6 at home. But while I’ve set it up myself a dozen times by now, I rarely had the tunnel active for a long time. Reason: I’m not too happy about a connection without any sort of firewall applied. So in this post, I’m going to describe how to set up a basic IPv6 firewall on an interface in Vyatta. The Cisco-based solution might follow later. To be honest, I’m not even going to try the Windows Server based solution.

Vyatta allows for three directions to apply the rules: in, out and local. Local means traffic destined for the device itself. This is important: I do not have to define any entries in my rules concerning local packets, like routing protocols, LLDP and IPv6 neighbour discovery and router solicitation.

Also, I cannot just block all ICMPv6 packets. IPv6 routers cannot perform fragmentation, unlike IPv4. This means fragmentation has to be done by end nodes. An ICMPv6 type 2 datagram, “Packet too big”, has to be allowed through, otherwise connections will fail if a too big MTU value is used (because the end nodes never find out why it doesn’t work). ICMPv6 type 3 code 1, “Time exceeded” packets tell when fragments are lost during transit.  Finally, types 133-136 are for router solicitation and neighbour discovery, but are handled as local on the Vyatta. If you’re using other platforms, be aware that these types need to be allowed too.

Now for the real ‘firewalling’ part. I’m going to allow echo replies in, so I can ping outside devices. I will not be allowing echo requests in. Yes, that’s making me feel more secure, although it doesn’t have any added value anymore. I’m also letting IPSec through because I’m doing VPN experiments later on. Apart from that, UDP will be allowed, and TCP packets with the ACK bit set. This is similar to the keyword ‘established’ on a Cisco ACL, and will only allow return packets of active sessions. This is not the same as a stateful firewall, but it provides a basic defense against connection attempts. Here is the code:

reggle@vyatta# set firewall ipv6-name WANFW
[edit]
reggle@vyatta# set firewall ipv6-name WANFW description “Firewall to block incoming connections from IPv6 Tunnel”
[edit]
reggle@vyatta# set firewall ipv6-name WANFW default-action drop
[edit]
reggle@vyatta# set firewall ipv6-name WANFW rule 5 protocol icmpv6
[edit]
reggle@vyatta# set firewall ipv6-name WANFW rule 5 icmpv6 type packet-too-big
[edit]
reggle@vyatta# set firewall ipv6-name WANFW rule 5 action accept
[edit]
reggle@vyatta# set firewall ipv6-name WANFW rule 5 description “Must be allowed or MTU discovery will break”
[edit]
reggle@vyatta# set firewall ipv6-name WANFW rule 10 protocol icmpv6
[edit]
reggle@vyatta# set firewall ipv6-name WANFW rule 10 icmpv6 type pong
[edit]
reggle@vyatta# set firewall ipv6-name WANFW rule 10 action accept
[edit]
reggle@vyatta# set firewall ipv6-name WANFW rule 10 description “Allow ping replies”
[edit]
reggle@vyatta# set firewall ipv6-name WANFW rule 15 protocol icmpv6
[edit]
reggle@vyatta# set firewall ipv6-name WANFW rule 15 icmpv6 type time-exceeded
[edit]
reggle@vyatta# set firewall ipv6-name WANFW rule 15 action accept
[edit]
reggle@vyatta# set firewall ipv6-name WANFW rule 15 description “May cause fragmentation issues otherwise”
[edit]
reggle@vyatta# set firewall ipv6-name WANFW rule 20 ipsec match-ipsec
[edit]
reggle@vyatta# set firewall ipv6-name WANFW rule 20 action accept
[edit]
reggle@vyatta# set firewall ipv6-name WANFW rule 20 description “Allow incoming IPSec connections”
[edit]
reggle@vyatta# set firewall ipv6-name WANFW rule 30 protocol tcp
[edit]
reggle@vyatta# set firewall ipv6-name WANFW rule 30 tcp flags ACK
[edit]
reggle@vyatta# set firewall ipv6-name WANFW rule 30 action accept
[edit]
reggle@vyatta# set firewall ipv6-name WANFW rule 30 description “Allow established TCP connections”
[edit]
reggle@vyatta# set firewall ipv6-name WANFW rule 35 protocol udp
[edit]
reggle@vyatta# set firewall ipv6-name WANFW rule 35 action accept
[edit]
reggle@vyatta# set firewall ipv6-name WANFW rule 35 description “Allow stateless UDP”
[edit]

That’s it. After that, do a ‘set interfaces tunnel tun0 firewall in ipv6-name WANFW’, followed by ‘commit’, and it should work. You can test this by trying to ping an IPv6 host (like ipv6.google.com), which should work (echo reply allowed), while a ping to your computer should fail (echo request not allowed). The latter you can test on this website. Don’t forget to save the configuration if it works!

How to set up an IPv6 tunnel.

In an effort to promote IPv6 a bit more, I’m going to discuss three methods to set up an IPv6 tunnel today.

But first: what is an IPv6 tunnel and why would you need it? An IPv6 tunnel is a tunnel that transports IPv6 packets over an IPv4-only network, which is useful if you, like me, have an ISP that doesn’t use IPv6 addresses yet. By setting up the tunnel you can connect your local IPv6 network with the rest of the IPv6 internet. After configuring it, you should be able to surf to the Google IPv6 site.

Before you can begin configuring, you’ll first need an IPv6 provider. I used Hurricane Electric, others prefer Sixxs. Both are free. After registering on the site, you’ll receive a /64 subnet which is yours to use, as well as some details about setting up the connection. Yes, this means you get more IPv6 addresses for free to use in your living room than there are IPv4 addresses in the entire world.

After you have received your prefix we can begin configuration. Note that you’ll also receive a tunnel prefix which is used to configure the tunnel endpoints, as well as an IPv6 DNS server (which will require a DHCPv6 server to run on the network, annoying, I know). To make things consistent over the three configurations I’ll list example values that will be used:
Local IPv6 subnet:  2001:0:0:1234::/64
Tunnel subnet: 2001:0:0:1235::/64, with ::2 on our side and ::1 on the other endpoint side.
IPv6 DNS: 2000::2000
Device IPv4 address: 192.168.0.10
Tunnel endpoint: 50.60.70.80
Gateway to ISP: 192.168.0.1

I’m going to give the configuration for three types of device/operating system: a (virtualized) Vyatta 6.1, a (virtualized) Windows Server 2008 R2, and a Cisco 2691 router in GNS3. It is also possible to configure the tunnel on other devices (even an Apple Airport), but I have not tested those. Also, the tunnel used is an ipv6ip tunnel which uses IP Protocol 41. Since I’ll be passing through a NAT device (the ISP gateway), one of the tunnel endpoints will be a private address, which will be translated by the NAT device. You may need to put the IP in DMZ to forward the tunnel properly, or in my case, to forward the ICMP keepalives properly. And finally: the tunnel endpoint does not necessarily have two ethernet interfaces: the tunnel can be send out of the interface the IPv6 subnet is on.

Vyatta
Using the Vyatta as an IPv6 endpoint works stable and throughput is good. The basic version is free and it barely uses CPU, even when virtualized and under load, which makes for a nice endpoint without the need for a dedicated device. The configuration in the Vyatta is as following:

vyatta@vyatta:~$ configure
vyatta@vyatta# edit interfaces tunnel tun0
vyatta@vyatta# set encapsulation sit
vyatta@vyatta# set local-ip 192.168.0.10
vyatta@vyatta# set remote-ip 50.60.70.80
vyatta@vyatta# set address 2001:0:0:1235::2/64
vyatta@vyatta# set description “IPv6 Tunnel”
vyatta@vyatta# exit
vyatta@vyatta# set protocols static interface-route6 ::/0 next-hop-interface tun0
vyatta@vyatta# edit interfaces ethernet eth0
vyatta@vyatta# set address 192.168.0.10/24
vyatta@vyatta# set address 2001:0:0:1234::1/64
vyatta@vyatta# set ipv6 router-advert prefix 2001:0:0:1234::/64
vyatta@vyatta# exit
vyatta@vyatta# set system gateway-address 192.168.0.1
vyatta@vyatta# commit

Unfortunately, Vyatta currently does not properly support DHCPv6, so you can’t advertise the IPv6 DNS server to hosts in the subnet. In a dual stack environment this doesn’t break anything as the hosts will query the known IPv4 DNS servers, and those respond with IPv6 addresses in their payload if needed.

Cisco IOS
I can’t configure IPv6 on my 2611 routers, apparently they don’t have enough flash memory to store the right IOS version. The 3560 I have does support it with the Advanced IP Services IOS, but I don’t have that one, so I’m really out of luck here.
Update September 18, 2011: the 3560 has IPv6 support with the IP Services IOS as the Advanced IP Services is no longer used for a 3560, but there’s no support for tunneling as it can only be done in software and puts a heavy load on the CPU.

I resort to GNS3, where I set up a router and connect it to the physical network. The configuration of the tunnel is as following:

Router#configure terminal
Router(config)#ipv6 unicast-routing
Router(config)#interface Tunnel0
Router(config-if)#description IPv6 Tunnel
Router(config-if)#no ip address
Router(config-if)#ipv6 address 2001:0:0:1235::2/64
Router(config-if)#tunnel source 192.168.0.10
Router(config-if)#tunnel destination 50.60.70.80
Router(config-if)#tunnel mode ipv6ip
Router(config-if)#exit
Router(config)#ipv6 route ::/0 Tunnel0
Router(config)#interface FastEthernet0/0
Router(config-if)#ipv6 address 2001:0:0:1234::/64 eui-64
Router(config-if)#ipv6 nd prefix 2001:0:0:1234::/64
Router(config-if)#exit
Router(config)#ip default-gateway 192.168.0.1
Router(config)#end
Router#write

Note that, just like with the Vyatta, you have to tell the router which prefix to advertise over the subnet. I was unable to properly configure DHCPv6 so all hosts could get an IPv6 DNS server, despite best efforts. Either a command is not working as expected or I am doing it wrong, so for now, it will work just like the Vyatta, with hosts querying DNS by IPv4.

Windows Server 2008 R2
Despite that this is the only one of the three devices that has a GUI, most configuration on the Windows Server will be done through the command line as well. The netsh command allows you to manipulate the IP stack in detail, as shown in the following configuration:

C:\>netsh interface teredo set state disabled
C:\>netsh interface ipv6 add v6v4tunnel IPv6Tunnel 192.168.0.10 50.60.70.80
C:\>netsh interface ipv6 add address IPv6Tunnel 2001:0:0:1235::2
C:\>netsh interface ipv6 add route ::/0 IPv6Tunnel 2001:0:0:1235::1

The first command disables the build-in Teredo in Windows, which automatically tries to create an IPv6 tunnel in case such traffic is needed. If you care about security, I would recommend this command on all your Windows 7 computers.

Next, creating a gateway for the subnet. If you go to the Network & Sharing Center, choose Change Adapter Settings, you can give the network card facing the subnet a static IPv6 address, in this case 2001:0:0:1234::1/64. The gateway should be ::, DNS server 2000::2000.

Last, we make sure all hosts receive the DNS address. This requires the DHCP role installed on the Windows Server. If present, go to Server Manager, DHCP, and configure an IPv6 scope 2001:0:0:1234::/64. Next, in the scope options, add option 23, and fill in 2000::2000. Windows accepts this and does not give any warning, but I couldn’t get this to work without rebooting after this.

So, these are three methods to get your IPv6 tunnel working. I hope it is all clear, greetings!

Update October 18, 2011: the Cisco IOS and Vyatta configuration had a missing command: you need to configure a default-gateway, otherwise it will not know where to send the tunnel! Commands updated.

VRRP between Cisco and Vyatta.

I already mentioned in an earlier post that I was doing some experiments with Virtual Router Redundancy Protocol on routers from different vendors. For those of you not familiar with VRRP: it’s a protocol that allows multiple routers to share the same IP address, which then can be used as the default gateway for end devices. This gives you some redundancy in case a router goes down. VRRP is the IETF standard for an earlier protocol: HRSP, which is available on Cisco devices only. For more info, Wikipedia is your friend.

I already managed to get VRRP running on both GNS3 and real Cisco routers, but since it’s supposed to be a standard, why not try it in a multivendor environment? My favorite non-Cisco router is Vyatta: it’s a stripped-down Linux with nothing left but the kernel and network-related packages already installed. The command line handles somewhat like a Cisco IOS. Since it can run on almost any x86 hardware, you can virtualize it too, so it’s an easy solution in my lab. The basic version is free.

I followed the guide I found on openmaniak.com and got it running in no time. I used the following configuration: 192.168.0.2 for the Vyatta, 192.168.0.3 for the Cisco router (a 2611 running 12.3 IOS), and 192.168.0.5 as the virtual IP address.

I started and configured my Vyatta first. Here you see it sending VRRP multicasts to 224.0.0.18, to announce to the other router(s) that he’s currently the master and will handle all packets send to 192.168.0.5, the virtual address.

VRRP Vyatta

Next, I booted and configured the Cisco router. Note that both configurations used the ‘preempt’ command, which means that if a ‘better’ router is present in the subnet, it will immediately assume the master role, instead of waiting until the current leader (the Vyatta) goes down. The ‘better’ router here means the one with the higher priority, or in case of a tie, the one with the highest IP address.

Since the Cisco router has a higher IP address, it takes the master role after a few seconds:

After the Cisco router becomes the master, it will handle any packet destined for 192.168.0.5. Should the router fail, for example by me unplugging the ethernet cable, the Vyatta router will take the master role again and the address 192.168.0.5 will stay reachable.

So far so good. But I did come across a small problem in my tests. if you watch both images closely, you’ll notice that the Cisco router is using a source MAC address of 00:00:5e:00:01:01. This is correct, because this is the MAC address that must be used according to the RFC. (The last ’01’ is the VRRP group 1. Had I configured it with VRRP group 5, it would be ’05’.)

The Vyatta router does not use this MAC address but instead uses his own (00:0c:29:fd:d5:23, VMWare virtual NIC). I’ve done some research around the web and could not find anything conclusive, but I’ve heard of Linux versions having trouble using multiple source MAC addresses, so this may be the cause. It does create a problem though, because if a router fails in this configuration, the end devices are left with the wrong ARP information, making the 192.168.0.5 address unreachable after all. It’s possible to solve this issue by sending a Gratuitous ARP packet in case of a failure, but I didn’t notice such a packet in my tests, and it would still make things more complex than they are supposed to be. At this moment I am uncertain if VRRP works well in Vyatta. But that aside, I did learn a lot today.