guardedbeaconproxy

package module
v0.1.1 Latest Latest
Warning

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

Go to latest
Published: Sep 14, 2023 License: AGPL-3.0 Imports: 25 Imported by: 1

README

Guarded-BeaconProxy Go Reference

Guarded-Beacon-Proxy

Guarded-Beacon-Proxy is a library to enable reverse proxies that sit between Ethereum validators and their respective Beacon Nodes. In addition to reverse proxying traffic, it provides hooks to enforce user authentication and fee recipient validation. These hooks can be configured to prevent access from unauthorized VCs and/or prevent VCs from setting unauthorized fee recipients for their tips/MEV.

Guarded-Beacon-Proxy is designed to be similar to http.Server in its usage pattern. For example, a proxy can be instantiated like so:

        beaconURL, _ := url.Parse("http://eth2:5052")
        pr := &gbp.GuardedBeaconProxy{
                Addr:                       "http://0.0.0.0:8052",
                BeaconURL:                  beaconURL,
                GRPCAddr:                   "0.0.0.0:8053",
                GRPCBeaconURL:              "eth2:5053",

                HTTPAuthenticator:          func(r *http.Request) (AuthenticationStatus, context.Context, error) {
                        // Add your authentication here
                        return gbp.Authorized, nil, nil
                },
                GRPCAuthenticator:          func(md metadata.MD) (AuthenticationStatus, context.Context, error) {
                        // Add your authentication here
                        return gbp.Authorized, nil, nil
                },
                PrepareBeaconProposerGuard: func(PrepareBeaconProposerRequest r, ctx context.Context) (AuthenticationStatus, error) {
                        // Add your fee recipient validation here
                        return gbp.Authorized, nil
                },
                RegisterValidatorGuard:     func(r RegisterValidatorRequest, ctx context.Context) (AuthenticationStatus, error) {
                        // Add your fee recipient validation here
                        return gbp.Authorized, nil
                },
        }
        pr.TLS.CertFile = "/etc/ssl/certs/mycert/certfile"
        pr.TLS.KeyFile = "/etc/ssl/certs/mycert/certkey"

        // Blocks until pr.Stop() is called or a non-nil error is returned
        err := pr.ListenAndServe()

Validating fee recipients is important to prevent cross-client theft- that is, two node operators using the service stealing mev/tips from each other. However, because register_validator requires a signature from the VC, it is not as critical as prepare_beacon_proposer validation. You should establish which fee recipients are valid for which public keys out-of-band, ie, by looking at 0x01 credentials for the validator on the Beacon Chain. If you are operating the proxy for a LST, for instance, register_validator and prepare_beacon_proposer should both be guarded to prevent theft by node operators from the protocol itself, instead of just from one another.

Authenticating requests is useful to control who can connect to your Beacon Nodes, and shouldn't be overlooked just because of the fee recipient guards- many other paths are only guarded by authentication. For example, Rocket-Rescue-Node provides our users with HMAC credentials that encode some useful data to us, such as time limits and the address of the connecting node's Rocket Pool wallet.

See Rescue-Proxy as a reference implementation.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type AuthenticationStatus

type AuthenticationStatus uint32

AuthenticationStatus is a generic status response representing auth or guard results.

It is returned by the custom authentication or guard functions on the GuardedBeaconProxy, and mapped to an appropriate HTTP or gRPC error as needed.

const (
	Allowed AuthenticationStatus = iota
	BadRequest
	Unauthorized
	Forbidden
	Conflict
	TooManyRequests
	InternalError
)

These constants are the only allowable AuthenticationStatus values

type GRPCAuthenticator

type GRPCAuthenticator func(metadata.MD) (AuthenticationStatus, context.Context, error)

GRPCAuthenticator is a function type that authenticates gRPC traffic. The authentication method must be based on gRPC Metadata, as gRPC does not support BasicAuth out of box.

Returning an AuthenticationStatus other than Allowed will prevent the request from being proxied. You may optionally return a Context, which will be passed to the PrepareBeaconProposerGuard/RegisterValidatorGuard functions provided. In particular, conext.WithValue allows the authentication method to share state with the guard methods.

Any error returned will be sent back to the client, so do not encode sensitive information.

type GuardedBeaconProxy

type GuardedBeaconProxy struct {
	// URL of the upstream beacon node
	BeaconURL *url.URL
	// Optional GRPC URL of the upstream beacon node (prysm grpc port)
	GRPCBeaconURL string

	// Optional TLS certificates for gRPC
	TLS struct {
		// Path to certificate file
		CertFile string
		// Path to key file
		KeyFile string
	}

	// Address to listen for requests on
	Addr string
	// Optional GRPC address to listen on
	GRPCAddr string
	// Pass-through HTTP server settings
	ReadTimeout       time.Duration
	ReadHeaderTimeout time.Duration
	WriteTimeout      time.Duration
	IdleTimeout       time.Duration
	MaxHeaderBytes    int

	ErrorLog *log.Logger

	// Optional authentication function for HTTP requests
	HTTPAuthenticator HTTPAuthenticator
	// Optional authentication function for GRPC requests
	GRPCAuthenticator GRPCAuthenticator

	// Optional PrepareBeaconProposerGuard
	PrepareBeaconProposerGuard PrepareBeaconProposerGuard
	// Optional RegisterValidatorGuard
	RegisterValidatorGuard RegisterValidatorGuard
	// contains filtered or unexported fields
}

GuardedBeaconProxy is a reverse proxy for guarding beacon nodes with custom logic.

The main goal is to provide easy hooks for custom request authentication and fee recipient validation, which is achieved through the Authenticator and Guard callbacks.

Since Prysm uses gRPC, GuardedBeaconProxy can optionally run a gRPC reverse proxy in addition to an HTTP reverse proxy.

If GRPCBeaconURL is set, all GRPC fields are required except the TLS block. TLS is currently only supported for gRPC.

Fields in GuardedBeaconProxy should be set prior to calling ListenAndServe.

func (*GuardedBeaconProxy) ListenAndServe

func (gbp *GuardedBeaconProxy) ListenAndServe() error

ListenAndServe binds the GuardedBeaconProxy to its HTTP port, and optionally its gRPC port, and prepares to receive and proxy traffic from validators.

ListenAndServe blocks until Stop is called or an error is encountered.

func (*GuardedBeaconProxy) Serve

func (gbp *GuardedBeaconProxy) Serve(httpListener net.Listener, grpcListener *net.Listener) error

Serve attaches the proxy to the provided listener(s)

Serve blocks until Stop is called or an error is encountered.

func (*GuardedBeaconProxy) Stop

func (gbp *GuardedBeaconProxy) Stop(ctx context.Context)

Stop attempts to gracefully shut down the GuardedBeaconProxy.

Canceling the provided context will trigger an immediate stop.

type HTTPAuthenticator

type HTTPAuthenticator func(*http.Request) (AuthenticationStatus, context.Context, error)

HTTPAuthenticator is a function type which can authenticate HTTP requests. For example, by checking the contents of the BasicAuth header.

Returning an AuthenticationStatus other than Allowed will prevent the request from being proxied. You may optionally return a Context, which will be passed to the PrepareBeaconProposerGuard/RegisterValidatorGuard functions provided. In particular, conext.WithValue allows the authentication method to share state with the guard methods.

Any error returned will be sent back to the client, so do not encode sensitive information.

type PrepareBeaconProposerGuard

type PrepareBeaconProposerGuard func(PrepareBeaconProposerRequest, context.Context) (AuthenticationStatus, error)

PrepareBeaconProposerGuard is a function that validates whether or not a PrepareBeaconProposer call should be proxied. The provided Context is whatever was returned by the authenticator.

type PrepareBeaconProposerRequest

type PrepareBeaconProposerRequest []struct {
	ValidatorIndex string `json:"validator_index"`
	FeeRecipient   string `json:"fee_recipient"`
}

PrepareBeaconProposerRequest is the in-memory representation of a prepare_beacon_proposer API call, be it gRPC or HTTP.

type RegisterValidatorGuard

type RegisterValidatorGuard func(RegisterValidatorRequest, context.Context) (AuthenticationStatus, error)

RegisterValidatorGuard is a function that validates whether or not a RegisterValidator call should be proxied. The provided Context is whatever was returned by the authenticator.

type RegisterValidatorMessage

type RegisterValidatorMessage struct {
	FeeRecipient string `json:"fee_recipient"`
	GasLimit     string `json:"gas_limit"`
	Timestamp    string `json:"timestamp"`
	Pubkey       string `json:"pubkey"`
}

RegisterValidatorMessage is the in-memory representation of a register_validator API call entry, be it gRPC or HTTP.

type RegisterValidatorRequest

type RegisterValidatorRequest []struct {
	Message   RegisterValidatorMessage `json:"message"`
	Signature string                   `json:"signature"`
}

RegisterValidatorRequest is the in-memory representation of a register_validator API call, be it gRPC or HTTP.

Jump to

Keyboard shortcuts

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