Skip to content

Commit

Permalink
feat: ConnectorPacket
Browse files Browse the repository at this point in the history
fix: tunnel id from HelloPacket
  • Loading branch information
filipton committed Oct 8, 2024
1 parent ca4f6fb commit 65ae578
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 23 deletions.
2 changes: 1 addition & 1 deletion nginx-test-docker/nginx.conf
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
2 changes: 1 addition & 1 deletion nginx-test-docker/run.sh
Original file line number Diff line number Diff line change
@@ -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
15 changes: 8 additions & 7 deletions src/client/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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();
Expand All @@ -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,
Expand Down
34 changes: 23 additions & 11 deletions src/server/tunnel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down Expand Up @@ -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!"))?;

Expand All @@ -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)!"))?;

Expand All @@ -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?;
}
}
}
Expand All @@ -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);
Expand Down
69 changes: 66 additions & 3 deletions utils/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ pub struct HelloPacket {
pub tunnel_id: u128,
}

#[derive(Debug)]
#[derive(Debug, PartialEq)]
pub enum HelloPacketType {
Connector = 0,
Tunnel = 1,
Expand All @@ -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
}
Expand All @@ -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,
}
}
}
Expand Down

0 comments on commit 65ae578

Please sign in to comment.