l4postgres

package
v0.1.2 Latest Latest
Warning

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

Go to latest
Published: Jul 15, 2026 License: Apache-2.0 Imports: 10 Imported by: 3

Documentation

Overview

Package l4postgres allows the L4 multiplexing of Postgres connections.

The single "postgres" matcher detects a Postgres connection and can, in addition, filter on the contents of the first message the client sends:

  • user filters on the user (and, optionally, database) StartupMessage parameters;
  • client filters on the application_name StartupMessage parameter;
  • ssl requires the presence or absence of an SSLRequest.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func TLSClient added in v0.1.2

func TLSClient(conn net.Conn, cfg *tls.Config) (net.Conn, error)

TLSClient performs the PostgreSQL SSLRequest negotiation as a client on conn: it sends the SSLRequest, reads the server's reply, and on 'S' completes a TLS handshake using cfg, returning the encrypted connection. On 'N' (the server declines TLS) or any other reply it returns an error.

Use this to re-originate TLS to a Postgres upstream that expects sslmode != disable, i.e. the outbound counterpart of the inbound termination done by Handler + the `tls` handler.

Types

type Handler added in v0.1.2

type Handler struct{}

Handler negotiates the PostgreSQL SSLRequest preamble so that a following `tls` handler can terminate TLS and downstream matchers can then match the (now cleartext) startup message — e.g. by user, database, or application_name.

PostgreSQL does not begin TLS with a ClientHello: the client first sends an 8-byte SSLRequest and waits for a single byte, 'S' (server will use TLS) or 'N' (continue in plaintext). The generic `tls` handler expects a ClientHello immediately, so it cannot terminate a Postgres connection on its own. This handler reads the SSLRequest, replies 'S', and passes the connection on; put a `tls` handler next to perform the actual TLS handshake.

It must be preceded by a matcher that confirms the connection is a Postgres SSLRequest (e.g. the postgres matcher), so the 8 bytes it consumes really are the SSLRequest.

Example (Caddyfile): note that `postgres` is a matcher (it gates the route), while `postgres_tls`, `tls` and `proxy` are the handlers run on a match.

@pg postgres
route @pg {
	postgres_tls
	tls
	# downstream matchers now see the cleartext startup message
	proxy ...
}

func (*Handler) CaddyModule added in v0.1.2

func (*Handler) CaddyModule() caddy.ModuleInfo

CaddyModule returns the Caddy module information.

func (*Handler) Handle added in v0.1.2

func (h *Handler) Handle(cx *layer4.Connection, next layer4.Handler) error

Handle reads the SSLRequest, replies 'S', and hands off to the next handler.

func (*Handler) UnmarshalCaddyfile added in v0.1.2

func (h *Handler) UnmarshalCaddyfile(d *caddyfile.Dispenser) error

UnmarshalCaddyfile sets up the Handler from Caddyfile tokens. Syntax:

postgres_tls

type MatchPostgres

type MatchPostgres struct {
	// User maps a Postgres user name to the databases it is allowed to use.
	// The special key "*" applies to any user not listed explicitly. An empty
	// (or nil) database list matches any database for that user. Only applies to
	// StartupMessages (which carry the user/database parameters).
	User map[string][]string `json:"user,omitempty"`

	// Client is the list of accepted application_name values. Only applies to
	// StartupMessages (which carry the application_name parameter).
	Client []string `json:"client,omitempty"`

	// TLS constrains whether the connection must begin with an SSLRequest:
	// "enabled" requires one, "disabled" requires its absence, and "" (the
	// default) is indifferent.
	TLS string `json:"tls,omitempty"`
}

MatchPostgres matches Postgres connections. With no options set it matches any well-formed Postgres first message (SSLRequest, CancelRequest or a protocol-3 StartupMessage). The optional User, Client and TLS fields further constrain the match; when more than one is set, all must be satisfied.

func (*MatchPostgres) CaddyModule

func (*MatchPostgres) CaddyModule() caddy.ModuleInfo

CaddyModule returns the Caddy module information.

func (*MatchPostgres) Match

func (m *MatchPostgres) Match(cx *layer4.Connection) (bool, error)

Match returns true if the connection looks like the Postgres protocol and satisfies every configured constraint (tls, user/database, application_name).

func (*MatchPostgres) Provision

func (m *MatchPostgres) Provision(_ caddy.Context) error

Provision validates the TLS option.

func (*MatchPostgres) UnmarshalCaddyfile

func (m *MatchPostgres) UnmarshalCaddyfile(d *caddyfile.Dispenser) error

UnmarshalCaddyfile sets up the matcher from Caddyfile tokens. Syntax:

postgres

postgres {
	# match user/database pairs; repeat for each entry, "*" is the wildcard
	user <name> [<database>...]
	# match the application_name parameter
	client <name> [<name>...]
	# require (enabled) or reject (disabled) an SSLRequest; "*" is indifferent
	tls <enabled|disabled|*>
}

Jump to

Keyboard shortcuts

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