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.
 |
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.