Because the world continues to work from home this year, I’ve had to configure Cisco AnyConnect VPNs on ASA firewalls for clients a few times. Unfortunately, the documentation from Cisco is extremely confusing, and I’ve seen a lot of organizations that do it wrong (by which I mean insecurely). The process itself is quite simple, though, so let’s go through the steps you’ll need to configure Cisco AnyConnect for your VPN.

1. Configure AAA authentication

The first thing to configure is AAA authentication. My preference is to use RADIUS for authentication and authorization, but there are other options such as LDAP. The configuration is similar:

aaa-server MYRADIUS protocol radius
aaa-server MYRADIUS (INSIDE) host
 key ****

This configuration fragment says that I have a RADIUS server inside my network with IP address, which I refer to by the tag “MYRADIUS” in the ASA configuration. It’s accessed through the ASA interface that I called “INSIDE” in the interface configuration.

2. Define VPN protocols

When users connect their VPN, they’ll need an IP address for the VPN session. This is the address that will appear inside the corporate network for this user. It has nothing to do with the user’s public IP address or any address they might have inside their home network. It’s just used on the inside of the network after the remote user’s traffic has passed through the ASA.

ip local pool ANYCONNECT_POOL1 mask
ip local pool ANYCONNECT_POOL2 mask

I defined two pools here because I plan to have multiple tunnel groups later.

3. Configure tunnel groups

Next, I configure my tunnel groups. I’ll create two such groups for reasons I’ll explain later.

tunnel-group ANYCONN_1 type remote-access
tunnel-group ANYCONN_1 type general-attributes
 address-pool ANYCONNECT_POOL1 
 authentication-server-group MYRADIUS
 default-group-policy NOACCESS
tunnel-group ANYCONN_1 webvpn-attributes
 group-alias EMPLOYEES enable
tunnel-group ANYCONN_2 type remote-access
tunnel-group ANYCONN_2 type general-attributes
 address-pool ANYCONNECT_POOL2
 authentication-server-group MYRADIUS
 default-group-policy NOACCESS
tunnel-group ANYCONN_2 webvpn-attributes
 group-alias VENDORS enable

This creates two tunnel groups called ANYCONN_1 and ANYCONN_2. I’ve assigned the first pool to the first tunnel group and the second pool to the second.

Here I’m using the “group-alias” command, which creates a drop-down box on the AnyConnect client on the user’s PC. Users will see they can select either Employees or Vendors as options. The configuration we’re creating will allow people in the first group to connect only to the first tunnel group and users in the second group only to the second.

Note that the “authentication-server-group” command could be different in these two tunnel groups. So I could send my employees to one RADIUS server (perhaps one that’s integrated with my LDAP, or equivalently, I could use LDAP natively on the firewall) and the vendors to a different one.

4. Set group policies

Now we need group policies. In fact, we need three of them. We need a group policy for employees and a second one for vendors. The third policy is for anybody who somehow passed their authentication but failed their authorization. That is, they had valid credentials for logging in but they aren’t authorized to use the VPN.

The main reason this could happen is if they’ve simply selected the wrong profile. But it’s also possible I could have people who simply aren’t authorized to use the VPN at all, even though they have legitimate credentials. This could happen because the same authentication system is used for many things.

group-policy STAFF_VPN_GROUP internal
group-policy STAFF_VPN_GROUP attributes
 vpn-tunnel-protocol ssl-client
 vpn-filter value STAFF_VPN_ACL
group-policy VENDOR_VPN_GROUP internal
group-policy VENDOR_VPN_GROUP attributes
 vpn-tunnel-protocol ssl-client
 vpn-filter value VENDOR_VPN_ACL
group-policy NOACCESS internal
group-policy NOACCESS attributes
 vpn-tunnel-protocol ssl-client
 vpn-simultaneous-logins 0

Where do these names come from? This is where things get a little bit confusing, so bear with me. The group policy names, STAFF_VPN_GROUP and VENDOR_VPN_GROUP, are values supplied by either the RADIUS or LDAP server. The server must be configured so that, upon successful authentication, it hands back these values in its IETF type 25 field, also called Class. And it must be in a specific format: OU=STAFF_VPN_GROUP; (with the semicolon).

One other important little bit of configuration that I want to mention is the “vpn-filter” command. This applies a special ACL (access control list) to these users and allows us to restrict what they can and can’t access. For example, if I wanted to allow the employee group to access anything in the corporate network, but to restrict the vendors to only access a particular subnet, I could do this:

access-list STAFF_VPN_ACL extended permit ip any any
access-list VENDOR_VPN_ACL extended permit ip any

5. Apply the configuration

Finally, we need to apply the configuration to the OUTSIDE interface of the firewall:

 enable OUTSIDE
 anyconnect enable
 tunnel-group-list enable

Authenticating logic flow

Let’s review the logical flow in this configuration example.

First, the user opens their AnyConnect client. They connect to the hostname (or IP address) of our ASA’s outside interface. As soon as they connect, they get a login screen in which they can pick either Employees or Vendors from a drop-down menu. They enter their user ID and login credentials. So far we’re just in the tunnel group section of the configuration.

Then the login credentials are sent to the authentication server group configured for this tunnel group. If the authentication is successful, the RADIUS server will return a value, RADIUS attribute IETF-25 (also called Class). That value includes the name of the group policy this user should be in.

At this point, we could have several different group policies for different groups of users, all of whom connected using the same drop-down menu. We could assign a different ACL to each of them to restrict what they could access depending on their group. This mechanism can only select one group policy. If you want a user to be in multiple groups, you’ll need to get creative with your tunnel groups.

In the tunnel group configuration, we’ve defined a catchall default group policy that’s called NOACCESS. If the RADIUS server sends back something the ASA doesn’t understand, or perhaps nothing at all, then the user gets assigned to this group policy. For the sake of security, we want to deny access in these cases. We do this by making this NOACCESS group policy allow 0 simultaneous logins for each user ID:

vpn-simultaneous-logins 0

For those users who successfully gain access, we can apply an ACL using the “vpn-filter” command. This is an ACL applied on the firewall itself for connections heading to the destinations. So we put the specifically allowed or denied addresses in the “destination” part of the ACL:

access-list  extended permit ip any

The biggest mistake I’ve seen in AnyConnect configurations is to set the default group policy in the tunnel group to allow access. You should always deny by default.

Follow this simple workflow, and you should have a straightforward, easily adaptable process to configure your Cisco AnyConnect VPN.

Looking to learn more about VPNs? You might be interested in these related articles: