Merge pull request 'Merge the two binaries (client and server) into a single one' (#1) from merge-binaries into master

Reviewed-on: #1
This commit is contained in:
Pierre HUBERT 2022-09-01 08:16:46 +00:00
commit caa62b8e49
20 changed files with 107 additions and 130 deletions

36
Cargo.lock generated
View File

@ -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",
]

View File

@ -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"

View File

@ -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.

View File

@ -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"

3
src/lib.rs Normal file
View File

@ -0,0 +1,3 @@
mod base;
pub mod tcp_relay_client;
pub mod tcp_relay_server;

38
src/main.rs Normal file
View File

@ -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,
}
}

View File

@ -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<RemoteConfig, Box<dyn
}
/// Core logic of the application
pub async fn run_app(mut args: ClientConfig) -> Result<(), Box<dyn Error>> {
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<dyn Error>> {
}
// 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![];

View File

@ -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<ClientConfig>) {
log::info!("Start to listen on {}", listen_address);

View File

@ -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;

View File

@ -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);

View File

@ -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

View File

@ -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<Arc<dyn ClientCertVerifier>>,

View File

@ -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"

View File

@ -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<dyn Error>> {
env_logger::init_from_env(env_logger::Env::new().default_filter_or("info"));
tcp_relay_client::run_app(ClientConfig::parse()).await
}

View File

@ -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"

View File

@ -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
}