yesterday i was wondering if it were possible to allow Openvpn access to certain users only when their ip matches a predefined ip address.
In our case, we supply our users with a certificate login, (user bound, not ip) and they use it.
When the user leaves the company, we revoke it and all is good
Now, we have certain companies doing work for us, but we only want them to connect from their office ip address, so when a person from that company gets fired, they can't use the vpn certificate from outside the company anymore.
I did not find any functionality for this in iptables or the openvpn daemon itself, so i made a script which basically does the following:
Code: Select all
- on connect, using the learn-address statement pointing to a script, retrieve the CN (common name) from the users certificate file, and the remote ipadress of the user from your openvpn logfile.
-Check if the CN occurs in a file (containing the names and ip adresses of users with this limitation)
- If it matches something in the file, then check the ip address and verify if the ip is allowed to connect from.
- If the ip adress differs from the one specified in our file, then disconnect the user, and mail somebody saying something not good is happening!
-if the CN doesnt match anything in the file, then the user is allowed to connect from all ip adresses.
anyway, the code is in bash ,but hey it works!
Code: Select all
#!/bin/bash
# Created by Frank Uittenbosch, Feel free to use, change and everything else.
#Works on Debian squeeze, 64, and ubuntu
LOG=/var/log/openvpn-log
SYSLOG=/var/log/syslog
DATE=`date`
VPNSERVER="Ip address of your vpn server, if you want to use the management kill option"
VPNPORT="port of your MANAGEMENT interface on your vpn server"
CLIENTSUFF="client suffix if you want to use the kill option in management"
ALLOWIPFILE="/etc/openvpn/firewall/allowed-ip"
ADMINS="linuxadmin@yourcompany.nl"
function ip () {
IP=`tail -4000 $SYSLOG |grep -i $USERO|grep CONTROL |awk '{print $6}' |tail -1|cut -d "/" -f2|cut -d ":" -f1`
USER=`tail -4000 $SYSLOG |grep -i $USERO|grep CONTROL |awk '{print $6}' |tail -1|cut -d "/" -f1|cut -d "." -f1`
}
function checkip () {
egrep -i $USERO $ALLOWIPFILE && CHECK=1 || CHECK=0
if [ "$CHECK" == "1" ];then
ALLOWEDIP=`grep -i $USERO $ALLOWIPFILE |cut -d "," -f1`
ALLOWEDUS=`grep -i $USERO $ALLOWIPFILE |cut -d "," -f2`
if [ "$ALLOWEDIP" == "$IP" ];then
echo "$ALLOWEDUS is allowed from $IP" >>$LOG
elif [ "$ALLOWEDIP" != "$IP" ];then
echo "$USERO is NOT allowed from ip-address:$IP! only from: $ALLOWEDIP" >>$LOG
#DC USER ! Turn this on if you want to kill the users connection
#only useable when you have management available in your openvpn installation
# echo "kill $USERO.$CLIENTSUFF" |/usr/bin/telnet $VPNSERVER $VPNPORT
echo "According to $ALLOWIPFILE, $USERO came from $IP,But is only allowed from $ALLOWEDIP" |mutt $ADMINS -s "OpenVPN: Unauthorized connection attempt by $USERO"
else
echo "wtf is going on ? $ALLOWEDIP $ALLOWEDUS $IP" >>$LOG
fi
else
echo "$USERO is not in the allowed list so always allowed." >>$LOG
fi
}
if [ "$1" == "add" ]
then
USERO=`echo $3 |cut -d "." -f1`
ip
echo "$DATE $USERO CONNECTED to openvpn from $IP" >>$LOG
checkip
elif [ "$1" == "delete" ]
then
echo "$DATE $2 $3 DISCONNECTED from openvpn " >>$LOG
elif [ "$1" == "update" ]
then
USERO=`echo $3 |cut -d "." -f1`
ip
echo "$DATE $USERO CONNECTED to openvpn from $IP " >>$LOG
checkip
else
echo ERROR, ERROR, DOES NOT COMPUTE !! $1 $2 $3 >> $LOG
fi
Code: Select all
#notation:
#ipadress,username (for instance)
#Comma seperated!!
12.34.56.78,pietje
Result:
Our users pass the script always, because their ip adress is not in the ALLOWFILE
Our suppliers who do some maintenance on our servers can only connect from a certain ip adress.
and this saves us the trouble of always having to revoke a certificate of a supporting company when someone leaves, and had openvpn on their laptop.
(am i making any sence here ?
Anyway, Hope this helps, and perhaps gets built in openvpn in the near feature.
Should you see any improvements, or bugs, please let me know!
Kind regards,
Frank Uittenbosch