Setting up OpenVPN using radius on FreeBSD
I’ve got a MS ISA 2004 server, and some colleagues that connect to the office remotely, using the built-in windows PPTP client.
After using Microsoft’s PPTP server for about 6 years, I’ve totally had it. I’m tired and sick of problems with networking infrastructue (passing GRE through firewalls), the lack of easy error reporting functionality, etc. Every now and then connections don’t work, and rebooting a firewall here and there usually solves the problem.
After thinking about it for a while, I decided to ditch the MS PPTP server, and implement an OpenVPN server for my collegues on the road. I’ve been using OpenVPN for a while now as well, and I’m a big fan.. I’ve hooked up several data centres and remote locations using OpenVPN, and it has always been a rock solid solution. It can get a little complex at times, but it’s definitly worth the effort.
However, I’m used to using certificates-based authentication only. I don’t want to generate certificates for all user accounts or PC’s and manage the distribution. Luckily, I can use username and password-based authentication as well. But, I don’t want to manage user accounts on the VPN server or in a list, I want to be able to use the existing active directory infrastructure, and the existing useraccounts and passwords. That’s where radius comes into the picture.
I set up the OpenVPN server, and configured it to use radius authentication (after hours of searching google and trying), and set up IAS on a machine in my network (one of the domain controllers in my case), to authenticate users. I then created a custom openvpn-gui installer, with a configuration file which defines all the settings that are required, and published it to a web location my colleagues can access. They just have to download and install this openvpn-gui package, click on connect, enter their username and password, and they’re connected!
I chose to use bridging instead of routed mode, because it’s much easier to manage, and this is the way these ‘power users’ are used to work. And now they can even get net send messages and other broadcasts.
I have a seperate FreeBSD 6.2 machine set up behind my firewall, and redirected the OpenVPN port to the VPN server. The VPN server has one network card, which is bridged to the LAN. In my case, it’s a VMware guest, but that makes no difference (remember to enable promiscuous mode on the virtual switch if you use VMware!)
After the clean install of the FreeBSD machine and the upgrade to the latest version (perhaps not necessary, but I’m a perfectionist), I installed openvpn from ports.
In my rc.conf file I define the bridge, and add the physical nic to it (nic0). I automatically start openvpn on boot, set it to use tap mode, and specify the config file:
/etc/rc.conf
cloned_interfaces="bridge0"
ifconfig_bridge0="addm nic0 up"
openvpn_enable="YES"
openvpn_if="tap bridge"
openvpn_configfile="/usr/local/etc/openvpn/server.conf"
Since we want to use radius through pam.d, let’s create a module, which tells it to use radius (I’m not an expert on this matter, just copied and pasted it):
/etc/pam.d/openvpn
#%PAM-1.0
account required pam_radius.so
account required pam_radius.so
auth required pam_radius.so no_warn try_first_pass
And this is the radius client configuration. I set up IAS on the domain controller, and added the VPN server as an allowed client:
/etc/radius.conf
acct dc1.domain.local verysecretpassword
auth dc1.domain.local verysecretpassword
And this is how the config file looks. Notice the plugin line, which make openvpn use the pam.d module called openvpn we created above. The ‘client-cert-not-required’ option tells openvpn not to require a certificate (you can use both username/password AND certificate authentication!), and the ‘username-as-common-name’ options tells openvpn to use the username as common name, which comes in handy when creating custom scripts for specific users, and for logging.
The ‘server-bridge’ option specifies the ip-address of the vpn server, the subnet mask, and the ip’s to hand out to clients. I’m pushing some routes and DNS servers to the clients as well. Note that the pushed routes don’t yet work on Vista, but manually creating a persistant route on the client machine solves the problem. Not as nice as I had hoped, but it does the trick.
The ‘up’ and ‘down’ scripts (printed below) add the tap0 device to the bridge, and remove it again if the openvpn server starts or stops.
The ‘client-connect’ and ‘client-disconnect’ scripts (printed below) are just for logging in my case. I want to log all disconnects to a seperate logfile, and to an emailbox (for the moment)
The ‘client-to-client’ option lets the users connect to each other, and the ‘duplicate-cn’ make sure users can connect from multiple pc’s simultaniously using their own account (yes, we do that sometimes).
/usr/local/etc/openvpn/server.conf
port 1194
proto udp
dev tap0
plugin /usr/local/lib/openvpn-auth-pam.so openvpn
ca ca.crt
cert server.crt
key server.key
dh dh1024.pem
client-cert-not-required
username-as-common-name
server-bridge 192.168.123.25 255.255.255.0 192.168.123.60 192.168.123.99
up /usr/local/etc/openvpn/server-up.sh
down /usr/local/etc/openvpn/server-down.sh
client-connect /usr/local/etc/openvpn/client-connect.sh
client-disconnect /usr/local/etc/openvpn/client-disconnect.sh
push "route 10.1.1.0 255.255.255.0 192.168.123.1"
push "route 10.1.2.0 255.255.255.0 192.168.123.1"
push "dhcp-option DOMAIN domain.local"
push "dhcp-option DNS 192.168.123.2"
push "dhcp-option DNS 192.168.123.3"
client-to-client
duplicate-cn
keepalive 10 120
comp-lzo
persist-key
persist-tun
status openvpn-status.log
log-append openvpn.log
verb 3
server-up.sh
#!/bin/sh
ifconfig bridge0 addm $dev
server-down.sh
#!/bin/sh
ifconfig bridge0 deletem $dev
client-connect.sh
#!/bin/sh
logfile="/var/log/openvpn-connections.log"
datetime=`date`
#content=`set`
content=" "
logline="$datetime: user $common_name connected (local $ifconfig_pool_remote_ip remote $untrusted_ip)"
subject="TIL-VPN-01: $logline"
echo $logline >> $logfile
echo $content | mail -s "$subject" systeembeheer@domain.nl
client-disconnect.sh
#!/bin/sh
logfile="/var/log/openvpn-connections.log"
datetime=`date`
#content=`set`
content=" "
logline="$datetime: user $common_name disconnected (local $ifconfig_pool_remote_ip remote $untrusted_ip)"
subject="TIL-VPN-01: $logline"
echo $logline >> $logfile
echo $content | mail -s "$subject" systeembeheer@domain.nl
Oh yeah, and for the clients, I just download the installation package from www.openvpn.se, and send the clients the config file:
client
dev tap
proto udp
remote vpn.remotedomain.nl 1194
route-method exe
route-delay 2
resolv-retry infinite
nobind
persist-key
persist-tun
auth-user-pass
ca netmatch-ca.crt
comp-lzo
verb 3
Well, actually, I followed the instructions on openvpn.se, to create my own installer, where I include the client config file. So I can just have remote clients install the VPN client, click connect, they enter their credentials, and tadaa! They’re in.






[...] read more [...]
Angelo’s blog » Setting up OpenVPN using radius on FreeBSD | August 20, 2007 | 4:39 pm[...] read more [...]
Hey, Nice info! But you don't assign an adress to the
Hey,
Nice info! But you don’t assign an adress to the tap-device? I assumed I didn’t need one, but it didn’t work (no routing) when I didn’t assign an address to the tap-device. I now handle that in the client-connect script.
I have assigned my physical nic (in this case nic0)
I have assigned my physical nic (in this case nic0) an ip address.
On boot I create a bridge called bridge0, and I add the nic0 interface to it. That works. Then when OpenVPN starts, it adds the tap0 interface to the bridge. I guess this is just one of many ways it can work.
It would be lovely if you explain your openvpn client
It would be lovely if you explain your openvpn client conf & package =)
Any special options in the client.conf file on the client-side?
Any special options in the client.conf file on the client-side? or just the example .conf file?
Sebastiaan, Regis, you are right, I did not post the
Sebastiaan, Regis, you are right, I did not post the client config. Now I added it to the bottom of the post.
It’s quite default, but the most important line it the ‘auth-user-pass’, which tells the client it should use username and password authentication instead of certificate based authentication.
I found this document very useful, and combine the information
I found this document very useful, and combine the information in it with the information in the document http://www.mired.org/home/mwm/papers/FreeBSD-OpenVPN-Bridging.html to eventually achieve a working solution. I’m actually not doing radius (yet), but this document was the best I found for the basic setup on wanted in my general situation.
I am working with FreeBSD 7.0R, and thought I’d mention one thing which tripped me up. In my case ‘tun’ did not come ‘up’ without manual intervention, and I didn’t notice it in ‘ifconfig -a’ for some time. In my case, I made my ‘server-up.sh’ script read:
#!/bin/sh
ifconfig bridge0 addm $dev
ifconfig $dev up
which addressed the problem. I had no need to specify any addresses for anything besides the standard for fxp0 (in my case.)
Another thing which caused me confusion was the ‘server-bridge’ setting. In my case, for the first parameter, I used the internal IP of my router (a different FreeBSD host in my case) which is the standard gateway for all machines in my internal network. I did not need any ‘push “route …”‘ items in my situation. I found myself wishing for a diagram of Angelo’s topology (but also, very happy for what he provided of course!)
I also found better luck pushing DNS entries to the TAP-Win32 interface on my XP client test host by adding the directive:
push "ip-win32 dynamic"
but the jury is still out on how well it really works in practice. I’m just adding these comments early on while things are still fresh in my mind in case others find them helpful.
Absolutely brilliant. Thanks for taking the time to share
Absolutely brilliant. Thanks for taking the time to share this!
I have got a question, i want to use a
I have got a question, i want to use a script (client-connect & client-disconnet) on DebianEtch but i couldn’t find a good script on the Net. Could anyone help me? and show a good script…
thx, vipera
a) you only need a bridge when you have a
a) you only need a bridge when you have a layer2 protocol going over the vpn. If using IP traffic use tun so you have less overhead and layer2 attacks will not work over the vpn.
b) 2.1.1 has the windows gui built in, http://www.openvpn.net/download
the .se link is no longer up to date
a) you only need a bridge when you have a
a) you only need a bridge when you have a layer2 protocol going over the vpn. If using IP traffic use tun so you have less overhead and layer2 attacks will not work over the vpn.
b) 2.1.1 has the windows gui built in, http://www.openvpn.net/download
the .se link is no longer up to date
sorry for the doublepost, i had a typo to fix