GRE over IPSEC Tunnels
The MikroTik Security Guide and Networking with MikroTik: MTCNA Study Guide by Tyler Hart are available in paperback and Kindle!
IPSEC tunnels are extremely common in situations that require point-to-point networks that are also encrypted. GRE is widely-supported, and when put together they can create a routed, encrypted tunnel architecture. IPSEC doesn't create virtual interfaces that can be addressed and added to the routing table, but GRE picks up where IPSEC leaves off. EoIP can also create tunnels like GRE, but instead they are Layer 2 Ethernet tunnels.
Here's the basic premise: GRE tunnels ride over IPSEC tunnels, and everything else (OSPF, TCP/IP, etc) runs through the GRE tunnels. The protocols using the GRE tunnels aren't aware of the IPSEC tunnels underneath - essentially IPSEC becomes a transparent, encrypted transport mechanism. It's a three layer solution that is surprisingly easy to maintain once it's all in place and documented.
If you haven't yet reviewed how GRE and IPSEC tunnels are configured on Mikrotik routers, take a quick look at Mikrotik GRE Tunnels and Mikrotik Basic IPSEC for a refresher.
Here's the situation we're working with for this article: three offices, all with Mikrotik routers, and each with an Internet connection and static IP address. A server is located at the Boise office that folks in Boston and Seattle need to be able to access.
The topology above is what IPSEC will be implemented on top of, creating tunnels from Boston to Boise, Boise to Seattle, and Seattle to Boston. The encrypted IPSEC tunnels will allow GRE tunnels to be established, turning the topology above into this topology:
Please note: I picked the /30 subnet numbers out of thin air, there's really no reason that I chose to split the 192.168.0.0/24 subnet. Find a subnet in whichever private IP scope you're using and do the same, you don't have to use the addresses I'm using.
First, on each router we'll set up the IPSEC peers and policies - Boston to Boise, Boise to Seattle, and Seattle to Boston.
On Seattle:
/ip ipsec peer add address=23.179.32.2/32 comment=Boston enc-algorithm=aes-128 \ nat-traversal=no secret=mysecret add address=87.16.79.2/32 comment=Boise nat-traversal=no secret=mysecret /ip ipsec policy add comment=Boise dst-address=192.168.0.10/32 sa-dst-address=87.16.79.2 \ sa-src-address=165.95.23.2 src-address=192.168.0.9/32 tunnel=yes add comment=Boston dst-address=192.168.0.2/32 sa-dst-address=23.179.32.2 \ sa-src-address=165.95.23.2 src-address=192.168.0.1/32 tunnel=yes
On Boise:
/ip ipsec peer add address=165.95.23.2/32 comment=Seattle enc-algorithm=aes-128 \ nat-traversal=no secret=mysecret add address=23.179.32.2/32 comment=Boston enc-algorithm=aes-128 \ nat-traversal=no secret=mysecret /ip ipsec policy add comment=Seattle dst-address=192.168.0.9/32 sa-dst-address=165.95.23.2 \ sa-src-address=87.16.79.2 src-address=192.168.0.10/32 tunnel=yes add comment=Boston dst-address=192.168.0.5/32 sa-dst-address=23.179.32.2 \ sa-src-address=87.16.79.2 src-address=192.168.0.6/32 tunnel=yes
On Boston:
/ip ipsec peer add address=165.95.23.2/32 comment=Seattle enc-algorithm=aes-128 \ nat-traversal=no secret=mysecret add address=87.16.79.2/32 comment=Boise enc-algorithm=aes-128 nat-traversal=\ no secret=mysecret /ip ipsec policy add comment=Seattle dst-address=192.168.0.1/32 sa-dst-address=165.95.23.2 \ sa-src-address=23.179.32.2 src-address=192.168.0.2/32 tunnel=yes add comment=Boise dst-address=192.168.0.6/32 sa-dst-address=87.16.79.2 \ sa-src-address=23.179.32.2 src-address=192.168.0.5/32 tunnel=yes
This has laid the foundation for GRE and all the other protocols. The IPSEC peers are set between static WAN IPs, and the policies are set using the /30 point-to-point IP addresses. Once we create the GRE tunnels and assign those same /30 addresses to the GRE interfaces that will create the "interesting" IPSEC traffic and trigger the tunnels to come up and carry GRE traffic. We'll create the GRE tunnels next.
On Seattle:
/interface gre add comment=Boise !keepalive local-address=192.168.0.9 name="Boise GRE" \ remote-address=192.168.0.10 add comment=Boston !keepalive local-address=192.168.0.1 name="Boston GRE" \ remote-address=192.168.0.2
On Boise:
/interface gre add comment=Boston !keepalive local-address=192.168.0.6 name="Boston GRE" \ remote-address=192.168.0.5 add comment=Seattle !keepalive local-address=192.168.0.10 name="Seattle GRE" \ remote-address=192.168.0.9
On Boston:
/interface gre add comment=Boise !keepalive local-address=192.168.0.5 name="Boise GRE" \ remote-address=192.168.0.6 add comment=Seattle !keepalive local-address=192.168.0.2 name="Seattle GRE" \ remote-address=192.168.0.1
At this point the GRE tunnels should be up, but there's no traffic, nothing in the route table - we need to add some IP addresses to the virtual GRE interfaces so the routers have something to work with.
On Seattle:
/ip address add address=192.168.0.1/30 interface="Boston GRE" network=192.168.0.0 add address=192.168.0.9/30 interface="Boise GRE" network=192.168.0.8
On Boise:
/ip address add address=192.168.0.10/30 interface="Seattle GRE" network=192.168.0.8 add address=192.168.0.6/30 interface="Boston GRE" network=192.168.0.4
On Boston:
/ip address add address=192.168.0.2/30 interface="Seattle GRE" network=192.168.0.0 add address=192.168.0.5/30 interface="Boise GRE" network=192.168.0.4
Now we have usable entries in our route tables, and it's time to make the remote LAN subnets reachable. For the sake of simplicity, and because this network is small we'll use static routes. As the network grows, or if we want to introduce some resiliency we can run dynamic routing protocols over these tunnels instead of using static routes. It's also possible to start small, with static routes and as you grow move to dynamic routing. This is what happens with a lot of small businesses who grow and open new offices, acquire a competitor, etc.
We'll tell each router how to get to the remote LAN subnets with static routes pointing across the point-to-point /30 subnets.
On Seattle:
/ip route add comment="Boise LAN" distance=1 dst-address=192.168.30.0/24 gateway=\ 192.168.0.10 add comment="Boston LAN" distance=1 dst-address=192.168.70.0/24 gateway=\ 192.168.0.2
On Boise:
/ip route add comment="Boston LAN" distance=1 dst-address=192.168.70.0/24 gateway=\ 192.168.0.5 add comment="Seattle LAN" distance=1 dst-address=192.168.90.0/24 gateway=\ 192.168.0.9
On Boston:
/ip route add comment="Boise LAN" distance=1 dst-address=192.168.30.0/24 gateway=\ 192.168.0.6 add comment="Seattle LAN" distance=1 dst-address=192.168.90.0/24 gateway=\ 192.168.0.1
At this point we can reach all subnets from across the encrypted point-to-point links. Three remote locations have been combined to create one larger network, spanning all the sites. The route to the Boise LAN that is housing that server is now accessible from Seattle and Boston, so folks in those locations can access the Boise server.
This type of GRE over IPSEC solution can scale quite large, but you will begin to run into problems moving a lot of data over IPSEC tunnels due to the CPU load that encrypting / decrypting packets can create. Depending on how much data you want to move and what encryption algorithms are used it may be necessary to step up to a larger multi-core router. Some smaller Mikrotik routers handle the IPSEC encryption / decryption in software, which is not ideal, and others offload it to dedicated hardware. A lot can be built on top of this type of infrastructure, and it's a good alternative to dedicated MPLS circuits / dark fiber when QoS and latency aren't a big concern.