Open
Conversation
161c06c to
7d4dc7b
Compare
7d4dc7b to
e0e8d2e
Compare
9689483 to
9737ac8
Compare
dlon
commented
Apr 29, 2026
The multihop-router demonstrates how this can be used.
Packets whose source IPs overlap with those of the inner tunnel must be blocked, since there's only a single TUN device. Otherwise, the other tunnel can impersonate the inner tunnel.
dlon
commented
May 4, 2026
| pub fn payload(&self) -> Option<&[u8]> { | ||
| match self.as_v4_or_v6()? { | ||
| Either::Left(ipv4) => ipv4.payload(), | ||
| Either::Right(ipv6) => Some(&ipv6.payload), |
Member
Author
There was a problem hiding this comment.
Check if ipv6.payload works when there are extension headers.
dlon
commented
May 4, 2026
| /// Create a new `MergingIpRecv` that merges packets from `a` and `b`. | ||
| /// | ||
| /// `pool` is used as the packet buffer pool when receiving from `b`. | ||
| pub fn new(a: A, b: B, pool: PacketBufPool) -> Self { |
Member
Author
There was a problem hiding this comment.
Can we get rid of the extra pool?
dlon
commented
May 4, 2026
| } | ||
|
|
||
| fn mtu(&self) -> MtuWatcher { | ||
| // TODO |
dlon
commented
May 4, 2026
| }; | ||
|
|
||
| if tx.send(packet).await.is_err() { | ||
| // TODO: Should we only stop if all channels have been dropped? |
Member
Author
There was a problem hiding this comment.
This is probably fine for now.
dlon
commented
May 4, 2026
| Ok(packets) => packets, | ||
| Err(e) => { | ||
| log::error!("TUN router recv error: {e}"); | ||
| // TODO: Must stop if TUN goes down, but is this always unrecoverable? |
Member
Author
There was a problem hiding this comment.
We could use is_fatal_tun_error here.
dlon
commented
May 4, 2026
| .into(); | ||
| } | ||
| IpNextProtocol::Tcp => { | ||
| // TCP checksum is at byte offset 16 in the TCP header. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This adds several adapters for chaining WireGuard devices: we can have an inner device whose encrypted traffic is routed through an outer device, but only for certain destination prefixes. I.e. multihop with "routing".
How it works (simplified)
See the
multihop-routerexample for actual usage.We essentially need NAT and routing. NAT to ensure that the IP address is translated between the tunnel IP address of the actual TUN device and any "inner" userspace device. Routing to determine whether packets written to the TUN device should first take a detour via the inner device, and same for incoming UDP packets.
Inbound packets
("Device" is fully in userspace here, not an actual TUN device.)
Otherwise, pass it to the TUN device.
This replaces the tunnel IP used for the inner VPN tunnel with the IP assigned to the TUN
device.
Outgoing packets
The tunnel IP is replaced (NAT'd) with that of the inner VPN. It is encapsulated by the
inner WG device.
This change is