Cross-connect Linux interfaces with XDP

Overview

Cross-connect Linux interfaces with XDP redirect

Go Report Card GoDoc License: MIT Build Status

xdp-xconnect daemon is a long-running process that uses a YAML file as its configuration API. For example:

links:
    eth0: tap0
    veth2: veth3

Given the above YAML file, local Linux interfaces will be cross-connected (eth0<->tap0 and veth2<->veth3) with the following command:

sudo xdp-xconnect -conf config.yaml

This command will block, listening to any changes to the file and will perform "warm" reconfigurations on the fly.

Note: due to its nature (loading eBPF progs, maps and interacting with netlink), xdp-xconnect requires NET_ADMIN capabilities (root privileges are used for simplicity).

Theory

Each pair of interfaces will have an eBPF program attached to its XDP hook and will use bpf_redirect_map eBPF helper function to redirect packets directly to the receive queue of the peer interface. For mode details read this.

Prerequisites

Linux Kernel version > 4.14 (introduced veth XDP support) Go

Installation

Binary:

go get github.com/networkop/xdp-xconnect

Docker:

docker pull networkop/xdp-xconnect

Usage

Binary:

sudo xdp-xconnect -conf input.yaml

Docker:

docker run --net host -v$(pwd):/xc --privileged networkop/xdp-xconnect -conf /xc/input.yaml

Go code:

import "github.com/networkop/xdp-xconnect/pkg/xdp"

func main() {

    input := map[string]string{"eth1":"tap1"}

    app, err := xdp.NewXconnectApp(input)
    // handle error

    updateCh := make(chan map[string]string, 1)
    
    app.Launch(ctx, updateCh)
}

Demo

Create three network namespaces and three veth links:

sudo ip link add dev xconnect-1 type veth peer name xc-1
sudo ip link add dev xconnect-2 type veth peer name xc-2
sudo ip link add dev xconnect-3 type veth peer name xc-3
sudo ip netns add ns1
sudo ip netns add ns2
sudo ip netns add ns3

Move one side of each veth link into a correponding namespace and configure an IP address from 169.254.0.0/16 subnet:

sudo ip link set xc-1 netns ns1
sudo ip link set xc-2 netns ns2
sudo ip link set xc-3 netns ns3
sudo ip netns exec ns1 ip addr add 169.254.1.10/24 dev xc-1
sudo ip netns exec ns2 ip addr add 169.254.1.20/24 dev xc-2
sudo ip netns exec ns3 ip addr add 169.254.1.30/24 dev xc-3

Bring up both sides of veth links

sudo ip link set dev xconnect-1 up
sudo ip link set dev xconnect-2 up
sudo ip link set dev xconnect-3 up
sudo ip netns exec ns1 ip link set dev xc-1 up
sudo ip netns exec ns2 ip link set dev xc-2 up
sudo ip netns exec ns3 ip link set dev xc-3 up

At this point there should be no connectivity between IPs in individual namespaces, i.e. the following commands will return no output:

sudo ip netns exec ns1 ping 169.254.1.20 &
sudo ip netns exec ns1 ping 169.254.1.30 &

Start the xdp-xconnect app with and connect xconnect-1 to itself (see first.yaml):

cp testdata/first.yaml testdata/input.yaml
sudo go run ./main.go -conf testdata/input.yaml &

2021/03/03 20:08:41 Parsing config file: testdata/input.yaml
2021/03/03 20:08:41 App configuration: {Links:map[xconnect-1:xconnect-1]}

Now update the configuration by replacing the file to connect the first two interfaces (see second.yaml):

cp testdata/second.yaml testdata/input.yaml

2021/03/03 20:12:16 Parsing config file: testdata/input.yaml
2021/03/03 20:12:16 Error parsing the configuration file: EOF
2021/03/03 20:12:16 Parsing config file: testdata/input.yaml
2021/03/03 20:12:16 App configuration: {Links:map[xconnect-1:xconnect-2]}
64 bytes from 169.254.1.20: icmp_seq=113 ttl=64 time=0.068 ms
64 bytes from 169.254.1.20: icmp_seq=114 ttl=64 time=0.068 ms
64 bytes from 169.254.1.20: icmp_seq=115 ttl=64 time=0.075 ms

This proves that the first and second links are now connected. Now swap the connection over to the third link (see third.yaml):

cp testdata/third.yaml testdata/input.yaml

2021/03/03 20:13:53 Parsing config file: testdata/input.yaml
2021/03/03 20:13:53 Error parsing the configuration file: EOF
2021/03/03 20:13:53 Parsing config file: testdata/input.yaml
2021/03/03 20:13:53 App configuration: {Links:map[xconnect-1:xconnect-3]
64 bytes from 169.254.1.30: icmp_seq=207 ttl=64 time=0.075 ms
64 bytes from 169.254.1.30: icmp_seq=208 ttl=64 time=0.070 ms
64 bytes from 169.254.1.30: icmp_seq=209 ttl=64 time=0.071 ms
64 bytes from 169.254.1.30: icmp_seq=210 ttl=64 time=0.071 ms

Ping replies now come from the third link. Let's see what happens if we provide the malformed input (see bad.yaml)

cp testdata/bad.yaml testdata/input.yaml

2021/03/03 20:15:46 Parsing config file: testdata/input.yaml
2021/03/03 20:15:46 App configuration: {Links:map[xconnect-1:xconnect-asd]}
2021/03/03 20:15:46 Error updating eBPF: 1 error occurred:                                                                                                                   
	* Link not found

64 bytes from 169.254.1.30: icmp_seq=317 ttl=64 time=0.065 ms
64 bytes from 169.254.1.30: icmp_seq=318 ttl=64 time=0.065 ms
64 bytes from 169.254.1.30: icmp_seq=319 ttl=64 time=0.064 m

The app detected the error and cross-connect continues working with its last known configuration. Finally, we can terminate the application which will cleanup all of the configured state:

fg
[1]  + 1095444 running    sudo go run ./main.go -conf testdata/input.yaml
^C
2021/03/03 20:16:44 Received syscall:interrupt
2021/03/03 20:16:44 ctx.Done

Don't forget to cleanup test interfaces and namespaces:

sudo ip link del dev xconnect-1
sudo ip link del dev xconnect-2
sudo ip link del dev xconnect-3
sudo ip netns del ns1
sudo ip netns del ns2
sudo ip netns del ns3

Additional Reading and References

https://github.com/xdp-project/xdp-tutorial

https://docs.cilium.io/en/stable/bpf/

https://qmonnet.github.io/whirl-offload/2020/04/12/llvm-ebpf-asm/

https://github.com/takehaya/goxdp-template

https://github.com/hrntknr/nfNat

https://github.com/takehaya/Vinbero

https://github.com/tcfw/vpc

https://github.com/florianl/tc-skeleton

https://github.com/cloudflare/rakelimit

https://github.com/b3a-dev/ebpf-geoip-demo

https://github.com/lmb/ship-bpf-with-go

You might also like...
An implementation of the Mobile Adapter GB protocol, to connect to custom game servers.

libmobile Library that implements the Mobile Adapter GB protocol, in a way that should be easy to integrate into a plethora of different emulators/har

Connect to dialup modems over VoIP using SIP, no modem hardware required.

D-Modem Connect to dialup modems over VoIP using SIP, no modem hardware required.

A forward proxy module for CONNECT request handling

name This module provides support for the CONNECT method request. This method is mainly used to tunnel SSL requests through proxy servers. Table of Co

C++ framework for building lightweight HTTP interfaces
C++ framework for building lightweight HTTP interfaces

Pion Network Library C++ framework for building lightweight HTTP interfaces Project Home: https://github.com/rimmartin/pion-ng Documentation Retrievin

SixtyFPS is a toolkit to efficiently develop fluid graphical user interfaces for any display: embedded devices and desktop applications
SixtyFPS is a toolkit to efficiently develop fluid graphical user interfaces for any display: embedded devices and desktop applications

SixtyFPS is a toolkit to efficiently develop fluid graphical user interfaces for any display: embedded devices and desktop applications. We support multiple programming languages, such as Rust, C++, and JavaScript.

Cross-platform, single .h file HTTP server (Windows, Linux, Mac OS X)

EWS - Single .h File C Embeddable Web Server Latest Version: 1.1.4 released September 9, 2021 Supported platforms: Linux, Mac OS X, Windows License: B

Cross-platform, efficient, customizable, and robust asynchronous HTTP/WebSocket server C++14 library with the right balance between performance and ease of use

What Is RESTinio? RESTinio is a header-only C++14 library that gives you an embedded HTTP/Websocket server. It is based on standalone version of ASIO

RakNet is a cross platform, open source, C++ networking engine for game programmers.

RakNet 4.081 Copyright (c) 2014, Oculus VR, Inc. Package notes The Help directory contains index.html, which is full help documentation in HTML format

LibVNCServer/LibVNCClient are cross-platform C libraries that allow you to easily implement VNC server or client functionality in your program.

LibVNCServer: A library for easy implementation of a VNC server. Copyright (C) 2001-2003 Johannes E. Schindelin If you already used LibVNCServer, you

Owner
Michael Kashin
Michael Kashin
Michael Kashin
XDP programs that increment stat counters for packets/bytes.

XDP Stats Description This is a program that calculates stats inside of an XDP program (support for both XDP_DROP and XDP_TX). As of right now, the st

Christian Deacon 10 Oct 30, 2022
IP-Block is an XDP program, that is an IP firewall.

Description IP-Block is an XDP program, that is an IP firewall. use rules to allow/deny access to a range of IP addresses. Block ip behavior use XDP p

Sharp Liu 5 Aug 9, 2022
XDP connection ratelimiting network function

Connection Ratelimiting Connection ratelimiting uses a sliding window algorithm for managing the connections. This kernel function based on XDP keeps

L3AF 18 Feb 3, 2022
Packet filter using XDP.

MocTok This is a packet filter using XDP. Usage usage: moctok [options] ... options: -g, --gen Generate XDP program. (string) -a, --atta

Ai Nozaki 13 Aug 25, 2022
Unofficial Linux client for the Adobe Connect meeting application

Unofficial Adobe Connect Client for Linux Description: Adobe Connect does not have a linux version officially, however, since it's written in flash, i

Mahan Lamee 16 Dec 28, 2022
To have platform independent network interfaces over usb which is working with Linux, Windows, Mac OS ect.

To have platform independent network interfaces over usb which is working with Linux, Windows, Mac OS ect. called RNDIS. This project is a RNDIS demo, which addtionally implements a http server. It runs out of the box on a stm32f411 BlackPill board. My RNDIS library with an empty template for the second interface (which can ba UART, CAN, ETH or like in this demo a tcp/ip stack) can be found under following link: https://github.com/RDMsmartnetworks/STM32_HAL_RNDIS

Nico Korn 17 Dec 24, 2022
The C++ REST SDK is a Microsoft project for cloud-based client-server communication in native code using a modern asynchronous C++ API design. This project aims to help C++ developers connect to and interact with services.

Welcome! The C++ REST SDK is a Microsoft project for cloud-based client-server communication in native code using a modern asynchronous C++ API design

Microsoft 7.2k Dec 30, 2022
C++ Kite Connect API library / SDK

Kite Connect API C++ client Overview Dependencies Getting dependencies Linux Others & uWS v0.14 Building & installation Examples REST API Ticker Docum

Zerodha Technology 27 Dec 30, 2022
OceanBase Client for C. A driver to connect applications developed in C language to OceanBase Database.

Oceanbase Client for C OceanBase Client for C is a driver used to connect applications developed in C to OceanBase Database Server. Compatibility Serv

OceanBase 22 Nov 8, 2022
Husarnet is a Peer-to-Peer VPN to connect your laptops, servers and microcontrollers over the Internet with zero configuration.

Husarnet Client Husarnet is a Peer-to-Peer VPN to connect your laptops, servers and microcontrollers over the Internet with zero configuration. Key fe

Husarnet 180 Jan 1, 2023