global buf size mtu based config and protocol rename

This commit is contained in:
2026-03-25 16:03:11 +07:00
parent 743c6bf05c
commit a213c01158
30 changed files with 102 additions and 92 deletions
+196
View File
@@ -0,0 +1,196 @@
use crate::crypto::session::SessionKeys;
use crate::nrxp::errors::{ErrorAction, ErrorStage, TlsError};
use crate::nrxp::parser::parser::Parser;
use crate::tlseng::extension::ExtensionStack;
use crate::tlseng::handshake::{ClientHello, HelloHeader, ServerHello};
use crate::tlseng::profile::{BrowserProfile, ServerProfile};
use crate::tlseng::tls_record::TlsRecord;
use crate::tlseng::types::{ContentType, HelloType};
use crate::tlseng::ApplicationData;
use bytes::{Bytes, BytesMut};
pub trait TlsInterceptor {
type Output;
fn start_process(buffer: &mut BytesMut) -> Result<Option<Self::Output>, TlsError> {
match TlsRecord::parse(buffer) {
Ok(Some(record)) => Self::handle_record(record),
Ok(None) => Ok(None),
Err(e) => Err(e),
}
}
fn handle_record(record: TlsRecord) -> Result<Option<Self::Output>, TlsError>;
}
pub enum HandshakeMessage {
Client {
base: ClientHello,
extensions: ExtensionStack,
},
Server {
base: ServerHello,
extensions: ExtensionStack,
},
}
impl HandshakeMessage {
pub fn random(&self) -> [u8; 32] {
match self {
Self::Client { base, .. } => base.random,
Self::Server { base, .. } => base.random,
}
}
pub fn extensions(&self) -> &ExtensionStack {
match self {
Self::Client { extensions, .. } => extensions,
Self::Server { extensions, .. } => extensions,
}
}
}
impl TlsInterceptor for HandshakeMessage {
type Output = HandshakeMessage;
fn handle_record(record: TlsRecord) -> Result<Option<Self::Output>, TlsError> {
if record.content_type != ContentType::Handshake {
return Err(TlsError::new(
ErrorStage::Handshake("Expected Handshake record"),
ErrorAction::Drop,
record.serialize(),
));
}
let mut payload = BytesMut::from(record.payload.as_ref());
if let Some(header) = HelloHeader::parse(&mut payload)? {
match header.header_type {
HelloType::Client => {
if let Some(hello) = ClientHello::parse(&mut payload)? {
let ext =
ExtensionStack::parse(&mut BytesMut::from(hello.extensions.as_ref()))?
.ok_or_else(|| {
TlsError::new(
ErrorStage::Handshake("Ext Err"),
ErrorAction::Drop,
Bytes::new(),
)
})?;
return Ok(Some(HandshakeMessage::Client {
base: hello,
extensions: ext,
}));
}
}
HelloType::Server => {
if let Some(hello) = ServerHello::parse(&mut payload)? {
let ext =
ExtensionStack::parse(&mut BytesMut::from(hello.extensions.as_ref()))?
.ok_or_else(|| {
TlsError::new(
ErrorStage::Handshake("Ext Err"),
ErrorAction::Drop,
Bytes::new(),
)
})?;
return Ok(Some(HandshakeMessage::Server {
base: hello,
extensions: ext,
}));
}
}
}
}
Ok(None)
}
}
impl TlsInterceptor for ApplicationData {
type Output = ApplicationData;
fn handle_record(record: TlsRecord) -> Result<Option<Self::Output>, TlsError> {
if record.content_type != ContentType::ApplicationData {
return Err(TlsError::new(
ErrorStage::ApplicationData("Expected AppData record"),
ErrorAction::Drop,
record.serialize(),
));
}
Ok(Some(ApplicationData {
_len: record.payload.len(),
payload: record.payload,
}))
}
}
pub struct TlsBridge;
impl TlsBridge {
pub fn unpack_handshake(buffer: &mut BytesMut) -> Result<Option<HandshakeMessage>, TlsError> {
HandshakeMessage::start_process(buffer)
}
pub fn unpack_app_data(buffer: &mut BytesMut) -> Result<Option<ApplicationData>, TlsError> {
ApplicationData::start_process(buffer)
}
pub fn wrap_client_hello(profile: &BrowserProfile, host: &str, keys: &SessionKeys) -> Bytes {
ClientHello::make_client_hello(profile, host, keys)
}
pub fn wrap_server_hello(
client_msg: &HandshakeMessage,
keys: &mut SessionKeys,
profile: &ServerProfile,
) -> Result<Bytes, TlsError> {
if let HandshakeMessage::Client { base, extensions } = client_msg {
if base.session_id.len() != 32 {
return Err(TlsError::new(
ErrorStage::Handshake("Invalid SessionID len"),
ErrorAction::Drop,
Bytes::new(),
));
}
let mut received_tag = [0u8; 16];
received_tag.copy_from_slice(&base.session_id[16..32]);
if !keys.verify_auth_tag(&received_tag) {
netrunner_logger::warn!("Unauthorized ClientHello: Auth Tag mismatch");
return Err(TlsError::new(
ErrorStage::Handshake("Auth Failed"),
ErrorAction::Drop,
Bytes::new(),
));
}
keys.update_keys(base.random, extensions, true)
.map_err(|e| {
netrunner_logger::error!(error = %e, "Server failed key update");
TlsError::new(
ErrorStage::Handshake("Key Exchange Failed"),
ErrorAction::Drop,
Bytes::new(),
)
})?;
let server_pub_key = keys.ecdh.public_key.to_bytes();
Ok(ServerHello::make_server_hello(
base,
&server_pub_key,
keys.salt.get_local(),
profile,
))
} else {
Err(TlsError::new(
ErrorStage::Handshake("Expected ClientHello for SH generation"),
ErrorAction::Drop,
Bytes::new(),
))
}
}
pub fn pack_app_data(buffer: Bytes) -> Bytes {
TlsRecord::build_application_data(buffer)
}
}