Merge branch 'master' into renovate/configure
This commit is contained in:
commit
dcb00ccc6e
13
.drone.yml
Normal file
13
.drone.yml
Normal file
@ -0,0 +1,13 @@
|
||||
---
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: default
|
||||
|
||||
steps:
|
||||
- name: cargo_check
|
||||
image: rust
|
||||
commands:
|
||||
- rustup component add clippy
|
||||
- cargo clippy
|
||||
- cargo test
|
||||
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,5 +1,3 @@
|
||||
target
|
||||
.idea
|
||||
*.crt
|
||||
*.key
|
||||
pki
|
||||
|
191
Cargo.lock
generated
191
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"
|
||||
@ -639,15 +630,6 @@ dependencies = [
|
||||
"termcolor",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fastrand"
|
||||
version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499"
|
||||
dependencies = [
|
||||
"instant",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "firestorm"
|
||||
version = "0.5.1"
|
||||
@ -670,21 +652,6 @@ version = "1.0.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
||||
|
||||
[[package]]
|
||||
name = "foreign-types"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
|
||||
dependencies = [
|
||||
"foreign-types-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "foreign-types-shared"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
|
||||
|
||||
[[package]]
|
||||
name = "form_urlencoded"
|
||||
version = "1.0.1"
|
||||
@ -924,19 +891,6 @@ dependencies = [
|
||||
"tokio-rustls",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hyper-tls"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"hyper",
|
||||
"native-tls",
|
||||
"tokio",
|
||||
"tokio-native-tls",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "0.2.3"
|
||||
@ -958,15 +912,6 @@ dependencies = [
|
||||
"hashbrown",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "instant"
|
||||
version = "0.1.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ipnet"
|
||||
version = "2.5.0"
|
||||
@ -1098,21 +1043,12 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "native-tls"
|
||||
version = "0.2.10"
|
||||
name = "mktemp"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fd7e2f3618557f980e0b17e8856252eee3c97fa12c54dff0ca290fb6266ca4a9"
|
||||
checksum = "975de676448231fcde04b9149d2543077e166b78fc29eae5aa219e7928410da2"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"libc",
|
||||
"log",
|
||||
"openssl",
|
||||
"openssl-probe",
|
||||
"openssl-sys",
|
||||
"schannel",
|
||||
"security-framework",
|
||||
"security-framework-sys",
|
||||
"tempfile",
|
||||
"uuid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1189,51 +1125,12 @@ version = "1.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "074864da206b4973b84eb91683020dbefd6a8c3f0f38e054d93954e891935e4e"
|
||||
|
||||
[[package]]
|
||||
name = "openssl"
|
||||
version = "0.10.41"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "618febf65336490dfcf20b73f885f5651a0c89c64c2d4a8c3662585a70bf5bd0"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cfg-if",
|
||||
"foreign-types",
|
||||
"libc",
|
||||
"once_cell",
|
||||
"openssl-macros",
|
||||
"openssl-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "openssl-macros"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "openssl-probe"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
|
||||
|
||||
[[package]]
|
||||
name = "openssl-sys"
|
||||
version = "0.9.75"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5f9bd0c2710541a3cda73d6f9ac4f1b240de4ae261065d309dbe73d9dceb42f"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"cc",
|
||||
"libc",
|
||||
"pkg-config",
|
||||
"vcpkg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "os_str_bytes"
|
||||
version = "6.3.0"
|
||||
@ -1296,12 +1193,6 @@ version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
||||
|
||||
[[package]]
|
||||
name = "pkg-config"
|
||||
version = "0.3.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae"
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.16"
|
||||
@ -1406,15 +1297,6 @@ version = "0.6.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244"
|
||||
|
||||
[[package]]
|
||||
name = "remove_dir_all"
|
||||
version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "reqwest"
|
||||
version = "0.11.11"
|
||||
@ -1431,13 +1313,11 @@ dependencies = [
|
||||
"http-body",
|
||||
"hyper",
|
||||
"hyper-rustls",
|
||||
"hyper-tls",
|
||||
"ipnet",
|
||||
"js-sys",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"mime",
|
||||
"native-tls",
|
||||
"percent-encoding",
|
||||
"pin-project-lite",
|
||||
"rustls",
|
||||
@ -1446,7 +1326,6 @@ dependencies = [
|
||||
"serde_json",
|
||||
"serde_urlencoded",
|
||||
"tokio",
|
||||
"tokio-native-tls",
|
||||
"tokio-rustls",
|
||||
"tower-service",
|
||||
"url",
|
||||
@ -1719,58 +1598,33 @@ 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",
|
||||
"mktemp",
|
||||
"pem",
|
||||
"rand",
|
||||
"reqwest",
|
||||
"rustls",
|
||||
"rustls-pemfile",
|
||||
"serde",
|
||||
"tokio",
|
||||
"tokio-tungstenite",
|
||||
"urlencoding",
|
||||
"webpki",
|
||||
"x509-parser",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tempfile"
|
||||
version = "3.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"fastrand",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
"remove_dir_all",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "termcolor"
|
||||
version = "1.1.3"
|
||||
@ -1871,16 +1725,6 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-native-tls"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f7d995660bd2b7f8c1568414c1126076c13fbb725c40112dc0120b78eb9b717b"
|
||||
dependencies = [
|
||||
"native-tls",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-rustls"
|
||||
version = "0.23.4"
|
||||
@ -2040,10 +1884,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
|
||||
|
||||
[[package]]
|
||||
name = "vcpkg"
|
||||
version = "0.2.15"
|
||||
name = "uuid"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
|
||||
checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
|
36
Cargo.toml
36
Cargo.toml
@ -1,7 +1,31 @@
|
||||
[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"
|
||||
|
||||
[dev-dependencies]
|
||||
rand = "0.8.5"
|
||||
mktemp = "0.4.1"
|
20
README.MD
20
README.MD
@ -1,4 +1,6 @@
|
||||
# TCP over HTTP
|
||||
[![Build Status](https://drone.communiquons.org/api/badges/pierre/tcp-over-http/status.svg)](https://drone.communiquons.org/pierre/tcp-over-http)
|
||||
|
||||
This project aims to provide an easy-to-setup TCP forwarding solution:
|
||||
|
||||
```
|
||||
@ -10,20 +12,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"
|
@ -1,37 +0,0 @@
|
||||
use std::error::Error;
|
||||
use std::io::{Cursor, ErrorKind};
|
||||
|
||||
use rustls::{Certificate, PrivateKey};
|
||||
use rustls_pemfile::{read_one, Item};
|
||||
|
||||
/// Parse PEM certificates bytes into a [`rustls::Certificate`] structure
|
||||
pub fn parse_pem_certificates(certs: &[u8]) -> Result<Vec<Certificate>, Box<dyn Error>> {
|
||||
Ok(rustls_pemfile::certs(&mut Cursor::new(certs))?
|
||||
.into_iter()
|
||||
.map(Certificate)
|
||||
.collect())
|
||||
}
|
||||
|
||||
/// Parse PEM private key bytes into a [`rustls::PrivateKey`] structure
|
||||
pub fn parse_pem_private_key(privkey: &[u8]) -> Result<PrivateKey, Box<dyn Error>> {
|
||||
let key = match read_one(&mut Cursor::new(privkey))? {
|
||||
None => {
|
||||
Err(std::io::Error::new(
|
||||
ErrorKind::Other,
|
||||
"Failed to extract private key!",
|
||||
))?;
|
||||
unreachable!()
|
||||
}
|
||||
Some(Item::PKCS8Key(key)) => key,
|
||||
Some(Item::RSAKey(key)) => key,
|
||||
_ => {
|
||||
Err(std::io::Error::new(
|
||||
ErrorKind::Other,
|
||||
"Unsupported private key type!",
|
||||
))?;
|
||||
unreachable!();
|
||||
}
|
||||
};
|
||||
|
||||
Ok(PrivateKey(key))
|
||||
}
|
87
src/base/cert_utils.rs
Normal file
87
src/base/cert_utils.rs
Normal file
@ -0,0 +1,87 @@
|
||||
use std::error::Error;
|
||||
use std::io::{Cursor, ErrorKind};
|
||||
|
||||
use rustls::{Certificate, PrivateKey};
|
||||
use rustls_pemfile::{read_one, Item};
|
||||
|
||||
/// Parse PEM certificates bytes into a [`rustls::Certificate`] structure
|
||||
///
|
||||
/// An error is returned if not any certificate could be found
|
||||
pub fn parse_pem_certificates(certs: &[u8]) -> Result<Vec<Certificate>, Box<dyn Error>> {
|
||||
let certs = rustls_pemfile::certs(&mut Cursor::new(certs))?
|
||||
.into_iter()
|
||||
.map(Certificate)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
if certs.is_empty() {
|
||||
Err(std::io::Error::new(
|
||||
ErrorKind::InvalidData,
|
||||
"Could not find any certificate!",
|
||||
))?;
|
||||
unreachable!();
|
||||
}
|
||||
|
||||
Ok(certs)
|
||||
}
|
||||
|
||||
/// Parse PEM private key bytes into a [`rustls::PrivateKey`] structure
|
||||
pub fn parse_pem_private_key(privkey: &[u8]) -> Result<PrivateKey, Box<dyn Error>> {
|
||||
let key = match read_one(&mut Cursor::new(privkey))? {
|
||||
None => {
|
||||
Err(std::io::Error::new(
|
||||
ErrorKind::Other,
|
||||
"Failed to extract private key!",
|
||||
))?;
|
||||
unreachable!()
|
||||
}
|
||||
Some(Item::PKCS8Key(key)) => key,
|
||||
Some(Item::RSAKey(key)) => key,
|
||||
_ => {
|
||||
Err(std::io::Error::new(
|
||||
ErrorKind::Other,
|
||||
"Unsupported private key type!",
|
||||
))?;
|
||||
unreachable!();
|
||||
}
|
||||
};
|
||||
|
||||
Ok(PrivateKey(key))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::base::cert_utils::{parse_pem_certificates, parse_pem_private_key};
|
||||
|
||||
const SAMPLE_CERT: &[u8] = include_bytes!("samples/TCPTunnelTest.crt");
|
||||
const SAMPLE_KEY: &[u8] = include_bytes!("samples/TCPTunnelTest.key");
|
||||
|
||||
#[test]
|
||||
fn parse_valid_cert() {
|
||||
parse_pem_certificates(SAMPLE_CERT).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_invalid_cert_1() {
|
||||
parse_pem_certificates("Random content".as_bytes()).unwrap_err();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_invalid_cert_2() {
|
||||
parse_pem_certificates(SAMPLE_KEY).unwrap_err();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_valid_key() {
|
||||
parse_pem_private_key(SAMPLE_KEY).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_invalid_key_1() {
|
||||
parse_pem_private_key("Random content".as_bytes()).unwrap_err();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_invalid_key_2() {
|
||||
parse_pem_private_key(SAMPLE_CERT).unwrap_err();
|
||||
}
|
||||
}
|
12
src/base/err_utils.rs
Normal file
12
src/base/err_utils.rs
Normal file
@ -0,0 +1,12 @@
|
||||
use std::fmt::Display;
|
||||
use std::io::ErrorKind;
|
||||
|
||||
/// Encapsulate errors in [`std::io::Error`] with a message
|
||||
pub fn encpasulate_error<E: Display, F: ToString>(e: E, msg: F) -> std::io::Error {
|
||||
std::io::Error::new(ErrorKind::Other, format!("{}:\n* {}", msg.to_string(), e))
|
||||
}
|
||||
|
||||
/// Create a new [`std::io::Error`]
|
||||
pub fn new_err(msg: &str) -> std::io::Error {
|
||||
std::io::Error::new(ErrorKind::Other, msg.to_string())
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
pub mod cert_utils;
|
||||
pub mod err_utils;
|
||||
mod structs;
|
||||
|
||||
pub use structs::{RelayedPort, RemoteConfig};
|
29
src/base/samples/TCPTunnelTest.crt
Normal file
29
src/base/samples/TCPTunnelTest.crt
Normal file
@ -0,0 +1,29 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIE8DCCAtigAwIBAgIBATANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDEw1UQ1BU
|
||||
dW5uZWxUZXN0MB4XDTIyMDkwMTA2MzMyMFoXDTI0MDMwMTA2MzMxOFowGDEWMBQG
|
||||
A1UEAxMNVENQVHVubmVsVGVzdDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC
|
||||
ggIBALqh3EXg3TYq5TwZPjOX35bM7kol+fLlwjLaXCTx/lTXU0hTFsIa0kFCiPsT
|
||||
Vhm5nwhDLxnAARagc74gUHfhr6meMbsje2NzylmCpW1As1s1xo2n8oNi2YsqIA9A
|
||||
HWQWsihf7fPlyZOgBIwUQBsLd6ujpwbvaEhwBArS+peVYuB3zDbuNBJ2lqdvD5fa
|
||||
8aCyoPyseaJcaMMJ3R2W/8OYrUsJECKgg26A8zxF55RdvjJcBONG0kRlNsrxS6uO
|
||||
9dnQ8kyvUReluPgTEfZm/M54dCi9VvKVRKA/5md/+SQWwQhPyIig3+XXeYQNoUN6
|
||||
YXvlWw704VBg/hDBqrY42LjpS/FyMGsp4cHVCMXBLwRNHWPfik6w3rNTpFp7h4Mm
|
||||
effxX2V/xuBr3IciVcsmeD4Xmfp0o6g3o5VPK4KIR5/b+aKe7uL8/9hTTLSqWpm8
|
||||
+k0boE796/gb8egyELwBrPsrdGQIiIP2Ac6m53iTtEtceIOmMB+t7mUPkQHsiLoC
|
||||
LeRm2dbPWEKz2mO8fOVjVYT9nxY92l/AveuksTui5GZ2z4ZVp1m6pAxVjVf+L/Sg
|
||||
MMkEfcIUW6Xb8Ba+KYRCc/5U8Xkz26F80dhjGdeledTpBhkyKqsxcKpLqFsuYj3W
|
||||
b5FfLBlQe/Yargqd8HhvgMydi+lHG14FAflhp8emnOGOzaPbAgMBAAGjRTBDMA4G
|
||||
A1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQWBBTQ9A38
|
||||
JD46Si69hfW4me3CJZNK0DANBgkqhkiG9w0BAQsFAAOCAgEAIpNieyvlaO0E5oUz
|
||||
1o7QJ+YtwwhPriOifrXAV+NaJj0n7Y1Fq4ztIhBPGtqwhPqgDUEn0G/mIr0BjA1w
|
||||
/zQGJx1U8g9wNP8SERKVtD4Gx4S1ruLzTqK1V4xyV6bRhqmfi+YHNKviFNAEDDfz
|
||||
rhiH1ULuoVfww8mH3FpL2oGhR+x900WkG98xtJ43ik/EIQu2kN+r5x9GPYC+NTC2
|
||||
xScVG3OGbJLE7fHDJBPSa5vOCk4DkBXKyOjYwnfd8Saz2E1u6w7eH3dgzCqiw66K
|
||||
lcksjKD4+F1t4Jhy1p/K3qzZsZQ/NpHH9v++LATtwvUN2bzPLiZ/LhV5QH/kg9Qf
|
||||
49OBRMKjUJ6MgQ7/JOwtaHyu8jBuJWUNEE47hpHGUrIxmLUi2AWlxxQZdPic+Rxf
|
||||
LKWoNlGx5OrzcIuIc3lb11zinRdaawOjVV0yCKWIlSkb77Flp8WJIlZ6ZHLtqwsU
|
||||
8D9zN4EXefc9dXYMLyWvRHmHOTr8430PebYc/G5BA+XjOgpFQ3vu8trIA/3Dbuyc
|
||||
ggz1abiDnBmp+I66AYV+Ker81maM6CQU+03WKHbHZyJWr74SKuILY1knys/fXJvT
|
||||
UZRMhmaQqxc1QcWVOkWLv0RcAhEjwIX0+36NUC1W35JfrRpHtmqIiJH9kjcjr94w
|
||||
5sjM2EUFmMC5z0zjF9cSYKSHLSI=
|
||||
-----END CERTIFICATE-----
|
51
src/base/samples/TCPTunnelTest.key
Normal file
51
src/base/samples/TCPTunnelTest.key
Normal file
@ -0,0 +1,51 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
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
|
||||
-----END RSA PRIVATE KEY-----
|
6
src/lib.rs
Normal file
6
src/lib.rs
Normal file
@ -0,0 +1,6 @@
|
||||
mod base;
|
||||
pub mod tcp_relay_client;
|
||||
pub mod tcp_relay_server;
|
||||
|
||||
#[cfg(test)]
|
||||
mod test;
|
49
src/main.rs
Normal file
49
src/main.rs
Normal file
@ -0,0 +1,49 @@
|
||||
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\nSource code: https://gitea.communiquons.org/pierre/tcp-over-http"
|
||||
)]
|
||||
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,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::CliArgs;
|
||||
|
||||
#[test]
|
||||
fn verify_cli() {
|
||||
use clap::CommandFactory;
|
||||
CliArgs::command().debug_assert()
|
||||
}
|
||||
}
|
@ -1,8 +1,9 @@
|
||||
use crate::base::err_utils::encpasulate_error;
|
||||
use bytes::BufMut;
|
||||
use clap::Parser;
|
||||
|
||||
/// TCP relay client
|
||||
#[derive(Parser, Debug, Clone)]
|
||||
#[derive(Parser, Debug, Clone, Default)]
|
||||
#[clap(author, version, about, long_about = None)]
|
||||
pub struct ClientConfig {
|
||||
/// Access token
|
||||
@ -21,41 +22,37 @@ pub struct ClientConfig {
|
||||
#[clap(short = 'c', long)]
|
||||
pub root_certificate: Option<String>,
|
||||
|
||||
#[clap(skip)]
|
||||
_root_certificate_cache: Option<Vec<u8>>,
|
||||
|
||||
/// TLS certificate for TLS authentication.
|
||||
#[clap(long)]
|
||||
pub tls_cert: Option<String>,
|
||||
|
||||
#[clap(skip)]
|
||||
_tls_cert_cache: Option<Vec<u8>>,
|
||||
|
||||
/// TLS key for TLS authentication.
|
||||
#[clap(long)]
|
||||
pub tls_key: Option<String>,
|
||||
|
||||
#[clap(skip)]
|
||||
pub _keys_cache: KeysCache,
|
||||
}
|
||||
|
||||
#[derive(Parser, Debug, Clone, Default)]
|
||||
pub struct KeysCache {
|
||||
#[clap(skip)]
|
||||
_root_certificate_cache: Option<Vec<u8>>,
|
||||
#[clap(skip)]
|
||||
_tls_cert_cache: Option<Vec<u8>>,
|
||||
#[clap(skip)]
|
||||
_tls_key_cache: Option<Vec<u8>>,
|
||||
}
|
||||
|
||||
impl ClientConfig {
|
||||
/// Load certificates and put them in cache
|
||||
pub fn load_certificates(&mut self) {
|
||||
self._root_certificate_cache = self
|
||||
.root_certificate
|
||||
.as_ref()
|
||||
.map(|c| std::fs::read(c).expect("Failed to read root certificate!"));
|
||||
|
||||
self._tls_cert_cache = self
|
||||
.tls_cert
|
||||
.as_ref()
|
||||
.map(|c| std::fs::read(c).expect("Failed to read client certificate!"));
|
||||
|
||||
self._tls_key_cache = self
|
||||
.tls_key
|
||||
.as_ref()
|
||||
.map(|c| std::fs::read(c).expect("Failed to read client key!"));
|
||||
pub fn load_certificates(&mut self) -> std::io::Result<()> {
|
||||
self._keys_cache = KeysCache {
|
||||
_root_certificate_cache: load_pem_file(&self.root_certificate, "root certificate")?,
|
||||
_tls_cert_cache: load_pem_file(&self.tls_cert, "client certificate")?,
|
||||
_tls_key_cache: load_pem_file(&self.tls_key, "client key")?,
|
||||
};
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Get client token, returning a dummy token if none was specified
|
||||
@ -65,12 +62,15 @@ impl ClientConfig {
|
||||
|
||||
/// Get root certificate content
|
||||
pub fn get_root_certificate(&self) -> Option<Vec<u8>> {
|
||||
self._root_certificate_cache.clone()
|
||||
self._keys_cache._root_certificate_cache.clone()
|
||||
}
|
||||
|
||||
/// Get client certificate & key pair, if available
|
||||
pub fn get_client_keypair(&self) -> Option<(&Vec<u8>, &Vec<u8>)> {
|
||||
if let (Some(cert), Some(key)) = (&self._tls_cert_cache, &self._tls_key_cache) {
|
||||
if let (Some(cert), Some(key)) = (
|
||||
&self._keys_cache._tls_cert_cache,
|
||||
&self._keys_cache._tls_key_cache,
|
||||
) {
|
||||
Some((cert, key))
|
||||
} else {
|
||||
None
|
||||
@ -88,9 +88,19 @@ impl ClientConfig {
|
||||
}
|
||||
}
|
||||
|
||||
fn load_pem_file(path: &Option<String>, name: &str) -> std::io::Result<Option<Vec<u8>>> {
|
||||
Ok(match path {
|
||||
None => None,
|
||||
Some(p) => Some(
|
||||
std::fs::read(p)
|
||||
.map_err(|e| encpasulate_error(e, format!("Failed to load {}!", name)))?,
|
||||
),
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::client_config::ClientConfig;
|
||||
use crate::tcp_relay_client::client_config::ClientConfig;
|
||||
|
||||
#[test]
|
||||
fn verify_cli() {
|
@ -1,30 +1,36 @@
|
||||
extern crate core;
|
||||
|
||||
use std::error::Error;
|
||||
use std::io::ErrorKind;
|
||||
use std::sync::Arc;
|
||||
|
||||
use clap::Parser;
|
||||
use futures::future::join_all;
|
||||
use reqwest::{Certificate, Identity};
|
||||
|
||||
use base::RemoteConfig;
|
||||
use tcp_relay_client::client_config::ClientConfig;
|
||||
use tcp_relay_client::relay_client::relay_client;
|
||||
use crate::base::err_utils::{encpasulate_error, new_err};
|
||||
use crate::base::RemoteConfig;
|
||||
use crate::tcp_relay_client::client_config::ClientConfig;
|
||||
use crate::tcp_relay_client::relay_client::relay_client;
|
||||
|
||||
async fn get_server_config(config: &ClientConfig) -> Result<RemoteConfig, Box<dyn Error>> {
|
||||
let url = format!("{}/config", config.relay_url);
|
||||
pub mod client_config;
|
||||
mod relay_client;
|
||||
|
||||
/// Get remote server config i.e. get the list of forwarded ports
|
||||
async fn get_server_config(conf: &ClientConfig) -> Result<RemoteConfig, Box<dyn Error>> {
|
||||
let url = format!("{}/config", conf.relay_url);
|
||||
log::info!("Retrieving configuration on {}", url);
|
||||
|
||||
let mut client = reqwest::Client::builder();
|
||||
|
||||
// Specify root certificate, if any was specified in the command line
|
||||
if let Some(cert) = config.get_root_certificate() {
|
||||
if let Some(cert) = conf.get_root_certificate() {
|
||||
client = client.add_root_certificate(Certificate::from_pem(&cert)?);
|
||||
}
|
||||
|
||||
// Specify client certificate, if any
|
||||
if let Some(kp) = config.get_merged_client_keypair() {
|
||||
let identity = Identity::from_pem(&kp).expect("Failed to load certificates for reqwest!");
|
||||
if let Some(kp) = conf.get_merged_client_keypair() {
|
||||
let identity = Identity::from_pem(&kp)
|
||||
.map_err(|e| encpasulate_error(e, "Failed to load certificates for reqwest!"))?;
|
||||
client = client.identity(identity).use_rustls_tls();
|
||||
}
|
||||
|
||||
@ -32,37 +38,32 @@ async fn get_server_config(config: &ClientConfig) -> Result<RemoteConfig, Box<dy
|
||||
|
||||
let req = client
|
||||
.get(url)
|
||||
.header(
|
||||
"Authorization",
|
||||
format!("Bearer {}", config.get_auth_token()),
|
||||
)
|
||||
.header("Authorization", format!("Bearer {}", conf.get_auth_token()))
|
||||
.send()
|
||||
.await?;
|
||||
if req.status().as_u16() != 200 {
|
||||
log::error!(
|
||||
"Could not retrieve configuration! (got status {})",
|
||||
req.status()
|
||||
);
|
||||
std::process::exit(2);
|
||||
Err(std::io::Error::new(
|
||||
ErrorKind::Other,
|
||||
format!(
|
||||
"Could not retrieve configuration! (got status {})",
|
||||
req.status()
|
||||
),
|
||||
))?;
|
||||
}
|
||||
|
||||
Ok(req.json::<RemoteConfig>().await?)
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn Error>> {
|
||||
env_logger::init_from_env(env_logger::Env::new().default_filter_or("info"));
|
||||
|
||||
let mut args: ClientConfig = ClientConfig::parse();
|
||||
args.load_certificates();
|
||||
/// Core logic of the application
|
||||
pub async fn run_app(mut args: ClientConfig) -> std::io::Result<()> {
|
||||
args.load_certificates()?;
|
||||
let args = Arc::new(args);
|
||||
|
||||
// Check arguments coherence
|
||||
if args.tls_cert.is_some() != args.tls_key.is_some() {
|
||||
log::error!(
|
||||
"If you specify one of TLS certificate / key, you must then specify the other!"
|
||||
);
|
||||
panic!();
|
||||
return Err(new_err(
|
||||
"If you specify one of TLS certificate / key, you must then specify the other!",
|
||||
));
|
||||
}
|
||||
|
||||
if args.get_client_keypair().is_some() {
|
||||
@ -70,11 +71,20 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
||||
}
|
||||
|
||||
// Get server relay configuration (fetch the list of port to forward)
|
||||
let conf = get_server_config(&args).await?;
|
||||
let remote_conf = match get_server_config(&args).await {
|
||||
Ok(c) => c,
|
||||
Err(e) => {
|
||||
Err(std::io::Error::new(
|
||||
ErrorKind::Other,
|
||||
format!("Failed to fetch relay configuration from server! {}", e),
|
||||
))?;
|
||||
unreachable!();
|
||||
}
|
||||
};
|
||||
|
||||
// Start to listen port
|
||||
let mut handles = vec![];
|
||||
for port in conf {
|
||||
for port in remote_conf {
|
||||
let listen_address = format!("{}:{}", args.listen_address, port.port);
|
||||
|
||||
let h = tokio::spawn(relay_client(
|
@ -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);
|
@ -2,12 +2,16 @@ use std::sync::Arc;
|
||||
|
||||
use actix_web::web::Data;
|
||||
use actix_web::{middleware, web, App, HttpRequest, HttpResponse, HttpServer, Responder};
|
||||
use clap::Parser;
|
||||
|
||||
use base::{cert_utils, RelayedPort};
|
||||
use tcp_relay_server::relay_ws::relay_ws;
|
||||
use tcp_relay_server::server_config::ServerConfig;
|
||||
use tcp_relay_server::tls_cert_client_verifier::CustomCertClientVerifier;
|
||||
use crate::base::err_utils::{encpasulate_error, new_err};
|
||||
use crate::base::{cert_utils, RelayedPort};
|
||||
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;
|
||||
mod tls_cert_client_verifier;
|
||||
|
||||
pub async fn hello_route() -> &'static str {
|
||||
"Hello world!"
|
||||
@ -40,58 +44,58 @@ pub async fn config_route(req: HttpRequest, data: Data<Arc<ServerConfig>>) -> im
|
||||
)
|
||||
}
|
||||
|
||||
#[actix_web::main]
|
||||
async fn main() -> std::io::Result<()> {
|
||||
env_logger::init_from_env(env_logger::Env::new().default_filter_or("info"));
|
||||
|
||||
let mut args: ServerConfig = ServerConfig::parse();
|
||||
|
||||
pub async fn run_app(mut config: ServerConfig) -> std::io::Result<()> {
|
||||
// Check if no port are to be forwarded
|
||||
if args.ports.is_empty() {
|
||||
log::error!("No port to forward!");
|
||||
std::process::exit(2);
|
||||
if config.ports.is_empty() {
|
||||
return Err(new_err("No port to forward!"));
|
||||
}
|
||||
|
||||
// Read tokens from file, if any
|
||||
if let Some(file) = &args.tokens_file {
|
||||
if let Some(file) = &config.tokens_file {
|
||||
std::fs::read_to_string(file)
|
||||
.expect("Failed to read tokens file!")
|
||||
.map_err(|e| encpasulate_error(e, "Failed to read tokens file!"))?
|
||||
.split('\n')
|
||||
.filter(|l| !l.is_empty())
|
||||
.for_each(|t| args.tokens.push(t.to_string()));
|
||||
.for_each(|t| config.tokens.push(t.to_string()));
|
||||
}
|
||||
|
||||
if !args.has_auth() {
|
||||
log::error!("No authentication method specified!");
|
||||
std::process::exit(3);
|
||||
if !config.has_auth() {
|
||||
return Err(new_err("No authentication method specified!"));
|
||||
}
|
||||
|
||||
if args.has_tls_client_auth() && !args.has_tls_config() {
|
||||
log::error!("Cannot provide client auth without TLS configuration!");
|
||||
panic!();
|
||||
if config.tls_cert.is_some() != config.tls_key.is_some() {
|
||||
return Err(new_err("Incomplete server TLS configuration!"));
|
||||
}
|
||||
|
||||
let args = Arc::new(args);
|
||||
if config.has_tls_client_auth() && !config.has_tls_config() {
|
||||
return Err(new_err(
|
||||
"Cannot provide client auth without TLS configuration!",
|
||||
));
|
||||
}
|
||||
|
||||
let args = Arc::new(config);
|
||||
|
||||
// Load TLS configuration, if any
|
||||
let tls_config = if let (Some(cert), Some(key)) = (&args.tls_cert, &args.tls_key) {
|
||||
// Load TLS certificate & private key
|
||||
let cert_file = std::fs::read(cert).expect("Failed to read certificate file");
|
||||
let key_file = std::fs::read(key).expect("Failed to read server private key");
|
||||
let cert_file = std::fs::read(cert)
|
||||
.map_err(|e| encpasulate_error(e, "Failed to read certificate file"))?;
|
||||
let key_file = std::fs::read(key)
|
||||
.map_err(|e| encpasulate_error(e, "Failed to read server private key"))?;
|
||||
|
||||
// Get certificates chain
|
||||
let cert_chain =
|
||||
cert_utils::parse_pem_certificates(&cert_file).expect("Failed to extract certificates");
|
||||
let cert_chain = cert_utils::parse_pem_certificates(&cert_file)
|
||||
.map_err(|e| encpasulate_error(e, "Failed to extract certificates"))?;
|
||||
|
||||
// Get private key
|
||||
let key =
|
||||
cert_utils::parse_pem_private_key(&key_file).expect("Failed to extract private key!");
|
||||
let key = cert_utils::parse_pem_private_key(&key_file)
|
||||
.map_err(|e| encpasulate_error(e, "Failed to extract private key!"))?;
|
||||
|
||||
let config = rustls::ServerConfig::builder().with_safe_defaults();
|
||||
|
||||
let config = match args.has_tls_client_auth() {
|
||||
true => config
|
||||
.with_client_cert_verifier(Arc::new(CustomCertClientVerifier::new(args.clone()))),
|
||||
.with_client_cert_verifier(Arc::new(CustomCertClientVerifier::new(args.clone())?)),
|
||||
false => config.with_no_client_auth(),
|
||||
};
|
||||
|
@ -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);
|
||||
@ -196,11 +196,16 @@ pub async fn relay_ws(
|
||||
tcp_write,
|
||||
hb: Instant::now(),
|
||||
};
|
||||
|
||||
let resp = ws::start(relay, &req, stream);
|
||||
log::info!(
|
||||
"Opening new WS connection for {:?} to {}",
|
||||
"Opening new WS connection:\
|
||||
* for {:?}\
|
||||
* to {}\
|
||||
* token {:?}",
|
||||
req.peer_addr(),
|
||||
upstream_addr
|
||||
upstream_addr,
|
||||
query.token
|
||||
);
|
||||
resp
|
||||
}
|
@ -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
|
||||
@ -71,3 +71,14 @@ impl ServerConfig {
|
||||
self.has_token_auth() || self.has_tls_client_auth()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::tcp_relay_server::server_config::ServerConfig;
|
||||
|
||||
#[test]
|
||||
fn verify_cli() {
|
||||
use clap::CommandFactory;
|
||||
ServerConfig::command().debug_assert()
|
||||
}
|
||||
}
|
@ -1,14 +1,14 @@
|
||||
use std::sync::Arc;
|
||||
use std::time::SystemTime;
|
||||
|
||||
use rustls::{Certificate, DistinguishedNames, Error, RootCertStore};
|
||||
use rustls::internal::msgs::enums::AlertDescription;
|
||||
use rustls::server::{AllowAnyAuthenticatedClient, ClientCertVerified, ClientCertVerifier};
|
||||
use rustls::{Certificate, DistinguishedNames, Error, RootCertStore};
|
||||
use x509_parser::prelude::{CertificateRevocationList, FromDer, X509Certificate};
|
||||
|
||||
use base::cert_utils::parse_pem_certificates;
|
||||
|
||||
use crate::server_config::ServerConfig;
|
||||
use crate::base::cert_utils::parse_pem_certificates;
|
||||
use crate::base::err_utils::{encpasulate_error, new_err};
|
||||
use crate::tcp_relay_server::server_config::ServerConfig;
|
||||
|
||||
pub struct CustomCertClientVerifier {
|
||||
upstream_cert_verifier: Box<Arc<dyn ClientCertVerifier>>,
|
||||
@ -16,21 +16,28 @@ pub struct CustomCertClientVerifier {
|
||||
}
|
||||
|
||||
impl CustomCertClientVerifier {
|
||||
pub fn new(conf: Arc<ServerConfig>) -> Self {
|
||||
pub fn new(conf: Arc<ServerConfig>) -> std::io::Result<Self> {
|
||||
// Build root certifications list
|
||||
let cert_path = conf
|
||||
.tls_client_auth_root_cert
|
||||
.as_deref()
|
||||
.expect("No root certificates for client authentication provided!");
|
||||
let cert_file = std::fs::read(cert_path)
|
||||
.expect("Failed to read root certificates for client authentication!");
|
||||
let cert_file = std::fs::read(cert_path).map_err(|e| {
|
||||
encpasulate_error(
|
||||
e,
|
||||
"Failed to read root certificates for client authentication!",
|
||||
)
|
||||
})?;
|
||||
|
||||
let root_certs = parse_pem_certificates(&cert_file)
|
||||
.expect("Failed to read root certificates for server authentication!");
|
||||
let root_certs = parse_pem_certificates(&cert_file).map_err(|e| {
|
||||
encpasulate_error(
|
||||
e,
|
||||
"Failed to read root certificates for server authentication!",
|
||||
)
|
||||
})?;
|
||||
|
||||
if root_certs.is_empty() {
|
||||
log::error!("No certificates found for client authentication!");
|
||||
panic!();
|
||||
return Err(new_err("No certificates found for client authentication!"));
|
||||
}
|
||||
|
||||
let mut store = RootCertStore::empty();
|
||||
@ -42,19 +49,21 @@ impl CustomCertClientVerifier {
|
||||
|
||||
// Parse CRL file (if any)
|
||||
let crl = if let Some(crl_file) = &conf.tls_revocation_list {
|
||||
let crl_file = std::fs::read(crl_file).expect("Failed to open / read CRL file!");
|
||||
let crl_file = std::fs::read(crl_file)
|
||||
.map_err(|e| encpasulate_error(e, "Failed to open / read CRL file!"))?;
|
||||
|
||||
let parsed_crl = pem::parse(crl_file).expect("Failed to decode CRL file!");
|
||||
let parsed_crl = pem::parse(crl_file)
|
||||
.map_err(|e| encpasulate_error(e, "Failed to decode CRL file!"))?;
|
||||
|
||||
Some(parsed_crl.contents)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
Self {
|
||||
Ok(Self {
|
||||
upstream_cert_verifier: Box::new(AllowAnyAuthenticatedClient::new(store)),
|
||||
crl,
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -77,14 +86,14 @@ impl ClientCertVerifier for CustomCertClientVerifier {
|
||||
intermediates: &[Certificate],
|
||||
now: SystemTime,
|
||||
) -> Result<ClientCertVerified, Error> {
|
||||
let (_rem, cert) =
|
||||
X509Certificate::from_der(&end_entity.0).expect("Failed to read certificate!");
|
||||
|
||||
// Check the certificates sent by the client has been revoked
|
||||
if let Some(crl) = &self.crl {
|
||||
let (_rem, crl) =
|
||||
CertificateRevocationList::from_der(crl).expect("Failed to read CRL!");
|
||||
|
||||
let (_rem, cert) =
|
||||
X509Certificate::from_der(&end_entity.0).expect("Failed to read certificate!");
|
||||
|
||||
for revoked in crl.iter_revoked_certificates() {
|
||||
if revoked.user_certificate == cert.serial {
|
||||
log::error!(
|
||||
@ -97,7 +106,24 @@ impl ClientCertVerifier for CustomCertClientVerifier {
|
||||
}
|
||||
}
|
||||
|
||||
self.upstream_cert_verifier
|
||||
.verify_client_cert(end_entity, intermediates, now)
|
||||
let result = self
|
||||
.upstream_cert_verifier
|
||||
.verify_client_cert(end_entity, intermediates, now);
|
||||
|
||||
match result.as_ref() {
|
||||
Err(e) => log::error!(
|
||||
"FAILED authentication attempt from Serial={} / Subject={} : {}",
|
||||
cert.serial,
|
||||
cert.subject,
|
||||
e
|
||||
),
|
||||
Ok(_) => log::info!(
|
||||
"SUCCESSFUL authentication attempt from Serial={} / Subject={}",
|
||||
cert.serial,
|
||||
cert.subject
|
||||
),
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
}
|
160
src/test/client_invalid_tls_configuration.rs
Normal file
160
src/test/client_invalid_tls_configuration.rs
Normal file
@ -0,0 +1,160 @@
|
||||
use tokio::task;
|
||||
|
||||
use crate::tcp_relay_client::client_config::ClientConfig;
|
||||
use crate::tcp_relay_server::server_config::ServerConfig;
|
||||
use crate::test::dummy_tcp_sockets::wait_for_port;
|
||||
use crate::test::pki::Pki;
|
||||
use crate::test::test_files_utils::create_temp_file_with_random_content;
|
||||
use crate::test::{get_port_number, PortsAllocation, BAD_PATH, LOCALHOST_IP};
|
||||
|
||||
fn port(index: u16) -> u16 {
|
||||
get_port_number(PortsAllocation::ClientInvalidTlsConfiguration, index)
|
||||
}
|
||||
|
||||
#[tokio::test()]
|
||||
async fn random_file_for_cert() {
|
||||
let _ = env_logger::builder().is_test(true).try_init();
|
||||
|
||||
let pki = Pki::load();
|
||||
let random_file = create_temp_file_with_random_content();
|
||||
|
||||
crate::tcp_relay_client::run_app(ClientConfig {
|
||||
token: Some("token".to_string()),
|
||||
relay_url: format!("https://{}:{}", LOCALHOST_IP, port(0)),
|
||||
listen_address: LOCALHOST_IP.to_string(),
|
||||
tls_cert: Some(random_file.to_string_lossy().to_string()),
|
||||
tls_key: Some(pki.valid_client_key.file_path()),
|
||||
..Default::default()
|
||||
})
|
||||
.await
|
||||
.unwrap_err();
|
||||
}
|
||||
|
||||
#[tokio::test()]
|
||||
async fn random_file_for_key() {
|
||||
let _ = env_logger::builder().is_test(true).try_init();
|
||||
|
||||
let pki = Pki::load();
|
||||
let random_file = create_temp_file_with_random_content();
|
||||
|
||||
crate::tcp_relay_client::run_app(ClientConfig {
|
||||
token: Some("token".to_string()),
|
||||
relay_url: format!("https://{}:{}", LOCALHOST_IP, port(0)),
|
||||
listen_address: LOCALHOST_IP.to_string(),
|
||||
tls_cert: Some(pki.valid_client_crt.file_path()),
|
||||
tls_key: Some(random_file.to_string_lossy().to_string()),
|
||||
..Default::default()
|
||||
})
|
||||
.await
|
||||
.unwrap_err();
|
||||
}
|
||||
|
||||
#[tokio::test()]
|
||||
async fn bad_pem_file_for_cert() {
|
||||
let _ = env_logger::builder().is_test(true).try_init();
|
||||
|
||||
let pki = Pki::load();
|
||||
|
||||
crate::tcp_relay_client::run_app(ClientConfig {
|
||||
token: Some("token".to_string()),
|
||||
relay_url: format!("https://{}:{}", LOCALHOST_IP, port(0)),
|
||||
listen_address: LOCALHOST_IP.to_string(),
|
||||
tls_cert: Some(pki.root_ca_crl.file_path()),
|
||||
tls_key: Some(pki.valid_client_key.file_path()),
|
||||
..Default::default()
|
||||
})
|
||||
.await
|
||||
.unwrap_err();
|
||||
}
|
||||
|
||||
#[tokio::test()]
|
||||
async fn bad_pem_file_for_key() {
|
||||
let _ = env_logger::builder().is_test(true).try_init();
|
||||
|
||||
let pki = Pki::load();
|
||||
|
||||
crate::tcp_relay_client::run_app(ClientConfig {
|
||||
token: Some("token".to_string()),
|
||||
relay_url: format!("https://{}:{}", LOCALHOST_IP, port(0)),
|
||||
listen_address: LOCALHOST_IP.to_string(),
|
||||
tls_cert: Some(pki.valid_client_crt.file_path()),
|
||||
tls_key: Some(pki.root_ca_crl.file_path()),
|
||||
..Default::default()
|
||||
})
|
||||
.await
|
||||
.unwrap_err();
|
||||
}
|
||||
|
||||
#[tokio::test()]
|
||||
async fn non_existing_cert() {
|
||||
let _ = env_logger::builder().is_test(true).try_init();
|
||||
|
||||
let pki = Pki::load();
|
||||
|
||||
crate::tcp_relay_client::run_app(ClientConfig {
|
||||
token: Some("token".to_string()),
|
||||
relay_url: format!("https://{}:{}", LOCALHOST_IP, port(0)),
|
||||
listen_address: LOCALHOST_IP.to_string(),
|
||||
tls_cert: Some(BAD_PATH.to_string()),
|
||||
tls_key: Some(pki.valid_client_key.file_path()),
|
||||
..Default::default()
|
||||
})
|
||||
.await
|
||||
.unwrap_err();
|
||||
}
|
||||
|
||||
#[tokio::test()]
|
||||
async fn non_existing_key() {
|
||||
let _ = env_logger::builder().is_test(true).try_init();
|
||||
|
||||
let pki = Pki::load();
|
||||
|
||||
crate::tcp_relay_client::run_app(ClientConfig {
|
||||
token: Some("token".to_string()),
|
||||
relay_url: format!("https://{}:{}", LOCALHOST_IP, port(0)),
|
||||
listen_address: LOCALHOST_IP.to_string(),
|
||||
tls_cert: Some(pki.valid_client_crt.file_path()),
|
||||
tls_key: Some(BAD_PATH.to_string()),
|
||||
..Default::default()
|
||||
})
|
||||
.await
|
||||
.unwrap_err();
|
||||
}
|
||||
|
||||
#[tokio::test()]
|
||||
async fn unmatched_key_cert_pair() {
|
||||
let _ = env_logger::builder().is_test(true).try_init();
|
||||
|
||||
let pki = Pki::load();
|
||||
let local_set = task::LocalSet::new();
|
||||
local_set
|
||||
.run_until(async move {
|
||||
// Start server relay
|
||||
task::spawn_local(crate::tcp_relay_server::run_app(ServerConfig {
|
||||
tokens: vec!["dqsd".to_string()],
|
||||
tokens_file: None,
|
||||
ports: vec![port(1)],
|
||||
upstream_server: "127.0.0.1".to_string(),
|
||||
listen_address: format!("127.0.0.1:{}", port(0)),
|
||||
increment_ports: 1,
|
||||
tls_cert: Some(pki.localhost_crt.file_path()),
|
||||
tls_key: Some(pki.localhost_key.file_path()),
|
||||
tls_client_auth_root_cert: Some(pki.root_ca_crt.file_path()),
|
||||
tls_revocation_list: None,
|
||||
}));
|
||||
wait_for_port(port(0)).await;
|
||||
|
||||
crate::tcp_relay_client::run_app(ClientConfig {
|
||||
token: Some("token".to_string()),
|
||||
relay_url: format!("https://localhost:{}", port(0)),
|
||||
listen_address: LOCALHOST_IP.to_string(),
|
||||
tls_cert: Some(pki.valid_client_crt.file_path()),
|
||||
tls_key: Some(pki.revoked_client_key.file_path()),
|
||||
root_certificate: Some(pki.root_ca_crt.file_path()),
|
||||
..Default::default()
|
||||
})
|
||||
.await
|
||||
.unwrap_err();
|
||||
})
|
||||
.await;
|
||||
}
|
59
src/test/client_invalid_tls_root_certificate_file.rs
Normal file
59
src/test/client_invalid_tls_root_certificate_file.rs
Normal file
@ -0,0 +1,59 @@
|
||||
use crate::tcp_relay_client::client_config::ClientConfig;
|
||||
use crate::test::pki::Pki;
|
||||
use crate::test::test_files_utils::create_temp_file_with_random_content;
|
||||
use crate::test::{get_port_number, PortsAllocation, BAD_PATH, LOCALHOST_IP};
|
||||
|
||||
const VALID_TOKEN: &str = "AvalidTOKEN";
|
||||
|
||||
fn port(index: u16) -> u16 {
|
||||
get_port_number(PortsAllocation::TestsWithoutPortOpened, index)
|
||||
}
|
||||
|
||||
#[tokio::test()]
|
||||
async fn invalid_file_type() {
|
||||
let _ = env_logger::builder().is_test(true).try_init();
|
||||
|
||||
let pki = Pki::load();
|
||||
|
||||
crate::tcp_relay_client::run_app(ClientConfig {
|
||||
token: Some(VALID_TOKEN.to_string()),
|
||||
relay_url: format!("https://{}:{}", LOCALHOST_IP, port(0)),
|
||||
listen_address: LOCALHOST_IP.to_string(),
|
||||
root_certificate: Some(pki.expired_client_key.file_path()),
|
||||
..Default::default()
|
||||
})
|
||||
.await
|
||||
.unwrap_err();
|
||||
}
|
||||
|
||||
#[tokio::test()]
|
||||
async fn non_existing_file() {
|
||||
let _ = env_logger::builder().is_test(true).try_init();
|
||||
|
||||
crate::tcp_relay_client::run_app(ClientConfig {
|
||||
token: Some(VALID_TOKEN.to_string()),
|
||||
relay_url: format!("https://{}:{}", LOCALHOST_IP, port(0)),
|
||||
listen_address: LOCALHOST_IP.to_string(),
|
||||
root_certificate: Some(BAD_PATH.to_string()),
|
||||
..Default::default()
|
||||
})
|
||||
.await
|
||||
.unwrap_err();
|
||||
}
|
||||
|
||||
#[tokio::test()]
|
||||
async fn random_file() {
|
||||
let _ = env_logger::builder().is_test(true).try_init();
|
||||
|
||||
let random_file = create_temp_file_with_random_content();
|
||||
|
||||
crate::tcp_relay_client::run_app(ClientConfig {
|
||||
token: Some(VALID_TOKEN.to_string()),
|
||||
relay_url: format!("https://{}:{}", LOCALHOST_IP, port(0)),
|
||||
listen_address: LOCALHOST_IP.to_string(),
|
||||
root_certificate: Some(random_file.to_string_lossy().to_string()),
|
||||
..Default::default()
|
||||
})
|
||||
.await
|
||||
.unwrap_err();
|
||||
}
|
55
src/test/client_try_tls_while_there_is_no_tls.rs
Normal file
55
src/test/client_try_tls_while_there_is_no_tls.rs
Normal file
@ -0,0 +1,55 @@
|
||||
use tokio::task;
|
||||
|
||||
use crate::tcp_relay_client::client_config::ClientConfig;
|
||||
use crate::tcp_relay_server::server_config::ServerConfig;
|
||||
use crate::test::dummy_tcp_sockets::{wait_for_port, DummyTCPServer};
|
||||
use crate::test::{get_port_number, PortsAllocation, LOCALHOST_IP};
|
||||
|
||||
const VALID_TOKEN: &str = "AvalidTOKEN";
|
||||
|
||||
fn port(index: u16) -> u16 {
|
||||
get_port_number(PortsAllocation::ClientTryTLSWhileThereIsNoTLS, index)
|
||||
}
|
||||
|
||||
#[tokio::test()]
|
||||
async fn test() {
|
||||
let _ = env_logger::builder().is_test(true).try_init();
|
||||
|
||||
// Start internal service
|
||||
let local_server = DummyTCPServer::start(port(1)).await;
|
||||
tokio::spawn(async move {
|
||||
local_server.loop_conn_square_operations().await;
|
||||
});
|
||||
|
||||
let local_set = task::LocalSet::new();
|
||||
local_set
|
||||
.run_until(async move {
|
||||
wait_for_port(port(1)).await;
|
||||
|
||||
// Start server relay
|
||||
task::spawn_local(crate::tcp_relay_server::run_app(ServerConfig {
|
||||
tokens: vec![VALID_TOKEN.to_string()],
|
||||
tokens_file: None,
|
||||
ports: vec![port(1)],
|
||||
upstream_server: "127.0.0.1".to_string(),
|
||||
listen_address: format!("127.0.0.1:{}", port(0)),
|
||||
increment_ports: 1,
|
||||
tls_cert: None,
|
||||
tls_key: None,
|
||||
tls_client_auth_root_cert: None,
|
||||
tls_revocation_list: None,
|
||||
}));
|
||||
wait_for_port(port(0)).await;
|
||||
|
||||
crate::tcp_relay_client::run_app(ClientConfig {
|
||||
token: Some(VALID_TOKEN.to_string()),
|
||||
relay_url: format!("https://{}:{}", LOCALHOST_IP, port(0)),
|
||||
listen_address: LOCALHOST_IP.to_string(),
|
||||
root_certificate: None,
|
||||
..Default::default()
|
||||
})
|
||||
.await
|
||||
.unwrap_err();
|
||||
})
|
||||
.await;
|
||||
}
|
339
src/test/dummy_tcp_sockets.rs
Normal file
339
src/test/dummy_tcp_sockets.rs
Normal file
@ -0,0 +1,339 @@
|
||||
use std::time::Duration;
|
||||
|
||||
use rand::Rng;
|
||||
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||
use tokio::net::{TcpListener, TcpStream};
|
||||
use tokio::time;
|
||||
|
||||
use crate::test::LOCALHOST_IP;
|
||||
|
||||
pub struct DummyTCPServer(TcpListener);
|
||||
|
||||
impl DummyTCPServer {
|
||||
pub async fn start(port: u16) -> Self {
|
||||
let addr = format!("{}:{}", LOCALHOST_IP, port);
|
||||
println!("[DUMMY TCP] Listen on {}", addr);
|
||||
let listener = TcpListener::bind(addr)
|
||||
.await
|
||||
.expect("Failed to bind dummy TCP listener!");
|
||||
Self(listener)
|
||||
}
|
||||
|
||||
/// Receive chunk of data from following connection
|
||||
pub async fn read_next_connection(&self) -> Vec<u8> {
|
||||
let (mut conn, _addr) = self
|
||||
.0
|
||||
.accept()
|
||||
.await
|
||||
.expect("Could not open next connection!");
|
||||
|
||||
let mut buff = Vec::with_capacity(100);
|
||||
conn.read_to_end(&mut buff).await.unwrap();
|
||||
|
||||
buff
|
||||
}
|
||||
|
||||
/// Receive chunk of data from following connection
|
||||
pub async fn read_then_write_next_connection(&self, to_send: &[u8]) -> Vec<u8> {
|
||||
let (mut conn, _addr) = self
|
||||
.0
|
||||
.accept()
|
||||
.await
|
||||
.expect("Could not open next connection!");
|
||||
|
||||
let mut buff: [u8; 100] = [0; 100];
|
||||
let size = conn.read(&mut buff).await.unwrap();
|
||||
|
||||
conn.write_all(to_send).await.unwrap();
|
||||
|
||||
buff[0..size].to_vec()
|
||||
}
|
||||
|
||||
/// Receive chunk of data from following connection
|
||||
pub async fn write_next_connection(&self, to_send: &[u8]) {
|
||||
let (mut conn, _addr) = self
|
||||
.0
|
||||
.accept()
|
||||
.await
|
||||
.expect("Could not open next connection!");
|
||||
|
||||
conn.write_all(to_send).await.unwrap()
|
||||
}
|
||||
|
||||
/// Perform complex exchange: receive numbers from client and respond with their square
|
||||
pub async fn next_conn_square_operations(&self) {
|
||||
let (mut conn, _addr) = self
|
||||
.0
|
||||
.accept()
|
||||
.await
|
||||
.expect("Could not open next connection!");
|
||||
|
||||
let mut buff: [u8; 100] = [0; 100];
|
||||
loop {
|
||||
let size = conn.read(&mut buff).await.unwrap();
|
||||
if size == 0 {
|
||||
break;
|
||||
}
|
||||
|
||||
let content = String::from_utf8_lossy(&buff[0..size])
|
||||
.to_string()
|
||||
.parse::<i64>()
|
||||
.unwrap();
|
||||
|
||||
conn.write_all((content * content).to_string().as_bytes())
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn loop_conn_square_operations(&self) {
|
||||
loop {
|
||||
self.next_conn_square_operations().await
|
||||
}
|
||||
}
|
||||
|
||||
/// Perform complex exchange: receive numbers from client and respond with their value + a given number
|
||||
pub async fn next_conn_add_operations(&self, inc: i32) {
|
||||
let (mut conn, _addr) = self
|
||||
.0
|
||||
.accept()
|
||||
.await
|
||||
.expect("Could not open next connection!");
|
||||
|
||||
let mut buff: [u8; 100] = [0; 100];
|
||||
loop {
|
||||
let size = conn.read(&mut buff).await.unwrap();
|
||||
if size == 0 {
|
||||
break;
|
||||
}
|
||||
|
||||
let content = String::from_utf8_lossy(&buff[0..size])
|
||||
.to_string()
|
||||
.parse::<i64>()
|
||||
.unwrap();
|
||||
|
||||
conn.write_all((content + inc as i64).to_string().as_bytes())
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn loop_next_conn_add_operations(&self, inc: i32) {
|
||||
loop {
|
||||
self.next_conn_add_operations(inc).await
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn dummy_tcp_client_read_conn(port: u16) -> Vec<u8> {
|
||||
let mut socket = TcpStream::connect(format!("127.0.0.1:{}", port))
|
||||
.await
|
||||
.expect("Failed to connect to dummy TCP server!");
|
||||
|
||||
let mut buff: [u8; 100] = [0; 100];
|
||||
let size = socket.read(&mut buff).await.unwrap();
|
||||
|
||||
buff[0..size].to_vec()
|
||||
}
|
||||
|
||||
pub async fn dummy_tcp_client_write_then_read_conn(port: u16, data: &[u8]) -> Vec<u8> {
|
||||
let mut socket = TcpStream::connect(format!("127.0.0.1:{}", port))
|
||||
.await
|
||||
.expect("Failed to connect to dummy TCP server!");
|
||||
|
||||
socket.write_all(data).await.unwrap();
|
||||
|
||||
let mut buff: [u8; 100] = [0; 100];
|
||||
let size = socket.read(&mut buff).await.unwrap();
|
||||
|
||||
buff[0..size].to_vec()
|
||||
}
|
||||
|
||||
pub async fn dummy_tcp_client_write_conn(port: u16, data: &[u8]) {
|
||||
let mut socket = TcpStream::connect(format!("127.0.0.1:{}", port))
|
||||
.await
|
||||
.expect("Failed to connect to dummy TCP server!");
|
||||
|
||||
socket.write_all(data).await.unwrap()
|
||||
}
|
||||
|
||||
pub async fn dummy_tcp_client_square_root_requests(port: u16, num_exchanges: usize) {
|
||||
let mut socket = TcpStream::connect(format!("127.0.0.1:{}", port))
|
||||
.await
|
||||
.expect("Failed to connect to dummy TCP server!");
|
||||
|
||||
let mut rng = rand::thread_rng();
|
||||
let mut buff: [u8; 100] = [0; 100];
|
||||
|
||||
for _ in 0..num_exchanges {
|
||||
let num = rng.gen::<i32>() % 100;
|
||||
socket.write_all(num.to_string().as_bytes()).await.unwrap();
|
||||
|
||||
let size = socket.read(&mut buff).await.unwrap();
|
||||
|
||||
if size == 0 {
|
||||
panic!("Got empty response!");
|
||||
}
|
||||
|
||||
let got = String::from_utf8_lossy(&buff[0..size])
|
||||
.to_string()
|
||||
.parse::<i64>()
|
||||
.unwrap();
|
||||
println!("{} * {} = {} (based on server response)", num, num, got);
|
||||
assert_eq!((num * num) as i64, got);
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn dummy_tcp_client_additions_requests(port: u16, inc: i32, num_exchanges: usize) {
|
||||
let mut socket = TcpStream::connect(format!("127.0.0.1:{}", port))
|
||||
.await
|
||||
.expect("Failed to connect to dummy TCP server!");
|
||||
|
||||
let mut rng = rand::thread_rng();
|
||||
let mut buff: [u8; 100] = [0; 100];
|
||||
|
||||
for _ in 0..num_exchanges {
|
||||
let num = rng.gen::<i32>() % 100;
|
||||
socket.write_all(num.to_string().as_bytes()).await.unwrap();
|
||||
|
||||
let size = socket.read(&mut buff).await.unwrap();
|
||||
|
||||
if size == 0 {
|
||||
panic!("Got empty response!");
|
||||
}
|
||||
|
||||
let got = String::from_utf8_lossy(&buff[0..size])
|
||||
.to_string()
|
||||
.parse::<i64>()
|
||||
.unwrap();
|
||||
println!("{} + {} = {} (based on server response)", num, inc, got);
|
||||
assert_eq!((num + inc) as i64, got);
|
||||
}
|
||||
}
|
||||
|
||||
/// Check whether a given port is open or not
|
||||
pub async fn is_port_open(port: u16) -> bool {
|
||||
match TcpStream::connect(("127.0.0.1", port)).await {
|
||||
Ok(_) => true,
|
||||
Err(_) => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Wait for a port to become available
|
||||
pub async fn wait_for_port(port: u16) {
|
||||
for _ in 0..50 {
|
||||
if is_port_open(port).await {
|
||||
return;
|
||||
}
|
||||
time::sleep(Duration::from_millis(10)).await;
|
||||
}
|
||||
|
||||
eprintln!("Port {} did not open in time!", port);
|
||||
std::process::exit(2);
|
||||
}
|
||||
|
||||
mod test {
|
||||
use crate::test::dummy_tcp_sockets::{
|
||||
dummy_tcp_client_additions_requests, dummy_tcp_client_read_conn,
|
||||
dummy_tcp_client_square_root_requests, dummy_tcp_client_write_conn,
|
||||
dummy_tcp_client_write_then_read_conn, DummyTCPServer,
|
||||
};
|
||||
use crate::test::{get_port_number, PortsAllocation};
|
||||
|
||||
fn port(index: u16) -> u16 {
|
||||
get_port_number(PortsAllocation::DummyTCPServer, index)
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn socket_read_from_server() {
|
||||
const DATA: &[u8] = "Hello world!!!".as_bytes();
|
||||
|
||||
let listener = DummyTCPServer::start(port(0)).await;
|
||||
let handle = tokio::spawn(async move {
|
||||
listener.write_next_connection(DATA).await;
|
||||
});
|
||||
let data = dummy_tcp_client_read_conn(port(0)).await;
|
||||
assert_eq!(data, DATA);
|
||||
|
||||
handle.await.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn socket_write_to_server() {
|
||||
const DATA: &[u8] = "Hello world 2".as_bytes();
|
||||
|
||||
let listener = DummyTCPServer::start(port(1)).await;
|
||||
tokio::spawn(async move {
|
||||
dummy_tcp_client_write_conn(port(1), DATA).await;
|
||||
});
|
||||
let data = listener.read_next_connection().await;
|
||||
assert_eq!(data, DATA);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn socket_read_and_write_to_server() {
|
||||
const DATA_1: &[u8] = "Hello world 3a".as_bytes();
|
||||
const DATA_2: &[u8] = "Hello world 3b".as_bytes();
|
||||
|
||||
let listener = DummyTCPServer::start(port(2)).await;
|
||||
let handle = tokio::spawn(async move {
|
||||
println!("client handle");
|
||||
let data = dummy_tcp_client_write_then_read_conn(port(2), DATA_1).await;
|
||||
assert_eq!(data, DATA_2);
|
||||
});
|
||||
let h2 = tokio::spawn(async move {
|
||||
println!("server handle");
|
||||
let data = listener.read_then_write_next_connection(DATA_2).await;
|
||||
assert_eq!(data, DATA_1);
|
||||
});
|
||||
|
||||
handle.await.unwrap();
|
||||
h2.await.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn socket_dummy_root_calculator() {
|
||||
let listener = DummyTCPServer::start(port(3)).await;
|
||||
let handle = tokio::spawn(async move {
|
||||
listener.next_conn_square_operations().await;
|
||||
});
|
||||
let data = dummy_tcp_client_write_then_read_conn(port(3), "5".as_bytes()).await;
|
||||
assert_eq!(data, "25".as_bytes());
|
||||
|
||||
handle.await.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn socket_dummy_root_calculator_multiple() {
|
||||
let listener = DummyTCPServer::start(port(4)).await;
|
||||
let handle = tokio::spawn(async move {
|
||||
listener.next_conn_square_operations().await;
|
||||
});
|
||||
dummy_tcp_client_square_root_requests(port(4), 10).await;
|
||||
|
||||
handle.await.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn socket_dummy_addition_calculator() {
|
||||
let listener = DummyTCPServer::start(port(5)).await;
|
||||
let handle = tokio::spawn(async move {
|
||||
listener.next_conn_add_operations(4).await;
|
||||
});
|
||||
let data = dummy_tcp_client_write_then_read_conn(port(5), "5".as_bytes()).await;
|
||||
assert_eq!(data, "9".as_bytes());
|
||||
|
||||
handle.await.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn socket_dummy_addition_calculator_multiple() {
|
||||
let listener = DummyTCPServer::start(port(6)).await;
|
||||
let handle = tokio::spawn(async move {
|
||||
listener.next_conn_add_operations(7).await;
|
||||
});
|
||||
dummy_tcp_client_additions_requests(port(6), 7, 10).await;
|
||||
|
||||
handle.await.unwrap();
|
||||
}
|
||||
}
|
0
src/test/expired_certificate.rs
Normal file
0
src/test/expired_certificate.rs
Normal file
57
src/test/invalid_with_token_auth.rs
Normal file
57
src/test/invalid_with_token_auth.rs
Normal file
@ -0,0 +1,57 @@
|
||||
use tokio::task;
|
||||
|
||||
use crate::tcp_relay_client::client_config::ClientConfig;
|
||||
use crate::tcp_relay_server::server_config::ServerConfig;
|
||||
use crate::test::dummy_tcp_sockets::{wait_for_port, DummyTCPServer};
|
||||
use crate::test::{get_port_number, PortsAllocation, LOCALHOST_IP};
|
||||
|
||||
const VALID_TOKEN: &str = "AvalidTOKEN";
|
||||
const INVALID_TOKEN: &str = "AnInvalidTOKEN";
|
||||
|
||||
fn port(index: u16) -> u16 {
|
||||
get_port_number(PortsAllocation::InvalidWithTokenAuth, index)
|
||||
}
|
||||
|
||||
#[tokio::test()]
|
||||
async fn invalid_with_token_auth() {
|
||||
let _ = env_logger::builder().is_test(true).try_init();
|
||||
|
||||
tokio::spawn(async move {
|
||||
// Start internal service
|
||||
let local_server = DummyTCPServer::start(port(1)).await;
|
||||
local_server.loop_conn_square_operations().await;
|
||||
});
|
||||
|
||||
let local_set = task::LocalSet::new();
|
||||
local_set
|
||||
.run_until(async move {
|
||||
wait_for_port(port(1)).await;
|
||||
|
||||
// Start server relay
|
||||
task::spawn_local(crate::tcp_relay_server::run_app(ServerConfig {
|
||||
tokens: vec![VALID_TOKEN.to_string()],
|
||||
tokens_file: None,
|
||||
ports: vec![port(1)],
|
||||
upstream_server: "127.0.0.1".to_string(),
|
||||
listen_address: format!("127.0.0.1:{}", port(0)),
|
||||
increment_ports: 1,
|
||||
tls_cert: None,
|
||||
tls_key: None,
|
||||
tls_client_auth_root_cert: None,
|
||||
tls_revocation_list: None,
|
||||
}));
|
||||
wait_for_port(port(0)).await;
|
||||
|
||||
// Start client relay
|
||||
crate::tcp_relay_client::run_app(ClientConfig {
|
||||
token: Some(INVALID_TOKEN.to_string()),
|
||||
relay_url: format!("http://{}:{}", LOCALHOST_IP, port(0)),
|
||||
listen_address: LOCALHOST_IP.to_string(),
|
||||
root_certificate: None,
|
||||
..Default::default()
|
||||
})
|
||||
.await
|
||||
.unwrap_err();
|
||||
})
|
||||
.await;
|
||||
}
|
54
src/test/mod.rs
Normal file
54
src/test/mod.rs
Normal file
@ -0,0 +1,54 @@
|
||||
#[non_exhaustive]
|
||||
enum PortsAllocation {
|
||||
TestsWithoutPortOpened,
|
||||
DummyTCPServer,
|
||||
ValidWithTokenAuth,
|
||||
ValidWithTLSAuth,
|
||||
InvalidWithTokenAuth,
|
||||
ValidWithMultipleTokenAuth,
|
||||
ValidWithTokenFile,
|
||||
ClientTryTLSWhileThereIsNoTLS,
|
||||
ValidTokenWithCustomIncrement,
|
||||
ValidWithTokenAuthMultiplePorts,
|
||||
ValidWithTokenAuthAndServerTLS,
|
||||
WithTokenAuthAndInvalidServerTLSBadCA,
|
||||
WithTokenAuthAndInvalidServerTLSExpiredAndBadCN,
|
||||
TlsAuthExpiredClientCertificate,
|
||||
TlsAuthRevokedClientCertificate,
|
||||
TlsAuthInvalidClientCertificate,
|
||||
ClientInvalidTlsConfiguration,
|
||||
}
|
||||
|
||||
fn get_port_number(alloc: PortsAllocation, index: u16) -> u16 {
|
||||
30000 + 20 * (alloc as u16) + index
|
||||
}
|
||||
|
||||
const LOCALHOST_IP: &str = "127.0.0.1";
|
||||
const BAD_PATH: &str = "/bad/path/to/key/file";
|
||||
|
||||
mod dummy_tcp_sockets;
|
||||
mod pki;
|
||||
mod test_files_utils;
|
||||
|
||||
mod client_invalid_tls_configuration;
|
||||
mod client_invalid_tls_root_certificate_file;
|
||||
mod client_try_tls_while_there_is_no_tls;
|
||||
mod invalid_with_token_auth;
|
||||
mod server_invalid_tls_config_invalid_cert;
|
||||
mod server_invalid_tls_config_invalid_client_crl;
|
||||
mod server_invalid_tls_config_invalid_client_root_cert;
|
||||
mod server_invalid_tls_config_invalid_key;
|
||||
mod server_invalid_token_file;
|
||||
mod server_missing_auth;
|
||||
mod tls_auth_expired_certificate;
|
||||
mod tls_auth_invalid_certificate;
|
||||
mod tls_auth_revoked_certificate;
|
||||
mod valid_token_with_custom_increment;
|
||||
mod valid_with_multiple_token_auth;
|
||||
mod valid_with_tls_auth;
|
||||
mod valid_with_token_auth;
|
||||
mod valid_with_token_auth_and_server_tls;
|
||||
mod valid_with_token_auth_multiple_ports;
|
||||
mod valid_with_token_file;
|
||||
mod with_token_auth_and_invalid_server_tls_bad_ca;
|
||||
mod with_token_auth_and_invalid_server_tls_expired_and_bad_cn;
|
53
src/test/pki.rs
Normal file
53
src/test/pki.rs
Normal file
@ -0,0 +1,53 @@
|
||||
use mktemp::Temp;
|
||||
|
||||
use crate::test::test_files_utils::create_temp_file_with_content;
|
||||
|
||||
pub struct PemHolder(Temp);
|
||||
|
||||
impl PemHolder {
|
||||
fn new(b: &[u8]) -> Self {
|
||||
Self(create_temp_file_with_content(b))
|
||||
}
|
||||
|
||||
pub fn file_path(&self) -> String {
|
||||
self.0.to_str().unwrap().to_string()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Pki {
|
||||
pub expired_client_key: PemHolder,
|
||||
pub expired_client_crt: PemHolder,
|
||||
pub localhost_crt: PemHolder,
|
||||
pub localhost_key: PemHolder,
|
||||
pub other_ca_crl: PemHolder,
|
||||
pub other_ca_crt: PemHolder,
|
||||
pub other_ca_key: PemHolder,
|
||||
pub revoked_client_crt: PemHolder,
|
||||
pub revoked_client_key: PemHolder,
|
||||
pub root_ca_crl: PemHolder,
|
||||
pub root_ca_crt: PemHolder,
|
||||
pub root_ca_key: PemHolder,
|
||||
pub valid_client_crt: PemHolder,
|
||||
pub valid_client_key: PemHolder,
|
||||
}
|
||||
|
||||
impl Pki {
|
||||
pub fn load() -> Self {
|
||||
Self {
|
||||
expired_client_key: PemHolder::new(include_bytes!("test_pki/ExpiredClient.key")),
|
||||
expired_client_crt: PemHolder::new(include_bytes!("test_pki/ExpiredClient.crt")),
|
||||
localhost_crt: PemHolder::new(include_bytes!("test_pki/localhost.crt")),
|
||||
localhost_key: PemHolder::new(include_bytes!("test_pki/localhost.key")),
|
||||
other_ca_crl: PemHolder::new(include_bytes!("test_pki/OtherCA.crl")),
|
||||
other_ca_crt: PemHolder::new(include_bytes!("test_pki/OtherCA.crt")),
|
||||
other_ca_key: PemHolder::new(include_bytes!("test_pki/OtherCA.key")),
|
||||
revoked_client_crt: PemHolder::new(include_bytes!("test_pki/RevokedClient.crt")),
|
||||
revoked_client_key: PemHolder::new(include_bytes!("test_pki/RevokedClient.key")),
|
||||
root_ca_crl: PemHolder::new(include_bytes!("test_pki/TCPTunnelTestCA.crl")),
|
||||
root_ca_crt: PemHolder::new(include_bytes!("test_pki/TCPTunnelTestCA.crt")),
|
||||
root_ca_key: PemHolder::new(include_bytes!("test_pki/TCPTunnelTestCA.key")),
|
||||
valid_client_crt: PemHolder::new(include_bytes!("test_pki/ValidClient.crt")),
|
||||
valid_client_key: PemHolder::new(include_bytes!("test_pki/ValidClient.key")),
|
||||
}
|
||||
}
|
||||
}
|
100
src/test/server_invalid_tls_config_invalid_cert.rs
Normal file
100
src/test/server_invalid_tls_config_invalid_cert.rs
Normal file
@ -0,0 +1,100 @@
|
||||
use crate::tcp_relay_server::server_config::ServerConfig;
|
||||
use crate::test::pki::Pki;
|
||||
use crate::test::test_files_utils::create_temp_file_with_random_content;
|
||||
use crate::test::{get_port_number, PortsAllocation, BAD_PATH};
|
||||
|
||||
const TOKEN: &str = "mytok";
|
||||
|
||||
fn port(index: u16) -> u16 {
|
||||
get_port_number(PortsAllocation::TestsWithoutPortOpened, index)
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn unspecified() {
|
||||
let _ = env_logger::builder().is_test(true).try_init();
|
||||
|
||||
let pki = Pki::load();
|
||||
|
||||
crate::tcp_relay_server::run_app(ServerConfig {
|
||||
tokens: vec![TOKEN.to_string()],
|
||||
tokens_file: None,
|
||||
ports: vec![port(1)],
|
||||
upstream_server: "127.0.0.1".to_string(),
|
||||
listen_address: format!("127.0.0.1:{}", port(0)),
|
||||
increment_ports: 1,
|
||||
tls_cert: None,
|
||||
tls_key: Some(pki.localhost_key.file_path()),
|
||||
tls_client_auth_root_cert: None,
|
||||
tls_revocation_list: None,
|
||||
})
|
||||
.await
|
||||
.unwrap_err();
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn incorrect_pem_type() {
|
||||
let _ = env_logger::builder().is_test(true).try_init();
|
||||
|
||||
let pki = Pki::load();
|
||||
|
||||
crate::tcp_relay_server::run_app(ServerConfig {
|
||||
tokens: vec![TOKEN.to_string()],
|
||||
tokens_file: None,
|
||||
ports: vec![port(1)],
|
||||
upstream_server: "127.0.0.1".to_string(),
|
||||
listen_address: format!("127.0.0.1:{}", port(0)),
|
||||
increment_ports: 1,
|
||||
tls_cert: Some(pki.root_ca_crl.file_path()),
|
||||
tls_key: Some(pki.localhost_key.file_path()),
|
||||
tls_client_auth_root_cert: None,
|
||||
tls_revocation_list: None,
|
||||
})
|
||||
.await
|
||||
.unwrap_err();
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn random_contents() {
|
||||
let _ = env_logger::builder().is_test(true).try_init();
|
||||
|
||||
let pki = Pki::load();
|
||||
|
||||
let random_file = create_temp_file_with_random_content();
|
||||
|
||||
crate::tcp_relay_server::run_app(ServerConfig {
|
||||
tokens: vec![TOKEN.to_string()],
|
||||
tokens_file: None,
|
||||
ports: vec![port(1)],
|
||||
upstream_server: "127.0.0.1".to_string(),
|
||||
listen_address: format!("127.0.0.1:{}", port(0)),
|
||||
increment_ports: 1,
|
||||
tls_cert: Some(random_file.to_string_lossy().to_string()),
|
||||
tls_key: Some(pki.localhost_key.file_path()),
|
||||
tls_client_auth_root_cert: None,
|
||||
tls_revocation_list: None,
|
||||
})
|
||||
.await
|
||||
.unwrap_err();
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn invalid_path() {
|
||||
let _ = env_logger::builder().is_test(true).try_init();
|
||||
|
||||
let pki = Pki::load();
|
||||
|
||||
crate::tcp_relay_server::run_app(ServerConfig {
|
||||
tokens: vec![TOKEN.to_string()],
|
||||
tokens_file: None,
|
||||
ports: vec![port(1)],
|
||||
upstream_server: "127.0.0.1".to_string(),
|
||||
listen_address: format!("127.0.0.1:{}", port(0)),
|
||||
increment_ports: 1,
|
||||
tls_cert: Some(BAD_PATH.to_string()),
|
||||
tls_key: Some(pki.localhost_key.file_path()),
|
||||
tls_client_auth_root_cert: None,
|
||||
tls_revocation_list: None,
|
||||
})
|
||||
.await
|
||||
.unwrap_err();
|
||||
}
|
78
src/test/server_invalid_tls_config_invalid_client_crl.rs
Normal file
78
src/test/server_invalid_tls_config_invalid_client_crl.rs
Normal file
@ -0,0 +1,78 @@
|
||||
use crate::tcp_relay_server::server_config::ServerConfig;
|
||||
use crate::test::pki::Pki;
|
||||
use crate::test::test_files_utils::create_temp_file_with_random_content;
|
||||
use crate::test::{get_port_number, PortsAllocation, BAD_PATH};
|
||||
|
||||
const TOKEN: &str = "mytok";
|
||||
|
||||
fn port(index: u16) -> u16 {
|
||||
get_port_number(PortsAllocation::TestsWithoutPortOpened, index)
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn bad_path() {
|
||||
let _ = env_logger::builder().is_test(true).try_init();
|
||||
|
||||
let pki = Pki::load();
|
||||
|
||||
crate::tcp_relay_server::run_app(ServerConfig {
|
||||
tokens: vec![TOKEN.to_string()],
|
||||
tokens_file: None,
|
||||
ports: vec![port(1)],
|
||||
upstream_server: "127.0.0.1".to_string(),
|
||||
listen_address: format!("127.0.0.1:{}", port(0)),
|
||||
increment_ports: 1,
|
||||
tls_cert: Some(pki.localhost_crt.file_path()),
|
||||
tls_key: Some(pki.localhost_key.file_path()),
|
||||
tls_client_auth_root_cert: Some(pki.root_ca_crl.file_path()),
|
||||
tls_revocation_list: Some(BAD_PATH.to_string()),
|
||||
})
|
||||
.await
|
||||
.unwrap_err();
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn random_content() {
|
||||
let _ = env_logger::builder().is_test(true).try_init();
|
||||
|
||||
let pki = Pki::load();
|
||||
|
||||
let random_file = create_temp_file_with_random_content();
|
||||
|
||||
crate::tcp_relay_server::run_app(ServerConfig {
|
||||
tokens: vec![TOKEN.to_string()],
|
||||
tokens_file: None,
|
||||
ports: vec![port(1)],
|
||||
upstream_server: "127.0.0.1".to_string(),
|
||||
listen_address: format!("127.0.0.1:{}", port(0)),
|
||||
increment_ports: 1,
|
||||
tls_cert: Some(pki.localhost_crt.file_path()),
|
||||
tls_key: Some(pki.localhost_key.file_path()),
|
||||
tls_client_auth_root_cert: Some(pki.root_ca_crl.file_path()),
|
||||
tls_revocation_list: Some(random_file.to_string_lossy().to_string()),
|
||||
})
|
||||
.await
|
||||
.unwrap_err();
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn invalid_pem() {
|
||||
let _ = env_logger::builder().is_test(true).try_init();
|
||||
|
||||
let pki = Pki::load();
|
||||
|
||||
crate::tcp_relay_server::run_app(ServerConfig {
|
||||
tokens: vec![TOKEN.to_string()],
|
||||
tokens_file: None,
|
||||
ports: vec![port(1)],
|
||||
upstream_server: "127.0.0.1".to_string(),
|
||||
listen_address: format!("127.0.0.1:{}", port(0)),
|
||||
increment_ports: 1,
|
||||
tls_cert: Some(pki.localhost_crt.file_path()),
|
||||
tls_key: Some(pki.localhost_key.file_path()),
|
||||
tls_client_auth_root_cert: Some(pki.root_ca_crl.file_path()),
|
||||
tls_revocation_list: Some(pki.root_ca_crt.file_path()),
|
||||
})
|
||||
.await
|
||||
.unwrap_err();
|
||||
}
|
@ -0,0 +1,78 @@
|
||||
use crate::tcp_relay_server::server_config::ServerConfig;
|
||||
use crate::test::pki::Pki;
|
||||
use crate::test::test_files_utils::create_temp_file_with_random_content;
|
||||
use crate::test::{get_port_number, PortsAllocation, BAD_PATH};
|
||||
|
||||
const TOKEN: &str = "mytok";
|
||||
|
||||
fn port(index: u16) -> u16 {
|
||||
get_port_number(PortsAllocation::TestsWithoutPortOpened, index)
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn invalid_path() {
|
||||
let _ = env_logger::builder().is_test(true).try_init();
|
||||
|
||||
let pki = Pki::load();
|
||||
|
||||
crate::tcp_relay_server::run_app(ServerConfig {
|
||||
tokens: vec![TOKEN.to_string()],
|
||||
tokens_file: None,
|
||||
ports: vec![port(1)],
|
||||
upstream_server: "127.0.0.1".to_string(),
|
||||
listen_address: format!("127.0.0.1:{}", port(0)),
|
||||
increment_ports: 1,
|
||||
tls_cert: Some(pki.localhost_crt.file_path()),
|
||||
tls_key: Some(pki.localhost_key.file_path()),
|
||||
tls_client_auth_root_cert: Some(BAD_PATH.to_string()),
|
||||
tls_revocation_list: None,
|
||||
})
|
||||
.await
|
||||
.unwrap_err();
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn other_pem_file_type() {
|
||||
let _ = env_logger::builder().is_test(true).try_init();
|
||||
|
||||
let pki = Pki::load();
|
||||
|
||||
crate::tcp_relay_server::run_app(ServerConfig {
|
||||
tokens: vec![TOKEN.to_string()],
|
||||
tokens_file: None,
|
||||
ports: vec![port(1)],
|
||||
upstream_server: "127.0.0.1".to_string(),
|
||||
listen_address: format!("127.0.0.1:{}", port(0)),
|
||||
increment_ports: 1,
|
||||
tls_cert: Some(pki.localhost_crt.file_path()),
|
||||
tls_key: Some(pki.localhost_key.file_path()),
|
||||
tls_client_auth_root_cert: Some(pki.root_ca_crl.file_path()),
|
||||
tls_revocation_list: None,
|
||||
})
|
||||
.await
|
||||
.unwrap_err();
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn random_content() {
|
||||
let _ = env_logger::builder().is_test(true).try_init();
|
||||
|
||||
let pki = Pki::load();
|
||||
|
||||
let random_file = create_temp_file_with_random_content();
|
||||
|
||||
crate::tcp_relay_server::run_app(ServerConfig {
|
||||
tokens: vec![TOKEN.to_string()],
|
||||
tokens_file: None,
|
||||
ports: vec![port(1)],
|
||||
upstream_server: "127.0.0.1".to_string(),
|
||||
listen_address: format!("127.0.0.1:{}", port(0)),
|
||||
increment_ports: 1,
|
||||
tls_cert: Some(pki.localhost_crt.file_path()),
|
||||
tls_key: Some(pki.localhost_key.file_path()),
|
||||
tls_client_auth_root_cert: Some(random_file.to_string_lossy().to_string()),
|
||||
tls_revocation_list: None,
|
||||
})
|
||||
.await
|
||||
.unwrap_err();
|
||||
}
|
100
src/test/server_invalid_tls_config_invalid_key.rs
Normal file
100
src/test/server_invalid_tls_config_invalid_key.rs
Normal file
@ -0,0 +1,100 @@
|
||||
use crate::tcp_relay_server::server_config::ServerConfig;
|
||||
use crate::test::pki::Pki;
|
||||
use crate::test::test_files_utils::create_temp_file_with_random_content;
|
||||
use crate::test::{get_port_number, PortsAllocation, BAD_PATH};
|
||||
|
||||
const TOKEN: &str = "mytok";
|
||||
|
||||
fn port(index: u16) -> u16 {
|
||||
get_port_number(PortsAllocation::TestsWithoutPortOpened, index)
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn invalid_pem_file_type() {
|
||||
let _ = env_logger::builder().is_test(true).try_init();
|
||||
|
||||
let pki = Pki::load();
|
||||
|
||||
crate::tcp_relay_server::run_app(ServerConfig {
|
||||
tokens: vec![TOKEN.to_string()],
|
||||
tokens_file: None,
|
||||
ports: vec![port(1)],
|
||||
upstream_server: "127.0.0.1".to_string(),
|
||||
listen_address: format!("127.0.0.1:{}", port(0)),
|
||||
increment_ports: 1,
|
||||
tls_cert: Some(pki.root_ca_crt.file_path()),
|
||||
tls_key: Some(pki.root_ca_crt.file_path()),
|
||||
tls_client_auth_root_cert: None,
|
||||
tls_revocation_list: None,
|
||||
})
|
||||
.await
|
||||
.unwrap_err();
|
||||
}
|
||||
|
||||
#[tokio::test()]
|
||||
async fn unspecified() {
|
||||
let _ = env_logger::builder().is_test(true).try_init();
|
||||
|
||||
let pki = Pki::load();
|
||||
|
||||
crate::tcp_relay_server::run_app(ServerConfig {
|
||||
tokens: vec![TOKEN.to_string()],
|
||||
tokens_file: None,
|
||||
ports: vec![port(1)],
|
||||
upstream_server: "127.0.0.1".to_string(),
|
||||
listen_address: format!("127.0.0.1:{}", port(0)),
|
||||
increment_ports: 1,
|
||||
tls_cert: Some(pki.root_ca_crt.file_path()),
|
||||
tls_key: None,
|
||||
tls_client_auth_root_cert: None,
|
||||
tls_revocation_list: None,
|
||||
})
|
||||
.await
|
||||
.unwrap_err();
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn random_content() {
|
||||
let _ = env_logger::builder().is_test(true).try_init();
|
||||
|
||||
let pki = Pki::load();
|
||||
|
||||
let random_content = create_temp_file_with_random_content();
|
||||
|
||||
crate::tcp_relay_server::run_app(ServerConfig {
|
||||
tokens: vec![TOKEN.to_string()],
|
||||
tokens_file: None,
|
||||
ports: vec![port(1)],
|
||||
upstream_server: "127.0.0.1".to_string(),
|
||||
listen_address: format!("127.0.0.1:{}", port(0)),
|
||||
increment_ports: 1,
|
||||
tls_cert: Some(pki.root_ca_crt.file_path()),
|
||||
tls_key: Some(random_content.to_string_lossy().to_string()),
|
||||
tls_client_auth_root_cert: None,
|
||||
tls_revocation_list: None,
|
||||
})
|
||||
.await
|
||||
.unwrap_err();
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn invalid_path() {
|
||||
let _ = env_logger::builder().is_test(true).try_init();
|
||||
|
||||
let pki = Pki::load();
|
||||
|
||||
crate::tcp_relay_server::run_app(ServerConfig {
|
||||
tokens: vec![TOKEN.to_string()],
|
||||
tokens_file: None,
|
||||
ports: vec![port(1)],
|
||||
upstream_server: "127.0.0.1".to_string(),
|
||||
listen_address: format!("127.0.0.1:{}", port(0)),
|
||||
increment_ports: 1,
|
||||
tls_cert: Some(pki.localhost_crt.file_path()),
|
||||
tls_key: Some(BAD_PATH.to_string()),
|
||||
tls_client_auth_root_cert: None,
|
||||
tls_revocation_list: None,
|
||||
})
|
||||
.await
|
||||
.unwrap_err();
|
||||
}
|
28
src/test/server_invalid_token_file.rs
Normal file
28
src/test/server_invalid_token_file.rs
Normal file
@ -0,0 +1,28 @@
|
||||
use crate::tcp_relay_server::server_config::ServerConfig;
|
||||
use crate::test::{get_port_number, PortsAllocation};
|
||||
|
||||
const INVALID_TOKEN: &str = "/tmp/a/token/file/that/does/not/exists";
|
||||
|
||||
fn port(index: u16) -> u16 {
|
||||
get_port_number(PortsAllocation::TestsWithoutPortOpened, index)
|
||||
}
|
||||
|
||||
#[tokio::test()]
|
||||
async fn test() {
|
||||
let _ = env_logger::builder().is_test(true).try_init();
|
||||
|
||||
crate::tcp_relay_server::run_app(ServerConfig {
|
||||
tokens: vec![],
|
||||
tokens_file: Some(INVALID_TOKEN.to_string()),
|
||||
ports: vec![port(1)],
|
||||
upstream_server: "127.0.0.1".to_string(),
|
||||
listen_address: format!("127.0.0.1:{}", port(0)),
|
||||
increment_ports: 1,
|
||||
tls_cert: None,
|
||||
tls_key: None,
|
||||
tls_client_auth_root_cert: None,
|
||||
tls_revocation_list: None,
|
||||
})
|
||||
.await
|
||||
.unwrap_err();
|
||||
}
|
71
src/test/server_missing_auth.rs
Normal file
71
src/test/server_missing_auth.rs
Normal file
@ -0,0 +1,71 @@
|
||||
use crate::tcp_relay_server::server_config::ServerConfig;
|
||||
use crate::test::pki::Pki;
|
||||
use crate::test::{get_port_number, PortsAllocation};
|
||||
|
||||
fn port(index: u16) -> u16 {
|
||||
get_port_number(PortsAllocation::TestsWithoutPortOpened, index)
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn with_tls_server() {
|
||||
let _ = env_logger::builder().is_test(true).try_init();
|
||||
|
||||
let pki = Pki::load();
|
||||
|
||||
crate::tcp_relay_server::run_app(ServerConfig {
|
||||
tokens: vec![],
|
||||
tokens_file: None,
|
||||
ports: vec![port(1)],
|
||||
upstream_server: "127.0.0.1".to_string(),
|
||||
listen_address: format!("127.0.0.1:{}", port(0)),
|
||||
increment_ports: 1,
|
||||
tls_cert: Some(pki.root_ca_crl.file_path()),
|
||||
tls_key: Some(pki.localhost_key.file_path()),
|
||||
tls_client_auth_root_cert: None,
|
||||
tls_revocation_list: None,
|
||||
})
|
||||
.await
|
||||
.unwrap_err();
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn without_tls_server() {
|
||||
let _ = env_logger::builder().is_test(true).try_init();
|
||||
|
||||
crate::tcp_relay_server::run_app(ServerConfig {
|
||||
tokens: vec![],
|
||||
tokens_file: None,
|
||||
ports: vec![port(1)],
|
||||
upstream_server: "127.0.0.1".to_string(),
|
||||
listen_address: format!("127.0.0.1:{}", port(0)),
|
||||
increment_ports: 1,
|
||||
tls_cert: None,
|
||||
tls_key: None,
|
||||
tls_client_auth_root_cert: None,
|
||||
tls_revocation_list: None,
|
||||
})
|
||||
.await
|
||||
.unwrap_err();
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn tls_auth_without_tls_config() {
|
||||
let _ = env_logger::builder().is_test(true).try_init();
|
||||
|
||||
let pki = Pki::load();
|
||||
|
||||
crate::tcp_relay_server::run_app(ServerConfig {
|
||||
tokens: vec![],
|
||||
tokens_file: None,
|
||||
ports: vec![port(1)],
|
||||
upstream_server: "127.0.0.1".to_string(),
|
||||
listen_address: format!("127.0.0.1:{}", port(0)),
|
||||
increment_ports: 1,
|
||||
tls_cert: None,
|
||||
tls_key: None,
|
||||
tls_client_auth_root_cert: Some(pki.root_ca_crt.file_path()),
|
||||
tls_revocation_list: None,
|
||||
})
|
||||
.await
|
||||
.unwrap_err();
|
||||
}
|
17
src/test/test_files_utils.rs
Normal file
17
src/test/test_files_utils.rs
Normal file
@ -0,0 +1,17 @@
|
||||
use mktemp::Temp;
|
||||
use rand::Rng;
|
||||
|
||||
/// Create a temporary file and feed it with some specified content
|
||||
pub fn create_temp_file_with_content(content: &[u8]) -> Temp {
|
||||
let temp = Temp::new_file().unwrap();
|
||||
std::fs::write(&temp, content).unwrap();
|
||||
temp
|
||||
}
|
||||
|
||||
/// Generate a temporary file with some random content
|
||||
pub fn create_temp_file_with_random_content() -> Temp {
|
||||
let random_bytes = rand::thread_rng().gen::<[u8; 10]>();
|
||||
let temp = Temp::new_file().unwrap();
|
||||
std::fs::write(&temp, random_bytes).unwrap();
|
||||
temp
|
||||
}
|
25
src/test/test_pki/ExpiredClient.crt
Normal file
25
src/test/test_pki/ExpiredClient.crt
Normal file
@ -0,0 +1,25 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIELjCCAhagAwIBAgIRAOFWCcZCmPv3QHk6MwXfRogwDQYJKoZIhvcNAQELBQAw
|
||||
GjEYMBYGA1UEAxMPVENQVHVubmVsVGVzdENBMB4XDTIyMDkwMjA3MDkxM1oXDTIy
|
||||
MDkwMjA4MDkxM1owGDEWMBQGA1UEAxMNRXhwaXJlZENsaWVudDCCASIwDQYJKoZI
|
||||
hvcNAQEBBQADggEPADCCAQoCggEBANDTInGsDJ4xq/pSnpeTDSE6B2Z//Had0WQk
|
||||
Wl6z4k6W5t79xFwjmMa4cfJJijfgC1usbV2+BP0nh+dPxedTlItUhIW8Hjx2BM/r
|
||||
q1OPvYNu0bB7zcmT+WHddDLdfsxjSMt53b4UMbcWscflLry7V6ahoXccnPKUyt4U
|
||||
+ZcYaoyPAej32y5Ym8EB2Hv9lMoRVbF02mEoTcdanJdhP/y28NNm9ezMsiv1jtCq
|
||||
aR1ipVj7XdCW3K+vVLWzdfw75+P9bS5uXcAZHVQsJk37nrtezH/6Zgum9OQYUmIx
|
||||
TNzhEzZiKfUWa07l0l3SC81KVf1YVKfwO8pQKATLLaauqXIQWZ8CAwEAAaNxMG8w
|
||||
DgYDVR0PAQH/BAQDAgO4MB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAd
|
||||
BgNVHQ4EFgQUa/z5ULTQT52kxALqprqNhjhIcLswHwYDVR0jBBgwFoAU+53PiQbh
|
||||
7KSQGc797M71fZg+JDUwDQYJKoZIhvcNAQELBQADggIBAF77OAeuaaW00zZfOuRb
|
||||
9Eq6/MzS2kEUczFxkg6TZ3/cvx2tj9EQc7O5lRshbPmzjhGkRRLFBvnbL+wJrt93
|
||||
YS0enQNSGkdivS/q66Vqf0ujL/FhAxZYW5Gc+f7lLt0VYHzp/ChU2ryYx9dH2AJD
|
||||
AKl9vSqz/e5rUyQm/8lU1gNWbf7zb8rHA5WcHGWzTJGdz/pnUx1Mf29dtcAygzwz
|
||||
8yWJI1Rb755tGzocSPULvVuQw4Pvnum0fLJusLLBU9BTZzCW2psXUOaTzjwzza5C
|
||||
WedEPB+/Rtw4cwydEwoI0OvoDXezKcjo8bj8Dna4+UqBz85PFQFZKT23gYBuz4/A
|
||||
8/G/3pvXKf8DTnIo9370qU9Ce0UlohCu0U3rRQDEiMiTxQgkhHn7CXe0quOem9yt
|
||||
RUOXymAUz/IdB/Xu0jfuZUF4e6ObF9yULb1SzmHmsxUD7i2h+453KmsYpSDWp2CP
|
||||
R9UOrhINirSOr1qRm5PCnMO8b+Th7TlhfQBY3u8VTn1l5F4fdzGiIGV5IZmGb1fV
|
||||
b47WC7y3TdJ6i5fWVt2XtKQBQOjOLgPfZs5qW8GFHWrW1Z2otn6vrNMgquhV/9kd
|
||||
9TzSFgbymCFKvGkHXZQ70Rqkb8Q5v3dz3VSFfqdE728hvp3GRHqZDSJhcR/FVahm
|
||||
AKio0jBH1mENEttHndQhXQkE
|
||||
-----END CERTIFICATE-----
|
27
src/test/test_pki/ExpiredClient.key
Normal file
27
src/test/test_pki/ExpiredClient.key
Normal file
@ -0,0 +1,27 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpAIBAAKCAQEA0NMicawMnjGr+lKel5MNIToHZn/8dp3RZCRaXrPiTpbm3v3E
|
||||
XCOYxrhx8kmKN+ALW6xtXb4E/SeH50/F51OUi1SEhbwePHYEz+urU4+9g27RsHvN
|
||||
yZP5Yd10Mt1+zGNIy3ndvhQxtxaxx+UuvLtXpqGhdxyc8pTK3hT5lxhqjI8B6Pfb
|
||||
LlibwQHYe/2UyhFVsXTaYShNx1qcl2E//Lbw02b17MyyK/WO0KppHWKlWPtd0Jbc
|
||||
r69UtbN1/Dvn4/1tLm5dwBkdVCwmTfueu17Mf/pmC6b05BhSYjFM3OETNmIp9RZr
|
||||
TuXSXdILzUpV/VhUp/A7ylAoBMstpq6pchBZnwIDAQABAoIBACq3Zc5W4WXix0k3
|
||||
aVWcMQ1g726aM6yX7+NKRGom5d4ppCRtSKOIbJIJ3NUxEeMII4qnJOAOJLscQQKi
|
||||
INuHD1XI/irVJmI7yhQ2Ix++wYeHPcGaMahQaq0IPeLByFRK4vMshJ2DSAAp1kgL
|
||||
q5nTwMRHP947ric5JJ51L/Emf3Us1SBXBPppOJjy0yMTYpxGImKv/kelfFg5nHBT
|
||||
rnhJ2CuyX0H9R/7Quigwif0Ul7Vth6lUlBm5Y5Ouf9SFN6HvBwqp5J0dSRGejFbn
|
||||
5P7UrKpAL4GR+zocYXi4iv+5ffOj7LKPm47pym5WUJgo04HH+CbajO4R3XFpOyP/
|
||||
I7cj2uECgYEA5SYMAJDGLepkkSbyWd8pvxrHBYlbEFNXmjPaYdCQUTfLqffFl2wb
|
||||
saa/WxW9vQwMKLl0oLRtrEoey2ma3Wx65RLBRke4+WDo/6KRe7jA/C6MjbBTutAn
|
||||
hducVPkw4hKV/ERPb07cGGBA+N3VkS/BaxMu4Ki8oGfOyo53FJ6gvzcCgYEA6Utq
|
||||
jKN86GSL3Iy3tebhWbHw1vNN6JitQYVmlJ2THiVuQBKT9NK0OfPTQgQoWUWKK0v8
|
||||
lodQ1VoC0iiDGHYVjTtRwCT3ajS6/3T8mrpTWWi/gQRB6SXIoQrXC6rs/+OPrRbb
|
||||
uGP/nkLBj1EzPOeldv1jN5nTxxoW634RxuPd3NkCgYEA5Lm9cTMRHfPAvkIp1hsz
|
||||
CFYqIhSgmQMXhgwMB2avJuKSn+15hVObsQ/IIZrp8TF9UYkMKPzwG/FAG7oloq8N
|
||||
XGoEEaq1r/ZTnBchMGWR/CZalXNToDz1tl8nBIpXiNEUdOGaiHgmqQ4qzD5hVrJc
|
||||
Vgyn1geXgGUdvIHHywUrXrECgYEAzrI77+k11Oyoojqm1ep+hKrMOJYO0+LZtnCM
|
||||
B2ZpH0+IlAohvsskVSg7Z4UpfpbHKT9ExtWS/8SlNTAhnn2Y8K2666OU9itL9uPe
|
||||
nvQwvsm4yoVMJFaOoGhrSXIiU0F6XaAgAgnPQ5ffyKvn2rFef8NWsb9/zCrIXdMv
|
||||
yui+/FkCgYB9y+OJQ/CrkHC5zQqsG6PnKw7GZOII0fOrWdCUAJwCG0dv7cZJ03LQ
|
||||
yONxAVdrzTGGOZTOD2vG0oG3XDie2O75qU8d/OUcdl7OqnIqupGUZMARnW0Xny6U
|
||||
fpFdGYs8KeohUfw8LSf95VwJwSBb3zjaPPTR/ZZ+LI3k8wStXlOMiQ==
|
||||
-----END RSA PRIVATE KEY-----
|
16
src/test/test_pki/OtherCA.crl
Normal file
16
src/test/test_pki/OtherCA.crl
Normal file
@ -0,0 +1,16 @@
|
||||
-----BEGIN X509 CRL-----
|
||||
MIICgTBrAgEBMA0GCSqGSIb3DQEBCwUAMBIxEDAOBgNVBAMTB090aGVyQ0EXDTIy
|
||||
MDkwMjA3MTI0MloXDTQyMDkwMjA3MTI0MFowAKAjMCEwHwYDVR0jBBgwFoAUIdv7
|
||||
GAAmusKCN710x76ODIzpFDswDQYJKoZIhvcNAQELBQADggIBAJ6PEWN9ZdK6V1Z+
|
||||
qb1lE6UpDwee7Gvu+WmYLc/ySDy8zpt3er5bfJFEI5zLYRvR7C8I77QuHfm6ytny
|
||||
AcjdZoqLoYn6JkEnbZFj9yddcYfwmo1bxc7YsGKqitQPwUA+Ou2mq9q8pSyAIAY3
|
||||
d1cAKEqHZgnWm/7D4NZZ8lWGjjFz9hlwhP8jWKqRcGsL/RGylNW9wyroECGRg18R
|
||||
YiFIqgXiWAG1CAZcbcv2yKlijSm2q8OgBG5mFMClm5yHEmyju4ZyRowySraSkMkc
|
||||
1lZqOpxRFn59FNE278bm4RJfWFtprvO/1UONq46VIi49q3iykjowGS9enFhd2pDX
|
||||
JGRiMze5+Y9+MRqB7CkpgWr85a6VB/eZHt1klZDXHVviTPBwf7Sps0u2j63ZgMKl
|
||||
NZCG4oTyPguyNF+PF76xqwhGqJJB1zK63wizC+1go4It9vn22tg3/C2X1riWiKjN
|
||||
XimlHyumq1DkRoulwo716m3/DgVbAQD+dfTmGA80QnCMAEpRG0rjBwwrsbuz7TSX
|
||||
38YiBCBAbgM/L/XhVXzuki0Q5xrrcvH8bhxG6/j+gpAFdI3on2R3rHgWMXS8c9tw
|
||||
4gqXuPr4Th3Rb3pwZEsWvUXG3vY/5d2Pq9gCGcEUo36CCaZzMCDh7yrJHd1zY5gT
|
||||
e5zdMjCWD7b5jfM0GpSthrfh7cya
|
||||
-----END X509 CRL-----
|
29
src/test/test_pki/OtherCA.crt
Normal file
29
src/test/test_pki/OtherCA.crt
Normal file
@ -0,0 +1,29 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIE5DCCAsygAwIBAgIBATANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQDEwdPdGhl
|
||||
ckNBMB4XDTIyMDkwMjA3MTI0MloXDTQyMDkwMjA3MTI0MFowEjEQMA4GA1UEAxMH
|
||||
T3RoZXJDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAM802FZEmSvZ
|
||||
A+SfJNWBJsAt7SvWQBxxpzmP8joriDkULG4XCiJGAHY7MsNm6uAk/A2f3TNEghiL
|
||||
tbfQtJKfOEC2NDe8Y9H7bKo9cVep2YORGuXuDH4dkX4oAYYgKbdYSeMHyOsOkpEG
|
||||
1FBlA4rw73RuO/aMqF25e1idLWXgi5fk8SUiWgH9Twse8KcYg8v3pA/SZcoZtc2S
|
||||
rSsJFZJCrEOPZMJpTilW3Sd6KlZ+1niOAyEksYEy+ACQs9PU1H6edn6S+oNxpF24
|
||||
iy3Orr4u3miU40SDOtO2qtrv/6vlbXZaIju5KyEZSMyve0Vvc4v02xUfdGxNPR2y
|
||||
r7IDd0lIfewLMohpE2m2g2VPkWvC+EMkW3lA/a5xyDotF6aFGKblABRjHIRwNORT
|
||||
tx7/jXoX5Cg9zGmLrs3/MhNJvGsErfnNCmDvlP7J7+JbpFgDMJo1uOv1ozLu344Y
|
||||
R75trQBaOglTNNNs0D2sIgfEJTdwOt4PvGMgClcYGerjRZEKFmiX6//S6JBnlfGp
|
||||
d5cWDgLv67sHKk9FXbbsZpomoGOqWKF5DuPoUH+0yOEq4LSoqMmaxFIVf3LgIvD5
|
||||
G+1xV5jxkJsWv9JSY6QpYS9JDSpaOe2FqsQGF8VCd2SOnlzGxnMAISpT9xHrtYu+
|
||||
fCXnf+gXWUsy5Y01It7CMHnW6cFhP+ATAgMBAAGjRTBDMA4GA1UdDwEB/wQEAwIB
|
||||
BjASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQWBBQh2/sYACa6woI3vXTHvo4M
|
||||
jOkUOzANBgkqhkiG9w0BAQsFAAOCAgEAHLGe4p4gBwn2vCotnFxNRc/4NKkRkvO7
|
||||
dlr2jKGCIFfGgU9JsgaYYUckxDzkQadOujpuqeuB4J9OfH+GmbUNG8MOuSJdhtKi
|
||||
sASnYoaF17Go7cOg/6k0GfN5FuIQPjEOM8yFGhAhP4MfsWlNWxUQPh/3QewjfEUt
|
||||
TNJXZ/1zyY2Bjt5hygdSJ8eDe7V8fVV+HcLj17bfgfP+ILbgxPhsc0Sqh719j0va
|
||||
gptqzrLz1eSKjthwVrYh3RuJCBPJJKa51y54TKIqnDkrWEQc0YQf7K3wkJJQ7H6M
|
||||
UELhZLVF2zjEltxcfDGUCHtxcWYApA6chwsDTNYoeb7KdTAmXgQS7JNTqLuvF773
|
||||
nGCKQr6JYPwnQ7QOE7oWVEeINGZtSyKBb/+DpTacK0qaw7MymkJBlaRNHAGsTzfI
|
||||
U0/tKLsi6ItXi8vY/wTxRt4qvlu4mFeGFoTNdTDib6rJKS4D6HoGeRglhefOpv4r
|
||||
luaJ3MwANCTa0T5H/+vDN1NQTMJa6Iul6gKzDkX1vB1duenPpExAgnjm3QeNCvQ/
|
||||
yqNCPEAyZBg83L6ZKCEHQWo3SM2nMwV6X+pS0FKCY/z+7EGH6A4FHriaksOnSNeD
|
||||
HczdA3Kp8jCR9llFknwxvwvIzFbh73E0/KVifIfzmbKakIseohKRNF1kxhFaB+wR
|
||||
DE1o4VTfHl8=
|
||||
-----END CERTIFICATE-----
|
51
src/test/test_pki/OtherCA.key
Normal file
51
src/test/test_pki/OtherCA.key
Normal file
@ -0,0 +1,51 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
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
|
||||
-----END RSA PRIVATE KEY-----
|
25
src/test/test_pki/RevokedClient.crt
Normal file
25
src/test/test_pki/RevokedClient.crt
Normal file
@ -0,0 +1,25 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIELjCCAhagAwIBAgIRAMvrVtV8eUCAihX59TzwyVwwDQYJKoZIhvcNAQELBQAw
|
||||
GjEYMBYGA1UEAxMPVENQVHVubmVsVGVzdENBMB4XDTIyMDkwMjA3MDcwN1oXDTQy
|
||||
MDkwMjA3MDYxMlowGDEWMBQGA1UEAxMNUmV2b2tlZENsaWVudDCCASIwDQYJKoZI
|
||||
hvcNAQEBBQADggEPADCCAQoCggEBAOJ0s0ukj6FaKVQW1rZ7fdT7CqFyBcbQ0yr9
|
||||
nioaFIICJIiN/RsTROlwEtFBYoy68SP/9w+p4c0T+1QXr2T7JBljZ8I0RotPmUL9
|
||||
Jy6fM5dD8m4GM44K4oz+Mk6JaVNOcY1+j670KLRJKLhX/gNTiiqFdmMXrLUdl2KF
|
||||
3qrY2Jh4riygkO0xClKiL57m/8+tCDXI+cycftdfLMDOLkBPA7HCeVdahx2r6mHi
|
||||
5tSlk+sMeXEJy7kR4w4zDUb/MwP1cQgnSMwtdGE4Xz2zSLwEk0P8xNUe7Qwwx605
|
||||
syd/Y/lFDasoPeGgCqFvw/zgZE2D+6U8NbywZBAqa/Nd+UA0v+cCAwEAAaNxMG8w
|
||||
DgYDVR0PAQH/BAQDAgO4MB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAd
|
||||
BgNVHQ4EFgQUOJMPHK9liHjNrIt26DT1pWmat4EwHwYDVR0jBBgwFoAU+53PiQbh
|
||||
7KSQGc797M71fZg+JDUwDQYJKoZIhvcNAQELBQADggIBAI7d1CIJGwwTATNv1ATl
|
||||
UawbtuuV2dbasRA3C9kkG34UOmE8m9z01/rJiwXvF+57rbPMTZUvVhqOGajJNN7K
|
||||
7+S1DDUNjea7snbJO4zsHT6OGV1vw/b0EI4OJKxuYRE5kkUEGPcWSoFbsUEyEXtt
|
||||
Kl22TDOXCEYkvYW5vN2aJokyPl+rmCrzC6E207lkaKyDDBSBPYXxNApBkMMryxUO
|
||||
1yqRxYrfayb0CW0JRHzI9dQNOPtpj3Pd8XKxC0liguTnPReoHC1scTp6GR9uP5TT
|
||||
MlBPuAudcRNd4Kcz4vqBNc3M+ioWt5DBQ4n31beq772AbESpDaM5VBRdDlre6/Q3
|
||||
WEasplODNer44md+V09LbhT3sDYpHuTIYwvHcf7jOO6wUKl7JulOwEkBD2IiTs+6
|
||||
RMT2eIavlQjIObqNvLTWoVfm4b32vvBzyXdrZyr1FIlJ+VlhIpvEC1ZPq3ZLC831
|
||||
sDPtyVI+dA4KV/+ZN3NvP0BfL9+7KE20Ma1V2u8reV51nddjRzNkYt3AdAuO3B9i
|
||||
CUqauhe5o7Ey7QFRAxYvT4xmg9mRjSJSlX+jwXroKymtxgG3f/14Do+5yyN0bS3O
|
||||
FC1H3uV1vwQztxkpJdh8PoWoh+1OsqwrRIYSEAx9M1xSBHz5TzgHQJmot5fwLQTn
|
||||
QgvMyCyS46ciaMjRILqagt6P
|
||||
-----END CERTIFICATE-----
|
27
src/test/test_pki/RevokedClient.key
Normal file
27
src/test/test_pki/RevokedClient.key
Normal file
@ -0,0 +1,27 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEowIBAAKCAQEA4nSzS6SPoVopVBbWtnt91PsKoXIFxtDTKv2eKhoUggIkiI39
|
||||
GxNE6XAS0UFijLrxI//3D6nhzRP7VBevZPskGWNnwjRGi0+ZQv0nLp8zl0PybgYz
|
||||
jgrijP4yTolpU05xjX6PrvQotEkouFf+A1OKKoV2YxestR2XYoXeqtjYmHiuLKCQ
|
||||
7TEKUqIvnub/z60INcj5zJx+118swM4uQE8DscJ5V1qHHavqYeLm1KWT6wx5cQnL
|
||||
uRHjDjMNRv8zA/VxCCdIzC10YThfPbNIvASTQ/zE1R7tDDDHrTmzJ39j+UUNqyg9
|
||||
4aAKoW/D/OBkTYP7pTw1vLBkECpr8135QDS/5wIDAQABAoIBAEtCJWP6KJGi+SEt
|
||||
BeZXXBYv5/SHhEvyknszFiE/0ZjzRVjsdzVMThaWXGqWpD3I0uL36g+Wkagp/9iO
|
||||
loekvvaBBraP0PHzXifZIfBokCixOBxAi1mlXG0m/WkEWbCJ3Ur8yJuIIQ7pUVMS
|
||||
SySn2r8O461C7O60Ct9/ReTZdAIXWRj8uKiJF731RMZ/NFaOZfom5ijFyKcspyQ0
|
||||
ap6CCpx8cZ3M8IUwHZJFgoET8tJX+6LftYKTKhE2LjBBzmGw1xFDuOEXmkrb62Fd
|
||||
1HHUOdkgT3+2SLR3Mz8piWdhhvlg57+WTIKsA5Kx9GTDjIUUTXK5s3PsgxObEpc2
|
||||
JWLhuaECgYEA695jleVohwX1z/I3idmZpSJK1MJOi09Pj4IvR+RXtKN5DpGhQGRO
|
||||
x5TLGxJ9F2nQMErW8+oVBotl39iaFAlT77+CShBtBS7JfDX76whAvLwnouy8Winz
|
||||
YV9IBOFl9XT4hVhvkR7BAzm5CsKAiT9OJRPxX0uHdmsWbnTjMwcG0csCgYEA9cil
|
||||
Pes5ZOQ9Yn+M9wufrOJZ5FnC9NYvgre89OZTQhjISZmX0iW6McVkqEc7Av1S4IGC
|
||||
t8+jVgq4f2XWle83GYrnWxwItGADJdL/X2YWWqzzEvTeyLs3zuLtZUt4wG5MDJJ/
|
||||
XJaTiuA+a9r6/fsQto+0LI43R6Ge5UERi91qVtUCgYABvQLY4PbzP8z++lcEchEa
|
||||
0XThuojfp/b7JMd6bSlkUGwc+l/I3LRj7inNCkbXvFTndjW9WHVNNgvLKYqBKUxw
|
||||
EOZB63sSNbUQcElqAwaPHYfhQINm2rZLemtKderNc049lVhFJoffoTZG6QYPfOLz
|
||||
jQETZbga3FEvATeHcb7QHwKBgH0DPzkNSbYNeUN+SP7nBKJ0xvAkz8qknqnINu4B
|
||||
sNtvq3/0BYq38cqa8iW9hUByBRN4DDrd++Apt8nkzI6ai9YMFrz6t1q3cyJr/cRS
|
||||
MpCQY1qC/kXvI+Ww+rqI9rQ55aiHYwx+8jCy+kz1prBEYS3aTfRTqb5fcGh+/iO7
|
||||
zPi5AoGBANvsVAjy0HJxJom8yfCPw2tzMPh7o9v1jMblKN1xX8B249i27S5UOifO
|
||||
Viy0OR6uiNGT6YLA7Q7esGavkiuK0bWa0M9ezWbGoNh4DmOzn9Q8yEbDz9VF23Pw
|
||||
fc52Ehiq9zS9cqIXc+cQJe/o2J6YziUnBcJc2Ld7d75TISkkdYrN
|
||||
-----END RSA PRIVATE KEY-----
|
17
src/test/test_pki/TCPTunnelTestCA.crl
Normal file
17
src/test/test_pki/TCPTunnelTestCA.crl
Normal file
@ -0,0 +1,17 @@
|
||||
-----BEGIN X509 CRL-----
|
||||
MIICrjCBlwIBATANBgkqhkiG9w0BAQsFADAaMRgwFgYDVQQDEw9UQ1BUdW5uZWxU
|
||||
ZXN0Q0EXDTIyMDkwMjA3MDgwNFoXDTIyMDkwMjA3MDgwNFowJDAiAhEAy+tW1Xx5
|
||||
QICKFfn1PPDJXBcNMjIwOTAyMDcwODA0WqAjMCEwHwYDVR0jBBgwFoAU+53PiQbh
|
||||
7KSQGc797M71fZg+JDUwDQYJKoZIhvcNAQELBQADggIBAAT08Q5BJIU+yvPSsNdE
|
||||
yMBQZSUfTyFOxWYeUiqohpRkCBdhWYAnrZiZN83GArW7rFi1D9p0Cdg5ayDgY1A3
|
||||
4SsnXklwcEdYxIzaLskN1bRY7Idmu9TXdDssPWCyawTfWfV5AfqnqnuKx71gradf
|
||||
jMixrOoOWiBqMp3kHO6F2Q5gKGTQcvjYAe9yVeOF/tchMiHEHBw59HigiHmkX4od
|
||||
7GNbyWyqJlMaVoK13hOt/qnjOFKITsUSzIZ1pI8NY44sBFSIM1SzklfZZ3vBNaeC
|
||||
gA6JBrBm/vEvbZ/WsfCI0uVJwLgCoY4tupocKCLwyN2tyGFhvPwlv4UFEEkabYuo
|
||||
9F7/5CG3JO2yJPHMuflebLawyyfXlbjH9fqvjNRnyry3MXsdphU5OV/xavrSNgLW
|
||||
i8HItaFThCvnMdlMn38UYeGUqp/lgrpQiXEA8K+BX55lJzzNK+UPLNEkf3bROWvR
|
||||
01tstOAhn0rfPKW01HjqXKU8Si2ExBR+kzdamhiZoaKcxuemK/TPd+vmNXuvwede
|
||||
3o2qdXycgFddbKmKejV3gy+zptnFyEGlC3E3BgfSdQ2Tdn0BBltzhRdENB6o5SYh
|
||||
ZUP4Mo3Gr0Hy7eeLGQM7wzmxUxOGmVdqDoWnbOwC2ySEzR6Tsf9id7Sl50DDUcS5
|
||||
G20W0UM0cWIOyaaHAxKl9frl
|
||||
-----END X509 CRL-----
|
29
src/test/test_pki/TCPTunnelTestCA.crt
Normal file
29
src/test/test_pki/TCPTunnelTestCA.crt
Normal file
@ -0,0 +1,29 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIE9DCCAtygAwIBAgIBATANBgkqhkiG9w0BAQsFADAaMRgwFgYDVQQDEw9UQ1BU
|
||||
dW5uZWxUZXN0Q0EwHhcNMjIwOTAyMDcwNjE0WhcNNDIwOTAyMDcwNjEzWjAaMRgw
|
||||
FgYDVQQDEw9UQ1BUdW5uZWxUZXN0Q0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw
|
||||
ggIKAoICAQC5agi1SIe/1SqoBb+p3IstdnZa12IrKtTiSSANV/RtjLgFymqqlvNd
|
||||
I3OJOglJr/ISSWrldh+ZRb661Ds7USLPYC+ZGUXK4jRoe+CvW+WjqUMKbZu2CrAO
|
||||
YmlSy09QCARJX1kv1dLDgukfOmXCTz65uMpf6hZzTr/KNCWJImXSfsJLsuUqhRLn
|
||||
M4mEV3P2TX6hrtAYa8vCVqRO4vlFOvmYdYIOT/TfLTMhmqqodVFQMoUFvl4/ZZEc
|
||||
dEmJOInd+yktSCO9Ziv+A/24Zb9mY46X80NVSoUmvTYB2FEo3AMqmxq1QHo3I7/k
|
||||
3NxK2uLE3xFkpXckHI+FfTjuNvYBn+EqR0FNuCiM+YsCapYBZOW2olMHZs3BI+A3
|
||||
nFS4JGWN53qno5GqKl0mm16b5jt+O7qy6997VvvKlkOgXOFGfa3L3x9lR/i4WUIS
|
||||
+oK1M94xJtbhUgVSH1N8K6J52jyl1EEGCR/LbW2762Db0jIQXT2/T6k0HsF+CVVR
|
||||
BLOMdV8V2JrcXCcnW6L0jGl1pXO9idgnlNlGCndjM6E2wvr6livg7Fjpxw+xJLA1
|
||||
BMhc8gaKxcVZBcHkdmK2G6q49GAO5s6DCiGuNpGgZ1YCAV6OflbKiIJWPV/sGOp9
|
||||
iLEnxYXTAaYMwM86yfBqkIpQk7dqWa5Qfwfb+o2vDhWY5e6/bHdhGwIDAQABo0Uw
|
||||
QzAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQU
|
||||
+53PiQbh7KSQGc797M71fZg+JDUwDQYJKoZIhvcNAQELBQADggIBAFIqak9dGO/i
|
||||
mMRZGu9E7fItltodw9Qphixn5SKc1Rgf6RRj/XGj10JrYiG0ULnEsMLMCu9G4GAp
|
||||
IM2LKYLcirOvP+bM1sWS4ieMrldCVlbJdnhz8TnWInHb1+CNTvXKt41rc/NGsDCp
|
||||
QODmj2Iwd2/QI13ABKGSxjXUvTWl4Cq9kSUvkDZjV/WFjb8nUs6Y6vNQZTc3rne2
|
||||
CUb5+xDRmgz6q/SsAtgH8Rrzt8KYhrT5r4kMkpIFssLBWUQgHGdZEaEnt89qnIVb
|
||||
/mULw7l0716yTkqUBydibyDUsvhgOh1c5Xg/8ICwVptvFzzcbvWFtMjOQCuqB/ud
|
||||
lBcMPIlM2CyytQ6uJjcjEfoy2O1rAlgEb2QKR7abPinlLFo2d1kx3GwPgSzdpROB
|
||||
fJalW0QDLkdeSPSX2a/99KTI8GKQKriG5D2kcHVFAY57P7yjbyrLtD2dKdCTp0M5
|
||||
jPMGjWvFOJ86k8XiNB8yMtABp0K5WZLqqvPFm16sBPaJnpKGo/KUipnLOTnEOpHJ
|
||||
LWDDH8P+HKjhV99s7IwBu+67sDsKO/AsZGRuLJSGh1j8nl/iKhHGgXPfGPY7oDIZ
|
||||
6JyqnW0906KrIoUFZ0b8iKMwIu35aVR++rfWIdFcYqW4flNkAZI0XY5IlJ/i9d7N
|
||||
0ezY2xRAYlJSvefisMIylm0OgUDg0Nv7
|
||||
-----END CERTIFICATE-----
|
51
src/test/test_pki/TCPTunnelTestCA.key
Normal file
51
src/test/test_pki/TCPTunnelTestCA.key
Normal file
@ -0,0 +1,51 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
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
|
||||
-----END RSA PRIVATE KEY-----
|
25
src/test/test_pki/ValidClient.crt
Normal file
25
src/test/test_pki/ValidClient.crt
Normal file
@ -0,0 +1,25 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIELDCCAhSgAwIBAgIRAMBV0/1Yv1gtGnyi/NMvFl0wDQYJKoZIhvcNAQELBQAw
|
||||
GjEYMBYGA1UEAxMPVENQVHVubmVsVGVzdENBMB4XDTIyMDkwMjA3MDczN1oXDTQy
|
||||
MDkwMjA3MDYxMlowFjEUMBIGA1UEAxMLVmFsaWRDbGllbnQwggEiMA0GCSqGSIb3
|
||||
DQEBAQUAA4IBDwAwggEKAoIBAQCd5PIwp/QUA3UVHDHLBQankyDTOyQxSzKR6CbO
|
||||
yh2hkTs/l78eI2KewovYgP4oowRsHYUTNcZHBBKm3fE6BoZOVuQg0Tw126opJ5WE
|
||||
O57nPoeqn/Rlic+lm8r/IM6rUCU0cuPrP3OgzGKgceldlnWmBZ6z6CPtClgv0H0E
|
||||
gpvW57/gfveW4JfON4w+CjWKFFwAdk7NwgwAVupDeTDvzdK4ExWY/cGDs3NynAS/
|
||||
xS8C2KBVmK40l9eE0HMY6cFQ54hM9wYVeZFZsCQ+9P/3ywEtdb1xsVjcDzmk5Uhx
|
||||
wVGrzu9FIowx1K3b/zINQVhefsDPCa/IfMy4NaNxwg65zqjZAgMBAAGjcTBvMA4G
|
||||
A1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwHQYD
|
||||
VR0OBBYEFPw35WYKl2KasK9cNi2tROUQFX+RMB8GA1UdIwQYMBaAFPudz4kG4eyk
|
||||
kBnO/ezO9X2YPiQ1MA0GCSqGSIb3DQEBCwUAA4ICAQAe33X1mHnOIWeCA7XZGBVu
|
||||
+zbXTheHOSZICrM/pOzNbspTTFkQ68sBOwd2HcFhhm1WX09b05ipYiEbXNZCIELq
|
||||
RWPN6yr7x7zFNjZyXxZAtL01pOVih8yfyg1WgW2hVB3VH9/9txMRIySfRoD8OMD9
|
||||
rJfE8mhJcCELY1Fp2G4U6pghoGqRTyalHO5pxVFQuumudYnNlJhdSflcL6Y17Y5F
|
||||
pclI8vJ3j940x/w1XfAd68xiw/Rc6SZQzIzvl6mjSGyFX5Un814wWXQZ7kAtH9fV
|
||||
d8l75O02GLoocmkePwPFmhqc09WYAZTZgxJqEPyI6S1VHOUBsGru5rkY44zeRs2p
|
||||
V2jHSIpcsbP04iwMDNFJV24Fio8A9hV4LFm5Nyv3O6gBgyyiRnYGvfS9R6wazGNW
|
||||
LXAXQw69Wios4PxdlIX85jIJgyJ5GrjpjTTYmzkhe7fs8s3jdm4a2mFMWQcjbSia
|
||||
15mF/1TdVNcKqt/M55aYY6HL3AnIc90TDIXr7UWZVJSeYicVZdI8N0Ih/1myOYw7
|
||||
3NvqUetYLw/FQ7C+763N9QLgSdPlBTMkMSyB2pkXAAzWwJ/UPJ6z5REZmTVHu8Kf
|
||||
I5UD0GwVnfUpBTLEpUG4oTH39PhKlncCKtmMnaZiu0DzxMy0xeskFT7YZFj0BKQc
|
||||
JXXeqkcOvTFHibpLR5lQ1Q==
|
||||
-----END CERTIFICATE-----
|
27
src/test/test_pki/ValidClient.key
Normal file
27
src/test/test_pki/ValidClient.key
Normal file
@ -0,0 +1,27 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpgIBAAKCAQEAneTyMKf0FAN1FRwxywUGp5Mg0zskMUsykegmzsodoZE7P5e/
|
||||
HiNinsKL2ID+KKMEbB2FEzXGRwQSpt3xOgaGTlbkINE8NduqKSeVhDue5z6Hqp/0
|
||||
ZYnPpZvK/yDOq1AlNHLj6z9zoMxioHHpXZZ1pgWes+gj7QpYL9B9BIKb1ue/4H73
|
||||
luCXzjeMPgo1ihRcAHZOzcIMAFbqQ3kw783SuBMVmP3Bg7NzcpwEv8UvAtigVZiu
|
||||
NJfXhNBzGOnBUOeITPcGFXmRWbAkPvT/98sBLXW9cbFY3A85pOVIccFRq87vRSKM
|
||||
MdSt2/8yDUFYXn7AzwmvyHzMuDWjccIOuc6o2QIDAQABAoIBAQCdaZfOzFK49S1v
|
||||
61j090DIJhVOoaKWhkqXTiQKe1QJNJol7yo5aLu0XW5AXXGFn+gTxWZbXXwcZsIV
|
||||
nCUXXVPenB/5W8A0TZgaSX11hF8KWbu1bpyf8kGS8Hvz2IhSIKfG31e8u9iSEdGt
|
||||
9YLbq9oEt4ud/qx6cJq0qJ1Kts+Y8ofAXjTqxa0+LVmCPRJFp1CjCAanq/VBx+cR
|
||||
TjDMcBAnKB8u1wrMc4Hw8ew693wHaxYQEm1bZkjplQbUCA/IKTr1otIyCHRpNKUJ
|
||||
XmNTr+zU0zqjGudeeNrEu8vjXMFzlWXoKlbVoYgfJ7lIp/9s2KDa/AjEpsrbmDo6
|
||||
vAsH9gnFAoGBAMOcEd7LQFoIxdNl2BFV4jDoSLrTeNjTwXFfe4/UQSvb8lAwzYl5
|
||||
aD7uT6XpkK5PV0vX9w6Wi0JVidbZVRmF0Ml+sXn/SpV9juQxMR5GpCWsCz1H+3Vj
|
||||
a11GyAy836tX5harxLWhQq/q7HEit7SnNTe5i5Hvin8v1S7jfo6hdQ3TAoGBAM6k
|
||||
D3q8yBu/JDrruL1SfyKiQT+U+9ccR6OJ713qsM9gZ1HocbFMDwVXLG3U+NRRmhxF
|
||||
xbY9zyEaLERcNAPbbm/aB+hXCsBAIe5XO5EIYGi5cP2+/2UjDxx/YIZkx71fe/5+
|
||||
QoVUc+TK1i9lCZUXEvDxnVZdMYsu6dOEHldxvwcjAoGBAMJ/1DERLrqXkIUj9lU+
|
||||
bXut7GuATOBkpitiAs3AAtFmkSl1bVot0x8H/UB+3rLEB4xNgMYLoQrjXPy5+2k2
|
||||
aqWACV7CHtpID6YM18c//IXM7RwREBLoOWB1OgOYZlrMOuf+AcmMQHAFivbvy3Sg
|
||||
8kSnhQUmBzNyT2qhID0Yg/irAoGBAIDfAGhjY8kqI8Y7TDOGR5Op7Vdh6s307Rio
|
||||
5YeE3k/2p3kFpiIUdSm3fBXjRGvlmF8ZhHxrf8n9MK5Rcn8VUoKfT18vKZ1MYdzq
|
||||
ulNxDe9B953IiC7i9oGnTuOB5q/L5OCKjaHpUX3Wok1cjeVVRpLNnHpIFKXg1CL9
|
||||
uo5+ecxRAoGBAKUr4pYT8wmu8BoNNoVkn6/c7m7ssBJxRUsj7cjxNpCIXzUKMzDj
|
||||
Vqup7ex/tVOXZ10JEE96IMvm+b+Dje32x5oP2qaMYAlAhxJd6P0+5C7eRhZnwqYa
|
||||
n82eXRq0ij6ggvXHvfhxgpa51hCRtEv6MGNu5qJ9QGKxb8VAFbQT3vPI
|
||||
-----END RSA PRIVATE KEY-----
|
25
src/test/test_pki/localhost.crt
Normal file
25
src/test/test_pki/localhost.crt
Normal file
@ -0,0 +1,25 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIERzCCAi+gAwIBAgIQAtk0UZ5qjqGgxYWL7X9GhDANBgkqhkiG9w0BAQsFADAa
|
||||
MRgwFgYDVQQDEw9UQ1BUdW5uZWxUZXN0Q0EwHhcNMjIwOTAyMDcwNzUxWhcNNDIw
|
||||
OTAyMDcwNjEyWjAUMRIwEAYDVQQDEwlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEB
|
||||
AQUAA4IBDwAwggEKAoIBAQDLuZElNqvAPIiTBjWJIjD1Ie+Amw1MvsWMY7UP56qC
|
||||
czkvHI4wfHRJ+mCsUsbKnKR8nYDCa2CiiZpI/oWDZcQZBWmOjaoeBJajw6g+sjFl
|
||||
+lft4xY6aMSXnpcU71KNelOLZsZmPYs24ZUgmjnQB1s6HZlF1niGabCaNnLtd5z2
|
||||
HBPqHno2YvvD4r41n/+kDjhKoZ0t0coZnZaBlEPMvnBOlC1Z/Cn41tORTGkgm3rT
|
||||
+PY3aS8n2q7prLvMc7QD/4kaN5Ep6IydXYIB+gjwIscgSHEdLZq0rAU1Xk/PQrCc
|
||||
P3ysdeXFnSq4VuvgVSgXPa4pACvY+cNjaSTzk1WRaLW1AgMBAAGjgY4wgYswDgYD
|
||||
VR0PAQH/BAQDAgO4MB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAdBgNV
|
||||
HQ4EFgQU2uwKZmO17EkQ8bLDVMdiTqLlyYEwHwYDVR0jBBgwFoAU+53PiQbh7KSQ
|
||||
Gc797M71fZg+JDUwGgYDVR0RBBMwEYIJbG9jYWxob3N0hwR/AAABMA0GCSqGSIb3
|
||||
DQEBCwUAA4ICAQAHf8955HzEOTpmdN34O2jVKC1Riu8Zrpv19Gi1AJpi4WJN3xNv
|
||||
BR6EeaelYEazf17ia5pj3mlT+95aE9wDYVWyqzrJuni5sT94Vw2wIL87qHxFnnBc
|
||||
Wd2HhTbVSduYlIBOOFpaY28d1td6S2XsiTVfare7z8HESkcP/JeERtAtCnT8NCaC
|
||||
vxSPdW+fEQxIXssS+PrlOH3rOcZHj8xUD8SDxgiizf0BZw15aLG4YsEhVU8w292K
|
||||
mBmV0eYcsVpWTplE71zHDc1oJqmCZtLfYjPDy6gzyikkspPDCDU+MLT6y//WJC4d
|
||||
onY0JZ9CA6i9DKlSsOvQN0LypcYOFdKjWPMwXD0PXy1Mrte4KqexhxlTJfc8WHNt
|
||||
GhYOCMtYvScHE0T6XD9ybrFb2u+u8TFqrHCfTabJEaCGBsMMK2XwYQvtbRiTjvtB
|
||||
sTSJrB4fvKfWahYUXZtM4unll752xRjQawW+/Nt7Bi4CeKlQX/6nlpAJTmKDxLCK
|
||||
OWyS4oNWrcLmVUIKnPiaXA0AsnlOmwuR1Fsrgo+SYJqCeoe90+oo+GdqOmRuSZU9
|
||||
N+ry011LZMsNzaHifWqsh1jp3kUQ5XnBA4KWv1Asgg0oCpRnYmUS7GSSdBZkp9a2
|
||||
0TEp4yh/gUZ+YO3/XQmpDa1/3kojfhD+WcRQoZ5lwMrlwxtvmiOit4JJQA==
|
||||
-----END CERTIFICATE-----
|
27
src/test/test_pki/localhost.key
Normal file
27
src/test/test_pki/localhost.key
Normal file
@ -0,0 +1,27 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpAIBAAKCAQEAy7mRJTarwDyIkwY1iSIw9SHvgJsNTL7FjGO1D+eqgnM5LxyO
|
||||
MHx0SfpgrFLGypykfJ2AwmtgoomaSP6Fg2XEGQVpjo2qHgSWo8OoPrIxZfpX7eMW
|
||||
OmjEl56XFO9SjXpTi2bGZj2LNuGVIJo50AdbOh2ZRdZ4hmmwmjZy7Xec9hwT6h56
|
||||
NmL7w+K+NZ//pA44SqGdLdHKGZ2WgZRDzL5wTpQtWfwp+NbTkUxpIJt60/j2N2kv
|
||||
J9qu6ay7zHO0A/+JGjeRKeiMnV2CAfoI8CLHIEhxHS2atKwFNV5Pz0KwnD98rHXl
|
||||
xZ0quFbr4FUoFz2uKQAr2PnDY2kk85NVkWi1tQIDAQABAoIBAGipZAUPSjtPngaS
|
||||
iQxzsV0uWwHiJnoIBCt0yf9q0DGGiplGfVIxjfi3ldTSDejngqW2sQCw84ttUAMy
|
||||
J1ty+8SzACDJbN1RFCb8DMJw/2nZrDS9lpzZWC5gvlN2BB5E+wjB+ylpcsz2JYwD
|
||||
T7ItJVP9AtJbNb4wLBd945tV+SCCL4wrfaudjDAAXw5YZSIjTucxU4WRm2y8wZ86
|
||||
do4J+NscjLpUvuIthfGiui75WGHEdtNu5iveM1dUsQWrIsMxk53D425ovd5Szx6x
|
||||
6UJBjSwhmIAXxtAwzzrlO/U/4JAyMOHJs+hmCu78bLwjSJBzP/fZzG/KhFm0eyMD
|
||||
RNMDy4ECgYEA6g42ffOGfP/58IxPk8C+xoRjc2a1TAI/z3ymAxbC+iFYPCiuabXf
|
||||
twJkTl0yioupq3H0yW6dh2/nTtIpA99L2tEYr44R48LcSD2R5UyE8nYohz+LlOJf
|
||||
U/vx/p7ao6I8mv7xFI5E52ChvEfkvNwmVcUJlmZ1JswGdwNf4WZzb+ECgYEA3tNc
|
||||
EXdiWPbkzbOZISJwMyA6S5NqIZm5zoBLtU5ChDoqHQMYE6YmI0stgpNEwEvcmO2C
|
||||
+9cGvB5mhklrYxxIRL9TzqqUi628/DqSTubBm/Xm+WblRKoDCN0dKK6SS/pkrxWw
|
||||
YyIGbrCHQXWR1KOlvTvq7uHNXixOvpQVElrmkFUCgYEA6EUUhKeAJlosoi/L5NfZ
|
||||
Os40l1gswHJW+sQ7R0N2WJ1wn7rLYvJvQYFpI29Pcbgpt48OGjvgroA5rrnWpBYb
|
||||
g9oPQmCdlkZRLouTVlc6dBcYHyfLkAOaEJEtVL42QT8GH9ayTfDlpiv6NQuvjlB2
|
||||
5pTz78JbrhW4sLCznM577mECgYAcThMC8PxgOrSj4K2SBPLlu7FMCmTP8dwlfCyh
|
||||
0lgmvdC9sLftPwzXLOSSEq0IFFroXjtmTFFBskbpxgfLJjuT6A34Ubje6Wn5TGNr
|
||||
fGqZqin2AnkbONF73cKneU2CM0N47jNi1F6mzuvPh+THcyZJnIPiZnKVBOHX2a23
|
||||
kC57pQKBgQCchLrp2oX0q0jKVb5BqbsJiRMuBhRC96M0IABH6YRaCW372XCvgCWC
|
||||
jtvXuT0XmqTYbmtpPEw1Pp9eJ3qminK4Z55N2fG+c9wtzJ+Mli8UoS3yFRSzbneD
|
||||
LtbdqXEoZPYd6dLbTPTe43Pnl45o4epC+46c678nP/TrtfnKAiL1SA==
|
||||
-----END RSA PRIVATE KEY-----
|
58
src/test/tls_auth_expired_certificate.rs
Normal file
58
src/test/tls_auth_expired_certificate.rs
Normal file
@ -0,0 +1,58 @@
|
||||
use tokio::task;
|
||||
|
||||
use crate::tcp_relay_client::client_config::ClientConfig;
|
||||
use crate::tcp_relay_server::server_config::ServerConfig;
|
||||
use crate::test::dummy_tcp_sockets::{wait_for_port, DummyTCPServer};
|
||||
use crate::test::pki::Pki;
|
||||
use crate::test::{get_port_number, PortsAllocation, LOCALHOST_IP};
|
||||
|
||||
fn port(index: u16) -> u16 {
|
||||
get_port_number(PortsAllocation::TlsAuthExpiredClientCertificate, index)
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test() {
|
||||
let _ = env_logger::builder().is_test(true).try_init();
|
||||
|
||||
// Start internal service
|
||||
let local_server = DummyTCPServer::start(port(1)).await;
|
||||
tokio::spawn(async move {
|
||||
local_server.loop_conn_square_operations().await;
|
||||
});
|
||||
|
||||
let pki = Pki::load();
|
||||
|
||||
let local_set = task::LocalSet::new();
|
||||
local_set
|
||||
.run_until(async move {
|
||||
wait_for_port(port(1)).await;
|
||||
|
||||
// Start server relay
|
||||
task::spawn_local(crate::tcp_relay_server::run_app(ServerConfig {
|
||||
tokens: vec![],
|
||||
tokens_file: None,
|
||||
ports: vec![port(1)],
|
||||
upstream_server: "127.0.0.1".to_string(),
|
||||
listen_address: format!("127.0.0.1:{}", port(0)),
|
||||
increment_ports: 1,
|
||||
tls_cert: Some(pki.localhost_crt.file_path()),
|
||||
tls_key: Some(pki.localhost_key.file_path()),
|
||||
tls_client_auth_root_cert: Some(pki.root_ca_crt.file_path()),
|
||||
tls_revocation_list: Some(pki.root_ca_crl.file_path()),
|
||||
}));
|
||||
wait_for_port(port(0)).await;
|
||||
|
||||
// Start client relay
|
||||
crate::tcp_relay_client::run_app(ClientConfig {
|
||||
relay_url: format!("https://localhost:{}", port(0)),
|
||||
listen_address: LOCALHOST_IP.to_string(),
|
||||
root_certificate: Some(pki.root_ca_crt.file_path()),
|
||||
tls_cert: Some(pki.expired_client_crt.file_path()),
|
||||
tls_key: Some(pki.valid_client_key.file_path()),
|
||||
..Default::default()
|
||||
})
|
||||
.await
|
||||
.unwrap_err();
|
||||
})
|
||||
.await;
|
||||
}
|
58
src/test/tls_auth_invalid_certificate.rs
Normal file
58
src/test/tls_auth_invalid_certificate.rs
Normal file
@ -0,0 +1,58 @@
|
||||
use tokio::task;
|
||||
|
||||
use crate::tcp_relay_client::client_config::ClientConfig;
|
||||
use crate::tcp_relay_server::server_config::ServerConfig;
|
||||
use crate::test::dummy_tcp_sockets::{wait_for_port, DummyTCPServer};
|
||||
use crate::test::pki::Pki;
|
||||
use crate::test::{get_port_number, PortsAllocation, LOCALHOST_IP};
|
||||
|
||||
fn port(index: u16) -> u16 {
|
||||
get_port_number(PortsAllocation::TlsAuthInvalidClientCertificate, index)
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test() {
|
||||
let _ = env_logger::builder().is_test(true).try_init();
|
||||
|
||||
// Start internal service
|
||||
let local_server = DummyTCPServer::start(port(1)).await;
|
||||
tokio::spawn(async move {
|
||||
local_server.loop_conn_square_operations().await;
|
||||
});
|
||||
|
||||
let pki = Pki::load();
|
||||
|
||||
let local_set = task::LocalSet::new();
|
||||
local_set
|
||||
.run_until(async move {
|
||||
wait_for_port(port(1)).await;
|
||||
|
||||
// Start server relay
|
||||
task::spawn_local(crate::tcp_relay_server::run_app(ServerConfig {
|
||||
tokens: vec![],
|
||||
tokens_file: None,
|
||||
ports: vec![port(1)],
|
||||
upstream_server: "127.0.0.1".to_string(),
|
||||
listen_address: format!("127.0.0.1:{}", port(0)),
|
||||
increment_ports: 1,
|
||||
tls_cert: Some(pki.localhost_crt.file_path()),
|
||||
tls_key: Some(pki.localhost_key.file_path()),
|
||||
tls_client_auth_root_cert: Some(pki.other_ca_crt.file_path()),
|
||||
tls_revocation_list: Some(pki.other_ca_crl.file_path()),
|
||||
}));
|
||||
wait_for_port(port(0)).await;
|
||||
|
||||
// Start client relay
|
||||
crate::tcp_relay_client::run_app(ClientConfig {
|
||||
relay_url: format!("https://localhost:{}", port(0)),
|
||||
listen_address: LOCALHOST_IP.to_string(),
|
||||
root_certificate: Some(pki.root_ca_crt.file_path()),
|
||||
tls_cert: Some(pki.revoked_client_crt.file_path()),
|
||||
tls_key: Some(pki.revoked_client_key.file_path()),
|
||||
..Default::default()
|
||||
})
|
||||
.await
|
||||
.unwrap_err();
|
||||
})
|
||||
.await;
|
||||
}
|
58
src/test/tls_auth_revoked_certificate.rs
Normal file
58
src/test/tls_auth_revoked_certificate.rs
Normal file
@ -0,0 +1,58 @@
|
||||
use tokio::task;
|
||||
|
||||
use crate::tcp_relay_client::client_config::ClientConfig;
|
||||
use crate::tcp_relay_server::server_config::ServerConfig;
|
||||
use crate::test::dummy_tcp_sockets::{wait_for_port, DummyTCPServer};
|
||||
use crate::test::pki::Pki;
|
||||
use crate::test::{get_port_number, PortsAllocation, LOCALHOST_IP};
|
||||
|
||||
fn port(index: u16) -> u16 {
|
||||
get_port_number(PortsAllocation::TlsAuthRevokedClientCertificate, index)
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test() {
|
||||
let _ = env_logger::builder().is_test(true).try_init();
|
||||
|
||||
// Start internal service
|
||||
let local_server = DummyTCPServer::start(port(1)).await;
|
||||
tokio::spawn(async move {
|
||||
local_server.loop_conn_square_operations().await;
|
||||
});
|
||||
|
||||
let pki = Pki::load();
|
||||
|
||||
let local_set = task::LocalSet::new();
|
||||
local_set
|
||||
.run_until(async move {
|
||||
wait_for_port(port(1)).await;
|
||||
|
||||
// Start server relay
|
||||
task::spawn_local(crate::tcp_relay_server::run_app(ServerConfig {
|
||||
tokens: vec![],
|
||||
tokens_file: None,
|
||||
ports: vec![port(1)],
|
||||
upstream_server: "127.0.0.1".to_string(),
|
||||
listen_address: format!("127.0.0.1:{}", port(0)),
|
||||
increment_ports: 1,
|
||||
tls_cert: Some(pki.localhost_crt.file_path()),
|
||||
tls_key: Some(pki.localhost_key.file_path()),
|
||||
tls_client_auth_root_cert: Some(pki.root_ca_crt.file_path()),
|
||||
tls_revocation_list: Some(pki.root_ca_crl.file_path()),
|
||||
}));
|
||||
wait_for_port(port(0)).await;
|
||||
|
||||
// Start client relay
|
||||
crate::tcp_relay_client::run_app(ClientConfig {
|
||||
relay_url: format!("https://localhost:{}", port(0)),
|
||||
listen_address: LOCALHOST_IP.to_string(),
|
||||
root_certificate: Some(pki.root_ca_crt.file_path()),
|
||||
tls_cert: Some(pki.revoked_client_crt.file_path()),
|
||||
tls_key: Some(pki.revoked_client_key.file_path()),
|
||||
..Default::default()
|
||||
})
|
||||
.await
|
||||
.unwrap_err();
|
||||
})
|
||||
.await;
|
||||
}
|
59
src/test/valid_token_with_custom_increment.rs
Normal file
59
src/test/valid_token_with_custom_increment.rs
Normal file
@ -0,0 +1,59 @@
|
||||
use tokio::task;
|
||||
|
||||
use crate::tcp_relay_client::client_config::ClientConfig;
|
||||
use crate::tcp_relay_server::server_config::ServerConfig;
|
||||
use crate::test::dummy_tcp_sockets::{
|
||||
dummy_tcp_client_square_root_requests, wait_for_port, DummyTCPServer,
|
||||
};
|
||||
use crate::test::{get_port_number, PortsAllocation, LOCALHOST_IP};
|
||||
|
||||
const VALID_TOKEN: &str = "AvalidTOKEN";
|
||||
|
||||
fn port(index: u16) -> u16 {
|
||||
get_port_number(PortsAllocation::ValidTokenWithCustomIncrement, index)
|
||||
}
|
||||
|
||||
#[tokio::test()]
|
||||
async fn test() {
|
||||
let _ = env_logger::builder().is_test(true).try_init();
|
||||
|
||||
// Start internal service
|
||||
let local_server = DummyTCPServer::start(port(1)).await;
|
||||
tokio::spawn(async move {
|
||||
local_server.loop_conn_square_operations().await;
|
||||
});
|
||||
|
||||
let local_set = task::LocalSet::new();
|
||||
local_set
|
||||
.run_until(async move {
|
||||
wait_for_port(port(1)).await;
|
||||
|
||||
// Start server relay
|
||||
task::spawn_local(crate::tcp_relay_server::run_app(ServerConfig {
|
||||
tokens: vec![VALID_TOKEN.to_string()],
|
||||
tokens_file: None,
|
||||
ports: vec![port(1)],
|
||||
upstream_server: "127.0.0.1".to_string(),
|
||||
listen_address: format!("127.0.0.1:{}", port(0)),
|
||||
increment_ports: 3,
|
||||
tls_cert: None,
|
||||
tls_key: None,
|
||||
tls_client_auth_root_cert: None,
|
||||
tls_revocation_list: None,
|
||||
}));
|
||||
wait_for_port(port(0)).await;
|
||||
|
||||
// Start client relay
|
||||
task::spawn(crate::tcp_relay_client::run_app(ClientConfig {
|
||||
token: Some(VALID_TOKEN.to_string()),
|
||||
relay_url: format!("http://{}:{}", LOCALHOST_IP, port(0)),
|
||||
listen_address: LOCALHOST_IP.to_string(),
|
||||
root_certificate: None,
|
||||
..Default::default()
|
||||
}));
|
||||
wait_for_port(port(4)).await;
|
||||
|
||||
dummy_tcp_client_square_root_requests(port(4), 10).await;
|
||||
})
|
||||
.await;
|
||||
}
|
63
src/test/valid_with_multiple_token_auth.rs
Normal file
63
src/test/valid_with_multiple_token_auth.rs
Normal file
@ -0,0 +1,63 @@
|
||||
use tokio::task;
|
||||
|
||||
use crate::tcp_relay_client::client_config::ClientConfig;
|
||||
use crate::tcp_relay_server::server_config::ServerConfig;
|
||||
use crate::test::dummy_tcp_sockets::{
|
||||
dummy_tcp_client_square_root_requests, wait_for_port, DummyTCPServer,
|
||||
};
|
||||
use crate::test::{get_port_number, PortsAllocation, LOCALHOST_IP};
|
||||
|
||||
const VALID_TOKEN: &str = "AvalidTOKEN";
|
||||
|
||||
fn port(index: u16) -> u16 {
|
||||
get_port_number(PortsAllocation::ValidWithTokenFile, index)
|
||||
}
|
||||
|
||||
#[tokio::test()]
|
||||
async fn valid_with_multiple_token_auth() {
|
||||
let _ = env_logger::builder().is_test(true).try_init();
|
||||
|
||||
// Start internal service
|
||||
let local_server = DummyTCPServer::start(port(1)).await;
|
||||
tokio::spawn(async move {
|
||||
local_server.loop_conn_square_operations().await;
|
||||
});
|
||||
|
||||
let local_set = task::LocalSet::new();
|
||||
local_set
|
||||
.run_until(async move {
|
||||
wait_for_port(port(1)).await;
|
||||
|
||||
// Start server relay
|
||||
task::spawn_local(crate::tcp_relay_server::run_app(ServerConfig {
|
||||
tokens: vec![
|
||||
"tok0".to_string(),
|
||||
VALID_TOKEN.to_string(),
|
||||
"tok2".to_string(),
|
||||
],
|
||||
tokens_file: None,
|
||||
ports: vec![port(1)],
|
||||
upstream_server: "127.0.0.1".to_string(),
|
||||
listen_address: format!("127.0.0.1:{}", port(0)),
|
||||
increment_ports: 1,
|
||||
tls_cert: None,
|
||||
tls_key: None,
|
||||
tls_client_auth_root_cert: None,
|
||||
tls_revocation_list: None,
|
||||
}));
|
||||
wait_for_port(port(0)).await;
|
||||
|
||||
// Start client relay
|
||||
task::spawn(crate::tcp_relay_client::run_app(ClientConfig {
|
||||
token: Some(VALID_TOKEN.to_string()),
|
||||
relay_url: format!("http://{}:{}", LOCALHOST_IP, port(0)),
|
||||
listen_address: LOCALHOST_IP.to_string(),
|
||||
root_certificate: None,
|
||||
..Default::default()
|
||||
}));
|
||||
wait_for_port(port(2)).await;
|
||||
|
||||
dummy_tcp_client_square_root_requests(port(2), 10).await;
|
||||
})
|
||||
.await;
|
||||
}
|
61
src/test/valid_with_tls_auth.rs
Normal file
61
src/test/valid_with_tls_auth.rs
Normal file
@ -0,0 +1,61 @@
|
||||
use tokio::task;
|
||||
|
||||
use crate::tcp_relay_client::client_config::ClientConfig;
|
||||
use crate::tcp_relay_server::server_config::ServerConfig;
|
||||
use crate::test::dummy_tcp_sockets::{
|
||||
dummy_tcp_client_square_root_requests, wait_for_port, DummyTCPServer,
|
||||
};
|
||||
use crate::test::pki::Pki;
|
||||
use crate::test::{get_port_number, PortsAllocation, LOCALHOST_IP};
|
||||
|
||||
fn port(index: u16) -> u16 {
|
||||
get_port_number(PortsAllocation::ValidWithTLSAuth, index)
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test() {
|
||||
let _ = env_logger::builder().is_test(true).try_init();
|
||||
|
||||
// Start internal service
|
||||
let local_server = DummyTCPServer::start(port(1)).await;
|
||||
tokio::spawn(async move {
|
||||
local_server.loop_conn_square_operations().await;
|
||||
});
|
||||
|
||||
let pki = Pki::load();
|
||||
|
||||
let local_set = task::LocalSet::new();
|
||||
local_set
|
||||
.run_until(async move {
|
||||
wait_for_port(port(1)).await;
|
||||
|
||||
// Start server relay
|
||||
task::spawn_local(crate::tcp_relay_server::run_app(ServerConfig {
|
||||
tokens: vec![],
|
||||
tokens_file: None,
|
||||
ports: vec![port(1)],
|
||||
upstream_server: "127.0.0.1".to_string(),
|
||||
listen_address: format!("127.0.0.1:{}", port(0)),
|
||||
increment_ports: 1,
|
||||
tls_cert: Some(pki.localhost_crt.file_path()),
|
||||
tls_key: Some(pki.localhost_key.file_path()),
|
||||
tls_client_auth_root_cert: Some(pki.root_ca_crt.file_path()),
|
||||
tls_revocation_list: Some(pki.root_ca_crl.file_path()),
|
||||
}));
|
||||
wait_for_port(port(0)).await;
|
||||
|
||||
// Start client relay
|
||||
task::spawn(crate::tcp_relay_client::run_app(ClientConfig {
|
||||
relay_url: format!("https://localhost:{}", port(0)),
|
||||
listen_address: LOCALHOST_IP.to_string(),
|
||||
root_certificate: Some(pki.root_ca_crt.file_path()),
|
||||
tls_cert: Some(pki.valid_client_crt.file_path()),
|
||||
tls_key: Some(pki.valid_client_key.file_path()),
|
||||
..Default::default()
|
||||
}));
|
||||
wait_for_port(port(2)).await;
|
||||
|
||||
dummy_tcp_client_square_root_requests(port(2), 10).await;
|
||||
})
|
||||
.await;
|
||||
}
|
59
src/test/valid_with_token_auth.rs
Normal file
59
src/test/valid_with_token_auth.rs
Normal file
@ -0,0 +1,59 @@
|
||||
use tokio::task;
|
||||
|
||||
use crate::tcp_relay_client::client_config::ClientConfig;
|
||||
use crate::tcp_relay_server::server_config::ServerConfig;
|
||||
use crate::test::dummy_tcp_sockets::{
|
||||
dummy_tcp_client_square_root_requests, wait_for_port, DummyTCPServer,
|
||||
};
|
||||
use crate::test::{get_port_number, PortsAllocation, LOCALHOST_IP};
|
||||
|
||||
const VALID_TOKEN: &str = "AvalidTOKEN";
|
||||
|
||||
fn port(index: u16) -> u16 {
|
||||
get_port_number(PortsAllocation::ValidWithTokenAuth, index)
|
||||
}
|
||||
|
||||
#[tokio::test()]
|
||||
async fn valid_with_token_auth() {
|
||||
let _ = env_logger::builder().is_test(true).try_init();
|
||||
|
||||
// Start internal service
|
||||
let local_server = DummyTCPServer::start(port(1)).await;
|
||||
tokio::spawn(async move {
|
||||
local_server.loop_conn_square_operations().await;
|
||||
});
|
||||
|
||||
let local_set = task::LocalSet::new();
|
||||
local_set
|
||||
.run_until(async move {
|
||||
wait_for_port(port(1)).await;
|
||||
|
||||
// Start server relay
|
||||
task::spawn_local(crate::tcp_relay_server::run_app(ServerConfig {
|
||||
tokens: vec![VALID_TOKEN.to_string()],
|
||||
tokens_file: None,
|
||||
ports: vec![port(1)],
|
||||
upstream_server: "127.0.0.1".to_string(),
|
||||
listen_address: format!("127.0.0.1:{}", port(0)),
|
||||
increment_ports: 1,
|
||||
tls_cert: None,
|
||||
tls_key: None,
|
||||
tls_client_auth_root_cert: None,
|
||||
tls_revocation_list: None,
|
||||
}));
|
||||
wait_for_port(port(0)).await;
|
||||
|
||||
// Start client relay
|
||||
task::spawn(crate::tcp_relay_client::run_app(ClientConfig {
|
||||
token: Some(VALID_TOKEN.to_string()),
|
||||
relay_url: format!("http://{}:{}", LOCALHOST_IP, port(0)),
|
||||
listen_address: LOCALHOST_IP.to_string(),
|
||||
root_certificate: None,
|
||||
..Default::default()
|
||||
}));
|
||||
wait_for_port(port(2)).await;
|
||||
|
||||
dummy_tcp_client_square_root_requests(port(2), 10).await;
|
||||
})
|
||||
.await;
|
||||
}
|
62
src/test/valid_with_token_auth_and_server_tls.rs
Normal file
62
src/test/valid_with_token_auth_and_server_tls.rs
Normal file
@ -0,0 +1,62 @@
|
||||
use tokio::task;
|
||||
|
||||
use crate::tcp_relay_client::client_config::ClientConfig;
|
||||
use crate::tcp_relay_server::server_config::ServerConfig;
|
||||
use crate::test::dummy_tcp_sockets::{
|
||||
dummy_tcp_client_square_root_requests, wait_for_port, DummyTCPServer,
|
||||
};
|
||||
use crate::test::pki::Pki;
|
||||
use crate::test::{get_port_number, PortsAllocation, LOCALHOST_IP};
|
||||
|
||||
const VALID_TOKEN: &str = "AvalidTOKEN";
|
||||
|
||||
fn port(index: u16) -> u16 {
|
||||
get_port_number(PortsAllocation::ValidWithTokenAuthAndServerTLS, index)
|
||||
}
|
||||
|
||||
#[tokio::test()]
|
||||
async fn test() {
|
||||
let _ = env_logger::builder().is_test(true).try_init();
|
||||
|
||||
// Start internal service
|
||||
let local_server = DummyTCPServer::start(port(1)).await;
|
||||
tokio::spawn(async move {
|
||||
local_server.loop_conn_square_operations().await;
|
||||
});
|
||||
|
||||
let pki = Pki::load();
|
||||
|
||||
let local_set = task::LocalSet::new();
|
||||
local_set
|
||||
.run_until(async move {
|
||||
wait_for_port(port(1)).await;
|
||||
|
||||
// Start server relay
|
||||
task::spawn_local(crate::tcp_relay_server::run_app(ServerConfig {
|
||||
tokens: vec![VALID_TOKEN.to_string()],
|
||||
tokens_file: None,
|
||||
ports: vec![port(1)],
|
||||
upstream_server: "127.0.0.1".to_string(),
|
||||
listen_address: format!("127.0.0.1:{}", port(0)),
|
||||
increment_ports: 1,
|
||||
tls_cert: Some(pki.localhost_crt.file_path()),
|
||||
tls_key: Some(pki.localhost_key.file_path()),
|
||||
tls_client_auth_root_cert: None,
|
||||
tls_revocation_list: None,
|
||||
}));
|
||||
wait_for_port(port(0)).await;
|
||||
|
||||
// Start client relay
|
||||
task::spawn(crate::tcp_relay_client::run_app(ClientConfig {
|
||||
token: Some(VALID_TOKEN.to_string()),
|
||||
relay_url: format!("https://localhost:{}", port(0)),
|
||||
listen_address: LOCALHOST_IP.to_string(),
|
||||
root_certificate: Some(pki.root_ca_crt.file_path()),
|
||||
..Default::default()
|
||||
}));
|
||||
wait_for_port(port(2)).await;
|
||||
|
||||
dummy_tcp_client_square_root_requests(port(2), 10).await;
|
||||
})
|
||||
.await;
|
||||
}
|
67
src/test/valid_with_token_auth_multiple_ports.rs
Normal file
67
src/test/valid_with_token_auth_multiple_ports.rs
Normal file
@ -0,0 +1,67 @@
|
||||
use tokio::task;
|
||||
|
||||
use crate::tcp_relay_client::client_config::ClientConfig;
|
||||
use crate::tcp_relay_server::server_config::ServerConfig;
|
||||
use crate::test::dummy_tcp_sockets::{
|
||||
dummy_tcp_client_additions_requests, dummy_tcp_client_square_root_requests, wait_for_port,
|
||||
DummyTCPServer,
|
||||
};
|
||||
use crate::test::{get_port_number, PortsAllocation, LOCALHOST_IP};
|
||||
|
||||
const VALID_TOKEN: &str = "AvalidTOKEN";
|
||||
const NUM_INC: i32 = 5;
|
||||
|
||||
fn port(index: u16) -> u16 {
|
||||
get_port_number(PortsAllocation::ValidWithTokenAuthMultiplePorts, index)
|
||||
}
|
||||
|
||||
#[tokio::test()]
|
||||
async fn test() {
|
||||
let _ = env_logger::builder().is_test(true).try_init();
|
||||
|
||||
// Start internal services
|
||||
let local_server_1 = DummyTCPServer::start(port(1)).await;
|
||||
tokio::spawn(async move {
|
||||
local_server_1.loop_conn_square_operations().await;
|
||||
});
|
||||
|
||||
let local_server_2 = DummyTCPServer::start(port(3)).await;
|
||||
tokio::spawn(async move {
|
||||
local_server_2.loop_next_conn_add_operations(NUM_INC).await;
|
||||
});
|
||||
|
||||
let local_set = task::LocalSet::new();
|
||||
local_set
|
||||
.run_until(async move {
|
||||
wait_for_port(port(1)).await;
|
||||
|
||||
// Start server relay
|
||||
task::spawn_local(crate::tcp_relay_server::run_app(ServerConfig {
|
||||
tokens: vec![VALID_TOKEN.to_string()],
|
||||
tokens_file: None,
|
||||
ports: vec![port(1), port(3)],
|
||||
upstream_server: "127.0.0.1".to_string(),
|
||||
listen_address: format!("127.0.0.1:{}", port(0)),
|
||||
increment_ports: 1,
|
||||
tls_cert: None,
|
||||
tls_key: None,
|
||||
tls_client_auth_root_cert: None,
|
||||
tls_revocation_list: None,
|
||||
}));
|
||||
wait_for_port(port(0)).await;
|
||||
|
||||
// Start client relay
|
||||
task::spawn(crate::tcp_relay_client::run_app(ClientConfig {
|
||||
token: Some(VALID_TOKEN.to_string()),
|
||||
relay_url: format!("http://{}:{}", LOCALHOST_IP, port(0)),
|
||||
listen_address: LOCALHOST_IP.to_string(),
|
||||
root_certificate: None,
|
||||
..Default::default()
|
||||
}));
|
||||
wait_for_port(port(2)).await;
|
||||
|
||||
dummy_tcp_client_square_root_requests(port(2), 10).await;
|
||||
dummy_tcp_client_additions_requests(port(4), NUM_INC, 10).await;
|
||||
})
|
||||
.await;
|
||||
}
|
62
src/test/valid_with_token_file.rs
Normal file
62
src/test/valid_with_token_file.rs
Normal file
@ -0,0 +1,62 @@
|
||||
use tokio::task;
|
||||
|
||||
use crate::tcp_relay_client::client_config::ClientConfig;
|
||||
use crate::tcp_relay_server::server_config::ServerConfig;
|
||||
use crate::test::dummy_tcp_sockets::{
|
||||
dummy_tcp_client_square_root_requests, wait_for_port, DummyTCPServer,
|
||||
};
|
||||
use crate::test::{get_port_number, PortsAllocation, LOCALHOST_IP};
|
||||
|
||||
const VALID_TOKEN: &str = "AvalidTOKEN";
|
||||
|
||||
fn port(index: u16) -> u16 {
|
||||
get_port_number(PortsAllocation::ValidWithMultipleTokenAuth, index)
|
||||
}
|
||||
|
||||
#[tokio::test()]
|
||||
async fn valid_with_token_file() {
|
||||
let _ = env_logger::builder().is_test(true).try_init();
|
||||
|
||||
// Start internal service
|
||||
let local_server = DummyTCPServer::start(port(1)).await;
|
||||
tokio::spawn(async move {
|
||||
local_server.loop_conn_square_operations().await;
|
||||
});
|
||||
|
||||
let local_set = task::LocalSet::new();
|
||||
local_set
|
||||
.run_until(async move {
|
||||
wait_for_port(port(1)).await;
|
||||
|
||||
let token_file = mktemp::Temp::new_file().unwrap();
|
||||
std::fs::write(&token_file, format!("tok1\ntok2\n{}\ntok4", VALID_TOKEN)).unwrap();
|
||||
|
||||
// Start server relay
|
||||
task::spawn_local(crate::tcp_relay_server::run_app(ServerConfig {
|
||||
tokens: vec![],
|
||||
tokens_file: Some(token_file.to_str().unwrap().to_string()),
|
||||
ports: vec![port(1)],
|
||||
upstream_server: "127.0.0.1".to_string(),
|
||||
listen_address: format!("127.0.0.1:{}", port(0)),
|
||||
increment_ports: 1,
|
||||
tls_cert: None,
|
||||
tls_key: None,
|
||||
tls_client_auth_root_cert: None,
|
||||
tls_revocation_list: None,
|
||||
}));
|
||||
wait_for_port(port(0)).await;
|
||||
|
||||
// Start client relay
|
||||
task::spawn(crate::tcp_relay_client::run_app(ClientConfig {
|
||||
token: Some(VALID_TOKEN.to_string()),
|
||||
relay_url: format!("http://{}:{}", LOCALHOST_IP, port(0)),
|
||||
listen_address: LOCALHOST_IP.to_string(),
|
||||
root_certificate: None,
|
||||
..Default::default()
|
||||
}));
|
||||
wait_for_port(port(2)).await;
|
||||
|
||||
dummy_tcp_client_square_root_requests(port(2), 10).await;
|
||||
})
|
||||
.await;
|
||||
}
|
54
src/test/with_token_auth_and_invalid_server_tls_bad_ca.rs
Normal file
54
src/test/with_token_auth_and_invalid_server_tls_bad_ca.rs
Normal file
@ -0,0 +1,54 @@
|
||||
use tokio::task;
|
||||
|
||||
use crate::tcp_relay_client::client_config::ClientConfig;
|
||||
use crate::tcp_relay_server::server_config::ServerConfig;
|
||||
use crate::test::dummy_tcp_sockets::wait_for_port;
|
||||
use crate::test::pki::Pki;
|
||||
use crate::test::{get_port_number, PortsAllocation, LOCALHOST_IP};
|
||||
|
||||
const VALID_TOKEN: &str = "AvalidTOKEN";
|
||||
|
||||
fn port(index: u16) -> u16 {
|
||||
get_port_number(
|
||||
PortsAllocation::WithTokenAuthAndInvalidServerTLSBadCA,
|
||||
index,
|
||||
)
|
||||
}
|
||||
|
||||
#[tokio::test()]
|
||||
async fn test() {
|
||||
let _ = env_logger::builder().is_test(true).try_init();
|
||||
|
||||
let pki = Pki::load();
|
||||
|
||||
let local_set = task::LocalSet::new();
|
||||
local_set
|
||||
.run_until(async move {
|
||||
// Start server relay
|
||||
task::spawn_local(crate::tcp_relay_server::run_app(ServerConfig {
|
||||
tokens: vec![VALID_TOKEN.to_string()],
|
||||
tokens_file: None,
|
||||
ports: vec![port(1)],
|
||||
upstream_server: "127.0.0.1".to_string(),
|
||||
listen_address: format!("127.0.0.1:{}", port(0)),
|
||||
increment_ports: 1,
|
||||
tls_cert: Some(pki.localhost_crt.file_path()),
|
||||
tls_key: Some(pki.localhost_key.file_path()),
|
||||
tls_client_auth_root_cert: None,
|
||||
tls_revocation_list: None,
|
||||
}));
|
||||
wait_for_port(port(0)).await;
|
||||
|
||||
// Start client relay
|
||||
crate::tcp_relay_client::run_app(ClientConfig {
|
||||
token: Some(VALID_TOKEN.to_string()),
|
||||
relay_url: format!("https://localhost:{}", port(0)),
|
||||
listen_address: LOCALHOST_IP.to_string(),
|
||||
root_certificate: Some(pki.other_ca_crt.file_path()),
|
||||
..Default::default()
|
||||
})
|
||||
.await
|
||||
.unwrap_err();
|
||||
})
|
||||
.await;
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
use tokio::task;
|
||||
|
||||
use crate::tcp_relay_client::client_config::ClientConfig;
|
||||
use crate::tcp_relay_server::server_config::ServerConfig;
|
||||
use crate::test::dummy_tcp_sockets::wait_for_port;
|
||||
use crate::test::pki::Pki;
|
||||
use crate::test::{get_port_number, PortsAllocation, LOCALHOST_IP};
|
||||
|
||||
const VALID_TOKEN: &str = "AvalidTOKEN";
|
||||
|
||||
fn port(index: u16) -> u16 {
|
||||
get_port_number(
|
||||
PortsAllocation::WithTokenAuthAndInvalidServerTLSExpiredAndBadCN,
|
||||
index,
|
||||
)
|
||||
}
|
||||
|
||||
#[tokio::test()]
|
||||
async fn test() {
|
||||
let _ = env_logger::builder().is_test(true).try_init();
|
||||
|
||||
let pki = Pki::load();
|
||||
|
||||
let local_set = task::LocalSet::new();
|
||||
local_set
|
||||
.run_until(async move {
|
||||
// Start server relay
|
||||
task::spawn_local(crate::tcp_relay_server::run_app(ServerConfig {
|
||||
tokens: vec![VALID_TOKEN.to_string()],
|
||||
tokens_file: None,
|
||||
ports: vec![port(1)],
|
||||
upstream_server: "127.0.0.1".to_string(),
|
||||
listen_address: format!("127.0.0.1:{}", port(0)),
|
||||
increment_ports: 1,
|
||||
tls_cert: Some(pki.expired_client_crt.file_path()),
|
||||
tls_key: Some(pki.expired_client_key.file_path()),
|
||||
tls_client_auth_root_cert: None,
|
||||
tls_revocation_list: None,
|
||||
}));
|
||||
wait_for_port(port(0)).await;
|
||||
|
||||
// Start client relay
|
||||
crate::tcp_relay_client::run_app(ClientConfig {
|
||||
token: Some(VALID_TOKEN.to_string()),
|
||||
relay_url: format!("https://localhost:{}", port(0)),
|
||||
listen_address: LOCALHOST_IP.to_string(),
|
||||
root_certificate: Some(pki.root_ca_crt.file_path()),
|
||||
..Default::default()
|
||||
})
|
||||
.await
|
||||
.unwrap_err();
|
||||
})
|
||||
.await;
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
[package]
|
||||
name = "tcp_relay_client"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[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"] }
|
||||
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,2 +0,0 @@
|
||||
pub mod client_config;
|
||||
pub mod relay_client;
|
@ -1,21 +0,0 @@
|
||||
[package]
|
||||
name = "tcp_relay_server"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[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,3 +0,0 @@
|
||||
pub mod relay_ws;
|
||||
pub mod server_config;
|
||||
pub mod tls_cert_client_verifier;
|
Loading…
Reference in New Issue
Block a user