Limen.State.BanList (limen v0.2.1)

Copy Markdown View Source

Banned prefixes, with expiry.

A ban is keyed on the same prefix every other piece of state uses (see Limen.IP.prefix/3), so checking one is a single ETS lookup. Expired bans are ignored on lookup and removed later by Limen.State.Sweeper.

Each ban records the mode of whatever created it. A ban created by a policy in dry-run mode is looked up and reported exactly like any other, but never enforced, so a dry-run policy can never block traffic, not even through state it leaves behind.

A ban's action says what banned clients get: :deny (a 403) or :maze (the slow pages of Limen.Maze, for clients caught by a Limen.Trap).

The list holds at most :max_bans entries; further bans are refused.

When clustering is enabled (see Limen.Cluster), bans and unbans made on this node are also queued for broadcast; bans received from other nodes are not broadcast again.

Summary

Functions

Bans prefix for ttl seconds.

Lists active bans, soonest to expire first.

Returns the active ban for prefix at now (milliseconds), if any.

Removes expired bans and returns how many were removed.

Lifts the ban on prefix.

Types

action()

@type action() :: :deny | :maze

ban()

@type ban() :: %{
  prefix: Limen.IP.prefix(),
  expires_at: integer(),
  reason: term(),
  mode: :dry_run | :enforce,
  origin: origin(),
  action: action()
}

origin()

@type origin() :: :policy | :admin | :trap | :remote

Functions

ban(instance, prefix, ttl, opts \\ [])

@spec ban(Limen.Instance.t(), Limen.IP.prefix(), pos_integer(), keyword()) ::
  :ok | {:error, :full}

Bans prefix for ttl seconds.

If the prefix is already banned, the ban is extended when the new one lasts longer, escalated to :enforce when either ban enforces, and to the maze when either sends there: a client caught in a trap stays caught. Bans of the same prefix made at the same time all take effect.

Options

  • :reason - recorded with the ban and reported in decisions.
  • :mode - :enforce (default) or :dry_run.
  • :action - :deny (default) or :maze.
  • :origin - :policy, :admin (default), :trap or :remote.
  • :now - the current system time in milliseconds.

list(instance, now \\ System.system_time(:millisecond))

@spec list(Limen.Instance.t(), integer()) :: [ban()]

Lists active bans, soonest to expire first.

lookup(instance, prefix, now)

@spec lookup(Limen.Instance.t(), Limen.IP.prefix() | nil, integer()) :: ban() | nil

Returns the active ban for prefix at now (milliseconds), if any.

sweep(instance, now \\ System.system_time(:millisecond))

@spec sweep(Limen.Instance.t(), integer()) :: non_neg_integer()

Removes expired bans and returns how many were removed.

unban(instance, prefix, opts \\ [])

@spec unban(Limen.Instance.t(), Limen.IP.prefix(), keyword()) :: :ok

Lifts the ban on prefix.