Skip to content

Commit

Permalink
vmess udp
Browse files Browse the repository at this point in the history
  • Loading branch information
ibigbug committed Aug 22, 2023
1 parent ecc6ca6 commit 6d28be2
Show file tree
Hide file tree
Showing 9 changed files with 117 additions and 207 deletions.
2 changes: 1 addition & 1 deletion clash/tests/data/config/rules.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ rules:
- DOMAIN,google.com,ss
- SRC-IP-CIDR,192.168.1.1/24,DIRECT
- GEOIP,CN,DIRECT
- DST-PORT,80,DIRECT
- DST-PORT,53,plain-vmess
- SRC-PORT,7777,DIRECT
- MATCH, DIRECT
...
2 changes: 0 additions & 2 deletions clash_lib/src/app/dispatcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,6 @@ impl Dispatcher {
.get(outbound_name.as_str())
.expect(format!("unknown rule: {}", outbound_name).as_str());

info!("{} matched rule {}", sess, handler.name());

let mut outbound_handle_guard = outbound_handle_guard.lock().await;

match outbound_handle_guard.get_outbound_sender_mut(&outbound_name) {
Expand Down
160 changes: 105 additions & 55 deletions clash_lib/src/proxy/vmess/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::{collections::HashMap, io, sync::Arc};
use std::{collections::HashMap, io, net::IpAddr, sync::Arc};

use async_trait::async_trait;
use futures::TryFutureExt;
Expand All @@ -8,10 +8,13 @@ mod vmess_impl;

use crate::{
app::ThreadSafeDNSResolver,
common::errors::{map_io_error, new_io_error},
config::internal::proxy::{OutboundProxy, OutboundProxyProtocol},
session::{Session, SocksAddr},
};

use self::vmess_impl::OutboundDatagramVmess;

use super::{
transport::{self, Http2Config},
utils::new_tcp_stream,
Expand Down Expand Up @@ -73,61 +76,13 @@ impl Handler {
pub fn new(opts: HandlerOptions) -> AnyOutboundHandler {
Arc::new(Self { opts })
}
}

#[async_trait]
impl OutboundHandler for Handler {
fn name(&self) -> &str {
&self.opts.name
}

/// The protocol of the outbound handler
/// only contains Type information, do not rely on the underlying value
fn proto(&self) -> OutboundProxy {
OutboundProxy::ProxyServer(OutboundProxyProtocol::Vmess(Default::default()))
}

/// The proxy remote address
async fn remote_addr(&self) -> Option<SocksAddr> {
Some(SocksAddr::Domain(self.opts.server.clone(), self.opts.port))
}

/// whether the outbound handler support UDP
async fn support_udp(&self) -> bool {
self.opts.udp
}

async fn connect_stream(
&self,
sess: &Session,
resolver: ThreadSafeDNSResolver,
) -> io::Result<AnyStream> {
let stream = new_tcp_stream(
resolver.clone(),
self.opts.server.as_str(),
self.opts.port,
self.opts.common_opts.iface.as_ref(),
)
.map_err(|x| {
io::Error::new(
io::ErrorKind::Other,
format!(
"dial outbound {}:{}: {}",
self.opts.server, self.opts.port, x
),
)
})
.await?;

self.proxy_stream(stream, sess, resolver).await
}

/// wraps a stream with outbound handler
async fn proxy_stream(
&self,
async fn inner_proxy_stream<'a>(
&'a self,
s: AnyStream,
sess: &Session,
sess: &'a Session,
resolver: ThreadSafeDNSResolver,
udp: bool,
) -> io::Result<AnyStream> {
let mut stream = s;

Expand Down Expand Up @@ -196,17 +151,112 @@ impl OutboundHandler for Handler {
uuid: self.opts.uuid.to_owned(),
alter_id: self.opts.alter_id,
security: self.opts.security.to_owned(),
udp: false,
udp,
dst: sess.destination.clone(),
})?;

vmess_builder.proxy_stream(underlying).await
}
}

#[async_trait]
impl OutboundHandler for Handler {
fn name(&self) -> &str {
&self.opts.name
}

/// The protocol of the outbound handler
/// only contains Type information, do not rely on the underlying value
fn proto(&self) -> OutboundProxy {
OutboundProxy::ProxyServer(OutboundProxyProtocol::Vmess(Default::default()))
}

/// The proxy remote address
async fn remote_addr(&self) -> Option<SocksAddr> {
Some(SocksAddr::Domain(self.opts.server.clone(), self.opts.port))
}

/// whether the outbound handler support UDP
async fn support_udp(&self) -> bool {
self.opts.udp
}

async fn connect_stream(
&self,
sess: &Session,
resolver: ThreadSafeDNSResolver,
) -> io::Result<AnyStream> {
let stream = new_tcp_stream(
resolver.clone(),
self.opts.server.as_str(),
self.opts.port,
self.opts.common_opts.iface.as_ref(),
)
.map_err(|x| {
io::Error::new(
io::ErrorKind::Other,
format!(
"dial outbound {}:{}: {}",
self.opts.server, self.opts.port, x
),
)
})
.await?;

self.inner_proxy_stream(stream, sess, resolver, false).await
}

/// wraps a stream with outbound handler
async fn proxy_stream(
&self,
s: AnyStream,
sess: &Session,
resolver: ThreadSafeDNSResolver,
) -> io::Result<AnyStream> {
self.inner_proxy_stream(s, sess, resolver, false).await
}

async fn connect_datagram(
&self,
sess: &Session,
resolver: ThreadSafeDNSResolver,
) -> io::Result<AnyOutboundDatagram> {
todo!()
let stream = new_tcp_stream(
resolver.clone(),
self.opts.server.as_str(),
self.opts.port,
self.opts.common_opts.iface.as_ref(),
)
.map_err(|x| {
io::Error::new(
io::ErrorKind::Other,
format!(
"dial outbound {}:{}: {}",
self.opts.server, self.opts.port, x
),
)
})
.await?;

let remote_addr = resolver
.resolve_v4(sess.destination.host().as_str())
.map_err(map_io_error)
.await?
.ok_or(new_io_error(
format!("failed to resolve {}", sess.destination.host()).as_str(),
))?;

let stream = self
.inner_proxy_stream(stream, sess, resolver, true)
.await?;

Ok(Box::new(OutboundDatagramVmess::new(
stream,
SocksAddr::Ip(std::net::SocketAddr::new(
IpAddr::V4(remote_addr),
sess.destination.port(),
)),
)) as AnyOutboundDatagram)
.into()
}
}
140 changes: 0 additions & 140 deletions clash_lib/src/proxy/vmess/vmess_impl/chunk.rs

This file was deleted.

2 changes: 1 addition & 1 deletion clash_lib/src/proxy/vmess/vmess_impl/datagram.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ impl Sink<UdpPacket> for OutboundDatagramVmess {
let n = ready!(inner.as_mut().poll_write(cx, data.as_ref()))?;

debug!(
"send udp packet to remote ss server, len: {}, remote_addr: {}, dst_addr: {}",
"send udp packet to remote vmess server, len: {}, remote_addr: {}, dst_addr: {}",
n, remote_addr, addr
);

Expand Down
2 changes: 1 addition & 1 deletion clash_lib/src/proxy/vmess/vmess_impl/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
mod chunk;
mod cipher;
mod client;
mod header;
Expand Down Expand Up @@ -27,6 +26,7 @@ const MAX_CHUNK_SIZE: usize = 17 * 1024;

pub use client::Builder;
pub use client::VmessOption;
pub use datagram::OutboundDatagramVmess;
pub use stream::VmessStream;
pub use user::new_alter_id_list;
pub use user::new_id;
Loading

0 comments on commit 6d28be2

Please sign in to comment.