Thursday, January 16, 2014

Cisco ASA Packet Capture

The ASA platform has fantastic built-in packet capture capabilities which can come in very handy for troubleshooting issues. I will be demonstrating some of the capabilities using an ASA 5505 running version 9.0(1).

Performing a packet capture is done using the capture command from privileged exec mode.

asa5505(config)# capture asa_cap ?

exec mode commands/options:
  access-list      Capture packets that match access-list
  buffer           Configure size of capture buffer, default is 512 KB
  circular-buffer  Overwrite buffer from beginning when full, default is non-circular
  ethernet-type    Capture Ethernet packets of a particular type, default is IP
  headers-only     Capture only L2, L3 and L4 headers of packet without data in them
  interface        Capture packets on a specific interface
  match            Capture packets matching five-tuple
  packet-length    Configure maximum length to save from each packet, default is 1518 bytes
  real-time        Display captured packets in real-time. Warning: using this option with a slow console connection may
                   result in an excessive amount of non-displayed packets due to performance limitations.
  trace            Trace the captured packets
  type             Capture packets based on a particular type

A common scenario is to determine if you are seeing bidirectional traffic to a host on the internet. For this example, I'm going to validate that I am seeing IP traffic to, one of Google's public DNS servers.

! We will start with defining an access-list to match the traffic

access-list asa_cap extended permit ip any4 host
access-list asa_cap extended permit ip host any4

! Next we define the packet capture

capture asa_cap interface inside access-list asa_cap
We can verify the config by running 'show capture'.
capture asa_cap type raw-data access-list asa_cap interface inside [Capturing - 9648 bytes]

Looking at the results, you should notice that it automatically added the type 'raw-data' and also lists the amount of captured data. The raw-data type will capture any IP traffic that is transmitted through the ASA.
Now we can look at the captured data using 'show capture asa_cap'.
asa5505# sh cap asa_cap

177 packets captured

   1: 20:14:01.763006       802.1Q vlan#1 P0 >  udp 32
   2: 20:14:01.799824       802.1Q vlan#1 P0 >  udp 112
   3: 20:14:04.794056       802.1Q vlan#1 P0 >  udp 32
   4: 20:14:04.831988       802.1Q vlan#1 P0 >  udp 112
   5: 20:14:07.820529       802.1Q vlan#1 P0 >  udp 32
   6: 20:14:07.866303       802.1Q vlan#1 P0 >  udp 112

Each captured packet shows a timestamp of the time the packet was received, the VLAN ID since this is a 5505, the source IP and port, the destination IP and port, the type of packet, and the packet size. For TCP traffic it will also list the TCP MSS size which can be extremely helpful for troubleshooting MTU issues.
You can also examine a specific packet using the 'packet-number ' keyword and view some more packet details using the 'details' keyword. The details will include the TCP window size, TCP flags such as SYN and ACK, TTL, and if the DF bit is set.
If I want to do a quick packet capture, I typically skip the access-list altogether. You can do it inline using a 5-tuple match. A 5-tuple match uses 5 values to match a packet for the capture. Those values are protocol, source IP address, source port, destination IP address, and destination port. I also use the real-time keyword so that it will buffer the captured packets as well as follow them on the screen.
This time will capture packets to one of Google's web servers. Note that if you specify the capture traffic inline you do not need to specify the return traffic, it will match that automatically.

asa5505# capture asa_cap2 interface inside real-time match ip any host

Warning: using this option with a slow console connection may
         result in an excessive amount of non-displayed packets
         due to performance limitations.

Use ctrl-c to terminate real-time capture

   1: 20:35:14.573273       802.1Q vlan#1 P0 > S 1157924479:1157924479(0) win 8192 
   2: 20:35:14.574768       802.1Q vlan#1 P0 > S 3232879419:3232879419(0) win 8192 
   3: 20:35:14.614241       802.1Q vlan#1 P0 > S 3782939017:3782939017(0) ack 1157924480 win 42900 
   4: 20:35:14.617476       802.1Q vlan#1 P0 > . ack 3782939018 win 68
   5: 20:35:14.618284       802.1Q vlan#1 P0 > S 4201067853:4201067853(0) ack 3232879420 win 42900 
   6: 20:35:14.620130       802.1Q vlan#1 P0 > . ack 4201067854 win 68
   7: 20:35:14.649044       802.1Q vlan#1 P0 > P 1157924480:1157924818(338) ack 3782939018 win 68
   8: 20:35:14.688974       802.1Q vlan#1 P0 > . ack 1157924818 win 666
   9: 20:35:14.747443       802.1Q vlan#1 P0 > . 3782939018:3782940278(1260) ack 1157924818 win 666
  10: 20:35:14.748343       802.1Q vlan#1 P0 > . 3782940278:3782941538(1260) ack 1157924818 win 666
  11: 20:35:14.750434       802.1Q vlan#1 P0 > . 3782941538:3782942798(1260) ack 1157924818 win 666
  12: 20:35:14.750479       802.1Q vlan#1 P0 > . 3782942798:3782944058(1260) ack 1157924818 win 666
  13: 20:35:14.750510       802.1Q vlan#1 P0 > . 3782944058:3782945318(1260) ack 1157924818 win 666
  14: 20:35:14.750556       802.1Q vlan#1 P0 > . 3782945318:3782946578(1260) ack 1157924818 win 666
  15: 20:35:14.753348       802.1Q vlan#1 P0 > . ack 3782941538 win 68
  16: 20:35:14.753394       802.1Q vlan#1 P0 > . 3782946578:3782947838(1260) ack 1157924818 win 666
  17: 20:35:14.753440       802.1Q vlan#1 P0 > . 3782947838:3782949098(1260) ack 1157924818 win 666
  18: 20:35:14.753485       802.1Q vlan#1 P0 > . 3782949098:3782950358(1260) ack 1157924818 win 666
  19: 20:35:14.753516       802.1Q vlan#1 P0 > . 3782950358:3782951618(1260) ack 1157924818 win 666

You can also use the packet capture functionality to see any packet drops on the firewall. This can be helpful if you are not seeing bidirectional traffic with a raw packet capture even though you are expecting it. This is done using the 'type asp-drop'. You can also specify they type of drop, such as acl_drop or no_route. For our purposes, we will capture all drop types.
capture drop_cap type asp-drop all

   1: 20:43:54.793934       802.1Q vlan#1 P0 >  udp 125
   2: 20:43:55.827960       802.1Q vlan#1 P0 >  udp 125 Drop-reason: (acl-drop) Flow is denied by configured rule
   3: 20:43:56.830462       802.1Q vlan#1 P0 >  udp 125 Drop-reason: (acl-drop) Flow is denied by configured rule

You can see that my workstation is sending out multicast discovery messages for UPnP and my the ASA does not forward multicast packets by default, so it drops them.
At this point we have created a packet capture to capture raw packets matched by an access-list or inline. We have also captured dropped packets. But what if you want to examine the packet captures in even more details than what the ASA can provide? Thankfully the ASA has a way of downloading the pcap file. You can accomplish this through the copy command.
asa5505# copy /pcap capture:asa_cap2 tftp

Source capture name [asa_cap2]?

Address or name of remote host []?

Destination filename [asa_cap2]? asa_cap2.pcap
671 packets copied in 6.110 secs (111 packets/sec)
If you exclude the /pcap flag, the capture will still be uploaded to your tftp server, but it will be uploaded in the same format in which it's displayed using the 'show capture ' command. You can see below it displays the capture in Wireshark the same as it would if you ran the packet capture locally on your PC.

Click to enlarge

Other Thoughts

The packet capture is a powerful and useful tool that can be used to easily troubleshoot a lot of network and firewall issues. What I've demonstrated above is an overview of some of the capabilities. I urge you to explore deeper into this tool and discover everything else you can do. You can use it to capture different ethertype packets, encrypted and decrypted IPSec traffic if it is terminated at the ASA, webvpn traffic, and more.

One of my favorite uses is to prove (or disprove) proper NAT configuration. This was especially helpful when I was learning the changes that were first introduced in the 8.3 firmware. I will create two captures. One will capture traffic on the inside interface (on ingress) to a particular destination and one will capture traffic on the outside interface (on egress). The outside capture should show the outside local IP address as the source (and destination for return traffic). You can compare the two captures using timestamps and TCP data, such as source port. This can be a quick way to validate that your NAT configuration is good, or show that it needs some more work.