Skip to main content

SnapTunServer

Struct SnapTunServer 

Source
pub struct SnapTunServer<T> { /* private fields */ }
Expand description

The SnapTunServer manages one Tunn per remote socket address.

The main structural difference between WireGuard (R) and snaptun-ng is that there is a one-to-one relation between a remote socket address (of the initiator) and a tunnel. The SnapTunServer manages that relation.

§Scaling

The main methods SnapTunServer::handle_incoming_packet, SnapTunServer::handle_outgoing_packet, and SnapTunServer::update_timers all require an exclusive reference to the internal state. The reason is that processing both, incoming and outgoing packets requires access to the session state.

One simple way to achieve load distribution across different cores/threads is to shard over multiple SnapTunServer-instances based on a hash of the remote socket address.

§Future improvements

  • Separate incoming and outgoing code paths and optimistically lock the session state.

§How to use

The SnapTunServer is i/o-free; i.e. it only manages state. The following is a pseudo-code like description of the simplest i/o-layer integration:

let mut server = SnapTunServer::new(/*...*/);
let mut send_to_network = VecDequeue::new();
let mut current_sockaddr = ;
loop {
  switch {
    (network_packet, sockaddr) = network_socket => {
      server.handle_incoming_packet(/*...*/);
      /* dispatch packets to tunnel if necessary */
    }
    tunnel_packet = tunnel_socket => {
      server.handle_outgoing_packet(/*...*/);
    }
    timer = tick(250ms) => {
      server.update_timers();
    }
  }
  // dispatch packets to network
  for p in send_to_network {
    network_socket.send(sockaddr, p);
  }
}

Implementations§

Source§

impl<T: SnapTunAuthorization> SnapTunServer<T>

Source

pub fn new( static_private: StaticSecret, rate_limiter: Arc<RateLimiter>, authz: Arc<T>, ) -> Self

Creates a new SnapTunServer instance.

Source

pub fn handle_incoming_packet( &mut self, packet: Packet, from: SocketAddr, send_to_network: &mut VecDeque<WgKind>, ) -> TunnResult

Handle incoming packet for a tunnel assocated with remote socket address from.

This method never returns TunnResult::WriteToNetwork. Instead, it codifies the expected protocol behavior which is that, upon receiving a packet from the remote, the queue of outgoing packets is completely drained.

If the rate limiter signals that the server is under load, at most one packet is added to the queue.

Source

pub fn handle_outgoing_packet( &mut self, packet: Packet, to: SocketAddr, ) -> Option<WgKind>

Handles an outgoing packet sent through the tunnel identified by the remote socket address to.

Source

pub fn update_timers(&mut self) -> Vec<(SocketAddr, WgKind)>

Update timers of all tunnels. Generate corresponding keepalive or session handshake initializations.

As a result of this call, all expired tunnels are removed. Note that this is not the same as unauthorized tunnels.

Auto Trait Implementations§

§

impl<T> Freeze for SnapTunServer<T>

§

impl<T> !RefUnwindSafe for SnapTunServer<T>

§

impl<T> Send for SnapTunServer<T>
where T: Sync + Send,

§

impl<T> Sync for SnapTunServer<T>
where T: Sync + Send,

§

impl<T> Unpin for SnapTunServer<T>

§

impl<T> UnsafeUnpin for SnapTunServer<T>

§

impl<T> !UnwindSafe for SnapTunServer<T>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more