2025-12-07 23:53:47 -08:00
2025-12-07 23:53:47 -08:00
2025-12-07 03:52:18 -08:00
2025-12-07 00:00:12 -08:00
2025-12-07 13:26:00 -08:00
2025-11-19 12:58:49 -08:00

circus gateway

Juggles packets across multiple crappy links with """seamless""" failover, trying to maximize reliability.

Created because I'm too lazy to run a long ethernet cable or get better wifi adapters.

This is only the 9th time I've rewritten the entire daemon and relevant documentation.

who is this for?

If you are thinking about deploying circus-gw, please first consider that it is a band-aid fix by design and should never be used in mission-critical systems.

it's not for

  • circus-gw is not for networks that have several reliable links and wish to maximize speed and/or reliability. It will more likely hurt both speed and reliability in these situations, but you can try.
  • circus-gw is not for networks that have several unreliable links and could have reliable links with some extra effort. Those networks should just get the reliable links. Technically this is the situation I'm in, but don't worry about it.

it is for

circus-gw is for networks that have several unreliable links and have no choice but to use them. Unreliable as in they break every few hours, terrible latency, high packet loss, unproportional connection quality relative to each other, and are generally an IT nightmare.

circus-gw is designed to minimize the chances that you notice this terrible infrastructure mistake as a user.

circus-gw does not require you to control the entirety of each link (again, by design, as I don't), but it does require you to at least control both ends of it due to the way it's designed. As in, you must connect to another computer on the Internet with reliable links to act as your unified gateway to the public Internet.

If you can't see why, imagine you are a web server and some f*cking guy is trying to request a webpage and each part of the request comes from 7 different public IP addresses. Hopefully it's obvious why now.

why?

It's not practical, I know.

To explain why it's useful for me, I'll explain why normal/"sane" solutions aren't applicable.

why not use Linux bond interfaces?

Linux bond interfaces don't work on WiFi interfaces and don't self-heal, making them sub-optimal for a setup with genuine reliability issues (like WiFi). Linux bond interfaces are useful for redundancy and fault-tolerance in mission-critical systems which already are reliable.

why not use multi-wan in pfsense/opnsense?

Multi-wan is another great solution for added speed and/or redundancy and fault-tolerance in mission-critical systems that don't have actual genuine reliability issues. This is not for that.

The problem with multi-wan is that it only splits connections across load-balancing groups. It doesn't actually load-balance the packets themselves. This also means that if one of your gateways dies while a connection is routed through it, that connection dies. This is an acceptable tradeoff for genuine speed and reliability gains.

circus-gw doesn't promise genuine speed gains, in fact it may cause issues with TCP that slow down your connection in its current state. A much more involved solution could be created to fix these issues, but the effort isn't worth the payoff for me currently, since circus-gw is nearing the end of its usefulness as my Internet situation improves.

Instead, circus-gw ensures that no connection belongs to any single "unreliable link". This means that if a single link dies, approximately 50% of packets or more (depending on number of nodes, more is better) still make it to the destination before circus-gw even has time to react. This obviously isn't enough of the transmission to sustain a connection or do anything useful (unless you live in 1995), but once circus-gw removes the dead node from the load balancing map, deliverability returns to have its typical ceiling of 100%. If this happens quickly enough (i.e. without several successive failures), the connection will only see a slight speed loss or interruption for a fraction of a second before returning to normal.

why not run an ethernet cable?

no.

motivation

Now that I've explained why, it's probably still not clear what motivates me to create a massively over-complicated and over-engineered setup to get around running a simple ethernet cable.

But this question is simple to answer: I'm a nerd. I saw a problem that looked like it couldn't be solved and I can't stand it so I solved it. That's literally it. I nerd-sniped the shit out of myself.

S
Description
my upstream is a circus, and I am the clown.
https://test.dipshit.dev
Readme MIT 174 KiB
Languages
Python 64%
Shell 36%