From 65ae57806a1d313ba25b5db495e493684d4e5eef Mon Sep 17 00:00:00 2001 From: filipton Date: Tue, 8 Oct 2024 21:22:45 +0200 Subject: [PATCH] feat: ConnectorPacket fix: tunnel id from HelloPacket --- nginx-test-docker/nginx.conf | 2 +- nginx-test-docker/run.sh | 2 +- src/client/main.rs | 15 ++++---- src/server/tunnel.rs | 34 ++++++++++++------ utils/src/lib.rs | 69 ++++++++++++++++++++++++++++++++++-- 5 files changed, 99 insertions(+), 23 deletions(-) diff --git a/nginx-test-docker/nginx.conf b/nginx-test-docker/nginx.conf index 15c5ddc..c173afe 100644 --- a/nginx-test-docker/nginx.conf +++ b/nginx-test-docker/nginx.conf @@ -25,7 +25,7 @@ http { server { listen 80 default_server; listen [::]:80 default_server; - return 301 https://$host$request_uri; + #return 301 https://$host$request_uri; root /usr/share/nginx/html; } diff --git a/nginx-test-docker/run.sh b/nginx-test-docker/run.sh index 213595d..6efe2e8 100755 --- a/nginx-test-docker/run.sh +++ b/nginx-test-docker/run.sh @@ -1,4 +1,4 @@ #!/bin/bash docker build -t nginx-test-docker . -docker run -it --rm -p 1443:443/udp nginx-test-docker +docker run -it --rm -p 80:80/tcp -p 443:443/tcp -p 1443:443/udp nginx-test-docker diff --git a/src/client/main.rs b/src/client/main.rs index ab6903e..3391032 100644 --- a/src/client/main.rs +++ b/src/client/main.rs @@ -10,7 +10,7 @@ use tokio::{ use utils::{ certs::{cert_from_str, key_from_str}, http::construct_http_redirect, - parse_socketaddr, read_string_from_stream, HelloPacket, + parse_socketaddr, read_string_from_stream, ConnectorPacket, ConnectorPacketType, HelloPacket, }; const MAX_REQUEST_TIME: u128 = 1000; @@ -99,15 +99,16 @@ async fn connector(args: &Args) -> Result<()> { hello_packet.hp_type = utils::HelloPacketType::Tunnel; + let mut buf = [0; ConnectorPacket::buf_size()]; loop { - let first_byte = stream.read_u8().await?; - if first_byte == 0x69 { + stream.read_exact(&mut buf).await?; + let packet = ConnectorPacket::from_buf(&buf); + + if packet.packet_type == ConnectorPacketType::Ping { stream.write_u8(0x69).await?; continue; // ping/pong } - let tunnel_id = stream.read_u128().await?; - let ssl = first_byte == 0x01; let domain = domain.to_string(); let acceptor = acceptor.clone(); let requested_time = Instant::now(); @@ -119,13 +120,13 @@ async fn connector(args: &Args) -> Result<()> { http3: args.http3, }; - hello_packet.tunnel_id = tunnel_id; + hello_packet.tunnel_id = packet.tunnel_id; let hello_packet = hello_packet.to_buf(); tokio::task::spawn(async move { let res = spawn_tunnel( hello_packet, settings, - ssl, + packet.ssl, ssl_port, domain, acceptor, diff --git a/src/server/tunnel.rs b/src/server/tunnel.rs index 17307f0..b50243a 100644 --- a/src/server/tunnel.rs +++ b/src/server/tunnel.rs @@ -7,6 +7,7 @@ use tokio::{ net::{TcpListener, TcpStream}, }; use tokio_rustls::{client::TlsStream, rustls::pki_types, TlsAcceptor, TlsConnector}; +use utils::{ConnectorPacket, ConnectorPacketType, HelloPacket}; const PANEL_HTML: &str = include_str!("./resources/index.html"); const ERROR_HTML: &str = include_str!("./resources/error.html"); @@ -67,25 +68,27 @@ async fn connector_handler( .connect(pki_types::ServerName::try_from("proxy.lan")?, stream) .await?; - let mut connection_buff = [0u8; 80]; + let mut connection_buff = [0u8; HelloPacket::buf_size()]; stream.read_exact(&mut connection_buff).await?; - let url_hash: u64 = u64::from_be_bytes(connection_buff[1..9].try_into()?); + let hello_packet = ::utils::HelloPacket::from_buf(&connection_buff); let token = state - .get_token_by_url_hash(url_hash) + .get_token_by_url_hash(hello_packet.hash) .await .ok_or_else(|| anyhow!("Cant find token!"))?; - let hello_packet = ::utils::HelloPacket::from_buf(&connection_buff); if hello_packet.token != token { return Err(::utils::HelloPacketError::TokenMismatch.into()); } // im the connector! if connection_buff[0] == 0 { - tracing::info!("Connector connected to url with hash: {url_hash}"); + tracing::info!( + "Connector connected to url with hash: {}", + hello_packet.hash + ); let domain = state - .get_domain_by_hash(url_hash) + .get_domain_by_hash(hello_packet.hash) .await .ok_or_else(|| anyhow!("Cant find domain!"))?; @@ -105,9 +108,8 @@ async fn connector_handler( state.remove_tunnel(token).await; } else if connection_buff[0] == 1 { // im the tunnel! - let tunnel_id = u128::from_be_bytes(connection_buff[26..42].try_into().unwrap()); let tx = state - .get_tunnel_oneshot(tunnel_id) + .get_tunnel_oneshot(hello_packet.tunnel_id) .await .ok_or_else(|| anyhow!("Cant find tunnel with that id (probably after timeout)!"))?; @@ -129,8 +131,12 @@ async fn connector_loop( match res { TunnelRequest::Close => return Ok(()), TunnelRequest::Request { ssl, tunnel_id } => { - stream.write_u8(u8::from(ssl)).await?; - stream.write_u128(tunnel_id).await?; + stream.write_all(&ConnectorPacket { + packet_type: ConnectorPacketType::TunnelRequest, + tunnel_id, + ssl, + http3: false + }.to_buf()).await?; } } } @@ -140,7 +146,13 @@ async fn connector_loop( } } _ = pinger.tick() => { - stream.write_u8(0x69).await?; + stream.write_all(&ConnectorPacket { + packet_type: ConnectorPacketType::Ping, + tunnel_id: 0, + ssl: false, + http3: false + }.to_buf()).await?; + let read = stream.read_u8().await?; if read != 0x69 { tracing::error!("Wrong pong response: {:x}", read); diff --git a/utils/src/lib.rs b/utils/src/lib.rs index 0d804a4..ed6788a 100644 --- a/utils/src/lib.rs +++ b/utils/src/lib.rs @@ -16,7 +16,7 @@ pub struct HelloPacket { pub tunnel_id: u128, } -#[derive(Debug)] +#[derive(Debug, PartialEq)] pub enum HelloPacketType { Connector = 0, Tunnel = 1, @@ -43,13 +43,17 @@ impl HelloPacketType { } impl HelloPacket { + pub const fn buf_size() -> usize { + 80 + } + pub fn to_buf(&self) -> [u8; 80] { let mut tmp = [0; 80]; tmp[0] = self.hp_type.to_u8(); tmp[1..9].copy_from_slice(&self.hash.to_be_bytes()); tmp[10..26].copy_from_slice(&self.token.to_be_bytes()); tmp[26] = self.own_ssl as u8; - tmp[26..42].copy_from_slice(&self.tunnel_id.to_be_bytes()); + tmp[27..43].copy_from_slice(&self.tunnel_id.to_be_bytes()); tmp } @@ -60,7 +64,66 @@ impl HelloPacket { hash: u64::from_be_bytes(buf[1..9].try_into().unwrap()), token: u128::from_be_bytes(buf[10..26].try_into().unwrap()), own_ssl: buf[26] != 0, - tunnel_id: u128::from_be_bytes(buf[26..42].try_into().unwrap()), + tunnel_id: u128::from_be_bytes(buf[27..43].try_into().unwrap()), + } + } +} + +#[derive(Debug, PartialEq)] +pub enum ConnectorPacketType { + Ping = 0, + TunnelRequest = 1, + + Invalid, +} + +impl ConnectorPacketType { + pub fn to_u8(&self) -> u8 { + match self { + ConnectorPacketType::Ping => 0, + ConnectorPacketType::TunnelRequest => 1, + ConnectorPacketType::Invalid => u8::MAX, + } + } + + pub fn from_u8(val: u8) -> Self { + match val { + 0 => ConnectorPacketType::Ping, + 1 => ConnectorPacketType::TunnelRequest, + _ => ConnectorPacketType::Invalid, + } + } +} + +#[derive(Debug)] +pub struct ConnectorPacket { + pub packet_type: ConnectorPacketType, + pub tunnel_id: u128, + pub ssl: bool, + pub http3: bool, +} + +impl ConnectorPacket { + pub const fn buf_size() -> usize { + 20 + } + + pub fn to_buf(&self) -> [u8; 20] { + let mut tmp = [0; 20]; + tmp[0] = self.packet_type.to_u8(); + tmp[1..17].copy_from_slice(&self.tunnel_id.to_be_bytes()); + tmp[17] = self.ssl as u8; + tmp[18] = self.http3 as u8; + + tmp + } + + pub fn from_buf(buf: &[u8; 20]) -> Self { + Self { + packet_type: ConnectorPacketType::from_u8(buf[0]), + tunnel_id: u128::from_be_bytes(buf[1..17].try_into().unwrap()), + ssl: buf[17] != 0, + http3: buf[18] != 0, } } }