cleanup
This commit is contained in:
parent
05abcd441f
commit
f149b8190b
15 changed files with 171 additions and 195 deletions
150
src/main.rs
150
src/main.rs
|
@ -12,14 +12,14 @@ use crate::tunnel::listeners::{
|
||||||
new_stdio_listener, new_udp_listener, HttpProxyTunnelListener, Socks5TunnelListener, TcpTunnelListener,
|
new_stdio_listener, new_udp_listener, HttpProxyTunnelListener, Socks5TunnelListener, TcpTunnelListener,
|
||||||
};
|
};
|
||||||
use crate::tunnel::server::{TlsServerConfig, WsServer, WsServerConfig};
|
use crate::tunnel::server::{TlsServerConfig, WsServer, WsServerConfig};
|
||||||
use crate::tunnel::{to_host_port, RemoteAddr, TransportAddr, TransportScheme};
|
use crate::tunnel::{to_host_port, LocalProtocol, RemoteAddr, TransportAddr, TransportScheme};
|
||||||
|
use anyhow::{anyhow, Context};
|
||||||
use base64::Engine;
|
use base64::Engine;
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use hyper::header::HOST;
|
use hyper::header::HOST;
|
||||||
use hyper::http::{HeaderName, HeaderValue};
|
use hyper::http::{HeaderName, HeaderValue};
|
||||||
use log::debug;
|
use log::debug;
|
||||||
use parking_lot::{Mutex, RwLock};
|
use parking_lot::{Mutex, RwLock};
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::io;
|
use std::io;
|
||||||
|
@ -376,66 +376,11 @@ struct Server {
|
||||||
http_proxy_password: Option<String>,
|
http_proxy_password: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
|
|
||||||
enum LocalProtocol {
|
|
||||||
Tcp {
|
|
||||||
proxy_protocol: bool,
|
|
||||||
},
|
|
||||||
Udp {
|
|
||||||
timeout: Option<Duration>,
|
|
||||||
},
|
|
||||||
Stdio,
|
|
||||||
Socks5 {
|
|
||||||
timeout: Option<Duration>,
|
|
||||||
credentials: Option<(String, String)>,
|
|
||||||
},
|
|
||||||
TProxyTcp,
|
|
||||||
TProxyUdp {
|
|
||||||
timeout: Option<Duration>,
|
|
||||||
},
|
|
||||||
HttpProxy {
|
|
||||||
timeout: Option<Duration>,
|
|
||||||
credentials: Option<(String, String)>,
|
|
||||||
proxy_protocol: bool,
|
|
||||||
},
|
|
||||||
ReverseTcp,
|
|
||||||
ReverseUdp {
|
|
||||||
timeout: Option<Duration>,
|
|
||||||
},
|
|
||||||
ReverseSocks5 {
|
|
||||||
timeout: Option<Duration>,
|
|
||||||
credentials: Option<(String, String)>,
|
|
||||||
},
|
|
||||||
ReverseHttpProxy {
|
|
||||||
timeout: Option<Duration>,
|
|
||||||
credentials: Option<(String, String)>,
|
|
||||||
},
|
|
||||||
ReverseUnix {
|
|
||||||
path: PathBuf,
|
|
||||||
},
|
|
||||||
Unix {
|
|
||||||
path: PathBuf,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
impl LocalProtocol {
|
|
||||||
pub const fn is_reverse_tunnel(&self) -> bool {
|
|
||||||
matches!(
|
|
||||||
self,
|
|
||||||
Self::ReverseTcp
|
|
||||||
| Self::ReverseUdp { .. }
|
|
||||||
| Self::ReverseSocks5 { .. }
|
|
||||||
| Self::ReverseUnix { .. }
|
|
||||||
| Self::ReverseHttpProxy { .. }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct LocalToRemote {
|
pub struct LocalToRemote {
|
||||||
local_protocol: LocalProtocol,
|
local_protocol: LocalProtocol,
|
||||||
local: SocketAddr,
|
local: SocketAddr,
|
||||||
remote: (Host<String>, u16),
|
remote: (Host, u16),
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_duration_sec(arg: &str) -> Result<Duration, io::Error> {
|
fn parse_duration_sec(arg: &str) -> Result<Duration, io::Error> {
|
||||||
|
@ -773,24 +718,7 @@ async fn main() -> anyhow::Result<()> {
|
||||||
TransportScheme::from_str(args.remote_addr.scheme()).expect("invalid scheme in server url");
|
TransportScheme::from_str(args.remote_addr.scheme()).expect("invalid scheme in server url");
|
||||||
let tls = match transport_scheme {
|
let tls = match transport_scheme {
|
||||||
TransportScheme::Ws | TransportScheme::Http => None,
|
TransportScheme::Ws | TransportScheme::Http => None,
|
||||||
TransportScheme::Wss => Some(TlsClientConfig {
|
TransportScheme::Wss | TransportScheme::Https => Some(TlsClientConfig {
|
||||||
tls_connector: Arc::new(RwLock::new(
|
|
||||||
tls::tls_connector(
|
|
||||||
args.tls_verify_certificate,
|
|
||||||
transport_scheme.alpn_protocols(),
|
|
||||||
!args.tls_sni_disable,
|
|
||||||
tls_certificate,
|
|
||||||
tls_key,
|
|
||||||
)
|
|
||||||
.expect("Cannot create tls connector"),
|
|
||||||
)),
|
|
||||||
tls_sni_override: args.tls_sni_override,
|
|
||||||
tls_verify_certificate: args.tls_verify_certificate,
|
|
||||||
tls_sni_disabled: args.tls_sni_disable,
|
|
||||||
tls_certificate_path: args.tls_certificate.clone(),
|
|
||||||
tls_key_path: args.tls_private_key.clone(),
|
|
||||||
}),
|
|
||||||
TransportScheme::Https => Some(TlsClientConfig {
|
|
||||||
tls_connector: Arc::new(RwLock::new(
|
tls_connector: Arc::new(RwLock::new(
|
||||||
tls::tls_connector(
|
tls::tls_connector(
|
||||||
args.tls_verify_certificate,
|
args.tls_verify_certificate,
|
||||||
|
@ -824,25 +752,8 @@ async fn main() -> anyhow::Result<()> {
|
||||||
panic!("http headers file does not exists: {}", path.display());
|
panic!("http headers file does not exists: {}", path.display());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let http_proxy = if let Some(proxy) = args.http_proxy {
|
|
||||||
let mut proxy = if proxy.starts_with("http://") {
|
|
||||||
Url::parse(&proxy).expect("Invalid http proxy url")
|
|
||||||
} else {
|
|
||||||
Url::parse(&format!("http://{}", proxy)).expect("Invalid http proxy url")
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(login) = args.http_proxy_login {
|
let http_proxy = mk_http_proxy(args.http_proxy, args.http_proxy_login, args.http_proxy_password)?;
|
||||||
proxy.set_username(login.as_str()).expect("Cannot set http proxy login");
|
|
||||||
}
|
|
||||||
if let Some(password) = args.http_proxy_password {
|
|
||||||
proxy
|
|
||||||
.set_password(Some(password.as_str()))
|
|
||||||
.expect("Cannot set http proxy password");
|
|
||||||
}
|
|
||||||
Some(proxy)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
let client_config = WsClientConfig {
|
let client_config = WsClientConfig {
|
||||||
remote_addr: TransportAddr::new(
|
remote_addr: TransportAddr::new(
|
||||||
TransportScheme::from_str(args.remote_addr.scheme()).unwrap(),
|
TransportScheme::from_str(args.remote_addr.scheme()).unwrap(),
|
||||||
|
@ -1176,26 +1087,7 @@ async fn main() -> anyhow::Result<()> {
|
||||||
restriction_cfg
|
restriction_cfg
|
||||||
};
|
};
|
||||||
|
|
||||||
let http_proxy = if let Some(proxy) = args.http_proxy {
|
let http_proxy = mk_http_proxy(args.http_proxy, args.http_proxy_login, args.http_proxy_password)?;
|
||||||
let mut proxy = if proxy.starts_with("http://") {
|
|
||||||
Url::parse(&proxy).expect("Invalid http proxy url")
|
|
||||||
} else {
|
|
||||||
Url::parse(&format!("http://{}", proxy)).expect("Invalid http proxy url")
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(login) = args.http_proxy_login {
|
|
||||||
proxy.set_username(login.as_str()).expect("Cannot set http proxy login");
|
|
||||||
}
|
|
||||||
if let Some(password) = args.http_proxy_password {
|
|
||||||
proxy
|
|
||||||
.set_password(Some(password.as_str()))
|
|
||||||
.expect("Cannot set http proxy password");
|
|
||||||
}
|
|
||||||
Some(proxy)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
let server_config = WsServerConfig {
|
let server_config = WsServerConfig {
|
||||||
socket_so_mark: args.socket_so_mark,
|
socket_so_mark: args.socket_so_mark,
|
||||||
bind: args.remote_addr.socket_addrs(|| Some(8080)).unwrap()[0],
|
bind: args.remote_addr.socket_addrs(|| Some(8080)).unwrap()[0],
|
||||||
|
@ -1230,3 +1122,33 @@ async fn main() -> anyhow::Result<()> {
|
||||||
tokio::signal::ctrl_c().await.unwrap();
|
tokio::signal::ctrl_c().await.unwrap();
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn mk_http_proxy(
|
||||||
|
http_proxy: Option<String>,
|
||||||
|
proxy_login: Option<String>,
|
||||||
|
proxy_password: Option<String>,
|
||||||
|
) -> anyhow::Result<Option<Url>> {
|
||||||
|
let Some(proxy) = http_proxy else {
|
||||||
|
return Ok(None);
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut proxy = if proxy.starts_with("http://") {
|
||||||
|
Url::parse(&proxy).with_context(|| "Invalid http proxy url")?
|
||||||
|
} else {
|
||||||
|
Url::parse(&format!("http://{}", proxy)).with_context(|| "Invalid http proxy url")?
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(login) = proxy_login {
|
||||||
|
proxy
|
||||||
|
.set_username(login.as_str())
|
||||||
|
.map_err(|_| anyhow!("Cannot set http proxy login"))?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(password) = proxy_password {
|
||||||
|
proxy
|
||||||
|
.set_password(Some(password.as_str()))
|
||||||
|
.map_err(|_| anyhow!("Cannot set http proxy password"))?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Some(proxy))
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use super::udp_server::{Socks5UdpStream, Socks5UdpStreamWriter};
|
use super::udp_server::{Socks5UdpStream, Socks5UdpStreamWriter};
|
||||||
use crate::LocalProtocol;
|
use crate::tunnel::LocalProtocol;
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
use fast_socks5::server::{Config, DenyAuthentication, SimpleUserPassword, Socks5Server};
|
use fast_socks5::server::{Config, DenyAuthentication, SimpleUserPassword, Socks5Server};
|
||||||
use fast_socks5::util::target_addr::TargetAddr;
|
use fast_socks5::util::target_addr::TargetAddr;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::LocalProtocol;
|
use crate::tunnel::LocalProtocol;
|
||||||
use ipnet::{IpNet, Ipv4Net, Ipv6Net};
|
use ipnet::{IpNet, Ipv4Net, Ipv6Net};
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use serde::{Deserialize, Deserializer};
|
use serde::{Deserialize, Deserializer};
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::protocols;
|
use crate::protocols;
|
||||||
use crate::protocols::tls;
|
use crate::protocols::tls;
|
||||||
|
use crate::tunnel::client::l4_transport_stream::TransportStream;
|
||||||
use crate::tunnel::client::WsClientConfig;
|
use crate::tunnel::client::WsClientConfig;
|
||||||
use crate::tunnel::TransportStream;
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use bb8::ManageConnection;
|
use bb8::ManageConnection;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
|
61
src/tunnel/client/l4_transport_stream.rs
Normal file
61
src/tunnel/client/l4_transport_stream.rs
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
use std::io::{Error, IoSlice};
|
||||||
|
use std::pin::Pin;
|
||||||
|
use std::task::{Context, Poll};
|
||||||
|
use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
|
||||||
|
use tokio::net::TcpStream;
|
||||||
|
use tokio_rustls::client::TlsStream;
|
||||||
|
|
||||||
|
pub enum TransportStream {
|
||||||
|
Plain(TcpStream),
|
||||||
|
Tls(TlsStream<TcpStream>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsyncRead for TransportStream {
|
||||||
|
fn poll_read(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &mut ReadBuf<'_>) -> Poll<std::io::Result<()>> {
|
||||||
|
match self.get_mut() {
|
||||||
|
Self::Plain(cnx) => Pin::new(cnx).poll_read(cx, buf),
|
||||||
|
Self::Tls(cnx) => Pin::new(cnx).poll_read(cx, buf),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsyncWrite for TransportStream {
|
||||||
|
fn poll_write(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8]) -> Poll<Result<usize, Error>> {
|
||||||
|
match self.get_mut() {
|
||||||
|
Self::Plain(cnx) => Pin::new(cnx).poll_write(cx, buf),
|
||||||
|
Self::Tls(cnx) => Pin::new(cnx).poll_write(cx, buf),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Error>> {
|
||||||
|
match self.get_mut() {
|
||||||
|
Self::Plain(cnx) => Pin::new(cnx).poll_flush(cx),
|
||||||
|
Self::Tls(cnx) => Pin::new(cnx).poll_flush(cx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Error>> {
|
||||||
|
match self.get_mut() {
|
||||||
|
Self::Plain(cnx) => Pin::new(cnx).poll_shutdown(cx),
|
||||||
|
Self::Tls(cnx) => Pin::new(cnx).poll_shutdown(cx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn poll_write_vectored(
|
||||||
|
self: Pin<&mut Self>,
|
||||||
|
cx: &mut Context<'_>,
|
||||||
|
bufs: &[IoSlice<'_>],
|
||||||
|
) -> Poll<Result<usize, Error>> {
|
||||||
|
match self.get_mut() {
|
||||||
|
Self::Plain(cnx) => Pin::new(cnx).poll_write_vectored(cx, bufs),
|
||||||
|
Self::Tls(cnx) => Pin::new(cnx).poll_write_vectored(cx, bufs),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_write_vectored(&self) -> bool {
|
||||||
|
match &self {
|
||||||
|
Self::Plain(cnx) => cnx.is_write_vectored(),
|
||||||
|
Self::Tls(cnx) => cnx.is_write_vectored(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,6 +2,7 @@
|
||||||
mod client;
|
mod client;
|
||||||
mod cnx_pool;
|
mod cnx_pool;
|
||||||
mod config;
|
mod config;
|
||||||
|
pub mod l4_transport_stream;
|
||||||
|
|
||||||
pub use client::WsClient;
|
pub use client::WsClient;
|
||||||
pub use config::TlsClientConfig;
|
pub use config::TlsClientConfig;
|
||||||
|
|
|
@ -8,12 +8,12 @@ use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
|
||||||
use tokio::net::tcp::{OwnedReadHalf, OwnedWriteHalf};
|
use tokio::net::tcp::{OwnedReadHalf, OwnedWriteHalf};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
|
use crate::protocols;
|
||||||
use crate::protocols::dns::DnsResolver;
|
use crate::protocols::dns::DnsResolver;
|
||||||
use crate::protocols::udp;
|
use crate::protocols::udp;
|
||||||
use crate::protocols::udp::WsUdpSocket;
|
use crate::protocols::udp::WsUdpSocket;
|
||||||
use crate::tunnel::connectors::TunnelConnector;
|
use crate::tunnel::connectors::TunnelConnector;
|
||||||
use crate::tunnel::RemoteAddr;
|
use crate::tunnel::{LocalProtocol, RemoteAddr};
|
||||||
use crate::{protocols, LocalProtocol};
|
|
||||||
|
|
||||||
pub struct Socks5TunnelConnector<'a> {
|
pub struct Socks5TunnelConnector<'a> {
|
||||||
so_mark: Option<u32>,
|
so_mark: Option<u32>,
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
use crate::protocols::http_proxy;
|
use crate::protocols::http_proxy;
|
||||||
use crate::protocols::http_proxy::HttpProxyListener;
|
use crate::protocols::http_proxy::HttpProxyListener;
|
||||||
use crate::tunnel::RemoteAddr;
|
use crate::tunnel::{LocalProtocol, RemoteAddr};
|
||||||
use crate::LocalProtocol;
|
|
||||||
use anyhow::{anyhow, Context};
|
use anyhow::{anyhow, Context};
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
use crate::protocols::stdio;
|
use crate::protocols::stdio;
|
||||||
use crate::tunnel::RemoteAddr;
|
use crate::tunnel::{LocalProtocol, RemoteAddr};
|
||||||
use crate::LocalProtocol;
|
|
||||||
use anyhow::{anyhow, Context};
|
use anyhow::{anyhow, Context};
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
use std::task::Poll;
|
use std::task::Poll;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::tunnel::RemoteAddr;
|
use crate::protocols;
|
||||||
use crate::{protocols, LocalProtocol};
|
use crate::tunnel::{LocalProtocol, RemoteAddr};
|
||||||
use anyhow::{anyhow, Context};
|
use anyhow::{anyhow, Context};
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
|
use crate::protocols;
|
||||||
use crate::protocols::udp;
|
use crate::protocols::udp;
|
||||||
use crate::protocols::udp::{UdpStream, UdpStreamWriter};
|
use crate::protocols::udp::{UdpStream, UdpStreamWriter};
|
||||||
use crate::tunnel::{to_host_port, RemoteAddr};
|
use crate::tunnel::{to_host_port, LocalProtocol, RemoteAddr};
|
||||||
use crate::{protocols, LocalProtocol};
|
|
||||||
use anyhow::{anyhow, Context};
|
use anyhow::{anyhow, Context};
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
use crate::protocols::udp;
|
use crate::protocols::udp;
|
||||||
use crate::protocols::udp::{UdpStream, UdpStreamWriter};
|
use crate::protocols::udp::{UdpStream, UdpStreamWriter};
|
||||||
use crate::tunnel::RemoteAddr;
|
use crate::tunnel::{LocalProtocol, RemoteAddr};
|
||||||
use crate::LocalProtocol;
|
|
||||||
use anyhow::{anyhow, Context};
|
use anyhow::{anyhow, Context};
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
use crate::protocols::unix_sock;
|
use crate::protocols::unix_sock;
|
||||||
use crate::protocols::unix_sock::UnixListenerStream;
|
use crate::protocols::unix_sock::UnixListenerStream;
|
||||||
use crate::tunnel::RemoteAddr;
|
use crate::tunnel::{LocalProtocol, RemoteAddr};
|
||||||
use crate::LocalProtocol;
|
|
||||||
use anyhow::{anyhow, Context};
|
use anyhow::{anyhow, Context};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
|
|
|
@ -5,21 +5,17 @@ pub mod server;
|
||||||
mod tls_reloader;
|
mod tls_reloader;
|
||||||
mod transport;
|
mod transport;
|
||||||
|
|
||||||
use crate::{LocalProtocol, TlsClientConfig};
|
use crate::TlsClientConfig;
|
||||||
use jsonwebtoken::{Algorithm, DecodingKey, EncodingKey, Header, Validation};
|
use jsonwebtoken::{Algorithm, DecodingKey, EncodingKey, Header, Validation};
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::fmt::{Debug, Display, Formatter};
|
use std::fmt::{Debug, Display, Formatter};
|
||||||
use std::io::{Error, IoSlice};
|
|
||||||
use std::net::{IpAddr, SocketAddr};
|
use std::net::{IpAddr, SocketAddr};
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::pin::Pin;
|
use std::path::PathBuf;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::task::{Context, Poll};
|
use std::time::Duration;
|
||||||
use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
|
|
||||||
use tokio::net::TcpStream;
|
|
||||||
use tokio_rustls::client::TlsStream;
|
|
||||||
use url::Host;
|
use url::Host;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
@ -73,6 +69,61 @@ static JWT_DECODE: Lazy<(Validation, DecodingKey)> = Lazy::new(|| {
|
||||||
(validation, DecodingKey::from_secret(JWT_SECRET))
|
(validation, DecodingKey::from_secret(JWT_SECRET))
|
||||||
});
|
});
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
|
||||||
|
pub enum LocalProtocol {
|
||||||
|
Tcp {
|
||||||
|
proxy_protocol: bool,
|
||||||
|
},
|
||||||
|
Udp {
|
||||||
|
timeout: Option<Duration>,
|
||||||
|
},
|
||||||
|
Stdio,
|
||||||
|
Socks5 {
|
||||||
|
timeout: Option<Duration>,
|
||||||
|
credentials: Option<(String, String)>,
|
||||||
|
},
|
||||||
|
TProxyTcp,
|
||||||
|
TProxyUdp {
|
||||||
|
timeout: Option<Duration>,
|
||||||
|
},
|
||||||
|
HttpProxy {
|
||||||
|
timeout: Option<Duration>,
|
||||||
|
credentials: Option<(String, String)>,
|
||||||
|
proxy_protocol: bool,
|
||||||
|
},
|
||||||
|
ReverseTcp,
|
||||||
|
ReverseUdp {
|
||||||
|
timeout: Option<Duration>,
|
||||||
|
},
|
||||||
|
ReverseSocks5 {
|
||||||
|
timeout: Option<Duration>,
|
||||||
|
credentials: Option<(String, String)>,
|
||||||
|
},
|
||||||
|
ReverseHttpProxy {
|
||||||
|
timeout: Option<Duration>,
|
||||||
|
credentials: Option<(String, String)>,
|
||||||
|
},
|
||||||
|
ReverseUnix {
|
||||||
|
path: PathBuf,
|
||||||
|
},
|
||||||
|
Unix {
|
||||||
|
path: PathBuf,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LocalProtocol {
|
||||||
|
pub const fn is_reverse_tunnel(&self) -> bool {
|
||||||
|
matches!(
|
||||||
|
self,
|
||||||
|
Self::ReverseTcp
|
||||||
|
| Self::ReverseUdp { .. }
|
||||||
|
| Self::ReverseSocks5 { .. }
|
||||||
|
| Self::ReverseUnix { .. }
|
||||||
|
| Self::ReverseHttpProxy { .. }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct RemoteAddr {
|
pub struct RemoteAddr {
|
||||||
pub protocol: LocalProtocol,
|
pub protocol: LocalProtocol,
|
||||||
|
@ -245,61 +296,6 @@ impl TryFrom<JwtTunnelConfig> for RemoteAddr {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum TransportStream {
|
|
||||||
Plain(TcpStream),
|
|
||||||
Tls(TlsStream<TcpStream>),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AsyncRead for TransportStream {
|
|
||||||
fn poll_read(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &mut ReadBuf<'_>) -> Poll<std::io::Result<()>> {
|
|
||||||
match self.get_mut() {
|
|
||||||
Self::Plain(cnx) => Pin::new(cnx).poll_read(cx, buf),
|
|
||||||
Self::Tls(cnx) => Pin::new(cnx).poll_read(cx, buf),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AsyncWrite for TransportStream {
|
|
||||||
fn poll_write(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8]) -> Poll<Result<usize, Error>> {
|
|
||||||
match self.get_mut() {
|
|
||||||
Self::Plain(cnx) => Pin::new(cnx).poll_write(cx, buf),
|
|
||||||
Self::Tls(cnx) => Pin::new(cnx).poll_write(cx, buf),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Error>> {
|
|
||||||
match self.get_mut() {
|
|
||||||
Self::Plain(cnx) => Pin::new(cnx).poll_flush(cx),
|
|
||||||
Self::Tls(cnx) => Pin::new(cnx).poll_flush(cx),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Error>> {
|
|
||||||
match self.get_mut() {
|
|
||||||
Self::Plain(cnx) => Pin::new(cnx).poll_shutdown(cx),
|
|
||||||
Self::Tls(cnx) => Pin::new(cnx).poll_shutdown(cx),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn poll_write_vectored(
|
|
||||||
self: Pin<&mut Self>,
|
|
||||||
cx: &mut Context<'_>,
|
|
||||||
bufs: &[IoSlice<'_>],
|
|
||||||
) -> Poll<Result<usize, Error>> {
|
|
||||||
match self.get_mut() {
|
|
||||||
Self::Plain(cnx) => Pin::new(cnx).poll_write_vectored(cx, bufs),
|
|
||||||
Self::Tls(cnx) => Pin::new(cnx).poll_write_vectored(cx, bufs),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_write_vectored(&self) -> bool {
|
|
||||||
match &self {
|
|
||||||
Self::Plain(cnx) => cnx.is_write_vectored(),
|
|
||||||
Self::Tls(cnx) => cnx.is_write_vectored(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn to_host_port(addr: SocketAddr) -> (Host, u16) {
|
pub fn to_host_port(addr: SocketAddr) -> (Host, u16) {
|
||||||
match addr.ip() {
|
match addr.ip() {
|
||||||
IpAddr::V4(ip) => (Host::Ipv4(ip), addr.port()),
|
IpAddr::V4(ip) => (Host::Ipv4(ip), addr.port()),
|
||||||
|
|
|
@ -15,8 +15,8 @@ use std::pin::Pin;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use crate::tunnel::RemoteAddr;
|
use crate::protocols;
|
||||||
use crate::{protocols, LocalProtocol};
|
use crate::tunnel::{LocalProtocol, RemoteAddr};
|
||||||
use hyper::body::Incoming;
|
use hyper::body::Incoming;
|
||||||
use hyper::server::conn::{http1, http2};
|
use hyper::server::conn::{http1, http2};
|
||||||
use hyper::service::service_fn;
|
use hyper::service::service_fn;
|
||||||
|
|
Loading…
Reference in a new issue