Cisco 9800 CAPWAP Discovery w/ NAT

In certain instances, it may be a required to install a wireless LAN controller (WLC) behind a NAT boundary, requiring that the IP address used for CAPWAP discovery during access point (AP) initialisation, be defined as the NATed IP address, as opposed to the real one assigned to the wireless management interface (WMI) of the WLC, which typically is allocated from an RFC1918 range.

The WMI is the mandatory Layer 3 interface on the Cisco Catalyst 9800 Wireless Controller. It is used for all communications between the controller and access points. Also, it is used for all CAPWAP or inter-controller mobility messaging and tunnelling traffic.

WMI is also the default interface for in-band management and connectivity to enterprise services, such as, AAA, syslog, SNMP, and so on. You can use the WMI IP address to remotely connect to the device using SSH or Telnet (or) access the Graphical User Interface (GUI) using HTTP or HTTPs by entering the wireless management interface IP address of the controller in the address field of your browser.

Initial WMI CLI Configuration

1.0 Configure the VLAN for wireless management interface:

c9800(config)# vlan 10
c9800(config-vlan)# name wmi_interface

2.0 Configure the L3 SVI for wireless management interface

Device(config)# int vlan 10
Device(config-if)# description WMI Interface
Device(config-if)# ip address 10.0.10.5 255.255.255.0
Device(config-if)# no shutdown

3.0 Configure the phyiscal interfaces and port channels (If applicable)

####Cisco 9800-80 Configuration - Other platforms will differ####
!
interface Port-channel1
switchport trunk allowed vlan 10
switchport mode trunk
switchport nonegotiate
!
interface TenGigabitEthernet0/0/0
switchport trunk allowed vlan 10
switchport mode trunk
switchport nonegotiate
no negotiation auto
channel-group 1 mode active
lacp rate fast
!
interface TenGigabitEthernet0/0/1
switchport trunk allowed vlan 10
switchport mode trunk
switchport nonegotiate
no negotiation auto
channel-group 1 mode active
lacp rate fast

3.0 Assign the Layer 3 Interface as the WMI

c9800(config)# wireless management interface vlan 10
Cisco 9800 WMI LAB Setup

For the purpose of this example, the following topology will be used, the edge firewall is configured with a destination NAT policy to map the external range 100.65.1.x /24 to an internal range 10.0.10.x /24.

Once the AP has discovered the WMI IP address of the WLC, via either DHCP (Option 43) or DNS (cisco-capwap-controller.domain.local) which in this instance is configured as 100.65.1.5, the CAPWAP discovery process is initiated.

Cisco 9800 WMI NAT Configuration

When reachability to the WMI is required behind a NAT boundary for AP join, it is necessary to modify the WLC configuration to only reply to the initial CAPWAP discovery request with the NATed IP of the WMI in the CAPWAP discovery response.

If the wireless controller is behind a NAT device, the controller responds to the discovery response in the following ways:

  • Using the public IP.
  • Using the private IP.
  • Using public and private IP.

This is achieved using the following commands.

c9800(config)# wireless management interface vlan 10
c9800(config-mgmt-interface)# public-ip 100.65.1.5

The default AP join profile is configured for both public and private IPs.

Within the CLI, there are no commands defined for discovery, unless one of these options is disabled.

Cisco 9800 WMI NAT Validation

As a result of this configuration, two CAPWAP discovery responses are sent from the WLC.

From experience, and after conducting several tests, it seems that it’s purely by chance whether the AP will choose to select the public or private IP to which to send the join request.

In the following capture you can see that two discovery responses were sent, one with the private IP and one with the public IP. Luckily this information is in clear text, as it occurs prior to the DTLS tunnel being setup between the AP and the WLC.

If the AP selects the WMI address sent in the discovery response presented as the real, not the NATed address, which typically is not routable or accessible from the AP management network then the join request will fail with the following error.

[05/12/2023 13:28:15.8760] Discovery Request sent to 100.65.1.5, discovery type STATIC_CONFIG(1) [05/12/2023 13:28:15.8780] Discovery Response from 100.65.1.5
[05/12/2023 13:28:22.0000] Started wait dtls timer (60 sec) [05/12/2023 13:29:23.7800] No more AP manager addresses remain..
[05/12/2023 13:29:23.7800] No valid AP manager found for controller ‘WLC-MER-01-R2-C9800-01’ (ip: 10.0.10.5) [05/12/2023 13:29:23.7800] Failed to join controller WLC-MER-01-R2-C9800-01.
[*05/12/2023 13:29:23.7800] Failed to join controller.

To correct this behaviour, the option to AP join profile should be ammended as such.

c9800(config)# ap profile default-ap-profile
c9800(config)# no capwap-discovery private
c9800(config)# country GB
c9800(config)# description "default ap profile"

Once this command has been entered, only one discovery response packet is sent from the WLC during the CAPWAP discovery process, with the public IP address defined in the CAPWAP message element.

And as expected, the AP succesfully completes the CAPWAP join process.

[05/12/2023 20:06:51.6480] CAPWAP State: Discovery [05/12/2023 20:06:51.6490] Got WLC address 100.65.1.5 from DHCP.
[05/12/2023 20:06:51.6490] IP DNS query for CISCO-CAPWAP-CONTROLLER.domain.local [05/12/2023 20:06:51.7580] Discovery Request sent to 100.65.1.5, discovery type DHCP(2)
[05/12/2023 20:06:51.7590] Discovery Request sent to 255.255.255.255, discovery type UNKNOWN(0) [05/12/2023 20:06:51.7600]
[05/12/2023 20:06:51.7600] CAPWAP State: Discovery [05/12/2023 20:06:51.8060] Discovery Response from 100.65.1.5
[05/12/2023 20:08:49.0000] Started wait dtls timer (60 sec) [05/12/2023 20:08:49.0000]
[05/12/2023 20:08:49.0000] CAPWAP State: DTLS Setup [05/12/2023 20:08:49.1270] dtls_verify_server_cert: Controller certificate verification successful
[05/12/2023 20:08:49.4810] [05/12/2023 20:08:49.4810] CAPWAP State: Join
[05/12/2023 20:08:49.4840] Sending Join request to 100.65.1.5 through port 5257 [05/12/2023 20:08:54.1270] Sending Join request to 100.65.1.5 through port 5257
[05/12/2023 20:08:58.8880] Sending Join request to 100.65.1.5 through port 5257 [05/12/2023 20:08:58.9490] Join Response from 100.65.1.5
[05/12/2023 20:08:58.9490] AC accepted join request with result code: 0 [05/12/2023 20:08:58.9490] Received wlcType 0, timer 30
[05/12/2023 20:08:59.0660] [05/12/2023 20:08:59.0660] CAPWAP State: Image Data
[05/12/2023 20:08:59.0660] AP image version 17.6.5.22 backup 17.6.4.56, Controller 17.6.5.22 [05/12/2023 20:08:59.0660] Version is the same, do not need update.
[05/12/2023 20:08:59.1200] status ‘upgrade.sh: Script called with args:[NO_UPGRADE]’ [05/12/2023 20:08:59.1620] do NO_UPGRADE, part1 is active part
[05/12/2023 20:08:59.1740] [05/12/2023 20:08:59.1740] CAPWAP State: Configure