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> {
93 static_private: x25519::StaticSecret,
94 static_public: x25519::PublicKey,
95 active_tunnels: HashMap<SocketAddr, ActiveTunnel>,
96 rate_limiter: Arc<RateLimiter>,
97 authz: Arc<T>,
98}
99
100struct ActiveTunnel {
101 peer_static: x25519::PublicKey,
102 tunn: Tunn,
103}
104
105pub enum HandleIncomingPacketResult<S> {
111 Result {
114 result: TunnResult,
117 },
118 Forwarded {
121 packet: Packet,
123 processed_at: Instant,
125 session_data: Arc<S>,
127 },
128}
129
130impl<S> HandleIncomingPacketResult<S> {
131 pub fn into_result(self) -> TunnResult {
133 match self {
134 HandleIncomingPacketResult::Result { result } => result,
135 HandleIncomingPacketResult::Forwarded { packet, .. } => {
136 TunnResult::WriteToTunnel(packet)
137 }
138 }
139 }
140}
141
142pub struct HandleOutgoingPacketResult<S> {
145 pub network_packet: Option<WgKind>,
148 pub processed_at: Instant,
151 pub session_data: Arc<S>,
153}
154
155impl<S> HandleOutgoingPacketResult<S> {
156 pub fn into_packet(self) -> Option<WgKind> {
158 self.network_packet
159 }
160}
161
162impl<T: SnapTunAuthorization> SnapTunServer<T> {
163 fn incoming_packet_result(
166 result: TunnResult,
167 session_data: Arc<T::SessionData>,
168 now: Instant,
169 ) -> HandleIncomingPacketResult<T::SessionData> {
170 match result {
171 TunnResult::WriteToTunnel(packet) => {
172 HandleIncomingPacketResult::Forwarded {
173 packet,
174 processed_at: now,
175 session_data,
176 }
177 }
178 result => HandleIncomingPacketResult::Result { result },
179 }
180 }
181
182 fn outgoing_packet_result(
183 network_packet: Option<WgKind>,
184 now: Instant,
185 session_data: Arc<T::SessionData>,
186 ) -> HandleOutgoingPacketResult<T::SessionData> {
187 HandleOutgoingPacketResult {
188 network_packet,
189 processed_at: now,
190 session_data,
191 }
192 }
193
194 pub fn new(
196 static_private: x25519::StaticSecret,
197 rate_limiter: Arc<RateLimiter>,
198 authz: Arc<T>,
199 ) -> Self {
200 let static_public = x25519::PublicKey::from(&static_private);
201 Self {
202 static_private,
203 static_public,
204 active_tunnels: Default::default(),
205 rate_limiter,
206 authz,
207 }
208 }
209
210 pub fn handle_incoming_packet(
224 &mut self,
225 packet: Packet,
226 from: SocketAddr,
227 send_to_network: &mut VecDeque<WgKind>,
228 ) -> TunnResult {
229 self.handle_incoming_packet_with_session(packet, from, send_to_network)
230 .into_result()
231 }
232
233 #[tracing::instrument(skip_all, fields(remote = %from))]
246 pub fn handle_incoming_packet_with_session(
247 &mut self,
248 packet: Packet,
249 from: SocketAddr,
250 send_to_network: &mut VecDeque<WgKind>,
251 ) -> HandleIncomingPacketResult<T::SessionData> {
252 let parsed_packet = match self.rate_limiter.verify_packet(from.ip(), packet) {
253 Ok(p) => p,
254 Err(TunnResult::WriteToNetwork(c)) => {
255 tracing::debug!(remote = ?from, "rate limiter issued cookie reply");
256 send_to_network.push_back(c);
257 return HandleIncomingPacketResult::Result {
258 result: TunnResult::Done,
259 };
260 }
261 Err(e) => {
262 tracing::debug!(remote = ?from, err = ?e, "rate limiter rejected packet");
263 return HandleIncomingPacketResult::Result { result: e };
264 }
265 };
266 let packet_now = Instant::now();
270
271 use std::collections::hash_map::Entry;
272
273 use ana_gotatun::noise::errors::WireGuardError;
274 match (self.active_tunnels.entry(from), parsed_packet) {
275 (Entry::Occupied(mut occupied_entry), p) => {
276 let active_tunnel = occupied_entry.get_mut();
277 let Some(session_data) = self
284 .authz
285 .is_authorized(packet_now, active_tunnel.peer_static.as_bytes())
286 else {
287 tracing::debug!(remote = ?from, peer_static = ?active_tunnel.peer_static, "rejected packet from unauthorized peer");
288 return HandleIncomingPacketResult::Result {
289 result: TunnResult::Err(WireGuardError::UnexpectedPacket),
290 };
291 };
292 let result = Self::handle_incoming_and_drain_queue(
293 send_to_network,
294 p,
295 &mut active_tunnel.tunn,
296 );
297 Self::incoming_packet_result(result, session_data, packet_now)
298 }
299 (e, WgKind::HandshakeInit(wg_init)) => {
300 let peer = match parse_handshake_anon(
301 &self.static_private,
302 &self.static_public,
303 &wg_init,
304 ) {
305 Ok(v) => v,
306 Err(e) => {
307 tracing::debug!(remote = ?from, err = ?e, "failed to parse handshake init");
308 return HandleIncomingPacketResult::Result {
309 result: TunnResult::from(e),
310 };
311 }
312 };
313
314 let Some(session_data) = self
320 .authz
321 .is_authorized(packet_now, &peer.peer_static_public)
322 else {
323 tracing::debug!(remote = ?from, "rejected handshake from unauthorized peer");
324 return HandleIncomingPacketResult::Result {
325 result: TunnResult::Err(WireGuardError::UnexpectedPacket),
326 };
327 };
328 tracing::debug!(remote = ?from, "accepted new handshake, inserting tunnel");
329 let peer_static = x25519::PublicKey::from(peer.peer_static_public);
330 let mut tunn = Tunn::new(
331 self.static_private.clone(),
332 peer_static,
333 None,
334 None,
335 0,
336 self.rate_limiter.clone(),
337 from,
338 );
339 let res = Self::handle_incoming_and_drain_queue(
340 send_to_network,
341 WgKind::HandshakeInit(wg_init),
342 &mut tunn,
343 );
344 let handled = Self::incoming_packet_result(res, session_data.clone(), packet_now);
347 e.insert_entry(ActiveTunnel { peer_static, tunn });
348 handled
349 }
350 (_, _p) => {
351 tracing::debug!(remote = ?from, "received unexpected packet kind for new entry");
352 HandleIncomingPacketResult::Result {
353 result: TunnResult::Err(WireGuardError::InvalidPacket),
354 }
355 }
356 }
357 }
358
359 pub fn handle_outgoing_packet(&mut self, packet: Packet, to: SocketAddr) -> Option<WgKind> {
362 self.handle_outgoing_packet_with_session(packet, to)
363 .and_then(HandleOutgoingPacketResult::into_packet)
364 }
365
366 #[tracing::instrument(skip_all, fields(remote = %to))]
373 pub fn handle_outgoing_packet_with_session(
374 &mut self,
375 packet: Packet,
376 to: SocketAddr,
377 ) -> Option<HandleOutgoingPacketResult<T::SessionData>> {
378 let Some(active_tunnel) = self.active_tunnels.get_mut(&to) else {
379 tracing::error!(to=?to, "No tunnel for outgoing packet found.");
380 return None;
381 };
382 let packet_now = Instant::now();
383 let Some(session_data) = self
384 .authz
385 .is_authorized(packet_now, active_tunnel.peer_static.as_bytes())
386 else {
387 tracing::debug!(remote = ?to, peer_static = ?active_tunnel.peer_static, "dropping outgoing packet for unauthorized peer");
388 return None;
389 };
390 Some(Self::outgoing_packet_result(
391 active_tunnel
392 .tunn
393 .handle_outgoing_packet(packet.into_bytes()),
394 packet_now,
395 session_data,
396 ))
397 }
398
399 pub fn update_timers(&mut self) -> Vec<(SocketAddr, WgKind)> {
409 self.rate_limiter.try_reset_count();
412
413 let mut res = vec![];
414 self.active_tunnels.retain(|k, active_tunnel| {
415 match active_tunnel.tunn.update_timers() {
416 Ok(Some(wg)) => res.push((*k, wg)),
417 Ok(None) => {},
418 Err(e) => tracing::error!(err=?e, remote_sockaddr=?k, "error when updating timers on tunnel"),
419 }
420
421 !active_tunnel.tunn.is_expired()
422 });
423 res
424 }
425
426 fn handle_incoming_and_drain_queue(
427 q: &mut VecDeque<WgKind>,
428 p: WgKind,
429 tunn: &mut Tunn,
430 ) -> TunnResult {
431 let r = match tunn.handle_incoming_packet(p) {
432 TunnResult::WriteToNetwork(p) => {
433 q.push_back(p);
434 TunnResult::Done
435 }
436 TunnResult::WriteToTunnel(p) if p.is_empty() => TunnResult::Done,
438 r => r,
439 };
440 for p in tunn.get_queued_packets() {
441 q.push_back(p);
442 }
443 r
444 }
445}
446
447pub trait SnapTunAuthorization: Send + Sync {
449 type SessionData: Clone + Send + Sync + 'static;
451
452 fn is_authorized(&self, now: Instant, identity: &[u8; 32]) -> Option<Arc<Self::SessionData>>;
454}
455
456#[cfg(test)]
457mod tests {
458 use std::{
459 collections::{HashMap, VecDeque},
460 net::SocketAddr,
461 sync::{Arc, Mutex},
462 time::Duration,
463 };
464
465 use ana_gotatun::{
466 noise::{Tunn, TunnResult, errors::WireGuardError, rate_limiter::RateLimiter},
467 packet::{IpNextProtocol, Packet, WgKind},
468 x25519,
469 };
470 use zerocopy::IntoBytes;
471
472 use crate::{
473 scion_packet::{Scion, ScionHeader},
474 server::{
475 HandleIncomingPacketResult, HandleOutgoingPacketResult, SnapTunAuthorization,
476 SnapTunServer,
477 },
478 };
479
480 type ResultT = Result<(), Box<dyn std::error::Error>>;
481
482 struct TrivialAuthz;
483
484 impl SnapTunAuthorization for TrivialAuthz {
485 type SessionData = ();
486
487 fn is_authorized(
488 &self,
489 _now: std::time::Instant,
490 _ident: &[u8; 32],
491 ) -> Option<Arc<Self::SessionData>> {
492 Some(Arc::new(()))
493 }
494 }
495
496 #[derive(Debug, Clone, PartialEq, Eq)]
497 struct MutableSessionData {
498 jti: &'static str,
499 pssid: &'static str,
500 tags: Vec<(&'static str, &'static str)>,
501 }
502
503 #[derive(Default)]
504 struct MutableAuthz {
505 sessions: Mutex<HashMap<[u8; 32], Arc<MutableSessionData>>>,
506 }
507
508 impl MutableAuthz {
509 fn set_session_data(&self, identity: [u8; 32], session_data: MutableSessionData) {
510 self.sessions
511 .lock()
512 .unwrap()
513 .insert(identity, Arc::new(session_data));
514 }
515 }
516
517 impl SnapTunAuthorization for MutableAuthz {
518 type SessionData = MutableSessionData;
519
520 fn is_authorized(
521 &self,
522 _now: std::time::Instant,
523 ident: &[u8; 32],
524 ) -> Option<Arc<Self::SessionData>> {
525 self.sessions.lock().unwrap().get(ident).cloned()
526 }
527 }
528
529 fn test_packet<const N: usize>(payload: [u8; N]) -> Packet {
530 let packet = Scion {
531 header: ScionHeader::new(
532 0,
533 0xAA,
534 0xABCDE,
535 payload.len() as _,
536 IpNextProtocol::Udp,
537 7,
538 0x0123_4567_89AB_CDEF,
539 0xFEDC_BA98_7654_3210,
540 ),
541 payload,
542 };
543 Packet::copy_from(packet.as_bytes())
544 }
545
546 fn establish_tunnel<T: SnapTunAuthorization>(
547 snaptun_server: &mut SnapTunServer<T>,
548 tunn_client: &mut Tunn,
549 packet: &Packet,
550 sockaddr_client: SocketAddr,
551 send_to_network: &mut VecDeque<WgKind>,
552 ) {
553 let Some(WgKind::HandshakeInit(hs_init)) =
554 tunn_client.handle_outgoing_packet(Packet::copy_from(packet))
555 else {
556 panic!("expected handshake init")
557 };
558
559 snaptun_server.handle_incoming_packet(
560 Packet::copy_from(hs_init.as_bytes()),
561 sockaddr_client,
562 send_to_network,
563 );
564 dispatch_one(tunn_client, send_to_network);
565 }
566
567 #[test]
568 fn connect_with_multiple_clients() -> ResultT {
569 let sockaddr_client0: SocketAddr = "192.168.1.1:1234".parse().unwrap();
570 let static_client0 = x25519::StaticSecret::from([0u8; 32]);
571 let sockaddr_client1: SocketAddr = "192.168.1.2:4321".parse().unwrap();
572 let static_client1 = x25519::StaticSecret::from([1u8; 32]);
573 let sockaddr_server: SocketAddr = "10.0.0.1:5001".parse().unwrap();
574 let static_server = x25519::StaticSecret::from([2u8; 32]);
575 let static_server_public = x25519::PublicKey::from(&static_server);
576
577 let rate_limiter = Arc::new(RateLimiter::new(&static_server_public, 100));
578 let mut snaptun_server =
579 SnapTunServer::new(static_server, rate_limiter.clone(), Arc::new(TrivialAuthz));
580
581 let mut send_to_network = VecDeque::<WgKind>::new();
582
583 let test_packet0 = test_packet(*b"TEST0");
584 let test_packet1 = test_packet(*b"TEST1");
585
586 let mut tunn_client0 = Tunn::new(
587 static_client0,
588 static_server_public,
589 None,
590 None,
591 0,
592 rate_limiter.clone(),
593 sockaddr_server,
594 );
595
596 let mut tunn_client1 = Tunn::new(
597 static_client1,
598 static_server_public,
599 None,
600 None,
601 0,
602 rate_limiter,
603 sockaddr_server,
604 );
605
606 establish_tunnel(
608 &mut snaptun_server,
609 &mut tunn_client0,
610 &test_packet0,
611 sockaddr_client0,
612 &mut send_to_network,
613 );
614 assert_eq!(
615 tunn_client0.get_initiator_remote_sockaddr(),
616 Some(sockaddr_client0)
617 );
618
619 establish_tunnel(
621 &mut snaptun_server,
622 &mut tunn_client1,
623 &test_packet1,
624 sockaddr_client1,
625 &mut send_to_network,
626 );
627 assert_eq!(
628 tunn_client1.get_initiator_remote_sockaddr(),
629 Some(sockaddr_client1)
630 );
631
632 let Some(WgKind::Data(p)) = tunn_client0.get_queued_packets().next() else {
634 panic!("expected packet to be queued");
635 };
636
637 let TunnResult::WriteToTunnel(p) = snaptun_server.handle_incoming_packet(
638 Packet::copy_from(p.as_bytes()),
639 sockaddr_client0,
640 &mut send_to_network,
641 ) else {
642 panic!("Expected packet to be processed")
643 };
644 assert_eq!(p.as_bytes(), test_packet0.as_bytes());
645
646 let Some(WgKind::Data(p1)) = tunn_client1.get_queued_packets().next() else {
650 panic!("expected packet to be queued");
651 };
652
653 let TunnResult::WriteToTunnel(p1) = snaptun_server.handle_incoming_packet(
654 Packet::copy_from(p1.as_bytes()),
655 sockaddr_client1,
656 &mut send_to_network,
657 ) else {
658 panic!("expected packet to be received on server side");
659 };
660 assert_eq!(p1.as_bytes(), test_packet1.as_bytes());
661
662 let res = snaptun_server.handle_outgoing_packet(p, sockaddr_client1);
664 let Some(p @ WgKind::Data(_)) = res else {
665 panic!("expected packet to be sent back to client")
666 };
667
668 let TunnResult::WriteToTunnel(p) = tunn_client1.handle_incoming_packet(p) else {
669 panic!("expected packet to be sent back to client")
670 };
671
672 assert_eq!(p.as_bytes(), test_packet0.as_bytes());
673
674 Ok(())
675 }
676
677 #[test]
678 fn outgoing_packet_with_session_returns_active_session() {
679 let sockaddr_client: SocketAddr = "192.168.1.1:1234".parse().unwrap();
680 let static_client = x25519::StaticSecret::from([0u8; 32]);
681 let sockaddr_server: SocketAddr = "10.0.0.1:5001".parse().unwrap();
682 let static_server = x25519::StaticSecret::from([2u8; 32]);
683 let static_server_public = x25519::PublicKey::from(&static_server);
684
685 let rate_limiter = Arc::new(RateLimiter::new(&static_server_public, 100));
686 let mut snaptun_server =
687 SnapTunServer::new(static_server, rate_limiter.clone(), Arc::new(TrivialAuthz));
688 let mut send_to_network = VecDeque::<WgKind>::new();
689
690 let test_packet = test_packet(*b"TEST");
691
692 let mut tunn_client = Tunn::new(
693 static_client,
694 static_server_public,
695 None,
696 None,
697 0,
698 rate_limiter,
699 sockaddr_server,
700 );
701
702 establish_tunnel(
703 &mut snaptun_server,
704 &mut tunn_client,
705 &test_packet,
706 sockaddr_client,
707 &mut send_to_network,
708 );
709
710 let Some(WgKind::Data(client_data)) = tunn_client.get_queued_packets().next() else {
711 panic!("expected packet to be queued");
712 };
713 let TunnResult::WriteToTunnel(server_plaintext) = snaptun_server.handle_incoming_packet(
714 Packet::copy_from(client_data.as_bytes()),
715 sockaddr_client,
716 &mut send_to_network,
717 ) else {
718 panic!("expected packet to be processed")
719 };
720
721 let handled = snaptun_server
722 .handle_outgoing_packet_with_session(server_plaintext, sockaddr_client)
723 .expect("expected packet to be encapsulated");
724 let HandleOutgoingPacketResult {
725 network_packet: Some(WgKind::Data(encapsulated)),
726 processed_at: _,
727 session_data,
728 } = handled
729 else {
730 panic!("expected encapsulated data packet")
731 };
732 assert_eq!(session_data.as_ref(), &());
733
734 let TunnResult::WriteToTunnel(plaintext) =
735 tunn_client.handle_incoming_packet(WgKind::Data(encapsulated))
736 else {
737 panic!("expected packet to be delivered back to client")
738 };
739 assert_eq!(plaintext.as_bytes(), test_packet.as_bytes());
740 }
741
742 #[test]
743 fn established_tunnel_refreshes_session_data_for_later_packets() {
744 let sockaddr_client: SocketAddr = "192.168.1.1:1234".parse().unwrap();
745 let static_client = x25519::StaticSecret::from([0u8; 32]);
746 let client_identity = x25519::PublicKey::from(&static_client);
747 let sockaddr_server: SocketAddr = "10.0.0.1:5001".parse().unwrap();
748 let static_server = x25519::StaticSecret::from([2u8; 32]);
749 let static_server_public = x25519::PublicKey::from(&static_server);
750 let rate_limiter = Arc::new(RateLimiter::new(&static_server_public, 100));
751 let authz = Arc::new(MutableAuthz::default());
752 let original_session = MutableSessionData {
753 jti: "original-jti",
754 pssid: "original-pssid",
755 tags: vec![("subject_id", "subject-1"), ("scope", "basic")],
756 };
757 authz.set_session_data(*client_identity.as_bytes(), original_session);
758
759 let mut snaptun_server =
760 SnapTunServer::new(static_server, rate_limiter.clone(), authz.clone());
761 let mut send_to_network = VecDeque::<WgKind>::new();
762 let test_packet = test_packet(*b"TEST");
763
764 let mut tunn_client = Tunn::new(
765 static_client,
766 static_server_public,
767 None,
768 None,
769 0,
770 rate_limiter,
771 sockaddr_server,
772 );
773
774 establish_tunnel(
775 &mut snaptun_server,
776 &mut tunn_client,
777 &test_packet,
778 sockaddr_client,
779 &mut send_to_network,
780 );
781
782 let refreshed_session = MutableSessionData {
783 jti: "refreshed-jti",
784 pssid: "refreshed-pssid",
785 tags: vec![("subject_id", "subject-2"), ("scope", "premium")],
786 };
787 authz.set_session_data(*client_identity.as_bytes(), refreshed_session.clone());
788
789 let Some(WgKind::Data(client_data)) = tunn_client.get_queued_packets().next() else {
790 panic!("expected packet to be queued");
791 };
792 let HandleIncomingPacketResult::Forwarded {
793 packet: server_plaintext,
794 session_data,
795 ..
796 } = snaptun_server.handle_incoming_packet_with_session(
797 Packet::copy_from(client_data.as_bytes()),
798 sockaddr_client,
799 &mut send_to_network,
800 )
801 else {
802 panic!("expected forwarded packet with refreshed session data")
803 };
804 assert_eq!(session_data.as_ref(), &refreshed_session);
805
806 let Some(HandleOutgoingPacketResult {
807 network_packet: Some(WgKind::Data(encapsulated)),
808 processed_at: _,
809 session_data,
810 }) = snaptun_server.handle_outgoing_packet_with_session(server_plaintext, sockaddr_client)
811 else {
812 panic!("expected encapsulated data packet with refreshed session data")
813 };
814 assert_eq!(session_data.as_ref(), &refreshed_session);
815
816 let TunnResult::WriteToTunnel(plaintext) =
817 tunn_client.handle_incoming_packet(WgKind::Data(encapsulated))
818 else {
819 panic!("expected packet to be delivered back to client")
820 };
821 assert_eq!(plaintext.as_bytes(), test_packet.as_bytes());
822 }
823
824 #[test]
825 fn outgoing_packet_with_session_returns_none_without_tunnel() {
826 let sockaddr_client: SocketAddr = "192.168.1.1:1234".parse().unwrap();
827 let static_server = x25519::StaticSecret::from([2u8; 32]);
828 let static_server_public = x25519::PublicKey::from(&static_server);
829 let rate_limiter = Arc::new(RateLimiter::new(&static_server_public, 100));
830 let mut snaptun_server =
831 SnapTunServer::new(static_server, rate_limiter, Arc::new(TrivialAuthz));
832
833 let payload = *b"TEST";
834 let test_packet = Scion {
835 header: ScionHeader::new(
836 0,
837 0xAA,
838 0xABCDE,
839 payload.len() as _,
840 IpNextProtocol::Udp,
841 7,
842 0x0123_4567_89AB_CDEF,
843 0xFEDC_BA98_7654_3210,
844 ),
845 payload,
846 };
847
848 assert!(
849 snaptun_server
850 .handle_outgoing_packet_with_session(
851 Packet::copy_from(test_packet.as_bytes()),
852 sockaddr_client
853 )
854 .is_none()
855 );
856 }
857
858 #[test]
867 fn update_timers_resets_the_rate_limiter_without_active_tunnels() {
868 let static_server = x25519::StaticSecret::from([2u8; 32]);
869 let static_server_public = x25519::PublicKey::from(&static_server);
870 let sockaddr_server: SocketAddr = "10.0.0.1:5001".parse().unwrap();
871
872 let mut snaptun_server = SnapTunServer::new(
875 static_server,
876 Arc::new(RateLimiter::new(&static_server_public, 1)),
877 Arc::new(MutableAuthz::default()),
878 );
879 let client_rate_limiter = Arc::new(RateLimiter::new(&static_server_public, u64::MAX));
882
883 let handshake_from_new_client = |server: &mut SnapTunServer<MutableAuthz>, index: u8| {
884 let mut client = Tunn::new(
885 x25519::StaticSecret::from([index; 32]),
886 static_server_public,
887 None,
888 None,
889 0,
890 client_rate_limiter.clone(),
891 sockaddr_server,
892 );
893 let Some(WgKind::HandshakeInit(hs_init)) =
894 client.handle_outgoing_packet(test_packet([index]))
895 else {
896 panic!("expected handshake init")
897 };
898
899 let mut send_to_network = VecDeque::<WgKind>::new();
902 server.handle_incoming_packet(
903 Packet::copy_from(hs_init.as_bytes()),
904 SocketAddr::new("192.168.1.1".parse().unwrap(), 1234 + u16::from(index)),
905 &mut send_to_network,
906 );
907 send_to_network.pop_front()
908 };
909
910 assert!(
913 handshake_from_new_client(&mut snaptun_server, 1).is_none(),
914 "the first handshake is below the limit and must reach authorization"
915 );
916 assert!(
917 matches!(
918 handshake_from_new_client(&mut snaptun_server, 2),
919 Some(WgKind::CookieReply(_))
920 ),
921 "the second handshake reaches the limit and must be answered with a cookie"
922 );
923 assert!(
924 snaptun_server.active_tunnels.is_empty(),
925 "no tunnel may exist, otherwise its timers would reset the limiter"
926 );
927
928 #[allow(clippy::disallowed_methods)]
931 std::thread::sleep(Duration::from_millis(1_100));
932 snaptun_server.update_timers();
933
934 assert!(
935 handshake_from_new_client(&mut snaptun_server, 3).is_none(),
936 "after the reset period an idle server must stop demanding cookies"
937 );
938 }
939
940 fn dispatch_one(tunn: &mut Tunn, packets: &mut VecDeque<WgKind>) -> TunnResult {
941 if let Some(packet) = packets.pop_front() {
942 return tunn.handle_incoming_packet(packet);
943 }
944 TunnResult::Done
945 }
946
947 fn server_with_authorized_identities(
950 identities: &[&x25519::StaticSecret],
951 ) -> (
952 SnapTunServer<MutableAuthz>,
953 Arc<RateLimiter>,
954 x25519::PublicKey,
955 ) {
956 let static_server = x25519::StaticSecret::from([2u8; 32]);
957 let static_server_public = x25519::PublicKey::from(&static_server);
958 let rate_limiter = Arc::new(RateLimiter::new(&static_server_public, 100));
959
960 let authz = Arc::new(MutableAuthz::default());
961 for (index, identity) in identities.iter().enumerate() {
962 authz.set_session_data(
963 *x25519::PublicKey::from(*identity).as_bytes(),
964 session_data_of(index),
965 );
966 }
967
968 (
969 SnapTunServer::new(static_server, rate_limiter.clone(), authz),
970 rate_limiter,
971 static_server_public,
972 )
973 }
974
975 fn session_data_of(index: usize) -> MutableSessionData {
976 let names = ["first", "second"];
977 MutableSessionData {
978 jti: names[index],
979 pssid: names[index],
980 tags: vec![],
981 }
982 }
983
984 fn client_tunn(
985 static_client: x25519::StaticSecret,
986 static_server_public: x25519::PublicKey,
987 rate_limiter: Arc<RateLimiter>,
988 ) -> Tunn {
989 let sockaddr_server: SocketAddr = "10.0.0.1:5001".parse().unwrap();
990 Tunn::new(
991 static_client,
992 static_server_public,
993 None,
994 None,
995 0,
996 rate_limiter,
997 sockaddr_server,
998 )
999 }
1000
1001 fn handshake_init_of(tunn: &mut Tunn, packet: Packet) -> Packet {
1002 let Some(WgKind::HandshakeInit(hs_init)) = tunn.handle_outgoing_packet(packet) else {
1003 panic!("expected handshake init")
1004 };
1005 Packet::copy_from(hs_init.as_bytes())
1006 }
1007
1008 #[test]
1017 fn a_new_identity_cannot_take_over_the_address_of_an_active_tunnel() {
1018 let sockaddr_client: SocketAddr = "192.168.1.1:1234".parse().unwrap();
1019 let static_client_old = x25519::StaticSecret::from([0u8; 32]);
1020 let static_client_new = x25519::StaticSecret::from([1u8; 32]);
1021 let identity_old = x25519::PublicKey::from(&static_client_old);
1022
1023 let (mut snaptun_server, rate_limiter, static_server_public) =
1024 server_with_authorized_identities(&[&static_client_old, &static_client_new]);
1025 let mut send_to_network = VecDeque::<WgKind>::new();
1026
1027 let mut tunn_old = client_tunn(
1028 static_client_old,
1029 static_server_public,
1030 rate_limiter.clone(),
1031 );
1032 establish_tunnel(
1033 &mut snaptun_server,
1034 &mut tunn_old,
1035 &test_packet(*b"OLD"),
1036 sockaddr_client,
1037 &mut send_to_network,
1038 );
1039 send_to_network.clear();
1040
1041 let mut tunn_new = client_tunn(static_client_new, static_server_public, rate_limiter);
1042 let hs_init = handshake_init_of(&mut tunn_new, test_packet(*b"NEW"));
1043 let result =
1044 snaptun_server.handle_incoming_packet(hs_init, sockaddr_client, &mut send_to_network);
1045
1046 assert!(
1047 matches!(result, TunnResult::Err(WireGuardError::WrongKey)),
1048 "the handshake of the new identity must not be accepted, got {result:?}"
1049 );
1050 assert!(
1051 send_to_network.is_empty(),
1052 "the server must not answer the handshake of the new identity"
1053 );
1054 assert_eq!(
1055 snaptun_server.active_tunnels[&sockaddr_client].peer_static, identity_old,
1056 "the address must still hold the tunnel of the first identity"
1057 );
1058 }
1059
1060 #[test]
1063 fn the_same_identity_re_establishes_a_tunnel_on_the_same_address() {
1064 let sockaddr_client: SocketAddr = "192.168.1.1:1234".parse().unwrap();
1065 let static_client = x25519::StaticSecret::from([0u8; 32]);
1066 let identity = x25519::PublicKey::from(&static_client);
1067
1068 let (mut snaptun_server, rate_limiter, static_server_public) =
1069 server_with_authorized_identities(&[&static_client]);
1070 let mut send_to_network = VecDeque::<WgKind>::new();
1071
1072 let mut tunn_first = client_tunn(
1073 static_client.clone(),
1074 static_server_public,
1075 rate_limiter.clone(),
1076 );
1077 establish_tunnel(
1078 &mut snaptun_server,
1079 &mut tunn_first,
1080 &test_packet(*b"ONE"),
1081 sockaddr_client,
1082 &mut send_to_network,
1083 );
1084 send_to_network.clear();
1085
1086 let second_packet = test_packet(*b"TWO");
1088 let mut tunn_second = client_tunn(static_client, static_server_public, rate_limiter);
1089 establish_tunnel(
1090 &mut snaptun_server,
1091 &mut tunn_second,
1092 &second_packet,
1093 sockaddr_client,
1094 &mut send_to_network,
1095 );
1096
1097 let Some(WgKind::Data(client_data)) = tunn_second.get_queued_packets().next() else {
1098 panic!("expected the restarted client to complete the handshake and queue a packet");
1099 };
1100 let HandleIncomingPacketResult::Forwarded {
1101 packet,
1102 session_data,
1103 ..
1104 } = snaptun_server.handle_incoming_packet_with_session(
1105 Packet::copy_from(client_data.as_bytes()),
1106 sockaddr_client,
1107 &mut send_to_network,
1108 )
1109 else {
1110 panic!("expected the packet of the restarted client to be forwarded")
1111 };
1112 assert_eq!(packet.as_bytes(), second_packet.as_bytes());
1113 assert_eq!(session_data.as_ref(), &session_data_of(0));
1114 assert_eq!(
1115 snaptun_server.active_tunnels[&sockaddr_client].peer_static, identity,
1116 "the address must still hold the tunnel of the same identity"
1117 );
1118 }
1119}