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.
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.
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
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.
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
July 21, 2009 at 4:33 p.m. UTC
clear and simple findings. Thanks :)
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.
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.
July 30, 2009 at 4:09 p.m. UTC
CoPP doesn't do any good here, as the amount of traffic needed to open 20 TCP connections is negligible (twenty 40-byte packets).
August 7, 2009 at 9:54 a.m. UTC
Hello. Thank you for this great info! Keep up the good job!
August 11, 2009 at 8:58 p.m. UTC
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."
September 29, 2009 at 6:46 p.m. UTC
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.