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:
- It reduces the retransmission timeout from one second to 0.5 seconds, so that the TCP SYN-ACK packets are sent more frequently. This ensures that any legitimately half-open sessions are given an opportunity to respond.
- It reduces the maximum time that it will maintain a half-open session from the default 30 seconds to 15 seconds. Again, there are many reasons why a client might be legitimately slow to respond, but if the server is under attack, then reducing these timers can help to clear out the sessions that aren't legitimate.
- And, most importantly, with each new connection attempt, the router will delete one half-open session from its table. By default, it will delete the oldest session, but you can instead configure it to drop a random entry from the table.
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.
|
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.