reallyenglish.com is
geographically diverse. The HQ in UK, a few branches in Asia, maybe more in the future. Except for few exceptions, the employees expect universal services, such as source code repository, project management system and wiki. All of them must be protected by strong encryption. IPsec is a standard protocol designed for encrypting packets from one place to another. We extensively use IPsec between our offices.
As a sysadmin, whenever someone says "the Internet is down", I say "no, it isn't". The problem would be caused by networking issue, misconfiguration by someone, maybe his own fault or whatever. The Internet is fine. But, partially, he is right. The Internet is the network of networks. Different network is managed by different entity. As such, links between networks
cut off for various reason every day somewhere on the Internet. You just don't know it is happening. The Internet as a whole works somehow thanks to "dynamic routing".
What dynamic routing does is, in short, "if there are multiple paths to the destination, use the best path" and "tell neighbors about your directly connected networks so that others can understand the whole network map". Without dynamic routing, you have to teach every possible route to every single router. For our intranet, we're using OSPF.
Okay, for robust intranetworking, all you need is multiple meshed IPsec tunnels with OSPF. IPSec is a standard and mature protocol, and so is OSPF. Sounds easy? Not quite. What I don't really like about IPsec is, it wasn't designed with routing in mind. As Security Association is statically configured, you cannot specify multiple path to a destination. Moreover, it doesn't handle multicast packet. OSPF is a routing protocol and uses multicast for its communication.
One more thing to make this problem complicated is proprietary products, Netscreen security devices to be specific, we're still using. If you stick with a specific vendor, you will not have interoperability problem, but you're successfully vendor locked-in. What you can do is what that particular vendor implemented. If they don't, you cannot do anything with it. Anyway, I strongly prefer open standards and open platforms. The choice in this case is
OpenBSD. However, there wasn't documentation about how to implement meshed, dynamically routed IPsec with OpenBSD and ScreenOS.
IPsec doesn't like multicast pakcet. Okay, use GRE, Generic Routing Encapsulation. By encapsulating multicast packet into GRE unicast packet, IPsec happily forward the packet to its peer. When the link to the peer goes down,
ospfd(8) marks the link as unavailable and use alternative path to the destination. Sounds simple, isn't it? Again, not quite. You have to understand all the network layers involved. There would be 6 endpoints, or IP addresses, involved in this setup. IPsec endpoints, GRE tunnel endpoints and a /30 network for OSPF communication.
Let's configure OpenBSD first. Make sure both packet forwarding and GRE are enabled. Also, you better to disable
pf(4) during the testing. You can enable it again after everything works. OpenBSD 4.6 and later enable
pf by default.
# sysctl net.inet.gre.allow=1
# sysctl net.inet.ip.forwarding=1
# pfctl -d
Next, create GRE tunnel.
# ifconfig gre0 create
# ifconfig gre0 tunnel myglobal.ip.addre.ss peerglobal.ip.addre.ss (outer header)
# ifconfig gre0 inet mygre.ip.addre.ss peergre.ip.addre.ss netmask 0xffffffff link0 up (inner header)
The packets between mygre.ip.addre.ss and peergre.ip.addre.ss will be encapsulated by GRE unicast packets with the global IP addresses of the both endpoints as source and destination header. GRE packets are not encrypted, yet.
Then, configure IPsec. OpenBSD's newer
ipsec.conf(5) makes IPsec configuration much easier than ever. The security policy would be "encrypt all packets between the endpoints with their global address". Due to performance limitation of the hardware, we use SHA1 and 3DES.
# vi /etc/ipsec.conf
mypeer = "peerglobal.ip.addre.ss"
me = "myglobal.ip.addre.ss"
mypassword = "password"
ike esp from $me to $mypeer peer $mypeer \
main auth hmac-sha1 enc 3des group modp1024 \
srcid $me/32 dstid $mypeer/32 \
psk $mypassword
Start isakmpd and tell it to read security policy from /etc/ipsec.conf.
# isakmpd -K
# ipsecctl -f /etc/ipsec.conf
NS 5GT's config is not so straight forward, but almost same you did above on OpenBSD.
set interface tunnel.1 zone untrust
set interface tunnel.1 ip mygre.ip.addre.ss/30 (inner header)
set interface tunnel.1 tunnel encap gre
set interface tunnel.1 tunnel local-if untrust dst-ip global.ip.addre.ss (outer GRE header, GRE endpoints)
set interface tunnel.1 tunnel keep-alive (optional, but useful to see GRE packet on the wire)
set ike gateway mypeer address peerglobal.ip.addre.ss main outgoing-interface "untrust" preshare password sec-level compatible
set vpn mypeer gateway jp proposal "nopfs-esp-3des-sha"
set vpn mypeer bind interface tunnel.1
set vpn mypeer proxy-id local-ip global.ip.addre.ss/32 remote-ip peerglobal.ip.adre.ss/32 ANY
The gotcha was, I thought it wasn't possible for OpenBSD and 5GT to talk to each other in a setup like this because OpenBSD's GRE tunnel is point-to-point, 5GT's is a normal /30 subnet. I even didn't give it a try during the initial testing. In fact, it is. Now, you can ping the peer using GRE /30 IP address each other.
# ping peergre.ip.addre.ss
PING peergre.ip.addre.ss (peergre.ip.addre.ss): 56 data bytes
64 bytes from peergre.ip.addre.ss: icmp_seq=0 ttl=64 time=277.665 ms
...
You'll see ICMP packets on the GRE interface.
# tcpdump -tnei gre0 -c 10 icmp
tcpdump: listening on gre0, link-type NULL
mygre.ip.addre.ss > peergre.ip.addre.ss: icmp: echo reply
peergre.ip.addre.ss > mygre.ip.addre.ss: icmp: echo request
...
Make sure the traffic is encrypted. Replace vr0 with your egress interface's name.
# ipsecctl -s all
FLOWS:
flow esp in from myglobal.ip.addre.ss to peerglobal.ip.addre.ss peer peerglobal.ip.addre.ss srcid myglobal.ip.addre.ss/32 dstid peerglobal.ip.addre.ss/32 type use
flow esp out from peerglobal.ip.addre.ss to myglobal.ip.addre.ss peer peerglobal.ip.addre.ss srcid peerglobal.ip.addre.ss/32 dstid myglobal.ip.addre.ss/32 type require
SAD:
esp tunnel from myglobal.ip.addre.ss to peerglobal.ip.addre.ss spi 0x1275cf8c auth hmac-sha1 enc aes
esp tunnel from peerglobal.ip.addre.ss to myglobal.ip.addre.ss spi 0x20eec763 auth hmac-sha1 enc aes
# tcpdump -tni vr0 -c 10
tcpdump: listening on vr0, link-type EN10MB
esp myglobal.ip.addre.ss > peerglobal.ip.addre.ss spi 0x61a862f2 seq 45586 len 372
esp peerglobal.ip.addre.ss > myglobal.ip.addre.ss spi 0x84cd621d seq 45973 len 132
Now that both IPsec and GRE tunnel worked, the last thing you need is enabling OSPF. ospfd.conf is very simple. Replace vr1 with your internal network interface.
# vi /etc/ospfd.conf
password="mypassword"
auth-md 1 $password
auth-type crypt
auth-md-keyid 1
area 0.0.0.0 {
interface gre0 { }
interface vr1 { passive }
}
Start ospfd(8) in debug and verbose mode.
# ospfd -dv
... lots of debug information ...
Do the same thing on 5GT.
set vr trust-vr protocol ospf enable
set interface tunnel.1 protocol ospf area 0.0.0.0
set interface tunnel.1 protocol ospf authentication md5 mypassword key-id 1
set interface tunnel.1 protocol ospf authentication active-md5-key-id 1
set interface tunnel.1 protocol ospf enable
set interface trust protocol ospf area 0.0.0.0
set interface trust protocol ospf passive
set interface trust protocol ospf enable
Now you'll see OSPF neighbor relationship is established.
# ospfctl show neighbor
ID Pri State DeadTime Address Iface Uptime
peergre.ip.addre.ss 1 FULL/P2P 00:00:30 peergre.ip.addre.ss vr1 00:00:23
run "ospfctl show rib" to see RIB and "ospfctl show fib" to see FIB. It should show you the network at the peer's end. If it doesn't work for you, make sure IPsec flow is established, OSPF packet is flowing between both hosts. To make a meshed IPsec, simply repeat this procedure. Tedious? Well, for that matter, you have to replace all the proprietary boxes with OpenBSD and use some kind of automated configuration management system.
Recent Comments