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
@@ -114,6 +114,43 @@ pub enum IpAllowEntry {
DomainScoped { ip: String, domains: Vec<String> },
}
/// Authenticated VPN metadata received from trusted PROXY protocol TLVs.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct VpnConnectionInfo {
pub client_id: String,
pub assigned_ip: String,
pub transport_type: Option<String>,
pub remote_addr: Option<String>,
}
/// A VPN client allow entry: full-route client ID or domain-scoped client ID.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum VpnClientAllowEntry {
Plain(String),
DomainScoped {
#[serde(rename = "clientId")]
client_id: String,
domains: Vec<String>,
},
}
/// VPN-specific route access control.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RouteVpnSecurity {
/// Require authenticated VPN metadata for this route.
#[serde(skip_serializing_if = "Option::is_none")]
pub required: Option<bool>,
/// Allowed VPN client IDs. Empty/None means any authenticated VPN client when required=true.
#[serde(skip_serializing_if = "Option::is_none")]
pub allowed_clients: Option<Vec<VpnClientAllowEntry>>,
/// Allowed VPN assigned tunnel IPs. Mainly for compatibility; client IDs are preferred.
#[serde(skip_serializing_if = "Option::is_none")]
pub allowed_assigned_ips: Option<Vec<String>>,
}
/// Security options for routes.
/// Matches TypeScript: `IRouteSecurity`
#[derive(Debug, Clone, Serialize, Deserialize)]
@@ -142,4 +179,7 @@ pub struct RouteSecurity {
/// JWT auth
#[serde(skip_serializing_if = "Option::is_none")]
pub jwt_auth: Option<JwtAuthConfig>,
/// Authenticated VPN client requirement/allow list.
#[serde(skip_serializing_if = "Option::is_none")]
pub vpn: Option<RouteVpnSecurity>,
}