1+ use std:: net:: SocketAddr ;
2+
13use anyhow:: Result ;
4+ use redis:: io:: AsyncDNSResolver ;
5+ use redis:: AsyncConnectionConfig ;
26use redis:: { aio:: MultiplexedConnection , AsyncCommands , FromRedisValue , Value } ;
37use spin_core:: wasmtime:: component:: Resource ;
48use spin_factor_outbound_networking:: config:: allowed_hosts:: OutboundAllowedHosts ;
9+ use spin_factor_outbound_networking:: config:: blocked_networks:: BlockedNetworks ;
510use spin_world:: v1:: { redis as v1, redis_types} ;
611use spin_world:: v2:: redis:: {
712 self as v2, Connection as RedisConnection , Error , RedisParameter , RedisResult ,
@@ -11,6 +16,7 @@ use tracing::{instrument, Level};
1116
1217pub struct InstanceState {
1318 pub allowed_hosts : OutboundAllowedHosts ,
19+ pub blocked_networks : BlockedNetworks ,
1420 pub connections : spin_resource_table:: Table < MultiplexedConnection > ,
1521}
1622
@@ -23,9 +29,11 @@ impl InstanceState {
2329 & mut self ,
2430 address : String ,
2531 ) -> Result < Resource < RedisConnection > , Error > {
32+ let config = AsyncConnectionConfig :: new ( )
33+ . set_dns_resolver ( SpinResolver ( self . blocked_networks . clone ( ) ) ) ;
2634 let conn = redis:: Client :: open ( address. as_str ( ) )
2735 . map_err ( |_| Error :: InvalidAddress ) ?
28- . get_multiplexed_async_connection ( )
36+ . get_multiplexed_async_connection_with_config ( & config )
2937 . await
3038 . map_err ( other_error) ?;
3139 self . connections
@@ -365,3 +373,29 @@ impl FromRedisValue for RedisResults {
365373 Ok ( RedisResults ( values) )
366374 }
367375}
376+
377+ struct SpinResolver ( BlockedNetworks ) ;
378+
379+ impl AsyncDNSResolver for SpinResolver {
380+ fn resolve < ' a , ' b : ' a > (
381+ & ' a self ,
382+ host : & ' b str ,
383+ port : u16 ,
384+ ) -> redis:: RedisFuture < ' a , Box < dyn Iterator < Item = std:: net:: SocketAddr > + Send + ' a > > {
385+ Box :: pin ( async move {
386+ let mut addrs = tokio:: net:: lookup_host ( ( host, port) )
387+ . await ?
388+ . collect :: < Vec < _ > > ( ) ;
389+ // Remove blocked IPs
390+ let blocked_addrs = self . 0 . remove_blocked ( & mut addrs) ;
391+ if addrs. is_empty ( ) && !blocked_addrs. is_empty ( ) {
392+ tracing:: error!(
393+ "error.type" = "destination_ip_prohibited" ,
394+ ?blocked_addrs,
395+ "all destination IP(s) prohibited by runtime config"
396+ ) ;
397+ }
398+ Ok ( Box :: new ( addrs. into_iter ( ) ) as Box < dyn Iterator < Item = SocketAddr > + Send > )
399+ } )
400+ }
401+ }
0 commit comments