1use anyhow::{Context as _, Result, ensure};
44use std::collections::HashMap;
45use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr};
46use std::str::FromStr;
47use std::sync::LazyLock;
48use tokio::net::lookup_host;
49use tokio::time::timeout;
50
51use super::load_connection_timestamp;
52use crate::context::Context;
53use crate::log::warn;
54use crate::tools::time;
55
56async fn update_cache(context: &Context, host: &str, addr: &str, now: i64) -> Result<()> {
59 context
60 .sql
61 .execute(
62 "INSERT INTO dns_cache
63 (hostname, address, timestamp)
64 VALUES (?, ?, ?)
65 ON CONFLICT (hostname, address)
66 DO UPDATE SET timestamp=excluded.timestamp",
67 (host, addr, now),
68 )
69 .await?;
70 Ok(())
71}
72
73pub(crate) async fn prune_dns_cache(context: &Context) -> Result<()> {
74 let now = time();
75 context
76 .sql
77 .execute(
78 "DELETE FROM dns_cache
79 WHERE ? > timestamp + ?",
80 (now, super::CACHE_TTL),
81 )
82 .await?;
83 Ok(())
84}
85
86static LOOKUP_HOST_CACHE: LazyLock<parking_lot::RwLock<HashMap<String, Vec<IpAddr>>>> =
95 LazyLock::new(Default::default);
96
97async fn lookup_ips(host: impl tokio::net::ToSocketAddrs) -> Result<impl Iterator<Item = IpAddr>> {
99 Ok(lookup_host(host)
100 .await
101 .context("DNS lookup failure")?
102 .map(|addr| addr.ip()))
103}
104
105async fn lookup_host_with_memory_cache(
106 context: &Context,
107 hostname: &str,
108 port: u16,
109) -> Result<Vec<IpAddr>> {
110 let stale_result = {
111 let rwlock_read_guard = LOOKUP_HOST_CACHE.read();
112 rwlock_read_guard.get(hostname).cloned()
113 };
114 if let Some(stale_result) = stale_result {
115 {
117 let context = context.clone();
118 let hostname = hostname.to_string();
119 tokio::spawn(async move {
120 match lookup_ips((hostname.clone(), port)).await {
121 Ok(res) => {
122 LOOKUP_HOST_CACHE.write().insert(hostname, res.collect());
123 }
124 Err(err) => {
125 warn!(
126 context,
127 "Failed to revalidate results for {hostname:?}: {err:#}."
128 );
129 }
130 }
131 });
132 }
133
134 info!(
135 context,
136 "Using memory-cached DNS resolution for {hostname}."
137 );
138 Ok(stale_result)
139 } else {
140 info!(
141 context,
142 "No memory-cached DNS resolution for {hostname} available, waiting for the resolver."
143 );
144 let res: Vec<IpAddr> = lookup_ips((hostname, port)).await?.collect();
145
146 LOOKUP_HOST_CACHE
151 .write()
152 .insert(hostname.to_string(), res.clone());
153 Ok(res)
154 }
155}
156
157async fn lookup_host_and_update_cache(
160 context: &Context,
161 hostname: &str,
162 port: u16,
163 now: i64,
164) -> Result<Vec<SocketAddr>> {
165 let res: Vec<IpAddr> = timeout(
166 super::TIMEOUT,
167 lookup_host_with_memory_cache(context, hostname, port),
168 )
169 .await
170 .context("DNS lookup timeout")?
171 .context("DNS lookup with memory cache failure")?;
172
173 for ip in &res {
174 let ip_string = ip.to_string();
175 if ip_string == hostname {
176 continue;
178 }
179
180 info!(context, "Resolved {hostname} into {ip}.");
181
182 update_cache(context, hostname, &ip_string, now).await?;
184 }
185
186 let res = res
187 .into_iter()
188 .map(|ip| SocketAddr::new(ip, port))
189 .collect();
190 Ok(res)
191}
192
193pub(crate) async fn update_connect_timestamp(
208 context: &Context,
209 host: &str,
210 address: &str,
211) -> Result<()> {
212 if host == address {
213 return Ok(());
214 }
215
216 context
217 .sql
218 .execute(
219 "INSERT INTO dns_cache (hostname, address, timestamp)
220 VALUES (?, ?, ?)
221 ON CONFLICT (hostname, address)
222 DO UPDATE SET timestamp=excluded.timestamp",
223 (host, address, time()),
224 )
225 .await?;
226 Ok(())
227}
228
229static DNS_PRELOAD: LazyLock<HashMap<&'static str, Vec<IpAddr>>> = LazyLock::new(|| {
231 HashMap::from([
232 (
233 "imap.163.com",
234 vec![
235 IpAddr::V4(Ipv4Addr::new(111, 124, 203, 45)),
236 IpAddr::V4(Ipv4Addr::new(111, 124, 203, 50)),
237 ],
238 ),
239 (
240 "smtp.163.com",
241 vec![IpAddr::V4(Ipv4Addr::new(103, 129, 252, 45))],
242 ),
243 (
244 "newyear.aktivix.org",
245 vec![IpAddr::V4(Ipv4Addr::new(209, 51, 180, 245))],
246 ),
247 (
248 "smtp.aliyun.com",
249 vec![IpAddr::V4(Ipv4Addr::new(47, 246, 136, 232))],
250 ),
251 (
252 "imap.aliyun.com",
253 vec![
254 IpAddr::V4(Ipv4Addr::new(59, 82, 43, 123)),
255 IpAddr::V4(Ipv4Addr::new(59, 82, 9, 176)),
256 ],
257 ),
258 (
259 "imap.aol.com",
260 vec![
261 IpAddr::V4(Ipv4Addr::new(212, 82, 101, 33)),
262 IpAddr::V4(Ipv4Addr::new(87, 248, 98, 69)),
263 ],
264 ),
265 (
266 "imap.arcor.de",
267 vec![
268 IpAddr::V4(Ipv4Addr::new(178, 15, 69, 210)),
269 IpAddr::V4(Ipv4Addr::new(151, 189, 176, 206)),
270 ],
271 ),
272 (
273 "smtp.aol.com",
274 vec![IpAddr::V4(Ipv4Addr::new(87, 248, 97, 31))],
275 ),
276 (
277 "mail.arcor.de",
278 vec![
279 IpAddr::V4(Ipv4Addr::new(151, 189, 176, 206)),
280 IpAddr::V4(Ipv4Addr::new(178, 15, 69, 206)),
281 ],
282 ),
283 (
284 "mail.autistici.org",
285 vec![
286 IpAddr::V4(Ipv4Addr::new(93, 190, 126, 19)),
287 IpAddr::V4(Ipv4Addr::new(185, 218, 207, 228)),
288 IpAddr::V4(Ipv4Addr::new(198, 167, 222, 108)),
289 ],
290 ),
291 (
292 "smtp.autistici.org",
293 vec![
294 IpAddr::V4(Ipv4Addr::new(82, 94, 249, 234)),
295 IpAddr::V4(Ipv4Addr::new(93, 190, 126, 19)),
296 IpAddr::V4(Ipv4Addr::new(198, 167, 222, 108)),
297 ],
298 ),
299 (
300 "imaps.bluewin.ch",
301 vec![
302 IpAddr::V4(Ipv4Addr::new(16, 62, 253, 42)),
303 IpAddr::V4(Ipv4Addr::new(16, 63, 141, 244)),
304 IpAddr::V4(Ipv4Addr::new(16, 63, 146, 183)),
305 ],
306 ),
307 (
308 "smtpauths.bluewin.ch",
309 vec![
310 IpAddr::V4(Ipv4Addr::new(16, 62, 176, 232)),
311 IpAddr::V4(Ipv4Addr::new(16, 62, 15, 25)),
312 IpAddr::V4(Ipv4Addr::new(16, 63, 183, 216)),
313 ],
314 ),
315 (
316 "mail.buzon.uy",
317 vec![IpAddr::V4(Ipv4Addr::new(200, 40, 115, 74))],
318 ),
319 (
320 "daleth.cafe",
321 vec![IpAddr::V4(Ipv4Addr::new(37, 27, 6, 204))],
322 ),
323 (
324 "disroot.org",
325 vec![IpAddr::V4(Ipv4Addr::new(178, 21, 23, 139))],
326 ),
327 (
328 "imap.fastmail.com",
329 vec![
330 IpAddr::V4(Ipv4Addr::new(103, 168, 172, 43)),
331 IpAddr::V4(Ipv4Addr::new(103, 168, 172, 58)),
332 ],
333 ),
334 (
335 "smtp.fastmail.com",
336 vec![
337 IpAddr::V4(Ipv4Addr::new(103, 168, 172, 45)),
338 IpAddr::V4(Ipv4Addr::new(103, 168, 172, 60)),
339 ],
340 ),
341 (
342 "imap.gmail.com",
343 vec![
344 IpAddr::V4(Ipv4Addr::new(142, 250, 110, 108)),
345 IpAddr::V4(Ipv4Addr::new(142, 250, 110, 109)),
346 IpAddr::V4(Ipv4Addr::new(66, 102, 1, 108)),
347 IpAddr::V4(Ipv4Addr::new(66, 102, 1, 109)),
348 IpAddr::V6(Ipv6Addr::new(0x2a00, 0x1450, 0x400c, 0xc1f, 0, 0, 0, 0x6c)),
349 IpAddr::V6(Ipv6Addr::new(0x2a00, 0x1450, 0x400c, 0xc1f, 0, 0, 0, 0x6d)),
350 ],
351 ),
352 (
353 "mail.ecloud.global",
354 vec![IpAddr::V4(Ipv4Addr::new(95, 217, 246, 96))],
355 ),
356 (
357 "mail.ende.in.net",
358 vec![IpAddr::V4(Ipv4Addr::new(95, 217, 5, 72))],
359 ),
360 (
361 "smtp.gmail.com",
362 vec![
363 IpAddr::V4(Ipv4Addr::new(142, 250, 110, 109)),
364 IpAddr::V6(Ipv6Addr::new(0x2a00, 0x1450, 0x4013, 0xc04, 0, 0, 0, 0x6c)),
365 ],
366 ),
367 (
368 "mail.gmx.net",
369 vec![
370 IpAddr::V4(Ipv4Addr::new(212, 227, 17, 190)),
371 IpAddr::V4(Ipv4Addr::new(212, 227, 17, 168)),
372 ],
373 ),
374 (
375 "imap.gmx.net",
376 vec![
377 IpAddr::V4(Ipv4Addr::new(212, 227, 17, 170)),
378 IpAddr::V4(Ipv4Addr::new(212, 227, 17, 186)),
379 ],
380 ),
381 (
382 "mail.sangham.net",
383 vec![
384 IpAddr::V4(Ipv4Addr::new(159, 69, 186, 85)),
385 IpAddr::V6(Ipv6Addr::new(0x2a01, 0x4f8, 0xc17, 0x798c, 0, 0, 0, 1)),
386 ],
387 ),
388 (
389 "imap.mail.de",
390 vec![IpAddr::V4(Ipv4Addr::new(62, 201, 172, 16))],
391 ),
392 (
393 "smtp.mailbox.org",
394 vec![IpAddr::V4(Ipv4Addr::new(185, 97, 174, 196))],
395 ),
396 (
397 "imap.mailbox.org",
398 vec![IpAddr::V4(Ipv4Addr::new(185, 97, 174, 199))],
399 ),
400 (
401 "imap.naver.com",
402 vec![IpAddr::V4(Ipv4Addr::new(125, 209, 233, 34))],
403 ),
404 (
405 "imap.ouvaton.coop",
406 vec![IpAddr::V4(Ipv4Addr::new(194, 36, 166, 20))],
407 ),
408 (
409 "imap.purelymail.com",
410 vec![IpAddr::V4(Ipv4Addr::new(18, 204, 123, 63))],
411 ),
412 (
413 "mail.systemausfall.org",
414 vec![
415 IpAddr::V4(Ipv4Addr::new(51, 75, 71, 249)),
416 IpAddr::V4(Ipv4Addr::new(80, 153, 252, 42)),
417 ],
418 ),
419 (
420 "mail.systemli.org",
421 vec![IpAddr::V4(Ipv4Addr::new(93, 190, 126, 36))],
422 ),
423 ("testrun.org", vec![IpAddr::V4(Ipv4Addr::new(5, 1, 76, 52))]),
424 (
425 "nine.testrun.org",
426 vec![
427 IpAddr::V4(Ipv4Addr::new(128, 140, 126, 197)),
428 IpAddr::V4(Ipv4Addr::new(216, 144, 228, 100)),
429 IpAddr::V4(Ipv4Addr::new(77, 42, 49, 41)),
430 IpAddr::V6(Ipv6Addr::new(
431 0x2001, 0x41d0, 0x701, 0x1100, 0, 0, 0, 0x8ab1,
432 )),
433 IpAddr::V6(Ipv6Addr::new(0x2a01, 0x4f9, 0xfff1, 0x59, 0, 0, 0, 1)),
434 ],
435 ),
436 (
437 "secureimap.t-online.de",
438 vec![
439 IpAddr::V4(Ipv4Addr::new(194, 25, 134, 114)),
440 IpAddr::V4(Ipv4Addr::new(194, 25, 134, 115)),
441 IpAddr::V4(Ipv4Addr::new(194, 25, 134, 50)),
442 IpAddr::V4(Ipv4Addr::new(194, 25, 134, 51)),
443 ],
444 ),
445 (
446 "securesmtp.t-online.de",
447 vec![
448 IpAddr::V4(Ipv4Addr::new(194, 25, 134, 46)),
449 IpAddr::V4(Ipv4Addr::new(194, 25, 134, 110)),
450 ],
451 ),
452 (
453 "mail.riseup.net",
454 vec![
455 IpAddr::V4(Ipv4Addr::new(198, 252, 153, 171)),
456 IpAddr::V4(Ipv4Addr::new(198, 252, 153, 170)),
457 ],
458 ),
459 (
460 "pimap.schulon.org",
461 vec![IpAddr::V4(Ipv4Addr::new(194, 77, 246, 20))],
462 ),
463 (
464 "imap.tiscali.it",
465 vec![IpAddr::V4(Ipv4Addr::new(213, 205, 33, 10))],
466 ),
467 (
468 "smtp.tiscali.it",
469 vec![IpAddr::V4(Ipv4Addr::new(213, 205, 33, 13))],
470 ),
471 (
472 "imap.ukr.net",
473 vec![IpAddr::V4(Ipv4Addr::new(212, 42, 75, 240))],
474 ),
475 (
476 "smtp.ukr.net",
477 vec![IpAddr::V4(Ipv4Addr::new(212, 42, 75, 250))],
478 ),
479 (
480 "imap.web.de",
481 vec![
482 IpAddr::V4(Ipv4Addr::new(212, 227, 17, 162)),
483 IpAddr::V4(Ipv4Addr::new(212, 227, 17, 178)),
484 ],
485 ),
486 (
487 "imap.ziggo.nl",
488 vec![IpAddr::V4(Ipv4Addr::new(84, 116, 6, 3))],
489 ),
490 (
491 "imap.zoho.eu",
492 vec![
493 IpAddr::V4(Ipv4Addr::new(185, 230, 214, 25)),
494 IpAddr::V4(Ipv4Addr::new(185, 230, 214, 206)),
495 ],
496 ),
497 (
498 "mail.infomaniak.com",
499 vec![
500 IpAddr::V4(Ipv4Addr::new(83, 166, 143, 44)),
501 IpAddr::V4(Ipv4Addr::new(83, 166, 143, 45)),
502 ],
503 ),
504 (
505 "mail.mymagenta.at",
506 vec![IpAddr::V4(Ipv4Addr::new(80, 109, 253, 241))],
507 ),
508 (
509 "mail.nubo.coop",
510 vec![IpAddr::V4(Ipv4Addr::new(79, 99, 201, 10))],
511 ),
512 (
513 "mx.freenet.de",
514 vec![
515 IpAddr::V4(Ipv4Addr::new(194, 97, 208, 36)),
516 IpAddr::V4(Ipv4Addr::new(194, 97, 208, 34)),
517 IpAddr::V4(Ipv4Addr::new(194, 97, 208, 35)),
518 IpAddr::V4(Ipv4Addr::new(194, 97, 208, 39)),
519 IpAddr::V4(Ipv4Addr::new(194, 97, 208, 37)),
520 IpAddr::V4(Ipv4Addr::new(194, 97, 208, 38)),
521 ],
522 ),
523 (
524 "posteo.de",
525 vec![
526 IpAddr::V4(Ipv4Addr::new(185, 67, 36, 168)),
527 IpAddr::V4(Ipv4Addr::new(185, 67, 36, 169)),
528 ],
529 ),
530 (
531 "psmtp.schulon.org",
532 vec![IpAddr::V4(Ipv4Addr::new(194, 77, 246, 20))],
533 ),
534 (
535 "smtp.mail.de",
536 vec![IpAddr::V4(Ipv4Addr::new(62, 201, 172, 21))],
537 ),
538 (
539 "smtp.mail.ru",
540 vec![
541 IpAddr::V4(Ipv4Addr::new(94, 100, 180, 160)),
542 IpAddr::V4(Ipv4Addr::new(217, 69, 139, 160)),
543 ],
544 ),
545 (
546 "imap.mail.yahoo.com",
547 vec![
548 IpAddr::V4(Ipv4Addr::new(87, 248, 103, 8)),
549 IpAddr::V4(Ipv4Addr::new(212, 82, 101, 24)),
550 ],
551 ),
552 (
553 "smtp.mail.yahoo.com",
554 vec![IpAddr::V4(Ipv4Addr::new(87, 248, 97, 36))],
555 ),
556 (
557 "imap.mailo.com",
558 vec![IpAddr::V4(Ipv4Addr::new(213, 182, 54, 20))],
559 ),
560 (
561 "imap.migadu.com",
562 vec![
563 IpAddr::V4(Ipv4Addr::new(51, 210, 3, 23)),
564 IpAddr::V4(Ipv4Addr::new(51, 210, 3, 20)),
565 ],
566 ),
567 (
568 "smtp.migadu.com",
569 vec![
570 IpAddr::V4(Ipv4Addr::new(37, 59, 57, 117)),
571 IpAddr::V4(Ipv4Addr::new(51, 255, 82, 75)),
572 ],
573 ),
574 (
575 "smtp.mailo.com",
576 vec![IpAddr::V4(Ipv4Addr::new(213, 182, 54, 20))],
577 ),
578 (
579 "smtp.naver.com",
580 vec![IpAddr::V4(Ipv4Addr::new(125, 209, 238, 155))],
581 ),
582 (
583 "smtp.ouvaton.coop",
584 vec![IpAddr::V4(Ipv4Addr::new(194, 36, 166, 20))],
585 ),
586 (
587 "smtp.purelymail.com",
588 vec![IpAddr::V4(Ipv4Addr::new(18, 204, 123, 63))],
589 ),
590 (
591 "imap.qq.com",
592 vec![
593 IpAddr::V4(Ipv4Addr::new(43, 163, 178, 76)),
594 IpAddr::V4(Ipv4Addr::new(43, 129, 255, 54)),
595 ],
596 ),
597 (
598 "smtp.qq.com",
599 vec![
600 IpAddr::V4(Ipv4Addr::new(43, 129, 255, 54)),
601 IpAddr::V4(Ipv4Addr::new(43, 163, 178, 76)),
602 ],
603 ),
604 (
605 "imap.rambler.ru",
606 vec![
607 IpAddr::V4(Ipv4Addr::new(81, 19, 77, 168)),
608 IpAddr::V4(Ipv4Addr::new(81, 19, 77, 169)),
609 IpAddr::V4(Ipv4Addr::new(81, 19, 77, 170)),
610 IpAddr::V4(Ipv4Addr::new(81, 19, 77, 171)),
611 ],
612 ),
613 (
614 "smtp.rambler.ru",
615 vec![
616 IpAddr::V4(Ipv4Addr::new(81, 19, 77, 164)),
617 IpAddr::V4(Ipv4Addr::new(81, 19, 77, 165)),
618 IpAddr::V4(Ipv4Addr::new(81, 19, 77, 166)),
619 IpAddr::V4(Ipv4Addr::new(81, 19, 77, 167)),
620 ],
621 ),
622 (
623 "stinpriza.net",
624 vec![IpAddr::V4(Ipv4Addr::new(5, 9, 122, 184))],
625 ),
626 (
627 "webbox222.server-home.org",
628 vec![IpAddr::V4(Ipv4Addr::new(91, 203, 111, 88))],
629 ),
630 (
631 "undernet.uy",
632 vec![IpAddr::V4(Ipv4Addr::new(200, 40, 115, 74))],
633 ),
634 (
635 "imap.vivaldi.net",
636 vec![IpAddr::V4(Ipv4Addr::new(31, 209, 137, 15))],
637 ),
638 (
639 "smtp.vivaldi.net",
640 vec![IpAddr::V4(Ipv4Addr::new(31, 209, 137, 12))],
641 ),
642 (
643 "imap.vodafonemail.de",
644 vec![
645 IpAddr::V4(Ipv4Addr::new(178, 15, 69, 210)),
646 IpAddr::V4(Ipv4Addr::new(151, 189, 176, 206)),
647 ],
648 ),
649 (
650 "smtp.vodafonemail.de",
651 vec![
652 IpAddr::V4(Ipv4Addr::new(151, 189, 176, 206)),
653 IpAddr::V4(Ipv4Addr::new(178, 15, 69, 206)),
654 ],
655 ),
656 (
657 "smtp.web.de",
658 vec![
659 IpAddr::V4(Ipv4Addr::new(213, 165, 67, 124)),
660 IpAddr::V4(Ipv4Addr::new(213, 165, 67, 108)),
661 ],
662 ),
663 (
664 "imap.yandex.com",
665 vec![IpAddr::V4(Ipv4Addr::new(77, 88, 21, 125))],
666 ),
667 (
668 "smtp.yandex.com",
669 vec![IpAddr::V4(Ipv4Addr::new(77, 88, 21, 158))],
670 ),
671 (
672 "smtp.ziggo.nl",
673 vec![IpAddr::V4(Ipv4Addr::new(84, 116, 6, 3))],
674 ),
675 (
676 "smtp.zoho.eu",
677 vec![
678 IpAddr::V4(Ipv4Addr::new(185, 230, 212, 164)),
679 IpAddr::V4(Ipv4Addr::new(185, 230, 214, 164)),
680 ],
681 ),
682 (
684 "mehl.cloud",
685 vec![IpAddr::V4(Ipv4Addr::new(95, 217, 223, 172))],
686 ),
687 (
688 "mailchat.pl",
689 vec![IpAddr::V4(Ipv4Addr::new(46, 62, 144, 137))],
690 ),
691 (
692 "chatmail.woodpeckersnest.space",
693 vec![IpAddr::V4(Ipv4Addr::new(85, 215, 162, 146))],
694 ),
695 (
696 "chatmail.culturanerd.it",
697 vec![IpAddr::V4(Ipv4Addr::new(82, 165, 94, 165))],
698 ),
699 (
700 "chatmail.hackea.org",
701 vec![IpAddr::V4(Ipv4Addr::new(82, 165, 11, 85))],
702 ),
703 (
704 "chat.adminforge.de",
705 vec![IpAddr::V4(Ipv4Addr::new(94, 130, 17, 142))],
706 ),
707 (
708 "chika.aangat.lahat.computer",
709 vec![IpAddr::V4(Ipv4Addr::new(71, 19, 150, 113))],
710 ),
711 (
712 "tarpit.fun",
713 vec![IpAddr::V4(Ipv4Addr::new(152, 53, 86, 246))],
714 ),
715 (
716 "d.gaufr.es",
717 vec![IpAddr::V4(Ipv4Addr::new(51, 77, 140, 91))],
718 ),
719 (
720 "chtml.ca",
721 vec![IpAddr::V4(Ipv4Addr::new(51, 222, 156, 177))],
722 ),
723 (
724 "chatmail.au",
725 vec![IpAddr::V4(Ipv4Addr::new(45, 124, 54, 79))],
726 ),
727 (
728 "sombras.chat",
729 vec![IpAddr::V4(Ipv4Addr::new(82, 25, 70, 154))],
730 ),
731 (
732 "e2ee.wang",
733 vec![IpAddr::V4(Ipv4Addr::new(139, 84, 233, 161))],
734 ),
735 (
736 "chat.privittytech.com",
737 vec![IpAddr::V4(Ipv4Addr::new(35, 154, 144, 0))],
738 ),
739 ("e2ee.im", vec![IpAddr::V4(Ipv4Addr::new(45, 137, 99, 57))]),
740 (
741 "chatmail.email",
742 vec![IpAddr::V4(Ipv4Addr::new(57, 128, 220, 120))],
743 ),
744 (
745 "danneskjold.de",
746 vec![IpAddr::V4(Ipv4Addr::new(46, 62, 216, 132))],
747 ),
748 (
749 "chat.in-the.eu",
750 vec![IpAddr::V4(Ipv4Addr::new(78, 46, 190, 129))],
751 ),
752 (
753 "chat.nuvon.app",
754 vec![IpAddr::V4(Ipv4Addr::new(178, 238, 38, 165))],
755 ),
756 (
757 "nibblehole.com",
758 vec![IpAddr::V4(Ipv4Addr::new(94, 247, 42, 209))],
759 ),
760 (
761 "chat.zashm.org",
762 vec![IpAddr::V4(Ipv4Addr::new(91, 245, 76, 39))],
763 ),
764 (
765 "chat.sus.fr",
766 vec![IpAddr::V4(Ipv4Addr::new(152, 67, 76, 190))],
767 ),
768 (
769 "delta.thelab.uno",
770 vec![IpAddr::V4(Ipv4Addr::new(146, 59, 228, 39))],
771 ),
772 (
773 "chat.vim.wtf",
774 vec![IpAddr::V4(Ipv4Addr::new(116, 203, 206, 170))],
775 ),
776 (
777 "uninterest.ing",
778 vec![IpAddr::V4(Ipv4Addr::new(172, 245, 70, 237))],
779 ),
780 (
781 "sweetfern.net",
782 vec![IpAddr::V4(Ipv4Addr::new(178, 156, 228, 133))],
783 ),
784 (
785 "delta.disobey.net",
786 vec![IpAddr::V4(Ipv4Addr::new(37, 74, 102, 44))],
787 ),
788 (
789 "darkrun.dev",
790 vec![IpAddr::V4(Ipv4Addr::new(72, 11, 149, 146))],
791 ),
792 ])
793});
794
795async fn lookup_cache(
796 context: &Context,
797 host: &str,
798 port: u16,
799 alpn: &str,
800 now: i64,
801) -> Result<Vec<SocketAddr>> {
802 let mut res = Vec::new();
803 for cached_address in context
804 .sql
805 .query_map_vec(
806 "SELECT dns_cache.address
807 FROM dns_cache
808 LEFT JOIN connection_history
809 ON dns_cache.hostname = connection_history.host
810 AND dns_cache.address = connection_history.addr
811 AND connection_history.port = ?
812 AND connection_history.alpn = ?
813 WHERE dns_cache.hostname = ?
814 AND ? < dns_cache.timestamp + ?
815 ORDER BY IFNULL(connection_history.timestamp, dns_cache.timestamp) DESC
816 LIMIT 50",
817 (port, alpn, host, now, super::CACHE_TTL),
818 |row| {
819 let address: String = row.get(0)?;
820 Ok(address)
821 },
822 )
823 .await?
824 {
825 match IpAddr::from_str(&cached_address) {
826 Ok(ip_addr) => {
827 let addr = SocketAddr::new(ip_addr, port);
828 res.push(addr);
829 }
830 Err(err) => {
831 warn!(
832 context,
833 "Failed to parse cached address {:?}: {:#}.", cached_address, err
834 );
835 }
836 }
837 }
838 Ok(res)
839}
840
841async fn sort_by_connection_timestamp(
844 context: &Context,
845 input: Vec<SocketAddr>,
846 alpn: &str,
847 host: &str,
848) -> Result<Vec<SocketAddr>> {
849 let mut res: Vec<(Option<i64>, SocketAddr)> = Vec::with_capacity(input.len());
850 for addr in input {
851 let timestamp = load_connection_timestamp(
852 &context.sql,
853 alpn,
854 host,
855 addr.port(),
856 Some(&addr.ip().to_string()),
857 )
858 .await?;
859 res.push((timestamp, addr));
860 }
861 res.sort_by_key(|(ts, _addr)| std::cmp::Reverse(*ts));
862 Ok(res.into_iter().map(|(_ts, addr)| addr).collect())
863}
864
865pub(crate) async fn lookup_host_with_cache(
876 context: &Context,
877 hostname: &str,
878 port: u16,
879 alpn: &str,
880 load_cache: bool,
881) -> Result<Vec<SocketAddr>> {
882 let now = time();
883 let resolved_addrs = match lookup_host_and_update_cache(context, hostname, port, now).await {
884 Ok(res) => {
885 if alpn.is_empty() {
886 res
887 } else {
888 sort_by_connection_timestamp(context, res, alpn, hostname).await?
889 }
890 }
891 Err(err) => {
892 warn!(
893 context,
894 "DNS resolution for {hostname}:{port} failed: {err:#}."
895 );
896 Vec::new()
897 }
898 };
899
900 let addrs = if load_cache {
901 let mut cache = lookup_cache(context, hostname, port, alpn, now).await?;
902 if let Some(ips) = DNS_PRELOAD.get(hostname) {
903 for ip in ips {
904 let addr = SocketAddr::new(*ip, port);
905 if !cache.contains(&addr) {
906 cache.push(addr);
907 }
908 }
909 }
910
911 merge_with_cache(resolved_addrs, cache)
912 } else {
913 resolved_addrs
914 };
915 ensure!(
916 !addrs.is_empty(),
917 "Could not find DNS resolutions for {hostname}:{port}. Check server hostname and your network"
918 );
919 Ok(addrs)
920}
921
922fn merge_with_cache(
926 mut resolved_addrs: Vec<SocketAddr>,
927 cache: Vec<SocketAddr>,
928) -> Vec<SocketAddr> {
929 let rest = resolved_addrs.split_off(std::cmp::min(resolved_addrs.len(), 2));
930
931 for addr in cache.into_iter().chain(rest) {
932 if !resolved_addrs.contains(&addr) {
933 resolved_addrs.push(addr);
934 if resolved_addrs.len() >= 10 {
935 break;
936 }
937 }
938 }
939
940 resolved_addrs
941}
942
943#[cfg(test)]
944mod tests {
945 use super::*;
946
947 use crate::net::update_connection_history;
948 use crate::test_utils::TestContext;
949
950 #[tokio::test(flavor = "multi_thread", worker_threads = 2)]
951 async fn test_sort_by_connection_timestamp() {
952 let alice = &TestContext::new_alice().await;
953 let now = time();
954
955 let ipv6_addr = IpAddr::V6(Ipv6Addr::new(0x2a01, 0x4f8, 0x241, 0x4ce8, 0, 0, 0, 2));
956 let ipv4_addr = IpAddr::V4(Ipv4Addr::new(116, 202, 233, 236));
957
958 assert_eq!(
959 sort_by_connection_timestamp(
960 alice,
961 vec![
962 SocketAddr::new(ipv6_addr, 993),
963 SocketAddr::new(ipv4_addr, 993)
964 ],
965 "imap",
966 "nine.testrun.org"
967 )
968 .await
969 .unwrap(),
970 vec![
971 SocketAddr::new(ipv6_addr, 993),
972 SocketAddr::new(ipv4_addr, 993)
973 ]
974 );
975 update_connection_history(
976 alice,
977 "imap",
978 "nine.testrun.org",
979 993,
980 "116.202.233.236",
981 now,
982 )
983 .await
984 .unwrap();
985 assert_eq!(
986 sort_by_connection_timestamp(
987 alice,
988 vec![
989 SocketAddr::new(ipv6_addr, 993),
990 SocketAddr::new(ipv4_addr, 993)
991 ],
992 "imap",
993 "nine.testrun.org"
994 )
995 .await
996 .unwrap(),
997 vec![
998 SocketAddr::new(ipv4_addr, 993),
999 SocketAddr::new(ipv6_addr, 993),
1000 ]
1001 );
1002
1003 assert_eq!(
1004 sort_by_connection_timestamp(
1005 alice,
1006 vec![
1007 SocketAddr::new(ipv6_addr, 465),
1008 SocketAddr::new(ipv4_addr, 465)
1009 ],
1010 "smtp",
1011 "nine.testrun.org"
1012 )
1013 .await
1014 .unwrap(),
1015 vec![
1016 SocketAddr::new(ipv6_addr, 465),
1017 SocketAddr::new(ipv4_addr, 465),
1018 ]
1019 );
1020 update_connection_history(
1021 alice,
1022 "smtp",
1023 "nine.testrun.org",
1024 465,
1025 "116.202.233.236",
1026 now,
1027 )
1028 .await
1029 .unwrap();
1030 assert_eq!(
1031 sort_by_connection_timestamp(
1032 alice,
1033 vec![
1034 SocketAddr::new(ipv6_addr, 465),
1035 SocketAddr::new(ipv4_addr, 465)
1036 ],
1037 "smtp",
1038 "nine.testrun.org"
1039 )
1040 .await
1041 .unwrap(),
1042 vec![
1043 SocketAddr::new(ipv4_addr, 465),
1044 SocketAddr::new(ipv6_addr, 465),
1045 ]
1046 );
1047
1048 update_connection_history(
1049 alice,
1050 "imap",
1051 "nine.testrun.org",
1052 993,
1053 "2a01:4f8:241:4ce8::2",
1054 now,
1055 )
1056 .await
1057 .unwrap();
1058 assert_eq!(
1059 sort_by_connection_timestamp(
1060 alice,
1061 vec![
1062 SocketAddr::new(ipv6_addr, 993),
1063 SocketAddr::new(ipv4_addr, 993)
1064 ],
1065 "imap",
1066 "nine.testrun.org"
1067 )
1068 .await
1069 .unwrap(),
1070 vec![
1071 SocketAddr::new(ipv6_addr, 993),
1072 SocketAddr::new(ipv4_addr, 993)
1073 ]
1074 );
1075 }
1076
1077 #[tokio::test(flavor = "multi_thread", worker_threads = 2)]
1078 async fn test_lookup_cache() {
1079 let alice = &TestContext::new_alice().await;
1080
1081 let ipv4_addr = IpAddr::V4(Ipv4Addr::new(116, 202, 233, 236));
1082 let ipv6_addr = IpAddr::V6(Ipv6Addr::new(0x2a01, 0x4f8, 0x241, 0x4ce8, 0, 0, 0, 2));
1083
1084 let now = time();
1085 assert!(
1086 lookup_cache(alice, "nine.testrun.org", 587, "smtp", now)
1087 .await
1088 .unwrap()
1089 .is_empty()
1090 );
1091
1092 update_cache(alice, "nine.testrun.org", "116.202.233.236", now)
1093 .await
1094 .unwrap();
1095
1096 assert_eq!(
1097 lookup_cache(alice, "nine.testrun.org", 587, "smtp", now)
1098 .await
1099 .unwrap(),
1100 vec![SocketAddr::new(ipv4_addr, 587)]
1101 );
1102
1103 assert_eq!(
1106 lookup_cache(alice, "nine.testrun.org", 443, "", now)
1107 .await
1108 .unwrap(),
1109 vec![SocketAddr::new(ipv4_addr, 443)]
1110 );
1111
1112 update_cache(alice, "nine.testrun.org", "2a01:4f8:241:4ce8::2", now + 30)
1113 .await
1114 .unwrap();
1115
1116 assert_eq!(
1118 lookup_cache(alice, "nine.testrun.org", 443, "", now + 60)
1119 .await
1120 .unwrap(),
1121 vec![
1122 SocketAddr::new(ipv6_addr, 443),
1123 SocketAddr::new(ipv4_addr, 443)
1124 ],
1125 );
1126
1127 update_connection_history(
1130 alice,
1131 "smtp",
1132 "nine.testrun.org",
1133 465,
1134 "116.202.233.236",
1135 now + 100,
1136 )
1137 .await
1138 .unwrap();
1139 assert_eq!(
1140 lookup_cache(alice, "nine.testrun.org", 465, "smtp", now + 120)
1141 .await
1142 .unwrap(),
1143 vec![
1144 SocketAddr::new(ipv4_addr, 465),
1145 SocketAddr::new(ipv6_addr, 465)
1146 ]
1147 );
1148
1149 assert_eq!(
1151 lookup_cache(alice, "nine.testrun.org", 993, "imap", now + 120)
1152 .await
1153 .unwrap(),
1154 vec![
1155 SocketAddr::new(ipv6_addr, 993),
1156 SocketAddr::new(ipv4_addr, 993)
1157 ],
1158 );
1159 assert_eq!(
1160 lookup_cache(alice, "nine.testrun.org", 465, "imap", now + 120)
1161 .await
1162 .unwrap(),
1163 vec![
1164 SocketAddr::new(ipv6_addr, 465),
1165 SocketAddr::new(ipv4_addr, 465)
1166 ],
1167 );
1168 assert_eq!(
1169 lookup_cache(alice, "nine.testrun.org", 993, "smtp", now + 120)
1170 .await
1171 .unwrap(),
1172 vec![
1173 SocketAddr::new(ipv6_addr, 993),
1174 SocketAddr::new(ipv4_addr, 993)
1175 ],
1176 );
1177 }
1178
1179 #[test]
1180 fn test_merge_with_cache() {
1181 let first_addr = IpAddr::V4(Ipv4Addr::new(192, 168, 1, 1));
1182 let second_addr = IpAddr::V4(Ipv4Addr::new(192, 168, 1, 2));
1183
1184 {
1186 let resolved_addrs = vec![
1187 SocketAddr::new(first_addr, 993),
1188 SocketAddr::new(second_addr, 993),
1189 ];
1190 let cache = vec![];
1191 assert_eq!(
1192 merge_with_cache(resolved_addrs.clone(), cache),
1193 resolved_addrs
1194 );
1195 }
1196
1197 {
1200 let resolved_addrs = vec![SocketAddr::new(first_addr, 993)];
1201 let cache = vec![SocketAddr::new(second_addr, 993)];
1202 assert_eq!(
1203 merge_with_cache(resolved_addrs, cache),
1204 vec![
1205 SocketAddr::new(first_addr, 993),
1206 SocketAddr::new(second_addr, 993),
1207 ]
1208 );
1209 }
1210
1211 {
1214 let resolved_addrs = vec![
1215 SocketAddr::new(first_addr, 993),
1216 SocketAddr::new(second_addr, 993),
1217 ];
1218 let cache = vec![SocketAddr::new(second_addr, 993)];
1219 assert_eq!(
1220 merge_with_cache(resolved_addrs, cache),
1221 vec![
1222 SocketAddr::new(first_addr, 993),
1223 SocketAddr::new(second_addr, 993),
1224 ]
1225 );
1226 }
1227
1228 {
1232 let resolved_addrs = vec![
1233 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 993),
1234 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 2)), 993),
1235 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 3)), 993),
1236 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 4)), 993),
1237 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 5)), 993),
1238 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 6)), 993),
1239 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 7)), 993),
1240 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 8)), 993),
1241 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 9)), 993),
1242 ];
1243 let cache = vec![SocketAddr::new(second_addr, 993)];
1244 assert_eq!(
1245 merge_with_cache(resolved_addrs, cache),
1246 vec![
1247 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 993),
1248 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 2)), 993),
1249 SocketAddr::new(second_addr, 993),
1250 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 3)), 993),
1251 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 4)), 993),
1252 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 5)), 993),
1253 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 6)), 993),
1254 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 7)), 993),
1255 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 8)), 993),
1256 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 9)), 993),
1257 ]
1258 );
1259 }
1260
1261 {
1266 let resolved_addrs = vec![
1267 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 993),
1268 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 2)), 993),
1269 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 3)), 993),
1270 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 4)), 993),
1271 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 5)), 993),
1272 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 6)), 993),
1273 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 7)), 993),
1274 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 8)), 993),
1275 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 9)), 993),
1276 ];
1277 let cache = vec![
1278 SocketAddr::new(second_addr, 993),
1279 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 9)), 993),
1280 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 8)), 993),
1281 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 7)), 993),
1282 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 6)), 993),
1283 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 5)), 993),
1284 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 4)), 993),
1285 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 3)), 993),
1286 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 2)), 993),
1287 ];
1288 assert_eq!(
1289 merge_with_cache(resolved_addrs, cache),
1290 vec![
1291 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 993),
1292 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 2)), 993),
1293 SocketAddr::new(second_addr, 993),
1294 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 9)), 993),
1295 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 8)), 993),
1296 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 7)), 993),
1297 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 6)), 993),
1298 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 5)), 993),
1299 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 4)), 993),
1300 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 3)), 993),
1301 ]
1302 );
1303 }
1304 }
1305}