cargo format
This commit is contained in:
parent
65efa0a2e1
commit
af09c610b2
14 changed files with 154 additions and 81 deletions
|
|
@ -1,8 +1,8 @@
|
||||||
|
use std::net::ToSocketAddrs;
|
||||||
use std::{
|
use std::{
|
||||||
net::{IpAddr, Ipv4Addr, SocketAddr},
|
net::{IpAddr, Ipv4Addr, SocketAddr},
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
};
|
};
|
||||||
use std::net::ToSocketAddrs;
|
|
||||||
|
|
||||||
mod command;
|
mod command;
|
||||||
mod instance;
|
mod instance;
|
||||||
|
|
@ -54,8 +54,9 @@ pub async fn daemon_main() -> Result<()> {
|
||||||
let public_key = parse_public_key("uy75leriJay0+oHLhRMpV+A5xAQ0hCJ+q7Ww81AOvT4=")?;
|
let public_key = parse_public_key("uy75leriJay0+oHLhRMpV+A5xAQ0hCJ+q7Ww81AOvT4=")?;
|
||||||
let preshared_key = Some(parse_key("s7lx/mg+reVEMnGnqeyYOQkzD86n2+gYnx1M9ygi08k=")?);
|
let preshared_key = Some(parse_key("s7lx/mg+reVEMnGnqeyYOQkzD86n2+gYnx1M9ygi08k=")?);
|
||||||
tracing::debug!("beginning to find endpoint location");
|
tracing::debug!("beginning to find endpoint location");
|
||||||
let endpoint = "wg.burrow.rs:51820".to_socket_addrs()?
|
let endpoint = "wg.burrow.rs:51820"
|
||||||
.filter(|sock| {sock.is_ipv4()})
|
.to_socket_addrs()?
|
||||||
|
.filter(|sock| sock.is_ipv4())
|
||||||
.next()
|
.next()
|
||||||
.ok_or(anyhow!("DNS Lookup Fails!"))?; // DNS lookup under macos fails, somehow
|
.ok_or(anyhow!("DNS Lookup Fails!"))?; // DNS lookup under macos fails, somehow
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ fn fetch_socket_path() -> Option<PathBuf> {
|
||||||
for path in tries {
|
for path in tries {
|
||||||
let path = PathBuf::from(path);
|
let path = PathBuf::from(path);
|
||||||
if path.exists() {
|
if path.exists() {
|
||||||
return Some(path)
|
return Some(path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,7 @@ pub mod wireguard;
|
||||||
|
|
||||||
mod daemon;
|
mod daemon;
|
||||||
pub use daemon::{
|
pub use daemon::{
|
||||||
DaemonClient, DaemonCommand,
|
DaemonClient, DaemonCommand, DaemonResponse, DaemonResponseData, DaemonStartOptions, ServerInfo,
|
||||||
DaemonResponse,
|
|
||||||
DaemonResponseData,
|
|
||||||
DaemonStartOptions,
|
|
||||||
ServerInfo,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(target_vendor = "apple")]
|
#[cfg(target_vendor = "apple")]
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,92 @@
|
||||||
|
use crate::wireguard::{Interface as WgInterface, Peer as WgPeer};
|
||||||
|
use anyhow::{anyhow, Error, Result};
|
||||||
|
use base64::engine::general_purpose;
|
||||||
|
use base64::Engine;
|
||||||
|
use fehler::throws;
|
||||||
|
use ip_network::IpNetwork;
|
||||||
|
use nix::libc::malloc_printf;
|
||||||
|
use std::net::ToSocketAddrs;
|
||||||
|
use std::str::FromStr;
|
||||||
|
use x25519_dalek::{PublicKey, StaticSecret};
|
||||||
|
|
||||||
|
#[throws]
|
||||||
|
fn parse_key(string: &str) -> [u8; 32] {
|
||||||
|
let value = general_purpose::STANDARD.decode(string)?;
|
||||||
|
let mut key = [0u8; 32];
|
||||||
|
key.copy_from_slice(&value[..]);
|
||||||
|
key
|
||||||
|
}
|
||||||
|
|
||||||
|
#[throws]
|
||||||
|
fn parse_secret_key(string: &str) -> StaticSecret {
|
||||||
|
let key = parse_key(string)?;
|
||||||
|
StaticSecret::from(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[throws]
|
||||||
|
fn parse_public_key(string: &str) -> PublicKey {
|
||||||
|
let key = parse_key(string)?;
|
||||||
|
PublicKey::from(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A raw version of Peer Config that can be used later to reflect configuration files.
|
||||||
|
/// This should be later converted to a `WgPeer`.
|
||||||
|
/// Refers to https://github.com/pirate/wireguard-docs?tab=readme-ov-file#overview
|
||||||
|
pub struct Peer {
|
||||||
|
pub public_key: String,
|
||||||
|
pub preshared_key: Option<String>,
|
||||||
|
pub allowed_ips: Vec<String>,
|
||||||
|
pub endpoint: String,
|
||||||
|
pub persistent_keepalive: u32,
|
||||||
|
pub name: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Interface {
|
||||||
|
pub private_key: String,
|
||||||
|
pub address: String,
|
||||||
|
pub listen_port: u32,
|
||||||
|
pub dns: Vec<String>,
|
||||||
|
pub mtu: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Config {
|
||||||
|
pub peers: Vec<Peer>,
|
||||||
|
pub interface: Interface, // Support for multiple interfaces?
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<Config> for WgInterface {
|
||||||
|
type Error = anyhow::Error;
|
||||||
|
|
||||||
|
fn try_from(cfig: Config) -> Result<Self, Error> {
|
||||||
|
let sk = parse_secret_key(&cfig.interface.private_key)?;
|
||||||
|
let wg_peers: Vec<WgPeer> = cfig
|
||||||
|
.peers
|
||||||
|
.iter()
|
||||||
|
.map(|p| {
|
||||||
|
Ok(WgPeer {
|
||||||
|
private_key: sk.clone(),
|
||||||
|
public_key: parse_public_key(&p.public_key)?,
|
||||||
|
endpoint: p
|
||||||
|
.endpoint
|
||||||
|
.to_socket_addrs()?
|
||||||
|
.filter(|sock| sock.is_ipv4())
|
||||||
|
.next()
|
||||||
|
.ok_or(anyhow!("DNS Lookup Fails!"))?,
|
||||||
|
preshared_key: match &p.preshared_key {
|
||||||
|
None => Ok(None),
|
||||||
|
Some(k) => parse_key(k).map(|res| Some(res)),
|
||||||
|
}?,
|
||||||
|
allowed_ips: p
|
||||||
|
.allowed_ips
|
||||||
|
.iter()
|
||||||
|
.map(|ip_addr| {
|
||||||
|
IpNetwork::from_str(ip_addr)
|
||||||
|
.map_err(|e| anyhow!("Error parsing IP Network {}: {}", ip_addr, e))
|
||||||
|
})
|
||||||
|
.collect::<Result<Vec<IpNetwork>>>()?,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.collect::<Result<Vec<WgPeer>>>()?;
|
||||||
|
Ok(WgInterface::new(wg_peers)?)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -113,7 +113,7 @@ impl Interface {
|
||||||
Ok(Ok(len)) => &buf[..len],
|
Ok(Ok(len)) => &buf[..len],
|
||||||
Ok(Err(e)) => {
|
Ok(Err(e)) => {
|
||||||
error!("failed to read from interface: {}", e);
|
error!("failed to read from interface: {}", e);
|
||||||
continue
|
continue;
|
||||||
}
|
}
|
||||||
Err(_would_block) => continue,
|
Err(_would_block) => continue,
|
||||||
};
|
};
|
||||||
|
|
@ -126,7 +126,7 @@ impl Interface {
|
||||||
Some(addr) => addr,
|
Some(addr) => addr,
|
||||||
None => {
|
None => {
|
||||||
tracing::debug!("no destination found");
|
tracing::debug!("no destination found");
|
||||||
continue
|
continue;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -146,7 +146,7 @@ impl Interface {
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::error!("failed to send packet {}", e);
|
log::error!("failed to send packet {}", e);
|
||||||
continue
|
continue;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -170,12 +170,12 @@ impl Interface {
|
||||||
let tsk = async move {
|
let tsk = async move {
|
||||||
if let Err(e) = pcb.open_if_closed().await {
|
if let Err(e) = pcb.open_if_closed().await {
|
||||||
log::error!("failed to open pcb: {}", e);
|
log::error!("failed to open pcb: {}", e);
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
let r2 = pcb.run(tun).await;
|
let r2 = pcb.run(tun).await;
|
||||||
if let Err(e) = r2 {
|
if let Err(e) = r2 {
|
||||||
log::error!("failed to run pcb: {}", e);
|
log::error!("failed to run pcb: {}", e);
|
||||||
return
|
return;
|
||||||
} else {
|
} else {
|
||||||
tracing::debug!("pcb ran successfully");
|
tracing::debug!("pcb ran successfully");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
mod config;
|
||||||
mod iface;
|
mod iface;
|
||||||
mod noise;
|
mod noise;
|
||||||
mod pcb;
|
mod pcb;
|
||||||
|
|
@ -16,7 +17,7 @@ Address = 10.68.136.199/32,fc00:bbbb:bbbb:bb01::5:88c6/128
|
||||||
DNS = 10.64.0.1
|
DNS = 10.64.0.1
|
||||||
|
|
||||||
[Peer]
|
[Peer]
|
||||||
PublicKey = EKZXvHlSDeqAjfC/m9aQR0oXfQ6Idgffa9L0DH5yaCo=
|
public_key = EKZXvHlSDeqAjfC/m9aQR0oXfQ6Idgffa9L0DH5yaCo=
|
||||||
AllowedIPs = 0.0.0.0/0,::0/0
|
AllowedIPs = 0.0.0.0/0,::0/0
|
||||||
Endpoint = 146.70.173.66:51820
|
Endpoint = 146.70.173.66:51820
|
||||||
"#;
|
"#;
|
||||||
|
|
|
||||||
|
|
@ -9,20 +9,14 @@ use std::{
|
||||||
use aead::{Aead, Payload};
|
use aead::{Aead, Payload};
|
||||||
use blake2::{
|
use blake2::{
|
||||||
digest::{FixedOutput, KeyInit},
|
digest::{FixedOutput, KeyInit},
|
||||||
Blake2s256,
|
Blake2s256, Blake2sMac, Digest,
|
||||||
Blake2sMac,
|
|
||||||
Digest,
|
|
||||||
};
|
};
|
||||||
use chacha20poly1305::XChaCha20Poly1305;
|
use chacha20poly1305::XChaCha20Poly1305;
|
||||||
use rand_core::OsRng;
|
use rand_core::OsRng;
|
||||||
use ring::aead::{Aad, LessSafeKey, Nonce, UnboundKey, CHACHA20_POLY1305};
|
use ring::aead::{Aad, LessSafeKey, Nonce, UnboundKey, CHACHA20_POLY1305};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
errors::WireGuardError,
|
errors::WireGuardError, session::Session, x25519, HandshakeInit, HandshakeResponse,
|
||||||
session::Session,
|
|
||||||
x25519,
|
|
||||||
HandshakeInit,
|
|
||||||
HandshakeResponse,
|
|
||||||
PacketCookieReply,
|
PacketCookieReply,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -209,7 +203,7 @@ impl Tai64N {
|
||||||
/// Parse a timestamp from a 12 byte u8 slice
|
/// Parse a timestamp from a 12 byte u8 slice
|
||||||
fn parse(buf: &[u8; 12]) -> Result<Tai64N, WireGuardError> {
|
fn parse(buf: &[u8; 12]) -> Result<Tai64N, WireGuardError> {
|
||||||
if buf.len() < 12 {
|
if buf.len() < 12 {
|
||||||
return Err(WireGuardError::InvalidTai64nTimestamp)
|
return Err(WireGuardError::InvalidTai64nTimestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
let (sec_bytes, nano_bytes) = buf.split_at(std::mem::size_of::<u64>());
|
let (sec_bytes, nano_bytes) = buf.split_at(std::mem::size_of::<u64>());
|
||||||
|
|
@ -556,19 +550,22 @@ impl Handshake {
|
||||||
let timestamp = Tai64N::parse(×tamp)?;
|
let timestamp = Tai64N::parse(×tamp)?;
|
||||||
if !timestamp.after(&self.last_handshake_timestamp) {
|
if !timestamp.after(&self.last_handshake_timestamp) {
|
||||||
// Possibly a replay
|
// Possibly a replay
|
||||||
return Err(WireGuardError::WrongTai64nTimestamp)
|
return Err(WireGuardError::WrongTai64nTimestamp);
|
||||||
}
|
}
|
||||||
self.last_handshake_timestamp = timestamp;
|
self.last_handshake_timestamp = timestamp;
|
||||||
|
|
||||||
// initiator.hash = HASH(initiator.hash || msg.encrypted_timestamp)
|
// initiator.hash = HASH(initiator.hash || msg.encrypted_timestamp)
|
||||||
hash = b2s_hash(&hash, packet.encrypted_timestamp);
|
hash = b2s_hash(&hash, packet.encrypted_timestamp);
|
||||||
|
|
||||||
self.previous = std::mem::replace(&mut self.state, HandshakeState::InitReceived {
|
self.previous = std::mem::replace(
|
||||||
chaining_key,
|
&mut self.state,
|
||||||
hash,
|
HandshakeState::InitReceived {
|
||||||
peer_ephemeral_public,
|
chaining_key,
|
||||||
peer_index,
|
hash,
|
||||||
});
|
peer_ephemeral_public,
|
||||||
|
peer_index,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
self.format_handshake_response(dst)
|
self.format_handshake_response(dst)
|
||||||
}
|
}
|
||||||
|
|
@ -669,7 +666,7 @@ impl Handshake {
|
||||||
|
|
||||||
let local_index = self.cookies.index;
|
let local_index = self.cookies.index;
|
||||||
if packet.receiver_idx != local_index {
|
if packet.receiver_idx != local_index {
|
||||||
return Err(WireGuardError::WrongIndex)
|
return Err(WireGuardError::WrongIndex);
|
||||||
}
|
}
|
||||||
// msg.encrypted_cookie = XAEAD(HASH(LABEL_COOKIE || responder.static_public),
|
// msg.encrypted_cookie = XAEAD(HASH(LABEL_COOKIE || responder.static_public),
|
||||||
// msg.nonce, cookie, last_received_msg.mac1)
|
// msg.nonce, cookie, last_received_msg.mac1)
|
||||||
|
|
@ -725,7 +722,7 @@ impl Handshake {
|
||||||
dst: &'a mut [u8],
|
dst: &'a mut [u8],
|
||||||
) -> Result<&'a mut [u8], WireGuardError> {
|
) -> Result<&'a mut [u8], WireGuardError> {
|
||||||
if dst.len() < super::HANDSHAKE_INIT_SZ {
|
if dst.len() < super::HANDSHAKE_INIT_SZ {
|
||||||
return Err(WireGuardError::DestinationBufferTooSmall)
|
return Err(WireGuardError::DestinationBufferTooSmall);
|
||||||
}
|
}
|
||||||
|
|
||||||
let (message_type, rest) = dst.split_at_mut(4);
|
let (message_type, rest) = dst.split_at_mut(4);
|
||||||
|
|
@ -808,7 +805,7 @@ impl Handshake {
|
||||||
dst: &'a mut [u8],
|
dst: &'a mut [u8],
|
||||||
) -> Result<(&'a mut [u8], Session), WireGuardError> {
|
) -> Result<(&'a mut [u8], Session), WireGuardError> {
|
||||||
if dst.len() < super::HANDSHAKE_RESP_SZ {
|
if dst.len() < super::HANDSHAKE_RESP_SZ {
|
||||||
return Err(WireGuardError::DestinationBufferTooSmall)
|
return Err(WireGuardError::DestinationBufferTooSmall);
|
||||||
}
|
}
|
||||||
|
|
||||||
let state = std::mem::replace(&mut self.state, HandshakeState::None);
|
let state = std::mem::replace(&mut self.state, HandshakeState::None);
|
||||||
|
|
|
||||||
|
|
@ -45,11 +45,7 @@ const N_SESSIONS: usize = 8;
|
||||||
|
|
||||||
pub mod x25519 {
|
pub mod x25519 {
|
||||||
pub use x25519_dalek::{
|
pub use x25519_dalek::{
|
||||||
EphemeralSecret,
|
EphemeralSecret, PublicKey, ReusableSecret, SharedSecret, StaticSecret,
|
||||||
PublicKey,
|
|
||||||
ReusableSecret,
|
|
||||||
SharedSecret,
|
|
||||||
StaticSecret,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -141,7 +137,7 @@ impl Tunnel {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn parse_incoming_packet(src: &[u8]) -> Result<Packet, WireGuardError> {
|
pub fn parse_incoming_packet(src: &[u8]) -> Result<Packet, WireGuardError> {
|
||||||
if src.len() < 4 {
|
if src.len() < 4 {
|
||||||
return Err(WireGuardError::InvalidPacket)
|
return Err(WireGuardError::InvalidPacket);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checks the type, as well as the reserved zero fields
|
// Checks the type, as well as the reserved zero fields
|
||||||
|
|
@ -183,7 +179,7 @@ impl Tunnel {
|
||||||
|
|
||||||
pub fn dst_address(packet: &[u8]) -> Option<IpAddr> {
|
pub fn dst_address(packet: &[u8]) -> Option<IpAddr> {
|
||||||
if packet.is_empty() {
|
if packet.is_empty() {
|
||||||
return None
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
match packet[0] >> 4 {
|
match packet[0] >> 4 {
|
||||||
|
|
@ -207,7 +203,7 @@ impl Tunnel {
|
||||||
|
|
||||||
pub fn src_address(packet: &[u8]) -> Option<IpAddr> {
|
pub fn src_address(packet: &[u8]) -> Option<IpAddr> {
|
||||||
if packet.is_empty() {
|
if packet.is_empty() {
|
||||||
return None
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
match packet[0] >> 4 {
|
match packet[0] >> 4 {
|
||||||
|
|
@ -302,7 +298,7 @@ impl Tunnel {
|
||||||
self.timer_tick(TimerName::TimeLastDataPacketSent);
|
self.timer_tick(TimerName::TimeLastDataPacketSent);
|
||||||
}
|
}
|
||||||
self.tx_bytes += src.len();
|
self.tx_bytes += src.len();
|
||||||
return TunnResult::WriteToNetwork(packet)
|
return TunnResult::WriteToNetwork(packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there is no session, queue the packet for future retry
|
// If there is no session, queue the packet for future retry
|
||||||
|
|
@ -326,7 +322,7 @@ impl Tunnel {
|
||||||
) -> TunnResult<'a> {
|
) -> TunnResult<'a> {
|
||||||
if datagram.is_empty() {
|
if datagram.is_empty() {
|
||||||
// Indicates a repeated call
|
// Indicates a repeated call
|
||||||
return self.send_queued_packet(dst)
|
return self.send_queued_packet(dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut cookie = [0u8; COOKIE_REPLY_SZ];
|
let mut cookie = [0u8; COOKIE_REPLY_SZ];
|
||||||
|
|
@ -337,7 +333,7 @@ impl Tunnel {
|
||||||
Ok(packet) => packet,
|
Ok(packet) => packet,
|
||||||
Err(TunnResult::WriteToNetwork(cookie)) => {
|
Err(TunnResult::WriteToNetwork(cookie)) => {
|
||||||
dst[..cookie.len()].copy_from_slice(cookie);
|
dst[..cookie.len()].copy_from_slice(cookie);
|
||||||
return TunnResult::WriteToNetwork(&mut dst[..cookie.len()])
|
return TunnResult::WriteToNetwork(&mut dst[..cookie.len()]);
|
||||||
}
|
}
|
||||||
Err(TunnResult::Err(e)) => return TunnResult::Err(e),
|
Err(TunnResult::Err(e)) => return TunnResult::Err(e),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
|
|
@ -437,7 +433,7 @@ impl Tunnel {
|
||||||
let cur_idx = self.current;
|
let cur_idx = self.current;
|
||||||
if cur_idx == new_idx {
|
if cur_idx == new_idx {
|
||||||
// There is nothing to do, already using this session, this is the common case
|
// There is nothing to do, already using this session, this is the common case
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
if self.sessions[cur_idx % N_SESSIONS].is_none()
|
if self.sessions[cur_idx % N_SESSIONS].is_none()
|
||||||
|| self.timers.session_timers[new_idx % N_SESSIONS]
|
|| self.timers.session_timers[new_idx % N_SESSIONS]
|
||||||
|
|
@ -483,7 +479,7 @@ impl Tunnel {
|
||||||
force_resend: bool,
|
force_resend: bool,
|
||||||
) -> TunnResult<'a> {
|
) -> TunnResult<'a> {
|
||||||
if self.handshake.is_in_progress() && !force_resend {
|
if self.handshake.is_in_progress() && !force_resend {
|
||||||
return TunnResult::Done
|
return TunnResult::Done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.handshake.is_expired() {
|
if self.handshake.is_expired() {
|
||||||
|
|
@ -542,7 +538,7 @@ impl Tunnel {
|
||||||
};
|
};
|
||||||
|
|
||||||
if computed_len > packet.len() {
|
if computed_len > packet.len() {
|
||||||
return TunnResult::Err(WireGuardError::InvalidPacket)
|
return TunnResult::Err(WireGuardError::InvalidPacket);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.timer_tick(TimerName::TimeLastDataPacketReceived);
|
self.timer_tick(TimerName::TimeLastDataPacketReceived);
|
||||||
|
|
|
||||||
|
|
@ -12,19 +12,9 @@ use ring::constant_time::verify_slices_are_equal;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
handshake::{
|
handshake::{
|
||||||
b2s_hash,
|
b2s_hash, b2s_keyed_mac_16, b2s_keyed_mac_16_2, b2s_mac_24, LABEL_COOKIE, LABEL_MAC1,
|
||||||
b2s_keyed_mac_16,
|
|
||||||
b2s_keyed_mac_16_2,
|
|
||||||
b2s_mac_24,
|
|
||||||
LABEL_COOKIE,
|
|
||||||
LABEL_MAC1,
|
|
||||||
},
|
},
|
||||||
HandshakeInit,
|
HandshakeInit, HandshakeResponse, Packet, TunnResult, Tunnel, WireGuardError,
|
||||||
HandshakeResponse,
|
|
||||||
Packet,
|
|
||||||
TunnResult,
|
|
||||||
Tunnel,
|
|
||||||
WireGuardError,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const COOKIE_REFRESH: u64 = 128; // Use 128 and not 120 so the compiler can optimize out the division
|
const COOKIE_REFRESH: u64 = 128; // Use 128 and not 120 so the compiler can optimize out the division
|
||||||
|
|
@ -136,7 +126,7 @@ impl RateLimiter {
|
||||||
dst: &'a mut [u8],
|
dst: &'a mut [u8],
|
||||||
) -> Result<&'a mut [u8], WireGuardError> {
|
) -> Result<&'a mut [u8], WireGuardError> {
|
||||||
if dst.len() < super::COOKIE_REPLY_SZ {
|
if dst.len() < super::COOKIE_REPLY_SZ {
|
||||||
return Err(WireGuardError::DestinationBufferTooSmall)
|
return Err(WireGuardError::DestinationBufferTooSmall);
|
||||||
}
|
}
|
||||||
|
|
||||||
let (message_type, rest) = dst.split_at_mut(4);
|
let (message_type, rest) = dst.split_at_mut(4);
|
||||||
|
|
@ -202,7 +192,7 @@ impl RateLimiter {
|
||||||
let cookie_packet = self
|
let cookie_packet = self
|
||||||
.format_cookie_reply(sender_idx, cookie, mac1, dst)
|
.format_cookie_reply(sender_idx, cookie, mac1, dst)
|
||||||
.map_err(TunnResult::Err)?;
|
.map_err(TunnResult::Err)?;
|
||||||
return Err(TunnResult::WriteToNetwork(cookie_packet))
|
return Err(TunnResult::WriteToNetwork(cookie_packet));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -88,11 +88,11 @@ impl ReceivingKeyCounterValidator {
|
||||||
fn will_accept(&self, counter: u64) -> Result<(), WireGuardError> {
|
fn will_accept(&self, counter: u64) -> Result<(), WireGuardError> {
|
||||||
if counter >= self.next {
|
if counter >= self.next {
|
||||||
// As long as the counter is growing no replay took place for sure
|
// As long as the counter is growing no replay took place for sure
|
||||||
return Ok(())
|
return Ok(());
|
||||||
}
|
}
|
||||||
if counter + N_BITS < self.next {
|
if counter + N_BITS < self.next {
|
||||||
// Drop if too far back
|
// Drop if too far back
|
||||||
return Err(WireGuardError::InvalidCounter)
|
return Err(WireGuardError::InvalidCounter);
|
||||||
}
|
}
|
||||||
if !self.check_bit(counter) {
|
if !self.check_bit(counter) {
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -107,22 +107,22 @@ impl ReceivingKeyCounterValidator {
|
||||||
fn mark_did_receive(&mut self, counter: u64) -> Result<(), WireGuardError> {
|
fn mark_did_receive(&mut self, counter: u64) -> Result<(), WireGuardError> {
|
||||||
if counter + N_BITS < self.next {
|
if counter + N_BITS < self.next {
|
||||||
// Drop if too far back
|
// Drop if too far back
|
||||||
return Err(WireGuardError::InvalidCounter)
|
return Err(WireGuardError::InvalidCounter);
|
||||||
}
|
}
|
||||||
if counter == self.next {
|
if counter == self.next {
|
||||||
// Usually the packets arrive in order, in that case we simply mark the bit and
|
// Usually the packets arrive in order, in that case we simply mark the bit and
|
||||||
// increment the counter
|
// increment the counter
|
||||||
self.set_bit(counter);
|
self.set_bit(counter);
|
||||||
self.next += 1;
|
self.next += 1;
|
||||||
return Ok(())
|
return Ok(());
|
||||||
}
|
}
|
||||||
if counter < self.next {
|
if counter < self.next {
|
||||||
// A packet arrived out of order, check if it is valid, and mark
|
// A packet arrived out of order, check if it is valid, and mark
|
||||||
if self.check_bit(counter) {
|
if self.check_bit(counter) {
|
||||||
return Err(WireGuardError::InvalidCounter)
|
return Err(WireGuardError::InvalidCounter);
|
||||||
}
|
}
|
||||||
self.set_bit(counter);
|
self.set_bit(counter);
|
||||||
return Ok(())
|
return Ok(());
|
||||||
}
|
}
|
||||||
// Packets where dropped, or maybe reordered, skip them and mark unused
|
// Packets where dropped, or maybe reordered, skip them and mark unused
|
||||||
if counter - self.next >= N_BITS {
|
if counter - self.next >= N_BITS {
|
||||||
|
|
@ -247,7 +247,7 @@ impl Session {
|
||||||
panic!("The destination buffer is too small");
|
panic!("The destination buffer is too small");
|
||||||
}
|
}
|
||||||
if packet.receiver_idx != self.receiving_index {
|
if packet.receiver_idx != self.receiving_index {
|
||||||
return Err(WireGuardError::WrongIndex)
|
return Err(WireGuardError::WrongIndex);
|
||||||
}
|
}
|
||||||
// Don't reuse counters, in case this is a replay attack we want to quickly
|
// Don't reuse counters, in case this is a replay attack we want to quickly
|
||||||
// check the counter without running expensive decryption
|
// check the counter without running expensive decryption
|
||||||
|
|
|
||||||
|
|
@ -190,7 +190,7 @@ impl Tunnel {
|
||||||
|
|
||||||
{
|
{
|
||||||
if self.handshake.is_expired() {
|
if self.handshake.is_expired() {
|
||||||
return TunnResult::Err(WireGuardError::ConnectionExpired)
|
return TunnResult::Err(WireGuardError::ConnectionExpired);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear cookie after COOKIE_EXPIRATION_TIME
|
// Clear cookie after COOKIE_EXPIRATION_TIME
|
||||||
|
|
@ -206,7 +206,7 @@ impl Tunnel {
|
||||||
tracing::error!("CONNECTION_EXPIRED(REJECT_AFTER_TIME * 3)");
|
tracing::error!("CONNECTION_EXPIRED(REJECT_AFTER_TIME * 3)");
|
||||||
self.handshake.set_expired();
|
self.handshake.set_expired();
|
||||||
self.clear_all();
|
self.clear_all();
|
||||||
return TunnResult::Err(WireGuardError::ConnectionExpired)
|
return TunnResult::Err(WireGuardError::ConnectionExpired);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(time_init_sent) = self.handshake.timer() {
|
if let Some(time_init_sent) = self.handshake.timer() {
|
||||||
|
|
@ -219,7 +219,7 @@ impl Tunnel {
|
||||||
tracing::error!("CONNECTION_EXPIRED(REKEY_ATTEMPT_TIME)");
|
tracing::error!("CONNECTION_EXPIRED(REKEY_ATTEMPT_TIME)");
|
||||||
self.handshake.set_expired();
|
self.handshake.set_expired();
|
||||||
self.clear_all();
|
self.clear_all();
|
||||||
return TunnResult::Err(WireGuardError::ConnectionExpired)
|
return TunnResult::Err(WireGuardError::ConnectionExpired);
|
||||||
}
|
}
|
||||||
|
|
||||||
if time_init_sent.elapsed() >= REKEY_TIMEOUT {
|
if time_init_sent.elapsed() >= REKEY_TIMEOUT {
|
||||||
|
|
@ -299,11 +299,11 @@ impl Tunnel {
|
||||||
}
|
}
|
||||||
|
|
||||||
if handshake_initiation_required {
|
if handshake_initiation_required {
|
||||||
return self.format_handshake_initiation(dst, true)
|
return self.format_handshake_initiation(dst, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if keepalive_required {
|
if keepalive_required {
|
||||||
return self.encapsulate(&[], dst)
|
return self.encapsulate(&[], dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
TunnResult::Done
|
TunnResult::Done
|
||||||
|
|
|
||||||
|
|
@ -74,7 +74,7 @@ impl PeerPcb {
|
||||||
Ok(l) => l,
|
Ok(l) => l,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::error!("{}: error reading from socket: {:?}", rid, e);
|
log::error!("{}: error reading from socket: {:?}", rid, e);
|
||||||
continue
|
continue;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let mut res_dat = &res_buf[..len];
|
let mut res_dat = &res_buf[..len];
|
||||||
|
|
@ -90,7 +90,7 @@ impl PeerPcb {
|
||||||
TunnResult::Done => break,
|
TunnResult::Done => break,
|
||||||
TunnResult::Err(e) => {
|
TunnResult::Err(e) => {
|
||||||
tracing::error!(message = "Decapsulate error", error = ?e);
|
tracing::error!(message = "Decapsulate error", error = ?e);
|
||||||
break
|
break;
|
||||||
}
|
}
|
||||||
TunnResult::WriteToNetwork(packet) => {
|
TunnResult::WriteToNetwork(packet) => {
|
||||||
tracing::debug!("WriteToNetwork: {:?}", packet);
|
tracing::debug!("WriteToNetwork: {:?}", packet);
|
||||||
|
|
@ -98,17 +98,17 @@ impl PeerPcb {
|
||||||
socket.send(packet).await?;
|
socket.send(packet).await?;
|
||||||
tracing::debug!("WriteToNetwork done");
|
tracing::debug!("WriteToNetwork done");
|
||||||
res_dat = &[];
|
res_dat = &[];
|
||||||
continue
|
continue;
|
||||||
}
|
}
|
||||||
TunnResult::WriteToTunnelV4(packet, addr) => {
|
TunnResult::WriteToTunnelV4(packet, addr) => {
|
||||||
tracing::debug!("WriteToTunnelV4: {:?}, {:?}", packet, addr);
|
tracing::debug!("WriteToTunnelV4: {:?}, {:?}", packet, addr);
|
||||||
tun_interface.read().await.send(packet).await?;
|
tun_interface.read().await.send(packet).await?;
|
||||||
break
|
break;
|
||||||
}
|
}
|
||||||
TunnResult::WriteToTunnelV6(packet, addr) => {
|
TunnResult::WriteToTunnelV6(packet, addr) => {
|
||||||
tracing::debug!("WriteToTunnelV6: {:?}, {:?}", packet, addr);
|
tracing::debug!("WriteToTunnelV6: {:?}, {:?}", packet, addr);
|
||||||
tun_interface.read().await.send(packet).await?;
|
tun_interface.read().await.send(packet).await?;
|
||||||
break
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ impl TunInterface {
|
||||||
Ok(result) => return result,
|
Ok(result) => return result,
|
||||||
Err(_would_block) => {
|
Err(_would_block) => {
|
||||||
tracing::debug!("WouldBlock");
|
tracing::debug!("WouldBlock");
|
||||||
continue
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ impl TunInterface {
|
||||||
#[throws]
|
#[throws]
|
||||||
#[instrument]
|
#[instrument]
|
||||||
pub fn new_with_options(options: TunOptions) -> TunInterface {
|
pub fn new_with_options(options: TunOptions) -> TunInterface {
|
||||||
let ti = if options.tun_retrieve{
|
let ti = if options.tun_retrieve {
|
||||||
TunInterface::retrieve().ok_or(Error::new(
|
TunInterface::retrieve().ok_or(Error::new(
|
||||||
std::io::ErrorKind::NotFound,
|
std::io::ErrorKind::NotFound,
|
||||||
"No tun interface found",
|
"No tun interface found",
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue