VPN Server: How to allow only one active connection per user?

bmn1

Senior Member
Hello everyone,

I have set up the VPN Server and so far everything works fine.
How ever, I noticed that multiple clients can connect with one OpenVPN User credential at the same time.
This means I create one user "Thomas" and if he shares his login+client file, then several other users can login at the same time.

Is there a way to allow only one active connection per user?

Also:
Will setting "Client will use VPN to access: Internet only" disable any access inside the local network (e.g. file shares, SMB,...)?

Thanks!
 

eibgrad

Part of the Furniture
Hello everyone,

I have set up the VPN Server and so far everything works fine.
How ever, I noticed that multiple clients can connect with one OpenVPN User credential at the same time.
This means I create one user "Thomas" and if he shares his login+client file, then several other users can login at the same time.

Is there a way to allow only one active connection per user?

Your description begs the question, what's the actual problem here? Is it the fact users are sharing credentials (!), or that users can create multiple connections? Seems to me the latter would normally be desirable. But if it's the former, then users are violating security norms, and that's a NOT technical problem, but something you need to address separately. Because even if you limit access to one connection at a time, who's to say which of those users is the legitimate owner of those credentials? It basically comes down to who gets connected first.

IOW, you haven't convinced me this requires a technical solution, but seems more likely an administrative issue w/ your users.

If you actually want to limit users to only one connection for other reasons, that can be done. But again, it's NOT going to solve this security issue.

Also:
Will setting "Client will use VPN to access: Internet only" disable any access inside the local network (e.g. file shares, SMB,...)?

Thanks!

Yes. When you specify "Internet only", what the router does is allow access to anything BUT the private local network (e.g., 192.168.1.0/24), thus the internet becomes available by the lack of exclusion. Doesn't matter what services you maybe attempting to access, you're denied access to the local private IP network on that basis alone.
 

bmn1

Senior Member
Your description begs the question, what's the actual problem here? Is it the fact users are sharing credentials (!), or that users can create multiple connections? Seems to me the latter would normally be desirable. But if it's the former, then users are violating security norms, and that's a NOT technical problem, but something you need to address separately. Because even if you limit access to one connection at a time, who's to say which of those users is the legitimate owner of those credentials? It basically comes down to who gets connected first.

IOW, you haven't convinced me this requires a technical solution, but seems more likely an administrative issue w/ your users.

If you actually want to limit users to only one connection for other reasons, that can be done. But again, it's NOT going to solve this security issue.



Yes. When you specify "Internet only", what the router does is allow access to anything BUT the private local network (e.g., 192.168.1.0/24), thus the internet becomes available by the lack of exclusion. Doesn't matter what services you maybe attempting to access, you're denied access to the local private IP network on that basis alone.

You are absolutely right that this is a administrative issue.
I will be creating 1 (or 2) VPNs for persons/friends I met during a trip in another country who were really helpful and nice.
They asked for a VPN to browse certrain sites which are blocked in their country.
Obviously I want to help them but they aren't exactly family members or close friends.

By allowing only one connection per user, I could mitigate the account sharing atleast a bit since it would annoy the original user when he constantly gets kicked out of the VPN.
I would love to go even further and set e.g. traffic limits and time schedules on when this user can be used and when not.
But any bit of "restriction" is already going to make it "safer".
 

eibgrad

Part of the Furniture
If you want to limit each username to one connection (or more precisely, have any new connection attempt w/ the same credentials kick off the current user in favor of the new connection), you can add the following directive to the custom config field of the OpenVPN server.

Code:
username-as-common-name

And remove the duplicate-cn directive w/ a postconf script.

Code:
SCRIPTS_DIR='/jffs/scripts'
SCRIPT="$SCRIPTS_DIR/openvpnserver1.postconf"

mkdir -p $SCRIPTS_DIR

create_script() {
cat << 'EOF' > $SCRIPT
#!/bin/sh
CONFIG=$1
source /usr/sbin/helper.sh

pc_delete 'duplicate-cn' "$CONFIG"

exit 0
EOF
chmod +x $SCRIPT
}

if [ -f $SCRIPT ]; then
    echo "error: $SCRIPT already exists; requires manual installation"
else
    create_script
    echo 'Done.'
fi
:

Note, the script assumes server #1. Change as necessary.

Enable JFFS scripts in Administration > System, copy/paste the above script into the terminal window of an SSH session, and restart the server or reboot the router.
 
Last edited:

bmn1

Senior Member
If you want to limit each username to one connection (or more precisely, have any new connection attempt w/ the same credentials kick off the current user in favor of the new connection), you can add the following directive to the custom config field of the OpenVPN server.

Code:
username-as-common-name

And remove the duplicate-cn directive w/ a postconf script.

Code:
SCRIPTS_DIR='/jffs/scripts'
SCRIPT="$SCRIPTS_DIR/openvpnserver1.postconf"

mkdir -p $SCRIPTS_DIR

create_script() {
cat << 'EOF' > $SCRIPT
#!/bin/sh
CONFIG=$1
source /usr/sbin/helper.sh

pc_delete 'duplicate-cn' "$CONFIG"

exit 0
EOF
chmod +x $SCRIPT
}

if [ -f $SCRIPT ]; then
    echo "error: $SCRIPT already exists; requires manual installation"
else
    create_script
    echo 'Done.'
fi
:

Note, the script assumes server #1. Change as necessary.

Enable JFFS scripts in Administration > System, copy/paste the above script into the terminal window of an SSH session, and restart the server or reboot the router.

Oh thanks a lot! Will try it out during the weekend.
Is there cron running on merlin wrt so that I could also use cronjobs to enable/disable a user based on time/day? :)
 

eibgrad

Part of the Furniture
Oh thanks a lot! Will try it out during the weekend.
Is there cron running on merlin wrt so that I could also use cronjobs to enable/disable a user based on time/day? :)

There's nothing native to OpenVPN that manages users on a time-scheduled basis. Users have 24/7 access as long as the OpenVPN server is up and running, or until you reconfigure it (add or remove users) and restart it.

That's NOT to say you can't perhaps add some dynamic behavior in some instances. But you need to be precise about what enabling/disabling a user actually means. Are we talking about simply allowing/preventing authentication, or allowing/stopping ALL activity, both current and new?

If it's just preventing additional connections, I suppose you could use a cronjob to update the CCD files of certain users w/ the disable directive when they are NOT allowed access. I haven't actually had the need to do this myself, so I'm just thinking out loud how I might approach it.
 

bmn1

Senior Member
There's nothing native to OpenVPN that manages users on a time-scheduled basis. Users have 24/7 access as long as the OpenVPN server is up and running, or until you reconfigure it (add or remove users) and restart it.

That's NOT to say you can't perhaps add some dynamic behavior in some instances. But you need to be precise about what enabling/disabling a user actually means. Are we talking about simply allowing/preventing authentication, or allowing/stopping ALL activity, both current and new?

If it's just preventing additional connections, I suppose you could use a cronjob to update the CCD files of certain users w/ the disable directive when they are NOT allowed access. I haven't actually had the need to do this myself, so I'm just thinking out loud how I might approach it.

Hmm in the best case scenario I could set the behaviour on a per-user basis.
E.g. have my personal vpn user which runs 24/7 and another one that I can limit e.g. to the weekend only and maybe even during a specific time.
I wouldn't care how that one user gets disabled (password change, config file change, firewall rule to prevent any network access,...).

I use Linux as my main OS myself but I am far from being a "pro".
All I could think of is a cronjob or task via systemctl but no idea if either of them are available on merlin wrt and also where all the required files are located.

Edit:
It seems like OpenVPN can accept "per user" parameters?
Can I somehow set an inactivity threshold per user in the advanced settings then?
Or limit speed per user?
E.g.
--user <USER_OR_GROUP> --key "prop_isec" --value 300 UserPropPut
--user <USER_OR_GROUP> --key "prop_ibytes" --value 100000 UserPropPut
 
Last edited:

Martineau

Part of the Furniture
Oh thanks a lot! Will try it out during the weekend.
Is there cron running on merlin wrt so that I could also use cronjobs to enable/disable a user based on time/day? :)
You can use the following directive in the custom configuration GUI to execute a script whenever an OpenVPN client connects

e.g.
Code:
client-connect /jffs/scripts/VPNClientConnect.sh

Back in 2018 I put together a custom VPNClientConnect.sh script .

to have several pseudo OpenVPN options for controlling OpenVPN client connections in the specific user's CCD file

e.g.
Code:
# NOTE: 'staticip' is NOT an Official (valid) OpenVPN directive, but it is an easy to remember psuedo command short-cut!
staticip 22

# User SGA5 will pass-through the router direct via VPN Client 1 (ovpnc1)
# NOTE: 'passthru' is NOT an Official (valid) OpenVPN directive,
#passthru 1

# User SGA5 cannot override DNS
# NOTE: 'forcedns' is NOT an Official (valid) OpenVPN directive,
forcedns 8.8.4.4

# User SGA5 cannot access WAN only LAN resources
#      Optionally only allow access to specific LAN
# NOTE: 'lanonly' is NOT an Official (valid) OpenVPN directive,
#lanonly
# e.g. both NAS servers, both PS3s and ALL cameras
lanonly 10.88.8.195 10.88.8.197 10.88.8.142-10.88.8.143 10.88.8.126 CAMERAS

# User SGA5 wants to ensure LAN device(s) UP
# NOTE: 'wol' is NOT an Official (valid) OpenVPN directive,
#      e.g. DS-416J NAS
wol 00:11:32:4a:81:c9
#      e.g. DS-110J NAS (00:11:32:07:77:e7)
wol 10.88.8.195

# User SGA5 may ONLY connect from external WAN
# NOTE: 'blocklocal' is NOT an Official (valid) OpenVPN directive,
blocklocal

# User SGA5 may ONLY connect from listed IP addresses - not really useful for mobile devices?
# NOTE: 'allowip' is NOT an Official (valid) OpenVPN directive,
#allowip 1.2.3.4 5.6.7.8 55.55.55.55

# User SGA5 cannot connect from listed IP addresses - not really useful for mobile devices?
# NOTE: 'blockip' is NOT an Official (valid) OpenVPN directive,
#blockip 4.3.2.1 8.7.6.5
#blockip 213.205.198.18

# Permitted access hours
# NOTE: 'restrictperiod' is NOT an Official (valid) OpenVPN directive,
#allowperiod 08:59-17:00

# Restricted access hours
# NOTE: 'restrictperiod' is NOT an Official (valid) OpenVPN directive,
restrictperiod 00:59-05:00

# Limit Session to hh:mm:ss
# NOTE: 'limitsession' is NOT a valid OpenVPN directive,
limitsession 01:00:00

# Limit Data Received to n[GMK]
# NOTE: 'limitRX' is NOT a valid OpenVPN directive,
limitRX 10M

# Limit Data Transmitted to n[GMK]
# NOTE: 'limitTX' is NOT a valid OpenVPN directive,
limitTX 10M


Code:
<snip>

    # Was the 'restrictperiod' directive found? NOTE use 09:59-11:00 for actual 1 hour restriction 10am 'til 11am
    if [ -n "$RESTRICTED_PERIODS" ];then
        RESTRICTED=0
        RESTRICTED_PERIODS=$(echo $RESTRICTED_PERIODS | tr ',' ' ')
        for PERIOD in $RESTRICTED_PERIODS
            do
                FROM=$(echo $PERIOD | cut -d'-' -f1)
                TO=$(echo $PERIOD | cut -d'-' -f2)
                #Say "***DEBUG PERIOD="$PERIOD "FROM=>"$FROM"< TO >"$TO"<"
                if [ "$(HH_MM_in_Range "$FROM" "$TO")" == "Y" ];then
                    RESTRICTED=1
                    break
                fi
            done
        if [ $RESTRICTED -eq 1 ];then
            STATUS="FAIL"                    #Refuse the connection
            FAIL_REASON=95
            Say "***ERROR VPN Server" $VPN_SERVER_ID "Client I/P" $trusted_ip "address is PERIOD restricted $PERIOD - CONNECTION REFUSED rc="$FAIL_REASON
        else
            Say "VPN Server" $VPN_SERVER_ID "Client I/P" $trusted_ip "address is not PERIOD restricted("$RESTRICTED_PERIODS")"
        fi
    fi

You could extend the process to periodically (cron) check the connected OpenVPN clients and kick them off.
Code:
 ./OpenVPNServerStatus.sh limit

    There are 1 clients connected to OpenVPN Server 1 (Port nnnn, IP Pool:10.8.0.0)

        HP-Envy13/10.8.0.3 (nnn.27.128.46:52052) since Sat-Mar-26-17:16:09-2022 (Duration 21:16:12) Data Transfer:Rx=5.66 MiB,Tx=44.16 MiB

        Session duration 21:16:12 EXCEEDS 01:00:00 session limit!

        Transmitted Data (Tx) 44.16 MiB EXCEEDS 2.00 MiB session limit!

    There are 0 clients connected to OpenVPN Server 2
 
Last edited:

eibgrad

Part of the Furniture
Hmm in the best case scenario I could set the behaviour on a per-user basis.
E.g. have my personal vpn user which runs 24/7 and another one that I can limit e.g. to the weekend only and maybe even during a specific time.
I wouldn't care how that one user gets disabled (password change, config file change, firewall rule to prevent any network access,...).

I use Linux as my main OS myself but I am far from being a "pro".
All I could think of is a cronjob or task via systemctl but no idea if either of them are available on merlin wrt and also where all the required files are located.

Edit:
It seems like OpenVPN can accept "per user" parameters?
Can I somehow set an inactivity threshold per user in the advanced settings then?
Or limit speed per user?
E.g.
--user <USER_OR_GROUP> --key "prop_isec" --value 300 UserPropPut
--user <USER_OR_GROUP> --key "prop_ibytes" --value 100000 UserPropPut

You're jumping all over the place here when it comes to what you want. Now limits on bytes? Speed?

The --user directive is NOT a per-user setting. It's a way to drop privileges on the user that started the OpenVPN process itself. From the OpenVPN documentation ...

--user user Change the user ID of the OpenVPN process to user after initialization, dropping privileges in the process. This option is useful to protect the system in the event that some hostile party was able to gain control of an OpenVPN session. Though OpenVPN's security features make this unlikely, it is provided as a second line of defense.

By setting user to nobody or somebody similarly unprivileged, the hostile party would be limited in what damage they could cause. Of course once you take away privileges, you cannot return them to an OpenVPN session. This means, for example, that if you want to reset an OpenVPN daemon with a SIGUSR1 signal (for example in response to a DHCP reset), you should make use of one or more of the --persist options to ensure that OpenVPN doesn't need to execute any privileged operations in order to restart (such as re-reading key files or running ifconfig on the TUN device).


As I said before, you can control per-user settings by creating a file by the same name as the username in the CCD directory (assuming you added the username-as-common-name directive). If you're using Manage Client-Specific Options on the OpenVPN server, it's already there. And among the directives you can add, is the disable directive. The user's CCD file is examined each time a connection is made so OpenVPN can customize the session. And presumably you could then use a cronjob to update that file on a scheduled basis.
 

Sign Up For SNBForums Daily Digest

Get an update of what's new every day delivered to your mailbox. Sign up here!
Top