Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

lann
Copy link
Collaborator

@lann lann commented Jun 2, 2025

Example:

[outbound_networking]
# 'private' is a keyword that blocks IPs that aren't "globally-routable"
block_networks = ["1.2.3.4/16", "private"]

A couple of separate commits with supporting changes:

  • Added tracing logging to factors tests: 8f455ee
  • Removed rustls-pemfile crate in favor of rustls-pki-types which has the functionality we need with a slightly nicer API and is already a dependency for other reasons: a4c2219

Which still leaves a pretty hefty final commit, including some not-entirely-related refactoring (sorry):

  • Added BlockedNetworks runtime config to OutboundNetworkingFactor
    • Replaced OutboundHttpFactor's allow_private_ips config with this new feature
    • Enforced in outbound_socket_addr_check too which covers wasi:sockets
    • Should be relatively easy to apply to other factors as well
  • Overhauled OutboundNetworkingFactor's runtime config code; this should have been a separate PR but by the time I noticed it was very tangled up with the new feature
    • Split a large chunk of the TLS client config code out of runtime config where it was actually representing instance state; this is large diffs between runtime_config.rs and tls.rs. There is a lot of renaming and fussing with structs here but overall the behavior shouldn't have changed significantly.
  • Replaced some usage of ipnet crate with similar ip_network; we already had dependencies on both, they cover mostly the same ground, and ip_network has a bit more functionality

@lann lann force-pushed the block-networks branch from 929081d to 0dfa8ac Compare June 2, 2025 22:49
This gives more output when debugging test failures.

Signed-off-by: Lann Martin <[email protected]>
@lann lann force-pushed the block-networks branch 2 times, most recently from fb76b61 to ee902ca Compare June 3, 2025 13:16
@lann lann marked this pull request as ready for review June 3, 2025 13:21
@lann lann requested review from rylev and itowlson June 3, 2025 13:21
lann added 2 commits June 3, 2025 15:12
This functionality is available from the more common rustls-pki-types
crate which is already a depedency for other reasons.

Signed-off-by: Lann Martin <[email protected]>
This allows a host to block outbound connections by CIDR mask or with
the 'private' keyword which blocks non-publicly-routable IPs.

Signed-off-by: Lann Martin <[email protected]>
@lann lann force-pushed the block-networks branch from 6e16bd1 to 94ecf44 Compare June 3, 2025 19:12
@lann lann requested a review from fibonacci1729 June 3, 2025 19:28
Copy link
Collaborator

@rylev rylev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The implementation mostly looks good - just one major question I left in a comment. Overall, I'm super on board with the internal changes.

I'm more unsure about the exact UX of how we're extending the runtime config yaml. I don't have specific feedback, and so I'm not going to block. My FUD mainly extends from the fact that the yaml changes are permanent and must be kept into purpiutiy. I think I'd personally have felt much more comfortable if the internal changes were landed separately from the YAML changes. I understand why they're bundled, but they don't have to be, and I think I'd like to be a bit more careful about introducing changes that directly impact users.

@lann
Copy link
Collaborator Author

lann commented Jun 4, 2025

I'm more unsure about the exact UX of how we're extending the runtime config yaml.

The only user-visible changes should be the new [outbound_networking] / blocked_networks config. If that is what you are unsure about then we should definitely discuss before merging.

Comment on lines +53 to +58
// Convert IPv4-compatible IPv6 addresses to IPv4 and check again to prevent bypass
if let IpAddr::V6(ipv6) = ip_addr {
if let Some(ipv4_compat) = ipv6.to_ipv4() {
return self.is_blocked(&IpAddr::V4(ipv4_compat));
}
}
Copy link
Collaborator Author

@lann lann Jun 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I noticed this issue when adding the link to ip_network::Ipv6Network::is_global to the docs above; annoyingly, its behavior is subtly different from the unstable std::net::Ipv6Addr::is_global though that does lead to an arguably better solution here.

@rylev
Copy link
Collaborator

rylev commented Jun 5, 2025

The only user-visible changes should be the new [outbound_networking] / blocked_networks config. If that is what you are unsure about then we should definitely discuss before merging.

Indeed. My concern is more of a vibe than anything (which is why I've approved this PR and don't want to block). I don't have concrete suggestions - I'm simply unsure about the API and unsure about introducing such additions to the Spin API in a PR. For example, some random questions I have:

  • Should we expose this as blocking networks (as you've done here) or allowing networks (mirroring the API we expose in spin.toml)?
    • I think I agree with your choice of blocking vs. allowing (as typically operators care more about explicitly restricting rather than explicitly allowing).
  • Is the private keyword, the right way to block the use of all non-globally-routable networks?
    • It seems fine so 🤷

I guess in general, I'm wondering if the user facing changes should be introduced through a SIP instead of a PR. It's a small feature so I understand why that wasn't done initially, but it feels like anything that impacts the public API of Spin should be discussed in a SIP.

@lann
Copy link
Collaborator Author

lann commented Jun 5, 2025

  • Should we expose this as blocking networks (as you've done here) or allowing networks (mirroring the API we expose in spin.toml)?

    * I think I agree with your choice of blocking vs. allowing (as typically operators care more about explicitly restricting rather than explicitly allowing).
    

I thought about this a little. It seems somewhat unlikely that an operator that wanted to lock down the network that much wouldn't also have complete control over the apps (and therefor allowed_outbound_hosts), but if there is demand for that it should be quite easy to add an allow_hosts field which is either mutually exclusive with block_hosts or does something slightly more fancy to merge the two.

@lann
Copy link
Collaborator Author

lann commented Jun 5, 2025

* Is the `private` keyword, the right way to block the use of all non-globally-routable networks?
  
  * It seems fine so 🤷

You could translate private into a large set of explicit CIDRs. It's really just a convenience for what (to me) seems like the most likely use-case for this feature: "don't let apps access services behind the firewall".

@lann
Copy link
Collaborator Author

lann commented Jun 5, 2025

I guess in general, I'm wondering if the user facing changes should be introduced through a SIP instead of a PR.

First off, this is definitely a reasonable question to ask.

it feels like anything that impacts the public API of Spin should be discussed in a SIP.

Depending on your interpretation, "anything that impacts the public API" could apply to a lot of things that we haven't covered with SIPs before, but we can certainly adjust our attitudes / policies / guidance on that if we want. I guess it didn't even occur to me to do a SIP here in part because we didn't do one for the even larger [[client_tls]] feature it lives right next to. 🤷

More broadly:

SIPs are documented as being for "major work items" which...leaves a little room for interpretation 😅 but I think reflects that one of the goals is to avoid putting in "too much" work into an implementation before getting feedback on the design. This is important both to avoid wasting contributor's time and to avoid putting too much pressure on reviewers to accept a design just because there is a lot of code already written for it. On the flip side, there is overhead in the SIP process and every extra bit of friction incrementally raises the bar for contribution - even for maintainers!

@rylev
Copy link
Collaborator

rylev commented Jun 5, 2025

@lann it occurs to me that perhaps one reason I'm nervous about this is that runtime-config.yaml isn't currently versioned. Perhaps if it were, I'd be less worried?

@lann
Copy link
Collaborator Author

lann commented Jun 5, 2025

I prefer to think of it as "version 0"; you always get that one freebie before you have to start writing down explicit schema versions. 🙂

@lann lann merged commit 960490d into main Jun 5, 2025
17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants