fermyon / spin

Spin is the open source developer tool for building and running serverless applications powered by WebAssembly.
https://developer.fermyon.com/spin
Apache License 2.0
5.19k stars 247 forks source link

DNS Resolution and `allowed_outbound_hosts` #2181

Open rylev opened 10 months ago

rylev commented 10 months ago

Status Quo

Currently DNS resolution through the wasi:sockets/ip-name-lookup interface is completely blocked in Spin. Obviously, we want to allow for DNS resolution in a way that aligns well with Spin's deny-by-default behavior.

Networking is currently controlled through the allowed_outbound_hosts key in the Spin.toml manifest. Usage of all IP addresses is completely blocked unless opted in through allowed_outbound_hosts. This can either be a specific IP address or a range of IPs through CIDR notation.

Many or even most users, however, are unlikely to care about specific IP addresses and will instead wish to allow based on domain name.

Proposal

The following is the proposed semantics for allowed_outbound_hosts's interaction with wasi:sockets/ip-name-lookup:

Basic usage

The obvious use case should just work. If a user allows a domain for the "*" scheme in their allowed_outbound_hosts config, than the DNS name can be looked up and whatever IP addresses are returned from that lookup are allowed. Once wasi:sockets/ip-name-lookup#resolve_addresses gets called again, the IP addresses previously returned are no longer permitted unless the name resolves again to the same address or unless those IP addresses are explicitly allowed in allowed_outbound_hosts.

For example: Imagine allowed_outbound_hosts = ["*://google.com:443"]. If "google.com" resolves to "201.0.1.1", traffic to "201.0.1.1:443" is allowed until wasi:sockets/ip-name-lookup#resolve_addresses gets called again and "google.com" resolves to something different than "201.0.1.1".

Question: will this call spurious failures in clients? Do some clients do DNS lookups and keep IP addresses around eve after they do another lookup?

DNS lookup fails unless permitted

DNS lookups to domain names that are not specifically allowed in allowed_outbound_hosts will always fail.

For example: Imagine this config: allowed_outbound_hosts = ["*://201.0.1.1:443"] . Any call to wasi:sockets/ip-name-lookup#resolve_addresses will fail since there are no domain names in allowed_outbound_hosts. Even a name that would resolve to that IP address is not permitted (i.e., the call to wasi:sockets/ip-name-lookup#resolve_addresses will short circuit before the actual DNS request is issued).

Subdomains

For now, domain lookups must be exact.

For example: Imagine allowed_outbound_hosts = ["*://google.com:443"]. Lookups to subdomains like "docs.google.com" will fail.

In the future, we can expand the allowed_outbound_hosts syntax to allow subdomain lookups.

Additional Drawbacks

This proposal has some additional drawbacks:

lann commented 10 months ago

Question: will this call spurious failures in clients? Do some clients do DNS lookups and keep IP addresses around eve after they do another lookup?

I can't think of an obvious reason that a client would want to do this (without being broken).

lann commented 10 months ago

Users have no control over the usage of IPv4 vs IPv6

They could still resolve a domain manually and then pick one of its resolved addresses to connect to directly right?

calebschoepp commented 10 months ago

Users who want to interact with localhost will have to allow both ://localhost: and ://127.0.0.1: if they want either the IP address or the domain name to be used

We could consider putting this in our templates if we think it would be a big stumbling block for users.