Stopping Denial of Service Attacks

Problem

You want to mitigate Denial of Service attacks by throttling half-open TCP connections.

Solution

You can configure a router to protect your servers against TCP SYN attacks by enabling the ip tcp intercept command:

Router1#configure terminal Router1(config)#access-list 109 permit ip any host 192.168.99.2 Router1(config)#ip tcp intercept list 109 Router1(config)#ip tcp intercept max-incomplete high 10 Router1(config)#ip tcp intercept one-minute high 15 Router1(config)#ip tcp intercept max-incomplete low 5 Router1(config)#ip tcp intercept one-minute low 10 Router1(config)#end Router1#

 

Discussion

This feature allows the router to take an active role in managing the TCP session initiation between a client and server. In the normal TCP call setup procedure, a client device sends a TCP SYN packet to start the session. The server then responds with a SYN-ACK, and the client's next packet simply has the ACK flag set. Then the Layer 7 application information can start to flow. A relatively common denial of service attack involves sending large numbers of SYN packets, but never actually starting the session. This can fill up the server's connection table with these so-called "half-open" TCP sessions, and eventually prevents any legitimate sessions from starting.

However, when you enable the TCP Intercept feature, the router doesn't forward the initial SYN packet to the server. Instead, it responds directly to the client with a SYN-ACK packet, as if it were the server. If the client is legitimate and begins the TCP session, then the router quickly opens a session to the server, knits the two ends of the connection together, and steps into its more usual role of simply forwarding packets.

If the number of half-open sessions exceeds certain configurable thresholds, the router can protect the server by going into aggressive mode. In this mode, the router does three things:

In the configuration example, the first two lines enable the TCP Intercept feature:

Router1(config)#access-list 109 permit ip any host 192.168.99.2 Router1(config)#ip tcp intercept list 109

Here we have defined an ACL that specifies that we are only interested in packets with a destination IP address of 192.168.99.2, which is the server that we intend to protect. You could just as easily create an ACL that would protect a range of addresses. For example, if we wanted to protect all of the devices on the 192.168.99.0/24 subnet, we could have used the following access-list:

Router1(config)#access-list 109 permit ip any 192.168.99.0 0.0.0.255

We don't recommend using a permit ip any any type access-list here because that would force the router to intercept all TCP sessions passing through it, regardless of source or destination. This could cause performance problems on your network.

Then the command ip tcp intercept list enables the TCP intercept feature for the addresses specified in the access-list. Note that this is a global configuration command. It is not specific to an interface. This is useful because one common way to launch this type of attack is to send TCP SYN packets simultaneously from compromised computers throughout the network. If you have several interfaces on your router, you won't in principle know where to expect the packets to originate. It also means that you can protect servers on several different segments with a single command.

The remaining commands in the example simply configure the thresholds for aggressive mode. By default, the router allows 1,100 half-open sessions before going into aggressive mode. Configure this value using the ip tcp intercept max-incomplete high command. In the example, we have set a very low value for demonstration purposes:

Router1(config)#ip tcp intercept max-incomplete high 10

When we deliberately initiate a series of half-open sessions, we see this log message:

Nov 15 13:56:38.944: %TCP-6-INTERCEPT: getting aggressive, count (10/10) 1 min 0

A short time later, the attack ended, and the router went back into its normal mode:

Nov 15 13:58:14.367: %TCP-6-INTERCEPT: calming down, count (0/5) 1 min 11

We will explain the conditions for returning to the normal mode in a moment:

In addition to the total number of half-open sessions, you can also set thresholds on the number of TCP sessions initiated per minute:

Router1(config)#ip tcp intercept one-minute high 15

In this case, we have set the rather low threshold value of 15 for demonstration purposes. In practice, you would almost certainly want to use much higher numbers than these because these thresholds define the total number of connection attempts, whether successful or not. So setting this value too low will mean that your server will not be able to accept very many legitimate sessions.

The conditions for returning to normal mode are defined by these two commands:

Router1(config)#ip tcp intercept max-incomplete low 5 Router1(config)#ip tcp intercept one-minute low 10

The first command sets the low-water mark for the total number of half-open sessions, while the second command sets the low-water mark for the number of session-initiation attempts per minute. The router will not return to normal mode until both of these conditions are true. The default value for both of these thresholds is 900.

In production networks, we recommend initially leaving the thresholds at their default values and establishing a baseline for what is normal. Setting your thresholds too high could be of minimal benefit, while consuming large amounts of router memory. And using thresholds that are too low could be functionally the same as the denial of service attack you are trying to defend against.

The TCP Intercept feature also allows you to monitor for inactivity on the TCP sessions that it helped to initiate. By default, the router will allow a TCP session to be inactive for 24 hours (86,400 seconds). However, you can change this using the ip tcp intercept connection-timeout command, which accepts an argument in seconds. Here we set a maximum value of one hour:

Router1(config)#ip tcp intercept connection-timeout 3600

When this time is exceeded, the router will force a disconnection on this session.

As we mentioned earlier, by default the aggressive mode of the TCP Intercept feature will drop the oldest half-open connection each time it receives a new connection attempt. However, you can instead configure it to drop a randomly selected connection out of the table:

Router1(config)#ip tcp intercept drop-mode random

The theory behind this is that the attack might be very short lived. In this case, the oldest entries in the table are probably the only ones that are not associated with the attack, so you might prefer to drop a random session instead.

You can configure how long the router will watch a session, waiting for it to complete the TCP session initiation. By default, it waits 30 seconds, but you can change this value with the following command, which specifies this timeout value in seconds:

Router1(config)#ip tcp intercept watch-timeout 15

And one final option allows you to set whether the router actively intercepts and responds to TCP SYN packets, or instead allows these packets to pass through normally, but watches the session to ensure that it connects properly. By default the router will completely protect the server by taking over all responsibility for setting up the session. You can configure it to let the server handle the call, and only step in if there is a problem by configuring watch mode:

Router1(config)#ip tcp intercept mode watch

This is useful in situations when your router is watching a large number of servers or the server is configured to safely handle large numbers of half-open sessions. In such situations, you can save resources on your router by using watch mode.

There are two commands for monitoring the TCP Intercept feature. The first looks at the entire connection table:

Router1#show tcp intercept connections Incomplete: Client Server State Create Timeout Mode 192.168.100.201:3304 192.168.99.2:23 SYNRCVD 00:00:11 00:00:07 I 192.168.100.201:3305 192.168.99.2:23 SYNRCVD 00:00:08 00:00:02 I 192.168.100.201:3300 192.168.99.2:23 SYNRCVD 00:00:18 00:00:04 I 192.168.100.201:3301 192.168.99.2:23 SYNRCVD 00:00:16 00:00:06 I 192.168.100.201:3302 192.168.99.2:23 SYNRCVD 00:00:15 00:00:07 I 192.168.100.201:3303 192.168.99.2:23 SYNRCVD 00:00:13 00:00:01 I 192.168.100.201:3297 192.168.99.2:23 SYNRCVD 00:00:23 00:00:07 I 192.168.100.201:3298 192.168.99.2:23 SYNRCVD 00:00:21 00:00:09 I 192.168.100.201:3299 192.168.99.2:23 SYNRCVD 00:00:20 00:00:10 I Established: Client Server State Create Timeout Mode 192.168.100.1:26643 192.168.99.2:23 ESTAB 00:00:04 23:59:56 I Router1#

You will notice that there are usually very few sessions listed as Established at the end of this display. This is because the router only includes those sessions that have been established but for which it has not yet completely stepped out of the picture. This command output is useful for looking at who is attacking your servers. In this case, it looks like there is somebody attacking our server from the IP address 192.168.100.201. However, if you are using higher thresholds, this output is awkward to use.

Another command that is particularly useful with higher threshold values looks at the gross statistics:

Router1#show tcp intercept statistics Intercepting new connections using access-list 109 9 incomplete, 1 established connections (total 10) 8 connection requests per minute Router1#

In this case, you can see that there are nine incomplete sessions and one established. This output also shows the number of connection attempts per minute.

Категории