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:
commit
caa62b8e49
36
Cargo.lock
generated
36
Cargo.lock
generated
@ -350,15 +350,6 @@ version = "1.1.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "base"
|
|
||||||
version = "0.1.0"
|
|
||||||
dependencies = [
|
|
||||||
"rustls",
|
|
||||||
"rustls-pemfile",
|
|
||||||
"serde",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "base64"
|
name = "base64"
|
||||||
version = "0.13.0"
|
version = "0.13.0"
|
||||||
@ -1598,40 +1589,27 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tcp_relay_client"
|
name = "tcp_over_http"
|
||||||
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"
|
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"actix",
|
"actix",
|
||||||
"actix-tls",
|
"actix-tls",
|
||||||
"actix-web",
|
"actix-web",
|
||||||
"actix-web-actors",
|
"actix-web-actors",
|
||||||
"base",
|
"bytes",
|
||||||
"clap",
|
"clap",
|
||||||
"env_logger",
|
"env_logger",
|
||||||
"futures",
|
"futures",
|
||||||
|
"hyper-rustls",
|
||||||
"log",
|
"log",
|
||||||
"pem",
|
"pem",
|
||||||
|
"reqwest",
|
||||||
"rustls",
|
"rustls",
|
||||||
|
"rustls-pemfile",
|
||||||
"serde",
|
"serde",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
"tokio-tungstenite",
|
||||||
|
"urlencoding",
|
||||||
"webpki",
|
"webpki",
|
||||||
"x509-parser",
|
"x509-parser",
|
||||||
]
|
]
|
||||||
|
32
Cargo.toml
32
Cargo.toml
@ -1,7 +1,27 @@
|
|||||||
[workspace]
|
[package]
|
||||||
|
name = "tcp_over_http"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
description = "TCP-over-HTTP solution"
|
||||||
|
|
||||||
members = [
|
[dependencies]
|
||||||
"base",
|
clap = { version = "3.2.18", features = ["derive", "env"] }
|
||||||
"tcp_relay_server",
|
log = "0.4.17"
|
||||||
"tcp_relay_client",
|
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"
|
18
README.MD
18
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
|
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
|
## 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
|
* 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.
|
server the required certificates / key files in PEM format. It is also possible to provide the server a CRL file.
|
||||||
|
|
||||||
|
|
||||||
## Binaries
|
## Binary
|
||||||
This repository contains two binaries:
|
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.
|
* Server mode: Act as a server relay. In case of token authentication (NOT TLS authentication), it can be put behind a reverse proxy.
|
||||||
* `tcp_relay_client`: The client relay
|
* 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.
|
A single server - client relay pair can relay multiple ports simultaneously from the same machine.
|
||||||
|
@ -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
3
src/lib.rs
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
mod base;
|
||||||
|
pub mod tcp_relay_client;
|
||||||
|
pub mod tcp_relay_server;
|
38
src/main.rs
Normal file
38
src/main.rs
Normal 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,
|
||||||
|
}
|
||||||
|
}
|
@ -6,10 +6,9 @@ use std::sync::Arc;
|
|||||||
use futures::future::join_all;
|
use futures::future::join_all;
|
||||||
use reqwest::{Certificate, Identity};
|
use reqwest::{Certificate, Identity};
|
||||||
|
|
||||||
use base::RemoteConfig;
|
use crate::base::RemoteConfig;
|
||||||
|
use crate::tcp_relay_client::client_config::ClientConfig;
|
||||||
use crate::client_config::ClientConfig;
|
use crate::tcp_relay_client::relay_client::relay_client;
|
||||||
use crate::relay_client::relay_client;
|
|
||||||
|
|
||||||
pub mod client_config;
|
pub mod client_config;
|
||||||
mod relay_client;
|
mod relay_client;
|
||||||
@ -51,7 +50,7 @@ async fn get_server_config(conf: &ClientConfig) -> Result<RemoteConfig, Box<dyn
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Core logic of the application
|
/// 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();
|
args.load_certificates();
|
||||||
let args = Arc::new(args);
|
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)
|
// 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
|
// Start to listen port
|
||||||
let mut handles = vec![];
|
let mut handles = vec![];
|
@ -7,9 +7,9 @@ use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
|||||||
use tokio::net::{TcpListener, TcpStream};
|
use tokio::net::{TcpListener, TcpStream};
|
||||||
use tokio_tungstenite::tungstenite::Message;
|
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>) {
|
pub async fn relay_client(ws_url: String, listen_address: String, config: Arc<ClientConfig>) {
|
||||||
log::info!("Start to listen on {}", listen_address);
|
log::info!("Start to listen on {}", listen_address);
|
@ -3,11 +3,11 @@ use std::sync::Arc;
|
|||||||
use actix_web::web::Data;
|
use actix_web::web::Data;
|
||||||
use actix_web::{middleware, web, App, HttpRequest, HttpResponse, HttpServer, Responder};
|
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::tcp_relay_server::relay_ws::relay_ws;
|
||||||
use crate::server_config::ServerConfig;
|
use crate::tcp_relay_server::server_config::ServerConfig;
|
||||||
use crate::tls_cert_client_verifier::CustomCertClientVerifier;
|
use crate::tcp_relay_server::tls_cert_client_verifier::CustomCertClientVerifier;
|
||||||
|
|
||||||
mod relay_ws;
|
mod relay_ws;
|
||||||
pub mod server_config;
|
pub mod server_config;
|
@ -9,7 +9,7 @@ use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
|||||||
use tokio::net::tcp::{OwnedReadHalf, OwnedWriteHalf};
|
use tokio::net::tcp::{OwnedReadHalf, OwnedWriteHalf};
|
||||||
use tokio::net::TcpStream;
|
use tokio::net::TcpStream;
|
||||||
|
|
||||||
use crate::server_config::ServerConfig;
|
use crate::tcp_relay_server::server_config::ServerConfig;
|
||||||
|
|
||||||
/// How often heartbeat pings are sent
|
/// How often heartbeat pings are sent
|
||||||
const HEARTBEAT_INTERVAL: Duration = Duration::from_secs(5);
|
const HEARTBEAT_INTERVAL: Duration = Duration::from_secs(5);
|
@ -1,12 +1,12 @@
|
|||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
|
|
||||||
/// TCP relay server
|
/// TCP relay server mode
|
||||||
#[derive(Parser, Debug, Clone)]
|
#[derive(Parser, Debug, Clone)]
|
||||||
#[clap(
|
#[clap(
|
||||||
author,
|
author,
|
||||||
version,
|
version,
|
||||||
about,
|
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 {
|
pub struct ServerConfig {
|
||||||
/// Access tokens
|
/// Access tokens
|
@ -6,9 +6,9 @@ use rustls::server::{AllowAnyAuthenticatedClient, ClientCertVerified, ClientCert
|
|||||||
use rustls::{Certificate, DistinguishedNames, Error, RootCertStore};
|
use rustls::{Certificate, DistinguishedNames, Error, RootCertStore};
|
||||||
use x509_parser::prelude::{CertificateRevocationList, FromDer, X509Certificate};
|
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 {
|
pub struct CustomCertClientVerifier {
|
||||||
upstream_cert_verifier: Box<Arc<dyn ClientCertVerifier>>,
|
upstream_cert_verifier: Box<Arc<dyn ClientCertVerifier>>,
|
@ -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"
|
|
@ -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
|
|
||||||
}
|
|
@ -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"
|
|
@ -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
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user