Repository navigation
Conversation
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
| if err != nil { | ||
| return fmt.Errorf("private address allowlist: %w", err) | ||
| } | ||
| webhookOpts = append(webhookOpts, destwebhook.WithAddressGuard(&netguard.Guard{Allowlist: allowlist})) |
There was a problem hiding this comment.
@alexluong for the other destination types where the tenant gives us an HTTP endpoint, do we want the same rule? I think we probably should. From a quick look that's queue_url on SQS and endpoint on EventBridge, Kinesis and Pub/Sub.
RabbitMQ (server_url), Kafka (brokers) and Azure Service Bus (connection_string) also take a tenant-supplied host, so the same question applies there, even though they aren't HTTP.
There was a problem hiding this comment.
Yes, I think the same rule should cover them. I've renamed the switch to DESTINATIONS_BLOCK_PRIVATE_ADDRESSES so it isn't tied to webhooks, and I'll keep this PR to webhooks and follow up with the rest: SQS, EventBridge, Kinesis and Pub/Sub can reuse the same dialer check through their SDK's HTTP client, while RabbitMQ, Kafka and Service Bus need their own dialer hooks.
…VATE_ADDRESSES Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Docs for self hosting should really cover this internal network thing. Are we confident this is a definitive answer? Should we recommend to enable? Should we propose networking / node level firewall instead? |
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…stination-addresses # Conflicts: # internal/destregistry/providers/destwebhook/httphelper.go
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Destination URLs come from tenants, and Outpost stores the response body on each attempt. A tenant can point a webhook at the operator's internal network (cloud metadata endpoints, admin services, databases on private IPs) and read what comes back. This adds a switch that keeps webhooks on public addresses. Off by default, since many deployments deliver to services on their own network.
With
DESTINATIONS_BLOCK_PRIVATE_ADDRESSES=true, a webhook only connects to publicly routable addresses or to IPs and ranges listed inDESTINATIONS_PRIVATE_ADDRESS_ALLOWLIST. Create and update check the URL and reject it early. Without a forward proxy, the check also runs on the socket right before each connect, against the address actually being dialed, so a DNS answer that changes after creation (DNS rebinding) is still caught.internal/netguardpackage (standard library only): the IANA special-purpose address ranges, an allowlist of IPs/CIDRs,CheckURLfor a pre-flight check, and aDialContext(a standardnet.Dialer) whoseControlhook refuses any address that isn't allowed. Addresses embedded in IPv4-mapped, NAT64 and 6to4 IPv6 forms are judged by the IPv4 address inside.destregistry.HTTPClientConfiggets aGuardoption. Without a forward proxy, every connection goes through the guard, andHTTP_PROXY/HTTPS_PROXYare ignored (with a warning at startup when they are set). With a forward proxy, deliveries aren't checked: the proxy resolves and connects to the target, so it is the only place that can enforce this, and the config row says to make it refuse private addresses. Checking each request in Outpost would add a DNS lookup per delivery and could still be bypassed by rebinding.config.url must resolve to a public address), including when it doesn't resolve. A refused delivery is a failed attempt with codeaddress_not_allowed, retried like any other failure.Notes:
/0, host bits set) fails startup, also while blocking is off.Docs: an "Outbound Network Access" section on the self-hosting Deployment page (when to care, network egress rules, this switch), a note in the forward proxy guide, two config table rows.
Not in this PR: the same check for other destination types that take a tenant-supplied host (SQS, EventBridge, Kinesis, Pub/Sub, RabbitMQ, Kafka, Service Bus).
🤖 Generated with Claude Code