Up to Main Index                             Up to Journal for March, 2019

                   JOURNAL FOR FRIDAY 8TH MARCH, 2019
______________________________________________________________________________

SUBJECT: Connection quotas
   DATE: Fri  8 Mar 04:02:02 GMT 2019

After what seems like ages, I’ve finally pushed out connection quotas to the
public dev branch. This is my attempt to fight off this one-liner:


  seq 1000000 | xargs -P8 -n1 -i@ netcat -z 172.16.1.1 4001


Actually, that is a lie. This is my umpteenth attempt at fighting the
one-liner, but the first I’ve made public. At one point I had connection
tracking, then a connection limiter, others I’ve already forgotten. I’ve gone
back and forth between simple implementations and ones only a parent could
love. Sometimes I’d scrap the code and start over, other times I’d slowly
morph the code from one idea into the next idea. Along the way I’ve nearly
finished each implementation before starting over — including rewriting all of
the tests and documentation. It wasn’t that the code didn’t work, it wasn’t
‘clean’. I’d mixed up several ideas, or the code had become a convoluted mess,
or I’d just not expressed my ideas very well in code. Writing code and
documentation that is simple, and makes sense to others as well as yourself,
can be hard. Finding the right default values to tune this feature has been
even harder…

I’ve finally settled on an implementation I call connection quotas.

So what is it and how does it work?

Every IP address connecting to the server has a quota of 4 connection
attempts, unless quotas are disabled. If an IP address uses up its quota it
will be banned from connecting until its quota is reset.

The configuration file has a new Quota section with three new values that can
be set to control quotas:Quota.Window, Quota.Timeout and Quota.Stats.

Quota.Window is the minimum period that an IP address can use up its quota in.
If the IP address goes over its quota within this period it will be banned
from connecting until its quota is reset. Setting Quota.Window to 0 disables
quotas.

Quota.Window is the period it takes for an IP address’s quota to be reset.
In other words, the IP address will be banned for this amount of time.

If Quota.Window is set to 0 then the IP address’s quota will not be reset
until it has not attempted to connect to the server for the Quota.Window
period.

The Quota.Stats value controls how often statistics are logged for quotas.
Statistics are logged when the next non-banned IP address connects after the
Quota.Stats period has passed. Setting Quota.Stats to 0 turns off logging. A
quota log line looks like this:


  quota cache: 6 entries [3 evicted, 2 over quota, 1 recent]


Some configuration examples. Given:


  Quota.Window:  10s
  Quota.Timeout: 30m
  Quota.Stats:   10m


An IP address can connect to the server up to 4 times in 10 seconds. If it
tries a fifth time within 10 seconds it will be banned for 30 minutes.


  Quota.Window:  10s
  Quota.Timeout: 0
  Quota.Stats:   10m


If an IP address connects more than 4 times in 10s it will be banned until it
has made no connection attempts in the last 10 seconds. So if the IP address
is banned, waits 5 seconds and tries to connect it will be banned for another
10 seconds. If the IP address persistently tries to connect it will be
persistently banned.

Connection quotas require that connection attempts be cached per IP address.
However, if an IP address connects and then goes away the cached entry for the
IP address will become stale after the Quota.Window period passes. After a
period twice that of Quota.Window has passed the next non-banned IP address
connecting will cause stale quota to be evicted from the cache.

I think that this approach is simple, yet flexible enough for a lot of users.
For the time being the default configuration disables quotas. To enable them
edit the configuration file and set appropriate values for Quota.Window,
Quota.Timeout and Quota.Stats. You will need to experiment to see what values
work for you. I’m still not sure what values I should set as defaults, but I’d
suggest using a Quota.Window of 10s and Quota.Timeout of 30m to start with.

If you enable quotas I would appreciate knowing what values work for you. I’d
be especially interested in hearing from you if you need to set the constant
ringSize — in comms/ring.go — to something other than 4: diddymus@wolfmud.org

I can now get back to improving the current player commands with the new
search and matching code. But it's 4am. Guess I should at least try and get
some sleep…

--
Diddymus


  Up to Main Index                             Up to Journal for March, 2019