wg: bounded channels (#4037)

* Make peer event channel bounded

* Make tun task channel bounded
This commit is contained in:
Jon Häggblad
2023-10-24 16:04:27 +02:00
committed by GitHub
parent 732720c306
commit d94a0454ae
6 changed files with 31 additions and 30 deletions
+5 -5
View File
@@ -11,12 +11,12 @@ use crate::event::Event;
// Channels that are used to communicate with the various tunnels
#[derive(Clone)]
pub struct PeerEventSender(mpsc::UnboundedSender<Event>);
pub(crate) struct PeerEventReceiver(mpsc::UnboundedReceiver<Event>);
pub struct PeerEventSender(mpsc::Sender<Event>);
pub(crate) struct PeerEventReceiver(mpsc::Receiver<Event>);
impl PeerEventSender {
pub(crate) fn send(&self, event: Event) -> Result<(), mpsc::error::SendError<Event>> {
self.0.send(event)
pub(crate) async fn send(&self, event: Event) -> Result<(), mpsc::error::SendError<Event>> {
self.0.send(event).await
}
}
@@ -27,7 +27,7 @@ impl PeerEventReceiver {
}
pub(crate) fn peer_event_channel() -> (PeerEventSender, PeerEventReceiver) {
let (tx, rx) = mpsc::unbounded_channel();
let (tx, rx) = mpsc::channel(16);
(PeerEventSender(tx), PeerEventReceiver(rx))
}
+2 -2
View File
@@ -33,10 +33,10 @@ pub async fn start_wireguard(
gateway_client_registry: Arc<GatewayClientRegistry>,
) -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> {
// We can either index peers by their IP like standard wireguard
let peers_by_ip = Arc::new(std::sync::Mutex::new(network_table::NetworkTable::new()));
let peers_by_ip = Arc::new(tokio::sync::Mutex::new(network_table::NetworkTable::new()));
// ... or by their tunnel tag, which is a random number assigned to them
let peers_by_tag = Arc::new(std::sync::Mutex::new(wg_tunnel::PeersByTag::new()));
let peers_by_tag = Arc::new(tokio::sync::Mutex::new(wg_tunnel::PeersByTag::new()));
// Start the tun device that is used to relay traffic outbound
let (tun, tun_task_tx, tun_task_response_rx) = tun_device::TunDevice::new(peers_by_ip.clone());
+6 -6
View File
@@ -32,14 +32,14 @@ pub(crate) struct PacketRelayer {
tun_task_response_rx: TunTaskResponseRx,
// After receiving from the tun device, relay back to the correct tunnel
peers_by_tag: Arc<std::sync::Mutex<HashMap<u64, PeerEventSender>>>,
peers_by_tag: Arc<tokio::sync::Mutex<HashMap<u64, PeerEventSender>>>,
}
impl PacketRelayer {
pub(crate) fn new(
tun_task_tx: TunTaskTx,
tun_task_response_rx: TunTaskResponseRx,
peers_by_tag: Arc<std::sync::Mutex<HashMap<u64, PeerEventSender>>>,
peers_by_tag: Arc<tokio::sync::Mutex<HashMap<u64, PeerEventSender>>>,
) -> (Self, PacketRelaySender) {
let (packet_tx, packet_rx) = packet_relay_channel();
(
@@ -58,13 +58,13 @@ impl PacketRelayer {
tokio::select! {
Some((tag, packet)) = self.packet_rx.0.recv() => {
log::info!("Sent packet to tun device with tag: {tag}");
self.tun_task_tx.send((tag, packet)).unwrap();
self.tun_task_tx.send((tag, packet)).await.tap_err(|e| log::error!("{e}")).ok();
},
Some((tag, packet)) = self.tun_task_response_rx.recv() => {
log::info!("Received response from tun device with tag: {tag}");
self.peers_by_tag.lock().unwrap().get(&tag).and_then(|tx| {
tx.send(Event::Ip(packet.into())).tap_err(|e| log::error!("{e}")).ok()
});
if let Some(tx) = self.peers_by_tag.lock().await.get(&tag) {
tx.send(Event::Ip(packet.into())).await.tap_err(|e| log::error!("{e}")).ok();
}
}
}
}
@@ -43,7 +43,7 @@ pub struct TunDevice {
tun_task_response_tx: TunTaskResponseTx,
// The routing table, as how wireguard does it
peers_by_ip: Arc<std::sync::Mutex<PeersByIp>>,
peers_by_ip: Arc<tokio::sync::Mutex<PeersByIp>>,
// This is an alternative to the routing table, where we just match outgoing source IP with
// incoming destination IP.
@@ -52,7 +52,7 @@ pub struct TunDevice {
impl TunDevice {
pub fn new(
peers_by_ip: Arc<std::sync::Mutex<PeersByIp>>,
peers_by_ip: Arc<tokio::sync::Mutex<PeersByIp>>,
) -> (Self, TunTaskTx, TunTaskResponseRx) {
let tun = setup_tokio_tun_device(
format!("{TUN_BASE_NAME}%d").as_str(),
@@ -123,14 +123,12 @@ impl TunDevice {
// This is how wireguard does it, by consulting the AllowedIPs table.
if false {
let Ok(peers) = self.peers_by_ip.lock() else {
log::error!("Failed to lock peers_by_ip, aborting tun device read");
return;
};
let peers = self.peers_by_ip.lock().await;
if let Some(peer_tx) = peers.longest_match(dst_addr).map(|(_, tx)| tx) {
log::info!("Forward packet to wg tunnel");
peer_tx
.send(Event::Ip(packet.to_vec().into()))
.await
.tap_err(|err| log::error!("{err}"))
.ok();
return;
+5 -5
View File
@@ -3,15 +3,15 @@ use tokio::sync::mpsc;
pub(crate) type TunTaskPayload = (u64, Vec<u8>);
#[derive(Clone)]
pub struct TunTaskTx(mpsc::UnboundedSender<TunTaskPayload>);
pub(crate) struct TunTaskRx(mpsc::UnboundedReceiver<TunTaskPayload>);
pub struct TunTaskTx(mpsc::Sender<TunTaskPayload>);
pub(crate) struct TunTaskRx(mpsc::Receiver<TunTaskPayload>);
impl TunTaskTx {
pub(crate) fn send(
pub(crate) async fn send(
&self,
data: TunTaskPayload,
) -> Result<(), tokio::sync::mpsc::error::SendError<TunTaskPayload>> {
self.0.send(data)
self.0.send(data).await
}
}
@@ -22,7 +22,7 @@ impl TunTaskRx {
}
pub(crate) fn tun_task_channel() -> (TunTaskTx, TunTaskRx) {
let (tun_task_tx, tun_task_rx) = tokio::sync::mpsc::unbounded_channel();
let (tun_task_tx, tun_task_rx) = tokio::sync::mpsc::channel(16);
(TunTaskTx(tun_task_tx), TunTaskRx(tun_task_rx))
}
+9 -6
View File
@@ -50,10 +50,10 @@ pub struct WgUdpListener {
registered_peers: RegisteredPeers,
// The routing table, as defined by wireguard
peers_by_ip: Arc<std::sync::Mutex<PeersByIp>>,
peers_by_ip: Arc<tokio::sync::Mutex<PeersByIp>>,
// ... or alternatively we can map peers by their tag
peers_by_tag: Arc<std::sync::Mutex<PeersByTag>>,
peers_by_tag: Arc<tokio::sync::Mutex<PeersByTag>>,
// The UDP socket to the peer
udp: Arc<UdpSocket>,
@@ -70,8 +70,8 @@ pub struct WgUdpListener {
impl WgUdpListener {
pub async fn new(
packet_tx: PacketRelaySender,
peers_by_ip: Arc<std::sync::Mutex<PeersByIp>>,
peers_by_tag: Arc<std::sync::Mutex<PeersByTag>>,
peers_by_ip: Arc<tokio::sync::Mutex<PeersByIp>>,
peers_by_tag: Arc<tokio::sync::Mutex<PeersByTag>>,
gateway_client_registry: Arc<GatewayClientRegistry>,
) -> Result<Self, Box<dyn std::error::Error + Send + Sync + 'static>> {
let wg_address = SocketAddr::new(WG_ADDRESS.parse().unwrap(), WG_PORT);
@@ -143,6 +143,7 @@ impl WgUdpListener {
log::info!("udp: received {len} bytes from {addr} from known peer");
peer_tx
.send(Event::Wg(buf[..len].to_vec().into()))
.await
.tap_err(|e| log::error!("{e}"))
.ok();
continue;
@@ -186,6 +187,7 @@ impl WgUdpListener {
// We found the peer as connected, even though the addr was not known
log::info!("udp: received {len} bytes from {addr} which is a known peer with unknown addr");
peer_tx.send(Event::WgVerified(buf[..len].to_vec().into()))
.await
.tap_err(|err| log::error!("{err}"))
.ok();
} else {
@@ -205,10 +207,11 @@ impl WgUdpListener {
self.packet_tx.clone(),
);
self.peers_by_ip.lock().unwrap().insert(registered_peer.allowed_ips, peer_tx.clone());
self.peers_by_tag.lock().unwrap().insert(tag, peer_tx.clone());
self.peers_by_ip.lock().await.insert(registered_peer.allowed_ips, peer_tx.clone());
self.peers_by_tag.lock().await.insert(tag, peer_tx.clone());
peer_tx.send(Event::Wg(buf[..len].to_vec().into()))
.await
.tap_err(|e| log::error!("{e}"))
.ok();