This tutorial by user Felix J. Ogris shows us how to get OpenVPN routing with BIRD set up on FreeBSD.
If you run OpenVPN as an unprivileged user and/or in a chroot environment, it can’t dynamically modify routes. This becomes a problem if you run multiple OpenVPN daemons, no matter whether they run on the same box or on different servers. When a client disconnects from one instance and later connects to another instance, you have to update your internal routing information for that client. To solve this, I’ve been using the BIRD Internet Routing Daemon.
The relevant part of my /usr/local/etc/openvpn.conf looks like this:mode server chroot /usr/local/etc/openvpn/chroot client-connect /bin/cc.sh client-disconnect /bin/cc.sh script-security 2 user openvpn group openvpn
Note that the location of the client-connect and client-disconnect script /bin/cc.sh is relative to the chroot directory /usr/local/etc/openvpn/chroot, which contains three subdirectories:drwxr-xr-x 2 root wheel bin drwxr-xr-x 2 root wheel ccd drwxrwxr-x 2 root openvpn tmp
- bin contains three tools:-r-xr-xr-x 1 root wheel cc.sh -r-xr-xr-x 2 root wheel nc -r-xr-xr-x 2 root wheel sh
I copied sh from /rescue/sh, while nc was hardlinked to sh. All binaries in /rescue are statically linked, so they’ll work even in a chroot environment.
- ccd contains my client config files, each containing an ifconfig-push and optionally one or more iroute statements for a particular client. Those files are owned and writeable by root only.
- tmp contains the control socket for BIRD, and a dynamically created config file for each OpenVPN client.
When an OpenVPN client connects, cc.sh reads its ip address and routes from the config file in ccd, writes this information in BIRD compatible syntax to the config file in tmp, and informs BIRD to reload its configuration.
When a client disconnects, cc.sh just empties the config file in tmp, and reloads BIRD.
My /usr/local/etc/bird.conf looks like this: