This commit is contained in:
Σrebe - Romain GERARD 2024-08-10 11:08:22 +02:00
parent dff243369c
commit 0f33feecfc
No known key found for this signature in database
GPG key ID: 7A42B4B97E0332F4
11 changed files with 197 additions and 208 deletions

46
Cargo.lock generated
View file

@ -71,9 +71,9 @@ dependencies = [
[[package]]
name = "anstyle"
version = "1.0.7"
version = "1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b"
checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1"
[[package]]
name = "anstyle-parse"
@ -318,7 +318,7 @@ dependencies = [
"pin-project-lite",
"rustls 0.22.4",
"rustls-native-certs 0.7.1",
"rustls-pemfile 2.1.2",
"rustls-pemfile 2.1.3",
"rustls-pki-types",
"serde",
"serde_derive",
@ -358,9 +358,9 @@ checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50"
[[package]]
name = "cc"
version = "1.1.6"
version = "1.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2aba8f4e9906c7ce3c73463f62a7f0c65183ada1a2d47e397cc8810827f9694f"
checksum = "504bdec147f2cc13c8b57ed9401fd8a147cc66b67ad5cb241394244f2c947549"
dependencies = [
"jobserver",
"libc",
@ -413,9 +413,9 @@ dependencies = [
[[package]]
name = "clap"
version = "4.5.13"
version = "4.5.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fbb260a053428790f3de475e304ff84cdbc4face759ea7a3e64c1edd938a7fc"
checksum = "11d8838454fda655dafd3accb2b6e2bea645b9e4078abe84a22ceb947235c5cc"
dependencies = [
"clap_builder",
"clap_derive",
@ -423,9 +423,9 @@ dependencies = [
[[package]]
name = "clap_builder"
version = "4.5.13"
version = "4.5.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "64b17d7ea74e9f833c7dbf2cbe4fb12ff26783eda4782a8975b72f895c9b4d99"
checksum = "216aec2b177652e3846684cbfe25c9964d18ec45234f0f5da5157b207ed1aab6"
dependencies = [
"anstream",
"anstyle",
@ -1102,9 +1102,9 @@ dependencies = [
[[package]]
name = "http-body"
version = "1.0.0"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643"
checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184"
dependencies = [
"bytes",
"http 1.1.0",
@ -1192,9 +1192,9 @@ dependencies = [
[[package]]
name = "hyper-util"
version = "0.1.6"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ab92f4f49ee4fb4f997c784b7a2e0fa70050211e0b6a287f898c3c9785ca956"
checksum = "cde7055719c54e36e95e8719f95883f22072a48ede39db7fc17a4e1d5281e9b9"
dependencies = [
"bytes",
"futures-channel",
@ -1911,9 +1911,9 @@ dependencies = [
[[package]]
name = "regex"
version = "1.10.5"
version = "1.10.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f"
checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619"
dependencies = [
"aho-corasick",
"memchr",
@ -2073,7 +2073,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a88d6d420651b496bdd98684116959239430022a115c1240e6c3993be0b15fba"
dependencies = [
"openssl-probe",
"rustls-pemfile 2.1.2",
"rustls-pemfile 2.1.3",
"rustls-pki-types",
"schannel",
"security-framework",
@ -2090,9 +2090,9 @@ dependencies = [
[[package]]
name = "rustls-pemfile"
version = "2.1.2"
version = "2.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29993a25686778eb88d4189742cd713c9bce943bc54251a33509dc63cbacf73d"
checksum = "196fe16b00e106300d3e45ecfcb764fa292a535d7326a29a5875c579c7417425"
dependencies = [
"base64 0.22.1",
"rustls-pki-types",
@ -2191,18 +2191,18 @@ dependencies = [
[[package]]
name = "serde"
version = "1.0.204"
version = "1.0.205"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12"
checksum = "e33aedb1a7135da52b7c21791455563facbbcc43d0f0f66165b42c21b3dfb150"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.204"
version = "1.0.205"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222"
checksum = "692d6f5ac90220161d6774db30c662202721e64aed9058d2c394f451261420c1"
dependencies = [
"proc-macro2",
"quote",
@ -3149,7 +3149,7 @@ dependencies = [
"ppp",
"regex",
"rustls-native-certs 0.7.1",
"rustls-pemfile 2.1.2",
"rustls-pemfile 2.1.3",
"scopeguard",
"serde",
"serde_regex",

View file

@ -14,7 +14,7 @@ scopeguard = "1.2.0"
bb8 = { version = "0.8", features = [] }
bytes = { version = "1.7.1", features = [] }
clap = { version = "4.5.13", features = ["derive", "env"] }
clap = { version = "4.5.15", features = ["derive", "env"] }
fast-socks5 = { version = "0.9.6", features = [] }
fastwebsockets = { version = "0.8.0", features = ["upgrade", "simd", "unstable-split"] }
futures-util = { version = "0.3.30" }
@ -23,13 +23,13 @@ ppp = { version = "2.2.0", features = [] }
async-channel = { version = "2.3.1", features = [] }
# For config file parsing
regex = { version = "1.10.5", default-features = false, features = ["std", "perf"] }
regex = { version = "1.10.6", default-features = false, features = ["std", "perf"] }
serde_regex = "1.1.0"
serde_yaml = { version = "0.9.34", features = [] }
ipnet = { version = "2.9.0", features = ["serde"] }
hyper = { version = "1.4.1", features = ["client", "http1", "http2"] }
hyper-util = { version = "0.1.6", features = ["tokio", "server", "server-auto"] }
hyper-util = { version = "0.1.7", features = ["tokio", "server", "server-auto"] }
http-body-util = { version = "0.1.2" }
jsonwebtoken = { version = "9.3.0", default-features = false }
log = "0.4.22"
@ -40,9 +40,9 @@ pin-project = "1"
notify = { version = "6.1.1", features = [] }
rustls-native-certs = { version = "0.7.1", features = [] }
rustls-pemfile = { version = "2.1.2", features = [] }
rustls-pemfile = { version = "2.1.3", features = [] }
x509-parser = "0.16.0"
serde = { version = "1.0.204", features = ["derive"] }
serde = { version = "1.0.205", features = ["derive"] }
socket2 = { version = "0.5.7", features = [] }
tokio = { version = "1.39.2", features = ["full"] }
tokio-stream = { version = "0.1.15", features = ["net"] }

View file

@ -12,7 +12,8 @@ use crate::tunnel::listeners::{
new_stdio_listener, HttpProxyTunnelListener, Socks5TunnelListener, TcpTunnelListener, UdpTunnelListener,
};
use crate::tunnel::server::{TlsServerConfig, WsServer, WsServerConfig};
use crate::tunnel::{to_host_port, LocalProtocol, RemoteAddr, TransportAddr, TransportScheme};
use crate::tunnel::transport::{TransportAddr, TransportScheme};
use crate::tunnel::{to_host_port, LocalProtocol, RemoteAddr};
use anyhow::{anyhow, Context};
use base64::Engine;
use clap::Parser;

View file

@ -10,7 +10,7 @@ use tokio_rustls::client::TlsStream;
use crate::tunnel::client::WsClientConfig;
use crate::tunnel::server::TlsServerConfig;
use crate::tunnel::TransportAddr;
use crate::tunnel::transport::TransportAddr;
use tokio_rustls::rustls::client::danger::{HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier};
use tokio_rustls::rustls::pki_types::{CertificateDer, PrivateKeyDer, ServerName, UnixTime};
use tokio_rustls::rustls::server::WebPkiClientVerifier;

View file

@ -5,8 +5,8 @@ use crate::tunnel::connectors::TunnelConnector;
use crate::tunnel::listeners::TunnelListener;
use crate::tunnel::tls_reloader::TlsReloader;
use crate::tunnel::transport::io::{TunnelReader, TunnelWriter};
use crate::tunnel::transport::jwt_token_to_tunnel;
use crate::tunnel::{RemoteAddr, TransportScheme};
use crate::tunnel::transport::{jwt_token_to_tunnel, TransportScheme};
use crate::tunnel::RemoteAddr;
use anyhow::Context;
use futures_util::pin_mut;
use hyper::header::COOKIE;

View file

@ -1,5 +1,5 @@
use crate::protocols::dns::DnsResolver;
use crate::tunnel::TransportAddr;
use crate::tunnel::transport::TransportAddr;
use hyper::header::{HeaderName, HeaderValue};
use once_cell::sync::Lazy;
use parking_lot::RwLock;
@ -29,17 +29,6 @@ pub struct WsClientConfig {
}
impl WsClientConfig {
pub const fn websocket_scheme(&self) -> &'static str {
match self.remote_addr.tls().is_some() {
false => "ws",
true => "wss",
}
}
pub fn websocket_host_url(&self) -> String {
format!("{}:{}", self.remote_addr.host(), self.remote_addr.port())
}
pub fn tls_server_name(&self) -> ServerName<'static> {
static INVALID_DNS_NAME: Lazy<DnsName> = Lazy::new(|| DnsName::try_from("dns-name-invalid.com").unwrap());

View file

@ -3,14 +3,12 @@ pub mod connectors;
pub mod listeners;
pub mod server;
mod tls_reloader;
mod transport;
pub mod transport;
use crate::TlsClientConfig;
use serde::{Deserialize, Serialize};
use std::fmt::{Debug, Display, Formatter};
use std::fmt::Debug;
use std::net::{IpAddr, SocketAddr, SocketAddrV4, SocketAddrV6};
use std::path::PathBuf;
use std::str::FromStr;
use std::time::Duration;
use url::Host;
@ -72,7 +70,7 @@ impl LocalProtocol {
}
pub const fn is_dynamic_reverse_tunnel(&self) -> bool {
matches!(self, |Self::ReverseSocks5 { .. }| Self::ReverseHttpProxy { .. })
matches!(self, Self::ReverseSocks5 { .. } | Self::ReverseHttpProxy { .. })
}
}
@ -83,160 +81,6 @@ pub struct RemoteAddr {
pub port: u16,
}
#[derive(Copy, Clone, Debug)]
pub enum TransportScheme {
Ws,
Wss,
Http,
Https,
}
impl TransportScheme {
pub const fn values() -> &'static [Self] {
&[Self::Ws, Self::Wss, Self::Http, Self::Https]
}
pub const fn to_str(self) -> &'static str {
match self {
Self::Ws => "ws",
Self::Wss => "wss",
Self::Http => "http",
Self::Https => "https",
}
}
pub fn alpn_protocols(&self) -> Vec<Vec<u8>> {
match self {
Self::Ws => vec![],
Self::Wss => vec![b"http/1.1".to_vec()],
Self::Http => vec![],
Self::Https => vec![b"h2".to_vec()],
}
}
}
impl FromStr for TransportScheme {
type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"https" => Ok(Self::Https),
"http" => Ok(Self::Http),
"wss" => Ok(Self::Wss),
"ws" => Ok(Self::Ws),
_ => Err(()),
}
}
}
impl Display for TransportScheme {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.write_str(self.to_str())
}
}
#[derive(Clone)]
pub enum TransportAddr {
Wss {
tls: TlsClientConfig,
scheme: TransportScheme,
host: Host,
port: u16,
},
Ws {
scheme: TransportScheme,
host: Host,
port: u16,
},
Https {
scheme: TransportScheme,
tls: TlsClientConfig,
host: Host,
port: u16,
},
Http {
scheme: TransportScheme,
host: Host,
port: u16,
},
}
impl Debug for TransportAddr {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.write_fmt(format_args!("{}://{}:{}", self.scheme(), self.host(), self.port()))
}
}
impl TransportAddr {
pub fn new(scheme: TransportScheme, host: Host, port: u16, tls: Option<TlsClientConfig>) -> Option<Self> {
match scheme {
TransportScheme::Https => Some(Self::Https {
scheme: TransportScheme::Https,
tls: tls?,
host,
port,
}),
TransportScheme::Http => Some(Self::Http {
scheme: TransportScheme::Http,
host,
port,
}),
TransportScheme::Wss => Some(Self::Wss {
scheme: TransportScheme::Wss,
tls: tls?,
host,
port,
}),
TransportScheme::Ws => Some(Self::Ws {
scheme: TransportScheme::Ws,
host,
port,
}),
}
}
pub const fn is_websocket(&self) -> bool {
matches!(self, Self::Ws { .. } | Self::Wss { .. })
}
pub const fn is_http2(&self) -> bool {
matches!(self, Self::Http { .. } | Self::Https { .. })
}
pub const fn tls(&self) -> Option<&TlsClientConfig> {
match self {
Self::Wss { tls, .. } => Some(tls),
Self::Https { tls, .. } => Some(tls),
Self::Ws { .. } => None,
Self::Http { .. } => None,
}
}
pub const fn host(&self) -> &Host {
match self {
Self::Wss { host, .. } => host,
Self::Ws { host, .. } => host,
Self::Https { host, .. } => host,
Self::Http { host, .. } => host,
}
}
pub const fn port(&self) -> u16 {
match self {
Self::Wss { port, .. } => *port,
Self::Ws { port, .. } => *port,
Self::Https { port, .. } => *port,
Self::Http { port, .. } => *port,
}
}
pub const fn scheme(&self) -> &TransportScheme {
match self {
Self::Wss { scheme, .. } => scheme,
Self::Ws { scheme, .. } => scheme,
Self::Https { scheme, .. } => scheme,
Self::Http { scheme, .. } => scheme,
}
}
}
pub fn to_host_port(addr: SocketAddr) -> (Host, u16) {
match addr.ip() {
IpAddr::V4(ip) => (Host::Ipv4(ip), addr.port()),

View file

@ -1,6 +1,6 @@
use crate::tunnel::listeners::TunnelListener;
use crate::tunnel::RemoteAddr;
use ahash::{HashMap, HashMapExt};
use ahash::{AHashMap};
use anyhow::anyhow;
use futures_util::{pin_mut, StreamExt};
use log::warn;
@ -29,13 +29,13 @@ impl<T: TunnelListener> Clone for ReverseTunnelItem<T> {
}
pub struct ReverseTunnelServer<T: TunnelListener> {
servers: Arc<Mutex<HashMap<SocketAddr, ReverseTunnelItem<T>>>>,
servers: Arc<Mutex<AHashMap<SocketAddr, ReverseTunnelItem<T>>>>,
}
impl<T: TunnelListener> ReverseTunnelServer<T> {
pub fn new() -> Self {
Self {
servers: Arc::new(Mutex::new(HashMap::with_capacity(1))),
servers: Arc::new(Mutex::new(AHashMap::with_capacity(1))),
}
}

View file

@ -1,8 +1,8 @@
use super::io::{TunnelRead, TunnelWrite, MAX_PACKET_LENGTH};
use crate::tunnel::client::WsClient;
use crate::tunnel::transport::headers_from_file;
use crate::tunnel::transport::jwt::tunnel_to_jwt_token;
use crate::tunnel::{RemoteAddr, TransportScheme};
use crate::tunnel::transport::{headers_from_file, TransportScheme};
use crate::tunnel::RemoteAddr;
use anyhow::{anyhow, Context};
use bytes::{Bytes, BytesMut};
use http_body_util::{BodyExt, BodyStream, StreamBody};

View file

@ -9,11 +9,15 @@ use tracing::error;
pub mod http2;
pub mod io;
mod jwt;
mod types;
pub mod websocket;
pub use jwt::jwt_token_to_tunnel;
pub use jwt::tunnel_to_jwt_token;
pub use jwt::JwtTunnelConfig;
pub use jwt::JWT_HEADER_PREFIX;
pub use types::TransportAddr;
pub use types::TransportScheme;
#[allow(clippy::type_complexity)]
#[inline]

View file

@ -0,0 +1,151 @@
use crate::tunnel::client::TlsClientConfig;
use std::fmt::{Debug, Display, Formatter};
use std::str::FromStr;
use url::Host;
#[derive(Copy, Clone, Debug)]
pub enum TransportScheme {
Ws,
Wss,
Http,
Https,
}
impl TransportScheme {
pub const fn values() -> &'static [Self] {
&[Self::Ws, Self::Wss, Self::Http, Self::Https]
}
pub const fn to_str(self) -> &'static str {
match self {
Self::Ws => "ws",
Self::Wss => "wss",
Self::Http => "http",
Self::Https => "https",
}
}
pub fn alpn_protocols(&self) -> Vec<Vec<u8>> {
match self {
Self::Ws => vec![],
Self::Wss => vec![b"http/1.1".to_vec()],
Self::Http => vec![],
Self::Https => vec![b"h2".to_vec()],
}
}
}
impl FromStr for TransportScheme {
type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"https" => Ok(Self::Https),
"http" => Ok(Self::Http),
"wss" => Ok(Self::Wss),
"ws" => Ok(Self::Ws),
_ => Err(()),
}
}
}
impl Display for TransportScheme {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.write_str(self.to_str())
}
}
#[derive(Clone)]
pub enum TransportAddr {
Wss {
tls: TlsClientConfig,
scheme: TransportScheme,
host: Host,
port: u16,
},
Ws {
scheme: TransportScheme,
host: Host,
port: u16,
},
Https {
scheme: TransportScheme,
tls: TlsClientConfig,
host: Host,
port: u16,
},
Http {
scheme: TransportScheme,
host: Host,
port: u16,
},
}
impl Debug for TransportAddr {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.write_fmt(format_args!("{}://{}:{}", self.scheme(), self.host(), self.port()))
}
}
impl TransportAddr {
pub fn new(scheme: TransportScheme, host: Host, port: u16, tls: Option<TlsClientConfig>) -> Option<Self> {
match scheme {
TransportScheme::Https => Some(Self::Https {
scheme: TransportScheme::Https,
tls: tls?,
host,
port,
}),
TransportScheme::Http => Some(Self::Http {
scheme: TransportScheme::Http,
host,
port,
}),
TransportScheme::Wss => Some(Self::Wss {
scheme: TransportScheme::Wss,
tls: tls?,
host,
port,
}),
TransportScheme::Ws => Some(Self::Ws {
scheme: TransportScheme::Ws,
host,
port,
}),
}
}
pub const fn tls(&self) -> Option<&TlsClientConfig> {
match self {
Self::Wss { tls, .. } => Some(tls),
Self::Https { tls, .. } => Some(tls),
Self::Ws { .. } => None,
Self::Http { .. } => None,
}
}
pub const fn host(&self) -> &Host {
match self {
Self::Wss { host, .. } => host,
Self::Ws { host, .. } => host,
Self::Https { host, .. } => host,
Self::Http { host, .. } => host,
}
}
pub const fn port(&self) -> u16 {
match self {
Self::Wss { port, .. } => *port,
Self::Ws { port, .. } => *port,
Self::Https { port, .. } => *port,
Self::Http { port, .. } => *port,
}
}
pub const fn scheme(&self) -> &TransportScheme {
match self {
Self::Wss { scheme, .. } => scheme,
Self::Ws { scheme, .. } => scheme,
Self::Https { scheme, .. } => scheme,
Self::Http { scheme, .. } => scheme,
}
}
}