This commit is contained in:
Mateusz Gruszczyński committed 2026-10-04 22:53:33 +02:00
1 parent 174389e5b1
commit e6604e41fc
73 files changed
+1240 -201

No files matched your search

+52 -16
View File
@@ -141,6 +141,11 @@ async fn forward(
"RustProxy: RFC 9220 WebSocket transport is not enabled for this vhost\n",
);
}
if let Some(response) = frontend
.and_then(|frontend| method_policy_denial(&frontend.method_policy, request.method()))
{
return response;
}
if !tls {
if let Some(response) = frontend.and_then(|frontend| force_ssl_redirect(frontend, &host, request.uri())) {
return response;
@@ -175,16 +180,19 @@ async fn forward(
if let Some(exchange) = request.extensions().get::<Arc<Exchange>>() {
*exchange.client_ip.lock().unwrap_or_else(|e| e.into_inner()) = Some(context.client_ip.to_string());
}
// GeoIP stays off the normal request path. Resolve lazily for any vhost or
// location policy that actually needs a country code, or for log capture.
let capture_country = state.logs.capture_country();
let mut country_resolved = false;
let mut country: Option<String> = None;
if let Some(frontend) = frontend {
// GeoIP is deliberately off the default request path. Resolve only when
// a country policy/rate-limit requires it or the operator explicitly
// enables country capture for access logs + traffic analytics.
let capture_country = state.logs.capture_country();
let country = (capture_country
if capture_country
|| frontend.profile_country_access.needs_geoip()
|| frontend.rate_limit.needs_geoip())
.then(|| state.geoip.country(context.client_ip))
.flatten();
|| frontend.rate_limit.needs_geoip()
{
country = state.geoip.country(context.client_ip);
country_resolved = true;
}
if capture_country {
if let Some(exchange) = request.extensions().get::<Arc<Exchange>>() {
*exchange.country.lock().unwrap_or_else(|e| e.into_inner()) = country.clone();
@@ -246,14 +254,42 @@ async fn forward(
return response;
}
let selected = snapshot.select_on(&host, &path, local.0, tls);
if !selected
.and_then(|r| r.acl.as_ref())
.is_none_or(|acl| acl.allows(context.client_ip))
{
return error(
StatusCode::FORBIDDEN,
"RustProxy: denied by access policy\n",
);
if let Some(route) = selected {
if let Some(response) = method_policy_denial(&route.method_policy, request.method()) {
return response;
}
if !route
.profile_acl
.as_ref()
.is_none_or(|acl| acl.allows(context.client_ip))
|| !route
.acl
.as_ref()
.is_none_or(|acl| acl.allows(context.client_ip))
{
return error(
StatusCode::FORBIDDEN,
"RustProxy: denied by access policy\n",
);
}
if (route.profile_country_access.needs_geoip() || route.country_access.needs_geoip())
&& !country_resolved
{
country = state.geoip.country(context.client_ip);
if capture_country {
if let Some(exchange) = request.extensions().get::<Arc<Exchange>>() {
*exchange.country.lock().unwrap_or_else(|e| e.into_inner()) = country.clone();
}
}
}
if !route.profile_country_access.allows(country.as_deref())
|| !route.country_access.allows(country.as_deref())
{
return error(
StatusCode::FORBIDDEN,
"RustProxy: location country access policy denied this request\n",
);
}
}
// The admin cookie is never ordinary application state. Strip it BEFORE
// auth/cache and keep only the removed fragment locally. A verified self-admin