multiplexer

package
v0.0.0-...-5c79d48 Latest Latest
Warning

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

Go to latest
Published: Feb 15, 2024 License: AGPL-3.0 Imports: 29 Imported by: 0

Documentation

Overview

Package multiplexer implements SSH and TLS multiplexing on the same listener

mux, _ := multiplexer.New(Config{Listener: listener}) mux.SSH() // returns listener getting SSH connections mux.TLS() // returns listener getting TLS connections

Index

Constants

View Source
const (
	// TCP4 is TCP over IPv4
	TCP4 = "TCP4"
	// TCP6 is tCP over IPv6
	TCP6 = "TCP6"
	// Unknown is unsupported or unknown protocol
	UNKNOWN = "UNKNOWN"

	PP2TypeNOOP PP2Type = 0x04 // No-op used for padding

	// Known custom types, spec allows to use 0xE0 - 0xEF for custom types
	PP2TypeGCP   PP2Type = 0xE0 // https://cloud.google.com/vpc/docs/configure-private-service-connect-producer
	PP2TypeAWS   PP2Type = 0xEA // https://docs.aws.amazon.com/elasticloadbalancing/latest/network/load-balancer-target-groups.html
	PP2TypeAzure PP2Type = 0xEE // https://learn.microsoft.com/en-us/azure/private-link/private-link-service-overview

	PP2TypeTeleport PP2Type = 0xE4 // Teleport own type for transferring our custom data such as connection metadata

	PP2TeleportSubtypeSigningCert PP2TeleportSubtype = 0x01 // Certificate used to sign JWT
	PP2TeleportSubtypeJWT         PP2TeleportSubtype = 0x02 // JWT used to verify information sent in plain PROXY header
)
View Source
const (
	Version2     = 2
	ProxyCommand = 1
	LocalCommand = 0
	ProtocolTCP4 = 0x11
	ProtocolTCP6 = 0x21
)

Variables

View Source
var (

	// ErrTruncatedTLV is returned when there's no enough bytes to read full TLV
	ErrTruncatedTLV = errors.New("TLV value was truncated")

	// ErrNoSignature is returned when proxy line doesn't have full required data (JWT and cert) for verification
	ErrNoSignature = errors.New("could not find signature data on the proxy line")
	// ErrBadCACert is returned when a HostCA cert could not successfully be added to roots for signing certificate verification
	ErrBadCACert = errors.New("could not add host CA to roots for verification")
	// ErrIncorrectRole is returned when signing cert doesn't have required system role (Proxy)
	ErrIncorrectRole = errors.New("could not find required system role on the signing certificate")
	// ErrNonLocalCluster is returned when we received signed PROXY header, which signing certificate is from remote cluster.
	ErrNonLocalCluster = errors.New("signing certificate is not signed by local cluster CA")
	// ErrNoHostCA is returned when CAGetter could not get host CA, for example if auth server is not available
	ErrNoHostCA = errors.New("could not get specified host CA to verify signed PROXY header")
)
View Source
var (
	// ErrBadIP is returned when there's a problem with client source or destination IP address
	ErrBadIP = trace.BadParameter(
		"client source and destination addresses should be valid same TCP version non-nil IP addresses")
)
View Source
var (
	ProxyV2Prefix = []byte{0x0D, 0x0A, 0x0D, 0x0A, 0x00, 0x0D, 0x0A, 0x51, 0x55, 0x49, 0x54, 0x0A}
)

Functions

func MarshalTLVs

func MarshalTLVs(tlvs []TLV) ([]byte, error)

MarshalTLVs marshals provided slice of TLVs into slice of bytes.

Types

type CertAuthorityGetter

type CertAuthorityGetter = func(ctx context.Context, id types.CertAuthID, loadKeys bool) (types.CertAuthority, error)

CertAuthorityGetter allows to get cluster's host CA for verification of signed PROXY headers. We define our own version to not create dependency on the 'services' package, which causes circular references

type Config

type Config struct {
	// Listener is listener to multiplex connection on
	Listener net.Listener
	// Context is a context to signal stops, cancellations
	Context context.Context
	// DetectTimeout is a timeout applied to the whole detection phase of the
	// connection, set to defaults.ReadHeadersTimeout if unspecified
	DetectTimeout time.Duration
	// Clock is a clock to override in tests, set to real time clock
	// by default
	Clock clockwork.Clock
	// PROXYProtocolMode controls behavior related to unsigned PROXY protocol headers.
	PROXYProtocolMode PROXYProtocolMode
	// ID is an identifier used for debugging purposes
	ID string
	// CertAuthorityGetter is used to get CA to verify singed PROXY headers sent internally by teleport
	CertAuthorityGetter CertAuthorityGetter
	// LocalClusterName set the local cluster for the multiplexer, it's used in PROXY headers verification.
	LocalClusterName string

	// IgnoreSelfConnections is used for tests, it makes multiplexer ignore the fact that it's self
	// connection (coming from same IP as the listening address) when deciding if it should drop connection with
	// missing required PROXY header. This is needed since all connections in tests are self connections.
	IgnoreSelfConnections bool

	// PreDetect, if set, is called on each incoming connection before protocol
	// detection; the returned [PostDetectFunc] (if any) will then be called
	// after protocol detection, and will have the ability to modify or wrap the
	// [*Conn] before it's passed to the listener; if the PostDetectFunc returns
	// a nil [net.Conn], the connection will not be handled any further by the
	// multiplexer, and it's the responsibility of the PostDetectFunc to arrange
	// for it to be eventually closed.
	PreDetect PreDetectFunc
}

Config is a multiplexer config

func (*Config) CheckAndSetDefaults

func (c *Config) CheckAndSetDefaults() error

CheckAndSetDefaults verifies configuration and sets defaults

type Conn

type Conn struct {
	net.Conn
	// contains filtered or unexported fields
}

Conn is a connection wrapper that supports communicating remote address from proxy protocol and replays first several bytes read during protocol detection

func NewConn

func NewConn(conn net.Conn) *Conn

NewConn returns a net.Conn wrapper that supports peeking into the connection.

func (*Conn) Detect

func (c *Conn) Detect() (Protocol, error)

Detect detects the connection protocol by peeking into the first few bytes.

func (*Conn) Discard

func (c *Conn) Discard(n int) (discarded int, err error)

Discard is *bufio.Reader.Discard.

func (*Conn) LocalAddr

func (c *Conn) LocalAddr() net.Addr

LocalAddr returns local address of the connection

func (*Conn) NetConn

func (c *Conn) NetConn() net.Conn

NetConn returns the underlying net.Conn.

func (*Conn) Peek

func (c *Conn) Peek(n int) ([]byte, error)

Peek is *bufio.Reader.Peek.

func (*Conn) Protocol

func (c *Conn) Protocol() Protocol

Protocol returns the detected connection protocol

func (*Conn) Read

func (c *Conn) Read(p []byte) (int, error)

Read reads from connection

func (*Conn) ReadByte

func (c *Conn) ReadByte() (byte, error)

ReadByte is *bufio.Reader.ReadByte.

func (*Conn) ReadProxyLine

func (c *Conn) ReadProxyLine() (*ProxyLine, error)

ReadProxyLine reads proxy-line from the connection.

func (*Conn) RemoteAddr

func (c *Conn) RemoteAddr() net.Addr

RemoteAddr returns remote address of the connection

type JWTPROXYSigner

type JWTPROXYSigner interface {
	SignPROXYJWT(p jwt.PROXYSignParams) (string, error)
}

JWTPROXYSigner provides ability to created JWT for signed PROXY headers.

type Listener

type Listener struct {
	// contains filtered or unexported fields
}

Listener is a listener that receives connections from multiplexer based on the connection type

func (*Listener) Accept

func (l *Listener) Accept() (net.Conn, error)

Accept accepts connections from parent multiplexer listener

func (*Listener) Addr

func (l *Listener) Addr() net.Addr

Addr returns listener addr, the address of multiplexer listener

func (*Listener) Close

func (l *Listener) Close() error

Close closes the listener.

func (*Listener) HandleConnection

func (l *Listener) HandleConnection(ctx context.Context, conn net.Conn)

HandleConnection injects the connection into the Listener, blocking until the context expires, the connection is accepted or the Listener is closed.

type Mux

type Mux struct {
	sync.RWMutex
	*log.Entry
	Config
	// contains filtered or unexported fields
}

Mux supports having both SSH and TLS on the same listener socket

func New

func New(cfg Config) (*Mux, error)

New returns a new instance of multiplexer

func (*Mux) Close

func (m *Mux) Close() error

Close closes listener

func (*Mux) DB

func (m *Mux) DB() net.Listener

DB returns listener that receives database connections

func (*Mux) SSH

func (m *Mux) SSH() net.Listener

SSH returns listener that receives SSH connections

func (*Mux) Serve

func (m *Mux) Serve() error

Serve is a blocking function that serves on the listening socket and accepts requests. Every request is served in a separate goroutine

func (*Mux) TLS

func (m *Mux) TLS() net.Listener

TLS returns listener that receives TLS connections

func (*Mux) Wait

func (m *Mux) Wait()

Wait waits until listener shuts down and stops accepting new connections this is to workaround issue https://github.com/golang/go/issues/10527 in tests

type PP2TeleportSubtype

type PP2TeleportSubtype PP2Type

type PP2Type

type PP2Type byte

PP2Type is the PROXY protocol v2 TLV type

type PROXYEnabledListener

type PROXYEnabledListener struct {
	net.Listener
	// contains filtered or unexported fields
}

PROXYEnabledListener wraps provided listener and can receive and apply PROXY headers and then pass connection up the chain.

func NewPROXYEnabledListener

func NewPROXYEnabledListener(cfg Config) (*PROXYEnabledListener, error)

NewPROXYEnabledListener creates news instance of PROXYEnabledListener

func (*PROXYEnabledListener) Accept

func (p *PROXYEnabledListener) Accept() (net.Conn, error)

Accept gets connection from the wrapped listener and detects whether we receive PROXY headers on it, after first non PROXY protocol detected it returns connection with PROXY addresses applied to it.

func (*PROXYEnabledListener) Close

func (p *PROXYEnabledListener) Close() error

type PROXYHeaderSigner

type PROXYHeaderSigner interface {
	SignPROXYHeader(source, destination net.Addr) ([]byte, error)
}

PROXYHeaderSigner allows to sign PROXY headers for securely propagating original client IP information

type PROXYProtocolMode

type PROXYProtocolMode string

PROXYProtocolMode controls behavior related to unsigned PROXY protocol headers. Possible values: - 'on': one PROXY header is accepted and required per incoming connection. - 'off': no PROXY headers are allows, otherwise connection is rejected. If unspecified - one PROXY header is allowed, but not required. Connection is marked with source port set to 0 and IP pinning will not be allowed. It is supposed to be used only as default mode for test setups. In production you should always explicitly set the mode based on your network setup - if you have L4 load balancer with enabled PROXY protocol in front of Teleport you should set it to 'on', if you don't have it, set it to 'off'

const (
	PROXYProtocolOn          PROXYProtocolMode = "on"
	PROXYProtocolOff         PROXYProtocolMode = "off"
	PROXYProtocolUnspecified PROXYProtocolMode = ""
)

type PROXYSigner

type PROXYSigner struct {
	// contains filtered or unexported fields
}

PROXYSigner implements PROXYHeaderSigner to sign PROXY headers

func NewPROXYSigner

func NewPROXYSigner(signingCert *x509.Certificate, jwtSigner JWTPROXYSigner) (*PROXYSigner, error)

NewPROXYSigner returns a new instance of PROXYSigner

func (*PROXYSigner) SignPROXYHeader

func (p *PROXYSigner) SignPROXYHeader(source, destination net.Addr) ([]byte, error)

SignPROXYHeader creates a signed PROXY header with provided source and destination addresses

type PostDetectFunc

type PostDetectFunc = func(*Conn) net.Conn

PostDetectFunc is optionally returned by a PreDetectFunc.

type PreDetectFunc

type PreDetectFunc = func(net.Conn) (PostDetectFunc, error)

PreDetectFunc is used in Mux's Config as the PreDetect hook.

type Protocol

type Protocol int

Protocol defines detected protocol type.

const (
	// ProtoUnknown is for unknown protocol
	ProtoUnknown Protocol = iota
	// ProtoTLS is TLS protocol
	ProtoTLS
	// ProtoSSH is SSH protocol
	ProtoSSH
	// ProtoProxy is a HAProxy proxy line protocol
	ProtoProxy
	// ProtoProxyV2 is a HAProxy binary protocol
	ProtoProxyV2
	// ProtoHTTP is HTTP protocol
	ProtoHTTP
	// ProtoPostgres is PostgreSQL wire protocol
	ProtoPostgres
)

func (Protocol) String

func (p Protocol) String() string

String returns the string representation of Protocol p. An empty string is returned when the protocol is not defined.

type ProxyLine

type ProxyLine struct {
	Protocol    string
	Source      net.TCPAddr
	Destination net.TCPAddr
	TLVs        []TLV // PROXY protocol extensions
	IsVerified  bool
}

ProxyLine implements PROXY protocol version 1 and 2 Spec: https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt Original implementation here: https://github.com/racker/go-proxy-protocol TLV: https://github.com/pires/go-proxyproto

func ReadProxyLine

func ReadProxyLine(reader *bufio.Reader) (*ProxyLine, error)

ReadProxyLine reads proxy line protocol from the reader

func ReadProxyLineV2

func ReadProxyLineV2(reader *bufio.Reader) (*ProxyLine, error)

ReadProxyLineV2 reads PROXY protocol v2 line from the reader

func (*ProxyLine) AddSignature

func (p *ProxyLine) AddSignature(signature, signingCert []byte) error

AddSignature adds provided signature and cert to the proxy line, marshaling it into appropriate TLV structure.

func (*ProxyLine) Bytes

func (p *ProxyLine) Bytes() ([]byte, error)

Bytes returns on-the wire bytes representation of proxy line conforming to the proxy v2 protocol

func (*ProxyLine) IsSigned

func (p *ProxyLine) IsSigned() bool

IsSigned returns true if proxy line's TLV contains signature. Does not take into account if signature is valid or not, just the presence of it.

func (*ProxyLine) String

func (p *ProxyLine) String() string

String returns on-the wire string representation of the proxy line

func (*ProxyLine) VerifySignature

func (p *ProxyLine) VerifySignature(ctx context.Context, caGetter CertAuthorityGetter, localClusterName string, clock clockwork.Clock) error

VerifySignature checks that signature contained in the proxy line is securely signed.

type TLSListener

type TLSListener struct {
	// contains filtered or unexported fields
}

TLSListener wraps tls.Listener and detects negotiated protocol (assuming it's either http/1.1 or http/2) and forwards the appropriate responses to either HTTP/1.1 or HTTP/2 listeners

func NewTLSListener

func NewTLSListener(cfg TLSListenerConfig) (*TLSListener, error)

NewTLSListener returns a new TLS listener

func (*TLSListener) Addr

func (l *TLSListener) Addr() net.Addr

Addr returns the listener's network address.

func (*TLSListener) Close

func (l *TLSListener) Close() error

Close closes the listener. Any blocked Accept operations will be unblocked and return errors.

func (*TLSListener) HTTP

func (l *TLSListener) HTTP() net.Listener

HTTP returns HTTP listener

func (*TLSListener) HTTP2

func (l *TLSListener) HTTP2() net.Listener

HTTP2 returns HTTP2 listener

func (*TLSListener) Serve

func (l *TLSListener) Serve() error

Serve accepts and forwards tls.Conn connections

type TLSListenerConfig

type TLSListenerConfig struct {
	// Listener is the listener returning *tls.Conn
	// connections on Accept
	Listener net.Listener
	// ID is an identifier used for debugging purposes
	ID string
	// ReadDeadline is a connection read deadline during the TLS handshake (start
	// of the connection). It is set to defaults.HandshakeReadDeadline if
	// unspecified.
	ReadDeadline time.Duration
	// Clock is a clock to override in tests, set to real time clock
	// by default
	Clock clockwork.Clock
}

TLSListenerConfig specifies listener configuration

func (*TLSListenerConfig) CheckAndSetDefaults

func (c *TLSListenerConfig) CheckAndSetDefaults() error

CheckAndSetDefaults verifies configuration and sets defaults

type TLV

type TLV struct {
	Type  PP2Type
	Value []byte
}

TLV (Type-Length-Value) is an extension mechanism in PROXY protocol v2, see end of section 2.2

func UnmarshalTLVs

func UnmarshalTLVs(rawBytes []byte) ([]TLV, error)

UnmarshalTLVs parses provided bytes slice into slice of TLVs

type TestProxy

type TestProxy struct {
	// contains filtered or unexported fields
}

TestProxy is tcp passthrough proxy that sends a proxy-line when connecting to the target server.

func NewTestProxy

func NewTestProxy(target string, v2 bool) (*TestProxy, error)

NewTestProxy creates a new test proxy that sends a proxy-line when proxying connections to the provided target address.

func (*TestProxy) Address

func (p *TestProxy) Address() string

Address returns the proxy listen address.

func (*TestProxy) Close

func (p *TestProxy) Close() error

Close closes the proxy listener.

func (*TestProxy) Serve

func (p *TestProxy) Serve() error

Serve starts accepting client connections and proxying them to the target.

type WebListener

type WebListener struct {
	// contains filtered or unexported fields
}

WebListener multiplexes tls connections between web and database listeners based on the client certificate.

func NewWebListener

func NewWebListener(cfg WebListenerConfig) (*WebListener, error)

NewWebListener returns a new web listener.

func (*WebListener) Addr

func (l *WebListener) Addr() net.Addr

Addr returns the listener's network address.

func (*WebListener) Close

func (l *WebListener) Close() error

Close closes the listener.

Any blocked Accept operations will be unblocked and return errors.

func (*WebListener) DB

func (l *WebListener) DB() net.Listener

DB returns database access listener.

func (*WebListener) Serve

func (l *WebListener) Serve() error

Serve starts accepting and forwarding tls connections to appropriate listeners.

func (*WebListener) Web

func (l *WebListener) Web() net.Listener

Web returns web listener.

type WebListenerConfig

type WebListenerConfig struct {
	// Listener is the listener that accepts tls connections.
	Listener net.Listener
	// ReadDeadline is a connection read deadline during the TLS handshake.
	ReadDeadline time.Duration
	// Clock is a clock to override in tests.
	Clock clockwork.Clock
}

WebListenerConfig is the web listener configuration.

func (*WebListenerConfig) CheckAndSetDefaults

func (c *WebListenerConfig) CheckAndSetDefaults() error

CheckAndSetDefaults verifies configuration and sets defaults.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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