Bump to hyper 1.x

This commit is contained in:
Σrebe - Romain GERARD 2023-12-15 09:47:06 +01:00
parent 9a16c38909
commit d1de41646f
No known key found for this signature in database
GPG key ID: 7A42B4B97E0332F4
5 changed files with 109 additions and 66 deletions

91
Cargo.lock generated
View file

@ -385,11 +385,14 @@ dependencies = [
[[package]] [[package]]
name = "fastwebsockets" name = "fastwebsockets"
version = "0.5.0" version = "0.6.0"
source = "git+https://github.com/denoland/fastwebsockets?rev=35a1930fdbcdfe9034bb531fcd1690ba9f7737ec#35a1930fdbcdfe9034bb531fcd1690ba9f7737ec" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f63dd7b57f9b33b1741fa631c9522eb35d43e96dcca4a6a91d5e4ca7c93acdc1"
dependencies = [ dependencies = [
"base64", "base64",
"http-body-util",
"hyper", "hyper",
"hyper-util",
"pin-project", "pin-project",
"rand", "rand",
"sha1", "sha1",
@ -561,9 +564,9 @@ dependencies = [
[[package]] [[package]]
name = "http" name = "http"
version = "0.2.11" version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" checksum = "b32afd38673a8016f7c9ae69e5af41a58f81b1d31689040f2f1959594ce194ea"
dependencies = [ dependencies = [
"bytes", "bytes",
"fnv", "fnv",
@ -572,12 +575,24 @@ dependencies = [
[[package]] [[package]]
name = "http-body" name = "http-body"
version = "0.4.6" version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643"
dependencies = [ dependencies = [
"bytes", "bytes",
"http", "http",
]
[[package]]
name = "http-body-util"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41cb79eb393015dadd30fc252023adb0b2400a0caee0fa2a077e6e21a551e840"
dependencies = [
"bytes",
"futures-util",
"http",
"http-body",
"pin-project-lite", "pin-project-lite",
] ]
@ -595,13 +610,12 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
[[package]] [[package]]
name = "hyper" name = "hyper"
version = "0.14.27" version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" checksum = "403f9214f3e703236b221f1a9cd88ec8b4adfa5296de01ab96216361f4692f56"
dependencies = [ dependencies = [
"bytes", "bytes",
"futures-channel", "futures-channel",
"futures-core",
"futures-util", "futures-util",
"http", "http",
"http-body", "http-body",
@ -609,11 +623,28 @@ dependencies = [
"httpdate", "httpdate",
"itoa", "itoa",
"pin-project-lite", "pin-project-lite",
"socket2 0.4.10",
"tokio", "tokio",
"want",
]
[[package]]
name = "hyper-util"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ca339002caeb0d159cc6e023dff48e199f081e42fa039895c7c6f38b37f2e9d"
dependencies = [
"bytes",
"futures-channel",
"futures-util",
"http",
"http-body",
"hyper",
"pin-project-lite",
"socket2",
"tokio",
"tower",
"tower-service", "tower-service",
"tracing", "tracing",
"want",
] ]
[[package]] [[package]]
@ -1235,16 +1266,6 @@ 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 = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970"
[[package]]
name = "socket2"
version = "0.4.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d"
dependencies = [
"libc",
"winapi",
]
[[package]] [[package]]
name = "socket2" name = "socket2"
version = "0.5.5" version = "0.5.5"
@ -1402,7 +1423,7 @@ dependencies = [
"parking_lot", "parking_lot",
"pin-project-lite", "pin-project-lite",
"signal-hook-registry", "signal-hook-registry",
"socket2 0.5.5", "socket2",
"tokio-macros", "tokio-macros",
"windows-sys 0.48.0", "windows-sys 0.48.0",
] ]
@ -1462,6 +1483,28 @@ dependencies = [
"tokio", "tokio",
] ]
[[package]]
name = "tower"
version = "0.4.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c"
dependencies = [
"futures-core",
"futures-util",
"pin-project",
"pin-project-lite",
"tokio",
"tower-layer",
"tower-service",
"tracing",
]
[[package]]
name = "tower-layer"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0"
[[package]] [[package]]
name = "tower-service" name = "tower-service"
version = "0.3.2" version = "0.3.2"
@ -1860,7 +1903,9 @@ dependencies = [
"fast-socks5", "fast-socks5",
"fastwebsockets", "fastwebsockets",
"futures-util", "futures-util",
"http-body-util",
"hyper", "hyper",
"hyper-util",
"jsonwebtoken", "jsonwebtoken",
"log", "log",
"nix", "nix",
@ -1871,7 +1916,7 @@ dependencies = [
"rustls-pemfile", "rustls-pemfile",
"scopeguard", "scopeguard",
"serde", "serde",
"socket2 0.5.5", "socket2",
"testcontainers", "testcontainers",
"tokio", "tokio",
"tokio-fd", "tokio-fd",

View file

@ -13,16 +13,18 @@ base64 = "0.21.5"
bb8 = { version = "0.8", features = [] } bb8 = { version = "0.8", features = [] }
bytes = { version = "1.5.0", features = [] } bytes = { version = "1.5.0", features = [] }
clap = { version = "4.4.10", features = ["derive"] } clap = { version = "4.4.11", features = ["derive"] }
fast-socks5 = { version = "0.9.1", features = [] } fast-socks5 = { version = "0.9.2", features = [] }
fastwebsockets = { git = "https://github.com/denoland/fastwebsockets", rev = '35a1930fdbcdfe9034bb531fcd1690ba9f7737ec', features = ["upgrade", "simd", "unstable-split"] } fastwebsockets = { version = "0.6.0", features = ["upgrade", "simd", "unstable-split"] }
futures-util = { version = "0.3.29" } futures-util = { version = "0.3.29" }
hyper = { version = "0.14.27", features = ["client", "runtime"] } hyper = { version = "1.0.1", features = ["client", "http1"] }
jsonwebtoken = { version = "9.1.0", default-features = false } hyper-util = { version = "0.1.0", features = ["tokio"] }
http-body-util = { version = "0.1.0" }
jsonwebtoken = { version = "9.2.0", default-features = false }
log = "0.4.20" log = "0.4.20"
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 = [] } once_cell = { version = "1.19.0", features = [] }
parking_lot = "0.12.1" parking_lot = "0.12.1"
pin-project = "1" pin-project = "1"
@ -31,7 +33,7 @@ rustls-pemfile = { version = "2.0.0", features = [] }
scopeguard = "1.2.0" scopeguard = "1.2.0"
serde = { version = "1.0.193", features = ["derive"] } serde = { version = "1.0.193", features = ["derive"] }
socket2 = { version = "0.5.5", features = [] } socket2 = { version = "0.5.5", features = [] }
tokio = { version = "1.34.0", features = ["full"] } tokio = { version = "1.35.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"] }

View file

@ -3,12 +3,16 @@ use crate::{LocalToRemote, WsClientConfig};
use anyhow::{anyhow, Context}; use anyhow::{anyhow, Context};
use base64::Engine; use base64::Engine;
use bytes::Bytes;
use fastwebsockets::WebSocket; use fastwebsockets::WebSocket;
use futures_util::pin_mut; use futures_util::pin_mut;
use http_body_util::Empty;
use hyper::body::Incoming;
use hyper::header::{AUTHORIZATION, COOKIE, SEC_WEBSOCKET_VERSION, UPGRADE}; use hyper::header::{AUTHORIZATION, COOKIE, SEC_WEBSOCKET_VERSION, UPGRADE};
use hyper::header::{CONNECTION, HOST, SEC_WEBSOCKET_KEY}; use hyper::header::{CONNECTION, HOST, SEC_WEBSOCKET_KEY};
use hyper::upgrade::Upgraded; use hyper::upgrade::Upgraded;
use hyper::{Body, Request, Response}; use hyper::{Request, Response};
use hyper_util::rt::{TokioExecutor, TokioIo};
use std::future::Future; use std::future::Future;
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
use std::sync::Arc; use std::sync::Arc;
@ -20,18 +24,6 @@ use tracing::{error, span, Instrument, Level, Span};
use url::{Host, Url}; use url::{Host, Url};
use uuid::Uuid; use uuid::Uuid;
struct SpawnExecutor;
impl<Fut> hyper::rt::Executor<Fut> for SpawnExecutor
where
Fut: Future + Send + 'static,
Fut::Output: Send + 'static,
{
fn execute(&self, fut: Fut) {
tokio::task::spawn(fut);
}
}
fn tunnel_to_jwt_token(request_id: Uuid, tunnel: &LocalToRemote) -> String { fn tunnel_to_jwt_token(request_id: Uuid, tunnel: &LocalToRemote) -> String {
let cfg = JwtTunnelConfig::new(request_id, tunnel); let cfg = JwtTunnelConfig::new(request_id, tunnel);
let (alg, secret) = JWT_KEY.deref(); let (alg, secret) = JWT_KEY.deref();
@ -42,7 +34,7 @@ pub async fn connect(
request_id: Uuid, request_id: Uuid,
client_cfg: &WsClientConfig, client_cfg: &WsClientConfig,
tunnel_cfg: &LocalToRemote, tunnel_cfg: &LocalToRemote,
) -> anyhow::Result<(WebSocket<Upgraded>, Response<Body>)> { ) -> anyhow::Result<(WebSocket<TokioIo<Upgraded>>, Response<Incoming>)> {
let mut pooled_cnx = match client_cfg.cnx_pool().get().await { let mut pooled_cnx = match client_cfg.cnx_pool().get().await {
Ok(tcp_stream) => tcp_stream, Ok(tcp_stream) => tcp_stream,
Err(err) => Err(anyhow!("failed to get a connection to the server from the pool: {err:?}"))?, Err(err) => Err(anyhow!("failed to get a connection to the server from the pool: {err:?}"))?,
@ -69,7 +61,7 @@ pub async fn connect(
req = req.header(AUTHORIZATION, auth); req = req.header(AUTHORIZATION, auth);
} }
let req = req.body(Body::empty()).with_context(|| { let req = req.body(Empty::<Bytes>::new()).with_context(|| {
format!( format!(
"failed to build HTTP request to contact the server {:?}", "failed to build HTTP request to contact the server {:?}",
client_cfg.remote_addr client_cfg.remote_addr
@ -77,7 +69,7 @@ pub async fn connect(
})?; })?;
debug!("with HTTP upgrade request {:?}", req); debug!("with HTTP upgrade request {:?}", req);
let transport = pooled_cnx.deref_mut().take().unwrap(); let transport = pooled_cnx.deref_mut().take().unwrap();
let (ws, response) = fastwebsockets::handshake::client(&SpawnExecutor, req, transport) let (ws, response) = fastwebsockets::handshake::client(&TokioExecutor::new(), req, transport)
.await .await
.with_context(|| format!("failed to do websocket handshake with the server {:?}", client_cfg.remote_addr))?; .with_context(|| format!("failed to do websocket handshake with the server {:?}", client_cfg.remote_addr))?;

View file

@ -2,6 +2,7 @@ use fastwebsockets::{Frame, OpCode, Payload, WebSocketError, WebSocketRead, WebS
use futures_util::{pin_mut, FutureExt}; use futures_util::{pin_mut, FutureExt};
use hyper::upgrade::Upgraded; use hyper::upgrade::Upgraded;
use hyper_util::rt::TokioIo;
use std::time::Duration; use std::time::Duration;
use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt, ReadHalf, WriteHalf}; use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt, ReadHalf, WriteHalf};
use tokio::select; use tokio::select;
@ -12,7 +13,7 @@ use tracing::{error, info, trace, warn};
pub(super) async fn propagate_read( pub(super) async fn propagate_read(
local_rx: impl AsyncRead, local_rx: impl AsyncRead,
mut ws_tx: WebSocketWrite<WriteHalf<Upgraded>>, mut ws_tx: WebSocketWrite<WriteHalf<TokioIo<Upgraded>>>,
mut close_tx: oneshot::Sender<()>, mut close_tx: oneshot::Sender<()>,
ping_frequency: Option<Duration>, ping_frequency: Option<Duration>,
) -> Result<(), WebSocketError> { ) -> Result<(), WebSocketError> {
@ -84,7 +85,7 @@ pub(super) async fn propagate_read(
pub(super) async fn propagate_write( pub(super) async fn propagate_write(
local_tx: impl AsyncWrite, local_tx: impl AsyncWrite,
mut ws_rx: WebSocketRead<ReadHalf<Upgraded>>, mut ws_rx: WebSocketRead<ReadHalf<TokioIo<Upgraded>>>,
mut close_rx: oneshot::Receiver<()>, mut close_rx: oneshot::Receiver<()>,
) -> Result<(), WebSocketError> { ) -> Result<(), WebSocketError> {
let _guard = scopeguard::guard((), |_| { let _guard = scopeguard::guard((), |_| {

View file

@ -12,11 +12,12 @@ use std::time::Duration;
use super::{JwtTunnelConfig, JWT_DECODE}; use super::{JwtTunnelConfig, JWT_DECODE};
use crate::{socks5, tcp, tls, udp, LocalProtocol, WsServerConfig}; use crate::{socks5, tcp, tls, udp, LocalProtocol, WsServerConfig};
use hyper::body::Incoming;
use hyper::header::COOKIE; use hyper::header::COOKIE;
use hyper::http::HeaderValue; use hyper::http::HeaderValue;
use hyper::server::conn::Http; use hyper::server::conn::http1;
use hyper::service::service_fn; use hyper::service::service_fn;
use hyper::{http, Body, Request, Response, StatusCode}; use hyper::{http, Request, Response, StatusCode};
use jsonwebtoken::TokenData; use jsonwebtoken::TokenData;
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use parking_lot::Mutex; use parking_lot::Mutex;
@ -188,8 +189,8 @@ where
async fn server_upgrade( async fn server_upgrade(
server_config: Arc<WsServerConfig>, server_config: Arc<WsServerConfig>,
mut req: Request<Body>, mut req: Request<Incoming>,
) -> Result<Response<Body>, anyhow::Error> { ) -> Result<Response<String>, anyhow::Error> {
if let Some(x) = req.headers().get("X-Forwarded-For") { if let Some(x) = req.headers().get("X-Forwarded-For") {
info!("Request X-Forwarded-For: {:?}", x); info!("Request X-Forwarded-For: {:?}", x);
Span::current().record("forwarded_for", x.to_str().unwrap_or_default()); Span::current().record("forwarded_for", x.to_str().unwrap_or_default());
@ -199,8 +200,8 @@ async fn server_upgrade(
warn!("Rejecting connection with bad upgrade request: {}", req.uri()); warn!("Rejecting connection with bad upgrade request: {}", req.uri());
return Ok(http::Response::builder() return Ok(http::Response::builder()
.status(StatusCode::BAD_REQUEST) .status(StatusCode::BAD_REQUEST)
.body(Body::from("Invalid upgrade request")) .body("Invalid upgrade request".into())
.unwrap_or_default()); .unwrap());
} }
if let Some(paths_prefix) = &server_config.restrict_http_upgrade_path_prefix { if let Some(paths_prefix) = &server_config.restrict_http_upgrade_path_prefix {
@ -217,8 +218,8 @@ async fn server_upgrade(
warn!("Rejecting connection with bad path prefix in upgrade request: {}", req.uri()); warn!("Rejecting connection with bad path prefix in upgrade request: {}", req.uri());
return Ok(http::Response::builder() return Ok(http::Response::builder()
.status(StatusCode::BAD_REQUEST) .status(StatusCode::BAD_REQUEST)
.body(Body::from("Invalid upgrade request")) .body("Invalid upgrade request".to_string())
.unwrap_or_default()); .unwrap());
} }
} }
@ -229,8 +230,8 @@ async fn server_upgrade(
warn!("Rejecting connection with bad upgrade request: {} {}", err, req.uri()); warn!("Rejecting connection with bad upgrade request: {} {}", err, req.uri());
return Ok(http::Response::builder() return Ok(http::Response::builder()
.status(StatusCode::BAD_REQUEST) .status(StatusCode::BAD_REQUEST)
.body(Body::from(format!("Invalid upgrade request: {:?}", err))) .body("Invalid upgrade request".to_string())
.unwrap_or_default()); .unwrap());
} }
}; };
@ -241,8 +242,8 @@ async fn server_upgrade(
warn!("Rejecting connection with bad upgrade request: {} {}", err, req.uri()); warn!("Rejecting connection with bad upgrade request: {} {}", err, req.uri());
return Ok(http::Response::builder() return Ok(http::Response::builder()
.status(StatusCode::BAD_REQUEST) .status(StatusCode::BAD_REQUEST)
.body(Body::from(format!("Invalid upgrade request: {:?}", err))) .body(format!("Invalid upgrade request: {:?}", err))
.unwrap_or_default()); .unwrap());
} }
}; };
@ -273,6 +274,8 @@ async fn server_upgrade(
)?, )?,
); );
} }
let response = Response::from_parts(response.into_parts().0, "".to_string());
Ok(response) Ok(response)
} }
@ -280,7 +283,7 @@ pub async fn run_server(server_config: Arc<WsServerConfig>) -> anyhow::Result<()
info!("Starting wstunnel server listening on {}", server_config.bind); info!("Starting wstunnel server listening on {}", server_config.bind);
let config = server_config.clone(); let config = server_config.clone();
let upgrade_fn = move |req: Request<Body>| server_upgrade(config.clone(), req); let upgrade_fn = move |req: Request<Incoming>| server_upgrade(config.clone(), req);
let listener = TcpListener::bind(&server_config.bind).await?; let listener = TcpListener::bind(&server_config.bind).await?;
let tls_acceptor = if let Some(tls) = &server_config.tls { let tls_acceptor = if let Some(tls) = &server_config.tls {
@ -310,14 +313,14 @@ pub async fn run_server(server_config: Arc<WsServerConfig>) -> anyhow::Result<()
let fut = async move { let fut = async move {
info!("Doing TLS handshake"); info!("Doing TLS handshake");
let tls_stream = match tls_acceptor.accept(stream).await { let tls_stream = match tls_acceptor.accept(stream).await {
Ok(tls_stream) => tls_stream, Ok(tls_stream) => hyper_util::rt::TokioIo::new(tls_stream),
Err(err) => { Err(err) => {
error!("error while accepting TLS connection {}", err); error!("error while accepting TLS connection {}", err);
return; return;
} }
}; };
let conn_fut = Http::new()
.http1_only(true) let conn_fut = http1::Builder::new()
.serve_connection(tls_stream, service_fn(upgrade_fn)) .serve_connection(tls_stream, service_fn(upgrade_fn))
.with_upgrades(); .with_upgrades();
@ -330,8 +333,8 @@ pub async fn run_server(server_config: Arc<WsServerConfig>) -> anyhow::Result<()
tokio::spawn(fut); tokio::spawn(fut);
// Normal // Normal
} else { } else {
let conn_fut = Http::new() let stream = hyper_util::rt::TokioIo::new(stream);
.http1_only(true) let conn_fut = http1::Builder::new()
.serve_connection(stream, service_fn(upgrade_fn)) .serve_connection(stream, service_fn(upgrade_fn))
.with_upgrades(); .with_upgrades();