1- use std:: { error:: Error , net :: IpAddr , sync:: Arc } ;
1+ use std:: { error:: Error , sync:: Arc } ;
22
33use anyhow:: Context ;
44use http:: { header:: HOST , Request } ;
55use http_body_util:: BodyExt ;
6- use ip_network :: IpNetwork ;
7- use rustls :: ClientConfig ;
8- use spin_factor_outbound_networking :: { ComponentTlsConfigs , OutboundAllowedHosts } ;
6+ use spin_factor_outbound_networking :: {
7+ BlockedNetworks , ComponentTlsClientConfigs , OutboundAllowedHosts , TlsClientConfig ,
8+ } ;
99use spin_factors:: { wasmtime:: component:: ResourceTable , RuntimeFactorsInstanceState } ;
1010use tokio:: { net:: TcpStream , time:: timeout} ;
1111use tracing:: { field:: Empty , instrument, Instrument } ;
@@ -97,7 +97,7 @@ impl WasiHttpView for WasiHttpImplInner<'_> {
9797 self . state . component_tls_configs . clone ( ) ,
9898 self . state . request_interceptor . clone ( ) ,
9999 self . state . self_request_origin . clone ( ) ,
100- self . state . allow_private_ips ,
100+ self . state . blocked_networks . clone ( ) ,
101101 )
102102 . in_current_span ( ) ,
103103 ) ,
@@ -109,10 +109,10 @@ async fn send_request_impl(
109109 mut request : Request < wasmtime_wasi_http:: body:: HyperOutgoingBody > ,
110110 mut config : wasmtime_wasi_http:: types:: OutgoingRequestConfig ,
111111 outbound_allowed_hosts : OutboundAllowedHosts ,
112- component_tls_configs : ComponentTlsConfigs ,
112+ component_tls_configs : ComponentTlsClientConfigs ,
113113 request_interceptor : Option < Arc < dyn OutboundHttpInterceptor > > ,
114114 self_request_origin : Option < SelfRequestOrigin > ,
115- allow_private_ips : bool ,
115+ blocked_networks : BlockedNetworks ,
116116) -> anyhow:: Result < Result < IncomingResponse , ErrorCode > > {
117117 // wasmtime-wasi-http fills in scheme and authority for relative URLs
118118 // (e.g. https://:443/<path>), which makes them hard to reason about.
@@ -196,7 +196,7 @@ async fn send_request_impl(
196196 span. record ( "server.port" , port. as_u16 ( ) ) ;
197197 }
198198
199- Ok ( send_request_handler ( request, config, tls_client_config, allow_private_ips ) . await )
199+ Ok ( send_request_handler ( request, config, tls_client_config, blocked_networks ) . await )
200200}
201201
202202/// This is a fork of wasmtime_wasi_http::default_send_request_handler function
@@ -210,8 +210,8 @@ async fn send_request_handler(
210210 first_byte_timeout,
211211 between_bytes_timeout,
212212 } : wasmtime_wasi_http:: types:: OutgoingRequestConfig ,
213- tls_client_config : Arc < ClientConfig > ,
214- allow_private_ips : bool ,
213+ tls_client_config : TlsClientConfig ,
214+ blocked_networks : BlockedNetworks ,
215215) -> Result < wasmtime_wasi_http:: types:: IncomingResponse , ErrorCode > {
216216 let authority_str = if let Some ( authority) = request. uri ( ) . authority ( ) {
217217 if authority. port ( ) . is_some ( ) {
@@ -230,12 +230,15 @@ async fn send_request_handler(
230230 . map_err ( |_| dns_error ( "address not available" . into ( ) , 0 ) ) ?
231231 . collect :: < Vec < _ > > ( ) ;
232232
233- // Potentially filter out private IPs
234- if !allow_private_ips && !socket_addrs. is_empty ( ) {
235- socket_addrs. retain ( |addr| !is_private_ip ( addr. ip ( ) ) ) ;
236- if socket_addrs. is_empty ( ) {
237- return Err ( ErrorCode :: DestinationIpProhibited ) ;
238- }
233+ // Remove blocked IPs
234+ let blocked_addrs = blocked_networks. remove_blocked ( & mut socket_addrs) ;
235+ if socket_addrs. is_empty ( ) && !blocked_addrs. is_empty ( ) {
236+ tracing:: error!(
237+ "error.type" = "destination_ip_prohibited" ,
238+ ?blocked_addrs,
239+ "all destination IP(s) prohibited by runtime config"
240+ ) ;
241+ return Err ( ErrorCode :: DestinationIpProhibited ) ;
239242 }
240243
241244 let tcp_stream = timeout ( connect_timeout, TcpStream :: connect ( socket_addrs. as_slice ( ) ) )
@@ -257,7 +260,7 @@ async fn send_request_handler(
257260 #[ cfg( not( any( target_arch = "riscv64" , target_arch = "s390x" ) ) ) ]
258261 {
259262 use rustls:: pki_types:: ServerName ;
260- let connector = tokio_rustls:: TlsConnector :: from ( tls_client_config) ;
263+ let connector = tokio_rustls:: TlsConnector :: from ( tls_client_config. inner ( ) ) ;
261264 let mut parts = authority_str. split ( ':' ) ;
262265 let host = parts. next ( ) . unwrap_or ( & authority_str) ;
263266 let domain = ServerName :: try_from ( host)
@@ -362,8 +365,3 @@ fn dns_error(rcode: String, info_code: u16) -> ErrorCode {
362365 info_code : Some ( info_code) ,
363366 } )
364367}
365-
366- /// Returns true if the IP is a private IP address.
367- fn is_private_ip ( ip : IpAddr ) -> bool {
368- !IpNetwork :: from ( ip) . is_global ( )
369- }
0 commit comments