Mac Deryng

WN Blog 014 – Cisco Catalyst 9800 – Configuration Guide (FlexConnect)

It’s simple, right? Sure! Took me a while to figure that one out.

Our goal in this post is to demo Cisco Catalyst 9800 WLC FlexConnect Configuration.

It’s assumed you’re familiar with all C9800 solution building blocks (we’ve covered it before here) but if it’s your first time, here is very quick recap:

Basic C9800 Configuration Blocks

And this is the lab. Note that VLAN 20 is now removed from the ESXi Trunk on the switch port G0/7. It is no longer needed as the AP plugged to port G0/1 will be dropping users’ data locally now.

Lab Environment


  1. Since we’re leveraging FlexConnect local switching (AP puts wireless users into the network, data traffic is no longer tunneled back to the C9800 WLC), AP trunk must allow vlan 20 (that is a wireless users VLAN, local to the AP)
  2. C9800-CL VM is freshly deployed as shown here or it is configured for central switching as shown here
  3. C9800 can communicate with the network; wireless management interface (VLAN 11 in this example) is up
  4. AP is registered to the C9800

In this example, we still have my AP registered as ‘local’ (central switching), centrally switched SSID is up, my phone is associated and has full access following the ‘central switching deployment’ blog here.

AP joined as ‘local’
9800-PSK-Central SSID is up and 1 client (my phone) is associated on 5GHz

The only places where the config is different between Central and Flex are:

  1. Policy Profile – sets SSID set to local switching and maps to a local VLAN
  2. Flex Profile – defines AP Flex attributes like AP Native VLAN, Local Auth and AP Local VLANs are specified here
  3. Site Tag – tells the AP to join as Flex and use specific Flex Profile

I’ll put more wording around the above only, as we’ve already covered all other relevant details in the ‘centrally switched’ blog post here.


This is how we registered AP as Flex and configured locally switched Flex WLAN.

1. Clean up the config

For simplicity, I just deleted all Profiles and Tags except of RF Profile and RF Tag (and that’s it, I didn’t delete anything else; still, don’t worry if you start with a fresh blank config :))

2. Create new WLAN profile

WLAN Profile – General Tab
WLAN Profile – Security Tab

3. Create Policy Profile

Policy Profile – General Tab

Central Switching” must be unticked to enable Flex Connect Local Switching; it also makes sense to untick “Central DHCP” as we’re probably happier with DHCP process being handled locally and not via a WLC. I also like to include the VLAN ID that we are mapping this Policy Profile to in the Name or Description, as we might have more Policy Profiles mapping different VLANs for different WLANs and it’s good to know what policy does what just by glancing at its name or description.

Policy Profile – Access Policies Tab

“VLAN/VLAN Group” is where you map WLAN to a VLAN! There is no direct equivalent to that mapping as we know from the AireOS. Please note that if you create a VLAN & name it (either through CLI: (config)# vlan 20; (config-vlan)# name LAB-WIRELESS-USERS or GUI: Configuration > Layer2 > VLAN) and use VLAN name to refer to it in a Policy Profile, it WILL NOT WORK! You must refer to a VLAN via its ID (and not a name, since it doesn’t exist on the AP!). If you want to refer a VLAN name here, you must specify 100% matching VLAN ID and corresponding VLAN name in the Flex Profile. See “Flex Profile” section below for more details.

4. Create Policy Tag

Policy Tag, stiching WLAN Profile and Policy Profile together

5. Create AP Join Profile

AP Join Profile – General Tab

6. Create Flex Profile

Flex Profile – General Tab
Flex Profile – Local Authentication Tab
Flex Profile – Policy ACL Tab
Flex Profile – VLAN Tab

We didn’t have to create Flex Profile for Centrally Switched WLAN, but we will need it here. We can use Flex Profile for many different things, but those are quite important:

  • General Tab
    • Native VLAN ID – this is where we specify AP mgmt. VLAN that the AP will be sitting in.
    • Efficient Image Upgrade – this means that when we upgrade the controller code, it will be pushed to just one Flex AP (called the FlexConnect Master AP in AireOS) tagged with a Site Tag containing the same Flex Profile. The code will then be distributed to the remaining APs locally without the need to transfer it over WAN or Internet multiple times. Neat.
  • Local Authentication Tab
    • This is where we can specify a RADIUS server local to the AP for wireless clients authentication so it doesn’t have to be central and go through a DC somewhere far far away. Radius Server Group can also be used in a very valid scenario, where the preference is to use central RADIUS for authentication and visibility and switch to local (from AP perspective) RADIUS when the central one is down. EAP based WLANs would gain a survivalability element in case the WLC or communication to the WLC goes down. Existing clients could potentially re-authenticate and new ones could connect but bear in mind that Flex AP and WLAN in not-connected mode (WLC not reachable) would lose access to RRM and roaming optimisation mechanisms.
  • Policy ACL Tab
    • If you ever want to use any ACLs on APs / WLANs configured as Flex Local Switching, you must create an ACL in ‘Configuration > ACL’ and, on top of that, you MUST add this ACL under ‘Flex Profile > Policy ACL’ tab! By doing so, the specific ACL is pushed down to the AP and can be refered to (statically or via RADIUS).
  • VLAN Tab
    • This is where you can create VLANs that will be pushed down to the AP. Remember VLAN/VLAN Group under Access Policies Tab of the Policy Profile, where we mapped the profile to wireless users’ VLAN 20 using VLAN ID? If we’d like to refer to the VLAN by its name, we would need to have a matching VLAN/name configured here!

7. Create Site Tag

Site Tag

We’ve come to the last place, where Flex relevant config sits! The second we untick “Enable Local Site”, “Flex Profile” dropdown appears. For the AP to join the WLC as a Flex AP, we need to untick “Enable Local Site” and select “Flex Profile” that the AP will use.

8. Create RF Profile (for 2.4 and 5GHz) and RF Tag

Since I created them in our ‘central’ switching blog and didn’t delete them, refer to our blog here to find out more about RF Profiles and Tags.

Apply all tags to relevant APs

AP(s) will now reboot and should join back as a Flex AP and broadcast our SSID:

AP Joined in Flex AP Mode
Flex SSID “9800-PSK” is broadcasted and a client (my phone) is happily connected

That’s it! 🙂 We massively hope it was helpful for someone!

Tons of love,

WiFi Ninjas x

WN Blog 013 – Cisco Catalyst 9800-CL – Redundancy HA SSO (CLI and Deeper Dive)

Hey! And welcome to another C9800 blog 🙂 Recently, Matt has blogged about Redundancy configuration using GUI and covered HA/SSO operation here. Today, I wanted to do a deeper dive into the topic. Enjoy!

Lab Environment:

In my lab, both C9800-CL VMs will sit on a single ESXi box. In the real world, they would rather be distributed across separate VM hosts or even separate geographical locations. In any case, configuration would stay identical and same pre-reqs are still relevant. Most importantly, both vWLCs need access to the LAN on their mgmt. interface (that will also be used by APs to register to) and a separate ‘P2P’ L2 link to form & monitor HA and sync configuration.

See a full picture of my lab below:

Lab – Fuill Picture

And to make things simple, also see a simplified logical diagram of C9800-CL networking and interfaces mapping to the VMware vSwitches:

Lab – Simplified Diagram

HA/SSO nitty-gritty stuff

  • HA/SSO in C9800 works differently to how it works in Aironet, it’s more like a VSS now.
  • Initially, both C9800-CL WLCs will require management IP address.
    • Note, that management IP is optional for a secondary WLC if you have a console access to it. Mgmt IP is no longer required to form a HA Pair
  • Redundancy Management as we know it from AireOS (additional IP per WLC from the same subnet as mgmt.) doesn’t exist anymore and therefore Redundancy Port IP is no longer automatically derived from the Redundancy Management IP (it used to be 169.254. + last two octets of the Redundancy Management IP) – you have to manually specify “Redundancy Port” IP and elect one of the VM interfaces to be used as a Redundancy Port (RP)
  • “Redundancy Port IP” is now called “Redundancy Local IP” (GUI) or “Local HA Interface IP” (CLI) <- same thing, just called differently in different places
    • Local HA Interface IP (I’ll call it just that as we’ll use CLI to form HA/SSO in this example) should be in a different subnet to a management interface. This subnet should not be routable.
  • Both WLCs are using the same mgmt. IP to maintain AP CAPWAP during failover once HA/SSO is formed
  • Two units are using a dedicated Redundancy Port (now called HA-Interface) to sync
  • Role election happens at boot, uses priority (1-15, default is 1; higher priority is preferred) or lowest MAC if priority is the same; two controllers are supported, not more
    • It’s best practice to assign higher priority to the preferred active WLC
  • Standby WLC continuously monitors Active via RP keepalives
  • Gratuitous ARP is sent by a Secondary WLC that is taking over the Active role
  • No preempt functionality is supported – failback, if needed, is manual
  • Timers:
    • SSO Failure Detection: 50 ms
    • Reconciliation Time (Standby becoming Active): max 1020ms
  • Reloading Active WLC via CLI: # reload will also reload a standby immediately
  • Forming HA wipes out the config!!!
    • Always form a HA first, configure later
  • WLC Interface used for HA will disappear from the interfaces list (sh ip int br etc. will not list it anymore)

HA/SSO Pre-reqs

  • HA Pair can only be formed between two WLCs of the same form factor (C9800-CL VMs in this example)
  • Both WLCs must be running same code version
  • Max RP RTT = 80ms, min bandwidth = 60Mbps, minimum MTU = 1500
  • Both WLCs are built, accessible, VMware networking is configured, WLCs have access to the LAN and separate L2 link for the HA is available between the WLCs
    • C9800-CL HA-Interface that we intend to use as a Redundancy Port L2 HA inter-vWLC link must be put into a separate, unused VLAN! Using existing VLAN/subnet, especially if it’s management VLAN/subnet, would theoretically work (I’ve tested it) but it will cause instability, duplicate ARP entries and ARP resolution issues. See below the ‘show logging’ output from my switch, where I had HA-Interfaces IP sitting in the mgmt. subnet:
  • See full deployment guide of the C9800-CL for VMware ESXi in our previous blog here
  • Prepare IP addresses and subnets; in this example we will use the following:
    • Active WLC
      • Chassis 1, priority 2
      • Mgmt. (VLAN 11): /24
      • HA Local IP (VLAN 666): /24 (VLAN 666
    • Backup WLC
      • Chassis 2, priority 1
      • Initial Mgmt (VLAN 11): /24 (optional if have console access, won’t be used anymore once HA is formed)
      • Mgmt: (VLAN 11) /24 (shared between HA WLCs once HA is formed)
      • HA Local IP (VLAN 666): /24

HA/SSO Configuration

I feel CLI gives us better visibility into what is happening on both WLCs while forming HA Redundancy, therefore we will use CLI here. It is possible to use GUI too, but I am not a huge fan of “click, wait, pray and hope for the best” approach, where I can’t see what’s happening 🙂


  • Active C9800-CL
    • # chassis ha-interface Gig 3 local-ip /24 remote-ip
    • # chassis 1 priority 2
    • # wr
    • # reload
  • Standby C9800-CL
    • # chassis ha-interface Gig 3 local-ip /24 remote-ip
    • # chassis 1 renumber 2
    • # chassis 1 priority 1
    • # wr
    • # reload


Refer to our previous C9800-CL Redundancy blog written by Matt here

Note: Standby WLC would need to be accessible on its management IP address to use GUI for Redundancy configuration.

Tshoot & Validation

It is good and useful to know how to monitor, tshoot and validate HA Redundancy configuration. You can do it in both CLI (see below) and GUI (Monitoring > System > Redundancy; Dashboard > Slot: Active / Standby)


# show chassis

Show Chassis
  • Validate Chassis# and Priority. Also see the HA state (“Ready” is the final and desired stage, you can also see “Initializing” etc.) and HA-Local IP of both C9800-CL VMs.

# show chassis ha-status local

Show Chassis HA-Status Local
  • Check before the reboot while forming the HA
  • Active should have higher priority, HA Local and Remote IPs and assigned interfaces are shown, together with Chassis# and Priority that will be assigned to this local WLC upon reboot (you might have changed those values and it can be slightly confusing, so it’s best to check after configuring and before rebooting_


# show redundancy

Show Redundancy
  • Another useful show command, where we can validate uptime in current state, versions, modes and more!

Want to Know More?

Yeh, totally get it – me too 😉 I’ll drop some useful stuff that I came across and used at some point here that might help with configuration and troubleshooting.

Manual failback

  • # redundancy force-switchover
  • Can be very useful in scenarios like primary DC maintenance, where Backup C9800-CL takes over. Since there is no preempt mechanism in C9800 HA (former Active WLC won’t claim its original Active role back when it comes back online)

Clear HA Configuration

  • # chassis clear
  • # reload

This is how it looks in the CLI:

Note: it’s enough to clear chassis information on the active HA Pair WLC, despite the information that the ‘other’ (Backup) chassis will keep its HA configuration. I’ve tested it and it will not! Backup chassis will also reboot with clear redundancy config!

  • Chassis clear is used to break the HA; be careful with this as you will end up with duplicate IPs! Both former Active and Passive WLCs will share identical configuration upon reboot!

Duplicate IP addresses after clearing chassis config

Successful HA/SSO Formation

This is how successful HA  formation should look like in a console of both Active and Passive WLCs:

Successful HA/SSO Formation upon reboot once ha-interface was configured; Active (left) was elected Active due to higher priority

That’s it for now! It feels great to play around with new toys and discovering differences between old and new WLCs! Don’t hesitate to comment, add to the discussion or simply let the world know that you are enjoying beta-testing Cisco gen 1 products as much as we are 😉

WN Blog 012 – Can You Crack 802.1X WPA2-Enterprise Wireless Data?

One of our clients has recently approached me with concerns about their new WiFi network that we were planning to put in. They were coming from a wired-only environment and were not sure if introducing EAP-TLS based corporate wireless was a good and safe idea. Additionally, while preparing for my CWAP exam I heard in one of the course videos that “you can’t decrypt 802.1x EAP, as there is no known key that we can enter to start 4-way handshake”. But is it really the case?

I will answer this question by first touching on the 802.1X EAP authentication framework recap that will help us understand conditions that must be met, and steps taken to decrypt WPA2-Enterprise data.

All modern EAP variations are using strong CCMP encryption. Instead of attacking it, we will focus on capturing RADIUS packets on the wire and extract a PMK from this transaction. We will then capture 4-way handshake to get Anonce and Snonce and use it together with PMK, Supplicant MAC and Authenticator MAC to derive PTK (Wireshark can do it for us) used to decrypt our wireless session.

802.1X EAP Recap

IEEE 802.1X is a standard for Network Access Control. It provides authentication (making sure that something is what it claims to be) mechanism to devices wishing to connect to a LAN or WLAN. 802.1X defines the encapsulation of the Extensive Authentication Protocol (EAP) over IEEE 802, that is known as EAP over LAN (EAPOL). 802.1X defines 3 roles: Supplicant (client), Authenticator/NAS (AP) and Authentication Server (RADIUS). Successful EAP transaction starts a process of 802.11 Security Keys Generation, that I tried to visualise in a diagram below, together with 802.11 Open Authentication, 802.11 Association, Tunnelled EAP Authentication and a 4-Way Handshake, collectively being part of an 802.1X standard.                   

802.1X EAP and 802.11 Security Keys Generation Process
802.1X EAP and 802.11 Security Keys Generation Process


The following conditions must be met to decrypt 802.1X EAP encrypted captures:

1. RADIUS key must be known

  • Brute force against the RADIUS capture is an option but strong RADIUS key would make it unpractical. Make sure the key is strong!
  • Social engineering attack – get network engineer’s contact details and ask him/her about a RADIUS key saying you’re from NOC tshooting an issue or a contractor working on upgrading RADIUS server and see what happens. Make sure staff is trained how to handle social engineering attacks and that their contact details like phones, mails and positions within the company are well secured!
  • Access to RADIUS server – some mainstream RADIUS servers (MS NPS, FreeRADIUS) store the key unencrypted in a file. Cisco ISE can show you password when you’re logged in. Make sure access to the RADIUS servers and logon credentials are properly secured!

2. Wireless capture of the session that we want to decrypt must be taken

  • Session must include 4-way handshake, so must include both packets coming from the client and AP, meaning that the potential attacker would need to be physically close to both. 

3. Wired capture of RADIUS authentication must be taken

  • Capture of RADIUS authentication on the wire is essential, as PMK is never sent over the wireless, so it can’t be eavesdropped. We’ll extract it from RADIUS wired captures.
  • Capturing RADIUS traffic would require physical access to the LAN to plug a collector into or access to the network infra to configure SPAN. Make sure that the admin access to the network equipment is secure and that all infrastructure is physically locked!

Lab Environment

Here is the lab setup and capture locations (both wired and wireless):

  • Wireless Captures: Cisco AP in sniffer mode placed between my wireless test client and client serving AP, configured to send captures to my Windows Server VM running Wireshark.
  • Wired Captures: Cisco switch with SPAN monitoring session and port facing my ESXi server (with Cisco ISE RADIUS VM running there) being a SPAN source and switch port facing my laptop being a SPAN destination.
Lab Network Diagram
Lab Network Diagram


Here is a high-level summary of what we need to do to decrypt our WPA2-Enterprise wireless session:

  • Extract PMK with wired RADIUS captures; use RADIUS Shared Secret, Request Authenticator from the final Access-Request RADIUS frame and MS-MPPE-Recv-Key from the RADIUS Access-Accept frame.
  • Capture 4-Way Handshake with wireless captures.
  • Use extracted PMK and 4-Way Handshake to derive PTK with Wireshark and use it to decrypt user data.

Note: PTK is valid only for the duration of a single session. Session timeout, new association or re-association (roaming) would require to derive new PTK!

Assuming all conditions are met, let’s crack on!

1. Obtain RADIUS key

  • Since I’m using ISE, here is where I would look to get it:
RADIUS key configured in Cisco ISE
RADIUS key configured in Cisco ISE

2. Start capturing wireless traffic of interest

  • Position capturing device so it can capture both wireless client and AP traffic.

3. Start capturing wired RADIUS traffic between the Authentication Server and the Authenticator

  • Ensure to capture full RADIUS exchange for the wireless device authentication.

4. Connect wireless device to the EAP SSID

  • If it’s your test device, disconnect and then connect again.
  • If it’s not your test device, you could try to force the device to re-connect by sending a de-auth; SSID must not use management frames protection mechanism, and they usually don’t for compatibility reasons.

5. Obtain Authenticator from the last Access-Request packet in wired RADIUS capture

  • Go to RADIUS Protocol > Authenticator.
  • Here it’s 00:0d:42:73:f6:19:5c:d3:88:73:cf:b3:2c:76:5d:16 (you can copy value in hex straight from the capture).
Authenticator value from Access-Request wired RADIUS capture
Authenticator value from Access-Request wired RADIUS capture

6. Obtain MS-MPPE-Recv-Key from the Access-Accept packet in wired RADIUS capture

  • Go to RADIUS Protocol > Attribute Value Pairs > AVP: t=Vendor Specific (last one)
  • Here it’s cf:6f:b5:06:da:57:b1:9c:e4:6d:76:af:93:51:59:7e:2c:f8:cd:79:c6:2b:e1:a5:4f:ab:28:bd:ed:d3:81:d3:a9:57:dd:74:f8:d1:41:b8:ec:50:ea:d7:27:75:85:d3:1e:d3
MS-MPPE-Recv-Key value from Access-Accept wired RADIUS capture
MS-MPPE-Recv-Key value from Access-Accept wired RADIUS capture

7. Compile PMKextract code, that we will use to extract PMK

  • I used Visual Studio in Windows to build the code mentioned earlier. There are also Python versions of similar code available but since I’ve already had Visual and it worked, I focused on this approach.
  • Create a new C++ project/file in Visual and paste this code:
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>

#define _WIN32_WINNT 0x0400
#include <wincrypt.h>

typedef unsigned int u32;
typedef unsigned char u8;

// This debugging function can be found in wpa_debug.c from the hostap package
//extern void wpa_hexdump_key(int level, const char *title, const u8 *buf, size_t len);

#define os_malloc(s) malloc((s))
#define os_free(p) free((p))
#define os_memcpy(d, s, n) memcpy((d), (s), (n))
#define MD5_MAC_LEN 16

static void cryptoapi_report_error(const char *msg)
 char *s, *pos;
 DWORD err = GetLastError();

     NULL, err, 0, (LPTSTR) &s, 0, NULL) == 0) {
   printf("CryptoAPI: %s: %d", msg, (int) err);

 pos = s;
 while (*pos) {
  if (*pos == '\n' || *pos == '\r') {
   *pos = '\0';

 printf("CryptoAPI: %s: %d: (%s)", msg, (int) err, s);

int cryptoapi_hash_vector(ALG_ID alg, size_t hash_len, size_t num_elem,
     const u8 *addr[], const size_t *len, u8 *mac)
 size_t i;
 DWORD hlen;
 int ret = 0;

 if (!CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, 0)) {
  return -1;

 if (!CryptCreateHash(prov, alg, 0, 0, &hash)) {
  CryptReleaseContext(prov, 0);
  return -1;

 for (i = 0; i < num_elem; i++) {
  if (!CryptHashData(hash, (BYTE *) addr[i], len[i], 0)) {
   CryptReleaseContext(prov, 0);

 hlen = hash_len;
 if (!CryptGetHashParam(hash, HP_HASHVAL, mac, &hlen, 0)) {
  ret = -1;

 CryptReleaseContext(prov, 0);

 return ret;

int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
 return cryptoapi_hash_vector(CALG_MD5, 16, num_elem, addr, len, mac);

static u8 * decrypt_ms_key(const u8 *key, size_t len,
      const u8 *req_authenticator,
      const u8 *secret, size_t secret_len, size_t *reslen)
 u8 *plain, *ppos, *res;
 const u8 *pos;
 size_t left, plen;
 u8 hash[MD5_MAC_LEN];
 int i, first = 1;
 const u8 *addr[3];
 size_t elen[3];

//wpa_hexdump_key(1, "key", key, len);
//wpa_hexdump_key(1, "secret", key, len);
//wpa_hexdump_key(1, "auth", req_authenticator, MD5_MAC_LEN);

 /* key: 16-bit salt followed by encrypted key info */

 if (len < 2 + 16)
  return NULL;

 pos = key + 2;
 left = len - 2;
 if (left % 16) {
  printf("Invalid ms key len %lu\n", (unsigned long) left);
  return NULL;

 plen = left;
 ppos = plain = (u8*)os_malloc(plen);
 if (plain == NULL)
  return NULL;
 plain[0] = 0;

 while (left > 0) {
  addr[0] = secret;
  elen[0] = secret_len;
  if (first) {
   addr[1] = req_authenticator;
   elen[1] = MD5_MAC_LEN;
   addr[2] = key;
   elen[2] = 2; /* Salt */
  } else {
   addr[1] = pos - MD5_MAC_LEN;
   elen[1] = MD5_MAC_LEN;
  md5_vector(first ? 3 : 2, addr, elen, hash);
  first = 0;

  for (i = 0; i < MD5_MAC_LEN; i++)
   *ppos++ = *pos++ ^ hash[i];
  left -= MD5_MAC_LEN;

 if (plain[0] == 0 || plain[0] > plen - 1) {
  printf("Failed to decrypt MPPE key\n");
  return NULL;

 res = (u8*)os_malloc(plain[0]);
 if (res == NULL) {
  return NULL;
 os_memcpy(res, plain + 1, plain[0]);
 if (reslen)
  *reslen = plain[0];
 return res;

void processTokens(char*  authenticator,
       u8*   processedAuthenticator,
       char*  recvKey,
       u8*   processedRecvKey )
 // Handle authenticator
 char* ptr = strtok( authenticator, ":");
 int i = 0;
 while( ptr )
  processedAuthenticator[i++] = ( u8 ) strtoul( ptr, NULL, 16 );
  ptr = strtok( NULL, ":");

 // Handle key
 ptr = strtok( recvKey, ":");
 i = 0;
 while( ptr )
  processedRecvKey[i++] = ( u8 ) strtoul( ptr, NULL, 16 );
  ptr = strtok( NULL, ":");

void dumpPmk( const u8*  pmk )
 printf( "PMK is:\n" );
 for( int i = 0; i < 32; i++ )
  printf( "%02x", pmk[i] );
 printf( "\n" );

int main(int argc, char*argv[])
 if( argc != 4 )
  printf( "Usage: %s secret authenticator recv-key", argv[0] );
  return( 1 );

 if( strlen( argv[2] ) != 47 )
  printf( "Bad authenticator length" );
  return( 1 );

 if( strlen( argv[3] ) != 149 )
  printf( "Bad recv-key length" );
  return( 1 );

 u8 processedAuthenticator[16];
 u8 processedRecvKey[50];
 u8* pmk;
 u32 pmklen = 0;

 processTokens(argv[2], processedAuthenticator, argv[3], processedRecvKey );

 pmk = decrypt_ms_key(processedRecvKey, 50,
      (u8*)argv[1], strlen(argv[1]), &pmklen);

 dumpPmk( pmk );


  • Save .cpp file. I saved it as “PMKextract.cpp”:
 Adding PMKextract.cpp to the Solution Explorer
Adding PMKextract.cpp to the Solution Explorer
  • If you try to build it now, you’d probably see the error:
Unsafe function or variable warning
Unsafe function or variable warning
  • To allow project to build successfully, add _CRT_SECURE_NO_WARNINGS under Project -> Properties -> C/C++ -> Preprocessor -> Preprocessor Definitions:
Allow project built by modifying Preprocessor Definitions
Allow project built by modifying Preprocessor Definitions
  • Build > Build project should now be successful:
Successful build of the PMK extracting code
Successful build of the PMK extracting code

I then copied compiled ‘Project1.exe’ file to C:\Geekwifi and renamed it to ‘PMKextract.exe’.

8. Extract PMK

  • Navigate to the location of your PMKextract.exe file. It takes all required attributes as shown:
PMKextract usage
PMKextract usage
  • Get the PMK:
Extracting PMK using all values that we gathered: RADIUS secret, authenticator and Recv-Key
Extracting PMK using all values that we gathered: RADIUS secret, authenticator and Recv-Key

9. Specify decryption key in wireless captures in Wireshark

  • Finally, open wireless captures and use our extracted PMK as a wpa-psk key.
Provide Wireshark with extracted PMK in ‘Edit > Preferences > Protocols > IEEE 802.11 > Decryption keys > Edit’
Provide Wireshark with extracted PMK in ‘Edit > Preferences > Protocols > IEEE 802.11 > Decryption keys > Edit’

10. Enjoy decrypted wireless captures!

  • We can see all the usual stuff – probes, authentication and association requests and responses, EAP process with EAP Success at the end, 4-way handshake and then decrypted data. Happy days!
Decrypted 802.1X WPA2-Enterprise session
Decrypted 802.1X WPA2-Enterprise session


Properly configured and physically secured WPA2-Enterptise wireless network, especially where client and server certs are involved, is still considered highly secure. Specific conditions must be met to decrypt 802.1X EAP wireless session captures, where RADIUS key must be known, and the attacker would have to be able to capture RADIUS conversation on the wire and 4-Way Handshake on wireless to make it possible. Additionally, decrypting WPA2-Enterprise session does not necessarily mean we could eavesdrop on the meaningful user data, as it might be encrypted on a data level, i.e. using TLS or SSL, that do not rely on WiFi infrastructure encryption.


WN Blog 010 – Cisco Catalyst 9800 – Configuration Guide (Basics & Central Switching)

Finding C9800 stuff hot and interesting? You’re not alone out there! 🙂

After initial C9800 configuration (see this blog) and registering your first AP (our AireOS AP Join Blog is still applicable here) you’re pretty much ready to go! There are just some pre-reqs to consider before we can associate with our first C9800 BSSID.


  • C9800 is built, GUI and CLI access is working
  • AP is registered
  • AP mgmt. VLAN (VLAN 10 in this example) is operational, AP has connectivity with to at least the vWLC
  • VM mgmt. VLAN (VLAN 11 in this example) is operational, C9800 can communicate with the network
  • WiFi Users VLAN (VLAN 20 in this example) is operational and, since it’s central switching we talk about here, VLAN 20 is allowed on C9800-CL management trunk (Gi2 in this example), on Port Group on the vSwitch C9800 Gi2 is mapped to and on ESXi management trunk to the switch; VLAN 20 must be allowed across entire path from the C9800 to its gateway

Note: since we’re talking central switching mode here, authenticated WiFi users’ traffic will be dropped into WiFi users VLAN at the vWLC level!

Lab Environment

To get better picture, see my lab environment below:

Lab Environment

New C9800 Architecture

Even though C9800 offers pretty much features parity with our beloved AireOS WLC, it is slightly different. If you spent some quality time with Cisco DNA Center you will feel comfortable with the new GUI and structure. If not (like me), be prepared to change some old habits and approach C9800 with an open mind 🙂

C9800 is designed to fit perfectly into Cisco SDA world and integration with DNAC and use of SGTs. But don’t worry if you don’t have few DNAC boxes worth £70k each and a fabric underlay lying around. C9800 can still work in a traditional way. The only real difference is where we configure the same stuff as we did in AireOS (using Profiles) and how we stich it together (using Tags).

Look at the visual representation of major blocks building a basic WiFi setup.

Wireless Setup Flow Overview

You can create multiple WLAN Profiles (SSIDs) and Policy Profiles and correlate both using a single Policy Tag. You then choose your AP Join Profile and Flex Profile (if in use) and correlate both using Site Tag. Your 2.4 and 5GHz RF profiles are stitched together using RF Tag. You now have all the config needed for the AP and SSID to operate described with just 3 tags, that are finally assigned to the AP of your choice. Takes some time getting used to, but it’s really not too bad.

Let’s dive straight in. Once we start looking at the real config it shouldn’t feel too overwhelming.

Note: only the WLAN Policy is mandatory but it is best practice to use all 3 policies and understand impact they all have on our wireless network.


In this example we’ll configure simple WPA2-PSK WLAN and cover more interesting stuff like popular enterprise security approaches using EAP (PEAP, EAP-TLS, BYOD) in future blogs! Guest flow (CWA with ISE) already has its blog and you can find it here: 🙂

Below steps show how to configure your first centrally switched WLAN. It’s PSK-based, but you can easily translate it to any other auth method. Have fun 🙂

1. Configure WLAN Profile

This is a pretty standard WLAN configuration that we’re all familiar with. Quite a few boxes to tick, tons of possibilities, standard Cisco overcomplication that feels like 1:1 port from the AireOS. Simplifying opportunity missed. But let’s not digress!

Go to Configuration > Tags & Profiles > WLANs or (I like to do that), Advanced Wireless Setup (top-right corner), where you can switch between all main solution building blocks from one list.

Advanced Wireless Setup

Amazing, isn’t it?

In General tab, configure Profile Name (must be unique) and SSID name (can have more than one on the same WLC) along with WLAN ID (ID <=16 = included in default Policy Profile, ID > 16 = won’t be included in default Policy Profile), Radio Policy (2.4GHz, 5GHz, or both). As L2 security in Security tab, use WPA + WPA2 with AES encryption and PSK key mgmt and specify ASCII PSK Key. FT should be disabled here due to Krack vulnerability. Leave all other security details on their default values. Advanced tab settings can also be left on default but please be mindful of the impact some settings on the performance and compatibility of your SSID. This is a topic for another discussion, but in essence I’d say that:

  • Aironet IE enables SSID name inclusion in beacons among many other things, which is helpful AF but can affect clients compatibility with this SSID
  • P2P Blocking is normally enabled on Guest SSIDs (blocks WiFi clients from attacking each other)
  • 802.11v can seriously affect (positively or negatively) your roaming behaviour – test with your clients
  • 802.11k is generally a good feature to use as it should reduce time your clients spend scanning off channel for alternative APs while roaming
  • Band select can be useful in some scenarios, but steer away when used with voice as it will make roaming slower
WLAN Profile General tab
WLAN Profile Security tab

2. Create a VLAN

Since we’re dealing with central switching, we might think that we would need a dedicated SVI on the C9800 sitting in the VLAN into which we would like to drop authenticated users’ traffic in the same fasion as we did in AireOS. We could do it and it would work, but it’s not necessary here. All we need is to create VLANs (as opposed to SVIs) to get centrally switched WLANs to work.

Add VLAN in CLI ((config)#vlan [VLAN ID]; (config-vlan)#name [VLAN name]) or GUI in Configuration > Layer2 > VLAN > Add

In this example I’m using VLAN 20 for wireless users. L3 sits on my core switch. VLAN 20 is allowed on vSwitch and ESXi trunk. Refer to the lab network diagram for more clarity – one pic speaks thousand words.

Add VLAN for wireless users

3. Configure Policy Profile

This is where we can configure TrustSec, decide if we want to use Central Switching, Authentication, DHCP or Association, map WLAN to a VLAN, apply an ACL to an SSID, turn on RADIUS Profiling, specify QoS, AVC, CAC, Anchors, AAA Policy (attributes returned to the NAC), basic WLAN timers and many more. Sounds easy? I know, I too feel it’s slightly on the overcomplicated side 🙂

General Tab:

Policy Profile – General Tab

Minimum config required:

  • Specify Name
  • Set Status to ENABLED
  • Enable Central Switching and Central DHCP

If you want to know more:

  • WLAN Switching Policy can move certain roles (switching, auth, DHCP, association) between AP and WLC. Central everything is the default. Note that “Central DHCP” must be used in Central Switching mode. If you disable it, clients won’t get an IP at all. Authentication and Association roles can be moved between WLC and AP and either would work just fine.
  • Passive Client (in short) allow comms from wired devices to wireless devices with static IP address by enabling WLC to pass ARP requests to them. Normally WLC proxies that responses but since there is no DHCP used, WLC wouldn’t know about those devices.

Access Policies Tab:

Policy Profile – Access Policies Tab

Minimum config required:

  • Specify VLAN/VLAN Group assignment (use just a VLAN number or use VLAN name set in step 2.)

If you want to know more:

  • VLAN/VLAN Group is where we specify the VLAN we want to drop wireless users into! This is extremely important to understand, since we don’t assign WLANs to dynamic interfaces (central) nor we have VLAN to WLAN mapping (flex) anymore. I have assigned ‘LAB-WIRELESS-USERS’ VLAN 20, that I created in step 2.
  • WLAN ACL can be applied to do basic firewalling on the AP or WLC level (depending if using central switching or Flex) before the traffic even hits the firewall.

Let’s leave the rest on default for now. We’ll cover it in more details in future blogs.

4. Configure Policy Tag

Policy tag just stitches WLAN Profile and Policy Profile together, nothing else 🙂

We could mix and match different WLAN and Policy Profiles while creating different tags. Example:

  • PSK WLAN with Policy Profile on VLAN 20
  • EAP WLAN with Policy Profile on VLAN 20
  • MAB WLAN with Policy Profile on VLAN 666

You get the drill.

Policy Tag

Minimum config required:

  • Create a new Policy Tag and select WLAN and Policy Profiles created in previous steps

5. Configure AP Join Profile

Here we’ll configure basic parametres used by APs after they join a controller.

AP Join Profile – General tab

Minimum config required:

  • Specify AP Join Profile Name

If you want to know more (I’ll only mention stuff I think is useful and filter out the noise):

  • If setting up a quick SSID is all we need, we can just create AP Join Profile, and specify its name in General tab. All other settings within the AP Join Profile can be left on default.
  • CAPWAP tab allows us to adjust CAPWAP & Retransmit timeouts and hardcode Primary and Secondary Controller Name and IP for N+1 designs.
  • AP tab allows us to set a Country Code, AP EAP Auth (FAST, PEAP, TLS), enable Hyperlocation, adjust BLE Beacons and AP Packet Capture settings (can capture straight to FTP location which is quite cool).
  • Management tab allows us to specify specific AP code that AP should download upon Joining the WLC, enable AP SSH access, set local mgmt user and dot1x credentials and set thresholds for detecting rogue APs.

Note: Flex Profile configuration is not required in Central Switching architecture.

6. Configure Site Tag

Now, Site Tag is slightly special 🙂

You might expect that since Policy Tag was just stitching profiles together, why would Site Tag be any different?

In Central Switching mode we don’t even specify Flex Profile assignment (let’s discuss it in more details in C9800 Flex blog post). We just specify Site Tag Name, AP Join Profile and, most importantly, we specify if the site is Local (centrally switched) or not (flex). It is confusing AF! In our example, we configure Site Tag with “Enable Local Site” checked.

Site Tag configuration

Minimum config required:

  • Set Site Tag Name, specify AP Join Profile configured in previous step and check “Enable Local Site” (which means that AP will leverage central switching).

7. Configure RF Profile

Custom RF Profiles are optional but extremely helpful to have, especially if your C9800 WLC caters for sites that have different RF requirement coverage areas. Maybe some sites will have APs expected to work in a High Density or Voice environment, while most APs would be serving ‘just data’ hungry stations? We would create different RF profile for each coverage type (High Density, Voice, Data) and for each band (2.4 and 5GHz).

Minimum config required:

  • None – custom RF Profiles are optional

If you want to know more:

  • General tab is just for specifying Name, Band and Description. Make sure your RF Profile is Enabled.
  • 802.11 tab is used to specify Data Rates and MCS Rates. Disabling low data rates is crucial in most scenarios (I personally never had to allow low data rates but I’ve heard stories where others had to due to weird wireless stations requirements). In short, management and control traffic is exchanged at lowest mandatory data rate. Clients associated with our BSSID would rate shift down when moving away from the AP and when the SNR drops for any reason. Supporting low rates and setting mandatory rate too low would contribute to sticky clients behaviour, slower transmission speeds for dodgy clients sitting on low data rates, increased airtime utililisation by those clients and finally, low mandatory rates would contribute to more airtime being consumed for control and management frames, leaving less space for data transmissions. Generally, in most situations, I would set minimum mandatory rate to 12 (standard deployment) or 24 Mbps (higher density), disable all lower rates and set all higher rates to supported. Please note that proper RF design following a proper on-site survey and predictive survey (and sometimes pre-deployment survey with AP-on-a-stick) is extremely important when tweaking radio configuration! Crap in crap out, can’t mitigate shit design with good config.
  • RRM tab is quite a comprehensive topic on its own! Let’s try to keep it short. You might want to increase default number of clients per AP that generate traps. Transmit Power Control (TPC) is extremely important to use wisely and to our advantage. Normally, it’s best to try and match Tx power level of the least powerful wireless device in the network. Allowing maximium available Tx power on the AP won’t necessarily mean ‘better coverage’. Coverage works in both directions – from AP and from a client. Not matching Tx power between AP and a client might cause asymmetric traffic patterns, where client can hear the AP, but AP can no longer hear the client. You also don’t want to go too low with Tx power as the goal is to maintain as high MCS rate as possible. Normally, 2.4GHz AP max Tx should be considerably lower than 5GHz max Tx. Dynamic Channel Assignment (DCA) is another supremely important factor contributing to general performance of a WiFi network. Do we want to bond channels? Do we want to use all available 5GHz channels there? The answer is “it depends”. I’d consider using 40MHz only in smaller deployments and only if it wouldn’t contribute to excessive channel contention. Remember that doubling the channel width doubles the interference and reduces SNR by 3dB. Also, even without ‘our’ APs, RF spectrum might already be crowded so we might want to stick to 20MHz sometimes even in smaller sites. Generally speaking it seems wise to stick to 20MHz in most cases in the enterprise world (but not only!) unless sheer higher throughout is required and you fully understand implications of bonding channels. Also, newer use “Best” channel width as we’ve seen it going wild with using 80MHz in central London on sites with 20+ CCI in a busy multi-tenant building. Now, which UNII bands to use? Stick to non-DFS channels 36-48? Use 36-64? Or maybe use all 19 available (in the EU) channels? It’s hard to answer this with a ‘one size fits all’ type of an answer, but in most cases we’d use all UNII bands, unless we have some weird clients that don’t work too well with upper bands and/or don’t support 802.11k while quick roaming is important.
  • Lastly, there are features like RX SOP or Client Load Balancing in the Advanced tab. RX SOP solves half of the CCI issue by ignoring signal below configured thershold from neighbouring BSSIDs operating on the same channel on an AP level. But how about contention on the wireless station level? Exactly. It’s still there. To solve this issue better, we’d want to think about 802.11ax, where OFDMA and BSS colouring should combat that contention crap nicely. Final tip – be careful with Client Load Balancing as it might hard disassociate your precious clients, potentially making them unhappy, especially if they’re in the middle of a call or conference. I now feel we should have a separate blog and podcast about the RF Profiles and RRM. And we probably will!

8. Configure RF Tag

We are almost there! With RF Profiles sorted, we just need to stich 2.4 and 5GHz profiles together with an RF Tag.

RF Tag configuration

Using RF Profiles and RF Tags, again, is optional (but cool, so please use it).

9. Apply Tags to the APs

Yup, this is the last step.

Select APs to tag and tag them with three tags we have created above (out of which only Policy Tag is mandatory).

Apply tags to APs

Think of tagging APs as of adding them to their relevant AP Groups with specific WLANs and RF Profiles. Well, kind of 🙂

That’s it. Simple. Similar to the AireOS that we all know and love so much, isn’t it? 🙂

Thanks for surviving going through this lengthy post and see you in the next WiFi Ninjas Blog!

WN Blog 008 – How to Change Cisco CMX GUI “admin” Password

Does this look familiar?

GUI password no longer works 😉

Sometimes we forget a password, sometimes it’s set by someone else and they forgot it, left company or are just evil and won’t tell us 😉

Assuming you still have access to  SSH, VMware console (if virtual), Remote or physical serial console (if appliance), you can easily change GUI password of your CMX box.

Console access: SSH to the left; VMware console to the right

NOTE: CMX uses separate user accounts for GUI and CLI access. GUI uses “admin”, CLI uses “cmxadmin” for all administrative purposes.

Since we want to regain access to GUI, we’ll be resetting “admin” user password.

First, we can list users for added peace of mind. Then, we can choose our admin user and set a new password.

GUI “admin” user password change syntax:

  • [cmx ~]$ cmxctl users list
  • [cmx ~]$ cmxctl users passwd admin
  • Enter a new password for user admin: [new password]
  • Repeat for confirmation: [new password]

And a quick screenshot:

GUI “admin” user password change

If you require more details, please see this link:

If you typed incorrect password too many times, you’ll need to unlock CLI or GUI user.

To unlock CMX access for a CLI or GUI user after they have been locked out, use the cmxctl users unlock command.

[cmx ~]$ cmxctl users unlock { cli username | gui username }

That’s it! Access regained. Beer time 😉

WN Blog 006 – Cisco Catalyst 9800 – Deployment with VMware ESXi

If you are geeky, crazy or just curious to try out first generation of Cisco products, new Catalyst 9800 Wireless LAN Controller, this guide might be useful to you 🙂

Jokes aside, C9800 feels like a solid product that is quickly gaining trust of wifi pros and gains traction in the enterprises.

It is a spiritual successor to Cisco AireOS WLCs that sits on the well known IOS-XE that everyone knows and loves :] Thankfully, it has nothing to do with Converged Access, that also was IOS-XE based.

C9800 code was re-written from scratch and offers almost full features parity with its AireOS counterpart.

It’s quite flexible too, meaning you can install it in a private cloud (VMware etc.) public cloud or use it as an on-prem appliance sitting on a switch or a standalone box. All versions offer exact same functionality (with some obvious limitations, like no central data switching when used in public cloud), so you really just need to decide what’s easiest for you to deploy and integrate and think about scale.

I thought that creating an with easy-to-follow ESXi installation steps guide would be a great start!

First of all, here is my lab environment:

Lab Environment

And installation steps below:

1. Download the WLC image

  • At the time of updating this post Gibraltar-16.11.1c(ED) is the latest TAC recommended version

2. Prepare VMware networking

  • C9800-CL requires 3 interfaces – make sure to have all the required VLANs / subnets ready!
    • OOB Mgmt. – not used in Cloud (VM) WLC version, but must be assigned to a vSwitch to bring the interface up
    • Mgmt. – used to manage the WLC and for APs registration. We’re using ESXi 6.0 here, so we have to enable either all 4095 VLANs (trunk) or just one specific VLAN (access). In newer ESXi versions it is possible to allow just selected VLANs on the VMware Distributed Switch trunk. So here we’ll allow all VLANs.
    • HA (L2) – used for HA/SSO and must be configured even when used in a standalone deployment
      • It is important to put C9800 interface that we intend to use as a Redundancy Port L2 HA inter-vWLC link into a seperate, unused VLAN! Note that ‘LAB-VM-L2-HA’ Port Group sits in VLAN 666. Only my two vWLCs’ HA RP ports will be put into that group.
ESXi vSwitches Configuration

3. Spin the OVA file

  • Choose the right size (I used smallest – 1k APs)
VM Size

4. Map WLC interfaces to VM networking

  • WLC Gigabit 1 -> OOB
  • WLC Gigabit 2 -> Mgmt.
  • WLC Gigabit 3 -> HA between WLC VMs
WLC to OVF Template Network Mapping

5. Set correct security parameters on the WLC Trunk interface

  • Promiscuous mode must be set to accept, otherwise tagged traffic won’t flow correctly! This step is easy to miss but it’s very important – WLC won’t pass traffic without ticking it 🙂 The C9800 uses multiple MAC address on the same VM, e.g. may be used by the SVI for wireless management (if bridge for centralised clients) or other SVI’s for loopback, etc., all of which will use different MAC address other that the one assigned to the vNIC of the VM.
  • Forged Transmits must also be set to accept, as having Forged Transmits set to reject will result in no connectivity due to host verifying the source MAC address which is transmitted by guest OS to match with the MAC address of the VM adapter. As this won’t match for C9800 instance, the ESXi host would drop the packet.
VM Trunk Promiscuous Mode and Forged Transmits

6. Boot the WLC using Virtual Console

The system will install, reboot, check if bootloader upgrade is needed, apply the config (empty at this point), etc. After few minutes, we should be presented with a familiar CLI.

Boot using Virtual Console

7. Terminate the configuration wizard

  • Would you like to enter the initial configuration dialog? [yes/no]: no
  • Would you like to terminate autoinstall? [yes]: yes

8. Set a host name

  • WLC> en
  • WLC# conf t
  • WLC(config)# hostname LAB-C9800CL

9. Add login credentials

  • LAB-C9800CL(config)# username admin privilege 15 secret <secret>

10. Configure the VLAN for wireless management interface

  • LAB-C9800CL(config)# vlan 11
  • LAB-C9800CL(config-vlan)# name wireless_management

11. Configure the SVI for wireless management interface

  • LAB-C9800CL(config)# interface vlan 11
  • LAB-C9800CL(config-if)# ip address
  • LAB-C9800CL(config-if)# no shut

12. Configure management interface

Note: since G1 is OOB, G2 is Mgmt. And G3 is HA in this VM, we’ll first configure G2 to access management plane of the WLC. All SSIDs I’m planning to use will leverage FlexConnect Local Switching (dropping data plane directly onto the switch on the AP level), therefore we don’t need to allow any other VLANs than 11 on this trunk. Still, we might want to test Central Switching, so let’s allow Wireless Users VLAN 20 (configured in later blogs) too:

  • LAB-C9800CL(config-if)# interface GigabitEthernet2
  • LAB-C9800CL(config-if)# switchport mode trunk
  • LAB-C9800CL(config-if)# switchport trunk allowed vlan 11,20
  • LAB-C9800CL(config-if)# no shut

Note: depending on your vSwitch configuration, you might need to tag management traffic on the controller side by adding “switchport trunk native vlan 11” command into the config above.

13. Configure a default route (or a more specific route) to reach the device

  • LAB-C9800CL(config)# ip route

At this point WLC9800 Mgmt. interface should be pingable 🙂

Note: you might need to shut / no shut int g2 and shut / no shut int vlan 11 for the SVI to come up!

14. Configure country code

Note: wireless network needs to be disabled first. Country code configuration forces GUI to skip the DAY 0 flow as the C9800 needs a country code to be operational. You can enter up to a maximum of 20 countries.

  • LAB-C9800CL(config)# ap dot11 5ghz shutdown
    • Disabling the 802.11a network may strand mesh APs.
  • Are you sure you want to continue? (y/n)[y]: y
  • LAB-C9800CL(config)# ap dot11 24ghz shutdown
    • Disabling the 802.11b network may strand mesh APs.
  • Are you sure you want to continue? (y/n)[y]: y
  • LAB-C9800CL(config)# ap country GB
    • Changing country code could reset channel and RRM grouping configuration. If running in RRM One-Time mode, reassign channels after this command. Check customized APs for valid channel values after this command.
  • Are you sure you want to continue? (y/n)[y]: y

Don’t forget to re-enable the radios 🙂

  • LAB-C9800CL(config)# no ap dot11 5ghz shutdown
  • LAB-C9800CL(config)# no ap dot11 24ghz shutdown

Finally, validate all is up and happy:

  • LAB-C9800CL# show ap dot11 5ghz summary
  • LAB-C9800CL# show ap dot11 24ghz summary
Validate Radios Operational State

15. Create a certificate for the AP to join the virtual controller

Note: you must specify the interface for the wireless management, create certificate and verify certificate installation. If you skip the certificate/trustpoint configuration, APs will not be able to join. However, you can go to the GUI and configure it by importing the desired certificate.

  • LAB-C9800CL(config)# wireless management interface vlan 11
  • LAB-C9800CL(config)# exit
  • LAB-C9800CL# wireless config vwlc-ssc key-size 2048 signature-algo sha256 password 0 <pwd>
  • LAB-C9800CL# show wireless management trustpoint

At this point, it should be possible to access the WLC via GUI using HTTPS, IP set in step 9 and credentials set in step 7!

SSH will not work yet as the lines are not yet configured.

Credentials have already been set, so we can jump straight into the stuff that’s needed to make SSH work!

Domain name is needed for RSA key generation process.

We’ll also need to specify enable password to allow us to use privileged mode.

16. Configure access via SSH

  • LAB-C9800CL(config)# enable secret <secret>
  • LAB-C9800CL(config)# aaa new-model
  • LAB-C9800CL(config)# ip domain-name <domain-name>
  • LAB-C9800CL(config)# crypto key generate rsa general-keys modulus 1024
  • LAB-C9800CL(config)# line vty 0 530
  • LAB-C9800CL(config-line)# privilege level 15
  • LAB-C9800CL(config-line)# transport input ssh

Voilà! We are now ready to register our first AP to the new, shiny and sexy WLC 😀 Well done!

WN Blog 004 – Modulation & Encoding Techniques

Hey! In this short blog post we’ll share our notes about older modulation techniques used in WiFi (up to OFDM and 256 QAM).

To learn more about OFDMA and 1024 QAM (both used in WiFi 6), see our other blog post about 802.11ax here:

Modulation Summary

  • How to use wireless waves’ physical attributes like amplitude and phase to represent binary data and send it over a wireless medium
  • 802.11 Tx signals must use physical filters to limit the signals sent away from the main target frequency:
  • Radio and attached antenna is called radio chain
  • Possible ways of modulating the waveform:
    • Amplitude – uses strength of the signal to modulate it with power (AM)
    • Phase – timing of the signal between peaks
    • Frequency – how often the signal repeats in one second (Hz, MHz, GHz)
PPDU Sensitivity Required to Use Modulation Techniques

DSSS Chip Sequence

  • DSSS – Direct-Sequence Spread Spectrum
  • Each bit is transformed into sequence, called ‘chip’ or ‘symbol’
  • DSSS sends a single data bit as a string of chips
  • Barker 11 was one of the first encoding methods
    • 1=01001000111
    • 0=10110111000
    • Sending ‘1’ or ‘0’ is represented by 11 ‘chips’
    • 11 ‘chips’ is called a ‘symbol’
    • By expanding original data in this way; with some signal lost due to noise; the original data can still be understood
    • Each bit takes 2MHz of frequency width, sending 11 in parallel takes 22 MHz
    • Supports 1, 2, 5.5 and 11 Mbps data rates
  • Round at the top in spectrum analyzer

DBPSK / DQPSK Modulation

  • DBPSK – Differential Binary Phase Phase Shift Keying
    • alter the signal phase by 180 degrees
    • max 1Mbps
    • ‘0’ – no change in direction
    • ‘1’ – change in direction
BPSK Modulation
  • DQPSK – Differential Quadrature Phase Phase Shift Keying
    • alter the signal phase by 90 degrees in four quadrants
    • max 2Mbps
    • Each ‘chip’ represents 2 bits instead of one as in PSK (hence twice as quick)
QPSK Modulation

CCK Encoding

  • Complimentary Code Keying
  • Code word (wave shape) represents a symbol
  • 2 bits used to check consistency
  • Still uses one 22MHz wide wave
  • CCK 4 – coding 4 bits per symbol (in a 6-bit chip) gave 5.5 Mbps
  • CCK 8 – coding 8 bits per symbol (in a 6-bit chip) gave 11 Mbps
  • CCK loses some of the extra bits used by Barker code to recover information received in a noisy or low SNR environment
    • CCK achieves faster data rates at the expense of requiring a stronger, less noisy signal
PSK Rates with Different Encoding


OFDM Dividing Channel into 64 Tones (Subcarriers)
  • Orthogonal Frequency-Division Multiplexing
  • Alternative to DSSS
  • Square at the top in spectrum analyzer
  • Instead of sending one wide combo-channel transmission, frequencies are broken up into sub-channels (called sub-carriers or tones)
  • Using a 20 MHz wide spectrum, each sub-carrier is 312.5 KHz apart from one another
    • 64 waves (tones / sub-carriers), 312.5 KHz apart
      • 12 ‘Guard’ subcarriers are – used to help set one channel apart from another and to help receivers lock onto the channel
        • 6 head and 5 trail have no power / not used (isolate neighbouring channels)
        • 1 in the middle have no power / not used (identify centre of the signal)
      • 4 ‘Pilot’ subcarriers  – equally spaced and always transmitted to help receivers evaluate the noise state of the channel
      • 48 ‘Data’ subcarriers – devoted to carrying data
        • Each data subcarrier can ‘carry’ 1125 kbps
  • To differentiate between the small sub-carriers, adjacent sub-carriers will have 90 degree changed polarization
  • Data is sent simultaneously over subcarriers in parallel
  • Some of the subcarriers are used to protect/guard against interference and control the signal as a whole
  • Inside OFDM, each tone can use BPSK or QPSK
    • BPSK – allows 250 kbps per tone (250 x 48 = 12 000 kbps = 12 Mbps per OFDM wave)
    • QPSK – allows 500 kbps per tone (500 x 48 = 24 000 kbps = 24 Mbps per OFDM wave)
    • No Barker 11 coding used, repeating allowed
    • Depending on the percentage of repeated signals, total throughput is:
      • BPSK – 9 Mbps (25% repeat) or 6 Mbps (50% repeat)
      • QPSK – 18 Mbps (25% repeat) or 9 Mbps (50% repeat)
  • Used in 802.11 a/g/n/ac

QAM – Quadrature Amplitude Modulation (freaking brilliant!)

  • To go faster than 18 Mbps, OFDM uses another technique, called QAM
  • Uses 90 degrees phase shifts like QPSK, but now combines that with Amplitude Modulation (or changing the amplitude) to accomplish more possible differentiations of simultaneous transmission
  • So then with the 4 ‘quads’, depending on how many differing amplitudes are varied will determine how many signals can be sent and therefore how much additional data can be realized
  • 16-QAM (4^2) used in 802.11a/g/n
  • 64-QAM (4^3) used in 802.11a/g/n
  • 256-QAM (4^4) used in 802.11ac
  • EVM (Error Vector Magnitude) used for improved reliability
    • if you miss the spot, vector length from the centre of expected spot is measured and used to decide what you wanted to hit
  • Denser QAM requires better (quieter) environment, noise can prevent the signal from being understood
  • With more noise introduced, signal will have to downgrade
  • With more advanced QAM modulation (16 > 64 > 256 > 1024), it is more and more challenging to ‘hit’ the right spot to code the right data, therefore more SNR is required to decode it correctly

See some graphical representations of QAM below!

16-QAM Representation 1
16-QAM Representation 2
64-QAM Representation 1
QAM – Bits per Symbol

Now, try to imagine how much more complexity would using 1024-QAM modulation bring!