From b24e8ba68bfaa0e99d5c88b06b520ad6b5385a40 Mon Sep 17 00:00:00 2001 From: Pierre Hubert Date: Thu, 1 Sep 2022 10:11:24 +0200 Subject: [PATCH 1/2] Merged all workspace projects into a single binary project --- Cargo.lock | 36 ++++-------------- Cargo.toml | 32 +++++++++++++--- base/Cargo.toml | 9 ----- {base/src => src/base}/cert_utils.rs | 0 base/src/lib.rs => src/base/mod.rs | 0 {base/src => src/base}/structs.rs | 0 src/lib.rs | 3 ++ src/main.rs | 38 +++++++++++++++++++ .../tcp_relay_client}/client_config.rs | 0 .../src/lib.rs => src/tcp_relay_client/mod.rs | 17 ++++++--- .../tcp_relay_client}/relay_client.rs | 4 +- .../src/lib.rs => src/tcp_relay_server/mod.rs | 8 ++-- .../src => src/tcp_relay_server}/relay_ws.rs | 2 +- .../tcp_relay_server}/server_config.rs | 4 +- .../tls_cert_client_verifier.rs | 4 +- tcp_relay_client/Cargo.toml | 19 ---------- tcp_relay_client/src/main.rs | 11 ------ tcp_relay_server/Cargo.toml | 22 ----------- tcp_relay_server/src/main.rs | 10 ----- 19 files changed, 96 insertions(+), 123 deletions(-) delete mode 100644 base/Cargo.toml rename {base/src => src/base}/cert_utils.rs (100%) rename base/src/lib.rs => src/base/mod.rs (100%) rename {base/src => src/base}/structs.rs (100%) create mode 100644 src/lib.rs create mode 100644 src/main.rs rename {tcp_relay_client/src => src/tcp_relay_client}/client_config.rs (100%) rename tcp_relay_client/src/lib.rs => src/tcp_relay_client/mod.rs (85%) rename {tcp_relay_client/src => src/tcp_relay_client}/relay_client.rs (98%) rename tcp_relay_server/src/lib.rs => src/tcp_relay_server/mod.rs (94%) rename {tcp_relay_server/src => src/tcp_relay_server}/relay_ws.rs (99%) rename {tcp_relay_server/src => src/tcp_relay_server}/server_config.rs (93%) rename {tcp_relay_server/src => src/tcp_relay_server}/tls_cert_client_verifier.rs (96%) delete mode 100644 tcp_relay_client/Cargo.toml delete mode 100644 tcp_relay_client/src/main.rs delete mode 100644 tcp_relay_server/Cargo.toml delete mode 100644 tcp_relay_server/src/main.rs diff --git a/Cargo.lock b/Cargo.lock index 30be93c..a4d754d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -350,15 +350,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" -[[package]] -name = "base" -version = "0.1.0" -dependencies = [ - "rustls", - "rustls-pemfile", - "serde", -] - [[package]] name = "base64" version = "0.13.0" @@ -1598,40 +1589,27 @@ dependencies = [ ] [[package]] -name = "tcp_relay_client" -version = "0.1.0" -dependencies = [ - "base", - "bytes", - "clap", - "env_logger", - "futures", - "hyper-rustls", - "log", - "reqwest", - "rustls", - "tokio", - "tokio-tungstenite", - "urlencoding", -] - -[[package]] -name = "tcp_relay_server" +name = "tcp_over_http" version = "0.1.0" dependencies = [ "actix", "actix-tls", "actix-web", "actix-web-actors", - "base", + "bytes", "clap", "env_logger", "futures", + "hyper-rustls", "log", "pem", + "reqwest", "rustls", + "rustls-pemfile", "serde", "tokio", + "tokio-tungstenite", + "urlencoding", "webpki", "x509-parser", ] diff --git a/Cargo.toml b/Cargo.toml index 48e1494..4a1925e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,27 @@ -[workspace] +[package] +name = "tcp_over_http" +version = "0.1.0" +edition = "2021" +description = "TCP-over-HTTP solution" -members = [ - "base", - "tcp_relay_server", - "tcp_relay_client", -] +[dependencies] +clap = { version = "3.2.18", features = ["derive", "env"] } +log = "0.4.17" +env_logger = "0.9.0" +actix = "0.13.0" +actix-web = { version = "4", features = ["rustls"] } +actix-web-actors = "4.1.0" +actix-tls = "3.0.3" +serde = { version = "1.0.144", features = ["derive"] } +tokio = { version = "1", features = ["full"] } +futures = "0.3.24" +webpki = "0.22.0" +x509-parser = "0.14.0" +pem = "1.1.0" +reqwest = { version = "0.11", features = ["json", "rustls-tls"], default-features = false } +tokio-tungstenite = { version = "0.17.2", features = ["__rustls-tls", "rustls-tls-native-roots"] } +urlencoding = "2.1.0" +hyper-rustls = { version = "0.23.0", features = ["rustls-native-certs"] } +bytes = "1.2.1" +rustls-pemfile = "1.0.1" +rustls = "0.20.6" \ No newline at end of file diff --git a/base/Cargo.toml b/base/Cargo.toml deleted file mode 100644 index 63654c4..0000000 --- a/base/Cargo.toml +++ /dev/null @@ -1,9 +0,0 @@ -[package] -name = "base" -version = "0.1.0" -edition = "2021" - -[dependencies] -serde = { version = "1.0.144", features = ["derive"] } -rustls-pemfile = "1.0.1" -rustls = "0.20.6" \ No newline at end of file diff --git a/base/src/cert_utils.rs b/src/base/cert_utils.rs similarity index 100% rename from base/src/cert_utils.rs rename to src/base/cert_utils.rs diff --git a/base/src/lib.rs b/src/base/mod.rs similarity index 100% rename from base/src/lib.rs rename to src/base/mod.rs diff --git a/base/src/structs.rs b/src/base/structs.rs similarity index 100% rename from base/src/structs.rs rename to src/base/structs.rs diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..841881a --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,3 @@ +mod base; +pub mod tcp_relay_client; +pub mod tcp_relay_server; diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..1b00bdc --- /dev/null +++ b/src/main.rs @@ -0,0 +1,38 @@ +use clap::{Parser, Subcommand}; + +use tcp_over_http::tcp_relay_client::client_config::ClientConfig; +use tcp_over_http::tcp_relay_server::server_config::ServerConfig; + +#[derive(Parser, Debug)] +#[clap( + author, + version, + about, + long_about = "Encapsulate TCP sockets inside HTTP WebSockets" +)] +struct CliArgs { + #[clap(subcommand)] + command: SubCommands, +} + +#[derive(Subcommand, Debug)] +enum SubCommands { + /// Run as server + Server(ServerConfig), + + /// Run as client + Client(ClientConfig), +} + +#[actix_web::main] +async fn main() -> std::io::Result<()> { + env_logger::init_from_env(env_logger::Env::new().default_filter_or("info")); + + let args: CliArgs = CliArgs::parse(); + + // Dispatch the request to the appropriate part of the program + match args.command { + SubCommands::Server(c) => tcp_over_http::tcp_relay_server::run_app(c).await, + SubCommands::Client(c) => tcp_over_http::tcp_relay_client::run_app(c).await, + } +} diff --git a/tcp_relay_client/src/client_config.rs b/src/tcp_relay_client/client_config.rs similarity index 100% rename from tcp_relay_client/src/client_config.rs rename to src/tcp_relay_client/client_config.rs diff --git a/tcp_relay_client/src/lib.rs b/src/tcp_relay_client/mod.rs similarity index 85% rename from tcp_relay_client/src/lib.rs rename to src/tcp_relay_client/mod.rs index e1b49cf..8010952 100644 --- a/tcp_relay_client/src/lib.rs +++ b/src/tcp_relay_client/mod.rs @@ -6,10 +6,9 @@ use std::sync::Arc; use futures::future::join_all; use reqwest::{Certificate, Identity}; -use base::RemoteConfig; - -use crate::client_config::ClientConfig; -use crate::relay_client::relay_client; +use crate::base::RemoteConfig; +use crate::tcp_relay_client::client_config::ClientConfig; +use crate::tcp_relay_client::relay_client::relay_client; pub mod client_config; mod relay_client; @@ -51,7 +50,7 @@ async fn get_server_config(conf: &ClientConfig) -> Result Result<(), Box> { +pub async fn run_app(mut args: ClientConfig) -> std::io::Result<()> { args.load_certificates(); let args = Arc::new(args); @@ -68,7 +67,13 @@ pub async fn run_app(mut args: ClientConfig) -> Result<(), Box> { } // Get server relay configuration (fetch the list of port to forward) - let remote_conf = get_server_config(&args).await?; + let remote_conf = match get_server_config(&args).await { + Ok(c) => c, + Err(e) => { + log::error!("Failed to fetch relay configuration from server! {}", e); + panic!(); + } + }; // Start to listen port let mut handles = vec![]; diff --git a/tcp_relay_client/src/relay_client.rs b/src/tcp_relay_client/relay_client.rs similarity index 98% rename from tcp_relay_client/src/relay_client.rs rename to src/tcp_relay_client/relay_client.rs index e77a4b3..eb44be1 100644 --- a/tcp_relay_client/src/relay_client.rs +++ b/src/tcp_relay_client/relay_client.rs @@ -7,9 +7,9 @@ use tokio::io::{AsyncReadExt, AsyncWriteExt}; use tokio::net::{TcpListener, TcpStream}; use tokio_tungstenite::tungstenite::Message; -use base::cert_utils; +use crate::base::cert_utils; -use crate::client_config::ClientConfig; +use crate::tcp_relay_client::client_config::ClientConfig; pub async fn relay_client(ws_url: String, listen_address: String, config: Arc) { log::info!("Start to listen on {}", listen_address); diff --git a/tcp_relay_server/src/lib.rs b/src/tcp_relay_server/mod.rs similarity index 94% rename from tcp_relay_server/src/lib.rs rename to src/tcp_relay_server/mod.rs index 7fa1859..aefea39 100644 --- a/tcp_relay_server/src/lib.rs +++ b/src/tcp_relay_server/mod.rs @@ -3,11 +3,11 @@ use std::sync::Arc; use actix_web::web::Data; use actix_web::{middleware, web, App, HttpRequest, HttpResponse, HttpServer, Responder}; -use base::{cert_utils, RelayedPort}; +use crate::base::{cert_utils, RelayedPort}; -use crate::relay_ws::relay_ws; -use crate::server_config::ServerConfig; -use crate::tls_cert_client_verifier::CustomCertClientVerifier; +use crate::tcp_relay_server::relay_ws::relay_ws; +use crate::tcp_relay_server::server_config::ServerConfig; +use crate::tcp_relay_server::tls_cert_client_verifier::CustomCertClientVerifier; mod relay_ws; pub mod server_config; diff --git a/tcp_relay_server/src/relay_ws.rs b/src/tcp_relay_server/relay_ws.rs similarity index 99% rename from tcp_relay_server/src/relay_ws.rs rename to src/tcp_relay_server/relay_ws.rs index 56a4707..32f58f3 100644 --- a/tcp_relay_server/src/relay_ws.rs +++ b/src/tcp_relay_server/relay_ws.rs @@ -9,7 +9,7 @@ use tokio::io::{AsyncReadExt, AsyncWriteExt}; use tokio::net::tcp::{OwnedReadHalf, OwnedWriteHalf}; use tokio::net::TcpStream; -use crate::server_config::ServerConfig; +use crate::tcp_relay_server::server_config::ServerConfig; /// How often heartbeat pings are sent const HEARTBEAT_INTERVAL: Duration = Duration::from_secs(5); diff --git a/tcp_relay_server/src/server_config.rs b/src/tcp_relay_server/server_config.rs similarity index 93% rename from tcp_relay_server/src/server_config.rs rename to src/tcp_relay_server/server_config.rs index 82b5201..838ca40 100644 --- a/tcp_relay_server/src/server_config.rs +++ b/src/tcp_relay_server/server_config.rs @@ -1,12 +1,12 @@ use clap::Parser; -/// TCP relay server +/// TCP relay server mode #[derive(Parser, Debug, Clone)] #[clap( author, version, about, - long_about = "TCP-over-HTTP server. This program might be configured behind a reverse-proxy." + long_about = "TCP-over-HTTP server. This program can be configured behind a reverse-proxy (without TLS authentication)." )] pub struct ServerConfig { /// Access tokens diff --git a/tcp_relay_server/src/tls_cert_client_verifier.rs b/src/tcp_relay_server/tls_cert_client_verifier.rs similarity index 96% rename from tcp_relay_server/src/tls_cert_client_verifier.rs rename to src/tcp_relay_server/tls_cert_client_verifier.rs index 5b50ceb..806b9b7 100644 --- a/tcp_relay_server/src/tls_cert_client_verifier.rs +++ b/src/tcp_relay_server/tls_cert_client_verifier.rs @@ -6,9 +6,9 @@ use rustls::server::{AllowAnyAuthenticatedClient, ClientCertVerified, ClientCert use rustls::{Certificate, DistinguishedNames, Error, RootCertStore}; use x509_parser::prelude::{CertificateRevocationList, FromDer, X509Certificate}; -use base::cert_utils::parse_pem_certificates; +use crate::base::cert_utils::parse_pem_certificates; -use crate::server_config::ServerConfig; +use crate::tcp_relay_server::server_config::ServerConfig; pub struct CustomCertClientVerifier { upstream_cert_verifier: Box>, diff --git a/tcp_relay_client/Cargo.toml b/tcp_relay_client/Cargo.toml deleted file mode 100644 index fa1e7cf..0000000 --- a/tcp_relay_client/Cargo.toml +++ /dev/null @@ -1,19 +0,0 @@ -[package] -name = "tcp_relay_client" -version = "0.1.0" -edition = "2021" -description = "TCP-over-HTTP client relay" - -[dependencies] -base = { path = "../base" } -clap = { version = "3.2.18", features = ["derive", "env"] } -log = "0.4.17" -env_logger = "0.9.0" -reqwest = { version = "0.11", features = ["json", "rustls-tls"], default-features = false } -tokio = { version = "1", features = ["full"] } -futures = "0.3.24" -tokio-tungstenite = { version = "0.17.2", features = ["__rustls-tls", "rustls-tls-native-roots"] } -urlencoding = "2.1.0" -rustls = { version = "0.20.6" } -hyper-rustls = { version = "0.23.0", features = ["rustls-native-certs"] } -bytes = "1.2.1" \ No newline at end of file diff --git a/tcp_relay_client/src/main.rs b/tcp_relay_client/src/main.rs deleted file mode 100644 index 9234c5e..0000000 --- a/tcp_relay_client/src/main.rs +++ /dev/null @@ -1,11 +0,0 @@ -use std::error::Error; - -use clap::Parser; - -use tcp_relay_client::client_config::ClientConfig; - -#[tokio::main] -async fn main() -> Result<(), Box> { - env_logger::init_from_env(env_logger::Env::new().default_filter_or("info")); - tcp_relay_client::run_app(ClientConfig::parse()).await -} diff --git a/tcp_relay_server/Cargo.toml b/tcp_relay_server/Cargo.toml deleted file mode 100644 index 74aba65..0000000 --- a/tcp_relay_server/Cargo.toml +++ /dev/null @@ -1,22 +0,0 @@ -[package] -name = "tcp_relay_server" -version = "0.1.0" -edition = "2021" -description = "TCP-over-HTTP server relay" - -[dependencies] -base = { path = "../base" } -clap = { version = "3.2.18", features = ["derive", "env"] } -log = "0.4.17" -env_logger = "0.9.0" -actix = "0.13.0" -actix-web = { version = "4", features = ["rustls"] } -actix-web-actors = "4.1.0" -actix-tls = "3.0.3" -serde = { version = "1.0.144", features = ["derive"] } -tokio = { version = "1", features = ["full"] } -futures = "0.3.24" -rustls = "0.20.6" -webpki = "0.22.0" -x509-parser = "0.14.0" -pem = "1.1.0" \ No newline at end of file diff --git a/tcp_relay_server/src/main.rs b/tcp_relay_server/src/main.rs deleted file mode 100644 index 3636c5e..0000000 --- a/tcp_relay_server/src/main.rs +++ /dev/null @@ -1,10 +0,0 @@ -use clap::Parser; - -use tcp_relay_server::server_config::ServerConfig; - -#[actix_web::main] -async fn main() -> std::io::Result<()> { - env_logger::init_from_env(env_logger::Env::new().default_filter_or("info")); - - tcp_relay_server::run_app(ServerConfig::parse()).await -} From 7c64003b139bb88ca9412fe279f5972ab8da3be6 Mon Sep 17 00:00:00 2001 From: Pierre Hubert Date: Thu, 1 Sep 2022 10:16:02 +0200 Subject: [PATCH 2/2] Update README --- README.MD | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/README.MD b/README.MD index 3f5cd48..739ce70 100644 --- a/README.MD +++ b/README.MD @@ -10,20 +10,24 @@ This project aims to provide an easy-to-setup TCP forwarding solution: ``` This project can be used especially to bypass firewalls that blocks traffics -from ports others than the HTTP / HTTPS ports. +from ports others than the HTTP / HTTPS ports. The TCP traffic is encapsulated inside an +HTTP WebSocket between the client and the server relays. ## Authentication -The client can authenticate agains the server relays through two different means: +The client can authenticate against the server relays through two different means: -* Using a token +* Using a token (the server relay can have several tokens at the same time) * Using a client TLS certificate. In this case, the server relay must act as a HTTPS server, and you must provide the server the required certificates / key files in PEM format. It is also possible to provide the server a CRL file. -## Binaries -This repository contains two binaries: +## Binary +This repository contains a single binary which can be used as a server or a client, depending of command line arguments: -* `tpc_relay_server`: The server relay. In case of token authentication, it can be put behind a reverse proxy. -* `tcp_relay_client`: The client relay +* Server mode: Act as a server relay. In case of token authentication (NOT TLS authentication), it can be put behind a reverse proxy. +* Client mode: Act as a client relay. It basically does three things: + * Fetch the list of forwared ports configuration from the server + * Listen to these port locally + * When a connection occurs on one of these ports, it forward the data exchanged by the socket to and from the server. A single server - client relay pair can relay multiple ports simultaneously from the same machine.