1use std::{
22 collections::{HashMap, VecDeque},
23 net::SocketAddr,
24 sync::Arc,
25 time::Instant,
26};
27
28use ana_gotatun::{
29 noise::{Tunn, TunnResult, handshake::parse_handshake_anon, rate_limiter::RateLimiter},
30 packet::{Packet, WgKind},
31 x25519,
32};
33
34pub struct SnapTunServer<T: SnapTunAuthorization> {
85 static_private: x25519::StaticSecret,
86 static_public: x25519::PublicKey,
87 active_tunnels: HashMap<SocketAddr, ActiveTunnel>,
88 rate_limiter: Arc<RateLimiter>,
89 authz: Arc<T>,
90}
91
92struct ActiveTunnel {
93 peer_static: x25519::PublicKey,
94 tunn: Tunn,
95}
96
97pub enum HandleIncomingPacketResult<S> {
103 Result {
106 result: TunnResult,
109 },
110 Forwarded {
113 packet: Packet,
115 processed_at: Instant,
117 session_data: Arc<S>,
119 },
120}
121
122impl<S> HandleIncomingPacketResult<S> {
123 pub fn into_result(self) -> TunnResult {
125 match self {
126 HandleIncomingPacketResult::Result { result } => result,
127 HandleIncomingPacketResult::Forwarded { packet, .. } => {
128 TunnResult::WriteToTunnel(packet)
129 }
130 }
131 }
132}
133
134pub struct HandleOutgoingPacketResult<S> {
137 pub network_packet: Option<WgKind>,
140 pub processed_at: Instant,
143 pub session_data: Arc<S>,
145}
146
147impl<S> HandleOutgoingPacketResult<S> {
148 pub fn into_packet(self) -> Option<WgKind> {
150 self.network_packet
151 }
152}
153
154impl<T: SnapTunAuthorization> SnapTunServer<T> {
155 fn incoming_packet_result(
158 result: TunnResult,
159 session_data: Arc<T::SessionData>,
160 now: Instant,
161 ) -> HandleIncomingPacketResult<T::SessionData> {
162 match result {
163 TunnResult::WriteToTunnel(packet) => {
164 HandleIncomingPacketResult::Forwarded {
165 packet,
166 processed_at: now,
167 session_data,
168 }
169 }
170 result => HandleIncomingPacketResult::Result { result },
171 }
172 }
173
174 fn outgoing_packet_result(
175 network_packet: Option<WgKind>,
176 now: Instant,
177 session_data: Arc<T::SessionData>,
178 ) -> HandleOutgoingPacketResult<T::SessionData> {
179 HandleOutgoingPacketResult {
180 network_packet,
181 processed_at: now,
182 session_data,
183 }
184 }
185
186 pub fn new(
188 static_private: x25519::StaticSecret,
189 rate_limiter: Arc<RateLimiter>,
190 authz: Arc<T>,
191 ) -> Self {
192 let static_public = x25519::PublicKey::from(&static_private);
193 Self {
194 static_private,
195 static_public,
196 active_tunnels: Default::default(),
197 rate_limiter,
198 authz,
199 }
200 }
201
202 pub fn handle_incoming_packet(
216 &mut self,
217 packet: Packet,
218 from: SocketAddr,
219 send_to_network: &mut VecDeque<WgKind>,
220 ) -> TunnResult {
221 self.handle_incoming_packet_with_session(packet, from, send_to_network)
222 .into_result()
223 }
224
225 #[tracing::instrument(skip_all, fields(remote = %from))]
232 pub fn handle_incoming_packet_with_session(
233 &mut self,
234 packet: Packet,
235 from: SocketAddr,
236 send_to_network: &mut VecDeque<WgKind>,
237 ) -> HandleIncomingPacketResult<T::SessionData> {
238 let parsed_packet = match self.rate_limiter.verify_packet(from.ip(), packet) {
239 Ok(p) => p,
240 Err(TunnResult::WriteToNetwork(c)) => {
241 tracing::debug!(remote = ?from, "rate limiter issued cookie reply");
242 send_to_network.push_back(c);
243 return HandleIncomingPacketResult::Result {
244 result: TunnResult::Done,
245 };
246 }
247 Err(e) => {
248 tracing::debug!(remote = ?from, err = ?e, "rate limiter rejected packet");
249 return HandleIncomingPacketResult::Result { result: e };
250 }
251 };
252 let packet_now = Instant::now();
256
257 use std::collections::hash_map::Entry;
258
259 use ana_gotatun::noise::errors::WireGuardError;
260 match (self.active_tunnels.entry(from), parsed_packet) {
261 (Entry::Occupied(mut occupied_entry), p) => {
262 let active_tunnel = occupied_entry.get_mut();
263 let Some(session_data) = self
270 .authz
271 .is_authorized(packet_now, active_tunnel.peer_static.as_bytes())
272 else {
273 tracing::debug!(remote = ?from, peer_static = ?active_tunnel.peer_static, "rejected packet from unauthorized peer");
274 return HandleIncomingPacketResult::Result {
275 result: TunnResult::Err(WireGuardError::UnexpectedPacket),
276 };
277 };
278 let result = Self::handle_incoming_and_drain_queue(
279 send_to_network,
280 p,
281 &mut active_tunnel.tunn,
282 );
283 Self::incoming_packet_result(result, session_data, packet_now)
284 }
285 (e, WgKind::HandshakeInit(wg_init)) => {
286 let peer = match parse_handshake_anon(
287 &self.static_private,
288 &self.static_public,
289 &wg_init,
290 ) {
291 Ok(v) => v,
292 Err(e) => {
293 tracing::debug!(remote = ?from, err = ?e, "failed to parse handshake init");
294 return HandleIncomingPacketResult::Result {
295 result: TunnResult::from(e),
296 };
297 }
298 };
299
300 let Some(session_data) = self
306 .authz
307 .is_authorized(packet_now, &peer.peer_static_public)
308 else {
309 tracing::debug!(remote = ?from, "rejected handshake from unauthorized peer");
310 return HandleIncomingPacketResult::Result {
311 result: TunnResult::Err(WireGuardError::UnexpectedPacket),
312 };
313 };
314 tracing::debug!(remote = ?from, "accepted new handshake, inserting tunnel");
315 let peer_static = x25519::PublicKey::from(peer.peer_static_public);
316 let mut tunn = Tunn::new(
317 self.static_private.clone(),
318 peer_static,
319 None,
320 None,
321 0,
322 self.rate_limiter.clone(),
323 from,
324 );
325 let res = Self::handle_incoming_and_drain_queue(
326 send_to_network,
327 WgKind::HandshakeInit(wg_init),
328 &mut tunn,
329 );
330 let handled = Self::incoming_packet_result(res, session_data.clone(), packet_now);
333 e.insert_entry(ActiveTunnel { peer_static, tunn });
334 handled
335 }
336 (_, _p) => {
337 tracing::debug!(remote = ?from, "received unexpected packet kind for new entry");
338 HandleIncomingPacketResult::Result {
339 result: TunnResult::Err(WireGuardError::InvalidPacket),
340 }
341 }
342 }
343 }
344
345 pub fn handle_outgoing_packet(&mut self, packet: Packet, to: SocketAddr) -> Option<WgKind> {
348 self.handle_outgoing_packet_with_session(packet, to)
349 .and_then(HandleOutgoingPacketResult::into_packet)
350 }
351
352 #[tracing::instrument(skip_all, fields(remote = %to))]
359 pub fn handle_outgoing_packet_with_session(
360 &mut self,
361 packet: Packet,
362 to: SocketAddr,
363 ) -> Option<HandleOutgoingPacketResult<T::SessionData>> {
364 let Some(active_tunnel) = self.active_tunnels.get_mut(&to) else {
365 tracing::error!(to=?to, "No tunnel for outgoing packet found.");
366 return None;
367 };
368 let packet_now = Instant::now();
369 let Some(session_data) = self
370 .authz
371 .is_authorized(packet_now, active_tunnel.peer_static.as_bytes())
372 else {
373 tracing::debug!(remote = ?to, peer_static = ?active_tunnel.peer_static, "dropping outgoing packet for unauthorized peer");
374 return None;
375 };
376 Some(Self::outgoing_packet_result(
377 active_tunnel
378 .tunn
379 .handle_outgoing_packet(packet.into_bytes()),
380 packet_now,
381 session_data,
382 ))
383 }
384
385 pub fn update_timers(&mut self) -> Vec<(SocketAddr, WgKind)> {
395 self.rate_limiter.try_reset_count();
398
399 let mut res = vec![];
400 self.active_tunnels.retain(|k, active_tunnel| {
401 match active_tunnel.tunn.update_timers() {
402 Ok(Some(wg)) => res.push((*k, wg)),
403 Ok(None) => {},
404 Err(e) => tracing::error!(err=?e, remote_sockaddr=?k, "error when updating timers on tunnel"),
405 }
406
407 !active_tunnel.tunn.is_expired()
408 });
409 res
410 }
411
412 fn handle_incoming_and_drain_queue(
413 q: &mut VecDeque<WgKind>,
414 p: WgKind,
415 tunn: &mut Tunn,
416 ) -> TunnResult {
417 let r = match tunn.handle_incoming_packet(p) {
418 TunnResult::WriteToNetwork(p) => {
419 q.push_back(p);
420 TunnResult::Done
421 }
422 TunnResult::WriteToTunnel(p) if p.is_empty() => TunnResult::Done,
424 r => r,
425 };
426 for p in tunn.get_queued_packets() {
427 q.push_back(p);
428 }
429 r
430 }
431}
432
433pub trait SnapTunAuthorization: Send + Sync {
435 type SessionData: Clone + Send + Sync + 'static;
437
438 fn is_authorized(&self, now: Instant, identity: &[u8; 32]) -> Option<Arc<Self::SessionData>>;
440}
441
442#[cfg(test)]
443mod tests {
444 use std::{
445 collections::{HashMap, VecDeque},
446 net::SocketAddr,
447 sync::{Arc, Mutex},
448 time::Duration,
449 };
450
451 use ana_gotatun::{
452 noise::{Tunn, TunnResult, rate_limiter::RateLimiter},
453 packet::{IpNextProtocol, Packet, WgKind},
454 x25519,
455 };
456 use zerocopy::IntoBytes;
457
458 use crate::{
459 scion_packet::{Scion, ScionHeader},
460 server::{
461 HandleIncomingPacketResult, HandleOutgoingPacketResult, SnapTunAuthorization,
462 SnapTunServer,
463 },
464 };
465
466 type ResultT = Result<(), Box<dyn std::error::Error>>;
467
468 struct TrivialAuthz;
469
470 impl SnapTunAuthorization for TrivialAuthz {
471 type SessionData = ();
472
473 fn is_authorized(
474 &self,
475 _now: std::time::Instant,
476 _ident: &[u8; 32],
477 ) -> Option<Arc<Self::SessionData>> {
478 Some(Arc::new(()))
479 }
480 }
481
482 #[derive(Debug, Clone, PartialEq, Eq)]
483 struct MutableSessionData {
484 jti: &'static str,
485 pssid: &'static str,
486 tags: Vec<(&'static str, &'static str)>,
487 }
488
489 #[derive(Default)]
490 struct MutableAuthz {
491 sessions: Mutex<HashMap<[u8; 32], Arc<MutableSessionData>>>,
492 }
493
494 impl MutableAuthz {
495 fn set_session_data(&self, identity: [u8; 32], session_data: MutableSessionData) {
496 self.sessions
497 .lock()
498 .unwrap()
499 .insert(identity, Arc::new(session_data));
500 }
501 }
502
503 impl SnapTunAuthorization for MutableAuthz {
504 type SessionData = MutableSessionData;
505
506 fn is_authorized(
507 &self,
508 _now: std::time::Instant,
509 ident: &[u8; 32],
510 ) -> Option<Arc<Self::SessionData>> {
511 self.sessions.lock().unwrap().get(ident).cloned()
512 }
513 }
514
515 fn test_packet<const N: usize>(payload: [u8; N]) -> Packet {
516 let packet = Scion {
517 header: ScionHeader::new(
518 0,
519 0xAA,
520 0xABCDE,
521 payload.len() as _,
522 IpNextProtocol::Udp,
523 7,
524 0x0123_4567_89AB_CDEF,
525 0xFEDC_BA98_7654_3210,
526 ),
527 payload,
528 };
529 Packet::copy_from(packet.as_bytes())
530 }
531
532 fn establish_tunnel<T: SnapTunAuthorization>(
533 snaptun_server: &mut SnapTunServer<T>,
534 tunn_client: &mut Tunn,
535 packet: &Packet,
536 sockaddr_client: SocketAddr,
537 send_to_network: &mut VecDeque<WgKind>,
538 ) {
539 let Some(WgKind::HandshakeInit(hs_init)) =
540 tunn_client.handle_outgoing_packet(Packet::copy_from(packet))
541 else {
542 panic!("expected handshake init")
543 };
544
545 snaptun_server.handle_incoming_packet(
546 Packet::copy_from(hs_init.as_bytes()),
547 sockaddr_client,
548 send_to_network,
549 );
550 dispatch_one(tunn_client, send_to_network);
551 }
552
553 #[test]
554 fn connect_with_multiple_clients() -> ResultT {
555 let sockaddr_client0: SocketAddr = "192.168.1.1:1234".parse().unwrap();
556 let static_client0 = x25519::StaticSecret::from([0u8; 32]);
557 let sockaddr_client1: SocketAddr = "192.168.1.2:4321".parse().unwrap();
558 let static_client1 = x25519::StaticSecret::from([1u8; 32]);
559 let sockaddr_server: SocketAddr = "10.0.0.1:5001".parse().unwrap();
560 let static_server = x25519::StaticSecret::from([2u8; 32]);
561 let static_server_public = x25519::PublicKey::from(&static_server);
562
563 let rate_limiter = Arc::new(RateLimiter::new(&static_server_public, 100));
564 let mut snaptun_server =
565 SnapTunServer::new(static_server, rate_limiter.clone(), Arc::new(TrivialAuthz));
566
567 let mut send_to_network = VecDeque::<WgKind>::new();
568
569 let test_packet0 = test_packet([b'T', b'E', b'S', b'T', b'0']);
570 let test_packet1 = test_packet([b'T', b'E', b'S', b'T', b'1']);
571
572 let mut tunn_client0 = Tunn::new(
573 static_client0,
574 static_server_public,
575 None,
576 None,
577 0,
578 rate_limiter.clone(),
579 sockaddr_server,
580 );
581
582 let mut tunn_client1 = Tunn::new(
583 static_client1,
584 static_server_public,
585 None,
586 None,
587 0,
588 rate_limiter,
589 sockaddr_server,
590 );
591
592 establish_tunnel(
594 &mut snaptun_server,
595 &mut tunn_client0,
596 &test_packet0,
597 sockaddr_client0,
598 &mut send_to_network,
599 );
600 assert_eq!(
601 tunn_client0.get_initiator_remote_sockaddr(),
602 Some(sockaddr_client0)
603 );
604
605 establish_tunnel(
607 &mut snaptun_server,
608 &mut tunn_client1,
609 &test_packet1,
610 sockaddr_client1,
611 &mut send_to_network,
612 );
613 assert_eq!(
614 tunn_client1.get_initiator_remote_sockaddr(),
615 Some(sockaddr_client1)
616 );
617
618 let Some(WgKind::Data(p)) = tunn_client0.get_queued_packets().next() else {
620 panic!("expected packet to be queued");
621 };
622
623 let TunnResult::WriteToTunnel(p) = snaptun_server.handle_incoming_packet(
624 Packet::copy_from(p.as_bytes()),
625 sockaddr_client0,
626 &mut send_to_network,
627 ) else {
628 panic!("Expected packet to be processed")
629 };
630 assert_eq!(p.as_bytes(), test_packet0.as_bytes());
631
632 let Some(WgKind::Data(p1)) = tunn_client1.get_queued_packets().next() else {
636 panic!("expected packet to be queued");
637 };
638
639 let TunnResult::WriteToTunnel(p1) = snaptun_server.handle_incoming_packet(
640 Packet::copy_from(p1.as_bytes()),
641 sockaddr_client1,
642 &mut send_to_network,
643 ) else {
644 panic!("expected packet to be received on server side");
645 };
646 assert_eq!(p1.as_bytes(), test_packet1.as_bytes());
647
648 let res = snaptun_server.handle_outgoing_packet(p, sockaddr_client1);
650 let Some(p @ WgKind::Data(_)) = res else {
651 panic!("expected packet to be sent back to client")
652 };
653
654 let TunnResult::WriteToTunnel(p) = tunn_client1.handle_incoming_packet(p) else {
655 panic!("expected packet to be sent back to client")
656 };
657
658 assert_eq!(p.as_bytes(), test_packet0.as_bytes());
659
660 Ok(())
661 }
662
663 #[test]
664 fn outgoing_packet_with_session_returns_active_session() {
665 let sockaddr_client: SocketAddr = "192.168.1.1:1234".parse().unwrap();
666 let static_client = x25519::StaticSecret::from([0u8; 32]);
667 let sockaddr_server: SocketAddr = "10.0.0.1:5001".parse().unwrap();
668 let static_server = x25519::StaticSecret::from([2u8; 32]);
669 let static_server_public = x25519::PublicKey::from(&static_server);
670
671 let rate_limiter = Arc::new(RateLimiter::new(&static_server_public, 100));
672 let mut snaptun_server =
673 SnapTunServer::new(static_server, rate_limiter.clone(), Arc::new(TrivialAuthz));
674 let mut send_to_network = VecDeque::<WgKind>::new();
675
676 let test_packet = test_packet([b'T', b'E', b'S', b'T']);
677
678 let mut tunn_client = Tunn::new(
679 static_client,
680 static_server_public,
681 None,
682 None,
683 0,
684 rate_limiter,
685 sockaddr_server,
686 );
687
688 establish_tunnel(
689 &mut snaptun_server,
690 &mut tunn_client,
691 &test_packet,
692 sockaddr_client,
693 &mut send_to_network,
694 );
695
696 let Some(WgKind::Data(client_data)) = tunn_client.get_queued_packets().next() else {
697 panic!("expected packet to be queued");
698 };
699 let TunnResult::WriteToTunnel(server_plaintext) = snaptun_server.handle_incoming_packet(
700 Packet::copy_from(client_data.as_bytes()),
701 sockaddr_client,
702 &mut send_to_network,
703 ) else {
704 panic!("expected packet to be processed")
705 };
706
707 let handled = snaptun_server
708 .handle_outgoing_packet_with_session(server_plaintext, sockaddr_client)
709 .expect("expected packet to be encapsulated");
710 let HandleOutgoingPacketResult {
711 network_packet: Some(WgKind::Data(encapsulated)),
712 processed_at: _,
713 session_data,
714 } = handled
715 else {
716 panic!("expected encapsulated data packet")
717 };
718 assert_eq!(session_data.as_ref(), &());
719
720 let TunnResult::WriteToTunnel(plaintext) =
721 tunn_client.handle_incoming_packet(WgKind::Data(encapsulated))
722 else {
723 panic!("expected packet to be delivered back to client")
724 };
725 assert_eq!(plaintext.as_bytes(), test_packet.as_bytes());
726 }
727
728 #[test]
729 fn established_tunnel_refreshes_session_data_for_later_packets() {
730 let sockaddr_client: SocketAddr = "192.168.1.1:1234".parse().unwrap();
731 let static_client = x25519::StaticSecret::from([0u8; 32]);
732 let client_identity = x25519::PublicKey::from(&static_client);
733 let sockaddr_server: SocketAddr = "10.0.0.1:5001".parse().unwrap();
734 let static_server = x25519::StaticSecret::from([2u8; 32]);
735 let static_server_public = x25519::PublicKey::from(&static_server);
736 let rate_limiter = Arc::new(RateLimiter::new(&static_server_public, 100));
737 let authz = Arc::new(MutableAuthz::default());
738 let original_session = MutableSessionData {
739 jti: "original-jti",
740 pssid: "original-pssid",
741 tags: vec![("subject_id", "subject-1"), ("scope", "basic")],
742 };
743 authz.set_session_data(*client_identity.as_bytes(), original_session);
744
745 let mut snaptun_server =
746 SnapTunServer::new(static_server, rate_limiter.clone(), authz.clone());
747 let mut send_to_network = VecDeque::<WgKind>::new();
748 let test_packet = test_packet([b'T', b'E', b'S', b'T']);
749
750 let mut tunn_client = Tunn::new(
751 static_client,
752 static_server_public,
753 None,
754 None,
755 0,
756 rate_limiter,
757 sockaddr_server,
758 );
759
760 establish_tunnel(
761 &mut snaptun_server,
762 &mut tunn_client,
763 &test_packet,
764 sockaddr_client,
765 &mut send_to_network,
766 );
767
768 let refreshed_session = MutableSessionData {
769 jti: "refreshed-jti",
770 pssid: "refreshed-pssid",
771 tags: vec![("subject_id", "subject-2"), ("scope", "premium")],
772 };
773 authz.set_session_data(*client_identity.as_bytes(), refreshed_session.clone());
774
775 let Some(WgKind::Data(client_data)) = tunn_client.get_queued_packets().next() else {
776 panic!("expected packet to be queued");
777 };
778 let HandleIncomingPacketResult::Forwarded {
779 packet: server_plaintext,
780 session_data,
781 ..
782 } = snaptun_server.handle_incoming_packet_with_session(
783 Packet::copy_from(client_data.as_bytes()),
784 sockaddr_client,
785 &mut send_to_network,
786 )
787 else {
788 panic!("expected forwarded packet with refreshed session data")
789 };
790 assert_eq!(session_data.as_ref(), &refreshed_session);
791
792 let Some(HandleOutgoingPacketResult {
793 network_packet: Some(WgKind::Data(encapsulated)),
794 processed_at: _,
795 session_data,
796 }) = snaptun_server.handle_outgoing_packet_with_session(server_plaintext, sockaddr_client)
797 else {
798 panic!("expected encapsulated data packet with refreshed session data")
799 };
800 assert_eq!(session_data.as_ref(), &refreshed_session);
801
802 let TunnResult::WriteToTunnel(plaintext) =
803 tunn_client.handle_incoming_packet(WgKind::Data(encapsulated))
804 else {
805 panic!("expected packet to be delivered back to client")
806 };
807 assert_eq!(plaintext.as_bytes(), test_packet.as_bytes());
808 }
809
810 #[test]
811 fn outgoing_packet_with_session_returns_none_without_tunnel() {
812 let sockaddr_client: SocketAddr = "192.168.1.1:1234".parse().unwrap();
813 let static_server = x25519::StaticSecret::from([2u8; 32]);
814 let static_server_public = x25519::PublicKey::from(&static_server);
815 let rate_limiter = Arc::new(RateLimiter::new(&static_server_public, 100));
816 let mut snaptun_server =
817 SnapTunServer::new(static_server, rate_limiter, Arc::new(TrivialAuthz));
818
819 let payload = [b'T', b'E', b'S', b'T'];
820 let test_packet = Scion {
821 header: ScionHeader::new(
822 0,
823 0xAA,
824 0xABCDE,
825 payload.len() as _,
826 IpNextProtocol::Udp,
827 7,
828 0x0123_4567_89AB_CDEF,
829 0xFEDC_BA98_7654_3210,
830 ),
831 payload,
832 };
833
834 assert!(
835 snaptun_server
836 .handle_outgoing_packet_with_session(
837 Packet::copy_from(test_packet.as_bytes()),
838 sockaddr_client
839 )
840 .is_none()
841 );
842 }
843
844 #[test]
853 fn update_timers_resets_the_rate_limiter_without_active_tunnels() {
854 let static_server = x25519::StaticSecret::from([2u8; 32]);
855 let static_server_public = x25519::PublicKey::from(&static_server);
856 let sockaddr_server: SocketAddr = "10.0.0.1:5001".parse().unwrap();
857
858 let mut snaptun_server = SnapTunServer::new(
861 static_server,
862 Arc::new(RateLimiter::new(&static_server_public, 1)),
863 Arc::new(MutableAuthz::default()),
864 );
865 let client_rate_limiter = Arc::new(RateLimiter::new(&static_server_public, u64::MAX));
868
869 let handshake_from_new_client = |server: &mut SnapTunServer<MutableAuthz>, index: u8| {
870 let mut client = Tunn::new(
871 x25519::StaticSecret::from([index; 32]),
872 static_server_public,
873 None,
874 None,
875 0,
876 client_rate_limiter.clone(),
877 sockaddr_server,
878 );
879 let Some(WgKind::HandshakeInit(hs_init)) =
880 client.handle_outgoing_packet(test_packet([index]))
881 else {
882 panic!("expected handshake init")
883 };
884
885 let mut send_to_network = VecDeque::<WgKind>::new();
888 server.handle_incoming_packet(
889 Packet::copy_from(hs_init.as_bytes()),
890 SocketAddr::new("192.168.1.1".parse().unwrap(), 1234 + u16::from(index)),
891 &mut send_to_network,
892 );
893 send_to_network.pop_front()
894 };
895
896 assert!(
899 handshake_from_new_client(&mut snaptun_server, 1).is_none(),
900 "the first handshake is below the limit and must reach authorization"
901 );
902 assert!(
903 matches!(
904 handshake_from_new_client(&mut snaptun_server, 2),
905 Some(WgKind::CookieReply(_))
906 ),
907 "the second handshake reaches the limit and must be answered with a cookie"
908 );
909 assert!(
910 snaptun_server.active_tunnels.is_empty(),
911 "no tunnel may exist, otherwise its timers would reset the limiter"
912 );
913
914 std::thread::sleep(Duration::from_millis(1_100));
917 snaptun_server.update_timers();
918
919 assert!(
920 handshake_from_new_client(&mut snaptun_server, 3).is_none(),
921 "after the reset period an idle server must stop demanding cookies"
922 );
923 }
924
925 fn dispatch_one(tunn: &mut Tunn, packets: &mut VecDeque<WgKind>) -> TunnResult {
926 if let Some(packet) = packets.pop_front() {
927 return tunn.handle_incoming_packet(packet);
928 }
929 TunnResult::Done
930 }
931}