ipblock

package
v1.86.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 20, 2026 License: Apache-2.0 Imports: 12 Imported by: 0

Documentation

Overview

Package ipblock blocks IP addresses and address ranges.

A blocklist has two sides, and callers depend only on the one they use. The command side, Writer, adds and lifts blocks. The query side, Reader, answers whether an address is blocked and lists the blocks in force. A List is both sides over one store:

  • NewService keeps blocks in a document.Service, such as a Firestore collection, so every process using the collection shares them.
  • NewMemoryList keeps them in process memory.

Checking a shared store for every address would cost a round trip each, so NewCache serves a Reader from memory, reloading it from another Reader once per TTL. That is the query side a hot path should hold.

A block covers a prefix; a single address is a /32 or /128 prefix. IPv4-mapped IPv6 addresses are the IPv4 addresses they map. A block may lapse on its own at Block.ExpiresAt, after which it is neither matched nor listed, whether or not its storage has been cleaned up.

Index

Constants

This section is empty.

Variables

View Source
var ErrNotBlocked = errors.New("ipblock: prefix is not blocked")

ErrNotBlocked is returned by Unblock when there is no block to lift.

Functions

This section is empty.

Types

type Block

type Block struct {
	// Prefix is the blocked range. Writers store it with its host bits
	// masked off, and IPv4-mapped prefixes as IPv4.
	Prefix netip.Prefix
	// Reason says why the prefix is blocked, for whoever reads it later.
	Reason string
	// BlockedBy identifies who blocked it.
	BlockedBy string
	// BlockedAt is when it was blocked. Writers set it to the current
	// time when it is zero.
	BlockedAt time.Time
	// ExpiresAt is when the block lapses. The zero time means never.
	ExpiresAt time.Time
}

Block blocks every address in a prefix.

type List

type List interface {
	Writer
	Reader
}

List is a blocklist: both sides of one store of blocks.

func NewMemoryList

func NewMemoryList() List

NewMemoryList returns a List kept in process memory. Its blocks are not shared with other processes and do not outlive this one.

func NewService

func NewService(db document.Service) List

NewService returns a List that keeps one document per block in db. Every call reads or writes db, and Check reads the whole collection, so wherever addresses are checked often, check them through NewCache instead.

A lapsed block is ignored but its document is not deleted. On Firestore, a TTL policy on the ExpiresAt field deletes them; it is null on blocks that never lapse, which a TTL policy leaves alone.

type Reader

type Reader interface {
	// Check returns the block covering addr, and false when there is
	// none. When several blocks cover addr the narrowest one is
	// returned.
	Check(ctx context.Context, addr netip.Addr) (Block, bool, error)

	// List returns the blocks in force, ordered by prefix.
	List(ctx context.Context) ([]Block, error)
}

Reader is the query side of a blocklist.

func NewCache

func NewCache(src Reader, ttl time.Duration) Reader

NewCache returns a Reader that answers from an in-memory copy of the blocks src lists, so that checking an address costs no round trip to src. The copy is loaded on the first call and reloaded once it is ttl old, which bounds how long a change to src takes to show:

  • The first call waits for the load. If the load fails, the error is returned until ttl has passed, rather than every call retrying against a source that is down.
  • Once loaded, calls never wait: a reload runs in the background while the current copy keeps answering.
  • A failed reload keeps the current copy, so a source outage leaves the blocks it last listed in force rather than lifting them all. Blocks still lapse at their ExpiresAt meanwhile.

It panics when src is nil or ttl is not positive.

type Writer

type Writer interface {
	// Block blocks b.Prefix until b.ExpiresAt. It replaces any block on
	// the same prefix, so blocking again is how a block is extended or
	// reworded. It fails when the prefix is invalid or ExpiresAt is set
	// but not in the future.
	Block(ctx context.Context, b Block) error

	// Unblock lifts the block on exactly p. Blocks on prefixes that
	// contain p, or that p contains, are left alone. It returns
	// ErrNotBlocked when p has no block in force.
	Unblock(ctx context.Context, p netip.Prefix) error
}

Writer is the command side of a blocklist.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL