Documentation
¶
Overview ¶
Package egress guards outbound HTTP requests whose destination comes from tenant-controlled data, such as an alert connection's webhook URL. A Policy refuses loopback, private, link-local (including the 169.254.169.254 cloud metadata address), shared, unspecified, multicast and broadcast addresses, unless the operator allows a range explicitly.
The check runs on the address the dialer is about to connect to, after DNS resolution, not on the URL's host name. A name that resolves to a public address when validated and to an internal one when used (DNS rebinding) is therefore still refused, and so is every redirect hop, because each hop is dialed through the same guard.
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ErrBlockedDestination = errors.New("egress: destination address is not allowed")
ErrBlockedDestination is returned (wrapped) when a request would connect to an address the Policy refuses.
Functions ¶
This section is empty.
Types ¶
type Policy ¶
type Policy struct {
// contains filtered or unexported fields
}
Policy decides which destination addresses an outbound request may reach. The zero value is not usable; build one with NewPolicy.
func NewPolicy ¶
NewPolicy returns a Policy that refuses every non-public address except those inside allowedCIDRs. Each entry is a CIDR ("10.20.0.0/16") or a single address ("192.168.5.7"). An entry that parses as neither is an error, so a typo fails at startup instead of silently allowing nothing. IPv4-mapped entries are stored as IPv4 and zones are dropped, matching how Check sees the dialed address.
func (*Policy) Check ¶
Check returns nil when addr may be dialed and an error wrapping ErrBlockedDestination otherwise. IPv4-mapped, NAT64 and 6to4 addresses are checked as the IPv4 address they carry; a zone is ignored.
func (*Policy) Client ¶
Client returns an HTTP client whose every connection, redirects included, is checked against the Policy. It dials directly and ignores the proxy environment variables: through a proxy the dialed address would be the proxy's, and the real destination could not be checked. It follows at most maxRedirects redirects.
func (*Policy) ReopenedSensitive ¶
ReopenedSensitive names the loopback and metadata destinations the allow list lets through, so the operator can be warned that an allowed range is broader than it looks. Empty when none is.