feat(rustproxy): add authenticated VPN route security
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user