SSL VPN single sign-on using LDAP-integrated certificates

Facebooktwittergoogle_plusredditpinterestlinkedinFacebooktwittergoogle_plusredditpinterestlinkedin

In this recipe, you will configure an SSL VPN tunnel that requires users to authenticate solely with a certificate. We will configure a PKI peer object in order to search our LDAP using the certificate’s UserPrincipalName in order to determine group memberships of the user. We will then be able to base our SSL VPN policies on LDAP group membership, without the need to explicitly request the user’s LDAP credentials during the client VPN session establishment.

This recipe was tested with a Windows 2012R2 Active Directory acting as both the user certificate issuer, the certificate authority and the LDAP server.

While it is possible to force explicit LDAP authentication for the user during VPN establishment, this cookbook article’s goal is to offer a true “single-sign on” approach in which we use pre-established credentials (the user’s issued certificate) while maintaining the ability to know what Active Directory groups the connecting user belongs to based on the username found in the certificate.

Note that this article skims over the basics of SSL VPN configuration – refer to other more basic articles if you need a refresher on the basic mechanics related to SSL VPN or other features found in this article.

1. Windows 10 certificate

While it is not the goal of this article to cover Microsoft’s Certificate Authority and its operation, suffice to note that our test user (user1) has been issued a standard “User” template certificate for which he has enrolment permissions for.

 

 

In our case, we duplicated the standard “User” template and made certain that we have the User Principal Name included in the subject name of the issued certificate – this is the user field we will be using to search LDAP during the connection attempt.

For reference, UPN designates the format “user@domain”, with domain being the Active Directory domain.

2. Requesting and installing a server certificate for FortiOS

Using our Microsoft Certificate Authority’s web interface, we request a “Web Server” type certificate and use the CSR generated from FortiOS’s GUI to obtain a trusted certificate. Do note that “trusted” in this example is limited in scope to the organization’s assets – you would use a public CA to generate a certificate for FortiOS if you expect non-corporate assets to connect to the SSL VPN as those are unlikely to trust the Active Directory CA we are using in our example.

While the below process goes through the manual certificate request process, FortiOS is SCEP capable which can be used to automate the certificate request process with a SCEP-compliant CA server (Microsoft CA does support SCEP).

Export the CA certificate from your CA using the available methods. In our case, we use the Windows CA web interface to download our CA cert in BASE64 format.

Go to System > Certificates and select Import > CA Certificate.

Select the Microsoft CA certificate file.

 

The CA certificate now appears in the list of Certificates. Note that it is named “G_CA_Cert_1″ – keep that in mind as we refer to this later in the article.

Next, we generate a CSR on FortiOS which we will use to obtain a signed certificate from our CA, again in our case the Microsoft CA. The domain name used should match the domain name users will be connecting to using FortiClient and is generally what resolves to the IP of the interface listening for SSL VPN.

Download the generated CSR, which is a text file containing the BASE64 certificate request.

We again use our Microsoft CA web interface to submit our CSR and obtain a certificate of type “Web Server”.

Download the resulting signed request in BASE64 format.

Finally, import that signed request as a local certificate on FortiOS to finalize our SSL VPN server certificate. 

Our request is complete and our certificate is now usable. We will use this certificate later in our SSL VPN configuration.

3. Configuring LDAP, PKI and a group

As we will be validating incoming VPN requests using the UserPrincipalName found in the trusted certificates used by clients, we need to define our LDAP server.

Go to User & Device > LDAP Servers and create a new LDAP server definition.

This definition is common, except for the fact that we will be using UserPrincipalName as our Common Name Identifier – the UPN field is what we are extracting from the certificates and need to match to locate users in LDAP.

 

Next, head to the CLI. This is the only part of this article that requires a CLI definition.

Create a PKI “peer” object as shown. This is a relatively static object which will not require frequent visits to the CLI.

 

config user peer
    edit "FORTIQC_CERTS"
        set ca "G_CA_Cert_1"
        set ldap-server "FORTIQC"
        set ldap-mode principal-name
    next
end

A PKI “peer” object is created in order to instruct FortiOS to match an incoming certificate’s UserPrincipalName to a target LDAP server object, providing that certificate is signed by the designated CA and is valid. You will recognize the G_CA_Cert_1 as the name of the CA certificate we imported earlier.

The “ldap-mode” parameter is important as it dictates that authentication is not explicit (the user does not need to pass a username and password) and instead is based on validating that the UserPrincipalName found in the certificate does exist. We will extend  this in a moment to also request that the user be a member of a specific LDAP group.

4. Configuring a group

 

Next, we configure the group object that will assemble our previously configured LDAP and PKI objects together.

Go to User & Device > User groups and create a new group.

Add the PKI peer object previously created as a local member of the group.

Next add a remote group on the LDAP server and select the group of interest you need these users to be members of using the LDAP browser window.

 

 What just happened here?

This configuration is counter-intuitive at first glance as matching against a group object generally means matching at least one of its members.

However when using a PKI object in the “member” field, the group object’s behaviour change and instead, the group will only match if the PKI object is true (the certificate is valid and trusted and the user exists in LDAP) AND the group memberships obtained from LDAP for the user also match one of the remote LDAP groups defined.

We will look at connection debug information later to see this process happening.

5. Configuring the SSL VPN settings

Go to VPN > SSL-VPN Settings.

Ensure that the “Require Client Certificate” option is checked.

Select the certificate we generated earlier for FortiOS.

If needed, map our newly created group to a specific portal definition. This is only necessary if the default portal (designated by “All Other Users/Groups” entry) is not the right one. In our case, it wasn’t necessary to define the group to portal mapping as the default portal was the same.

 

6. Configuring the policy

Finally, under Policy & Objects > IPv4 Policy create or modify your existing SSL VPN policies to incorporate your new group.

 

 

7. Results

 

Our FortiClient is configured with the target hostname and local certificate issued to the user. Connecting to the VPN requires neither username or password – only the user’s certificate.

 

 

Lets look at the output of “diag debug app fnbamd -1” while the user connects. We have shortened the output of the diag in a few locations to focus on the important parts.

We can see the lookups being done to find the group memberships (3 groups total) of the user and that the correct group being found results in a match.

We can also use “diag firewall auth list” to validate that a firewall user entry exists for our SSLVPN user and is part of the right groups.

As a reference, fnbamd is short for “Fortinet Non-Blocking Authentication Management Daemon” and is the process responsible for the vast majority of explicit authentication duties found in FortiOS.

MN140D-1 (root) # diag debug reset
diag debug
MN140D-1 (root) # diag debug app fnbamd -1
Debug messages will be on for 30 minutes.

[1590] cert_check_group_list-checking group type 1 group name 'FORTIQC_PKI_GrpCertAuth'
[1425] quick_check_peer-Cert subject 'CN = user1'
[1483] check_add_peer-check peer user 'FORTIQC_CERTS' in group 'FORTIQC_PKI_GrpCertAuth', result is 4
[1614] cert_check_group_list-Status pending for group 'FORTIQC_PKI_GrpCertAuth'
[804] resolve_ldap_FQDN-Resolved address 192.168.129.40, result 192.168.129.40
[1185] fnbamd_ldap_init-search filter is: (&(userPrincipalName=user1@fortiqc.local)
    (!(UserAccountControl:1.2.840.113556.1.4.803:=2)))

[1189] fnbamd_ldap_init-search base is: dc=fortiqc,dc=local

[258] start_search_dn-base:'dc=fortiqc,dc=local' filter:(&(userPrincipalName=user1@fortiqc.local)
    (!(UserAccountControl:1.2.840.113556.1.4.803:=2)))
...
[306] get_all_dn-Found 1 DN's
[556] start_user_attrs_lookup-Adding attr 'memberOf'
[577] start_user_attrs_lookup-base:'CN=user1,CN=Users,DC=fortiqc,DC=local' filter:cn=*
...
[1851] fnbamd_ldap_get_result-Going to DONE state res=0
[141] __ldap_copy_grp_list-copied CN=GrpCertAuth,CN=Users,DC=fortiqc,DC=local
[141] __ldap_copy_grp_list-copied CN=testgroup,CN=Users,DC=fortiqc,DC=local
[141] __ldap_copy_grp_list-copied CN=Domain Users,CN=Users,DC=fortiqc,DC=local
[1845] __match_ldap_group-Matching server 'FORTIQC' - 'FORTIQC'
[1853] __match_ldap_group-Matching group 
       'CN=GrpCertAuth,CN=Users,DC=fortiqc,DC=local' - 'CN=GrpCertAuth,CN=Users,DC=fortiqc,DC=local'
[1953] fnbamd_auth_cert_poll-Result for ldap svr[0] '192.168.129.40' is SUCCESS
[1959] fnbamd_auth_cert_poll-matched user 'FORTIQC_CERTS', matched group 'FORTIQC_PKI_GrpCertAuth'
...


MN140D-1 (root) # diag firewall auth list

10.212.134.200, cn=user1, FORTIQC_PKI_GrpCertAuth
	type: fw, id: 0, duration: 181, idled: 0
	expire: 28797, allow-idle: 28797
	flag(a0): idle sslvpn
	packets: in 1427 out 1505, bytes: in 291364 out 359030
	group_id: 2
	group_name: FORTIQC_PKI_GrpCertAuth

----- 1 listed, 0 filtered ------


 

 

8. Logs

Finally, our logs show our LDAP user’s traffic:

9. Summary

This article presented a technique allowing for “credential-less” VPN connectivity using certificates while maintaining the ability to authorize access with policies that are based on LDAP groups. As a side note, this technique may not be suitable to the levels of security requirements of all environments as it foregoes explicit authentication in addition to PKI authentication. Your organization’s security versus ease-of-use requirements ultimately dictate the requirements.

 

  • Was this helpful?
  • Yes   No
  • Jael

    Hello, I have a question. I want to do this in my company but I need that the user introduce his user and password on the client too.
    That way I can achieve a 2 factor authentication: the username/password, and the cert on the device.

    • Mathieu Nantel

      The setting called two-factor under the “config user peer” object definition may very well meet your requirements:

      MN140D-1 (FORTIQC_CERTS) # set
      mandatory-ca-verify Enable/disable mandatory CA verify.
      ca Peer certificate CA (CA name in local).
      subject Peer certificate name constraints.
      cn Peer certificate common name.
      cn-type Peer certificate common name type.
      ldap-server LDAP server for access rights check.
      ldap-mode Peer LDAP mode.
      ocsp-override-server OSCP server.
      two-factor Enable/disable 2-factor authentication (certificate + password).

      • Jael

        Thanks,

  • Viet Le

    Hi Matt

    In Windows 10 cert section, do you have KB that shows how to duplicate User certificate template?

    I am trying this cookbook but get stuck at making the right user certs.

    Thanks, Viet

  • Steve Furniss

    I though that you might like to know that we have made a slight modification to step 3. We have created a pki peer for each of our users and added the subject to the configuration.

    config user peer
    edit “test1”
    set mandatory-ca-verify enable
    set ca “G_CA_Cert_1”
    set subject “test1@somedomain.co.uk”
    set ldap-server “FORTIQC”
    set ldap-mode principal-name
    next
    end

    config user peer
    edit “test2”
    set mandatory-ca-verify enable
    set ca “G_CA_Cert_1”
    set subject “test2@somedomain.co.uk”
    set ldap-server “FORTIQC”
    set ldap-mode principal-name
    next
    end

    The reason for doing this is that you can only see the one connection for the one pki peer…. if you have multiple users you are unable to differentiate between them. By doing it this way you get a match with the subject in the certificate to an individual pki peer.

    • Mathieu Nantel

      Hi Steve,
      I am surprised you would not be able to see multiple distinct connections for each user. I’ll proceed to retest this ASAP, but the presumption based on my screenshots above was that you would see distinct SSL VPN connections in terms of authentication, with the cn=X user extracted. The method you are using has the downside of requiring individual user provisioning on the unit which is OK for some environment but too operationally heavy for the majority. Could you provide more detail as to what you meant by “only see one connection” ?

  • Steve Furniss

    Can the SSL VPN be automatically initiated? Is there a way to get the VPN to connect when the device is not connected to the Corporate LAN?

    • Mathieu Nantel

      FortiClient has auto-connect at logon capabilities that can be enabled, if your intention is to support automatic connection at logon.

      • Steve Furniss

        We have managed to get the auto-connect to work when “Off-Net”, however if the user is still logged on to the device and then returns back on the corporate LAN, it appears that as the VPN is in a re-connect cycle, it does not check if it is back on the LAN and continues to try and connect.
        I currently have a case logged with support regarding this.

        • Mathieu Nantel

          Would you let me know what versions of FOS and FCT you are using for your particular case? Also, what on-net detection technique are you using?

  • Steve Furniss

    Can this be modified for IPSec VPN as well? if so can you provide steps?

    • Mathieu Nantel

      I have not tested it, but at first glance I presume it should work with a common X509-based dialup VPN configuration. Reusing the above object names, it would look like:

      config vpn ipsec phase1-interface
      edit “dialup”
      set type dynamic
      set interface “wan1”
      set authmethod signature
      set mode-cfg enable
      set proposal aes128-sha1
      set certificate “FORTIQC_Cert”
      set peer “FORTIQC_CERTS”
      set ipv4-start-ip 10.10.10.1
      set ipv4-end-ip 10.10.10.10
      next
      end

      • Steve Furniss

        So far we have been unable to get this to work. Thanks for your suggestion though.