mirror of
https://mirror.suhoan.cn/https://github.com/EasyTier/EasyTier.git
synced 2025-12-14 21:57:24 +08:00
zero copy tunnel (#55)
make tunnel zero copy, for better performance. remove most of the locks in io path. introduce quic tunnel prepare for encryption
This commit is contained in:
@@ -116,7 +116,7 @@ pub fn add_ns_to_bridge(br_name: &str, ns_name: &str) {
|
||||
|
||||
pub fn enable_log() {
|
||||
let filter = tracing_subscriber::EnvFilter::builder()
|
||||
.with_default_directive(tracing::level_filters::LevelFilter::INFO.into())
|
||||
.with_default_directive(tracing::level_filters::LevelFilter::TRACE.into())
|
||||
.from_env()
|
||||
.unwrap()
|
||||
.add_directive("tarpc=error".parse().unwrap());
|
||||
|
||||
@@ -9,18 +9,18 @@ use super::*;
|
||||
|
||||
use crate::{
|
||||
common::{
|
||||
config::{ConfigLoader, NetworkIdentity, TomlConfigLoader},
|
||||
config::{ConfigLoader, NetworkIdentity, TomlConfigLoader, VpnPortalConfig},
|
||||
netns::{NetNS, ROOT_NETNS_NAME},
|
||||
},
|
||||
instance::instance::Instance,
|
||||
peers::tests::wait_for_condition,
|
||||
tunnels::{
|
||||
common::tests::_tunnel_pingpong_netns,
|
||||
ring_tunnel::RingTunnelConnector,
|
||||
tcp_tunnel::{TcpTunnelConnector, TcpTunnelListener},
|
||||
udp_tunnel::{UdpTunnelConnector, UdpTunnelListener},
|
||||
tunnel::{
|
||||
ring::RingTunnelConnector,
|
||||
tcp::TcpTunnelConnector,
|
||||
udp::UdpTunnelConnector,
|
||||
wireguard::{WgConfig, WgTunnelConnector},
|
||||
},
|
||||
vpn_portal::wireguard::get_wg_config_for_portal,
|
||||
};
|
||||
|
||||
pub fn prepare_linux_namespaces() {
|
||||
@@ -113,6 +113,26 @@ pub async fn init_three_node(proto: &str) -> Vec<Instance> {
|
||||
vec![inst1, inst2, inst3]
|
||||
}
|
||||
|
||||
async fn ping_test(from_netns: &str, target_ip: &str) -> bool {
|
||||
let _g = NetNS::new(Some(ROOT_NETNS_NAME.to_owned())).guard();
|
||||
let code = tokio::process::Command::new("ip")
|
||||
.args(&[
|
||||
"netns",
|
||||
"exec",
|
||||
from_netns,
|
||||
"ping",
|
||||
"-c",
|
||||
"1",
|
||||
"-W",
|
||||
"1",
|
||||
target_ip.to_string().as_str(),
|
||||
])
|
||||
.status()
|
||||
.await
|
||||
.unwrap();
|
||||
code.code().unwrap() == 0
|
||||
}
|
||||
|
||||
#[rstest::rstest]
|
||||
#[tokio::test]
|
||||
#[serial_test::serial]
|
||||
@@ -130,12 +150,20 @@ pub async fn basic_three_node_test(#[values("tcp", "udp", "wg")] proto: &str) {
|
||||
insts[2].peer_id(),
|
||||
insts[0].get_peer_manager().list_routes().await,
|
||||
);
|
||||
|
||||
wait_for_condition(
|
||||
|| async { ping_test("net_c", "10.144.144.1").await },
|
||||
Duration::from_secs(5),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
|
||||
#[rstest::rstest]
|
||||
#[tokio::test]
|
||||
#[serial_test::serial]
|
||||
pub async fn tcp_proxy_three_node_test(#[values("tcp", "udp", "wg")] proto: &str) {
|
||||
use crate::tunnel::{common::tests::_tunnel_pingpong_netns, tcp::TcpTunnelListener};
|
||||
|
||||
let insts = init_three_node(proto).await;
|
||||
|
||||
insts[2]
|
||||
@@ -187,25 +215,19 @@ pub async fn icmp_proxy_three_node_test(#[values("tcp", "udp", "wg")] proto: &st
|
||||
)
|
||||
.await;
|
||||
|
||||
// wait updater
|
||||
tokio::time::sleep(tokio::time::Duration::from_secs(6)).await;
|
||||
|
||||
// send ping with shell in net_a to net_d
|
||||
let _g = NetNS::new(Some(ROOT_NETNS_NAME.to_owned())).guard();
|
||||
let code = tokio::process::Command::new("ip")
|
||||
.args(&[
|
||||
"netns", "exec", "net_a", "ping", "-c", "1", "-W", "1", "10.1.2.4",
|
||||
])
|
||||
.status()
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(code.code().unwrap(), 0);
|
||||
wait_for_condition(
|
||||
|| async { ping_test("net_a", "10.1.2.4").await },
|
||||
Duration::from_secs(5),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
|
||||
#[rstest::rstest]
|
||||
#[tokio::test]
|
||||
#[serial_test::serial]
|
||||
pub async fn proxy_three_node_disconnect_test(#[values("tcp", "wg")] proto: &str) {
|
||||
use crate::tunnel::wireguard::{WgConfig, WgTunnelConnector};
|
||||
|
||||
let insts = init_three_node(proto).await;
|
||||
let mut inst4 = Instance::new(get_inst_config("inst4", Some("net_d"), "10.144.144.4"));
|
||||
if proto == "tcp" {
|
||||
@@ -266,6 +288,8 @@ pub async fn proxy_three_node_disconnect_test(#[values("tcp", "wg")] proto: &str
|
||||
#[tokio::test]
|
||||
#[serial_test::serial]
|
||||
pub async fn udp_proxy_three_node_test(#[values("tcp", "udp", "wg")] proto: &str) {
|
||||
use crate::tunnel::{common::tests::_tunnel_pingpong_netns, udp::UdpTunnelListener};
|
||||
|
||||
let insts = init_three_node(proto).await;
|
||||
|
||||
insts[2]
|
||||
@@ -389,21 +413,108 @@ pub async fn foreign_network_forward_nic_data() {
|
||||
)
|
||||
.await;
|
||||
|
||||
let _g = NetNS::new(Some(ROOT_NETNS_NAME.to_owned())).guard();
|
||||
let code = tokio::process::Command::new("ip")
|
||||
.args(&[
|
||||
"netns",
|
||||
"exec",
|
||||
"net_b",
|
||||
"ping",
|
||||
"-c",
|
||||
"1",
|
||||
"-W",
|
||||
"1",
|
||||
"10.144.145.2",
|
||||
])
|
||||
.status()
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(code.code().unwrap(), 0);
|
||||
wait_for_condition(
|
||||
|| async { ping_test("net_b", "10.144.145.2").await },
|
||||
Duration::from_secs(5),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
|
||||
use std::{net::SocketAddr, str::FromStr};
|
||||
|
||||
use defguard_wireguard_rs::{
|
||||
host::Peer, key::Key, net::IpAddrMask, InterfaceConfiguration, WGApi, WireguardInterfaceApi,
|
||||
};
|
||||
|
||||
fn run_wireguard_client(
|
||||
endpoint: SocketAddr,
|
||||
peer_public_key: Key,
|
||||
client_private_key: Key,
|
||||
allowed_ips: Vec<String>,
|
||||
client_ip: String,
|
||||
) -> Result<(), Box<dyn std::error::Error>> {
|
||||
// Create new API object for interface
|
||||
let ifname: String = if cfg!(target_os = "linux") || cfg!(target_os = "freebsd") {
|
||||
"wg0".into()
|
||||
} else {
|
||||
"utun3".into()
|
||||
};
|
||||
let wgapi = WGApi::new(ifname.clone(), false)?;
|
||||
|
||||
// create interface
|
||||
wgapi.create_interface()?;
|
||||
|
||||
// Peer secret key
|
||||
let mut peer = Peer::new(peer_public_key.clone());
|
||||
|
||||
log::info!("endpoint");
|
||||
// Peer endpoint and interval
|
||||
peer.endpoint = Some(endpoint);
|
||||
peer.persistent_keepalive_interval = Some(25);
|
||||
for ip in allowed_ips {
|
||||
peer.allowed_ips.push(IpAddrMask::from_str(ip.as_str())?);
|
||||
}
|
||||
|
||||
// interface configuration
|
||||
let interface_config = InterfaceConfiguration {
|
||||
name: ifname.clone(),
|
||||
prvkey: client_private_key.to_string(),
|
||||
address: client_ip,
|
||||
port: 12345,
|
||||
peers: vec![peer],
|
||||
};
|
||||
|
||||
#[cfg(not(windows))]
|
||||
wgapi.configure_interface(&interface_config)?;
|
||||
#[cfg(windows)]
|
||||
wgapi.configure_interface(&interface_config, &[])?;
|
||||
wgapi.configure_peer_routing(&interface_config.peers)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[serial_test::serial]
|
||||
pub async fn wireguard_vpn_portal() {
|
||||
let mut insts = init_three_node("tcp").await;
|
||||
let net_ns = NetNS::new(Some("net_d".into()));
|
||||
let _g = net_ns.guard();
|
||||
insts[2]
|
||||
.get_global_ctx()
|
||||
.config
|
||||
.set_vpn_portal_config(VpnPortalConfig {
|
||||
wireguard_listen: "0.0.0.0:22121".parse().unwrap(),
|
||||
client_cidr: "10.14.14.0/24".parse().unwrap(),
|
||||
});
|
||||
insts[2].run_vpn_portal().await.unwrap();
|
||||
|
||||
let net_ns = NetNS::new(Some("net_d".into()));
|
||||
let _g = net_ns.guard();
|
||||
let wg_cfg = get_wg_config_for_portal(&insts[2].get_global_ctx().get_network_identity());
|
||||
run_wireguard_client(
|
||||
"10.1.2.3:22121".parse().unwrap(),
|
||||
Key::try_from(wg_cfg.my_public_key()).unwrap(),
|
||||
Key::try_from(wg_cfg.peer_secret_key()).unwrap(),
|
||||
vec!["10.14.14.0/24".to_string(), "10.144.144.0/24".to_string()],
|
||||
"10.14.14.2".to_string(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// ping other node in network
|
||||
wait_for_condition(
|
||||
|| async { ping_test("net_d", "10.144.144.1").await },
|
||||
Duration::from_secs(5),
|
||||
)
|
||||
.await;
|
||||
wait_for_condition(
|
||||
|| async { ping_test("net_d", "10.144.144.2").await },
|
||||
Duration::from_secs(5),
|
||||
)
|
||||
.await;
|
||||
|
||||
// ping portal node
|
||||
wait_for_condition(
|
||||
|| async { ping_test("net_d", "10.144.144.3").await },
|
||||
Duration::from_secs(500),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user