Merge the two binaries (client and server) into a single one #1
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"
|
||||
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",
|
||||
]
|
||||
|
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 = [
|
||||
"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"
|
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
|
||||
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.
|
||||
|
@ -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 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![];
|
@ -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);
|
@ -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;
|
@ -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);
|
@ -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
|
@ -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>>,
|
@ -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