The original plan was a full kernel-space SOCKS proxifier, but that would be a little bit complex for the goal: a faster TCP proxy. Then I found a very elegant solution for the problem: eBPF sockmap support. There is a API for redirect packets between sockets in kernel space using sockmap eBPF program. I decided to extend my shadowsocks-libev fork with the eBPF support. The disabled encryption already give some additional performance, so if anyone already using this one, there is a new option to get more performance.
I did some performance and functional tests in my test environment (described here). The eBPF performance is fairly good compared to the regular version. I included two screenshots, one with and one without eBPF enabled. For sockmap support, at least 4.14 kernel required! (The iperf3 tests performed on 4.14.41 MPTCP supported kernel with 1 network path). host1 machine is connected to ubu1 machine and use it as a router to ubu2 (see the diagram here). For more information about use a machine as a router and transparent proxy please take a look into this.
iperf3 -c ubu2 iperf -s +-----------+ +------------+ +----------+ | | | | | | | host1 +------------> | ubu1 +-------------> | ubu2 | | | | | | | +-----------+ +------------+ +----------+ ss-redir --ebpf ss-server
The branch with eBPF sockmap support: https://github.com/SPYFF/shadowsocks-libev-nocrypto/tree/ebpf
Sadly in practice, there is an issue with the current version. For example in a long FTP file transmission, at the end it will skip some bytes or push additional (duplicated) bytes to the receiver. That’s because in the current kernel implementation sometimes if an error happens during the transmission, the packet size returned instead of the error code. I consulted with John Fastabend (he is the creator of the eBPF sockmap) about the issue and he told me he will send a patch for that which will be get merged into the kernel soon. After that if everything works fine, I will put the whole work into a OpenWRT package.
- An interesting use-case is the layer3 multipath implemented with IPv6 segment routing and eBPF, done by Mathieu Xhonneux. You can check his thesis here and the code in his github repository.
- In the near future we will see customizable path selection with eBPF, mentioned here: https://www.files.netdevconf.org/d/22fb4894c58e4854b23a/