mirror of
https://github.com/EasyTier/EasyTier.git
synced 2026-05-07 02:09:06 +00:00
Add support for IPv6 within VPN (#1061)
* add flake.nix with nix based dev shell * add support for IPv6 * update thunk --------- Co-authored-by: sijie.sun <sijie.sun@smartx.com>
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
use std::{
|
||||
collections::BTreeSet,
|
||||
io,
|
||||
net::Ipv4Addr,
|
||||
net::{IpAddr, Ipv4Addr, Ipv6Addr},
|
||||
pin::Pin,
|
||||
sync::{Arc, Weak},
|
||||
task::{Context, Poll},
|
||||
@@ -25,7 +25,7 @@ use byteorder::WriteBytesExt as _;
|
||||
use bytes::{BufMut, BytesMut};
|
||||
use futures::{lock::BiLock, ready, SinkExt, Stream, StreamExt};
|
||||
use pin_project_lite::pin_project;
|
||||
use pnet::packet::ipv4::Ipv4Packet;
|
||||
use pnet::packet::{ipv4::Ipv4Packet, ipv6::Ipv6Packet};
|
||||
use tokio::{
|
||||
io::{AsyncRead, AsyncWrite, ReadBuf},
|
||||
sync::Mutex,
|
||||
@@ -434,12 +434,26 @@ impl VirtualNic {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn add_ipv6_route(&self, address: Ipv6Addr, cidr: u8) -> Result<(), Error> {
|
||||
let _g = self.global_ctx.net_ns.guard();
|
||||
self.ifcfg
|
||||
.add_ipv6_route(self.ifname(), address, cidr, None)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn remove_ip(&self, ip: Option<Ipv4Addr>) -> Result<(), Error> {
|
||||
let _g = self.global_ctx.net_ns.guard();
|
||||
self.ifcfg.remove_ip(self.ifname(), ip).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn remove_ipv6(&self, ip: Option<Ipv6Addr>) -> Result<(), Error> {
|
||||
let _g = self.global_ctx.net_ns.guard();
|
||||
self.ifcfg.remove_ipv6(self.ifname(), ip).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn add_ip(&self, ip: Ipv4Addr, cidr: i32) -> Result<(), Error> {
|
||||
let _g = self.global_ctx.net_ns.guard();
|
||||
self.ifcfg
|
||||
@@ -448,6 +462,14 @@ impl VirtualNic {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn add_ipv6(&self, ip: Ipv6Addr, cidr: i32) -> Result<(), Error> {
|
||||
let _g = self.global_ctx.net_ns.guard();
|
||||
self.ifcfg
|
||||
.add_ipv6_ip(self.ifname(), ip, cidr as u8)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get_ifcfg(&self) -> impl IfConfiguerTrait {
|
||||
IfConfiger {}
|
||||
}
|
||||
@@ -496,6 +518,20 @@ impl NicCtx {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn assign_ipv6_to_tun_device(&self, ipv6_addr: cidr::Ipv6Inet) -> Result<(), Error> {
|
||||
let nic = self.nic.lock().await;
|
||||
nic.link_up().await?;
|
||||
nic.remove_ipv6(None).await?;
|
||||
nic.add_ipv6(ipv6_addr.address(), ipv6_addr.network_length() as i32)
|
||||
.await?;
|
||||
#[cfg(any(target_os = "macos", target_os = "freebsd"))]
|
||||
{
|
||||
nic.add_ipv6_route(ipv6_addr.first_address(), ipv6_addr.network_length())
|
||||
.await?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn do_forward_nic_to_peers_ipv4(ret: ZCPacket, mgr: &PeerManager) {
|
||||
if let Some(ipv4) = Ipv4Packet::new(ret.payload()) {
|
||||
if ipv4.get_version() != 4 {
|
||||
@@ -509,16 +545,53 @@ impl NicCtx {
|
||||
);
|
||||
|
||||
// TODO: use zero-copy
|
||||
let send_ret = mgr.send_msg_ipv4(ret, dst_ipv4).await;
|
||||
let send_ret = mgr.send_msg_by_ip(ret, IpAddr::V4(dst_ipv4)).await;
|
||||
if send_ret.is_err() {
|
||||
tracing::trace!(?send_ret, "[USER_PACKET] send_msg_ipv4 failed")
|
||||
tracing::trace!(?send_ret, "[USER_PACKET] send_msg failed")
|
||||
}
|
||||
} else {
|
||||
tracing::warn!(?ret, "[USER_PACKET] not ipv4 packet");
|
||||
}
|
||||
}
|
||||
|
||||
fn do_forward_nic_to_peers(
|
||||
async fn do_forward_nic_to_peers_ipv6(ret: ZCPacket, mgr: &PeerManager) {
|
||||
if let Some(ipv6) = Ipv6Packet::new(ret.payload()) {
|
||||
if ipv6.get_version() != 6 {
|
||||
tracing::info!("[USER_PACKET] not ipv6 packet: {:?}", ipv6);
|
||||
return;
|
||||
}
|
||||
let dst_ipv6 = ipv6.get_destination();
|
||||
tracing::trace!(
|
||||
?ret,
|
||||
"[USER_PACKET] recv new packet from tun device and forward to peers."
|
||||
);
|
||||
|
||||
// TODO: use zero-copy
|
||||
let send_ret = mgr.send_msg_by_ip(ret, IpAddr::V6(dst_ipv6)).await;
|
||||
if send_ret.is_err() {
|
||||
tracing::trace!(?send_ret, "[USER_PACKET] send_msg failed")
|
||||
}
|
||||
} else {
|
||||
tracing::warn!(?ret, "[USER_PACKET] not ipv6 packet");
|
||||
}
|
||||
}
|
||||
|
||||
async fn do_forward_nic_to_peers(ret: ZCPacket, mgr: &PeerManager) {
|
||||
let payload = ret.payload();
|
||||
if payload.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
match payload[0] >> 4 {
|
||||
4 => Self::do_forward_nic_to_peers_ipv4(ret, mgr).await,
|
||||
6 => Self::do_forward_nic_to_peers_ipv6(ret, mgr).await,
|
||||
_ => {
|
||||
tracing::warn!(?ret, "[USER_PACKET] unknown IP version");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn do_forward_nic_to_peers_task(
|
||||
&mut self,
|
||||
mut stream: Pin<Box<dyn ZCPacketStream>>,
|
||||
) -> Result<(), Error> {
|
||||
@@ -532,7 +605,7 @@ impl NicCtx {
|
||||
tracing::error!("read from nic failed: {:?}", ret);
|
||||
break;
|
||||
}
|
||||
Self::do_forward_nic_to_peers_ipv4(ret.unwrap(), mgr.as_ref()).await;
|
||||
Self::do_forward_nic_to_peers(ret.unwrap(), mgr.as_ref()).await;
|
||||
}
|
||||
panic!("nic stream closed");
|
||||
});
|
||||
@@ -647,7 +720,7 @@ impl NicCtx {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn run(&mut self, ipv4_addr: cidr::Ipv4Inet) -> Result<(), Error> {
|
||||
pub async fn run(&mut self, ipv4_addr: Option<cidr::Ipv4Inet>, ipv6_addr: Option<cidr::Ipv6Inet>) -> Result<(), Error> {
|
||||
let tunnel = {
|
||||
let mut nic = self.nic.lock().await;
|
||||
match nic.create_dev().await {
|
||||
@@ -681,10 +754,19 @@ impl NicCtx {
|
||||
|
||||
let (stream, sink) = tunnel.split();
|
||||
|
||||
self.do_forward_nic_to_peers(stream)?;
|
||||
self.do_forward_nic_to_peers_task(stream)?;
|
||||
self.do_forward_peers_to_nic(sink);
|
||||
|
||||
self.assign_ipv4_to_tun_device(ipv4_addr).await?;
|
||||
// Assign IPv4 address if provided
|
||||
if let Some(ipv4_addr) = ipv4_addr {
|
||||
self.assign_ipv4_to_tun_device(ipv4_addr).await?;
|
||||
}
|
||||
|
||||
// Assign IPv6 address if provided
|
||||
if let Some(ipv6_addr) = ipv6_addr {
|
||||
self.assign_ipv6_to_tun_device(ipv6_addr).await?;
|
||||
}
|
||||
|
||||
self.run_proxy_cidrs_route_updater().await?;
|
||||
|
||||
Ok(())
|
||||
@@ -710,7 +792,7 @@ impl NicCtx {
|
||||
|
||||
let (stream, sink) = tunnel.split();
|
||||
|
||||
self.do_forward_nic_to_peers(stream)?;
|
||||
self.do_forward_nic_to_peers_task(stream)?;
|
||||
self.do_forward_peers_to_nic(sink);
|
||||
|
||||
Ok(())
|
||||
|
||||
Reference in New Issue
Block a user