Documentation
¶
Overview ¶
Package atunnel carries actor ingress and egress through an ateom worker pod.
Index ¶
- Constants
- Variables
- func ParsePort(s string) (port int, ok bool)
- func TCPOriginalDestination(conn net.Conn) (string, error)
- type BrokerCertificateSource
- type BrokerConfig
- type Client
- type ClientConfig
- type ClientOption
- type Config
- type ConnectRejectedError
- type DialFunc
- type Egress
- type OriginalDestination
- type Server
- func (s *Server) Activate(atespace, actorName string) error
- func (s *Server) Deactivate(ctx context.Context) error
- func (s *Server) Serve(ctx context.Context, lis net.Listener) error
- func (s *Server) ServeConnect(ctx context.Context, lis net.Listener) error
- func (s *Server) ServeConnectHTTP(w http.ResponseWriter, r *http.Request)
- func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request)
Constants ¶
const ( // DefaultConnectPort is the worker port on which atunnel accepts inbound // mTLS CONNECT tunnels from the ingress router. DefaultConnectPort = 8443 // StaleAssignmentHeader distinguishes an atunnel routing rejection from a // 421 returned by the actor application itself. StaleAssignmentHeader = "X-Ate-Assignment-Stale" // OriginalHostHeader carries the actor authority across router dataplanes // that must use :authority to select the worker as their dynamic backend. // atunnel only accepts mTLS-authenticated router clients, and the router's // ext_proc server overwrites this header before every request. OriginalHostHeader = "X-Ate-Original-Host" // TargetPortHeader carries the port to reach on the actor: the CONNECT // :authority's port for arbitrary-port ingress, or the default 80 // otherwise (see atenet-router's HandleRequestHeaders). cfg.Upstream is // fixed for the Server's lifetime, so this lets the port vary per // request; stripped before the request reaches the actor. TargetPortHeader = "X-Ate-Target-Port" )
Variables ¶
var ErrGatewayHandshake = errors.New("atunnel: egress gateway TLS handshake")
ErrGatewayHandshake reports that the gateway's front door refused the connection at TLS: it rejected the client certificate, or its own certificate did not verify.
Functions ¶
func ParsePort ¶
ParsePort parses s as a TCP port number, returning ok=false for anything outside the valid 1-65535 range (including non-numeric input).
func TCPOriginalDestination ¶
TCPOriginalDestination reads the IPv4 destination preserved by a Linux REDIRECT rule. Actor networking is currently IPv4-only. TODO(liorlieberman) add the IPv6 IP6T_SO_ORIGINAL_DST variant when actor veth setup gains dual-stack support.
Types ¶
type BrokerCertificateSource ¶
type BrokerCertificateSource struct {
// contains filtered or unexported fields
}
BrokerCertificateSource owns atunnel's actor private key and obtains the matching short-lived certificate from the node-local atelet.
func NewBrokerCertificateSource ¶
func NewBrokerCertificateSource(cfg BrokerConfig) (*BrokerCertificateSource, error)
NewBrokerCertificateSource creates one actor key for this activation. The key is reused across renewals and never leaves atunnel; only its CSR crosses the credential broker socket.
func (*BrokerCertificateSource) GetClientCertificate ¶
func (s *BrokerCertificateSource) GetClientCertificate(*tls.CertificateRequestInfo) (*tls.Certificate, error)
GetClientCertificate supplies the current actor certificate to the egress gateway TLS handshake and refuses to use it after expiry.
type BrokerConfig ¶
type BrokerConfig struct {
// SocketPath is the atelet-owned Unix socket shared with this worker.
SocketPath string
// CredentialBundlePath is the worker Pod certificate and private key used
// only to authenticate atunnel to atelet.
CredentialBundlePath string
// TrustBundlePath verifies atelet's Pod certificate.
TrustBundlePath string
// ExpectedActorUID prevents a mint started for an old activation from
// receiving the newly assigned actor's certificate.
ExpectedActorUID string
}
BrokerConfig configures the node-local atelet credential broker client.
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client opens actor egress streams through an mTLS-authenticated gateway.
func NewClient ¶
func NewClient(cfg ClientConfig, opts ...ClientOption) (*Client, error)
NewClient creates an egress CONNECT client and validates its TLS material.
type ClientConfig ¶
type ClientConfig struct {
GatewayAddress string
ServerName string
GetClientCertificate func(*tls.CertificateRequestInfo) (*tls.Certificate, error)
TrustBundlePath string
}
TODO(liorlieberman): support/use CONNECT on Ingress as well. ClientConfig configures an egress CONNECT client.
type ClientOption ¶
type ClientOption func(*Client)
ClientOption customizes a Client beyond its configuration. Production callers need none of these.
func WithDialer ¶
func WithDialer(dial DialFunc) ClientOption
WithDialer overrides how the client reaches the egress gateway. It exists so tests can substitute a transport; by default a net.Dialer is used.
type Config ¶
type Config struct {
CredentialBundlePath string
TrustBundlePath string
AllowedClientID string
Upstream *url.URL
}
Config configures an ingress Server.
type ConnectRejectedError ¶
type ConnectRejectedError struct {
StatusCode int
// Status is the full status line, e.g. "403 Forbidden".
Status string
// Message is the response body, or the status text when the body is empty.
Message string
}
ConnectRejectedError reports a CONNECT the gateway answered with a non-2xx status. The caller authenticated successfully and the request was declined anyway, which is what an authorization denial looks like from here. The status code is carried separately from the message because it is the part a caller can act on.
func (*ConnectRejectedError) Error ¶
func (e *ConnectRejectedError) Error() string
type Egress ¶
type Egress struct {
// contains filtered or unexported fields
}
Egress proxies actor TCP connections through an egress CONNECT dialer. It is long-lived across actor activations, but only carries traffic while an actor is assigned to its worker.
func NewEgress ¶
func NewEgress(originalDestination OriginalDestination) (*Egress, error)
NewEgress creates an activation-aware egress proxy.
func (*Egress) Activate ¶
func (e *Egress) Activate(dialer egressDialer, certificateSource actorCertificateSource, expiresAt time.Time) error
Activate allows egress with a previously obtained actor certificate and renews it until deactivation.
func (*Egress) Deactivate ¶
Deactivate rejects new egress, closes active streams, and waits for their forwarding goroutines to exit.
type OriginalDestination ¶
OriginalDestination returns the address that a transparently intercepted connection originally targeted.
type Server ¶
type Server struct {
// contains filtered or unexported fields
}
Server is an activation-aware HTTPS reverse proxy. It is long-lived across actor activations, but only routes requests for the actor currently assigned to its worker.
func (*Server) Activate ¶
Activate allows requests for actorName in atespace. There can be only one active actor per worker.
func (*Server) Deactivate ¶
Deactivate rejects new requests, cancels requests for the active actor, and waits for their handlers to exit before returning.
func (*Server) ServeConnect ¶
ServeConnect serves the mTLS CONNECT endpoint. CONNECT is deliberately on a separate listener so ordinary actor ingress remains a request proxy, while the router can use this listener for a bidirectional tunnel.
func (*Server) ServeConnectHTTP ¶
func (s *Server) ServeConnectHTTP(w http.ResponseWriter, r *http.Request)
ServeConnectHTTP accepts a router-authenticated CONNECT request and relays its tunnel to the named port on the currently active actor.