feat(rustproxy): add authenticated VPN route security

This commit is contained in:
2026-05-24 01:25:06 +00:00
parent c161ac664d
commit c7785d2f78
12 changed files with 310 additions and 14 deletions
@@ -25,6 +25,7 @@ use std::pin::Pin;
use std::task::{Context, Poll};
use rustproxy_metrics::MetricsCollector;
use rustproxy_config::VpnConnectionInfo;
use rustproxy_routing::RouteManager;
use rustproxy_security::RateLimiter;
@@ -461,6 +462,20 @@ impl HttpProxyService {
cancel: CancellationToken,
) where
I: tokio::io::AsyncRead + tokio::io::AsyncWrite + Unpin + Send + 'static,
{
self.handle_io_with_vpn(stream, peer_addr, port, cancel, None).await;
}
/// Handle an incoming HTTP connection with optional authenticated VPN metadata.
pub async fn handle_io_with_vpn<I>(
self: Arc<Self>,
stream: I,
peer_addr: std::net::SocketAddr,
port: u16,
cancel: CancellationToken,
vpn_info: Option<VpnConnectionInfo>,
) where
I: tokio::io::AsyncRead + tokio::io::AsyncWrite + Unpin + Send + 'static,
{
let io = TokioIo::new(stream);
@@ -484,6 +499,7 @@ impl HttpProxyService {
let la_inner = Arc::clone(&last_activity);
let ar_inner = Arc::clone(&active_requests);
let cancel_inner = cancel.clone();
let vpn_info = Arc::new(vpn_info);
let service = hyper::service::service_fn(move |req: Request<Incoming>| {
// Detect frontend protocol from the first request on this connection.
// OnceLock ensures only the first call opens the counter.
@@ -499,6 +515,7 @@ impl HttpProxyService {
let svc = Arc::clone(&self);
let peer = peer_addr;
let cn = cancel_inner.clone();
let vpn = Arc::clone(&vpn_info);
let la = Arc::clone(&la_inner);
let st = start;
let ca = ConnActivity {
@@ -510,7 +527,7 @@ impl HttpProxyService {
};
async move {
let req = req.map(|body| BoxBody::new(body));
let result = svc.handle_request(req, peer, port, cn, ca).await;
let result = svc.handle_request(req, peer, port, cn, ca, vpn.as_ref().as_ref()).await;
// Mark request end — update activity timestamp before guard drops
la.store(st.elapsed().as_millis() as u64, Ordering::Relaxed);
drop(req_guard); // Explicitly drop to decrement active_requests
@@ -600,6 +617,7 @@ impl HttpProxyService {
port: u16,
cancel: CancellationToken,
mut conn_activity: ConnActivity,
vpn_info: Option<&VpnConnectionInfo>,
) -> Result<Response<BoxBody<Bytes, hyper::Error>>, hyper::Error> {
let host = extract_request_host(&req).map(str::to_string);
@@ -679,11 +697,12 @@ impl HttpProxyService {
.or_insert_with(|| Arc::new(RateLimiter::new(rl.max_requests, rl.window)))
.clone()
});
if let Some(response) = RequestFilter::apply_with_rate_limiter(
if let Some(response) = RequestFilter::apply_with_rate_limiter_and_vpn(
security,
&req,
&peer_addr,
rate_limiter.as_ref(),
vpn_info,
) {
return Ok(response);
}