This commit is contained in:
lbl
2026-02-10 18:20:39 +08:00
parent 71da72da34
commit b4301a8106
261 changed files with 20179 additions and 21547 deletions
+72
View File
@@ -0,0 +1,72 @@
use crate::context::{NetworkAddr, TrafficStats};
use crate::enhanced_tunnel::quic_over::quic_inbound::EnhancedQuicInbound;
use crate::nat::internal_nat::InternalNatInbound;
use crate::protocol::ip_packet_protocol::{HEAD_LENGTH, MsgType, NetPacket};
use crate::protocol::transmission::TransmissionBytes;
use crate::tun::enhanced_tun::EnhancedTunInbound;
use anyhow::{Context, bail};
use pnet_packet::ipv4::Ipv4Packet;
use std::net::Ipv4Addr;
#[derive(Clone)]
pub(crate) struct EnhancedInbound {
tun_data_inbound: EnhancedTunInbound,
quic_inbound: EnhancedQuicInbound,
internal_nat_inbound: Option<InternalNatInbound>,
traffic_stats: TrafficStats,
}
impl EnhancedInbound {
pub fn new(
tun_data_inbound: EnhancedTunInbound,
quic_inbound: EnhancedQuicInbound,
internal_nat_inbound: Option<InternalNatInbound>,
traffic_stats: TrafficStats,
) -> Self {
Self {
tun_data_inbound,
quic_inbound,
internal_nat_inbound,
traffic_stats,
}
}
pub async fn inbound(
&self,
network_addr: &NetworkAddr,
msg_type: MsgType,
src: Ipv4Addr,
packet: NetPacket<TransmissionBytes>,
) -> anyhow::Result<()> {
let mut buf = packet.into_buffer();
self.traffic_stats.record_rx(src, buf.len() as u64);
buf.advance_head(HEAD_LENGTH)?;
match msg_type {
MsgType::Turn => {
if let Some(internal_nat_inbound) = self.internal_nat_inbound.as_ref() {
let Some(ipv4) = Ipv4Packet::new(&buf) else {
bail!("EnhancedInbound not ipv4")
};
let dest = ipv4.get_destination();
if dest != network_addr.ip && !network_addr.network().contains(&dest) {
internal_nat_inbound.send(&buf, network_addr).await?;
return Ok(());
}
}
self.tun_data_inbound.inbound(buf, network_addr).await?;
}
MsgType::Broadcast | MsgType::ExcludeBroadcast => {
self.tun_data_inbound.inbound(buf, network_addr).await?;
}
MsgType::Quic => {
let payload = buf.into_bytes().freeze();
self.quic_inbound
.inbound(payload, src)
.await
.context("inbound quic")?;
}
_ => {}
}
Ok(())
}
}
+75
View File
@@ -0,0 +1,75 @@
use crate::context::AppState;
use crate::enhanced_tunnel::inbound::EnhancedInbound;
use crate::enhanced_tunnel::outbound::EnhancedOutbound;
use crate::nat::SubnetExternalRoute;
use crate::nat::internal_nat::{InternalNatInbound, PortMappingManager};
use crate::port_mapping::PortMapping;
use crate::tun::enhanced_tun::EnhancedTunInbound;
use crate::tunnel_core::outbound::HybridOutbound;
use crate::utils::task_control::TaskGroup;
pub(crate) mod quic_over;
pub(crate) mod inbound;
pub(crate) mod outbound;
pub(crate) struct TunnelConfig {
pub mtu: u16,
pub password: Option<String>,
pub open_quic_client: bool,
pub port_mapping: Vec<PortMapping>,
}
pub(crate) struct TunnelComponents {
pub hybrid_outbound: HybridOutbound,
pub external_route: SubnetExternalRoute,
pub internal_nat_inbound: Option<InternalNatInbound>,
pub port_mapping_manager: PortMappingManager,
}
pub(crate) async fn enhanced_ipv4_tunnel(
app_state: AppState,
task_group: TaskGroup,
tun_data_sender: EnhancedTunInbound,
config: TunnelConfig,
components: TunnelComponents,
) -> anyhow::Result<(EnhancedInbound, Option<EnhancedOutbound>)> {
let password = config.password.unwrap_or_else(|| "password".to_string());
let tun = match &tun_data_sender {
EnhancedTunInbound::Tun(tun) => Some(tun.clone()),
EnhancedTunInbound::Nat(_) => None,
};
let (inbound, outbound) = quic_over::boot::quic_tunnel_start(
app_state.clone(),
task_group,
tun,
quic_over::boot::QuicTunnelConfig {
mtu: config.mtu,
password,
open_quic_client: config.open_quic_client,
port_mapping: config.port_mapping,
},
quic_over::boot::QuicTunnelComponents {
hybrid_outbound: components.hybrid_outbound.clone(),
external_route: components.external_route,
internal_nat_manager: components.internal_nat_inbound.clone(),
port_mapping_manager: components.port_mapping_manager,
},
)
.await?;
let enhanced_inbound = EnhancedInbound::new(
tun_data_sender,
inbound,
components.internal_nat_inbound,
app_state.traffic_stats.clone(),
);
let enhanced_outbound = outbound.map(|outbound| {
EnhancedOutbound::new(
app_state.network.clone(),
outbound,
components.hybrid_outbound,
)
});
Ok((enhanced_inbound, enhanced_outbound))
}
+68
View File
@@ -0,0 +1,68 @@
use crate::context::SharedNetworkAddr;
use crate::enhanced_tunnel::quic_over::quic_outbound::EnhancedQuicOutbound;
use crate::protocol::transmission::TransmissionBytes;
use crate::tunnel_core::outbound::HybridOutbound;
use pnet_packet::ipv4::Ipv4Packet;
pub struct EnhancedOutbound {
network: SharedNetworkAddr,
enhanced_quic_outbound: EnhancedQuicOutbound,
hybrid_outbound: HybridOutbound,
}
impl EnhancedOutbound {
pub fn new(
network: SharedNetworkAddr,
enhanced_quic_outbound: EnhancedQuicOutbound,
hybrid_outbound: HybridOutbound,
) -> Self {
Self {
network,
enhanced_quic_outbound,
hybrid_outbound,
}
}
pub async fn ipv4_outbound(&self, data: TransmissionBytes) {
if data.is_empty() || data[0] >> 4 != 4 {
return;
}
if let Err(e) = self.ipv4_outbound_impl(data).await {
log::warn!("EnhancedOutbound error: {:?}", e);
}
}
async fn ipv4_outbound_impl(&self, data: TransmissionBytes) -> anyhow::Result<()> {
let Some(ipv4) = Ipv4Packet::new(data.as_ref()) else {
return Ok(());
};
let Some(net) = self.network.get() else {
return Ok(());
};
let src = ipv4.get_source();
let dest = ipv4.get_destination();
if dest == src || dest.is_unspecified() {
return Ok(());
}
if dest == net.gateway {
// 发送到网关
return self.hybrid_outbound.ipv4_gateway_outbound(net, data).await;
}
if dest.is_multicast() || dest == net.broadcast || dest.is_broadcast() {
// 广播
return self
.hybrid_outbound
.ipv4_broadcast_outbound(net, data)
.await;
}
if self
.enhanced_quic_outbound
.outbound(&net, data.as_ref())
.await
{
// 使用quic 通道传输
return Ok(());
}
// 使用通用通道传输
self.hybrid_outbound.ipv4_outbound(net, data).await
}
}
@@ -0,0 +1,200 @@
use crate::context::AppState;
use crate::enhanced_tunnel::quic_over::enhanced_io::enhanced_inbound::{
QuicDataInbound, create_enhanced_inbound,
};
use crate::enhanced_tunnel::quic_over::enhanced_io::enhanced_outbound::create_enhanced_outbound;
use crate::enhanced_tunnel::quic_over::enhanced_io::socket::ExtendedQuicSocket;
use crate::enhanced_tunnel::quic_over::quic_client::QuicTunnelClient;
use crate::enhanced_tunnel::quic_over::quic_inbound::EnhancedQuicInbound;
use crate::enhanced_tunnel::quic_over::quic_outbound::EnhancedQuicOutbound;
use crate::enhanced_tunnel::quic_over::{quic_client, quic_server};
use crate::nat::SubnetExternalRoute;
use crate::nat::internal_nat::{InternalNatInbound, PortMappingManager};
use crate::port_mapping::PortMapping;
use crate::tls;
use crate::tun::TunDataInbound;
use crate::tunnel_core::outbound::HybridOutbound;
use crate::utils::task_control::TaskGroup;
use anyhow::Context;
use quinn::congestion::BbrConfig;
use quinn::crypto::rustls::QuicServerConfig;
use quinn::{ClientConfig, Endpoint, EndpointConfig, TransportConfig, default_runtime};
use rustls::ServerConfig;
use sha2::{Digest, Sha256};
use std::io;
use std::sync::Arc;
use std::time::Duration;
use tcp_ip::{IpStackConfig, IpStackRecv};
pub(crate) struct QuicTunnelConfig {
pub mtu: u16,
pub password: String,
pub open_quic_client: bool,
pub port_mapping: Vec<PortMapping>,
}
pub(crate) struct QuicTunnelComponents {
pub hybrid_outbound: HybridOutbound,
pub external_route: SubnetExternalRoute,
pub internal_nat_manager: Option<InternalNatInbound>,
pub port_mapping_manager: PortMappingManager,
}
pub(crate) async fn quic_tunnel_start(
app_state: AppState,
task_group: TaskGroup,
tun_data_sender: Option<TunDataInbound>,
config: QuicTunnelConfig,
components: QuicTunnelComponents,
) -> anyhow::Result<(EnhancedQuicInbound, Option<EnhancedQuicOutbound>)> {
let ip_stack_config = IpStackConfig {
mtu: config.mtu,
..Default::default()
};
let (ip_stack, ip_socket, quic_outbound) = if let Some(tun_data_sender) = tun_data_sender {
let (ip_stack, ip_stack_send, ip_stack_recv) = tcp_ip::ip_stack(ip_stack_config)?;
let ip_socket = tcp_ip::ip::IpSocket::bind_all(None, ip_stack.clone()).await?;
let ip_socket = Arc::new(ip_socket);
task_group.spawn(ip_stack_recv_task(
ip_stack_recv,
app_state.clone(),
tun_data_sender,
));
let quic_outbound =
EnhancedQuicOutbound::new(config.open_quic_client, ip_stack_send, ip_stack.clone());
(Some(ip_stack), Some(ip_socket), Some(quic_outbound))
} else {
(None, None, None)
};
let (inbound, endpoint) = create_quic_endpoint(
config.password,
task_group.clone(),
components.hybrid_outbound,
)
.await?;
quic_server::server_listen(
&task_group,
endpoint.clone(),
ip_socket.clone(),
ip_stack.clone(),
components.internal_nat_manager,
components.port_mapping_manager,
)
.await;
if config.open_quic_client {
let quic_client =
QuicTunnelClient::new(app_state.clone(), endpoint, components.external_route);
// 客户端使用指纹验证
if let (Some(ip_stack), Some(ip_socket)) = (ip_stack, ip_socket) {
quic_client::create_client(
quic_client.clone(),
task_group.clone(),
ip_stack.clone(),
ip_socket,
)
.await;
}
if !config.port_mapping.is_empty() {
crate::port_mapping::port_mapping_start(&task_group, config.port_mapping, quic_client)
.await?;
}
} else if !config.port_mapping.is_empty() {
let quic_client =
QuicTunnelClient::new(app_state.clone(), endpoint, components.external_route);
crate::port_mapping::port_mapping_start(&task_group, config.port_mapping, quic_client)
.await?;
}
let quic_inbound = EnhancedQuicInbound::new(inbound);
Ok((quic_inbound, quic_outbound))
}
async fn create_quic_endpoint(
password: String,
task_group: TaskGroup,
hybrid_outbound: HybridOutbound,
) -> anyhow::Result<(QuicDataInbound, Endpoint)> {
let (cert, private_key) = crate::tls::cert::generate_deterministic_cert(&password)?;
let mut hasher = Sha256::new();
hasher.update(cert.as_ref());
let calculated_hash: [u8; 32] = hasher.finalize().into();
log::info!("QUIC Cert Fingerprint: {}", hex::encode(calculated_hash));
let outbound = create_enhanced_outbound(task_group.clone(), hybrid_outbound).await;
let (inbound, inbound_receiver) = create_enhanced_inbound();
let socket = ExtendedQuicSocket::new(inbound_receiver, outbound);
let server_config = ServerConfig::builder()
.with_no_client_auth()
.with_single_cert(vec![cert], private_key)
.context("TLS config error")?;
let server_crypto = QuicServerConfig::try_from(server_config)
.map_err(|e| anyhow::anyhow!("QUIC TLS config error: {:?}", e))?;
let server_config = quinn::ServerConfig::with_crypto(Arc::new(server_crypto));
// 替换运行时
let runtime = default_runtime().ok_or_else(|| io::Error::other("no async runtime found"))?;
let fingerprint_verifier = tls::verifier::FingerprintVerifier::new(calculated_hash);
let client_config = rustls::ClientConfig::builder()
.dangerous()
.with_custom_certificate_verifier(Arc::new(fingerprint_verifier))
.with_no_client_auth();
let mut client_config = ClientConfig::new(Arc::new(
quinn::crypto::rustls::QuicClientConfig::try_from(client_config)
.context("Failed to create QUIC client config")?,
));
client_config.transport_config(build_transport_config());
let mut endpoint_config = EndpointConfig::default();
endpoint_config.max_udp_payload_size(1300)?;
let mut endpoint = quinn::Endpoint::new_with_abstract_socket(
endpoint_config,
Some(server_config),
Arc::new(socket),
runtime,
)
.context("quic server create failed")?;
endpoint.set_default_client_config(client_config);
Ok((inbound, endpoint))
}
fn build_transport_config() -> Arc<TransportConfig> {
let mut transport = TransportConfig::default();
transport.congestion_controller_factory(Arc::new(BbrConfig::default()));
transport.keep_alive_interval(Some(Duration::from_secs(5)));
transport.max_idle_timeout(Some(Duration::from_secs(10).try_into().unwrap()));
Arc::new(transport)
}
async fn ip_stack_recv_task(
mut ip_stack_recv: IpStackRecv,
app_state: AppState,
tun_data_sender: TunDataInbound,
) {
let mut buf = vec![0u8; 1500];
loop {
let len = match ip_stack_recv.recv(&mut buf).await {
Ok(len) => len,
Err(e) => {
log::error!("IP stack recv error: {:?}", e);
break;
}
};
let Some(net) = app_state.get_network() else {
log::error!("not network");
break;
};
match tun_data_sender.send((&buf[..len]).into(), &net).await {
Ok(_) => {}
Err(e) => {
log::error!("IP stack send error: {:?}", e);
break;
}
}
}
}
@@ -0,0 +1,93 @@
use anyhow::anyhow;
use bytes::Bytes;
use parking_lot::Mutex;
use quinn::udp::RecvMeta;
use std::fmt::{Debug, Formatter};
use std::io::IoSliceMut;
use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4};
use std::sync::Arc;
use std::task::{Context, Poll};
use tokio::sync::mpsc::{Receiver, Sender};
#[derive(Clone)]
pub struct QuicInnerInboundReceiver {
receiver: Arc<Mutex<Receiver<(Bytes, Ipv4Addr)>>>,
}
#[derive(Clone)]
pub struct QuicDataInbound {
sender: Sender<(Bytes, Ipv4Addr)>,
}
impl QuicDataInbound {
pub async fn send(&self, data: Bytes, addr: Ipv4Addr) -> anyhow::Result<()> {
self.sender
.send((data, addr))
.await
.map_err(|_e| anyhow!("quic data inbound error"))
}
}
impl Debug for QuicInnerInboundReceiver {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_struct("EnhancedInbound").finish()
}
}
pub fn create_enhanced_inbound() -> (QuicDataInbound, QuicInnerInboundReceiver) {
let (sender, receiver) = tokio::sync::mpsc::channel(256);
(
QuicDataInbound { sender },
QuicInnerInboundReceiver::new(receiver),
)
}
impl QuicInnerInboundReceiver {
pub fn new(receiver: Receiver<(Bytes, Ipv4Addr)>) -> Self {
Self {
receiver: Arc::new(Mutex::new(receiver)),
}
}
pub fn poll_recv(
&self,
cx: &mut Context,
bufs: &mut [IoSliceMut<'_>],
meta: &mut [RecvMeta],
) -> Poll<std::io::Result<usize>> {
let mut guard = self.receiver.lock();
let rs = guard.poll_recv(cx);
drop(guard);
match rs {
Poll::Ready(Some((buf, ip))) => {
let (buf_mut, meta) = match (bufs.get_mut(0), meta.get_mut(0)) {
(Some(b), Some(m)) => (b, m),
_ => {
return Poll::Ready(Err(std::io::Error::new(
std::io::ErrorKind::InvalidInput,
"no buffer available",
)));
}
};
if buf_mut.len() < buf.len() {
return Poll::Ready(Err(std::io::Error::new(
std::io::ErrorKind::InvalidInput,
format!(
"buffer too small: need {}, got {}",
buf.len(),
buf_mut.len()
),
)));
}
buf_mut[..buf.len()].copy_from_slice(&buf);
meta.len = buf.len();
meta.stride = buf.len();
meta.addr = SocketAddr::V4(SocketAddrV4::new(ip, 10000));
Poll::Ready(Ok(1))
}
Poll::Ready(None) => Poll::Ready(Err(std::io::Error::new(
std::io::ErrorKind::BrokenPipe,
"inbound channel closed",
))),
Poll::Pending => Poll::Pending,
}
}
}
@@ -0,0 +1,89 @@
use crate::protocol::ip_packet_protocol::{HEAD_LENGTH, MsgType, NetPacket};
use crate::protocol::transmission::TransmissionBytes;
use crate::tunnel_core::outbound::HybridOutbound;
use crate::utils::task_control::TaskGroup;
use quinn::UdpPoller;
use std::fmt::{Debug, Formatter};
use std::io;
use std::net::Ipv4Addr;
use std::pin::Pin;
use std::task::{Context, Poll};
use tokio::sync::mpsc::{Sender, error::TrySendError};
use tokio_util::sync::PollSender;
#[derive(Clone)]
pub struct QuicInnerOutbound {
sender: Sender<(Ipv4Addr, NetPacket<TransmissionBytes>)>,
}
pub async fn create_enhanced_outbound(
task_group: TaskGroup,
hybrid_outbound: HybridOutbound,
) -> QuicInnerOutbound {
let (s, mut r) = tokio::sync::mpsc::channel(256);
task_group.spawn(async move {
while let Some((dst, packet)) = r.recv().await {
if let Err(e) = hybrid_outbound.outbound_raw(dst, packet).await {
log::debug!("outbound error: {e:?}, dst={dst}");
}
}
});
QuicInnerOutbound { sender: s }
}
impl QuicInnerOutbound {
pub fn try_outbound(&self, buf: &[u8], dest: Ipv4Addr) -> io::Result<()> {
let send = match self.sender.try_reserve() {
Ok(send) => send,
Err(TrySendError::Full(_)) => {
return Err(io::Error::new(
io::ErrorKind::WouldBlock,
"outbound channel full",
));
}
Err(TrySendError::Closed(_)) => {
return Err(io::Error::new(
io::ErrorKind::BrokenPipe,
"outbound channel closed",
));
}
};
let mut packet = NetPacket::new(TransmissionBytes::zeroed(HEAD_LENGTH + buf.len()))?;
packet.set_ttl(5);
packet.set_msg_type(MsgType::Quic);
packet.set_dest_id(dest.into());
packet.set_payload(buf)?;
send.send((dest, packet));
Ok(())
}
pub fn create_io_poller(&self) -> Pin<Box<dyn UdpPoller>> {
Box::pin(EnhancedOutboundPoller {
sender: PollSender::new(self.sender.clone()),
})
}
}
pub struct EnhancedOutboundPoller {
sender: PollSender<(Ipv4Addr, NetPacket<TransmissionBytes>)>,
}
impl Debug for EnhancedOutboundPoller {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_struct("EnhancedOutboundPoller").finish()
}
}
impl UdpPoller for EnhancedOutboundPoller {
fn poll_writable(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<io::Result<()>> {
match self.sender.poll_reserve(cx) {
Poll::Ready(Ok(_)) => {
self.sender.abort_send();
Poll::Ready(Ok(()))
}
Poll::Ready(Err(_e)) => Poll::Ready(Err(io::Error::new(
io::ErrorKind::BrokenPipe,
"outbound channel closed",
))),
Poll::Pending => Poll::Pending,
}
}
}
@@ -0,0 +1,3 @@
pub mod enhanced_inbound;
pub mod enhanced_outbound;
pub mod socket;
@@ -0,0 +1,55 @@
use crate::enhanced_tunnel::quic_over::enhanced_io::enhanced_inbound::QuicInnerInboundReceiver;
use crate::enhanced_tunnel::quic_over::enhanced_io::enhanced_outbound::QuicInnerOutbound;
use quinn::udp::{RecvMeta, Transmit};
use quinn::{AsyncUdpSocket, UdpPoller};
use std::fmt::{Debug, Formatter};
use std::io::IoSliceMut;
use std::net::{IpAddr, Ipv4Addr, SocketAddr, SocketAddrV4};
use std::pin::Pin;
use std::sync::Arc;
use std::task::{Context, Poll};
pub struct ExtendedQuicSocket {
inbound: QuicInnerInboundReceiver,
outbound: QuicInnerOutbound,
}
impl Debug for ExtendedQuicSocket {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_struct("QuicSocket").finish()
}
}
impl ExtendedQuicSocket {
pub fn new(inbound: QuicInnerInboundReceiver, outbound: QuicInnerOutbound) -> Self {
Self { inbound, outbound }
}
}
impl AsyncUdpSocket for ExtendedQuicSocket {
fn create_io_poller(self: Arc<Self>) -> Pin<Box<dyn UdpPoller>> {
self.outbound.create_io_poller()
}
fn try_send(&self, transmit: &Transmit) -> std::io::Result<()> {
let IpAddr::V4(dest) = transmit.destination.ip() else {
return Ok(());
};
self.outbound.try_outbound(transmit.contents, dest)
}
fn poll_recv(
&self,
cx: &mut Context,
bufs: &mut [IoSliceMut<'_>],
meta: &mut [RecvMeta],
) -> Poll<std::io::Result<usize>> {
self.inbound.poll_recv(cx, bufs, meta)
}
fn local_addr(&self) -> std::io::Result<SocketAddr> {
Ok(SocketAddr::V4(SocketAddrV4::new(
Ipv4Addr::new(127, 0, 0, 1),
10000,
)))
}
}
@@ -0,0 +1,7 @@
mod enhanced_io;
pub(crate) mod quic_client;
pub(crate) mod quic_inbound;
pub(crate) mod quic_outbound;
mod quic_server;
pub(crate) mod boot;
@@ -0,0 +1,309 @@
use crate::context::AppState;
use crate::nat::SubnetExternalRoute;
use crate::protocol::client_message::{
IpProxyHandshake, QuicProxyHandshake, TcpProxyHandshake, quic_proxy_handshake,
};
use crate::utils::task_control::TaskGroup;
use anyhow::{Context, bail};
use bytes::Bytes;
use futures::SinkExt;
use parking_lot::Mutex;
use pnet_packet::ip::IpNextHeaderProtocol;
use prost::Message;
use quinn::{Connection, Endpoint, RecvStream, SendStream};
use std::collections::HashMap;
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
use std::sync::Arc;
use tcp_ip::IpStack;
use tcp_ip::ip::IpSocket;
use tcp_ip::tcp::TcpStream;
use tokio::io::AsyncWriteExt;
use tokio::sync::OnceCell;
use tokio::sync::mpsc::Sender;
use tokio::sync::mpsc::error::TrySendError;
use tokio_util::codec::{FramedWrite, LengthDelimitedCodec};
#[derive(Clone)]
pub struct QuicTunnelClient {
app_state: AppState,
endpoint: Endpoint,
connection_map: Arc<Mutex<HashMap<Ipv4Addr, Arc<OnceCell<Connection>>>>>,
external_route: SubnetExternalRoute,
}
impl QuicTunnelClient {
pub fn new(
app_state: AppState,
endpoint: Endpoint,
external_route: SubnetExternalRoute,
) -> QuicTunnelClient {
Self {
app_state,
endpoint,
connection_map: Arc::new(Default::default()),
external_route,
}
}
pub async fn open_bi(&self, mut dest: Ipv4Addr) -> anyhow::Result<(SendStream, RecvStream)> {
let Some(net) = self.app_state.get_network() else {
bail!("no network found");
};
if !net.network().contains(&dest) {
if let Some(v) = self.external_route.route(&dest) {
dest = v;
} else {
bail!("invalid route found:{dest}");
}
}
let mut count = 0;
loop {
count += 1;
let cell = self
.connection_map
.lock()
.entry(dest)
.or_insert_with(|| Arc::new(OnceCell::new()))
.clone();
let connection = cell
.get_or_try_init(|| async {
self.endpoint
.connect(SocketAddr::new(dest.into(), 10000), "localhost")?
.await
.context("connect failed")
})
.await?;
return match connection.open_bi().await {
Ok(rs) => Ok(rs),
Err(e) => {
self.connection_map.lock().remove(&dest);
if count == 1 {
continue;
}
Err(e.into())
}
};
}
}
pub async fn open_uni(&self, mut dest: Ipv4Addr) -> anyhow::Result<SendStream> {
let Some(net) = self.app_state.get_network() else {
bail!("no network found");
};
if !net.network().contains(&dest) {
if let Some(v) = self.external_route.route(&dest) {
dest = v;
} else {
bail!("invalid route found:{dest}");
}
}
let mut count = 0;
loop {
count += 1;
let cell = self
.connection_map
.lock()
.entry(dest)
.or_insert_with(|| Arc::new(OnceCell::new()))
.clone();
let connection = cell
.get_or_try_init(|| async {
self.endpoint
.connect(SocketAddr::new(dest.into(), 10000), "localhost")?
.await
.context("connect failed")
})
.await?;
return match connection.open_uni().await {
Ok(rs) => Ok(rs),
Err(e) => {
self.connection_map.lock().remove(&dest);
if count == 1 {
continue;
}
Err(e.into())
}
};
}
}
}
pub(crate) async fn send_handshake(
send_stream: &mut SendStream,
handshake: QuicProxyHandshake,
) -> anyhow::Result<()> {
let handshake = handshake.encode_to_vec();
send_stream.write_u16(handshake.len() as u16).await?;
send_stream.write_all(&handshake).await?;
Ok(())
}
pub async fn create_client(
quic_client: QuicTunnelClient,
task_group: TaskGroup,
ip_stack: IpStack,
ip_socket: Arc<IpSocket>,
) {
task_group.spawn(tcp_listen(
task_group.clone(),
ip_stack.clone(),
quic_client.clone(),
));
task_group.spawn(ip_listen(task_group.clone(), ip_socket, quic_client));
}
async fn tcp_listen(
task_group: TaskGroup,
ip_stack: IpStack,
quic_tunnel_client: QuicTunnelClient,
) {
if let Err(e) = tcp_listen_impl(task_group, ip_stack, quic_tunnel_client).await {
log::error!("tcp_listen {e:?}");
}
}
async fn tcp_listen_impl(
task_group: TaskGroup,
ip_stack: IpStack,
quic_tunnel_client: QuicTunnelClient,
) -> anyhow::Result<()> {
let mut listener = tcp_ip::tcp::TcpListener::bind_all(ip_stack).await?;
loop {
let (tcp_stream, addr) = listener.accept().await?;
let quic_tunnel_client = quic_tunnel_client.clone();
task_group.spawn(async move {
if let Err(e) = tcp_stream_handle(tcp_stream, quic_tunnel_client).await {
log::error!("TCP stream handle failed with error: {e:?},addr={addr}");
}
});
}
}
async fn tcp_stream_handle(
tcp_stream: TcpStream,
quic_tunnel_client: QuicTunnelClient,
) -> anyhow::Result<()> {
// 连接方向是反过来的,因为自己充当目标做了tcp卸载
let SocketAddr::V4(peer_addr) = tcp_stream.local_addr()? else {
bail!("invalid IP address");
};
let SocketAddr::V4(local_addr) = tcp_stream.peer_addr()? else {
bail!("invalid IP address");
};
log::debug!("connect TCP stream {}->{}", local_addr, peer_addr);
let (mut send_stream, mut recv_stream) = quic_tunnel_client.open_bi(*peer_addr.ip()).await?;
let handshake = QuicProxyHandshake {
handshake: Some(quic_proxy_handshake::Handshake::Tcp(TcpProxyHandshake {
src_ip: (*local_addr.ip()).into(),
src_port: local_addr.port().into(),
dst_ip: (*peer_addr.ip()).into(),
dst_port: peer_addr.port().into(),
})),
};
send_handshake(&mut send_stream, handshake).await?;
let (mut tcp_w, mut tcp_r) = tcp_stream.split()?;
tokio::select! {
_ = tokio::io::copy(&mut recv_stream, &mut tcp_w) => {},
_ = tokio::io::copy(&mut tcp_r, &mut send_stream) => {},
}
log::debug!("disconnect TCP stream {}->{}", local_addr, peer_addr);
Ok(())
}
async fn ip_listen(
task_group: TaskGroup,
ip_socket: Arc<IpSocket>,
quic_tunnel_client: QuicTunnelClient,
) {
if let Err(e) = ip_listen_impl(task_group, ip_socket, quic_tunnel_client).await {
log::error!("ip_listen {e:?}");
}
}
#[derive(Eq, PartialEq, Hash, Copy, Clone, Debug)]
struct IpKey {
protocol: IpNextHeaderProtocol,
src: Ipv4Addr,
dest: Ipv4Addr,
}
async fn ip_listen_impl(
task_group: TaskGroup,
ip_socket: Arc<IpSocket>,
quic_tunnel_client: QuicTunnelClient,
) -> anyhow::Result<()> {
let mut buf = vec![0u8; 65536];
let dest_map = Arc::new(Mutex::new(HashMap::<IpKey, Sender<Bytes>>::new()));
loop {
let (len, protocol, src, dest) = ip_socket.recv_protocol_from_to(&mut buf).await?;
let (IpAddr::V4(src), IpAddr::V4(dest)) = (src, dest) else {
continue;
};
let key = IpKey {
protocol,
src,
dest,
};
let bytes = Bytes::copy_from_slice(&buf[..len]);
let tx = {
let mut map = dest_map.lock();
if let Some(tx) = map.get(&key) {
tx.clone()
} else {
let (tx, rx) = tokio::sync::mpsc::channel::<Bytes>(128);
spawn_dest_sender(task_group.clone(), key, rx, quic_tunnel_client.clone());
map.insert(key, tx.clone());
tx
}
};
if let Err(err) = tx.try_send(bytes) {
match err {
TrySendError::Full(_) => {}
TrySendError::Closed(_) => {
let mut map = dest_map.lock();
map.remove(&key);
}
}
}
}
}
fn spawn_dest_sender(
task_group: TaskGroup,
key: IpKey,
mut rx: tokio::sync::mpsc::Receiver<Bytes>,
quic_tunnel_client: QuicTunnelClient,
) {
log::info!("send ip({}) packet {}->{}", key.protocol, key.src, key.dest);
task_group.spawn(async move {
let result = async {
let mut send_stream = quic_tunnel_client.open_uni(key.dest).await?;
let handshake = QuicProxyHandshake {
handshake: Some(quic_proxy_handshake::Handshake::Ip(IpProxyHandshake {
ip_next_header_protocol: key.protocol.0 as _,
src_ip: key.src.into(),
dst_ip: key.dest.into(),
})),
};
send_handshake(&mut send_stream, handshake).await?;
let mut framed = FramedWrite::new(send_stream, LengthDelimitedCodec::new());
while let Some(pkt) = rx.recv().await {
framed.send(pkt).await?;
}
Ok::<(), anyhow::Error>(())
}
.await;
if let Err(e) = result {
log::error!("key {:?} sender task exit: {:?}", key, e);
}
});
}
@@ -0,0 +1,18 @@
use crate::enhanced_tunnel::quic_over::enhanced_io::enhanced_inbound::QuicDataInbound;
use bytes::Bytes;
use std::net::Ipv4Addr;
#[derive(Clone)]
pub struct EnhancedQuicInbound {
quic_data_inbound: QuicDataInbound,
}
impl EnhancedQuicInbound {
pub fn new(quic_data_inbound: QuicDataInbound) -> Self {
Self { quic_data_inbound }
}
pub async fn inbound(&self, data: Bytes, src: Ipv4Addr) -> anyhow::Result<()> {
self.quic_data_inbound.send(data, src).await?;
Ok(())
}
}
@@ -0,0 +1,94 @@
use crate::context::NetworkAddr;
use pnet_packet::Packet;
use pnet_packet::ip::IpNextHeaderProtocols;
use pnet_packet::ipv4::{Ipv4Flags, Ipv4Packet};
use pnet_packet::tcp::TcpFlags::{ACK, SYN};
use pnet_packet::tcp::TcpPacket;
use std::net::SocketAddr;
use tcp_ip::{IpStack, IpStackSend};
pub struct EnhancedQuicOutbound {
open_quic_client: bool,
ip_stack_send: IpStackSend,
ip_stack: IpStack,
}
impl EnhancedQuicOutbound {
pub fn new(open_quic_client: bool, ip_stack_send: IpStackSend, ip_stack: IpStack) -> Self {
Self {
open_quic_client,
ip_stack_send,
ip_stack,
}
}
pub async fn outbound(&self, _net: &NetworkAddr, data: &[u8]) -> bool {
let Some(ipv4) = Ipv4Packet::new(data) else {
return true;
};
if self.open_quic_client {
// 针对tcp 如果不是从IpStack建立的连接,则不使用IpStack解析
if ipv4.get_next_level_protocol() == IpNextHeaderProtocols::Tcp {
let more_fragments =
ipv4.get_flags() & Ipv4Flags::MoreFragments == Ipv4Flags::MoreFragments;
let offset = ipv4.get_fragment_offset();
let segmented = more_fragments || offset > 0;
if !segmented {
let Some(tcp) = TcpPacket::new(ipv4.payload()) else {
return true;
};
// 不是第一个包
if !(tcp.get_flags() & SYN == SYN && tcp.get_flags() & ACK != ACK) {
let local_addr =
SocketAddr::new(ipv4.get_source().into(), tcp.get_source());
let peer_addr =
SocketAddr::new(ipv4.get_destination().into(), tcp.get_destination());
// 在IpStack中找不到连接
if !self
.ip_stack
.has_tcp_connection(local_addr, peer_addr)
.unwrap_or(false)
&& !self
.ip_stack
.has_tcp_connection(peer_addr, local_addr)
.unwrap_or(false)
&& !self
.ip_stack
.has_tcp_half_open(peer_addr, local_addr)
.unwrap_or(false)
{
return false;
}
}
}
}
_ = self.ip_stack_send.send_ip_packet(data).await;
return true;
}
// 判断tcp流
if ipv4.get_next_level_protocol() == IpNextHeaderProtocols::Tcp {
let more_fragments =
ipv4.get_flags() & Ipv4Flags::MoreFragments == Ipv4Flags::MoreFragments;
let offset = ipv4.get_fragment_offset();
let segmented = more_fragments || offset > 0;
if !segmented && let Some(tcp) = TcpPacket::new(ipv4.payload()) {
// 如果对端使用IpStack连接了自己,则也需要原路回复
// 这是连接回复,所以方向是和流方向相反的
let peer_addr = SocketAddr::new(ipv4.get_source().into(), tcp.get_source());
let local_addr =
SocketAddr::new(ipv4.get_destination().into(), tcp.get_destination());
if self
.ip_stack
.has_tcp_connection(local_addr, peer_addr)
.unwrap_or(false)
{
_ = self.ip_stack_send.send_ip_packet(data).await;
return true;
}
}
}
false
}
}
@@ -0,0 +1,245 @@
use crate::nat::internal_nat::{InternalNatInbound, PortMappingManager};
use crate::protocol::client_message::QuicProxyHandshake;
use crate::protocol::client_message::quic_proxy_handshake::Handshake;
use crate::utils::task_control::TaskGroup;
use anyhow::{Context, bail};
use futures::StreamExt;
use pnet_packet::ip::IpNextHeaderProtocol;
use prost::Message;
use quinn::{Connection, Endpoint, RecvStream, SendStream};
use std::net::{Ipv4Addr, SocketAddr};
use std::sync::Arc;
use tcp_ip::IpStack;
use tcp_ip::ip::IpSocket;
use tokio::io::AsyncReadExt;
use tokio_util::codec::{FramedRead, LengthDelimitedCodec};
pub async fn server_listen(
task_group: &TaskGroup,
endpoint: Endpoint,
ip_socket: Option<Arc<IpSocket>>,
ip_stack: Option<IpStack>,
internal_nat_manager: Option<InternalNatInbound>,
port_mapping_manager: PortMappingManager,
) {
task_group.spawn(quic_endpoint_accept(
ip_stack,
task_group.clone(),
endpoint,
ip_socket,
internal_nat_manager,
port_mapping_manager,
));
}
async fn quic_endpoint_accept(
ip_stack: Option<IpStack>,
task_group: TaskGroup,
endpoint: Endpoint,
ip_socket: Option<Arc<IpSocket>>,
internal_nat_manager: Option<InternalNatInbound>,
port_mapping_manager: PortMappingManager,
) {
while let Some(connecting) = endpoint.accept().await {
let remote_addr = connecting.remote_address();
let task_group_clone = task_group.clone();
let ip_socket = ip_socket.clone();
let ip_stack = ip_stack.clone();
let internal_nat_manager = internal_nat_manager.clone();
let port_mapping_manager = port_mapping_manager.clone();
task_group.spawn(async move {
match connecting.await {
Ok(connection) => {
log::info!("QUIC connection: {}", remote_addr);
if let Err(e) = quic_accept(
ip_stack,
task_group_clone,
connection,
ip_socket,
internal_nat_manager,
port_mapping_manager,
)
.await
{
log::info!("quic close: {remote_addr},{e:?}",);
}
}
Err(e) => {
log::error!("connect: {:?},remote_addr={remote_addr}", e);
}
}
});
}
log::warn!("quic server closed");
}
async fn quic_accept(
ip_stack: Option<IpStack>,
task_group_clone: TaskGroup,
connection: Connection,
ip_socket: Option<Arc<IpSocket>>,
internal_nat_manager: Option<InternalNatInbound>,
port_mapping_manager: PortMappingManager,
) -> anyhow::Result<()> {
loop {
tokio::select! {
rs = connection.accept_bi()=>{
let (send_stream, recv_stream) = rs?;
let ip_stack = ip_stack.clone();
let internal_nat_manager = internal_nat_manager.clone();
let port_mapping_manager = port_mapping_manager.clone();
task_group_clone.spawn(async move {
if let Err(e) = quic_stream_bi_handle(ip_stack,send_stream, recv_stream,&internal_nat_manager,port_mapping_manager).await{
log::error!("quic_stream_bi_handle: {e:?}");
}
});
}
rs = connection.accept_uni()=>{
let recv_stream = rs?;
let ip_socket = ip_socket.clone();
let internal_nat_manager = internal_nat_manager.clone();
task_group_clone.spawn(async move {
if let Err(e) = quic_stream_uni_handle(recv_stream, ip_socket,&internal_nat_manager).await{
log::error!("quic_stream_uni_handle: {e:?}");
}
});
}
}
}
}
async fn quic_stream_bi_handle(
ip_stack: Option<IpStack>,
mut send_stream: SendStream,
mut recv_stream: RecvStream,
internal_nat_manager: &Option<InternalNatInbound>,
port_mapping_manager: PortMappingManager,
) -> anyhow::Result<()> {
let handshake = recv_handshake(&mut recv_stream).await?;
let Some(handshake) = handshake.handshake else {
return Ok(());
};
match handshake {
Handshake::Tcp(handshake) => {
let src = SocketAddr::new(
Ipv4Addr::from(handshake.src_ip).into(),
handshake.src_port as _,
);
let dst_ip = Ipv4Addr::from(handshake.dst_ip);
let dst = SocketAddr::new(dst_ip.into(), handshake.dst_port as _);
if src == dst {
bail!("tcp handshake failed, ip: {}", src);
}
log::debug!("accept TCP stream {src}->{dst}");
// 如果不是网段内的,并且启用了内置nat,则直接转发
if let Some(internal_nat_manager) = internal_nat_manager {
if internal_nat_manager.use_nat(&dst_ip) {
internal_nat_manager
.tcp_nat(recv_stream, send_stream, dst_ip, dst.port())
.await?;
return Ok(());
}
if internal_nat_manager.no_tun() {
return Ok(());
}
}
if let Some(ip_stack) = ip_stack {
let stream = tcp_ip::tcp::TcpStream::bind(ip_stack, src)?
.connect_to(dst)
.await?;
let (mut tcp_w, mut tcp_r) = stream.split()?;
tokio::select! {
_ = tokio::io::copy(&mut recv_stream, &mut tcp_w) => {},
_ = tokio::io::copy(&mut tcp_r, &mut send_stream) => {},
}
log::debug!("accept close TCP stream {src}->{dst}");
}
}
Handshake::Ip(_) => {}
Handshake::TcpPortMapping(handshake) => {
port_mapping_manager
.tcp_mapping(
recv_stream,
send_stream,
handshake.dst_host,
handshake.dst_port as _,
)
.await?;
}
Handshake::UdpPortMapping(handshake) => {
port_mapping_manager
.udp_mapping(
recv_stream,
send_stream,
handshake.dst_host,
handshake.dst_port as _,
)
.await?;
}
}
Ok(())
}
async fn recv_handshake(recv_stream: &mut RecvStream) -> anyhow::Result<QuicProxyHandshake> {
let len = recv_stream.read_u16().await?;
let mut buf = vec![0u8; len as usize];
recv_stream.read_exact(&mut buf).await?;
let handshake = QuicProxyHandshake::decode(&buf[..])?;
Ok(handshake)
}
async fn quic_stream_uni_handle(
mut recv_stream: RecvStream,
ip_socket: Option<Arc<IpSocket>>,
internal_nat_manager: &Option<InternalNatInbound>,
) -> anyhow::Result<()> {
let handshake = recv_handshake(&mut recv_stream).await?;
let Some(handshake) = handshake.handshake else {
return Ok(());
};
match handshake {
Handshake::Tcp(_) => {}
Handshake::Ip(handshake) => {
let ip_next_header_protocol =
IpNextHeaderProtocol::new(handshake.ip_next_header_protocol as _);
let src_ip = Ipv4Addr::from(handshake.src_ip);
let dest_ip = Ipv4Addr::from(handshake.dst_ip);
log::debug!("recv IP({ip_next_header_protocol}) packet {src_ip}->{dest_ip}");
let mut framed_read = FramedRead::new(recv_stream, LengthDelimitedCodec::new());
// 如果不是网段内的,并且启用了内置nat,则直接转发
if let Some(internal_nat_manager) = internal_nat_manager {
if internal_nat_manager.use_nat(&dest_ip) {
loop {
let buf = framed_read
.next()
.await
.context("receive quic stream failed")??;
internal_nat_manager
.send_ipv4_payload(ip_next_header_protocol, src_ip, dest_ip, buf)
.await?;
}
}
if internal_nat_manager.no_tun() {
return Ok(());
}
}
let Some(ip_socket) = ip_socket else {
return Ok(());
};
let src_ip = src_ip.into();
let dest_ip = dest_ip.into();
loop {
let buf = framed_read
.next()
.await
.context("receive quic stream failed")??;
ip_socket
.send_protocol_from_to(&buf, ip_next_header_protocol, src_ip, dest_ip)
.await?;
}
}
Handshake::TcpPortMapping(_) => {}
Handshake::UdpPortMapping(_) => {}
}
Ok(())
}