Allow clients to connect only from a specific ip address

How to customize and extend your OpenVPN installation.

Moderators: TinCanTech, TinCanTech, TinCanTech, TinCanTech, TinCanTech, TinCanTech

Post Reply
frankuit
OpenVPN User
Posts: 34
Joined: Thu Apr 12, 2012 12:12 pm

Allow clients to connect only from a specific ip address

Post by frankuit » Thu Apr 12, 2012 12:49 pm

Hi All,

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 :oops: ,but hey it works! :P

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

Content of the "ALLOWFILE"

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
Kind regards,
Frank Uittenbosch

dropje
OpenVPN User
Posts: 28
Joined: Wed Aug 24, 2011 9:08 am

Re: Allow clients to connect only from a specific ip address

Post by dropje » Thu Apr 12, 2012 2:21 pm

It's a nice idea. We don't have a use case for it but i like it.

One addition, why aren't you using client-connect for this and instead of grabbing the remote ip from your logfile use the environment variable untrusted_ip or trusted_ip
untrusted if you want to know the ip before authentication or trusted if you want to know after.

The two vars i'd use in your setup are:

$common_name
$untrusted_ip

Furthermore, what's wrong with bash to do this for you :) We have all our important scripts for access policies etc written in bash :P

frankuit
OpenVPN User
Posts: 34
Joined: Thu Apr 12, 2012 12:12 pm

Re: Allow clients to connect only from a specific ip address

Post by frankuit » Thu Apr 12, 2012 2:25 pm

Thanks for the pointers Dropje, I'm going to make another version of this script with your info.
Is that variable untrusted_ip exported by default and adressable in shell ?
dropje wrote: Furthermore, what's wrong with bash to do this for you :) We have all our important scripts for access policies etc written in bash :P
well, nothing wrong with bash, but some programmers have a tendancy to flame bash-programmers a bit on other sites :P
Kind regards,
Frank Uittenbosch

frankuit
OpenVPN User
Posts: 34
Joined: Thu Apr 12, 2012 12:12 pm

Re: Allow clients to connect only from a specific ip address

Post by frankuit » Thu Apr 12, 2012 2:51 pm

So,
here is the updated version of the client_connect script:

Code: Select all

#!/bin/bash

#$common_name $untrusted_ip are imported from openvpn

LOG=/var/log/openvpn-log
DATE=`date`
VPNSERVER="your ip addres server here"
VPNPORT="management port here"
CLIENTSUFF="client suffix here"
ALLOWIPFILE="/etc/openvpn/firewall/allowed-ip"
ADMINS="linuxadmin@yourdomain.nl"
USERO=`echo $common_name |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" == "$untrusted_ip" ];then
                echo "$ALLOWEDUS is allowed from $untrusted_ip" >>$LOG
        elif [ "$ALLOWEDIP" != "$untrusted_ip" ];then
                echo "$USERO is NOT allowed from ip-address:$untrusted_ip! only from: $ALLOWEDIP" >>$LOG
                #DC USER ! Turn this off if you only want an email
                echo "kill $USERO.$CLIENTSUFF" |/usr/bin/telnet $VPNSERVER $VPNPORT
                echo "According to $ALLOWIPFILE, $USERO came from $untrusted_ip,But is only allowed from $ALLOWEDIP" |mutt $ADMINS -s "OpenVPN: Unauthorized connection attempt by $USERO"
        else
                echo "wtf is going on ? $ALLOWEDIP $ALLOWEDUS $untrusted_ip" >>$LOG
        fi
else
        echo "$USERO is not in the list so always allowed." >>$LOG
fi

}
#make a log entry stating who tried to connect
echo "$DATE $USERO CONNECTED to openvpn from $untrusted_ip " >>$LOG
#run the check function to determine if user can get access based on his untrusted_ip
checkip
Kind regards,
Frank Uittenbosch

kashifmax
OpenVpn Newbie
Posts: 5
Joined: Sat May 12, 2012 1:33 pm

Re: Allow clients to connect only from a specific ip address

Post by kashifmax » Sat May 12, 2012 2:18 pm

Hi Frank,
Can you please tell me where/how to run your script ? :roll:

frankuit
OpenVPN User
Posts: 34
Joined: Thu Apr 12, 2012 12:12 pm

Re: Allow clients to connect only from a specific ip address

Post by frankuit » Mon May 14, 2012 9:29 am

kashifmax wrote:Hi Frank,
Can you please tell me where/how to run your script ? :roll:
Hi Kashifmax,

i have put it in : /etc/openvpn/scripts/connect

and set in /etc/openvpn/server.conf

Code: Select all

client-connect /etc/openvpn/scripts/connect
Regards,
Frank
Kind regards,
Frank Uittenbosch

kashifmax
OpenVpn Newbie
Posts: 5
Joined: Sat May 12, 2012 1:33 pm

Re: Allow clients to connect only from a specific ip address

Post by kashifmax » Mon May 14, 2012 2:30 pm

Thank you Frank. I'll try it out and I'll tell you the result. Thanks again...

kashifmax
OpenVpn Newbie
Posts: 5
Joined: Sat May 12, 2012 1:33 pm

Re: Allow clients to connect only from a specific ip address

Post by kashifmax » Tue May 15, 2012 1:10 pm

Hi Frank,
I modified the script but I think I miss something ?

#!/bin/bash
# I modified the script according to my need. Thanks to Frank Uittenbosch (OpenVPN Community)
# FileName connect
LOG=/var/log/openvpn-log
OPENVPN=/var/log/openvpn/openvpn.log
DATE=`date`
ALLOWIPFILE="/etc/openvpn/firewall/allowed-ip"
ADMINS="kashif@domain.com"

function ip () {
IP=`tail -4000 $OPENVPN |grep -i $USERO|awk '{print $6}' |tail -1|cut -d "/" -f2|cut -d ":" -f1`
USER=`tail -4000 $OPENVPN |grep -i $USERO|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
echo "According to $ALLOWIPFILE, $USERO came from $IP, But is only allowed from $ALLOWEDIP" |mail $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
#END


OpenVPN Log
------------------
ay 15 13:35:44 local 95.x.x.22:15365 LZO compression initialized
May 15 13:35:45 local 95.x.x.22:15365 [user1] Peer Connection Initiated with 95.x.x.22:15365 (via 192.x.x.2)
May 15 13:35:45 local user1/95.x.x.22:15365 client-connect command failed: external program exited with error status: 1
May 15 13:35:45 local 46.x.x.148:61291 Re-using SSL/TLS context
May 15 13:35:45 local 46.x.x.148:61291 LZO compression initialized
May 15 13:35:46 local 46.x.x.148:1195 Re-using SSL/TLS context
May 15 13:35:46 local 46.x.x.148:1195 LZO compression initialized
May 15 13:35:47 local 46.x.x.148:61291 [user2] Peer Connection Initiated with 46.x.x.148:61291 (via 192.168.110.2)
May 15 13:35:47 local user2/46.x.x.148:61291 client-connect command failed: external program exited with error status: 1
May 15 13:35:55 local 77.x.x.249:51276 [user3] Peer Connection Initiated with 77.x.x.249:51276 (via 192.x.x.2)
May 15 13:35:55 local user3/77.x.x.249:51276 client-connect command failed: external program exited with error status: 1
May 15 13:36:01 local read UDPv4 [CMSG=8|ECONNREFUSED]: Connection refused (code=111)
May 15 13:36:14 local OpenVPN CLIENT LIST
May 15 13:36:14 local Updated,Tue May 15 13:36:14 2012
May 15 13:36:14 local Common Name,Real Address,Bytes Received,Bytes Sent,Connected Since
May 15 13:36:14 local ROUTING TABLE
May 15 13:36:14 local Virtual Address,Common Name,Real Address,Last Ref
May 15 13:36:14 local GLOBAL STATS
May 15 13:36:14 local Max bcast/mcast queue length,0
May 15 13:36:14 local END
May 15 13:36:14 local event_wait : Interrupted system call (code=4)
May 15 13:36:14 local OpenVPN CLIENT LIST
May 15 13:36:14 local Updated,Tue May 15 13:36:14 2012
May 15 13:36:14 local Common Name,Real Address,Bytes Received,Bytes Sent,Connected Since
May 15 13:36:14 local ROUTING TABLE
May 15 13:36:14 local Virtual Address,Common Name,Real Address,Last Ref
May 15 13:36:14 local GLOBAL STATS
May 15 13:36:14 local Max bcast/mcast queue length,0
May 15 13:36:14 local END
May 15 13:36:15 local event_wait : Interrupted system call (code=4)


allowed-ip file content
---------------------------
77.x.x.249,user3
77.x.x.249,user4


Added in /etc/openvpn/openvpn.conf
----------------------------------------------
client-connect "/etc/openvpn/scripts/connect"

Note: There was already a client-connect/client-disconnect option (/usr/local/bin/openvpn-client-connect, /usr/local/bin/openvpn-client-disconnect) in the openvpn configuration and I disabled both but the same result. That file has the following code.

import os
import sys
from endian.job.engine_control import send_cmd_to_engine

if len(sys.argv) < 2 or not 'common_name' in os.environ or not 'ifconfig_pool_remote_ip' in os.environ:
print "Invalid usage - this script must be triggered by OpenVPN daemon"
sys.exit(2)

print send_cmd_to_engine("call openvpnjob.client_connect",
options={'config_pathname': os.path.abspath(sys.argv[1]),
'common_name': os.environ['common_name'],
'ifconfig_pool_remote_ip': os.environ['ifconfig_pool_remote_ip']})

frankuit
OpenVPN User
Posts: 34
Joined: Thu Apr 12, 2012 12:12 pm

Re: Allow clients to connect only from a specific ip address

Post by frankuit » Wed May 16, 2012 10:52 am

Hi Kashif,

Sorry, i was mistaken in the client-connect statement.

THis script has to be launched using the learn-address option in your openvpn server.conf file, eg:
learn-address /etc/openvpn/scripts/scriptname

I have changed the script recently, and it uses client connect now.
i'll post the new version later today.

Regards,
Frank Uittenbosch
Kind regards,
Frank Uittenbosch

frankuit
OpenVPN User
Posts: 34
Joined: Thu Apr 12, 2012 12:12 pm

Re: Allow clients to connect only from a specific ip address

Post by frankuit » Wed May 16, 2012 10:59 am

This is the new script. (changelog below)

What you need:OpenVPN(doh),geoiplookup, mutt.

Enter the following info in your server.conf

Code: Select all

client-connect /etc/openvpn/scripts/connect
put the code below in /etc/openvpn/scripts/connect

Code: Select all

#!/bin/bash

#$common_name $untrusted_ip are imported from openvpn

LOG=/var/log/openvpn-log
PATTERNFILE=/var/log/openvpn-log-pattern
DATE=`date`
ALLOWIPFILE="/etc/openvpn/firewall/allowed-ip"
ADMINS="youradminemailadres@you.com"
USERO=`echo $common_name |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" == "$untrusted_ip" ];then
                echo "$ALLOWEDUS is allowed from $untrusted_ip" >>$LOG
        elif [ "$ALLOWEDIP" != "$untrusted_ip" ];then
                echo "$USERO is NOT allowed from ip-address:$untrusted_ip! only from: $ALLOWEDIP" >>$LOG
                echo "According to $ALLOWIPFILE, $USERO came from $untrusted_ip,But is only allowed from $ALLOWEDIP" |mutt $ADMINS -s "OpenVPN: Unauthorized connection attempt by $USERO"
                exit 1
        else
                echo "wtf is going on ? $ALLOWEDIP $ALLOWEDUS $untrusted_ip" >>$LOG
                echo "wtf is going on ? $ALLOWEDIP $ALLOWEDUS $untrusted_ip $CHECK" |mutt $ADMINS -s "OpenVPN: yo shizzle aint workin' bro: $USERO"
        fi
else
        echo ""
        #echo "$USERO is not in the list so always allowed." >>$LOG
fi

}
#make a log entry stating who tried to connect
#trace ip address to country if available
COUNTRY=`/usr/bin/geoiplookup $untrusted_ip |cut -d "," -f2 |grep -v Address`
echo "$DATE $USERO CONNECTED    from $untrusted_ip. Country:$COUNTRY and is assigned $ifconfig_pool_local_ip/16 " >>$LOG
#see if we can distinguish patterns from user logins so that we can prevent hacks.
echo "$USERO,$untrusted_ip,$COUNTRY" >>$PATTERNFILE
#run the check function to determine if user can get access based on his untrusted_ip
checkip

create file: /etc/openvpn/firewall/allowed-ip (ALLOWIPFILE) and use the following notation:

Code: Select all

#notation:
#ipadress,username (for instance)
#Comma seperated!!
12.34.56.78,pietje
Make sure your OpenVPN server has access to:

Code: Select all

/var/log/openvpn-log
/var/log/openvpn-log-pattern
Or be sure to change the paths in the script to someplace OpenVPN can write to.

How this new version works explained:
OpenVPN server calls client-connect script, and the script checks a person in the allow file.
If the person is found in the file, then his ip address must correspond to the one specified in the allow file otherwise the script will return exit status 1 and send an email to the adminmailadress stating somebody falsely connected.
If the person is NOT found in the file, then the scripts returns nothing (CONNECT).
If something else happens admin get's mailed with the variable error logging.


Changelog:

-Changed from learn-address to client-connect.
-Added extra logging and doing an ip country lookup.
-alfa testing of login pattern recognition


Hope this helps!
Kind regards,
Frank Uittenbosch

kashifmax
OpenVpn Newbie
Posts: 5
Joined: Sat May 12, 2012 1:33 pm

Re: Allow clients to connect only from a specific ip address

Post by kashifmax » Sat May 19, 2012 8:08 am

Thanks Frank,
I have tried using learn-address but the same error. I'll try to use your new script but I have to do some changes because I am using Endian Firewall. I suppose that $common_name and $untrusted_ip will not work but I will try again. Thanks.

kashifmax
OpenVpn Newbie
Posts: 5
Joined: Sat May 12, 2012 1:33 pm

Re: Allow clients to connect only from a specific ip address

Post by kashifmax » Sat May 19, 2012 9:45 am

Same error
user2/46.x.x.148:10369 client-connect command failed: external program exited with error status: 1

Can you please point out any mistake in the privious script that I have uploaded ? Or can you adjust it with your current script ?
Anyways thanks a lot...

martinib
OpenVpn Newbie
Posts: 1
Joined: Wed Nov 28, 2012 4:49 pm

Re: Allow clients to connect only from a specific ip address

Post by martinib » Wed Nov 28, 2012 4:50 pm

Hi, i'm having the same goal with my configuration.
Is this script the best way to accomplish the task?. Did someone have a windows batch translation of the script?.
Thanks.

frankuit
OpenVPN User
Posts: 34
Joined: Thu Apr 12, 2012 12:12 pm

Re: Allow clients to connect only from a specific ip address

Post by frankuit » Wed Nov 28, 2012 11:56 pm

Well,

I've never translated this to batch / Windows.
BUt if you need any help in understanding the code, let me know.

Regards,
Frank
Kind regards,
Frank Uittenbosch

sahibzadafahad
OpenVpn Newbie
Posts: 1
Joined: Fri Aug 10, 2018 5:42 am

Re: Allow clients to connect only from a specific ip address

Post by sahibzadafahad » Wed Aug 15, 2018 10:28 am

It gives me following error in openvpn status:
WARNING: External program may not be called unless '--script-security 2' or higher is enabled. See --help text...r detailed info
WARNING: Failed running command (--client-connect): external program fork failed
PUSH: Received control message: 'PUSH_REQUEST'
Delayed exit in 5 seconds
SENT CONTROL [sahibzadafahad]: 'AUTH_FAILED' (status=1)

frankuit
OpenVPN User
Posts: 34
Joined: Thu Apr 12, 2012 12:12 pm

Re: Allow clients to connect only from a specific ip address

Post by frankuit » Sat Aug 18, 2018 8:26 pm

so when starting up openvpn server, you have to add the '--script-security 2' to the daemon.
either in the config file or on the command line.
also, this may be needed to in the client.conf file.

Post Reply