crusty_core/
resolver.rs

1use std::{
2	net::ToSocketAddrs,
3	task::{Context, Poll},
4	vec::IntoIter,
5};
6
7use hyper::{client::connect::dns::Name, service::Service};
8use ipnet::{Ipv4Net, Ipv6Net};
9use trust_dns_resolver::{
10	config::{ResolverConfig, ResolverOpts},
11	TokioAsyncResolver,
12};
13
14use crate::_prelude::*;
15
16pub trait Resolver: Send + Sync + Debug + 'static {
17	fn resolve(&self, host: &str) -> PinnedFut<Result<IntoIter<SocketAddr>, io::Error>>;
18}
19
20#[derive(Clone, Debug)]
21pub struct AsyncStaticResolver {
22	addrs: Vec<SocketAddr>,
23}
24
25#[derive(Clone, Debug)]
26pub struct AsyncTrustDnsResolver {
27	resolver:         Arc<TokioAsyncResolver>,
28	net_v4_blacklist: Arc<Vec<Ipv4Net>>,
29	net_v6_blacklist: Arc<Vec<Ipv6Net>>,
30}
31
32impl AsyncTrustDnsResolver {
33	pub fn new(config: ResolverConfig, options: ResolverOpts) -> Result<Self, io::Error> {
34		let resolver = Arc::new(TokioAsyncResolver::tokio(config, options)?);
35
36		Ok(Self { resolver, net_v4_blacklist: Arc::new(vec![]), net_v6_blacklist: Arc::new(vec![]) })
37	}
38
39	pub fn with_net_v4_blacklist(&mut self, blacklist: Vec<Ipv4Net>) {
40		self.net_v4_blacklist = Arc::new(blacklist);
41	}
42
43	pub fn with_net_v6_blacklist(&mut self, blacklist: Vec<Ipv6Net>) {
44		self.net_v6_blacklist = Arc::new(blacklist);
45	}
46}
47
48impl AsyncStaticResolver {
49	pub fn new(addrs: Vec<SocketAddr>) -> Self {
50		Self { addrs }
51	}
52}
53
54impl Resolver for AsyncTrustDnsResolver {
55	fn resolve(&self, name: &str) -> PinnedFut<Result<IntoIter<SocketAddr>, io::Error>> {
56		let resolver = self.clone();
57
58		let name = name.to_string();
59		Box::pin(async move {
60			let r = resolver
61				.resolver
62				.lookup_ip(name.as_str())
63				.await?
64				.iter()
65				.map(|addr| (addr, 0_u16).to_socket_addrs())
66				.try_fold(Vec::new(), |mut acc, s_addr| {
67					acc.extend(s_addr?);
68					Ok::<_, io::Error>(acc)
69				})?
70				.into_iter();
71
72			let mut err = None;
73			let mut out_addrs: Vec<SocketAddr> = vec![];
74			for addr in r.into_iter() {
75				match addr {
76					SocketAddr::V4(addr) => {
77						for blacklisted_net in resolver.net_v4_blacklist.iter() {
78							if blacklisted_net.contains(addr.ip()) {
79								err = Some(io::Error::new(
80									io::ErrorKind::Interrupted,
81									format!("resolved IPv4 {} is blacklisted", addr.ip().to_string().as_str()),
82								));
83								continue
84							}
85						}
86					}
87					SocketAddr::V6(addr) => {
88						for blacklisted_net in resolver.net_v6_blacklist.iter() {
89							if blacklisted_net.contains(addr.ip()) {
90								err = Some(io::Error::new(
91									io::ErrorKind::Interrupted,
92									format!("resolved IPv6 {} is blacklisted", addr.ip().to_string().as_str()),
93								));
94								continue
95							}
96						}
97					}
98				}
99				out_addrs.push(addr);
100			}
101
102			if out_addrs.is_empty() {
103				if let Some(err) = err {
104					return Err(err)
105				}
106			}
107
108			Ok(out_addrs.into_iter())
109		})
110	}
111}
112
113impl Resolver for AsyncStaticResolver {
114	fn resolve(&self, _name: &str) -> PinnedFut<Result<IntoIter<SocketAddr>, io::Error>> {
115		let resolver = self.clone();
116
117		Box::pin(async move { Ok(resolver.addrs.into_iter()) })
118	}
119}
120
121#[derive(Clone)]
122pub(crate) struct Adaptor {
123	resolver: Arc<Box<dyn Resolver>>,
124}
125
126impl Adaptor {
127	pub fn new(resolver: Arc<Box<dyn Resolver>>) -> Self {
128		Self { resolver }
129	}
130}
131
132impl Service<Name> for Adaptor {
133	type Error = io::Error;
134	type Future = PinnedFut<Result<Self::Response, Self::Error>>;
135	type Response = std::vec::IntoIter<SocketAddr>;
136
137	fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
138		Poll::Ready(Ok(()))
139	}
140
141	fn call(&mut self, name: Name) -> Self::Future {
142		let adaptor = self.clone();
143		Box::pin(async move { adaptor.resolver.resolve(name.as_str()).await })
144	}
145}
146
147lazy_static! {
148	pub static ref RESERVED_V4_SUBNETS: Vec<Ipv4Net> = {
149		vec![
150			// see https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml
151			"0.0.0.0/8",
152			"10.0.0.0/8",
153			"100.64.0.0/10",
154			"127.0.0.0/8",
155			"169.254.0.0/16",
156			"172.16.0.0/12",
157			"192.0.0.0/24",
158			"192.0.2.0/24",
159			"192.88.99.0/24",
160			"192.168.0.0/16",
161			"198.18.0.0/15",
162			"198.51.100.0/24",
163			"203.0.113.0/24",
164			"224.0.0.0/4",
165			"233.252.0.0/24",
166			"240.0.0.0/4",
167			"255.255.255.255/32",
168		].iter().map(|net|net.parse().unwrap()).collect::<Vec<_>>()
169	};
170
171	pub static ref RESERVED_V6_SUBNETS: Vec<Ipv6Net> = {
172		vec![
173			// see https://www.iana.org/assignments/iana-ipv6-special-registry/iana-ipv6-special-registry.xhtml
174			"::1/128",
175			"::/128",
176			"::ffff:0:0/96",
177			"64:ff9b::/96",
178			"64:ff9b:1::/48",
179			"100::/64",
180			"2001::/23",
181			"2001::/32",
182			"2001:1::1/128",
183			"2001:1::2/128",
184			"2001:2::/48",
185			"2001:3::/32",
186			"2001:4:112::/48",
187			"2001:10::/28",
188			"2001:20::/28",
189			"2001:db8::/32",
190			"2002::/16",
191			"2620:4f:8000::/48",
192			"fc00::/7",
193			"fe80::/10",
194		].iter().map(|net|net.parse().unwrap()).collect::<Vec<_>>()
195	};
196}