Limit one connection to the VPN server per user

Hello all,

    I thought it would be worthwhile to blog a post specifically on this topic. I've seen quite a number of people having this requirement to limit the number of VPN connections that can be made to the VPN server using a particular username to just one. And I did take this one as the example program in my earlier post about developing a RAS administration DLL. However, I thought it would be good to elaborate a little more on what the DLL actually does.

You can refer to the code (attached as a rtf file) in this post --> https://blogs.technet.com/rrasblog/archive/2007/12/20/steps-to-develop-a-ras-administration-dll-using-visual-studio.aspx

Among all the callback functions that we have implemented, the two important ones to consider are MprAdminConnectionHangupNotification2 and MprAdminAcceptNewConnection2. These are the functions where we do processing when there is a client connection/disconnection coming.

Let's the take MprAdminAcceptNewConnection2 first. This function has the below prototype

BOOL WINAPI

MprAdminAcceptNewConnection2(RAS_CONNECTION_0 * pRasConnection0,

RAS_CONNECTION_1 * pRasConnection1,

RAS_CONNECTION_2 * pRasConnection2)

When there is a connection coming from the client, this callback is called with the parameters populated. Let's use the pRasConnection2 parameter for our processing. This structure RAS_CONNECTION_2 has the following format:

typedef struct _RAS_CONNECTION_2 {
HANDLE hConnection;
WCHAR wszUserName[UNLEN + 1];
ROUTER_INTERFACE_TYPE dwInterfaceType;
GUID guid;
PPP_INFO_2 PppInfo2;

} RAS_CONNECTION_2,
*PRAS_CONNECTION_2;

The wszUserName parameter here is the one that is of interest to us here.

This contains the name of the user who is connecting. We want to ensure that if there is already an active connection on this server from this user, this connection should be refused. So we need to do some book-keeping to keep track of the users who have an active connection on the server currently.

For this we maintain a linked list in this example. When a client connects, we check if the username already exists in the list. If yes, we reject the connection, else we allow the connection to go through and add the username to the list.

When a connection is disconnected, the callback MprAdminConnectionHangupNotification2 is called. This function's prototype is as below:

VOID WINAPI

MprAdminConnectionHangupNotification2(RAS_CONNECTION_0 * pRasConnection0,

RAS_CONNECTION_1 * pRasConnection1,

RAS_CONNECTION_2 * pRasConnection2)

Again here, we get the username from the pRasConnection2 structure and delete that user from the list.

Coming to the implementation in detail, you can see that we are keeping track of the user's security identifiers (SID) rather than the name itself. This is because a username can be represented in many ways - DOMAINUSER, USER@DOMAIN etc. However, the SID is the same across. So we convert the username to user SID and store it in the list that we maintain.

Apart from this, during the DLL initialization, we also create a log file for debugging.

The linked list is just to explain the logic of how this is accomplished using administration DLL. However, we can use better ways of storing this information so that a look up is easy thereby ensuring lesser delay during connection.

Hope this helps.

Let us know if you would like to hear about something specific. Drop us a line at rrasblog@online.microsoft.com **

** Remove the online from the email ID to actually mail us.

Janani Vasudevan
Software Design Engineer/Test
RRAS, Windows Enterprise Networking

[This posting is provided "AS IS" with no warranties, and confers no rights.]