Let's assume the following network topology and ip setup.
eth0
: 10.10.1.1/24
eth1
: 192.168.1.1/24
, fd01:c0:a801::1/64
tun0
: 172.16.1.1
tun1
: 172.16.2.1
tun2
: 172.16.99.1/24
eth0
: 10.20.2.2/24
eth1
: 192.168.2.1/24
, fd01:c0:a802::1/64
tun0
: 172.16.1.2
tun1
: 172.16.3.1
eth0
: 10.30.3.3/24
eth1
: 192.168.3.1/24
, fd01:c0:a803::1/64
tun0
: 172.16.2.2
tun1
: 172.16.3.2
eth0
)eth0
)11961
, 11962
and 1196
, respective11961
We need to set up openvpn on all servers. I'll use a very basic example with preshared secrets to show the concept. Please use additional security measures in your production, like client certificates, user authentication, strong ciphers, etc.pp.
First, generate some shared keys:
for s in sagittarius aquarius columba draco; do
openvpn --genkey --secret ${s}.key
done
and push them to the corresponding servers. Then create openvpn's configuration files.
Now start up the daemons
systemctl start openvpn-server@*
systemctl start openvpn-client@*
and wait for them connecting to each other:
ip a show dev tun0
ip a show dev tun1
...
tl;dr: get the configs here:
for service in zebra ospfd ospf6d; do
systemctl enable --now ${service}
done
conf t
int eth0
desc public
!
int eth1
desc local network
!
int tun0
desc vpn name (e.g. sagittarius)
!
int tun1
desc ...
! ...
ip forwarding
ipv6 forwarding
conf t
router ospf
! let's use router-id 1 for aldebaran, 2 for beteigeuze, 3 for castor
router-id 0.0.0.1
! do not announce ospf here
passive-interface eth0
passive-interface eth1
! on aldebaran, do not announce ospf on tun2
passive-interface tun2
!
int eth1
ip ospf area 2
!
int tun0
ip ospf area 0
!
int tun1
ip ospf area 0
!
! on aldebaran, add tun2 to area 1
int tun2
ip ospf area 1
aldebaran# show ip ospf neighbor
Neighbor ID Pri State Dead Time Address Interface RXmtL RqstL DBsmL
0.0.0.3 1 Full/DROther 35.849s 172.16.2.2 tun1:172.16.2.1 0 0 0
0.0.0.2 1 Full/DROther 34.149s 172.16.1.2 tun0:172.16.1.1 0 0 0
aldebaran# show ip route ospf
Codes: K - kernel route, C - connected, S - static, R - RIP,
O - OSPF, I - IS-IS, B - BGP, E - EIGRP, N - NHRP,
T - Table, v - VNC, V - VNC-Direct, A - Babel, D - SHARP,
F - PBR, f - OpenFabric,
> - selected route, * - FIB route
O 172.16.99.0/24 [110/10000] is directly connected, tun2, 00:03:01
O 192.168.1.0/24 [110/10] is directly connected, eth1, 00:03:06
O>* 192.168.2.0/24 [110/10010] via 172.16.1.2, tun0 onlink, 00:02:53
O>* 192.168.3.0/24 [110/10010] via 172.16.2.2, tun1 onlink, 00:02:53
conf t
router ospf6
! let's use router-id 1 for aldebaran, 2 for beteigeuze, 3 for castor
ospf router-id 0.0.0.1
interface tun0 area 0.0.0.0
interface tun1 area 0.0.0.0
interface eth1 area 0.0.0.2
! on aldebaran, add tun2 to area 0.0.0.1
interface tun2 area 0.0.0.1
!
int eth0
! do not announce ospfv3 here
ipv6 ospf6 passive
!
int eth1
! do not announce ospfv3 here
ipv6 ospf6 passive
!
! on aldebaran, do not announce ospfv3 on tun2
int tun2
ipv6 ospf6 passive
!
int tun0
ipv6 ospf6 network point-to-point
!
int tun1
ipv6 ospf6 network point-to-point
aldebaran# show ipv6 ospf6 neighbor
Neighbor ID Pri DeadTime State/IfState Duration I/F[State]
0.0.0.2 1 00:00:31 Full/PointToPoint 00:39:30 tun0[PointToPoint]
0.0.0.3 1 00:00:32 Full/PointToPoint 00:39:30 tun1[PointToPoint]
aldebaran# show ipv6 route ospf6
Codes: K - kernel route, C - connected, S - static, R - RIPng,
O - OSPFv3, I - IS-IS, B - BGP, N - NHRP, T - Table,
v - VNC, V - VNC-Direct, A - Babel, D - SHARP, F - PBR,
f - OpenFabric,
> - selected route, * - FIB route
O fd01:c0:a801::/64 [110/10] is directly connected, eth1, 00:03:39
O>* fd01:c0:a802::/64 [110/10010] via fe80::9008:17d:4a6b:41b3, tun0, 00:03:27
O>* fd01:c0:a803::/64 [110/10010] via fe80::37d2:ebfd:821f:2a5, tun1, 00:03:00
In this simple setup the point-to-point addresses are not redistributed via ospf. For example, castor will not know about sagittarius' addresses. That might lead to irritation when communicating with the interface's address:
To circumvent this, try one of the following:
This could be for example the local network address (192.168.1.1
on aldebaran) or a loopback address:
conf t
interface lo
ip address 192.168.255.1/32
ip ospf area 127
usage:
ping -I 192.168.255.1 192.168.2.1
you'll need staticd
for that:
systemctl enable --now staticd
! for aldebaran
ip route 172.16.1.0/30 tun0
ip route 172.16.2.0/30 tun1
!
router ospf
redistribute static
!
! or, if you have static routes your don't want to redistribute
!
! route-map redistribute-area-0 permit 1
! match interface tun0
! !
! route-map redistribute-area-0 permit 2
! match interface tun1
! !
! router ospf
! redistribute static route-map redistribute-area-0
Keep in mind not all connected routes shall be advertised (i.e. hide the public network). Therefore we'll use a route map.
route-map redistribute-area-0 permit 1
match interface tun0
!
route-map redistribute-area-0 permit 2
match interface tun1
!
router ospf
redistribute connected route-map redistribute-area-0
The routes to the networks will change in a short couple of time depending of timeout and failover settings.
show ip route ospf
on aldebaran (watch the interfaces)show ip route ospf
on beteigeuze (watch the interfaces)show ipv6 route ospf6
on aldebaran (watch the interfaces)show ipv6 route ospf6
on beteigeuze (watch the interfaces)With this bash script you'll create an LXC environment of this article's setup. Tested on Fedora 30. Prerequisites:
lxc
, lxc-templates
, bridge-utils
and busybox
are installedbash
>= 4.3