Skip to content

fabianbergmark/splitter

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

24 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Splitter Documentation

Introduction

Splitter is intended to be a network tool for creating transparent high performance, highly stable connections over WAN and LAN connections, with built-in support for advanced networking features such as SCTP multi-homing.

Planned use

Splitter is developed to be the work-horse in a pocket-router based on Raspberry PI. The router will act as a bridge between one client and several connected devices with WAN access.

Modes of operation

Achieving high speed and stability can be done both in several ways the protocol. Its iteresting to explore different solutions as they offer different capabilities and faces different problems.

Protocol layer

Using a client-server model, it’s possible to create a single SCTP association, utilizing the advanced multi-homing and fault-tolerance built into the protocol. This connection can be used to tunnel TCP (useful for SOCKS-data), IP (TUN) or Ethernet (TAP) frames. The later of the two would be easily implemented by patching OpenVPN with SCTP support.

Split routing

It is possible to achieve load balancing by routing traffic trough all available interfaces. In short it is achieved by creating multiple routing tables, each using a different default interface, and distribute routing lookups between these tables.

Test Suite

As with all development of network protocols, its necessary to evaluate variables in a reproducible and controllable environment that can be used to model several real-world variables such as package-loss, delays and bandwidth-throttling. The git repository includes a test branch with a test-suit for testing the splitter tool under various network layouts and conditions.

Obstacles

Application layer

SCTP was developed to facilitate special needs in the telecom industry that wasn’t satisfied by the available network protocols. It has unfortunately made slow progress outside this domain. This can be explained by the fact that it is somewhat more difficult to build applications using SCTP, and legacy NATs. SCTP is a general multi-purpose protocol. As such it has to impose several limitations on the protocol features. It might be interesting to remove some of these limitations when developing a single-purpose tool.

Protocol support

As a not-widely used protocol, SCTP suffers from lacking support in networking hardware. Gateways usually only support TCP and UDP port forwarding, making it impossible to run more than one public SCTP application on a network. Additionally, the widespread use of TCP has led to protocol-specific code has been added to NAT-implementations for TCP. This allows several internal addresses to use the same public address and still use the same port for their connections. This is referred to as Network Address and Port Translation (NAPT). An initial research showed that the lack of SCTP support in NATs is a serious impediment when used with mobile tethering.

Load balancing

The current specification of the SCTP protocol only allows using the mulihoming functionality for fault-tolerance purposes. This main reason is said to be lacking theory for multi-homed connections. However, in the simpler server-client model there might be possible to successfully implement load-balancing features.

Physical layer

The inability to control the network options for the thetered network hosted by the phone enforces some limitations on how load-balancing can be achieved. For example, the network hosted by an iPhone always has the subnet 172.20.10.0/28.

Modules and Libraries

Recent versions of the Linux kernel includes an SCTP protocol stack. Several user-space libraries interfaces with this stack. Libsctp provided by the lksctp suit implements and extends the sockets API to work with SCTP and should thus feel familiar with other network programming. Sctplib is used as a reference implementation mainly for the UDP-encapsulation feature.

Used terms and technologies

SCTP

SCTP, or Stream Control Transmission Protocol is sometimes referred to as the third transport layer protocol after TCP and UDP. It was developed for the telecom industry to be a high performance and fault-tolerant protocol. SCTP combines the features of TCP and UDP and adds several new.

  • Message based - SCTP sends data in groups called messages. As with UDP, messages are sent and received in one operation.
  • Multi-streaing - SCTP offers the capability to transmit several independent stream in parallel, avoiding Head-of-line blocking.
  • Multi-homing - SCTP extends the notion of a connection between TCP peers to allow for multiple endpoints on both sides, called an association. This allows for transparent fail-over between redundant paths.
    ---------------                              ---------------
    | SCTP User   |                              | SCTP User   |
    | Application |                              | Application |
    |             |                              |             |
    |-------------+                              +-------------|
    | SCTP        |                              | SCTP        |
    | Transport   |                              | Transport   |
    | Layer       |                              | Layer       |
    |-------------+                              +-------------|
    | IP          | One or more  \/  One or more | IP          |
    | Transport   | IP endpoint  /\  IP endpoint | Transport   |
    | Layer       | interfaces       interfaces  | Layer       |
    ---------------                              ---------------
        

Header

The SCTP header resembles the TCP header.

<--------------- 32 bit ------------- >
|-------------------------------------|-------------
| Source Port      | Destination Port | SCTP
|-------------------------------------| Common
|          Verification Tag           | Header
|-------------------------------------|
|               Checksum              |
|-------------------------------------|-------------
|  Type   | Flags  |      Length      | Chunk 1
|-------------------------------------|
|              User Data              |
|-------------------------------------|-------------
                   .
                   .
                   .
|-------------------------------------|-------------
|  Type   | Flags  |      Length      | Chunk N
|-------------------------------------|
|              User Data              |
|-------------------------------------|-------------

Sockets API conformance

Lksctp implements extensions to the sockets API to work with SCTP associations. Some abnormalities exists comparing with TCP and UDP sockets. Be sure to not confuse one-to-many style sockets with the multi-homing functionality in SCTP. One-to-many style sockets can be associated with many associations, each of which supports multi-homing.

One-to-many style interface
  • socket() - Sockets are created with IPPROTO_SCTP as the protocol. One-to-many style sockets uses SOCK_SEQPACKET as type.
  • accept() - One-to-many style socket don’t call accept to retrieve new associations. Instead new associations are accepted automatically and a notification is delivered via recvmsg().
  • sendmsg() - In one-to-many connections, the msg_name field in the msghdr structure will be set to one of the transport addresses of the intended reciever.
  • recvmsg() - In one-to-many connections, the msg_name field in the msghdr structure will be set to the source transport address for the received data.
  • connect() - Multiple calls to connect() on the same socket can be used to create multiple associations. SCTP allows for data exchange during the association set up phase. To use this feature, application cant use connect(), and should instead use sendmsg() with SCTP_INIT type ancillary data.
  • select() - Caution needs to be exercised when using select() on write or on read with a one-to-many socket. A positive return on write only indicates that one of the associations is writable. A write operation on the socket could therefore still block. Likewise, a positive return on read only indicates that one of the associations has data to read. sctp_peelof() can be used to separate associations from a one-to-many socket.
One-to-one style interface
  • sendmsg() - The msg_name field in the msghdr structure is used to indicate the preferred peer address. This can be used to discurage the stack from sending on the primary interface.

Special considerations

As SCTP allows a socket to have many associations associated with it, application programmers should consider using non-blocking style for one-to-many sockets. Otherwise, one stalled association may block the entire socket.

UDP encapsulation

To solve the problem with legacy NAT support, one possible solution is to encapsulate packages in an UDP/IP packet. As encapsulation requires “decapsulation”, both peers must support the same encapsulation method.

Implementation

The splitter tool consists of four related but separate projects.

  • A extensive test framework has to be created to ensure correct protocol behavior (except when purposely diverging from the specification) and to measure impact on performance and fault-tolerance.
  • The SCTP protocol must be extended to solve problems with NAT traversal. Experimental load-balancing is also a topic of investigation.
  • A server-client application has to be developed that allows traffic to be tunneled transparently over an SCTP-connection.

Physical layer

Split access routing can be achieved in several ways in Linux. The simplest solution would be to utilize the nexthop option in ‘ip route’ command in the iproute2 package creating a multipath route.

ip route add default scope global nexthop via $P1 dev $IF1 weight 1 \
                                  nexthop via $P2 dev $IF2 weight 1 \
                                                   .
                                                   .
                                                   .
                                  nexthop via $Pn dev $IFn weight 1

However, this can’t handle the situation with duplicate subnets. A more explicit solution is to use iptables fwmark option together with the statistical module to, with a certain probability, mark outgoing connections with a number n where n is a routing table number of an interface, and then create a rule that every packet marked with n should use routing table n. One has only to ensure that sum(prob(n)) = 1 and that the probability that a package will marked with a certain n follows a random distritbution.

iptables -t mangle -A PREROUTING -j CONNMARK --restore-mark
iptables -t mangle -A PREROUTING -m mark ! --mark 0 -j ACCEPT

iptables -t mangle -A PREROUTING -j MARK --set-mark $TN_1
iptables -t mangle -A PREROUTING -m statistic --mode random --probability 1/2 --set-mark $TN_2
                                            .
                                            .
                                            .
iptables -t mangle -A PREROUTING -m statistic --mode random --probability 1/n --set-mark $TN_n

iptables -t mangle -A PREROUTING -j CONNMARK --save-mark
ip rule add fwmark $TN_1 table $TN_1
                 .
                 .
                 .
ip rule add fwmark $TN_n table $TN_n

Test suite

Lksctp provides a test suite that serves as a basis for protocol functionality testing. To test aspects as NAT traversal and protocol performance, a testing environment has to be created. This environment has to offer a controllable and reproducible tests for various network layouts.

Performance evaluation

As the project aims to make changes to the transportation layer of SCTP as well as implementing application layer transportation, some measurement tool has to be used to analyze performance and stability. Iperf is a tool that performs network throughput tests for both TCP and UDP. It should be possible to extend iperf with SCTP protocol support.

Network emulation

Linux has native support for virtual, in-kernel network interfaces. This allows for creation of various network layouts. Netem provides network emulation of WAN functionality for testing protocols. It allows to emulate variables as delay, loss, duplication and re-ordering of packages.

Tests

Protocol extensions

UDP encapsulation

To solve the problem with NAT traversal one possible solution is to wrap SCTP packages in UDP headers.

|-------------------------------------|
|              IP Header              |
|-------------------------------------|
|             UDP Header              |
|-------------------------------------|
|         SCTP Common Header          |
|-------------------------------------|
|            SCTP Chunk 1             |
|-------------------------------------|
                   .
                   .
                   .
|-------------------------------------|
|            SCTP Chunk N             |
|-------------------------------------|

The whole SCTP packet resides in the data-portion of the UDP packet. This would require creation of UDP sockets and hooking into the state transitions of the SCTP socket, preferably without having to change the protocol logic. To simplify the creation of encapsulation sockets, UDP as a connectionless protocol is ideal. One UDP socket is created for each SCTP endpoint and copies the state transitions of the SCTP socket, ie. binding and connecting. The UDP socket is bound to the same port as the SCTP socket to simplify port configuration. The steps for sending data are:

  • Right before dumping the packet on IP, create an UDP header with the same destination port and address as the SCTP header and push it onto the packet SKB.
  • Change the owner of the SKB to the encapsulating UDP socket.

The steps for receiving data are:

  • In the receiving hook for the UDP socket, pull the UDP header from the packet SKB.
  • Pass the packet to the original receiving function for SCTP packages.

To hold the information about the encapsulating socket and the associated SCTP endpoint, a new structure was introduced. A pointer to this structure is stored in both the endpoint and the UDP socket.

Improvements

In a future implementation, the original SCTP socket wouldn’t be needed, and the encapsulation could be integrated more closely into the protocol. The current implementation however, gives a clear view of the functionality needed for encapsulation. Other encapsulation methods than UDP might also be of interest, and the current implementation makes it easy to add a new encapsulation mode.

Server-client tunneling

As most content is served over either TCP or UDP, the use of SCTP must be integrated so that it’s transparent to both sender and reciever. This is preferably done beneath the IP layer but can also be partly done in the TCP/UDP layer.

OpenVPN

OpenVPN offers an ideal solution by tunneling on a low level (TUN/TAP interfaces). In it’s current version, OpenVPN only supports TCP and UDP, but this could be extended to include SCTP. By routing forwarded traffic on the device over the OpenVPN interface, one would achieve truly transparent tunneling.

Application layer

The simpler implementation is to create tunnels like: TCP -> SCTP -> TCP A client would bind to a port on the selected protocol and wait for connections. Incoming data would be sent over the SCTP connection to the server at either stream-level or connection-level. The server would then forward the data over the same protocol to some destination. Thus, traffic between the client and the server utilize advanced SCTP functions while being transparent to the sender and reciever except source and destination information in the IP and application layer headers.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published