Skip to content

Instantly share code, notes, and snippets.

@shpark
Last active November 1, 2021 05:31
Show Gist options
  • Save shpark/ec0275d719e241146517e91f2467fbbd to your computer and use it in GitHub Desktop.
Save shpark/ec0275d719e241146517e91f2467fbbd to your computer and use it in GitHub Desktop.

Tun and UDP listener

Tx

A local process attempts to send packet to WireGuard IP address (e.g., 192.168.4.3). The packet is delivered to wg interface (for user-space implementation, this is a TUN interface). Boringtun reads packets from the tun interface, find a matching peer, encapsulate packet and emit packet via the Udp socket. Recall that unlike TCP (connection, STREAM, ...), a UDP socket can be reused to send packets to different destinations (See sendto() and recvfrom() usages).

Rx

When a packet arrives to the Udp socket, receive it (and records its source address). If rate_limiter.verify_packet(Some(addr.ip()), packet, &mut t.dst_buf) is Err(TunnResult::WriteToNetwork(cookie), then udp.sendto(cookie, addr).

In most cases, boringtun will decapsulate the data and send it through the tun interface (Check the source IP address).

Device

Conceptually, Device is mapped to a Wireguard interface (iface: Arc<T>). udp4 or udp6 is the listening UDP socket.

The device maintains a mapping from public key to Peer used for crypto-key routing.

peers_by_ip is a trie of IP/cidr addresses.

pub struct Device<T: Tun, S: Sock> {
    key_pair: Option<(Arc<X25519SecretKey>, Arc<X25519PublicKey>)>,
    queue: Arc<EventPoll<Handler<T, S>>>,

    listen_port: u16,
    fwmark: Option<u32>,

    iface: Arc<T>,
    udp4: Option<Arc<S>>,
    udp6: Option<Arc<S>>,

    yield_notice: Option<EventRef>,
    exit_notice: Option<EventRef>,

    peers: HashMap<Arc<X25519PublicKey>, Arc<Peer<S>>>,
    peers_by_ip: AllowedIps<Arc<Peer<S>>>,
    peers_by_idx: HashMap<u32, Arc<Peer<S>>>,
    next_index: u32,

    config: DeviceConfig,

    cleanup_paths: Vec<String>,

    mtu: AtomicUsize,

    rate_limiter: Option<Arc<RateLimiter>>,
}

update_peer

impl<T: Tun, S: Sock> Device<T, S> {
    // ...

    #[allow(clippy::too_many_arguments)]
    fn update_peer(
        &mut self,
        pub_key: X25519PublicKey,
        remove: bool,
        _replace_ips: bool,
        endpoint: Option<SocketAddr>,
        allowed_ips: Vec<AllowedIP>,
        keepalive: Option<u16>,
        preshared_key: Option<[u8; 32]>,
    ) {
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment