📜 ⬆️ ⬇️

OpenVPN OSPF between two servers, multiple tunnels

OpenVPN is well documented and there are articles on installation in Habré, for example:
this one

But so that at once several tunnels, between two servers and automatic fault tolerance are not found. In my case, the servers on which OpenVPN and OSPF will be located are both behind NAT. This somewhat complicates the decision, but mainly due to the need to control traffic leaving the interfaces of the border router.

Given:


Centos 7 Two Border Routers:

r01:
ens0 1.1.1.1 - provider 1
ens1 2.2.2.2 - provider 2
ens2 10.0.0.1 - virtual network between the gateway and the OpenVPN server.
r02:
ens0 3.3.3.3 - provider 3
ens1 4.4.4.4 - provider 4
ens2 10.1.1.1 - virtual network between the gateway and the OpenVPN server.

Two Centos 7 OpenVPN / OSPF Servers:
')
host01:
ens0 10.0.0.2 - SNAT via network provider 1.
ens0 10.0.0.3 - SNAT via network provider 2.
ens1 192.168.0.0/23 - local area network.
host02:
ens0 10.1.1.2 - SNAT via network provider 3.
ens0 10.1.1.3 - SNAT via network provider 4.
ens1 192.168.4.0/23 - local area network.

All providers in this scheme are different, have different speed, cost.

Task:


Create 4 tunnels between host01 and host02 so that they are always active and if any of the providers fail, the route should switch to a slower or more expensive channel. Even if both providers fail (one on each server), the channel should also function. At the same time, if the preferred channel works, the server will have to switch to it.

In this article I will not describe in detail the process of generating keys, installing OpenVPN, Quagga. Let me just say that it is enough to generate keys for the server and client once, since you can use DH and all other keys and certificates for all instances at the same time. But, of course, if you are very concerned about security, you can generate two certificates for each tunnel. In my case, there was one certificate for server services and one for client services.

Installation:


CentOS Linux release 7.4.1708 (Core) / 3.10.0-693.5.2.el7.x86_64.
yum install openvpn easy-rsa quagga
software versions that were used:

openvpn 2.4.4 x86_64 easy-rsa 2.2.2-1.el7 quagga.x86_64 0.99.22.4-4.el7 

Setup:


The following ports are selected for the tunnels:

udp 1150 - 1.1.1.1-3.3.3.3
udp 1151 - 2.2.2.2-4.4.4.4
udp 1152 - 1.1.1.1-4.4.4.4
udp 1153 - 2.2.2.2-3.3.3.3

It should be noted that OpenVPN requires that the port from which the server and client send packets is the same as the packet receiving port, when using NAT, the outgoing packet port may differ and the tunnel will not rise with this error:
TCP / UDP: Incoming packet rejected from [AF_INET] 1.1.1.1: 1194 [2], expected peer address: [AF_INET] 1.1.1.1: 2364 (allow this incoming source address to be added by --float )

To ensure that the port is always correct, you must configure the border router and OpenVPN server:

host01:

 -A POSTROUTING -p udp --dport 1150 -o ens0 -j SNAT --to-source 10.0.0.2:1050 -A POSTROUTING -p udp --dport 1151 -o ens0 -j SNAT --to-source 10.0.0.3:1051 

In turn, on the border router it will be like this (r01):

 -A POSTROUTING -p udp -s 10.0.0.2 --dport 1150 -o ens0 -j SNAT --to-source 1.1.1.1:1150 -A POSTROUTING -p udp -s 10.0.0.3 --dport 1151 -o ens1 -j SNAT --to-source 2.2.2.2:1151 

Next, we configure the tunnels, I will give the configuration of one client / server pair, the rest are also configured, the port, addresses and the tun number of the interface just change.

Server configuration:

 dev tun1 proto udp topology subnet remote 1.1.1.1 ifconfig 10.10.11.1 255.255.255.252 cipher AES-256-CBC persist-tun persist-key ping 10 ping-restart 30 tls-server daemon dh /etc/openvpn/dh2048.pem ca /etc/openvpn/ca.crt cert /etc/openvpn/srv.crt key /etc/openvpn/srv.key reneg-sec 300 port 1150 verb 3 


Client configuration:

 dev tun1 proto udp topology subnet remote 3.3.3.3 ifconfig 10.10.11.2 255.255.255.252 cipher AES-256-CBC ping 10 ping-restart 30 tls-client daemon ca /etc/openvpn/ca.crt cert /etc/openvpn/cli.crt key /etc/openvpn/cli.key reneg-sec 300 port 1150 verb 3 

An important parameter in the configuration of the topology subnet tunnel, it allows you to address the tunnel so that it looks like a subnet and not a point-to-point interface. The parameter is not the default parameter and is recommended for modern servers. Without it, there is no possibility to exchange broadcast packets inside the tunnel, thus it will not be possible to configure OSPF.

When raising the tunnel ifconfig on the server and the client will look like this:

 tun1: flags=4305<UP,POINTOPOINT,RUNNING,NOARP,MULTICAST> mtu 1500 inet 10.10.11.1 netmask 255.255.255.252 destination 10.10.11.1 

 tun1: flags=4305<UP,POINTOPOINT,RUNNING,NOARP,MULTICAST> mtu 1500 inet 10.10.11.2 netmask 255.255.255.252 destination 10.10.11.2 

After all 4 tunnels are raised, this picture is obtained.

udp 1150 - 1.1.1.1-3.3.3.3 - tun1 - 10.10.11.1-10.10.11.2
udp 1151 - 2.2.2.2-4.4.4.4 - tun2 - 10.10.12.1-10.10.12.2
udp 1152 - 1.1.1.1-4.4.4.4 - tun3 - 10.10.15.1-10.10.15.2
udp 1153 - 2.2.2.2-3.3.3.3 - tun4 - 10.10.16.1-10.10.16.2

No additional static routes are required, except for adding firewall rules:

 -A FORWARD -o tun1 -m comment --comment "1" -j ACCEPT -A FORWARD -i tun1 -m comment --comment "1"-j ACCEPT -A FORWARD -o tun2 -m comment --comment "2" -j ACCEPT -A FORWARD -i tun2 -m comment --comment "2"-j ACCEPT -A FORWARD -o tun3 -m comment --comment "3" -j ACCEPT -A FORWARD -i tun3 -m comment --comment "3"-j ACCEPT -A FORWARD -o tun4 -m comment --comment "4" -j ACCEPT -A FORWARD -i tun4 -m comment --comment "4"-j ACCEPT 

Fault tolerance.


It is possible to achieve route switching using scripts, but it would be a cumbersome and not at all elegant solution. Previously, I have not had the opportunity to use dynamic routing in practice. There are a lot of protocols, I stopped at OSPF, by and large, because I found more information and methods of use. Protocol linkstate type, takes into account the state of the channels, interfaces and exchanges it. I think that it is quite possible to implement this on BGP or RIP. I would love to look at the BGP version of the solution.
In order for OSPF to receive and send LSA service packets, a Link State Advertisement will need to open ports on the firewall:

 -A INPUT -i tun1 -p 89 -m comment --comment "multicast tun1"-j ACCEPT -A INPUT -i tun2 -p 89 -m comment --comment "multicast tun2"-j ACCEPT -A INPUT -i tun3 -p 89 -m comment --comment "multicast tun3"-j ACCEPT -A INPUT -i tun4 -p 89 -m comment --comment "multicast tun4"-j ACCEPT 

Let's move on to setting up Quagga.


First you need to make sure that the folders and files that appear in the work of the Quagga services belonged to the user under which the service starts:

 chown -R quagga:quagga /etc/quagga chown -R quagga:quagga /var/log/quagga/ospfd.log 

We start services:

 systemctl start zebra systemctl start ospfd 

After that, you can begin to configure OSPF.

You can get to the console in two ways, telnet or vtysh , I chose the second one.
It is better to immediately try to write to check the rights to the configuration files, otherwise all the commands you enter will not be saved, it should turn out like this:

 host01# wr Building Configuration... Configuration saved to /etc/quagga/zebra.conf Configuration saved to /etc/quagga/ospfd.conf [OK] 

Check if all your interfaces are available for zebra.

 sh inter 

If the routed networks through OSPF and all tun interfaces are in place, you can continue.
First of all, you need to configure the cost of tunnels, the lower the cost, the more priority the tunnel. You can do it like this:

 interface tun1 ip ospf cost 10 

And further for other tun2 30, tun3 15, tun4 20 in my case.

Then you can start the router:

 router ospf ospf router-id 192.168.1.0 redistribute connected route-map LAN passive-interface default no passive-interface ens0 no passive-interface tun1 no passive-interface tun2 no passive-interface tun3 no passive-interface tun4 network 10.10.11.0/30 area 0.0.0.0 network 10.10.12.0/30 area 0.0.0.0 network 10.10.15.0/30 area 0.0.0.0 network 10.10.16.0/30 area 0.0.0.0 network 192.168.1.0/23 area 0.0.0.0 ! ip prefix-list LAN seq 10 permit 192.168.4.0/23 ip prefix-list LAN seq 100 deny any ! route-map LAN permit 10 match ip address prefix-list LAN 

In this configuration, the redistribute connected parameter is used to advertise not all routes to another server, but only the necessary ones, and the route-map LAN parameter allows filtering networks.

Exactly the same configuration should be on the other side of the tunnel. After activating the ospfd service, after about 10 seconds, the neighbors' routes will appear on both servers and the tunnel will be selected according to the cost. If the preferred tunnel stops working, it will automatically switch to another tunnel and so on, until the tunnels remain. And also, if a better interface is activated again, routing will go through it.

The estimated update time for routes is 10 seconds, you can vary the ip ospf hello-interval and ip ospf dead-interval parameters to shorten this time.

Do not forget to add all services to autoload, for example my OpenVPN configuration files are called srv-1050.conf and cli-1050.conf, in this case the commands will look like this:

 systemctl enable openvpn@srv-1050 systemctl enable openvpn@cli-1050 

Thank you for your attention, I will believe that it will be useful to someone.

Source: https://habr.com/ru/post/348360/


All Articles