Introduction

Virtual Private LAN Services (VPLS) provide means for building Layer 2 communication on top of existing IP networks. VPLS can be built using various approaches. However, when building a production-grade VPLS solution one needs to have a clear picture of how such aspects as security, mobility, and L2 issues will be solved.

In this short article, we will demonstrate how to build the VPLS using Host Identity Protocol (HIP). Since our goal is not to build a production-grade implementation of HIP-switches, we will only demonstrate proof of a concept solution that uses Mininet – a framework for simulating L2 and L3 networks. It is worth mentioning that the code we have produced can be also deployed (under certain conditions; for example, our HIP implementation does not feature the NAT traversal mechanisms and does not yet provide an L2 loop prevention mechanism) on the real hardware.

While building HIP-switches (the switches that are deployed at the border of a network) we came across several challenges. First, we understood that HIP-switches need to support the IEEE 802.1D protocol (or its modification – this really depends on the version of the protocol supported by the switches) to avoid L2 loops in the network. This problem was initially addressed in the relevant IETF draft. Second, there were certain issues with MTU and the inability of the Linux kernel to deliver IP packets when those are fragmented in user space and injected into the network stack using raw sockets. And finally, it took us some time to repackage the existing implementation of HIP protocol as a library, so that it will be agnostic about low-level networking (such as raw sockets, etc.). Since the implementation of the IEEE 802.1D protocol for our HIP-switches is still ongoing, we will demonstrate the usage of HIP-based VPLS using loop-free L2 topology.

Host Identity Protocol

Host Identity Protocol (HIP) was originally designed to split the dual role of the IP addresses. In other words, HIP is a Layer 3.5 solution that sits between the IP and transport layers. HIP uses hashes of public keys as identifiers. These identifiers, or Host Identity Tags (HITs), are exposed to the transport layer and never change (well, strictly speaking, they might change if the system administrator will decide to rotate the RSA or ECDSA key pairs for instance, but that will happen rarely). On the other hand, HIP uses routable IP addresses (these can be both IPv4 or IPv6) as locators and are used to deliver the HIP and IPSec packets between the end-points. Overall, to identify each other and exchange secret keys HIP relies on a 4-way handshake (also known as HIP base exchange, or HIP BEX for short). During the BEX, peers negotiate a set of cryptographic algorithms to be used, identify each other (since HITs are permanent and are bound to public keys HIP can employ a simple firewall based on HITs to filter out untrusted connections), exchange the keys (HIP can use Diffie-Hellman and Elliptic Curve Diffie-Hellman algorithms), and even protect from Denial of Service attacks using computational puzzles (these are based on cryptographic hash functions and ability of peers to find collisions in hash functions; the complexity of a solution is regulated by a responder in HIP BEX). HIP also supports mobility and uses a separate handshake procedure during which the peer notifies its counterpart about the changes in the locator (read the IP address used for routing purposes).

After the BEX, a set of cryptographic keys is derived and the peers can use these keys to protect the data plane traffic (for example, the keys and negotiated algorithms can be used to set up so-called IPSec security associations).

Deploying the HIP-based VPLS in Mininet

We are going to demonstrate the simulation of the following topology:

HIP-VPLS

 

Since we have tested the implementation using Ubuntu 20.04, below we assume that this version of Linux OS is being used to execute the commands that are presented. First, one needs to check out the source code of the HIP-VPLS:

$ cd ~ $ git clone https://github.com/strangebit-io/hip-vpls.git

Then go the directory that contains the HIP VPLS and execute the following commands:

$ cd hip-vpls $ sudo bash deploy.sh

We are now ready to test the setup. Simply, run the following command in Mininet (the deploy script automatically starts the simulator):

mininet> h1 ping h2

Give it a few seconds before HIP BEX is completed and the full mesh is constructed. The output should be the following:

mininet> h1 ping h2 PING 192.168.1.101 (192.168.1.101) 56(84) bytes of data. From 192.168.1.100 icmp_seq=1 Destination Host Unreachable From 192.168.1.100 icmp_seq=2 Destination Host Unreachable From 192.168.1.100 icmp_seq=3 Destination Host Unreachable From 192.168.1.100 icmp_seq=4 Destination Host Unreachable From 192.168.1.100 icmp_seq=5 Destination Host Unreachable From 192.168.1.100 icmp_seq=6 Destination Host Unreachable From 192.168.1.100 icmp_seq=7 Destination Host Unreachable 64 bytes from 192.168.1.101: icmp_seq=8 ttl=64 time=1085 ms 64 bytes from 192.168.1.101: icmp_seq=9 ttl=64 time=79.7 ms

Would you need to inspect the logs, you can run the following:

$ cd ~/hip-vpls $ tail -f router1/hipls.log

There are four folders, one per HIP switch.

Would you need to start the simulator afterwards without running the deploy script, you can run the following command in the terminal:

$ cd ~/hip-vpls $ sudo python3 hipls-mn.py

Avoiding L2 loops with Spanning Tree Protocol

All good, but the topology we have simulated above does not have L2 loops (at least the author believes so). Consider a slightly modified topology:

HIP-VPLS-LOOP

 

Here when the broadcast frame arrives at HS1 and HS2 from S1, the frame will be forwarded to HS2 (by HS1) and to HS1 (by HS2) correspondingly since we have a full mesh between HIP switches. According to the implementation, the switches will reinject the frames into L2 segment (S1). But in this case the switch will forward the same frame to all ports except the port from which the frame arrived. And so, the frame will be looping endlessly in the network. To avoid such a situation, we are currently working on the implementation of IEEE 802.1D protocol for HIP switches. To our understanding this will put certain links in blocking mode and so L2 loops will be avoided.

To fragment or limit the MTU?

Originally the MTU was set to 1500 bytes on all hosts (h1, h2, h3, h4). This means when an L2 frame arrives at the HIP switch, it needs to be encapsulated into the IPSec, which is in turn encapsulated into an IPv4 packet. Thus, when an L2 frame arrives at the HIP switch it already has the size of 1514 bytes. Now, if it is wrapped with additional headers, the packet size will be somewhere around 1576 bytes (we assume that the block size of the symmetric encryption algorithm is 128 bits and that HMAC based on SHA-256 is being used). Obviously, such a packet cannot be sent through an interface whose MTU is just 1500 bytes, and, thus, we need to fragment the IP packet. Unfortunately, Linux kernel does not allow to fragment IP packets in user space and send them through the raw socket (that is true if the IP_HDRINCL socket option is used). The solution is to lower the interface MTU to, say, 1400 bytes on all the hosts that are part of the VPLS. This is an additional manual configuration step.

Static configuration of the HIP-switches

We are not aware of any solution that allows to dynamically configure HIP switches (although, we think that there are proprietary protocols to achieve the goal). However, we think that there are still lots of use cases that bear in mind only static deployments (meaning that the number and location of HIP switches do not change after the deployment).

To configure a HIP switch, one needs to follow certain steps. First, generate a key pair for every HIP switch:

$ cd ~/hip-vpls/hiplib $ bash tools/genkey.sh gen RSA 2048

Once the key pair is generated for each HIP switch, obtain the HIT for a public key:

$ cd ~/hip-vpls/ $ python3 hiplib/tools/genhit.py

Copy the generated HIP and note the public IP address of each HIP switch (the IP address routable in the Internet).  

Generate the HIP firewall rules for each pair. Since we are talking about full mesh that comprises N*(N-1)/2 virtual links, we need to have N*(N-1) rules and place them in the hiplib/config/rules file. Here is an example of the contents of the rules file:

$ cat hiplib/config/rules 2001:2001:c191:4f98:b087:8715:3083:5b08 2001:2001:c65e:9fc7:dd33:7ed9:da10:f85f allow 2001:2001:c191:4f98:b087:8715:3083:5b08 2001:2001:0b8e:9c09:a674:65cc:b108:93e6 allow 2001:2001:c191:4f98:b087:8715:3083:5b08 2001:2001:9000:97c6:1b55:b70f:da3d:3890 allow 2001:2001:c65e:9fc7:dd33:7ed9:da10:f85f 2001:2001:c191:4f98:b087:8715:3083:5b08 allow 2001:2001:c65e:9fc7:dd33:7ed9:da10:f85f 2001:2001:0b8e:9c09:a674:65cc:b108:93e6 allow 2001:2001:c65e:9fc7:dd33:7ed9:da10:f85f 2001:2001:9000:97c6:1b55:b70f:da3d:3890 allow 2001:2001:0b8e:9c09:a674:65cc:b108:93e6 2001:2001:c191:4f98:b087:8715:3083:5b08 allow 2001:2001:0b8e:9c09:a674:65cc:b108:93e6 2001:2001:c65e:9fc7:dd33:7ed9:da10:f85f allow 2001:2001:0b8e:9c09:a674:65cc:b108:93e6 2001:2001:9000:97c6:1b55:b70f:da3d:3890 allow 2001:2001:9000:97c6:1b55:b70f:da3d:3890 2001:2001:c191:4f98:b087:8715:3083:5b08 allow 2001:2001:9000:97c6:1b55:b70f:da3d:3890 2001:2001:c65e:9fc7:dd33:7ed9:da10:f85f allow 2001:2001:9000:97c6:1b55:b70f:da3d:3890 2001:2001:0b8e:9c09:a674:65cc:b108:93e6 allow

The next step is to fill in the file used by the HIP resolver to map HIT to an IP address (again this needs to be done for every HIP switch)

$ cat hiplib/config/hosts 2001:2001:c191:4f98:b087:8715:3083:5b08 192.168.3.1 2001:2001:c65e:9fc7:dd33:7ed9:da10:f85f 192.168.3.2 2001:2001:0b8e:9c09:a674:65cc:b108:93e6 192.168.3.3 2001:2001:9000:97c6:1b55:b70f:da3d:3890 192.168.3.4

Note that the firewall rules can be removed if public key certificates are to be used in the network setup.

And finally, we need to populate the mesh file hiplib/config/mesh for each HIP switch. This file will contain N-1 records. For a particular HIP switch configuration, it should have first HIT its own HIT, while the second HIT should be the HIT of a HIP switch with which this switch will have a virtual link. Here is an output of the hiplib/config/mesh for one of the HIP switches:

2001:2001:c191:4f98:b087:8715:3083:5b08 2001:2001:c65e:9fc7:dd33:7ed9:da10:f85f 2001:2001:c191:4f98:b087:8715:3083:5b08 2001:2001:0b8e:9c09:a674:65cc:b108:93e6 2001:2001:c191:4f98:b087:8715:3083:5b08 2001:2001:9000:97c6:1b55:b70f:da3d:3890

To conclude, the development is ongoing, but if you would like to test the prototype, then the source code can be found here: https://github.com/strangebit-io/hip-vpls

Would you like to contact the author, you can send a message to dmitriy.kuptsov@strangebit.io