proxy

package
v3.5.0 Latest Latest
Warning

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

Go to latest
Published: Aug 12, 2026 License: MIT Imports: 18 Imported by: 2

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrUpstreamSchemeNotAllowed is returned when the proxied URL uses a
	// scheme outside the configured allowlist (default: http, https).
	ErrUpstreamSchemeNotAllowed = errors.New("proxy: upstream scheme is not allowed")

	// ErrUpstreamHostInvalid is returned when the proxied URL is missing a
	// host or cannot be parsed.
	ErrUpstreamHostInvalid = errors.New("proxy: upstream host is empty or invalid")

	// ErrUpstreamHostBlocked is returned when the proxied URL resolves to
	// an address inside a blocked range (loopback, RFC 1918 private,
	// link-local, multicast, unspecified, or CGNAT) and AllowPrivateIPs
	// is false.
	ErrUpstreamHostBlocked = errors.New("proxy: upstream host resolves to a blocked address")

	// ErrRedirectDowngrade is returned when DoRedirects encounters a
	// redirect from an HTTPS upstream to a plaintext HTTP target and
	// AllowHTTPSDowngrade is false.
	ErrRedirectDowngrade = errors.New("proxy: HTTPS to HTTP redirect blocked")
)

Sentinel errors returned when an upstream target violates the configured proxy security policy.

View Source
var ConfigDefault = Config{
	Next:                 nil,
	ModifyRequest:        nil,
	ModifyResponse:       nil,
	MaxConnsPerHost:      defaultMaxConnsPerHost,
	Timeout:              fasthttp.DefaultLBClientTimeout,
	KeepConnectionHeader: false,
}

ConfigDefault is the default config

Functions

func Balancer

func Balancer(config ...Config) fiber.Handler

Balancer creates a load balancer among multiple upstream servers

func BalancerForward

func BalancerForward(servers []string, clients ...*fasthttp.Client) fiber.Handler

BalancerForward Forward performs the given http request with round robin algorithm to server and fills the given http response. This method will return a fiber.Handler.

As with DomainForward, every server is parsed and policy-checked at handler construction. A misconfigured entry panics at startup.

SSRF note: despite the name, this helper dispatches through the shared/user-supplied client rather than a Balancer HostClient, but it gets the same protection as Do — up-front host validation plus the dial-time validated-IP guard on the dispatching client when AllowPrivateIPs is false.

func Do

func Do(c fiber.Ctx, addr string, clients ...*fasthttp.Client) error

Do performs the given http request and fills the given http response. This method can be used within a fiber.Handler

SSRF note: the upstream host is validated against the active SecurityPolicy before the request is sent, and when AllowPrivateIPs is false the resolved IP is re-validated at dial time by the guard installed on the dispatching *fasthttp.Client. The connection therefore targets exactly the address that passed the blocklist, so a rebinding-capable resolver cannot slip a private IP past the check.

The guard is installed via the client's ConfigureClient hook, which only affects HostClients created after installation. The default client and WithClient clients are guarded before first use; a client supplied as a per-call variadic override is guarded on first use, so a host it had already dialed keeps a cached, pre-guard HostClient. For a full guarantee with a custom client, register it via WithClient (or pass a dedicated, unused client) before first use.

func DoDeadline

func DoDeadline(c fiber.Ctx, addr string, deadline time.Time, clients ...*fasthttp.Client) error

DoDeadline performs the given request and waits for response until the given deadline. This method can be used within a fiber.Handler

SSRF note: same protection as Do — up-front host validation plus the dial-time validated-IP guard when AllowPrivateIPs is false.

func DoRedirects

func DoRedirects(c fiber.Ctx, addr string, maxRedirectsCount int, clients ...*fasthttp.Client) error

DoRedirects performs the given http request and fills the given http response, following up to maxRedirectsCount redirects. When the redirect count exceeds maxRedirectsCount, ErrTooManyRedirects is returned. This method can be used within a fiber.Handler

Each redirect target is re-validated against the active SecurityPolicy. Unless AllowHTTPSDowngrade is enabled, redirects from an HTTPS origin to a plaintext HTTP target are rejected with ErrRedirectDowngrade.

SSRF note: every hop's host is validated against the policy, and when AllowPrivateIPs is false each dial is re-validated by the guard on the dispatching client — so per-hop redirects (including cross-host ones) cannot be rebound to a private IP between validation and connection.

func DoTimeout

func DoTimeout(c fiber.Ctx, addr string, timeout time.Duration, clients ...*fasthttp.Client) error

DoTimeout performs the given request and waits for response during the given timeout duration. This method can be used within a fiber.Handler

SSRF note: same protection as Do — up-front host validation plus the dial-time validated-IP guard when AllowPrivateIPs is false.

func DomainForward

func DomainForward(hostname, addr string, clients ...*fasthttp.Client) fiber.Handler

DomainForward performs an http request based on the given domain and populates the given http response. This method will return a fiber.Handler.

The upstream addr is validated at handler construction: scheme allowlist, SSRF block, and URL parsing all run once. Unlike Balancer (which defers DNS to dial time to survive transient resolver failures at startup), this construction check resolves the host, so a misconfigured or unresolvable addr panics at startup instead of failing per request. Each request also re-validates the host against the current policy before dispatch.

SSRF note: the per-request validation is an up-front host check, and when AllowPrivateIPs is false the dispatching client's dial-time guard re-validates the resolved IP at connect time — so a rebinding-capable resolver cannot reach a private address through this handler.

func Forward

func Forward(addr string, clients ...*fasthttp.Client) fiber.Handler

Forward performs the given http request and fills the given http response. This method will return a fiber.Handler

SSRF note: Forward validates the upstream host against the active SecurityPolicy up front and, when AllowPrivateIPs is false, re-validates the resolved IP at dial time via the guard installed on the dispatching client, so a rebinding-capable resolver cannot swap a public answer for a private one between validation and connection.

func WithClient

func WithClient(cli *fasthttp.Client)

WithClient sets the global proxy client. This function should be called before Do and Forward — doing so installs the dial-time SSRF guard (via the client's ConfigureClient hook, composing with any hook it already carries) before the client dials any host, so requests dispatched through it re-validate the resolved IP at connect time, matching the default client's behavior.

Types

type Config

type Config struct {
	// Next defines a function to skip this middleware when returned true.
	//
	// Optional. Default: nil
	Next func(c fiber.Ctx) bool

	// ModifyRequest allows you to alter the request
	//
	// Optional. Default: nil
	ModifyRequest fiber.Handler

	// ModifyResponse allows you to alter the response
	//
	// Optional. Default: nil
	ModifyResponse fiber.Handler

	// tls config for the http client.
	TLSConfig *tls.Config

	// Client is custom client when client config is complex.
	// Note that Servers, Timeout, WriteBufferSize, ReadBufferSize, TLSConfig
	// and DialDualStack will not be used if the client are set.
	Client *fasthttp.LBClient

	// SecurityPolicy overrides the default SSRF, redirect, and
	// hop-by-hop header rules for this balancer. When nil, the
	// package-level policy set via WithSecurityPolicy is used.
	//
	// Optional. Default: nil
	SecurityPolicy *SecurityPolicy

	// Servers defines a list of <scheme>://<host> HTTP servers,
	//
	// which are used in a round-robin manner.
	// i.e.: "https://foobar.com, http://www.foobar.com"
	//
	// Required
	Servers []string

	// Timeout is the request timeout used when calling the proxy client
	//
	// Optional. Default: 1 second
	Timeout time.Duration

	// Maximum number of connections per upstream host.
	//
	// Optional. Default: 1024
	MaxConnsPerHost int

	// Per-connection buffer size for requests' reading.
	// This also limits the maximum header size.
	// Increase this buffer if your clients send multi-KB RequestURIs
	// and/or multi-KB headers (for example, BIG cookies).
	ReadBufferSize int

	// Per-connection buffer size for responses' writing.
	WriteBufferSize int

	// MaxResponseBodySize bounds the size (in bytes) of upstream
	// responses accepted by the proxy. Responses larger than this are
	// rejected to protect the proxy from memory exhaustion. Zero
	// preserves fasthttp's default unlimited behavior.
	//
	// Optional. Default: 0
	MaxResponseBodySize int

	// KeepConnectionHeader keeps the "Connection" header when set to true.
	//
	// Note: even when KeepConnectionHeader is true, other RFC 7230 §6.1
	// hop-by-hop headers (Keep-Alive, Proxy-Authenticate,
	// Proxy-Authorization, TE, Trailer, Transfer-Encoding, Upgrade) are
	// still stripped. To preserve every hop-by-hop header, set
	// SecurityPolicy.KeepHopByHopHeaders.
	//
	// Optional. Default: false
	KeepConnectionHeader bool

	// Attempt to connect to both ipv4 and ipv6 host addresses if set to true.
	//
	// By default client connects only to ipv4 addresses, since unfortunately ipv6
	// remains broken in many networks worldwide :)
	//
	// Optional. Default: false
	DialDualStack bool
}

Config defines the config for middleware.

type SecurityPolicy added in v3.5.0

type SecurityPolicy struct {
	// AllowedSchemes restricts the URL schemes accepted as upstream
	// targets. Empty defaults to []string{schemeHTTP, schemeHTTPS}.
	AllowedSchemes []string

	// AllowPrivateIPs allows upstream hosts to resolve to loopback,
	// private (RFC 1918), link-local, multicast, unspecified, or CGNAT
	// (RFC 6598) addresses. SECURITY: enabling this exposes the proxy
	// to SSRF attacks against internal services such as cloud
	// metadata endpoints. Default: false.
	//
	// DNS-rebinding scope: when false, the resolved IP is re-validated at
	// dial time, not only up front, so a malicious resolver cannot swap a
	// public answer (seen during validation) for a private one at connect
	// time. Balancer installs a guarded Dial on each HostClient it builds;
	// the runtime helpers — Do, DoRedirects, DoTimeout, DoDeadline,
	// Forward, DomainForward, BalancerForward — install the same guard on
	// the shared/user-supplied *fasthttp.Client they dispatch through.
	//
	// The default client and clients registered via WithClient are guarded
	// before first use and are fully protected. A client passed as a
	// per-call variadic argument is guarded on first use, so any host it had
	// already dialed keeps a cached, pre-guard HostClient; register such a
	// client via WithClient (or hand the proxy a dedicated, unused client)
	// for the full guarantee. The only path with no guard at all is a custom
	// Balancer Config.Client (*fasthttp.LBClient): its underlying dialers
	// are the caller's responsibility.
	AllowPrivateIPs bool

	// AllowHTTPSDowngrade permits proxy.DoRedirects to follow redirects
	// from HTTPS upstreams to plaintext HTTP URLs. SECURITY: enabling
	// this can leak credentials or session cookies in plaintext.
	// Default: false.
	AllowHTTPSDowngrade bool

	// KeepHopByHopHeaders disables the RFC 7230 §6.1 hop-by-hop header
	// stripping applied to both the outbound request and the inbound
	// response. SECURITY: enabling this can enable request smuggling
	// and proxy-auth credential forwarding. Default: false.
	KeepHopByHopHeaders bool
}

SecurityPolicy controls runtime security restrictions applied to the proxy.Do, proxy.Forward, proxy.DoRedirects, proxy.DoTimeout, and proxy.DoDeadline runtime helpers as well as Balancer instances that do not supply their own policy via Config.SecurityPolicy.

func DefaultSecurityPolicy added in v3.5.0

func DefaultSecurityPolicy() SecurityPolicy

DefaultSecurityPolicy returns the secure-by-default proxy security policy. Callers can clone it, mutate selected fields, and pass it back via Config.SecurityPolicy or WithSecurityPolicy.

AllowedSchemes is a freshly allocated slice on every call: the field is exported, so returning the shared defaultAllowedSchemes backing array would let a caller doing e.g. policy.AllowedSchemes[0] = "file" silently weaken the package defaults and every policy that references them.

func WithSecurityPolicy added in v3.5.0

func WithSecurityPolicy(policy SecurityPolicy) SecurityPolicy

WithSecurityPolicy installs policy as the global default consulted by proxy.Do, proxy.Forward, proxy.DoRedirects, proxy.DoTimeout, and proxy.DoDeadline (and by Balancer instances that do not set Config.SecurityPolicy). It returns the previously installed policy so callers can restore it — useful in tests that need to relax the policy for a single scope.

Jump to

Keyboard shortcuts

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