Updated on 11-06-2023.
Virtual Private Networks
I've been supporting or implementing VPN solutions since 2013, which hits the 10-year mark. I've seen several different vendors like Palo Alto, Juniper, CheckPoint and Citrix. This post is not a comparison between vendors nor is between modern implementations as the ZTNA and the SSL VPN, but a review of rather intresting configuration on the latter.
Our Case Study
We need to cover the following check points in our implementation:
- Inspection and sanitization of VPN Machines
This is generally Machine Level Authentication or Machine SSL Tunnel. Performing End Point Analysis scan requiering device certificate and establishing Machine Level Tunnel placing the machine into specific VLAN. The machine will have network connectivity so installed security software can report internally whenever the machine is on. This will make the machine also accessible for any Support Agents.
- Network Identity Aware Access
Upon User Level Authentication (User Tunnel Establishment) acess could be provided based on EPA scans, device, location or Group Membership for example. This is Contextual Access, different users, based on real-time security context should receive different level of network access.
First let's have a look how the AlwaysON VPN works.
The AlwaysOn VPN has two stages:
- Machine Level Tunnel
- User Level Tunnel
Apart from the two stages the AlwaysOn requires configuration on two sides:
- Client Registry Config
- NetScaler VPN Config
In part 1 of these VPN series we'll discuss only the Machine Tunnel and the required configuration there. Simplified flow of machine SSL VPN Tunnel:
The AlwaysON VPN establishes connection on machine power on and tunnel remains active until machine is powered off. There are many advantages of such configuration. One is Windows machine becomes a part of the corporate intranet even before users log in. We'll refer to this subnet range as inspection VLAN. This VLAN is designated for machine security checks and tools providing feedback to our corporate security monitoring (This is not a quarantine VLAN).
The NetScaler will be responsible for distributing intranet IPs upon successful authentication. The authentication mechanism is by providing device certificate (the machine on itself can hardly provide anything else).
Below are some useful links and information not necessarily related to the current setup (feel free to skip and return to it if needed):
- WFP Driver
By default SAC uses the DNE drivers. I would recommend switching to the WFP driver & API of Windows. (DNE is considered legacy). To use the WFP driver for tunneling, admins must create the below registry entry (reboot required):
REG_PATH - HKEY_LOCAL_MACHINE\SOFTWARE\Citrix\Secure Access Client REG_TYPE - REG_DWORD REG_NAME - EnableWFP REG_VALUE – Set value to 1 to use WFP and 0 to use DNE (by default DNE is enabled if this registry value is not present or is set to 0)
- AlwaysOn Profile, Proxy Settings & Client Control
All these settings are quite well documented in Citrix docs Client control settings as location based VPN is not covered in the article.
- NetScaler VPN Client Registry Keys
These will be needed for the client side configuration (pushed via GPO or configured upon installation with SCCM) - Citrix docs
The most important keys that are not controlled on server side are noted below:
Client Side Registry Keys
|Registry key||Type||Values and description|
|AlwaysOnService||REG_DWORD||1 = Establish machine level tunnel but not user level tunnel. 2 = Establish machine level tunnel and user level tunnel.|
|AlwaysOnURL||REG_SZ||URL of the Citrix Gateway virtual server the user wants to connect to. Example: https://xyz.companyDomain.com|
|suffixList||REG_SZ||Comma separated list of intranet domains. Used when location detection is enabled.|
|AlwaysOnAllowlist||REG_SZ||Semicolon separated list of IP addresses or FQDNs to be whitelisted by the driver in Always On strict mode.|
|userCertCAList||REG_SZ||Used in the context of the Always On service where a customer can specify the list of CAs to choose the client certificate from.|
|Connected||REG_DWORD||On successful connection this key is set to 1 and else set to 0. This key is used internally. Users must not modify this key.|
|NoDHCPRoute||REG_DWORD||If set to 1, the DHCP server route is not added (it will add route towards the public IP of the NetScaler VPN vServer).|
|secureDNSUpdate||REG_DWORD||0 = The VPN plug-in tries the unsecure DNS update only. 1 = The VPN plug-in tries the unsecure DNS update first. If the unsecure DNS update fails, the VPN plug-in then tries the secure DNS update. This is the default behavior starting from the 22.214.171.124 Windows plug-in build. 2 = The VPN plug-in tries only the secure DNS update.|
The NetScaler configuration side consists of the following components:
- VPN vServer
- AAA vServer
- nFactor Authentication Policy Flow
- Authorization Policy
- Intranet IPs (DHCP range for IIP - Tunnel IP)
- AlwaysOn VPN Profile
- VPN Session Policy
- Machine AAA Group
As we mentioned we have Machine inspection VLAN. This Machine Level Tunnel vlan (1616) should differ from the User Level Tunnel. We must assign different IIP ranges for Computers and Users. This could be segregated further with User Groups if required.
The two tunnels does not co-exist. Once the user logs in the tunnel will go to User Mode. The Machine Tunnel will be replaced by the User Tunnel.
There is nothing special in the VPN vServer & AAA vServer configuration. We can go to the nFactor Authentication Policy Flow. The nFactor Flow does not require any Login Schema (at least for the Machine Tunnel). Let's create the AlwaysOn Authentication Policy and bind it to the AAA vServer:
add authentication epaAction EPA_ACT_AON_CERT -csecexpr "sys.client_expr(\"device-cert_0_0\")" add authentication Policy EPA_POL_AON_CERT -rule is_aoservice -action EPA_ACT_AON_CERT
The expression "sys.client_expr("device-cert_0_0")" is device certificate EPA action. Notice there is no CA filtering like issuer. You can filter that with client registry "userCertCAList". If issuer is not filtered and there is more than one device certificate, the VPN Tunnel might fail to establish. The expression "is_aoservice" means "HTTP.REQ.HEADER("User-Agent").CONTAINS("AO-Service")".
As noted in the Citrix docs Machine level tunnel uses certificate-based authentication and the session that is created has the certificate’s common name as a user name. So, if device certificates have unique common names, different machines’ sessions have different user name and thus different IIPs. Ensure that you generate a device certificate with unique names. Ideally, you must use machine names as the device certificate’s common name.
Make sure certificate’s common name is the Machine's name. Failing to do so has several implications:
- All machines will establish their tunnel with username "anonymous".
Every user logon (Machine or ADUser) caches the IIP that has received until range exhaustion (this cache is on NetScaler side). The "anonymous" user will take same IP every time, hence only single machine tunnel will be established.
I would actually encourage creation of DENY rule for "anonymous" username even after successful authentication.
- The Citrix Secure Access client sends DNS updates upon tunnel establishment.
If all machines use same user and share same IP your DNS records will start overwriting the data. Usually the agent will unregister the machine from the DNS upon tunnel dissolution, but when sharing the IP for the machine tunnel the agent will not have the time to do so.
Below you can see the Common Name in my Machine Certificate (You can edit your CA template so the common name reflects the actual machine name).
Afterwards you'll be able to see session in the NetScaler with the correct machine name.
Next thing are the IIPs. At this moment the Machine is actually treated as a normal user. You have several options for assigning IIP ranges:
- On the vServer
- On AAA Group
- On AAA Users (out of the question.)
Remember we need to assign different IIP ranges for machines and users.
vServer level could work in the following format:
- vServer = Machine IIP
- AAA Group = User IIP
AAA Group settings takes precedence! What if we have several types of machines? We do not want to place machines manually into NetScaler groups, correct?
How to dynamically categorize the machines and assign VLAN upon Machine Level Tunnel establishment?
We could do contextual access (EPA) with different nFactor flows ending in different default group that has different IIP assignment. Would work, but also would overcomplicate things.
LDAP Search for Machines
We currently have a signle action checking for device certificate. We can extend the authentication flow with next policy label & ldap search. The LDAP Filters are valid for machines as well as for users. Since we do not have any password we'll need to disable password verification on the LDAP action, but we can quiery the existance of the machine and any additional info about it. We query from the LDAP server the machine group membership and assign the IIP range to the group.
Let's do that!
Our Authentication Flow will look like this:
Find an attribute of your machine AD object that macthes the Common Name (Username) from the device certificate. We're going to query it in our LDAP request.
I'm using 'name' attribute, but it could be very well sAMAccountName or dNSHostName. Yes, machines do have sAMAccountNames. You can test the query with the below powershell command:
Get-ADComputer -Server "fqdn.domain.controller:3269" -LDAPFilter '(&(name=CTX-XD03)(objectClass=*))'
You'll need a Login Schema for this one. You need it, because the NetScaler does not pick up correctly the username after Cert validation and authentication.
add authentication loginSchema AON_NO_LSCHEMA -authenticationSchema noschema -userExpression AAA.USER.NAME add authentication loginSchemaPolicy AAA_LSP_AON_LDAP -rule true -action AON_NO_LSCHEMA
Next create your LDAP Action, LDAP Policy, put it in a Policy Label and Configure it as Next Factor:
add authentication policylabel AAA_LBL_AON_MACHINE_LDAP -loginSchema AON_NO_LSCHEMA add authentication ldapAction LDAP_ACT_GC_VPN_MACHINES -serverIP xx.xx.xx.xx -serverPort 3269 -authTimeout 4 -ldapBase "DC=kernetix,DC=local" -ldapBindDn <SERVICE_ACCOUNT> -ldapBindDnPassword ******** -ldapLoginName name -authentication DISABLED -secType SSL -groupAttrName memberOf -subAttributeName cn add authentication Policy AAA_LDAP_POL_AON_LDAP_MACHINE -rule true -action LDAP_ACT_GC_VPN_MACHINES bind authentication policylabel AAA_LBL_AON_MACHINE_LDAP -policyName AAA_LDAP_POL_AON_LDAP_MACHINE -priority 100 -gotoPriorityExpression NEXT bind authentication vserver AAA_VS_AON_SERVER -policy EPA_POL_AON_CERT -priority 100 -nextFactor AAA_LBL_AON_MACHINE_LDAP -gotoPriorityExpression NEXT
Main things from the above LDAP CLI:
- -ldapLoginName name
- -authentication DISABLED
- -groupAttrName memberOf -subAttributeName cn
Assing IIP range, intranet applications and authorization policies to any domain extracted group. Don't forget to bind your CA certificate to the AAA vServer for cert validation and you have your inspection VLAN ready. Tomorrow you can easily introduce another subnet for another subset of machines.
With this setup you have IIP ranges based on Domain Computers' group membership. Although you can assign Network access with NetScaler rules, you certianly do have firewall behind it. This firewall would have rules for your IIP range assignment. This introduces better segregation on IIP subnets from network security perspective.
Part 2 will cover user-aware firewall access after User Level Tunnel establishment.
Thank you for reading!