Using uRPF at the access layer to deter DDoS attacks

By stretch | Monday, July 20, 2009 at 12:38 a.m. UTC

How do you protect your infrastructure devices from unauthorized virtual terminal connections? Arguably the most common configuration is a simple inbound ACL applied to the VTY lines or control plane, something like the following:

ip access-list standard PROTECT_VTY
 permit 10.0.0.0 0.0.0.255
!
line vty 0 15
 access-class PROTECT_VTY in

While this will prevent hosts outside of the specified range(s) from connecting, it unfortunately does nothing to protect against one of the most trivial (D)DoS attacks: the TCP SYN flood.

The Attack

A TCP SYN flood attack is accomplished by transmitting an excess of TCP SYN packets to a host in order to exhaust its incoming TCP connection queue. For each valid received SYN, a host (for the sake of this scenario, a router) must record each half-open connection in a temporary queue in anticipation of the following ACK when the TCP handshake is completed. Unfortunately, the size of this queue on most TCP/IP stack implementations is relatively small and easily exhausted; IOS 12.4T, for example, can handle only 20 half-open inbound connections to its VTY daemons.

When the victim's TCP connection queue is full, no new connections will be accepted, from authorized hosts or otherwise. So long as the attack continues, administrators will be unable to initiate new in-band terminal connections to their affected devices. To make matters worse, only empty TCP packets are needed to perform a SYN flood; a single malicious or infected host can easily sustain an attack against hundreds or thousands of victims across a local network.

To better understand how a TCP SYN flood can impair in-band network management, we can launch a simple attack against the router in our configuration example above. We can use a raw packet generator like scapy to generate TCP SYN packets at a constant rate, sourced from random spoofed addresses within the allowed management network (10.0.0.0/24):

>>> send(IP(src=RandIP('10.0.0.0/24'), dst='192.168.0.1')/TCP(sport=RandShort(),
 dport=22), loop=1)

NOTE: Issuing this command in a live environment is potentially a resume-generating event. Do not attempt this attack on a production network without authorization.

Appending the loop=1 parameter to scapy's send() command instructs it to regenerate and retransmit the packet at a constant rate indefinitely. On the victim router, we can see that the TCP connection queue is immediately exhausted:

R1# show control-plane host open-ports
Active internet connections (servers and established)
Prot               Local Address             Foreign Address                  Service    State
 tcp                        *:22            10.0.0.209:21704               SSH-Server ESTABLIS
 tcp                        *:22             10.0.0.184:4075               SSH-Server ESTABLIS
 tcp                        *:22            10.0.0.204:45665               SSH-Server ESTABLIS
 tcp                        *:22                         *:0               SSH-Server   LISTEN
 tcp                        *:23                         *:0                   Telnet   LISTEN
 tcp                        *:22             10.0.0.68:26559               SSH-Server ESTABLIS
 tcp                        *:22              10.0.0.0:40397               SSH-Server ESTABLIS
 tcp                        *:22            10.0.0.223:65093               SSH-Server ESTABLIS
 tcp                        *:22              10.0.0.4:24615               SSH-Server ESTABLIS
 tcp                        *:22            10.0.0.158:30095               SSH-Server ESTABLIS
 tcp                        *:22            10.0.0.246:35431               SSH-Server ESTABLIS
 tcp                        *:22              10.0.0.67:5708               SSH-Server ESTABLIS
 tcp                        *:22             10.0.0.18:23424               SSH-Server ESTABLIS
 tcp                        *:22            10.0.0.132:24587               SSH-Server ESTABLIS
 tcp                        *:22             10.0.0.26:15867               SSH-Server ESTABLIS
 tcp                        *:22             10.0.0.53:28094               SSH-Server ESTABLIS
 tcp                        *:22            10.0.0.243:26208               SSH-Server ESTABLIS
 tcp                        *:22            10.0.0.106:22409               SSH-Server ESTABLIS
 tcp                        *:22             10.0.0.50:23524               SSH-Server ESTABLIS
 tcp                        *:22             10.0.0.173:4664               SSH-Server ESTABLIS
 tcp                        *:22             10.0.0.67:19703               SSH-Server ESTABLIS
 tcp                        *:22             10.0.0.12:24496               SSH-Server ESTABLIS

Note that although each session is listed with a state of "established," the router has not received the final ACK from the spoof sourced, and it never will. Each of these connections will remain in memory for 30 seconds (this time will differ among stack implementations) until it expires. Assuming a constant, short-interval flood, the expired connection is almost sure to be immediately replaced with a new false connection before a valid connection can be attempted.

Obviously, there are two caveats to this attack: first, the attacker must know an authorized management subnet from which to spoof the SYN packets. Second, remember that the router is sending SYN/ACK replies to each of the sessions it accepts in it queue; if the spoofed source belongs to a legitimate, reachable machine, that machine will (or should) send a RST back to the router. When this happens, the corresponding half-open session will be immediately purged from the queue. Of course, a crafty attacker can easily get around both of these limitations, as typically only a single open authorized IP address is needed.

Mitigation

SYN flooding is certainly nothing new or complex, yet many networks are left vulnerable to the attack despite the relative ease of mitigation. As in mitigating many denial of service attacks, the idea is simply to prevent spoofed packets from reaching the target. On an enterprise network, this can generally be accomplished in one of two ways at the access edge:

  • deny user traffic destined for infrastructure devices, or;
  • allow only traffic from valid user subnets.

As it's preferable to deny by default and enforce a white list, most engineers will find the second option more appealing. Plus, it's easy to accomplish on IOS using uRPF:

R1(config)# interface f0/0
R1(config-if)# ip verify unicast source reachable-via rx

Applied to an access interface (an interface acting as the first-hop for a host subnet), the router will now accept only packets sourced from that interface's assigned subnet(s). This source filtering impedes not only the SYN flood against infrastructure devices demonstrated here, but any attack which relies on IP source spoofing.

About the Author

Jeremy Stretch is a network engineer living in the Raleigh-Durham, North Carolina area. He is known for his blog and cheat sheets here at Packet Life. You can reach him by email or follow him on Twitter.

Posted in Security

Comments


Roland Dobbins (guest)
July 20, 2009 at 2:06 a.m. UTC

As noted before in response to your blackhole article, combining uRPF with a BGP-triggered blackhole allows one to blackhole based upon source IPs, which is far more useful than destination-oriented blackholing. This technique is referred to as S/RTBH.

Also, enabling NetFlow telemetry for visibility is key to detecting, classifying, and tracing back network traffic, including DoS traffic. NetFlow may be exported from routers and utlilized with a variety of open-source and commercial tools; it may also be used on the command-line via various permutations of the 'sh ip cache flow' command.


hack2learn (guest)
July 20, 2009 at 3:55 a.m. UTC

Nice and helpful article. So many enterprise network administrator dont care about security or DDOS Attacks at all. thats sad


shivlu jain (guest)
July 21, 2009 at 4:33 p.m. UTC

clear and simple findings. Thanks :)


Murali Suriar (guest)
July 21, 2009 at 5:46 p.m. UTC

One caveat with uRPF is reachability of HSRP standby interfaces. If you have multiple routers on a subnet, then off-subnet traffic to at least some of the router interfaces on that subnet will traverse the L2 subnet and hence will fail a uRPF check. Management tools that alert on reachability of interfaces may raise complaints about this.

One way around this is to use:

ip verify unicast source reachable-via rx <acl>

which checks packets against an ACL if they fail the uRPF check. This allows you to grant your management hosts access across subnets for the purposes of reachability testing.

NOTE: depending on code version, this feature can cause large numbers of packets to be CPU switched. For example, in 12.2(18)SXF, any release before SXF13 (I think) will punt any packets that don't hit the ACL to the CPU, while packets that do hit the ACL are switched in TCAM. Later releases swap this behaviour around, so that 'spurious' traffic is CPU switched.


Ciscozine.com (guest)
July 30, 2009 at 5:54 a.m. UTC

It is possible protect our router/switches using the CoPP feature. The control plane policing (CoPP) feature significantly improves upon the rACL feature. Whereas rACLs allow the configuration of basic “permit” and “deny” filters for traffic destined to the router CPU, the CPP feature extends this by allowing users to configure a quality of service (QoS) filter that can also “rate-limit” this traffic.


stretch
July 30, 2009 at 4:09 p.m. UTC

@Ciscozine:

CoPP doesn't do any good here, as the amount of traffic needed to open 20 TCP connections is negligible (twenty 40-byte packets).


johnny (guest)
August 7, 2009 at 9:54 a.m. UTC

Hello. Thank you for this great info! Keep up the good job!


David (guest)
August 11, 2009 at 8:58 p.m. UTC

Murali Suriar,

Can you elaborate more on this statement?

"One caveat with uRPF is reachability of HSRP standby interfaces. If you have multiple routers on a subnet, then off-subnet traffic to at least some of the router interfaces on that subnet will traverse the L2 subnet and hence will fail a uRPF check."

Thanks


Murali Suriar (guest)
September 29, 2009 at 6:46 p.m. UTC

@David:

Consider the following topology:

  R1          R2
   |.2         |.3
-----------------------
Vlan100:192.168.100.0/24

R1 and R2 are distribution routers on a subnet, and both have equal cost uplinks connecting to the rest of the network.

Assume you have HSRP running between R1 and R2 on Vlan100 (HSRP address 192.168.100.1), and the Vlan100 interfaces on R1 and R2 are costed at 20 and 40 respectively in your IGP.

Consider management traffic sourcing from a subnet that is not directly connected to either R1 or R2 (Source IP: 10.10.10.10). Traffic to R2's Vlan100 interface (192.168.100.3) from off subnet will be routed to R1, as Vlan100 is advertised at a lower cost from R1. R1 will then forward the packet across the Vlan, as 192.168.100.0/24 is a directly connected interface.

R2 will receive this packet, sourcing from 10.10.10.10, on its Vlan 100 interface, however uRPF will be expecting traffic from this source to come from an uplink interface, and will drop the packet.

Hope that helps.

Leave a Comment


Optional; will not be displayed publicly or given out.
No commercial links. Only personal (e.g. blog, Twitter, or LinkedIn) and/or on-topic links, please.
What protocol is used to retrieve web pages?