netguard

package
v1.3.2 Latest Latest
Warning

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

Go to latest
Published: Oct 12, 2026 License: Apache-2.0 Imports: 9 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrEmptyHost: the host is empty or blank.
	ErrEmptyHost = errors.New("empty host")
	// ErrUnresolvable: the host name did not resolve to an address.
	ErrUnresolvable = errors.New("host name could not be resolved")
	// ErrHostNotAllowed: the host is, or resolves to, a blocked address
	// (see BlockedIP).
	ErrHostNotAllowed = errors.New("destination not allowed")
	// ErrInvalidURL: the URL does not parse.
	ErrInvalidURL = errors.New("invalid URL")
	// ErrURLScheme: the URL scheme is neither http nor https.
	ErrURLScheme = errors.New("URL scheme must be http or https")
	// ErrURLNoHost: the URL has no host.
	ErrURLNoHost = errors.New("URL has no host")
)

Errors of the pre-flight checks. Their texts are fixed: they never contain the checked host or URL, a resolved address or resolver details, so a caller may return them to the client that submitted the value.

View Source
var ErrBlockedAddress = errors.New("dial refused: address resolves to a blocked range")

ErrBlockedAddress is returned by the guarded dialer when a resolved address is blocked.

Functions

func BlockedIP

func BlockedIP(ip netip.Addr) bool

BlockedIP reports whether an outbound connection to ip must be refused to prevent SSRF: loopback, link-local (incl. the cloud metadata endpoint), multicast, and unspecified addresses are blocked. Private RFC-1918 ranges are intentionally allowed (legitimate private clusters live there).

func GuardedDialContext

func GuardedDialContext(base *net.Dialer) func(ctx context.Context, network, addr string) (net.Conn, error)

GuardedDialContext returns a DialContext that resolves the host, refuses the dial if ANY resolved address is blocked (matching the validation-time guard's all-addresses policy), and connects to the exact validated IPs in order to close the resolve->dial TOCTOU window (DNS rebinding) while preserving multi-address failover for HA hosts. base may be nil (a default dialer with a sane timeout is used).

After confirming that no resolved address is blocked, each IP is tried in the order returned by the resolver; the first successful connection is returned. If every IP fails, the last dial error is returned (wrapped). The hostname is never re-resolved between attempts so the TOCTOU guarantee is preserved.

func GuardedDialWith added in v1.3.0

func GuardedDialWith(
	resolve func(ctx context.Context, network, host string) ([]netip.Addr, error),
	dialOne func(ctx context.Context, network, addr string) (net.Conn, error),
) func(ctx context.Context, network, addr string) (net.Conn, error)

GuardedDialWith is GuardedDialContext with an injectable resolver and per-IP dial function. Tests in other packages use it to point a guarded client at a local fake broker: the resolver maps a test host to an allowed address and dialOne redirects that address. The SSRF rules still apply to every resolved address, so a blocked address is refused before dialOne runs.

func ValidateHost

func ValidateHost(host string) error

ValidateHost is HostValidator.Host for a single host, resolved with net.DefaultResolver.

func ValidateURL

func ValidateURL(raw string) error

ValidateURL is HostValidator.URL for a single URL, resolved with net.DefaultResolver.

Types

type BlockedAddressError added in v1.3.0

type BlockedAddressError struct {
	// Addr is the host:port the dial was asked for.
	Addr string
	// Host is the host part of Addr, as given (name or IP literal).
	Host string
	// IP is the first resolved address that is blocked, as resolved.
	IP netip.Addr
}

BlockedAddressError is the error the guarded dialer returns when a resolved address is blocked. It unwraps to ErrBlockedAddress, so errors.Is keeps working, and carries the refused dial target for callers that report it.

func (*BlockedAddressError) Error added in v1.3.0

func (e *BlockedAddressError) Error() string

Error keeps the text of the former wrapped ErrBlockedAddress byte for byte.

func (*BlockedAddressError) Unwrap added in v1.3.0

func (e *BlockedAddressError) Unwrap() error

Unwrap makes errors.Is(err, ErrBlockedAddress) true.

type HostValidator added in v1.3.0

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

HostValidator runs the pre-flight checks of ValidateHost and ValidateURL for one request. It keeps the result per host, so the definitions of a request that name the same host several times cost one lookup. It is safe for concurrent use; checks run one at a time.

These checks turn obviously unsafe destinations into a validation error before any connection is attempted. They are not the enforcement point: DNS can change between the check and the dial, so outbound connections must still go through GuardedDialContext.

func NewHostValidator added in v1.3.0

func NewHostValidator(lookup LookupFunc) *HostValidator

NewHostValidator returns a HostValidator that resolves host names with lookup, or with net.DefaultResolver when lookup is nil.

func (*HostValidator) Host added in v1.3.0

func (v *HostValidator) Host(ctx context.Context, host string) error

Host checks host, a "host" or "host:port". It returns ErrEmptyHost, ErrUnresolvable, ErrHostNotAllowed when the host is or resolves to any blocked address (see BlockedIP), or nil.

func (*HostValidator) URL added in v1.3.0

func (v *HostValidator) URL(ctx context.Context, raw string) error

URL parses raw, requires an http(s) scheme and checks its host with Host. It returns ErrInvalidURL, ErrURLScheme, ErrURLNoHost, an error of Host or nil.

type LookupFunc added in v1.3.0

type LookupFunc func(ctx context.Context, host string) ([]string, error)

LookupFunc resolves a host name to its addresses, like net.Resolver.LookupHost.

Jump to

Keyboard shortcuts

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