Filtering Based on TCP Header Flags
Problem
You want to filter on the flag bits in the TCP header.
Solution
The following ACL blocks several illegal combinations of TCP header flags:
Router1#configure terminal
Enter configuration commands, one per line. End with CNTL/Z.
Router1(config)#access-list 161 deny tcp any any ack fin psh rst syn urg
Router1(config)#access-list 161 deny tcp any any rst syn
Router1(config)#access-list 161 deny tcp any any rst syn fin
Router1(config)#access-list 161 deny tcp any any rst syn fin ack
Router1(config)#access-list 161 deny tcp any any syn fin
Router1(config)#access-list 161 deny tcp any any syn fin ack
Router1(config)#end
Router1#
Beginning with IOS Version 12.3(4)T, Cisco changed the format of TCP flag filtering, while still maintaining support for the legacy method. The following is the same example as above using the new TCP flag filtering method:
Router2#configure terminal
Enter configuration commands, one per line. End with CNTL/Z.
Router2(config)#ip access-list extended TCPFLAGFILTER
Router2(config-ext-nacl)#deny tcp any any match-all +ack +fin +psh +rst +syn +urg
Router2(config-ext-nacl)#deny tcp any any match-all +rst +syn
Router2(config-ext-nacl)#deny tcp any any match-all +rst +syn +fin
Router2(config-ext-nacl)#deny tcp any any match-all +rst +syn +fin +ack
Router2(config-ext-nacl)#deny tcp any any match-all +syn +fin
Router2(config-ext-nacl)#deny tcp any any match-all +syn +fin +ack
Router2(config-ext-nacl)#end
Router2#
Discussion
There are six flag bits in the TCP header that the devices use to control the session:
-
Acknowledgment.
-
Synchronize sequence numbers at the start of the session.
-
Terminate the session.
-
Reset the session.
-
Push this data to the application immediately; this usually means that all of the data has been sent.
-
Look at the Urgent pointer later in the packet.
TCP uses a so-called three-way handshake to set up sessions. To start a session, the client device sends a packet with the SYN bit, which is an instruction to synchronize sequence numbers. The server device responds with a packet that has both SYN and ACK bits set, which the first device then acknowledges with an ACK to complete the handshake process.
The session teardown procedure is similar, but it actually uses four packets instead of three. One device sends the other a packet with the FIN bit set. The second device then responds to this with an ACK. Then, in a separate packet, the second device sends its own FIN, which the first device responds to with an ACK to terminate the session.
Devices use the RST flag for a couple of different reasons, but one of the most common is the so-called abortive close. This happens when one device can't wait around for the other device to acknowledge the end of the session by using the normal FIN and ACK pattern. So it simply sends a packet that has both the RST and ACK bits set to end the session. There is no need for the other device to respond to this packet.
Obviously, some combinations of these bits are not valid, however. For example, it makes no sense to have a single packet with both the SYN and FIN bits set. And, in defining test cases for TCP implementations, RFC 1025 defines a packet with all six bits set as a nastygram (or a kamikaze packet, Christmas tree packet, or lamp test segment). The first line in the example ACL blocks nastygrams:
Router1(config)#access-list 161 deny tcp any any ack fin psh rst syn urg
The remaining lines block other illegal combinations of flags.
As mentioned in the Solution section, Cisco introduced a new method of filtering based on TCP flags that provides far greater control over the legacy method. Users can now match on TCP flags that are set, as well as TCP flags that are not set. In addition, you can now filter on any combination of TCP flags.
Cisco has introduced two new keywords: match-any and match-all. The match-any keyword matches the specified TCP flag(s), regardless of whether other TCP flags are set or not. In contrast, the match-all keyword only matches the exact specified TCP flags, and if others are set, then no match is made.
Let's take a look at an example:
Router2(config-ext-nacl)#permit tcp any any match-all +syn
Router2(config-ext-nacl)#permit tcp any any match-any +syn
Even though the two commands look nearly identical, their filtering behavior is quite different. The match-all command only permits TCP packets with the SYN bit set. If any other TCP flag is enabled, then it won't match this ACL entry. On the other hand, the match-any command will match all TCP packets that have the SYN bit set regardless of whether any other TCP flag is enabled. The match-any command emulates the legacy TCP flag filtering behavior.
As we mentioned earlier, the new method also permits us to filter on TCP flags that are not set. Instead of using a "+" sign, we use a "-" to identify which unset TCP flags to filter on. For example:
Router2(config-ext-nacl)#permit tcp any any match-any -syn
In this example, only TCP packets that don't have the SYN bit enabled will be permitted. There was no way of matching unset flags using the legacy method of TCP flag filtering.