Setting up IPSec over GRE on OpenBSD
This document will explain howto set up an IPSec encrypted GRE tunnel on OpenBSD. In the document, both end points are OpenBSD 4.1 systems, however it should be fairly straight forward to implement on other systems.
To start, I would advise disabling pf on gre0 and enc0 until you have the encrypted tunnel working, this will eliminate pf from any toubleshooting you may have to do, you can do that by adding the following in /etc/pf.conf, make sure you re-load the pf rules.
set skip on enc0 set skip on gre0
Now, on to the tutorial…
Assume two hosts in disparate parts of the world with the following interfaces
Host A public interface 10.0.0.5 private interface 10.0.50.0/24 Host B public interface 192.168.0.5 private interface 192.168.50.0/24
First, enable gre on both hosts A and B by enabling the sysctl net.inet.gre.allow
# sysctl -w net.inet.gre.allow=1
To make it more permanent, add net.inet.gre.allow=1 to /etc/sysctl.conf.
Now, we will construct a gre tunnel to allow their private networks to communicate.
On Host A you would run the following
# ifconfig gre0 create # ifconfig gre0 172.16.0.1 172.16.0.2 netmask 0xffffffff link0 up # ifconfig gre0 tunnel 10.0.0.5 192.168.0.5 # route add -net 192.168.50 -netmask 255.255.255.0 172.16.0.2
Where did 172.16.0.1 and 172.16.0.2 come from, you might ask? These addresses create the point to point gre tunnel, you should pick them from RFC1918 space that is unused in the network(s) you will be connecting.
On to Host B
# ifconfig gre0 create # ifconfig gre0 172.16.0.2 172.16.0.1 netmask 0xffffffff link0 up # ifconfig gre0 tunnel 192.168.0.5 10.0.0.5 # route add -net 10.0.50 -netmask 255.255.255.0 172.16.0.1
Once you’ve proven a host on 10.0.50.x can communicate with a host on 192.168.50.x, you can write the gre to /etc/hostname.gre0.
Host A’s /etc/hostname.gre0 looks like this,
172.16.0.1 172.16.0.2 netmask 0xffffffff link0 up tunnel 10.0.0.5 192.168.0.5 !route add -net 192.168.50 -netmask 255.255.255.0 172.16.0.2
At this point your GRE tunnel should be working, do not move onto implementing IPSec until your GRE tunnel is functioning, it will only complicate troubleshooting
Now, enable ipsec on both hosts A and B by enabling the sysctl net.inet.esp.enable
# sysctl -w net.inet.esp.enable=1
To make it more permanent, add net.inet.esp.enable=1 to /etc/sysctl.conf.
Now, in this document we will be using public key authentication, to implement x509 certificate authentication please refer to this document.
For public key encryption, you will make use of the file /etc/isakmpd/local.pub. If for some reason this file does not exist, check to see if /etc/isakmpd/private/local.key exists, if neither exists you can create them with the following commands.
# /usr/sbin/openssl genrsa -out /etc/isakmpd/private/local.key 1024
# chmod 600 /etc/isakmpd/private/local.key
# openssl rsa -out /etc/isakmpd/local.pub \
-in /etc/isakmpd/private/local.key -pubout
If /etc/isakmpd/private/local.key exists but /etc/isakmpd/local.pub does not, you can generate it with the command
# openssl rsa -out /etc/isakmpd/local.pub \
-in /etc/isakmpd/private/local.key -pubout
Now, you’ll want to copy Host A’s /etc/isakmpd/local.pub to Host B and copy it to /etc/isakmpd/pubkeys/ipv4/10.0.0.5
Note: 10.0.0.5 is a file, not a directory
Likewise, you’ll need to copy Host B’s /etc/isakmpd/local.pub to Host A and copy it to /etc/isakmpd/pubkeys/ipv4/192.168.0.5
Once these have been copied, you need to setup ipsec, Host A’s /etc/ipsec.conf should contain the following
ike esp transport from 10.0.0.5 to 192.168.0.5
And Host B’s /etc/ipsec.conf should contain
ike esp transport from 192.168.0.5 to 10.0.0.5
Note: We chose transport, because ipsec is not tunneling our subnets, the gre tunnel is taking care of that for us, we are simply encrypting between the two endpoints of the tunnel.
Now, we start isakmpd and load the ipsec rules
# isakmpd -K # ipsecctl -f /etc/ipsec.conf
Now, to test if you’ve been successful, try to connect from a host on 10.0.50.x to a host on 192.168.50.x.
Assuming you can still connect, run the following on one of the end points:
# tcpdump -ni enc0 tcpdump: WARNING: enc0: no IPv4 address assigned tcpdump: listening on enc0, link-type ENC 20:07:03.036687 (authentic,confidential): SPI 0x8d8b5b6b: 192.168.50.120 > 10.0.50.10: icmp: echo request (gre encap) 20:07:03.075990 (authentic,confidential): SPI 0xaf01c27a: 10.0.50.10 > 192.168.50.120: icmp: echo reply (gre encap)
Success! As the packet dump is telling us, you’ve a gre encapsulated packet, that is also being encrypted.
Now, to make some of those settings more permanent, add the following to /etc/rc.conf.local
isakmpd_flags="-K" ipsec=YES
Now that you have IPSec over GRE working, I would strongly advise you remove the set skip rules added to your pf.conf and modify your pf rules for more stringent enforcement.
Posted: May 17th, 2007 under Networking, OpenBSD, Papers, Security.
Comments: 5
Comments
Comment from JMA
Time: June 22, 2007, 2:44 pm
Short & sweet tutorial. I would like to extend the topic to the pf.conf involved:
How can you do so that if your IPSEC VPN stops/crashes/isnomore [aka enc0 dead], gre0 traffic is not allowed to pass out (clear) on your external interface?
Thank you,
JMA
Comment from TriBudi
Time: November 9, 2007, 3:36 pm
How to NAT private address Host B in public interface A ?
Thank You,
Comment from Jeff
Time: November 9, 2007, 8:24 pm
@TriBudi
In order to NAT the private addresses on host B to the public interface on host A, first you’ll need to setup a static route. For example on host B you’d.
route add -net 10.0.0 192.168.0.1
This allows the GRE tunnel to continue to function when you remove the default route. Again on host B.
route delete default
route add default 172.16.0.1
Now host A’s gre tunnel interface will be host B’s default route. Finally you would setup the proper nat statements in host A’s pf.conf as you would for any other network.
Comment from Jeff
Time: November 9, 2007, 8:35 pm
@JMA
If the IPSec tunnel crashes, you should still be safe because your ipsec rules are configured to _require_ encryption for outbound traffic to the gre end-point. If the encryption is not present the traffic will not flow.
Comment from Imre
Time: July 13, 2008, 4:18 pm
Hi! I found this article very useful, followed it and managed to get myself working soluton (though actually i used gif interfaces), thanks! But one remark, if routing traffic over ipsec between two private networks, does it really suffice to have ‘ike esp transport from 10.0.0.5 to 192.168.0.5′ and not tunneling? I tested it and saw traffic unencripted until i added something like ‘ike esp tunnel from subnet to sunbet peer 172.16.0.x’.
@Imre
The addresses used in this were for example only. Transport is used for the two endpoints of the gre tunnel. The gre tunnel itself (and the routes that are added) takes care of the networks behind the endpoints. You could do this with IPSec in tunnel mode but I’ve found transport to be more efficient. For example I run ospf on both endpoints and redistribute numerous routes. This could result in a large number of ipsec tunnels. Instead if you simply encrypt the traffic between the gre endpoints you can dynamically add networks behind the endpoints without having the be concerned with updating ipsec. Hope this helps shed some light on your options and why I made the choices I did.

Write a comment