Network Anti-Spoofing with SDN Data plane


Traditional DDoS anti-spoofing scrubbers require dedicated middleboxes thus adding CAPEX, latency and complexity in the network.

This work starts by showing that the current SDN match-and-action model is rich enough to implement a collection of anti-spoofing methods. Secondly we develop and utilize advance methods for dynamic resource sharing to distribute the required mitigation resources over a network of switches.

None of the earlier attempts to implement anti-spoofing in SDN actually directly exploited the match and action power of the switch data plane. They required additional functionalities on top of the match-and-action model, and are not implementable on an SDN switch as is. Our method builds on the premise that an SDN data path is a very fast and efficient engine to perform low level primitive operations at wire speed. The solution requires a number of flow-table rules and switch-controller messages proportional to the legitimate traffic. To scale when protecting multiple large servers the flow tables of multiple switches are harnessed in a distributed and dynamic network based solution. We have fully implemented all our methods in either OpenFlow1.5 in Open-vSwitch and in P4. The system mitigates spoofed attacks on either the SDN infrastructure itself or on downstream servers.




Software Defined DDoS Mitigation

The SDN data-plane is capable of operating in wire speed. Recently a new phase in the development of SDN has emerged, where the software running over the SDN infrastructure becomes richer, more flexible and capable of expressing more powerful network operation.

New SDN high level languages such as P4, and the corresponding appearance of SDN programmable switch like Intel FlexPipe and RMT enable SDN switches to carry out advanced packet modifications, including a richer set of key action primitives necessary to manipulate packet headers.

Only Match and Action

Our solution utilizes the data plane to efficiently implement a TCP cookie. The implemntation follows the SDN OpenFlow match and action model. No extra components/blocks are added to the switch.

The TCP authentication (3way handshake) is completed in the data plane. Any malicious traffic is dropped by the SDN switch. Thus, the controller is not flooded by the attack traffic. The controller is updated only in case of successfully authenticated sessions (legitimate traffic).

lior shafir
lior shafir

TCP Proxy: In this method, after being authenticated the mitigating device performs a handshake with the server and from here on acts as a proxy between the client and server for the entire duration of the connection. For each packet, in both directions, it has to adjust its server side sequence number as part of the TCP splicing. This is the main disadvantage of this method; the mitigation device has to see and process all the traffic (at least of the first connection from that client) in both directions, which may present a significant overhead.

lior shafir

HTTP Redirect: Here, after being authenticated the mitigating device installs a pinhole by recording the source IP of the connection as legitimate, then responds to the http get request with a corresponding http-redirect response, and finally closes the authenticated connection. Sending a redirect response with the same original server address causes the client to re-establish the connection. This time it will go directly to the server because of the installed pinhole.

TCP Reset: This method is similar to the HTTP Redirect method except that a RST packet is sent from the mitigating device to the client instead of an HTTP-Redirect response upon handshake completion. This technique do require application awareness, thus suitable with all TCP connections that retry to connect when a RST message is received.

lior shafir

Safe Reset: In this weak version of the SYN cookie, the switch responds to the initial SYN message with an SYN-ACK containing a bogus ACK number. If the client is compliant with RFC 793 (TCP), it immediately responds to the bogus ACK number with a RST packet containing the bogus ACK number as its sequence number (thus being authenticated). Then, 1 second after this, the client initiates a new connection by sending a new SYN request. This technique assumes no application-level awareness and requires only TCP compliance, thus is suitable not only for HTTP protocols but also SMTP and others.

lior shafir

DNS Spoofing Cookie: The SYN flood mitigation techniques appear above can be applied to mitigate a spoofed DNS request flood in SDN. A DNS spoofed attack exhausts the server bandwidth, CPU, and other resources by sending a large amount of spoofed DNS requests (over UDP port 53). Although the majority of DNS traffic is carried over UDP, DNS may also be carried over TCP. Thus, when the mitigating device receives a DNS UDP request from a source it has not authenticated before, it can force the client to repeat its request over TCP, and then perform a TCP authentication using a cookie. In order to force the client to repeat its first UDP request in TCP, the TC bit (Truncated - Indicates that the UDP response is too long to be carried by UDP) in the DNS header should be set in the response. This method is similar to the HTTP-Redirect method. The switch responds to the original UDP request by setting the TC bit. Then after the TCP handshake is completed, it forwards the TCP DNS request to the controller that translates the TCP to UDP both for the request and response from the DNS server. Finally, the controller installs rules (pinhole) to allow future DNS UDP requests from this authenticated source. Notice this method requires in the case of OpenFlow 1.5 an extension to allow setting the TC bit in the DNS response packet.

Open vSwitch Modifications

We chose to implement our solution in Open vSwitch version 2.3.1 that contains most of the latest OpenFlow 1.5 extensions. Open vSwitch gained much popularity as a flexible and general purpose virtual switch when the demand for complex virtual functions was fast increasing. To date, Open vSwitch is compatible with most hypervisors and containers under Linux (including Xen, KVM, and Docker).

Design Considerations:In Open vSwitch, the packet may be directed through user-space daemon main component (ovs-vswitchd) or through datapath-kernel-module. When a first packet of a flow has a kernel cache miss, it is directed to the user-space component using an upcall, the user-space forwarding actions for this packet are being cached in the kernel for subsequent packets of the same flow. We implemented the new actions that match and write the TCP header fields in the same way that TCP source and destination port set commands are implemented to allow efficient execution in the kernel-data-path. However, although the caching functionalities of Open vSwitch are based on microflows, and in recent versions also on megaflows, we saw in our experiments that a random spoofed ip-address attack is not cached efficiently in the kernel. All our additions and changes conform to the format, design and structure of OVS.

Code Changes in Open vSwitch:We added and modified 390 code lines in 26 files in Open vSwitch 2.3.1 to support the following missing matching and additional actions that are used by our methods:

For TCP-Reset and HTTP-Redirect:

  • write to SEQ number field
  • match/write to ACK number field
  • increment SEQ number field by one.
  • write to TCP-Flags field (the field is supported in OF 1.5 but write is not implemented in OVS)

For Safe-Reset:

  • write to ACK number field
  • match SEQ number field
  • write to TCP-Flags field

For TCP-Proxy:

  • write to SEQ number field
  • match/write to ACK number field
  • write to TCP-Flags
  • add a fixed value to SEQ/ACK number fields

The new TCP fields that our new actions deal with were added to ovs key tcp in order to fit exactly to the same API and structures of other similar field actions (TCP ports fields match/write). We used the inet proto csum replace2 and inet proto csum replace4 to calculate the checksum exactly in the same way that TCP ports modifications is performed in the kernel space.

lior shafir

Example: TCP-RESET implementation

We demonstrate the details of the implementation in Open vSwitch on one of the anti-spoofing methods, the TCP-Reset. After the controller has allocated cookies for each partition, (in this example the partition is done using subnets for simplicity) we show in the above figure an example of two rules that should be set in the switch flow-table in order to implement the the TCPReset method. The first rule (Fig. lines 2-6) matches SYN packets, write the cookie to the SEQ number field, and transform the SYN packet to a SYN-ACK packet, for each matched packet. The second rule (Fig. lines 8-14) matches an ACK packet with the correct cookie, then transforms it to a RST packet, and finally installs (using the learn action) another rule to allow traffic from the authenticated client. These two rules are for a single partition; Similar pairs of rules must be installed for each partition. We use ovs-ofctl tool to show the rules as a flow-table dump:

First Rule: In our example, as appears in the figure above (lines 2-6), all the SYN packets from 10.0.0.0/8 should be answered by replies with SEQ = 347834245. The rule contains the following actions:

move:NXM_OF_IP_DST[]->NXM_NX_REG0[]
move:NXM_OF_IP_SRC[]->NXM_OF_IP_DST[]
move:NXM_NX_REG0[]->NXM_OF_IP_SRC[]
//Actions to swap the IP addresses

move:NXM_OF_TCP_SRC[]->NXM_OF_TCP_DST[]
mod_tp_src:80
//These actions handle the TCP ports exchange. We assumed http, but a full swap can be used.

move:NXM_OF_ETH_SRC[]->NXM_OF_ETH_DST[]
mod_dl_src:00:00:00:00:00:02
//These actions swap the ETH addresses.

mod_tcp_seq:347834245
//This action sets 347834245 in the SEQ field

mod_tcp_ack:1
//This action responsible to set SEQ+1 in the ACK field (1 is a reserved number for this operation)

mod_tcp_flags:18
//sets 0x12 in the TCP-flags field; raise the ACK in addition to the SYN flag

IN_PORT
//return the SYN-ACK 'cooked' packet back to the sender.

Second Rule: This rule matches and validates ACK packets from 10.0.0.0/8 that have the correct ACK (347834246) number, and convert it into an RST packet that is sent back to the sender. As appears in the above figure, it contains the appropriate match attributes (nw src=10.0.0.0/8, +ack, ack num = 347834246) and contains similar actions as in the first rule (swap the IP, ETH addresses, and TCP ports). In this rule we also demonstrate how authenticated flows can be enabled in the switch without notifying the controller. We use the learn action (nx action learn - Nicira extensions) which causes the generation of a new table entry triggered by the current packet but for the future packets. The learn action allows us to generate a new table entry that allows traffic from the authenticated source IP to the server, locally on the switch. If such a function is not supported, the authenticated ACK should be sent to the controller, that will reactively set a similar pinhole flowentry. Formally, the actions that appear in this rule and that differ from those in the first rule are:

learn(table=0,hard_timeout=60,priority=65535, eth_type=0x800,NXM_OF_IP_SRC[],NXM_OF_IP_DST[],output:NXM_NX_REG1[1..2])
//The nx_action_learn as described above

mod_tcp_seq:347834246
//The SEQ number of the RST packet must be the same as the ACK number (347834246).

mod_tcp_flags:4
///Raise RST flag.

In the above figure, we show a TCP handshake (a Wireshark snapshot) in action, based on the rules we described above. The first packet is a SYN packet (#4) sent by the client (10.0.0.1) to the server. The switch replies by an SYN-ACK message (#5- generated by the first rule) encapsulating the corresponding cookie (SEQ number = 347834245). The client responds with an ACK message (#6 - with ACK number = 347834246) to complete the authentication. Then the switch replies by an RST message (#7 - generated by the second rule). In addition, a new ‘allow’ rule is being installed by the second rule for the authenticated flow. The client then performs another TCP handshake with the real server (#8-#10) and complete a successful HTTP request.

P4 (Programming Protocol-Independent Packet Processors) is a new programming language that appears to be the next step in the evolution of the OpenFlow protocol. One of the main goals of P4 is to propose a protocol independent abstraction. That is, allowing the developer to program network applications without being tied to a specific protocol and without assuming a fixed header format. The P4 abstraction level fits exactly to our solution requirements. Several key principles in P4 provide a natural API for our proposed network program, easing its design and implementation, thus generally demonstrating how more sophisticated data plane customizations can be adopted quickly using this approach. Here we briefly describe which key aspects of P4 are required by our task.

P4 (Programming Protocol-Independent Packet Processors) is a new programming language that appears to be the next step in the evolution of the OpenFlow protocol. One of the main goals of P4 is to propose a protocol independent abstraction. That is, allowing the developer to program network applications without being tied to a specific protocol and without assuming a fixed header format. The P4 abstraction level fits exactly to our solution requirements. Several key principles in P4 provide a natural API for our proposed network program, easing its design and implementation, thus generally demonstrating how more sophisticated data plane customizations can be adopted quickly using this approach. Here we briefly describe which key aspects of P4 are required by our task.


P4 - a natural API for our task

Configurable Packet Parser. P4 does not assume a fixed parser. The developer can define any custom subset of header formats. In our case, we use standard header formats (IP, TCP) but would like to interact with TCP header fields that are not supported by latest OpenFlow versions. It is often the case that an SDN switches can inspect and write to these fields but this capability is not exposed due to limitations of existing protocols. P4 however allows us to easily interact with any field within the TCP header without being restricted by standardization issues. Furthermore, the flow table rules that we define can operate on any one of the fields being received from the configurable parser using P4. Specifically, we can easily define TCP flags and SEQ/ACK matching and writing rules using P4.

General Packet Processing Primitives. In P4, the processing instructions are not a fixed set of actions. The developer can construct generic actions that can be built out of simple operations such as add, modify, remove, increment, etc. For example, the following are primitive actions from the latest P4 specification:

add_to_field - Add a value to a field.
copy_header - Copy one header instance to another.
modify_field - Set the value of a field..

These examples reflect the protocol-independence property. Unlike fixed protocol-dependent actions such as PUSH MPLS, POP VLAN, and SET NW TTL in existing protocols, the proposed P4 primitive actions are more natural and suitable for applications such as our solution that manipulate the packet to swap between header fields, increment the ACK field, and modify other fields in the TCP header

Configurable Packet Parser. P4 does not assume a fixed parser. The developer can define any custom subset of header formats. In our case, we use standard header formats (IP, TCP) but would like to interact with TCP header fields that are not supported by latest OpenFlow versions. It is often the case that an SDN switches can inspect and write to these fields but this capability is not exposed due to limitations of existing protocols. P4 however allows us to easily interact with any field within the TCP header without being restricted by standardization issues. Furthermore, the flow table rules that we define can operate on any one of the fields being received from the configurable parser using P4. Specifically, we can easily define TCP flags and SEQ/ACK matching and writing rules using P4.

Implementation under the P4 Environment:

P4 program consists of header, parser, table/actions and a control flow. First we added a TCP header definition to allow reading and matching based on the TCP fields. Since we modified the TCP fields, a TCP checksum recalculation should also be defined in the parser and must be explicitly declared within a P4 program. Then we defined logical tables that are matched based on the partitions, and applied the relevant actions that modify the SYN and ACK packets including writing the corresponding SEQ number into the packet. As appears here in the code represents the SYN matching table and the set cookie action), writing a P4 action reflects our intention in a very simple way:

action set_seq(seq_num, port) {
	modify_field(standard_metadata.egress_spec, port);
	modify_field(r_metadata.src_ipv4, ipv4.srcAddr);
	modify_field(r_metadata.src_mac, ethernet.srcAddr);
	modify_field(r_metadata.dst_port, tcp.dstPort);
	modify_field(ipv4.srcAddr, ipv4.dstAddr);
	modify_field(ethernet.srcAddr, ethernet.dstAddr);
	modify_field(tcp.dstPort, tcp.srcPort);
	add_to_field(tcp.seqNum, 1);
	modify_field(tcp.ackNum, tcp.seqNum);
	modify_field(tcp.seqNum, seq_num);
	add_to_field(ipv4.ttl, -1);
}
table handle_syn {
	reads {
		ipv4.srcAddr : ternary;
		ipv4.dstAddr : exact;
		tcp.srcPort : ternary;
		tcp.tcpFlags1 : exact;
	}
	actions {
		set_seq;
		_drop;
	}
	size: 512;
}

The P4 experimental platforms are developing these days. We used a behavioral model that has a software simulation with a Mininet plugin. The model compiles a P4 program into an executable simulation component, and also generates the API to be used to populate the flow tables’ rules during run-time. This allowed us to test the behavior of our packet modifications using Mininet, a TCP client (wget) and tcpdump.


OpenFlow and P4 - Our experience

The main difference we observed between OpenFlow and P4 is related to protocol-dependent issues. When starting to examine the feasibility of our solution in OpenFlow 1.5, we had to start bottom-up. Since protocol standardization and details are strongly tied with Open-Flow’s level of abstraction, questions like ’Which header fields can be accessed?’,’which bits can we manipulate in which version?’, and many other platform and protocol dependent issues turned to be our main concern at the beginning of our work. Indeed, adding match/modify of only few fields inside the Open-vSwitch code required plumbing of code into dozens of different files, despite the fact that those new actions were exactly the same as other actions that modify similar but different fields in the same header. As appears in the description above, implementing the same behavior in P4 enabled us to focus on our main task of defining our flow, in a more natural way, mapping our techniques into the relevant logical tables and actions. The resulted P4 program verbosity did reflect the actual task we were trying to perform, thereby, was at the appropriate abstraction level (and expressiveness level). P4 supported a natural top-down networking design. However, understandingly, we could not experiment the P4 outcomes at the same rich level as we could do with the OpenFlow implementation using the virtual switch (OVS). As a widely adopted and extensively used protocol, OpenFlow lets you test and deploy SDN applications on a diverse set of experimental platforms.