wstunnel/src/tunnel/mod.rs

159 lines
5.4 KiB
Rust
Raw Normal View History

pub mod client;
mod io;
pub mod server;
2023-12-29 17:03:43 +00:00
mod tls_reloader;
use crate::dns::DnsResolver;
2023-10-28 13:55:14 +00:00
use crate::{tcp, tls, LocalProtocol, LocalToRemote, WsClientConfig};
use async_trait::async_trait;
use bb8::ManageConnection;
use jsonwebtoken::{Algorithm, DecodingKey, EncodingKey, Header, Validation};
use once_cell::sync::Lazy;
use serde::{Deserialize, Serialize};
use std::collections::HashSet;
2023-10-28 13:55:14 +00:00
use std::io::{Error, IoSlice};
2023-12-01 19:20:33 +00:00
use std::net::{IpAddr, SocketAddr};
2023-10-28 13:55:14 +00:00
use std::pin::Pin;
use std::task::{Context, Poll};
use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
use tokio::net::TcpStream;
use tokio_rustls::client::TlsStream;
2023-12-01 19:20:33 +00:00
use url::Host;
2023-10-28 13:55:14 +00:00
use uuid::Uuid;
#[derive(Debug, Clone, Serialize, Deserialize)]
struct JwtTunnelConfig {
pub id: String,
pub p: LocalProtocol,
pub r: String,
pub rp: u16,
}
2023-10-28 13:55:14 +00:00
impl JwtTunnelConfig {
fn new(request_id: Uuid, tunnel: &LocalToRemote) -> Self {
Self {
id: request_id.to_string(),
p: match tunnel.local_protocol {
LocalProtocol::Tcp => LocalProtocol::Tcp,
LocalProtocol::Udp { .. } => tunnel.local_protocol,
LocalProtocol::Stdio => LocalProtocol::Tcp,
LocalProtocol::Socks5 => LocalProtocol::Tcp,
2023-11-26 14:47:49 +00:00
LocalProtocol::ReverseTcp => LocalProtocol::ReverseTcp,
2023-11-26 17:22:28 +00:00
LocalProtocol::ReverseUdp { .. } => tunnel.local_protocol,
2023-12-01 21:25:01 +00:00
LocalProtocol::ReverseSocks5 => LocalProtocol::ReverseSocks5,
2023-12-01 19:20:33 +00:00
LocalProtocol::TProxyTcp => LocalProtocol::Tcp,
2023-12-03 09:24:31 +00:00
LocalProtocol::TProxyUdp { timeout } => LocalProtocol::Udp { timeout },
2023-10-28 13:55:14 +00:00
},
r: tunnel.remote.0.to_string(),
rp: tunnel.remote.1,
}
}
}
static JWT_HEADER_PREFIX: &str = "authorization.bearer.";
static JWT_SECRET: &[u8; 15] = b"champignonfrais";
2023-10-30 07:13:38 +00:00
static JWT_KEY: Lazy<(Header, EncodingKey)> =
Lazy::new(|| (Header::new(Algorithm::HS256), EncodingKey::from_secret(JWT_SECRET)));
static JWT_DECODE: Lazy<(Validation, DecodingKey)> = Lazy::new(|| {
let mut validation = Validation::new(Algorithm::HS256);
validation.required_spec_claims = HashSet::with_capacity(0);
(validation, DecodingKey::from_secret(JWT_SECRET))
});
2023-10-28 13:55:14 +00:00
pub enum TransportStream {
Plain(TcpStream),
Tls(TlsStream<TcpStream>),
}
impl AsyncRead for TransportStream {
2023-10-30 07:13:38 +00:00
fn poll_read(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &mut ReadBuf<'_>) -> Poll<std::io::Result<()>> {
2023-10-28 13:55:14 +00:00
match self.get_mut() {
TransportStream::Plain(cnx) => Pin::new(cnx).poll_read(cx, buf),
TransportStream::Tls(cnx) => Pin::new(cnx).poll_read(cx, buf),
}
}
}
2023-10-28 13:55:14 +00:00
impl AsyncWrite for TransportStream {
2023-10-30 07:13:38 +00:00
fn poll_write(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8]) -> Poll<Result<usize, Error>> {
2023-10-28 13:55:14 +00:00
match self.get_mut() {
TransportStream::Plain(cnx) => Pin::new(cnx).poll_write(cx, buf),
TransportStream::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() {
TransportStream::Plain(cnx) => Pin::new(cnx).poll_flush(cx),
TransportStream::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() {
TransportStream::Plain(cnx) => Pin::new(cnx).poll_shutdown(cx),
TransportStream::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() {
TransportStream::Plain(cnx) => Pin::new(cnx).poll_write_vectored(cx, bufs),
TransportStream::Tls(cnx) => Pin::new(cnx).poll_write_vectored(cx, bufs),
}
}
fn is_write_vectored(&self) -> bool {
match &self {
TransportStream::Plain(cnx) => cnx.is_write_vectored(),
TransportStream::Tls(cnx) => cnx.is_write_vectored(),
}
}
}
#[async_trait]
impl ManageConnection for WsClientConfig {
2023-10-28 13:55:14 +00:00
type Connection = Option<TransportStream>;
type Error = anyhow::Error;
async fn connect(&self) -> Result<Self::Connection, Self::Error> {
let (host, port) = &self.remote_addr;
2023-11-26 17:22:28 +00:00
let so_mark = self.socket_so_mark;
let timeout = self.timeout_connect;
let tcp_stream = if let Some(http_proxy) = &self.http_proxy {
tcp::connect_with_http_proxy(http_proxy, host, *port, so_mark, timeout).await?
} else {
tcp::connect(host, *port, so_mark, timeout, &DnsResolver::System).await?
};
match &self.tls {
2023-10-28 13:55:14 +00:00
None => Ok(Some(TransportStream::Plain(tcp_stream))),
Some(tls_cfg) => {
let tls_stream = tls::connect(self, tls_cfg, tcp_stream).await?;
2023-10-28 13:55:14 +00:00
Ok(Some(TransportStream::Tls(tls_stream)))
}
}
}
async fn is_valid(&self, _conn: &mut Self::Connection) -> Result<(), Self::Error> {
Ok(())
}
fn has_broken(&self, conn: &mut Self::Connection) -> bool {
2023-10-28 13:55:14 +00:00
conn.is_none()
}
}
2023-12-01 19:20:33 +00:00
pub fn to_host_port(addr: SocketAddr) -> (Host, u16) {
match addr.ip() {
IpAddr::V4(ip) => (Host::Ipv4(ip), addr.port()),
IpAddr::V6(ip) => (Host::Ipv6(ip), addr.port()),
}
}