Allows to load EC and RSA encoded tls private key

This commit is contained in:
Σrebe - Romain GERARD 2023-12-04 18:21:55 +01:00
parent fffec24c99
commit b64b0bb70b
No known key found for this signature in database
GPG key ID: 7A42B4B97E0332F4
9 changed files with 214 additions and 124 deletions

173
Cargo.lock generated
View file

@ -101,7 +101,7 @@ checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.38", "syn 2.0.39",
] ]
[[package]] [[package]]
@ -181,6 +181,12 @@ dependencies = [
"serde_with", "serde_with",
] ]
[[package]]
name = "bumpalo"
version = "3.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec"
[[package]] [[package]]
name = "bytes" name = "bytes"
version = "1.5.0" version = "1.5.0"
@ -233,7 +239,7 @@ dependencies = [
"heck", "heck",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.38", "syn 2.0.39",
] ]
[[package]] [[package]]
@ -250,9 +256,9 @@ checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
[[package]] [[package]]
name = "core-foundation" name = "core-foundation"
version = "0.9.3" version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f"
dependencies = [ dependencies = [
"core-foundation-sys", "core-foundation-sys",
"libc", "libc",
@ -260,9 +266,9 @@ dependencies = [
[[package]] [[package]]
name = "core-foundation-sys" name = "core-foundation-sys"
version = "0.8.4" version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f"
[[package]] [[package]]
name = "cpufeatures" name = "cpufeatures"
@ -320,9 +326,9 @@ dependencies = [
[[package]] [[package]]
name = "deranged" name = "deranged"
version = "0.3.9" version = "0.3.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f32d04922c60427da6f9fef14d042d9edddef64cb9d4ce0d64d0685fbeb1fd3" checksum = "8eb30d70a07a3b04884d2677f06bec33509dc67ca60d92949e5535352d3191dc"
dependencies = [ dependencies = [
"powerfmt", "powerfmt",
] ]
@ -340,9 +346,9 @@ dependencies = [
[[package]] [[package]]
name = "fast-socks5" name = "fast-socks5"
version = "0.9.1" version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa6a4a9ab1f87e2d8e9345ce944de7c45d065ee89f5942512f32698e48a8429a" checksum = "d449e348301d5fb9b0e5781510d8235ffe3bbac3286bd305462736a9e7043039"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"async-trait", "async-trait",
@ -439,7 +445,7 @@ checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.38", "syn 2.0.39",
] ]
[[package]] [[package]]
@ -484,20 +490,22 @@ dependencies = [
[[package]] [[package]]
name = "getrandom" name = "getrandom"
version = "0.2.10" version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"js-sys",
"libc", "libc",
"wasi", "wasi",
"wasm-bindgen",
] ]
[[package]] [[package]]
name = "gimli" name = "gimli"
version = "0.28.0" version = "0.28.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253"
[[package]] [[package]]
name = "heck" name = "heck"
@ -528,9 +536,9 @@ dependencies = [
[[package]] [[package]]
name = "http" name = "http"
version = "0.2.9" version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb"
dependencies = [ dependencies = [
"bytes", "bytes",
"fnv", "fnv",
@ -606,12 +614,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38"
[[package]] [[package]]
name = "jsonwebtoken" name = "js-sys"
version = "9.1.0" version = "0.3.66"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "155c4d7e39ad04c172c5e3a99c434ea3b4a7ba7960b38ecd562b270b097cce09" checksum = "cee9c64da59eae3b50095c18d3e74f8b73c0b86d2792824ff01bbce68ba229ca"
dependencies = [
"wasm-bindgen",
]
[[package]]
name = "jsonwebtoken"
version = "9.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c7ea04a7c5c055c175f189b6dc6ba036fd62306b58c66c9f6389036c503a3f4"
dependencies = [ dependencies = [
"base64", "base64",
"js-sys",
"ring", "ring",
"serde", "serde",
"serde_json", "serde_json",
@ -803,7 +821,7 @@ checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.38", "syn 2.0.39",
] ]
[[package]] [[package]]
@ -832,9 +850,9 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.69" version = "1.0.70"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b"
dependencies = [ dependencies = [
"unicode-ident", "unicode-ident",
] ]
@ -933,9 +951,9 @@ checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
[[package]] [[package]]
name = "ring" name = "ring"
version = "0.17.5" version = "0.17.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fb0205304757e5d899b9c2e448b867ffd03ae7f988002e47cd24954391394d0b" checksum = "684d5e6e18f669ccebf64a92236bb7db9a34f07be010e3627368182027180866"
dependencies = [ dependencies = [
"cc", "cc",
"getrandom", "getrandom",
@ -953,9 +971,9 @@ checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
[[package]] [[package]]
name = "rustls" name = "rustls"
version = "0.21.8" version = "0.21.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "446e14c5cda4f3f30fe71863c34ec70f5ac79d6087097ad0bb433e1be5edf04c" checksum = "629648aced5775d558af50b2b4c7b02983a04b312126d45eeead26e7caa498b9"
dependencies = [ dependencies = [
"log", "log",
"ring", "ring",
@ -965,25 +983,33 @@ dependencies = [
[[package]] [[package]]
name = "rustls-native-certs" name = "rustls-native-certs"
version = "0.6.3" version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" checksum = "8f1fb85efa936c42c6d5fc28d2629bb51e4b2f4b8a5211e297d599cc5a093792"
dependencies = [ dependencies = [
"openssl-probe", "openssl-probe",
"rustls-pemfile", "rustls-pemfile",
"rustls-pki-types",
"schannel", "schannel",
"security-framework", "security-framework",
] ]
[[package]] [[package]]
name = "rustls-pemfile" name = "rustls-pemfile"
version = "1.0.4" version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" checksum = "35e4980fa29e4c4b212ffb3db068a564cbf560e51d3944b7c88bd8bf5bec64f4"
dependencies = [ dependencies = [
"base64", "base64",
"rustls-pki-types",
] ]
[[package]]
name = "rustls-pki-types"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb0a1f9b9efec70d32e6d6aa3e58ebd88c3754ec98dfe9145c63cf54cc829b83"
[[package]] [[package]]
name = "rustls-webpki" name = "rustls-webpki"
version = "0.101.7" version = "0.101.7"
@ -1065,14 +1091,14 @@ checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.38", "syn 2.0.39",
] ]
[[package]] [[package]]
name = "serde_json" name = "serde_json"
version = "1.0.107" version = "1.0.108"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65" checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b"
dependencies = [ dependencies = [
"itoa", "itoa",
"ryu", "ryu",
@ -1158,9 +1184,9 @@ dependencies = [
[[package]] [[package]]
name = "smallvec" name = "smallvec"
version = "1.11.1" version = "1.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970"
[[package]] [[package]]
name = "socket2" name = "socket2"
@ -1213,9 +1239,9 @@ dependencies = [
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.38" version = "2.0.39"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b" checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -1256,7 +1282,7 @@ checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.38", "syn 2.0.39",
] ]
[[package]] [[package]]
@ -1352,7 +1378,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.38", "syn 2.0.39",
] ]
[[package]] [[package]]
@ -1402,7 +1428,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.38", "syn 2.0.39",
] ]
[[package]] [[package]]
@ -1551,6 +1577,60 @@ version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasm-bindgen"
version = "0.2.89"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e"
dependencies = [
"cfg-if",
"wasm-bindgen-macro",
]
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.89"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826"
dependencies = [
"bumpalo",
"log",
"once_cell",
"proc-macro2",
"quote",
"syn 2.0.39",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.89"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
]
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.89"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.39",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.89"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f"
[[package]] [[package]]
name = "winapi" name = "winapi"
version = "0.3.9" version = "0.3.9"
@ -1655,7 +1735,6 @@ dependencies = [
"futures-util", "futures-util",
"hyper", "hyper",
"jsonwebtoken", "jsonwebtoken",
"libc",
"log", "log",
"nix", "nix",
"once_cell", "once_cell",
@ -1680,20 +1759,20 @@ dependencies = [
[[package]] [[package]]
name = "zerocopy" name = "zerocopy"
version = "0.7.20" version = "0.7.28"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd66a62464e3ffd4e37bd09950c2b9dd6c4f8767380fabba0d523f9a775bc85a" checksum = "7d6f15f7ade05d2a4935e34a457b936c23dc70a05cc1d97133dc99e7a3fe0f0e"
dependencies = [ dependencies = [
"zerocopy-derive", "zerocopy-derive",
] ]
[[package]] [[package]]
name = "zerocopy-derive" name = "zerocopy-derive"
version = "0.7.20" version = "0.7.28"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "255c4596d41e6916ced49cfafea18727b24d67878fa180ddfd69b9df34fd1726" checksum = "dbbad221e3f78500350ecbd7dfa4e63ef945c05f4c61cb7f4d3f84cd0bba649b"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.38", "syn 2.0.39",
] ]

View file

@ -3,54 +3,50 @@ name = "wstunnel"
version = "8.1.1" version = "8.1.1"
edition = "2021" edition = "2021"
repository = "https://github.com/erebe/wstunnel.git" repository = "https://github.com/erebe/wstunnel.git"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
clap = { version = "4.4.10", features = ["derive"]} ahash = { version = "0.8.6", features = [] }
url = "2.5.0"
anyhow = "1.0.75" anyhow = "1.0.75"
async-trait = "0.1.74"
base64 = "0.21.5"
bb8 = { version = "0.8", features = [] }
bytes = { version = "1.5.0", features = [] }
clap = { version = "4.4.10", features = ["derive"] }
fast-socks5 = { version = "0.9.1", features = [] }
fastwebsockets = { git = "https://github.com/denoland/fastwebsockets", branch = "main", features = ["upgrade", "simd", "unstable-split"] }
futures-util = { version = "0.3.29" }
hyper = { version = "0.14.27", features = ["client", "runtime"] } hyper = { version = "0.14.27", features = ["client", "runtime"] }
fastwebsockets = { git = "https://github.com/denoland/fastwebsockets", branch = "main", features = ["upgrade", "simd", "unstable-split"]} jsonwebtoken = { version = "9.1.0", default-features = false }
libc = { version = "0.2.150", features = []} log = "0.4.20"
once_cell = { version = "1.18.0", features = [] }
ahash = { version = "0.8.6", features = []}
pin-project = "1"
scopeguard = "1.2.0"
uuid = { version = "1.6.1", features = ["v7", "serde"] }
jsonwebtoken = { version = "9.1.0", default-features = false }
rustls-pemfile = { version = "1.0.4", features = [] }
bytes = { version = "1.5.0", features = [] }
parking_lot = "0.12.1"
urlencoding = "2.1.3"
nix = { version = "0.27.1", features = ["socket", "net", "uio"] } nix = { version = "0.27.1", features = ["socket", "net", "uio"] }
once_cell = { version = "1.18.0", features = [] }
parking_lot = "0.12.1"
pin-project = "1"
rustls-native-certs = { version = "0.6.3", features = [] } rustls-native-certs = { version = "0.7.0", features = [] }
rustls-pemfile = { version = "2.0.0", features = [] }
scopeguard = "1.2.0"
serde = { version = "1.0.193", features = ["derive"] }
socket2 = { version = "0.5.5", features = [] }
tokio = { version = "1.34.0", features = ["full"] } tokio = { version = "1.34.0", features = ["full"] }
tokio-rustls = { version = "0.24.1", features = ["tls12", "dangerous_configuration", "early-data"] } tokio-rustls = { version = "0.24.1", features = ["tls12", "dangerous_configuration", "early-data"] }
tokio-stream = { version = "0.1.14", features = ["net"] } tokio-stream = { version = "0.1.14", features = ["net"] }
fast-socks5 = { version = "0.9.1", features = [] }
futures-util = { version = "0.3.29" }
tracing = { version = "0.1.40", features = ["log"] } tracing = { version = "0.1.40", features = ["log"] }
tracing-subscriber = { version = "0.3.18", features = ["env-filter", "fmt", "local-time"] } tracing-subscriber = { version = "0.3.18", features = ["env-filter", "fmt", "local-time"] }
base64 = "0.21.5" url = "2.5.0"
serde = { version = "1.0.193", features = ["derive"] } urlencoding = "2.1.3"
log = "0.4.20" uuid = { version = "1.6.1", features = ["v7", "serde"] }
bb8 = { version = "0.8", features = [] }
async-trait = "0.1.74"
socket2 = { version = "0.5.5", features = [] }
[target.'cfg(target_family = "unix")'.dependencies] [target.'cfg(target_family = "unix")'.dependencies]
tokio-fd = "0.3.0" tokio-fd = "0.3.0"
[dev-dependencies] [dev-dependencies]
testcontainers = "0.15.0" testcontainers = "0.15.0"
[profile.release] [profile.release]
lto = "fat" lto = "fat"
panic = "abort" panic = "abort"

View file

@ -1,15 +1,26 @@
use log::info;
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use tokio_rustls::rustls::{Certificate, PrivateKey}; use tokio_rustls::rustls::{Certificate, PrivateKey};
pub static TLS_PRIVATE_KEY: Lazy<PrivateKey> = Lazy::new(|| { pub static TLS_PRIVATE_KEY: Lazy<PrivateKey> = Lazy::new(|| {
info!("Loading embedded tls private key");
let key = include_bytes!("../certs/key.pem"); let key = include_bytes!("../certs/key.pem");
let mut keys = let key = rustls_pemfile::private_key(&mut key.as_slice())
rustls_pemfile::pkcs8_private_keys(&mut key.as_slice()).expect("failed to load embedded tls private key"); .expect("failed to load embedded tls private key")
PrivateKey(keys.remove(0)) .expect("failed to load embedded tls private key");
PrivateKey(key.secret_der().to_vec())
}); });
pub static TLS_CERTIFICATE: Lazy<Vec<Certificate>> = Lazy::new(|| { pub static TLS_CERTIFICATE: Lazy<Vec<Certificate>> = Lazy::new(|| {
let cert = include_bytes!("../certs/cert.pem"); info!("Loading embedded tls certificate");
let certs = rustls_pemfile::certs(&mut cert.as_slice()).expect("failed to load embedded tls certificate");
certs.into_iter().map(Certificate).collect() let cert = include_bytes!("../certs/cert.pem");
let certs = rustls_pemfile::certs(&mut cert.as_slice())
.next()
.expect("failed to load embedded tls certificate");
certs
.into_iter()
.map(|cert| Certificate(cert.as_ref().to_vec()))
.collect()
}); });

View file

@ -77,7 +77,7 @@ struct Client {
/// (linux only) Mark network packet with SO_MARK sockoption with the specified value. /// (linux only) Mark network packet with SO_MARK sockoption with the specified value.
/// You need to use {root, sudo, capabilities} to run wstunnel when using this option /// You need to use {root, sudo, capabilities} to run wstunnel when using this option
#[arg(long, value_name = "INT", verbatim_doc_comment)] #[arg(long, value_name = "INT", verbatim_doc_comment)]
socket_so_mark: Option<i32>, socket_so_mark: Option<u32>,
/// Client will maintain a pool of open connection to the server, in order to speed up the connection process. /// Client will maintain a pool of open connection to the server, in order to speed up the connection process.
/// This option set the maximum number of connection that will be kept open. /// This option set the maximum number of connection that will be kept open.
@ -141,7 +141,7 @@ struct Server {
/// (linux only) Mark network packet with SO_MARK sockoption with the specified value. /// (linux only) Mark network packet with SO_MARK sockoption with the specified value.
/// You need to use {root, sudo, capabilities} to run wstunnel when using this option /// You need to use {root, sudo, capabilities} to run wstunnel when using this option
#[arg(long, value_name = "INT", verbatim_doc_comment)] #[arg(long, value_name = "INT", verbatim_doc_comment)]
socket_so_mark: Option<i32>, socket_so_mark: Option<u32>,
/// Frequency at which the server will send websocket ping to client. /// Frequency at which the server will send websocket ping to client.
#[arg(long, value_name = "seconds", value_parser = parse_duration_sec, verbatim_doc_comment)] #[arg(long, value_name = "seconds", value_parser = parse_duration_sec, verbatim_doc_comment)]
@ -438,7 +438,7 @@ pub struct TlsServerConfig {
#[derive(Clone)] #[derive(Clone)]
pub struct WsServerConfig { pub struct WsServerConfig {
pub socket_so_mark: Option<i32>, pub socket_so_mark: Option<u32>,
pub bind: SocketAddr, pub bind: SocketAddr,
pub restrict_to: Option<Vec<String>>, pub restrict_to: Option<Vec<String>>,
pub restrict_http_upgrade_path_prefix: Option<Vec<String>>, pub restrict_http_upgrade_path_prefix: Option<Vec<String>>,
@ -465,7 +465,7 @@ impl Debug for WsServerConfig {
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct WsClientConfig { pub struct WsClientConfig {
pub remote_addr: (Host<String>, u16), pub remote_addr: (Host<String>, u16),
pub socket_so_mark: Option<i32>, pub socket_so_mark: Option<u32>,
pub tls: Option<TlsClientConfig>, pub tls: Option<TlsClientConfig>,
pub http_upgrade_path_prefix: String, pub http_upgrade_path_prefix: String,
pub http_upgrade_credentials: Option<HeaderValue>, pub http_upgrade_credentials: Option<HeaderValue>,

View file

@ -3,8 +3,8 @@ use tokio_fd::AsyncFd;
pub async fn run_server() -> Result<(AsyncFd, AsyncFd), anyhow::Error> { pub async fn run_server() -> Result<(AsyncFd, AsyncFd), anyhow::Error> {
eprintln!("Starting STDIO server"); eprintln!("Starting STDIO server");
let stdin = AsyncFd::try_from(libc::STDIN_FILENO)?; let stdin = AsyncFd::try_from(nix::libc::STDIN_FILENO)?;
let stdout = AsyncFd::try_from(libc::STDOUT_FILENO)?; let stdout = AsyncFd::try_from(nix::libc::STDOUT_FILENO)?;
Ok((stdin, stdout)) Ok((stdin, stdout))
} }

View file

@ -14,27 +14,22 @@ use tracing::debug;
use tracing::log::info; use tracing::log::info;
use url::{Host, Url}; use url::{Host, Url};
fn configure_socket(socket: &mut TcpSocket, so_mark: &Option<i32>) -> Result<(), anyhow::Error> { fn configure_socket(socket: &mut TcpSocket, so_mark: &Option<u32>) -> Result<(), anyhow::Error> {
socket socket
.set_nodelay(true) .set_nodelay(true)
.with_context(|| format!("cannot set no_delay on socket: {}", io::Error::last_os_error()))?; .with_context(|| format!("cannot set no_delay on socket: {}", io::Error::last_os_error()))?;
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
if let Some(so_mark) = so_mark { if let Some(so_mark) = so_mark {
use std::os::fd::AsRawFd; use std::os::fd::AsFd;
unsafe {
let optval: libc::c_int = *so_mark;
let ret = libc::setsockopt(
socket.as_raw_fd(),
libc::SOL_SOCKET,
libc::SO_MARK,
&optval as *const _ as *const libc::c_void,
std::mem::size_of_val(&optval) as libc::socklen_t,
);
if ret != 0 { let ret = nix::sys::socket::setsockopt(&socket.as_fd(), nix::sys::socket::sockopt::Mark, so_mark);
return Err(anyhow!("Cannot set SO_MARK on the connection {:?}", io::Error::last_os_error())); if let Err(err) = ret {
} return Err(anyhow!(
"Cannot set SO_MARK on the connection {:?} {:?}",
err,
io::Error::last_os_error()
));
} }
} }
@ -44,7 +39,7 @@ fn configure_socket(socket: &mut TcpSocket, so_mark: &Option<i32>) -> Result<(),
pub async fn connect( pub async fn connect(
host: &Host<String>, host: &Host<String>,
port: u16, port: u16,
so_mark: Option<i32>, so_mark: Option<u32>,
connect_timeout: Duration, connect_timeout: Duration,
) -> Result<TcpStream, anyhow::Error> { ) -> Result<TcpStream, anyhow::Error> {
info!("Opening TCP connection to {}:{}", host, port); info!("Opening TCP connection to {}:{}", host, port);
@ -103,7 +98,7 @@ pub async fn connect_with_http_proxy(
proxy: &Url, proxy: &Url,
host: &Host<String>, host: &Host<String>,
port: u16, port: u16,
so_mark: Option<i32>, so_mark: Option<u32>,
connect_timeout: Duration, connect_timeout: Duration,
) -> Result<TcpStream, anyhow::Error> { ) -> Result<TcpStream, anyhow::Error> {
let proxy_host = proxy.host().context("Cannot parse proxy host")?.to_owned(); let proxy_host = proxy.host().context("Cannot parse proxy host")?.to_owned();

View file

@ -2,6 +2,7 @@ use crate::{TlsClientConfig, TlsServerConfig, WsClientConfig};
use anyhow::{anyhow, Context}; use anyhow::{anyhow, Context};
use std::fs::File; use std::fs::File;
use log::warn;
use std::io::BufReader; use std::io::BufReader;
use std::path::Path; use std::path::Path;
use std::sync::Arc; use std::sync::Arc;
@ -30,23 +31,35 @@ impl ServerCertVerifier for NullVerifier {
} }
pub fn load_certificates_from_pem(path: &Path) -> anyhow::Result<Vec<Certificate>> { pub fn load_certificates_from_pem(path: &Path) -> anyhow::Result<Vec<Certificate>> {
info!("Loading tls certificate from {:?}", path);
let file = File::open(path)?; let file = File::open(path)?;
let mut reader = BufReader::new(file); let mut reader = BufReader::new(file);
let certs = rustls_pemfile::certs(&mut reader)?; let certs = rustls_pemfile::certs(&mut reader);
Ok(certs.into_iter().map(Certificate).collect()) Ok(certs
.into_iter()
.filter_map(|cert| match cert {
Ok(cert) => Some(Certificate(cert.to_vec())),
Err(err) => {
warn!("Error while parsing tls certificate: {:?}", err);
None
}
})
.collect())
} }
pub fn load_private_key_from_file(path: &Path) -> anyhow::Result<PrivateKey> { pub fn load_private_key_from_file(path: &Path) -> anyhow::Result<PrivateKey> {
info!("Loading tls private key from {:?}", path);
let file = File::open(path)?; let file = File::open(path)?;
let mut reader = BufReader::new(file); let mut reader = BufReader::new(file);
let mut keys = rustls_pemfile::pkcs8_private_keys(&mut reader)?;
match keys.len() { let Some(private_key) = rustls_pemfile::private_key(&mut reader)? else {
0 => Err(anyhow!("No PKCS8-encoded private key found in {path:?}")), return Err(anyhow!("No private key found in {path:?}"));
1 => Ok(PrivateKey(keys.remove(0))), };
_ => Err(anyhow!("More than one PKCS8-encoded private key found in {path:?}")),
} Ok(PrivateKey(private_key.secret_der().to_vec()))
} }
fn tls_connector(tls_cfg: &TlsClientConfig, alpn_protocols: Option<Vec<Vec<u8>>>) -> anyhow::Result<TlsConnector> { fn tls_connector(tls_cfg: &TlsClientConfig, alpn_protocols: Option<Vec<Vec<u8>>>) -> anyhow::Result<TlsConnector> {
@ -55,7 +68,7 @@ fn tls_connector(tls_cfg: &TlsClientConfig, alpn_protocols: Option<Vec<Vec<u8>>>
// Load system certificates and add them to the root store // Load system certificates and add them to the root store
let certs = rustls_native_certs::load_native_certs().with_context(|| "Cannot load system certificates")?; let certs = rustls_native_certs::load_native_certs().with_context(|| "Cannot load system certificates")?;
for cert in certs { for cert in certs {
root_store.add(&Certificate(cert.0))?; root_store.add(&Certificate(cert.as_ref().to_vec()))?;
} }
let mut config = ClientConfig::builder() let mut config = ClientConfig::builder()

View file

@ -181,23 +181,19 @@ where
ws.set_auto_apply_mask(client_config.websocket_mask_frame); ws.set_auto_apply_mask(client_config.websocket_mask_frame);
// Connect to endpoint // Connect to endpoint
let remote: (Host, u16) = response let remote = response
.headers() .headers()
.get(COOKIE) .get(COOKIE)
.and_then(|h| { .and_then(|h| h.to_str().ok())
h.to_str() .and_then(|h| base64::engine::general_purpose::STANDARD.decode(h).ok())
.ok() .and_then(|h| Url::parse(&String::from_utf8_lossy(&h)).ok())
.and_then(|s| base64::engine::general_purpose::STANDARD.decode(s).ok()) .and_then(|url| match (url.host(), url.port()) {
.and_then(|s| Url::parse(&String::from_utf8_lossy(&s)).ok()) (Some(h), Some(p)) => Some((h.to_owned(), p)),
.and_then(|url| match (url.host(), url.port()) { _ => None,
(Some(h), Some(p)) => Some((h.to_owned(), p)),
_ => None,
})
}) })
.unwrap_or(remote_ori.clone()); .unwrap_or(remote_ori.clone());
let stream = connect_to_dest(remote.clone()).instrument(span.clone()).await;
let stream = match stream { let stream = match connect_to_dest(remote.clone()).instrument(span.clone()).await {
Ok(s) => s, Ok(s) => s,
Err(err) => { Err(err) => {
error!("Cannot connect to {remote:?}: {err:?}"); error!("Cannot connect to {remote:?}: {err:?}");

View file

@ -377,7 +377,7 @@ pub fn mk_send_socket_tproxy(listener: &Arc<UdpSocket>) -> anyhow::Result<Arc<Ud
use std::net::IpAddr; use std::net::IpAddr;
use std::os::fd::AsRawFd; use std::os::fd::AsRawFd;
let mut cmsg_space = cmsg_space!(libc::sockaddr_in6); let mut cmsg_space = cmsg_space!(nix::libc::sockaddr_in6);
let mut buf = [0; 8]; let mut buf = [0; 8];
let mut io = [IoSliceMut::new(&mut buf)]; let mut io = [IoSliceMut::new(&mut buf)];
let msg: RecvMsg<SockaddrIn> = nix::sys::socket::recvmsg( let msg: RecvMsg<SockaddrIn> = nix::sys::socket::recvmsg(