Linux Networking Software


This is the first post of several. Next posts will focus on running WireGuard inside a Docker container on amd64 Linux and a Raspberry Pi.

I’ve been running WireGuard for a few months now and I’ve been loving it.

I first started using it about a year ago when in China — OpenVPN was once again being actively blocked and it was driving me nuts. Overnight I set up a DigitalOcean server in Singapore and ran WireGuard from it — both my phone and laptop were able to actively bypass the GFW and (at that time) surf the internet freely once more. As WireGuard gains popularity, I am sure the GFW will start detecting it — it’s a quiet but not a stealthy protocol.

Since then I’ve dug quite a bit deeper in WireGuard and am really looking forward to what it’s going to bring.

WireGuard differentiates itself to be an extremely simple VPN server (which can make getting started and debugging a bit more challenging) — but it wants to seamlessly work together with existing tools. One of the main features still missing is for example running a DHCP server on the server and dynamically assigning IPs (like oVPN does).

WireGuard network
Simplified diagram of my network. Using static routing my clients can access the WireGuard network even without running WireGuard directly. (Some of) my containers are also able to access the network, this allows me to run Resilio Sync over WireGuard. It’s using one big subnet to create one big LAN.

It’s also pretty cool because any node can both be a server and a client at the same time. In my setup I am running two servers: one running at home in Singapore on a RPi4 (1Gbit fiber connection) and one on a virtual machine in Amsterdam (1Gbit as well). The RPis at my parents are connected to the server in Amsterdam, my iPad and phones are connected to the server in Singapore. If I am in Europe I might switch over and let my iDevices connect to the AMS server instead.

WireGuard and traffic shaping
Click to enlarge.
Bandwidth stats from Resilio Sync, transferring several big files. We can clearly see a speed increase (from 2-5mb/s to 11mb/s) when routing the exact same traffic over WireGuard. Traffic shaping at its best.

The example above clearly shows speed gains by cloaking the traffic in UDP packets. The shared folder has only two nodes (sender and receiver) and shows several big files being transferred from Amsterdam to Singapore. Resilio Sync uses the Bittorrent protocol, something ISPs generally hate and tend to slow down as much as they can — thanks Starhub.

Wireguard also allows the client to decide what to route through the server: only the VPN LAN traffic, or a whole subnet, or So for my iPhone I for example route all traffic through VPN to avoid hotel/airport/… WiFi’s to mine/log/scan my data. For my laptop I have two configs, one to only connect to the LAN, but another that routes all my traffic through the VPN if I want to avoid exposure or circumvent censoring.

Note that I am not running WireGuard to remain anonymous and I’ll definitely leak some information — just trying to minimise and remain in control of what I leak. This is not a Tor replacement.

Apple Linux Networking Software VM

Box — Docker shell server

A couple of months ago I had the great idea to set up a shell server in Docker. Simply because my docker skillz were quite rusty and a shell server was something I actually genuinely needed.

Shell servers… so 2005. I remember in the good old IRC days people asking for (free) shell servers to run their eggdrop and stuff. OMG am I getting old? Anyhow…

I ssh quite often. I manage quite a few servers (~15?) and routers that require me to login and do some random stuff. I also work on a laptop quite often and that means closing the lid and moving around.

First of all, mosh is amazing and allows you to stay connected via ssh, even with crappy (airport/hotel) internet as well as moving around networks — that solves half the problem. If you are not using it, start using it now!

Second, during my datacenter technician days at Google we used to have a “jump server” — a shell server that allowed us to bridge the corporate network and ssh into prod machines. Doubt that’s still used nowadays, but the idea stuck. I wanted something similar to ssh from, wherever I was, and easily connect to my servers. And as the network the shell server is running on is stable, I only need to use mosh to the shell server. Thereafter, the connection very rarely dies.

And I guess, third, I recently purchased an iPad Pro and I really need to have my local “dev” environment with my git repo that I edit quite frequently but iPadOS isn’t really your average computer, and doesn’t even have a proper terminal. This is my experiment to make iPadOS work as a main computer when on the move.

Enter box — Docker shell server

I’ve copied over the files I use to this example repo, and added some comments. Mind you that this repo acts as a proof of concept and isn’t kept up to date, as I have my own private repo — but this should give you a good idea on how to set up your own shell server with Docker. — this is a simple script that I execute when I first run or need to update the container. I execute the same file on two different servers: Liana, my Raspberry Pi at home and Ocean, my server in Amsterdam. — this installs what I care about for zsh. This could be part of the Dockerfile but for some reason I separated it. ¯\_(ツ)_/¯ — this clones my Git repos so I can edit and commit stuff from the shell server. — this file is launched by Dockerfile at the end and executes what matters: the ssh daemon. It also adds a Wireguard route and executes the scripts above.

Dockerfile — this installs everything I need and configures the whole thing. I’ve added tons of comments that should get you going.

I am also cloning misc and homefiles as submodules in files/ — but you should change this to something that works for you. See the Dockerfile for more info.

Hardware Linux Networking

Edgerouter IPsec tunnel to Fritzbox

So, I have an EdgeRouter Lite in Singapore (Starhub) and a FritzBox in Belgium (EDPnet).

This is mostly stuff that I have found from several articles, mostly from here.

ERL: eth0 is WAN, eth1 ( and eth2 (unused, not VPN’ed) are LAN

This is the FritzBox config (go to VPN and them Import a config) fritzvpn.cfg:

vpncfg {
        connections {
                enabled = yes;
                conn_type = conntype_lan;
                name = "VPN Yeri";
                always_renew = yes;
                reject_not_encrypted = no;
                dont_filter_netbios = yes;
                localip =;
                local_virtualip =;
                remoteip =;
                remote_virtualip =;
                remotehostname = "";
                localid {
                        fqdn = "";
                remoteid {
                        fqdn = "";
                mode = phase1_mode_idp;
                phase1ss = "all/all/all";
                keytype = connkeytype_pre_shared;
                key = "SOMEPASSWORD";
                cert_do_server_auth = no;
                use_nat_t = yes;
                use_xauth = no;
                use_cfgmode = no;
                phase2localid {
                        ipnet {
                                ipaddr =;
                                mask =;
                phase2remoteid {
                        ipnet {
                                ipaddr =;
                                mask =;
                phase2ss = "esp-all-all/ah-none/comp-all/pfs";
                accesslist = "permit ip any";
        ike_forward_rules = "udp", 

Be sure to modify the password, local (Fritz) and remote (ERL) LAN and edit the local and remote fqdn.

This is the ERL config (via ssh, you’ll need to set this:

[email protected]# show vpn ipsec 
 auto-update 60
 auto-firewall-nat-exclude enable
 esp-group FOO0 {
     proposal 1 {
         encryption aes256
         hash sha1
 ike-group FOO0 {
     dead-peer-detection {
         action restart
         interval 60
         timeout 60
     lifetime 3600
     proposal 1 {
         dh-group 2
         encryption aes256
         hash sha1
 ipsec-interfaces {
     interface eth0
 nat-networks {
     allowed-network {
 nat-traversal enable
 site-to-site {
     peer {
         authentication {
             mode pre-shared-secret
             pre-shared-secret SOMEPASSWORD
         connection-type initiate
         description "VPN to"
         ike-group FOO0
         tunnel 1 {
             esp-group FOO0
             local {
             remote {


[email protected]:~$ show vpn ipsec status
IPSec Process Running PID: 20140

1 Active IPsec Tunnels

IPsec Interfaces :
        eth0    (no IP on interface statically configured as local-address for any VPN peer)
[email protected]:~$ show vpn ipsec sa #9, ESTABLISHED, IKEv1, 85a2d010ada73113:ca439c40ac3bca06
  local  '' @ 116.87.x.y
  remote '' @ 109.236.x.y
  established 1592s ago, reauth in 1333s #1, INSTALLED, TUNNEL, ESP:AES_CBC-256/HMAC_SHA1_96/MODP_1024
    installed 1592 ago, rekeying in 1200s, expires in 2009s
    in  c0bb652e, 1038032 bytes, 10726 packets,     0s ago
    out 8d5df3f5, 532685 bytes,  6062 packets,     0s ago

I haven’t really figured out what no IP on interface statically configured as local-address for any VPN peer means yet though.

Next up: VLANs

Errors Linux Networking Software

OpenVPN packet drops

I recently started to notice following error messages on my openVPN server.

ovpn-server[6306]: MULTI: packet dropped due to output saturation (multi_process_incoming_tun)

This basically means that the TUN or TAP interface is making more packets than the real (TCP) interface can handle.

As I need to run OpenVPN using the TCP protocol (instead of the faster UDP protocol; as UDP is often blocked in networks I use my VPN in) I experimented by increasing the tcp-queue-limit. The default is 64, and I’ve set it to 256. So far, everything still seems to be working fine (but more packets will be queued before being dropped by OpenVPN, requiring less retransmissions).

Add this to the OpenVPN server config:

tcp-queue-limit 256

And restart the daemon.

Errors Networking Software Windows

OpenVPN & Windows 7

There’s a great GUI out for OpenVPN & Windows, located here.

However, this GUI includes an old OpenVPN, that is no longer compatible with Windows 7 and Windows Vista.

The TUN/TAP driver will be blocked due to compatibility issues, and when trying to connect to a VPN, you’ll get an error along the lines of:

All TAP-Win32 adapters on this system are currently in use

The simplest fix, is to install the GUI package (including the old OpenVPN binaries), and reinstall OpenVPN afterwards.

You can find the latest OpenVPN binaries here and the latest version, when writing this post here.

This will overwrite the old files and update the driver with a Windows 7 compatible driver.

Try to connect now, everything should work like a charm. 🙂