mirror of
https://github.com/tun2proxy/tun2proxy.git
synced 2025-06-06 06:40:18 +00:00
re-formatting with max_width = 120
This commit is contained in:
parent
4d9b10fd1c
commit
ff9c258fbd
11 changed files with 64 additions and 191 deletions
1
rustfmt.toml
Normal file
1
rustfmt.toml
Normal file
|
@ -0,0 +1 @@
|
||||||
|
max_width = 120
|
|
@ -23,9 +23,7 @@ pub unsafe extern "C" fn Java_com_github_shadowsocks_bg_Tun2proxy_run(
|
||||||
) -> jint {
|
) -> jint {
|
||||||
let log_level = if verbose != 0 { "trace" } else { "info" };
|
let log_level = if verbose != 0 { "trace" } else { "info" };
|
||||||
let filter_str = &format!("off,tun2proxy={log_level}");
|
let filter_str = &format!("off,tun2proxy={log_level}");
|
||||||
let filter = android_logger::FilterBuilder::new()
|
let filter = android_logger::FilterBuilder::new().parse(filter_str).build();
|
||||||
.parse(filter_str)
|
|
||||||
.build();
|
|
||||||
android_logger::init_once(
|
android_logger::init_once(
|
||||||
android_logger::Config::default()
|
android_logger::Config::default()
|
||||||
.with_tag("tun2proxy")
|
.with_tag("tun2proxy")
|
||||||
|
@ -61,10 +59,7 @@ pub unsafe extern "C" fn Java_com_github_shadowsocks_bg_Tun2proxy_run(
|
||||||
///
|
///
|
||||||
/// Shutdown tun2proxy
|
/// Shutdown tun2proxy
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn Java_com_github_shadowsocks_bg_Tun2proxy_stop(
|
pub unsafe extern "C" fn Java_com_github_shadowsocks_bg_Tun2proxy_stop(_env: JNIEnv, _: JClass) -> jint {
|
||||||
_env: JNIEnv,
|
|
||||||
_clazz: JClass,
|
|
||||||
) -> jint {
|
|
||||||
match &mut TUN_TO_PROXY {
|
match &mut TUN_TO_PROXY {
|
||||||
None => {
|
None => {
|
||||||
log::error!("tun2proxy not started");
|
log::error!("tun2proxy not started");
|
||||||
|
|
18
src/dns.rs
18
src/dns.rs
|
@ -7,11 +7,7 @@ use trust_dns_proto::{
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(feature = "use-rand")]
|
#[cfg(feature = "use-rand")]
|
||||||
pub fn build_dns_request(
|
pub fn build_dns_request(domain: &str, query_type: RecordType, used_by_tcp: bool) -> Result<Vec<u8>, String> {
|
||||||
domain: &str,
|
|
||||||
query_type: RecordType,
|
|
||||||
used_by_tcp: bool,
|
|
||||||
) -> Result<Vec<u8>, String> {
|
|
||||||
// [dependencies]
|
// [dependencies]
|
||||||
// rand = "0.8"
|
// rand = "0.8"
|
||||||
use rand::{rngs::StdRng, Rng, SeedableRng};
|
use rand::{rngs::StdRng, Rng, SeedableRng};
|
||||||
|
@ -34,12 +30,7 @@ pub fn build_dns_request(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build_dns_response(
|
pub fn build_dns_response(mut request: Message, domain: &str, ip: IpAddr, ttl: u32) -> Result<Message, String> {
|
||||||
mut request: Message,
|
|
||||||
domain: &str,
|
|
||||||
ip: IpAddr,
|
|
||||||
ttl: u32,
|
|
||||||
) -> Result<Message, String> {
|
|
||||||
let record = match ip {
|
let record = match ip {
|
||||||
IpAddr::V4(ip) => {
|
IpAddr::V4(ip) => {
|
||||||
let mut record = Record::with(Name::from_str(domain)?, RecordType::A, ttl);
|
let mut record = Record::with(Name::from_str(domain)?, RecordType::A, ttl);
|
||||||
|
@ -62,10 +53,7 @@ pub fn extract_ipaddr_from_dns_message(message: &Message) -> Result<IpAddr, Stri
|
||||||
}
|
}
|
||||||
let mut cname = None;
|
let mut cname = None;
|
||||||
for answer in message.answers() {
|
for answer in message.answers() {
|
||||||
match answer
|
match answer.data().ok_or("DNS response not contains answer data")? {
|
||||||
.data()
|
|
||||||
.ok_or("DNS response not contains answer data")?
|
|
||||||
{
|
|
||||||
RData::A(addr) => {
|
RData::A(addr) => {
|
||||||
return Ok(IpAddr::V4(*addr));
|
return Ok(IpAddr::V4(*addr));
|
||||||
}
|
}
|
||||||
|
|
31
src/http.rs
31
src/http.rs
|
@ -1,8 +1,8 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
error::Error,
|
error::Error,
|
||||||
tun2proxy::{
|
tun2proxy::{
|
||||||
ConnectionInfo, ConnectionManager, Direction, IncomingDataEvent, IncomingDirection,
|
ConnectionInfo, ConnectionManager, Direction, IncomingDataEvent, IncomingDirection, OutgoingDataEvent,
|
||||||
OutgoingDataEvent, OutgoingDirection, TcpProxy,
|
OutgoingDirection, TcpProxy,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use base64::Engine;
|
use base64::Engine;
|
||||||
|
@ -89,11 +89,9 @@ impl HttpConnection {
|
||||||
|
|
||||||
fn send_tunnel_request(&mut self) -> Result<(), Error> {
|
fn send_tunnel_request(&mut self) -> Result<(), Error> {
|
||||||
self.server_outbuf.extend(b"CONNECT ");
|
self.server_outbuf.extend(b"CONNECT ");
|
||||||
self.server_outbuf
|
self.server_outbuf.extend(self.destination.to_string().as_bytes());
|
||||||
.extend(self.destination.to_string().as_bytes());
|
|
||||||
self.server_outbuf.extend(b" HTTP/1.1\r\nHost: ");
|
self.server_outbuf.extend(b" HTTP/1.1\r\nHost: ");
|
||||||
self.server_outbuf
|
self.server_outbuf.extend(self.destination.to_string().as_bytes());
|
||||||
.extend(self.destination.to_string().as_bytes());
|
|
||||||
self.server_outbuf.extend(b"\r\n");
|
self.server_outbuf.extend(b"\r\n");
|
||||||
|
|
||||||
self.send_auth_data(if self.digest_state.borrow().is_none() {
|
self.send_auth_data(if self.digest_state.borrow().is_none() {
|
||||||
|
@ -126,14 +124,8 @@ impl HttpConnection {
|
||||||
let mut state = self.digest_state.borrow_mut();
|
let mut state = self.digest_state.borrow_mut();
|
||||||
let response = state.as_mut().unwrap().respond(&context)?;
|
let response = state.as_mut().unwrap().respond(&context)?;
|
||||||
|
|
||||||
self.server_outbuf.extend(
|
self.server_outbuf
|
||||||
format!(
|
.extend(format!("{}: {}\r\n", PROXY_AUTHORIZATION, response.to_header_string()).as_bytes());
|
||||||
"{}: {}\r\n",
|
|
||||||
PROXY_AUTHORIZATION,
|
|
||||||
response.to_header_string()
|
|
||||||
)
|
|
||||||
.as_bytes(),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
AuthenticationScheme::Basic => {
|
AuthenticationScheme::Basic => {
|
||||||
let cred = format!("{}:{}", credentials.username, credentials.password);
|
let cred = format!("{}:{}", credentials.username, credentials.password);
|
||||||
|
@ -198,8 +190,11 @@ impl HttpConnection {
|
||||||
}
|
}
|
||||||
|
|
||||||
if status_code != 407 {
|
if status_code != 407 {
|
||||||
let e =
|
let e = format!(
|
||||||
format!("Expected success status code. Server replied with {status_code} [Reason: {}].", res.reason.unwrap());
|
"Expected success status code. Server replied with {} [Reason: {}].",
|
||||||
|
status_code,
|
||||||
|
res.reason.unwrap()
|
||||||
|
);
|
||||||
return Err(e.into());
|
return Err(e.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -371,9 +366,7 @@ impl TcpProxy for HttpConnection {
|
||||||
match dir {
|
match dir {
|
||||||
Direction::Incoming(incoming) => match incoming {
|
Direction::Incoming(incoming) => match incoming {
|
||||||
IncomingDirection::FromServer => !self.server_inbuf.is_empty(),
|
IncomingDirection::FromServer => !self.server_inbuf.is_empty(),
|
||||||
IncomingDirection::FromClient => {
|
IncomingDirection::FromClient => !self.client_inbuf.is_empty() || !self.data_buf.is_empty(),
|
||||||
!self.client_inbuf.is_empty() || !self.data_buf.is_empty()
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
Direction::Outgoing(outgoing) => match outgoing {
|
Direction::Outgoing(outgoing) => match outgoing {
|
||||||
OutgoingDirection::ToServer => !self.server_outbuf.is_empty(),
|
OutgoingDirection::ToServer => !self.server_outbuf.is_empty(),
|
||||||
|
|
17
src/lib.rs
17
src/lib.rs
|
@ -124,24 +124,17 @@ pub fn tun_to_proxy<'a>(
|
||||||
let mut ttp = TunToProxy::new(interface, options)?;
|
let mut ttp = TunToProxy::new(interface, options)?;
|
||||||
let credentials = proxy.credentials.clone();
|
let credentials = proxy.credentials.clone();
|
||||||
let server = proxy.addr;
|
let server = proxy.addr;
|
||||||
|
#[rustfmt::skip]
|
||||||
let mgr = match proxy.proxy_type {
|
let mgr = match proxy.proxy_type {
|
||||||
ProxyType::Socks4 => Rc::new(SocksProxyManager::new(server, Version::V4, credentials))
|
ProxyType::Socks4 => Rc::new(SocksProxyManager::new(server, Version::V4, credentials)) as Rc<dyn ConnectionManager>,
|
||||||
as Rc<dyn ConnectionManager>,
|
ProxyType::Socks5 => Rc::new(SocksProxyManager::new(server, Version::V5, credentials)) as Rc<dyn ConnectionManager>,
|
||||||
ProxyType::Socks5 => Rc::new(SocksProxyManager::new(server, Version::V5, credentials))
|
ProxyType::Http => Rc::new(HttpManager::new(server, credentials)) as Rc<dyn ConnectionManager>,
|
||||||
as Rc<dyn ConnectionManager>,
|
|
||||||
ProxyType::Http => {
|
|
||||||
Rc::new(HttpManager::new(server, credentials)) as Rc<dyn ConnectionManager>
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
ttp.add_connection_manager(mgr);
|
ttp.add_connection_manager(mgr);
|
||||||
Ok(ttp)
|
Ok(ttp)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn main_entry(
|
pub fn main_entry(interface: &NetworkInterface, proxy: &Proxy, options: Options) -> Result<(), Error> {
|
||||||
interface: &NetworkInterface,
|
|
||||||
proxy: &Proxy,
|
|
||||||
options: Options,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
let mut ttp = tun_to_proxy(interface, proxy, options)?;
|
let mut ttp = tun_to_proxy(interface, proxy, options)?;
|
||||||
ttp.run()?;
|
ttp.run()?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
15
src/main.rs
15
src/main.rs
|
@ -26,13 +26,7 @@ struct Args {
|
||||||
proxy: Proxy,
|
proxy: Proxy,
|
||||||
|
|
||||||
/// DNS handling
|
/// DNS handling
|
||||||
#[arg(
|
#[arg(short, long, value_name = "method", value_enum, default_value = "virtual")]
|
||||||
short,
|
|
||||||
long,
|
|
||||||
value_name = "method",
|
|
||||||
value_enum,
|
|
||||||
default_value = "virtual"
|
|
||||||
)]
|
|
||||||
dns: ArgDns,
|
dns: ArgDns,
|
||||||
|
|
||||||
/// Routing and system setup
|
/// Routing and system setup
|
||||||
|
@ -102,12 +96,7 @@ fn main() -> ExitCode {
|
||||||
Some(addr) => addr,
|
Some(addr) => addr,
|
||||||
None => args.proxy.addr.ip(),
|
None => args.proxy.addr.ip(),
|
||||||
};
|
};
|
||||||
setup = Setup::new(
|
setup = Setup::new(&args.tun, &bypass_tun_ip, get_default_cidrs(), args.bypass_ip.is_some());
|
||||||
&args.tun,
|
|
||||||
&bypass_tun_ip,
|
|
||||||
get_default_cidrs(),
|
|
||||||
args.bypass_ip.is_some(),
|
|
||||||
);
|
|
||||||
|
|
||||||
setup.configure()?;
|
setup.configure()?;
|
||||||
|
|
||||||
|
|
46
src/setup.rs
46
src/setup.rs
|
@ -59,13 +59,7 @@ where
|
||||||
cmdline.append(&mut args);
|
cmdline.append(&mut args);
|
||||||
let command = cmdline.as_slice().join(" ");
|
let command = cmdline.as_slice().join(" ");
|
||||||
match String::from_utf8(output.stderr.clone()) {
|
match String::from_utf8(output.stderr.clone()) {
|
||||||
Ok(output) => Err(format!(
|
Ok(output) => Err(format!("[{}] Command `{}` failed: {}", nix::unistd::getpid(), command, output).into()),
|
||||||
"[{}] Command `{}` failed: {}",
|
|
||||||
nix::unistd::getpid(),
|
|
||||||
command,
|
|
||||||
output
|
|
||||||
)
|
|
||||||
.into()),
|
|
||||||
Err(_) => Err(format!(
|
Err(_) => Err(format!(
|
||||||
"Command `{:?}` failed with exit code {}",
|
"Command `{:?}` failed with exit code {}",
|
||||||
command,
|
command,
|
||||||
|
@ -126,14 +120,7 @@ impl Setup {
|
||||||
}
|
}
|
||||||
|
|
||||||
let (addr_str, prefix_len_str) = match dst_str.split_once(['/']) {
|
let (addr_str, prefix_len_str) = match dst_str.split_once(['/']) {
|
||||||
None => (
|
None => (dst_str, if self.tunnel_bypass_addr.is_ipv6() { "128" } else { "32" }),
|
||||||
dst_str,
|
|
||||||
if self.tunnel_bypass_addr.is_ipv6() {
|
|
||||||
"128"
|
|
||||||
} else {
|
|
||||||
"32"
|
|
||||||
},
|
|
||||||
),
|
|
||||||
Some((addr_str, prefix_len_str)) => (addr_str, prefix_len_str),
|
Some((addr_str, prefix_len_str)) => (addr_str, prefix_len_str),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -215,13 +202,8 @@ impl Setup {
|
||||||
|
|
||||||
fn shutdown(&mut self) -> Result<(), Error> {
|
fn shutdown(&mut self) -> Result<(), Error> {
|
||||||
self.set_up = false;
|
self.set_up = false;
|
||||||
log::info!(
|
log::info!("[{}] Restoring network configuration", nix::unistd::getpid());
|
||||||
"[{}] Restoring network configuration",
|
let _ = Command::new("ip").args(["link", "del", self.tun.as_str()]).output();
|
||||||
nix::unistd::getpid()
|
|
||||||
);
|
|
||||||
let _ = Command::new("ip")
|
|
||||||
.args(["link", "del", self.tun.as_str()])
|
|
||||||
.output();
|
|
||||||
if self.delete_proxy_route {
|
if self.delete_proxy_route {
|
||||||
let _ = Command::new("ip")
|
let _ = Command::new("ip")
|
||||||
.args(["route", "del", self.tunnel_bypass_addr.to_string().as_str()])
|
.args(["route", "del", self.tunnel_bypass_addr.to_string().as_str()])
|
||||||
|
@ -235,15 +217,7 @@ impl Setup {
|
||||||
if let Err(e) = (|| -> Result<(), Error> {
|
if let Err(e) = (|| -> Result<(), Error> {
|
||||||
nix::unistd::close(read_from_child)?;
|
nix::unistd::close(read_from_child)?;
|
||||||
run_iproute(
|
run_iproute(
|
||||||
[
|
["ip", "tuntap", "add", "name", self.tun.as_str(), "mode", "tun"],
|
||||||
"ip",
|
|
||||||
"tuntap",
|
|
||||||
"add",
|
|
||||||
"name",
|
|
||||||
self.tun.as_str(),
|
|
||||||
"mode",
|
|
||||||
"tun",
|
|
||||||
],
|
|
||||||
"failed to create tunnel device",
|
"failed to create tunnel device",
|
||||||
true,
|
true,
|
||||||
)?;
|
)?;
|
||||||
|
@ -306,10 +280,7 @@ impl Setup {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn configure(&mut self) -> Result<(), Error> {
|
pub fn configure(&mut self) -> Result<(), Error> {
|
||||||
log::info!(
|
log::info!("[{}] Setting up network configuration", nix::unistd::getpid());
|
||||||
"[{}] Setting up network configuration",
|
|
||||||
nix::unistd::getpid()
|
|
||||||
);
|
|
||||||
if nix::unistd::getuid() != 0.into() {
|
if nix::unistd::getuid() != 0.into() {
|
||||||
return Err("Automatic setup requires root privileges".into());
|
return Err("Automatic setup requires root privileges".into());
|
||||||
}
|
}
|
||||||
|
@ -345,10 +316,7 @@ impl Setup {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn restore(&mut self) -> Result<(), Error> {
|
pub fn restore(&mut self) -> Result<(), Error> {
|
||||||
nix::sys::signal::kill(
|
nix::sys::signal::kill(nix::unistd::Pid::from_raw(self.child), nix::sys::signal::SIGINT)?;
|
||||||
nix::unistd::Pid::from_raw(self.child),
|
|
||||||
nix::sys::signal::SIGINT,
|
|
||||||
)?;
|
|
||||||
nix::sys::wait::waitpid(nix::unistd::Pid::from_raw(self.child), None)?;
|
nix::sys::wait::waitpid(nix::unistd::Pid::from_raw(self.child), None)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
32
src/socks.rs
32
src/socks.rs
|
@ -1,14 +1,12 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
error::Error,
|
error::Error,
|
||||||
tun2proxy::{
|
tun2proxy::{
|
||||||
ConnectionInfo, ConnectionManager, Direction, IncomingDataEvent, IncomingDirection,
|
ConnectionInfo, ConnectionManager, Direction, IncomingDataEvent, IncomingDirection, OutgoingDataEvent,
|
||||||
OutgoingDataEvent, OutgoingDirection, TcpProxy,
|
OutgoingDirection, TcpProxy,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use smoltcp::wire::IpProtocol;
|
use smoltcp::wire::IpProtocol;
|
||||||
use socks5_impl::protocol::{
|
use socks5_impl::protocol::{self, handshake, password_method, Address, AuthMethod, StreamOperation, UserKey, Version};
|
||||||
self, handshake, password_method, Address, AuthMethod, StreamOperation, UserKey, Version,
|
|
||||||
};
|
|
||||||
use std::{collections::VecDeque, net::SocketAddr};
|
use std::{collections::VecDeque, net::SocketAddr};
|
||||||
|
|
||||||
#[derive(Eq, PartialEq, Debug)]
|
#[derive(Eq, PartialEq, Debug)]
|
||||||
|
@ -36,11 +34,7 @@ struct SocksProxyImpl {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SocksProxyImpl {
|
impl SocksProxyImpl {
|
||||||
pub fn new(
|
fn new(info: &ConnectionInfo, credentials: Option<UserKey>, version: Version) -> Result<Self, Error> {
|
||||||
info: &ConnectionInfo,
|
|
||||||
credentials: Option<UserKey>,
|
|
||||||
version: Version,
|
|
||||||
) -> Result<Self, Error> {
|
|
||||||
let mut result = Self {
|
let mut result = Self {
|
||||||
info: info.clone(),
|
info: info.clone(),
|
||||||
state: SocksState::ServerHello,
|
state: SocksState::ServerHello,
|
||||||
|
@ -60,8 +54,7 @@ impl SocksProxyImpl {
|
||||||
let credentials = &self.credentials;
|
let credentials = &self.credentials;
|
||||||
self.server_outbuf
|
self.server_outbuf
|
||||||
.extend(&[self.version as u8, protocol::Command::Connect.into()]);
|
.extend(&[self.version as u8, protocol::Command::Connect.into()]);
|
||||||
self.server_outbuf
|
self.server_outbuf.extend(self.info.dst.port().to_be_bytes());
|
||||||
.extend(self.info.dst.port().to_be_bytes());
|
|
||||||
let mut ip_vec = Vec::<u8>::new();
|
let mut ip_vec = Vec::<u8>::new();
|
||||||
let mut name_vec = Vec::<u8>::new();
|
let mut name_vec = Vec::<u8>::new();
|
||||||
match &self.info.dst {
|
match &self.info.dst {
|
||||||
|
@ -94,11 +87,7 @@ impl SocksProxyImpl {
|
||||||
let credentials = &self.credentials;
|
let credentials = &self.credentials;
|
||||||
// Providing unassigned methods is supposed to bypass China's GFW.
|
// Providing unassigned methods is supposed to bypass China's GFW.
|
||||||
// For details, refer to https://github.com/blechschmidt/tun2proxy/issues/35.
|
// For details, refer to https://github.com/blechschmidt/tun2proxy/issues/35.
|
||||||
let mut methods = vec![
|
let mut methods = vec![AuthMethod::NoAuth, AuthMethod::from(4_u8), AuthMethod::from(100_u8)];
|
||||||
AuthMethod::NoAuth,
|
|
||||||
AuthMethod::from(4_u8),
|
|
||||||
AuthMethod::from(100_u8),
|
|
||||||
];
|
|
||||||
if credentials.is_some() {
|
if credentials.is_some() {
|
||||||
methods.push(AuthMethod::UserPass);
|
methods.push(AuthMethod::UserPass);
|
||||||
}
|
}
|
||||||
|
@ -151,8 +140,7 @@ impl SocksProxyImpl {
|
||||||
let auth_method = respones.method;
|
let auth_method = respones.method;
|
||||||
|
|
||||||
if auth_method != AuthMethod::NoAuth && self.credentials.is_none()
|
if auth_method != AuthMethod::NoAuth && self.credentials.is_none()
|
||||||
|| (auth_method != AuthMethod::NoAuth && auth_method != AuthMethod::UserPass)
|
|| (auth_method != AuthMethod::NoAuth && auth_method != AuthMethod::UserPass) && self.credentials.is_some()
|
||||||
&& self.credentials.is_some()
|
|
||||||
{
|
{
|
||||||
return Err("SOCKS5 server requires an unsupported authentication method.".into());
|
return Err("SOCKS5 server requires an unsupported authentication method.".into());
|
||||||
}
|
}
|
||||||
|
@ -240,7 +228,7 @@ impl SocksProxyImpl {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn state_change(&mut self) -> Result<(), Error> {
|
fn state_change(&mut self) -> Result<(), Error> {
|
||||||
match self.state {
|
match self.state {
|
||||||
SocksState::ServerHello => self.receive_server_hello(),
|
SocksState::ServerHello => self.receive_server_hello(),
|
||||||
|
|
||||||
|
@ -308,9 +296,7 @@ impl TcpProxy for SocksProxyImpl {
|
||||||
match dir {
|
match dir {
|
||||||
Direction::Incoming(incoming) => match incoming {
|
Direction::Incoming(incoming) => match incoming {
|
||||||
IncomingDirection::FromServer => !self.server_inbuf.is_empty(),
|
IncomingDirection::FromServer => !self.server_inbuf.is_empty(),
|
||||||
IncomingDirection::FromClient => {
|
IncomingDirection::FromClient => !self.client_inbuf.is_empty() || !self.data_buf.is_empty(),
|
||||||
!self.client_inbuf.is_empty() || !self.data_buf.is_empty()
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
Direction::Outgoing(outgoing) => match outgoing {
|
Direction::Outgoing(outgoing) => match outgoing {
|
||||||
OutgoingDirection::ToServer => !self.server_outbuf.is_empty(),
|
OutgoingDirection::ToServer => !self.server_outbuf.is_empty(),
|
||||||
|
|
|
@ -222,25 +222,19 @@ impl<'a> TunToProxy<'a> {
|
||||||
pub fn new(interface: &NetworkInterface, options: Options) -> Result<Self, Error> {
|
pub fn new(interface: &NetworkInterface, options: Options) -> Result<Self, Error> {
|
||||||
let tun = match interface {
|
let tun = match interface {
|
||||||
NetworkInterface::Named(name) => TunTapInterface::new(name.as_str(), Medium::Ip)?,
|
NetworkInterface::Named(name) => TunTapInterface::new(name.as_str(), Medium::Ip)?,
|
||||||
NetworkInterface::Fd(fd) => {
|
NetworkInterface::Fd(fd) => TunTapInterface::from_fd(*fd, Medium::Ip, options.mtu.unwrap_or(1500))?,
|
||||||
TunTapInterface::from_fd(*fd, Medium::Ip, options.mtu.unwrap_or(1500))?
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
let poll = Poll::new()?;
|
let poll = Poll::new()?;
|
||||||
poll.registry().register(
|
poll.registry()
|
||||||
&mut SourceFd(&tun.as_raw_fd()),
|
.register(&mut SourceFd(&tun.as_raw_fd()), TUN_TOKEN, Interest::READABLE)?;
|
||||||
TUN_TOKEN,
|
|
||||||
Interest::READABLE,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let (exit_sender, mut exit_receiver) = mio::unix::pipe::new()?;
|
let (exit_sender, mut exit_receiver) = mio::unix::pipe::new()?;
|
||||||
poll.registry()
|
poll.registry()
|
||||||
.register(&mut exit_receiver, EXIT_TOKEN, Interest::READABLE)?;
|
.register(&mut exit_receiver, EXIT_TOKEN, Interest::READABLE)?;
|
||||||
|
|
||||||
|
#[rustfmt::skip]
|
||||||
let config = match tun.capabilities().medium {
|
let config = match tun.capabilities().medium {
|
||||||
Medium::Ethernet => Config::new(
|
Medium::Ethernet => Config::new(smoltcp::wire::EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x01]).into()),
|
||||||
smoltcp::wire::EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x01]).into(),
|
|
||||||
),
|
|
||||||
Medium::Ip => Config::new(smoltcp::wire::HardwareAddress::Ip),
|
Medium::Ip => Config::new(smoltcp::wire::HardwareAddress::Ip),
|
||||||
Medium::Ieee802154 => todo!(),
|
Medium::Ieee802154 => todo!(),
|
||||||
};
|
};
|
||||||
|
@ -285,8 +279,7 @@ impl<'a> TunToProxy<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expect_smoltcp_send(&mut self) -> Result<(), Error> {
|
fn expect_smoltcp_send(&mut self) -> Result<(), Error> {
|
||||||
self.iface
|
self.iface.poll(Instant::now(), &mut self.device, &mut self.sockets);
|
||||||
.poll(Instant::now(), &mut self.device, &mut self.sockets);
|
|
||||||
|
|
||||||
while let Some(vec) = self.device.exfiltrate_packet() {
|
while let Some(vec) = self.device.exfiltrate_packet() {
|
||||||
let slice = vec.as_slice();
|
let slice = vec.as_slice();
|
||||||
|
@ -314,7 +307,7 @@ impl<'a> TunToProxy<'a> {
|
||||||
let token = &conn.token;
|
let token = &conn.token;
|
||||||
self.token_to_info.remove(token);
|
self.token_to_info.remove(token);
|
||||||
_ = self.poll.registry().deregister(&mut conn.mio_stream);
|
_ = self.poll.registry().deregister(&mut conn.mio_stream);
|
||||||
log::info!("CLOSE {}", info);
|
log::info!("Close {}", info);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -429,8 +422,7 @@ impl<'a> TunToProxy<'a> {
|
||||||
interest = Interest::READABLE | Interest::WRITABLE;
|
interest = Interest::READABLE | Interest::WRITABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
poll.registry()
|
poll.registry().register(&mut state.mio_stream, state.token, interest)?;
|
||||||
.register(&mut state.mio_stream, state.token, interest)?;
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -524,10 +516,8 @@ impl<'a> TunToProxy<'a> {
|
||||||
let payload = &frame[payload_offset..payload_offset + payload_size];
|
let payload = &frame[payload_offset..payload_offset + payload_size];
|
||||||
let response = virtual_dns.receive_query(payload)?;
|
let response = virtual_dns.receive_query(payload)?;
|
||||||
{
|
{
|
||||||
let rx_buffer =
|
let rx_buffer = udp::PacketBuffer::new(vec![udp::PacketMetadata::EMPTY], vec![0; 4096]);
|
||||||
udp::PacketBuffer::new(vec![udp::PacketMetadata::EMPTY], vec![0; 4096]);
|
let tx_buffer = udp::PacketBuffer::new(vec![udp::PacketMetadata::EMPTY], vec![0; 4096]);
|
||||||
let tx_buffer =
|
|
||||||
udp::PacketBuffer::new(vec![udp::PacketMetadata::EMPTY], vec![0; 4096]);
|
|
||||||
let mut socket = udp::Socket::new(rx_buffer, tx_buffer);
|
let mut socket = udp::Socket::new(rx_buffer, tx_buffer);
|
||||||
socket.bind(dst)?;
|
socket.bind(dst)?;
|
||||||
let meta = UdpMetadata::from(connection_info.src);
|
let meta = UdpMetadata::from(connection_info.src);
|
||||||
|
@ -551,9 +541,7 @@ impl<'a> TunToProxy<'a> {
|
||||||
|
|
||||||
fn write_to_server(&mut self, info: &ConnectionInfo) -> Result<(), Error> {
|
fn write_to_server(&mut self, info: &ConnectionInfo) -> Result<(), Error> {
|
||||||
if let Some(state) = self.connection_map.get_mut(info) {
|
if let Some(state) = self.connection_map.get_mut(info) {
|
||||||
let event = state
|
let event = state.tcp_proxy_handler.peek_data(OutgoingDirection::ToServer);
|
||||||
.tcp_proxy_handler
|
|
||||||
.peek_data(OutgoingDirection::ToServer);
|
|
||||||
let buffer_size = event.buffer.len();
|
let buffer_size = event.buffer.len();
|
||||||
if buffer_size == 0 {
|
if buffer_size == 0 {
|
||||||
state.wait_write = false;
|
state.wait_write = false;
|
||||||
|
@ -590,9 +578,7 @@ impl<'a> TunToProxy<'a> {
|
||||||
Some(handle) => handle,
|
Some(handle) => handle,
|
||||||
None => break,
|
None => break,
|
||||||
};
|
};
|
||||||
let event = state
|
let event = state.tcp_proxy_handler.peek_data(OutgoingDirection::ToClient);
|
||||||
.tcp_proxy_handler
|
|
||||||
.peek_data(OutgoingDirection::ToClient);
|
|
||||||
let buflen = event.buffer.len();
|
let buflen = event.buffer.len();
|
||||||
let consumed;
|
let consumed;
|
||||||
{
|
{
|
||||||
|
@ -662,10 +648,7 @@ impl<'a> TunToProxy<'a> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let server = self
|
let server = self.get_connection_manager(&conn_info).ok_or(e)?.get_server_addr();
|
||||||
.get_connection_manager(&conn_info)
|
|
||||||
.ok_or(e)?
|
|
||||||
.get_server_addr();
|
|
||||||
|
|
||||||
let mut block = || -> Result<(), Error> {
|
let mut block = || -> Result<(), Error> {
|
||||||
if event.is_readable() || event.is_read_closed() {
|
if event.is_readable() || event.is_read_closed() {
|
||||||
|
|
|
@ -120,9 +120,7 @@ impl VirtualDns {
|
||||||
let started_at = self.next_addr;
|
let started_at = self.next_addr;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
if let RawEntryMut::Vacant(vacant) =
|
if let RawEntryMut::Vacant(vacant) = self.lru_cache.raw_entry_mut().from_key(&self.next_addr) {
|
||||||
self.lru_cache.raw_entry_mut().from_key(&self.next_addr)
|
|
||||||
{
|
|
||||||
let expiry = Instant::now() + Duration::from_secs(MAPPING_TIMEOUT);
|
let expiry = Instant::now() + Duration::from_secs(MAPPING_TIMEOUT);
|
||||||
let name0 = name.clone();
|
let name0 = name.clone();
|
||||||
vacant.insert(self.next_addr, NameCacheEntry { name, expiry });
|
vacant.insert(self.next_addr, NameCacheEntry { name, expiry });
|
||||||
|
|
|
@ -22,8 +22,7 @@ mod tests {
|
||||||
static TUN_TEST_DEVICE: &str = "tun0";
|
static TUN_TEST_DEVICE: &str = "tun0";
|
||||||
|
|
||||||
fn proxy_from_env(env_var: &str) -> Result<Proxy, String> {
|
fn proxy_from_env(env_var: &str) -> Result<Proxy, String> {
|
||||||
let url =
|
let url = env::var(env_var).map_err(|_| format!("{env_var} environment variable not found"))?;
|
||||||
env::var(env_var).map_err(|_| format!("{env_var} environment variable not found"))?;
|
|
||||||
Proxy::from_url(url.as_str()).map_err(|_| format!("{env_var} URL cannot be parsed"))
|
Proxy::from_url(url.as_str()).map_err(|_| format!("{env_var} URL cannot be parsed"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,15 +70,13 @@ mod tests {
|
||||||
Ok(ip_str) => IpAddr::from_str(ip_str.as_str()).unwrap(),
|
Ok(ip_str) => IpAddr::from_str(ip_str.as_str()).unwrap(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut setup =
|
let mut setup = Setup::new(TUN_TEST_DEVICE, &bypass_ip, get_default_cidrs(), false);
|
||||||
Setup::new(TUN_TEST_DEVICE, &bypass_ip, get_default_cidrs(), false);
|
|
||||||
setup.configure().unwrap();
|
setup.configure().unwrap();
|
||||||
|
|
||||||
match fork::fork() {
|
match fork::fork() {
|
||||||
Ok(Fork::Parent(child)) => {
|
Ok(Fork::Parent(child)) => {
|
||||||
test_function();
|
test_function();
|
||||||
signal::kill(Pid::from_raw(child), signal::SIGINT)
|
signal::kill(Pid::from_raw(child), signal::SIGINT).expect("failed to kill child");
|
||||||
.expect("failed to kill child");
|
|
||||||
setup.restore().unwrap();
|
setup.restore().unwrap();
|
||||||
}
|
}
|
||||||
Ok(Fork::Child) => {
|
Ok(Fork::Child) => {
|
||||||
|
@ -109,59 +106,41 @@ mod tests {
|
||||||
#[test_log::test]
|
#[test_log::test]
|
||||||
fn test_socks4() {
|
fn test_socks4() {
|
||||||
require_var("SOCKS4_SERVER");
|
require_var("SOCKS4_SERVER");
|
||||||
run_test(
|
run_test(|test| test.proxy.proxy_type == ProxyType::Socks4, request_ip_host_http)
|
||||||
|test| test.proxy.proxy_type == ProxyType::Socks4,
|
|
||||||
request_ip_host_http,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[serial]
|
#[serial]
|
||||||
#[test_log::test]
|
#[test_log::test]
|
||||||
fn test_socks5() {
|
fn test_socks5() {
|
||||||
require_var("SOCKS5_SERVER");
|
require_var("SOCKS5_SERVER");
|
||||||
run_test(
|
run_test(|test| test.proxy.proxy_type == ProxyType::Socks5, request_ip_host_http)
|
||||||
|test| test.proxy.proxy_type == ProxyType::Socks5,
|
|
||||||
request_ip_host_http,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[serial]
|
#[serial]
|
||||||
#[test_log::test]
|
#[test_log::test]
|
||||||
fn test_http() {
|
fn test_http() {
|
||||||
require_var("HTTP_SERVER");
|
require_var("HTTP_SERVER");
|
||||||
run_test(
|
run_test(|test| test.proxy.proxy_type == ProxyType::Http, request_ip_host_http)
|
||||||
|test| test.proxy.proxy_type == ProxyType::Http,
|
|
||||||
request_ip_host_http,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[serial]
|
#[serial]
|
||||||
#[test_log::test]
|
#[test_log::test]
|
||||||
fn test_socks4_dns() {
|
fn test_socks4_dns() {
|
||||||
require_var("SOCKS4_SERVER");
|
require_var("SOCKS4_SERVER");
|
||||||
run_test(
|
run_test(|test| test.proxy.proxy_type == ProxyType::Socks4, request_example_https)
|
||||||
|test| test.proxy.proxy_type == ProxyType::Socks4,
|
|
||||||
request_example_https,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[serial]
|
#[serial]
|
||||||
#[test_log::test]
|
#[test_log::test]
|
||||||
fn test_socks5_dns() {
|
fn test_socks5_dns() {
|
||||||
require_var("SOCKS5_SERVER");
|
require_var("SOCKS5_SERVER");
|
||||||
run_test(
|
run_test(|test| test.proxy.proxy_type == ProxyType::Socks5, request_example_https)
|
||||||
|test| test.proxy.proxy_type == ProxyType::Socks5,
|
|
||||||
request_example_https,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[serial]
|
#[serial]
|
||||||
#[test_log::test]
|
#[test_log::test]
|
||||||
fn test_http_dns() {
|
fn test_http_dns() {
|
||||||
require_var("HTTP_SERVER");
|
require_var("HTTP_SERVER");
|
||||||
run_test(
|
run_test(|test| test.proxy.proxy_type == ProxyType::Http, request_example_https)
|
||||||
|test| test.proxy.proxy_type == ProxyType::Http,
|
|
||||||
request_example_https,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue