use serde::Deserialize;
#[derive(Debug, Deserialize)]
#[serde(untagged)]
pub enum MatchExprConfig {
Composite(CompositeMatcher),
Leaf(Box<LeafMatcher>),
}
#[derive(Debug, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct CompositeMatcher {
#[serde(default)]
pub all: Option<Vec<MatchExprConfig>>,
#[serde(default)]
pub any_of: Option<Vec<MatchExprConfig>>,
#[serde(default)]
pub not: Option<Box<MatchExprConfig>>,
}
#[derive(Debug, Deserialize, Default)]
#[serde(deny_unknown_fields)]
pub struct LeafMatcher {
pub host_exact: Option<String>,
pub host_suffix: Option<String>,
pub host_regex: Option<String>,
pub destination_port_regex: Option<String>,
pub destination_port: Option<u16>,
pub destination_port_range: Option<Vec<u16>>,
pub destination_port_set: Option<Vec<u16>>,
pub destination_cidr: Option<String>,
pub source_cidr: Option<String>,
pub source_port: Option<u16>,
pub listener: Option<String>,
pub protocol: Option<String>,
pub identity: Option<String>,
pub transport: Option<String>,
pub reverse_listener: Option<String>,
}
#[derive(Debug, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct ConfigFile {
pub version: Option<u32>,
pub process: Option<ProcessConfig>,
pub timeouts: Option<TimeoutConfig>,
pub listeners: Option<Vec<ListenerConfig>>,
pub upstreams: Option<Vec<UpstreamConfig>>,
pub upstream_groups: Option<Vec<UpstreamGroupConfig>>,
pub rules: Option<Vec<RuleConfig>>,
pub rules_file: Option<String>,
pub routing: Option<RoutingConfig>,
pub admin: Option<AdminConfig>,
#[serde(default)]
pub reverse_servers: Option<Vec<ReverseServerConfig>>,
#[serde(default)]
pub reverse_clients: Option<Vec<ReverseClientConfig>>,
}
#[derive(Debug, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct ProcessConfig {
pub log_format: Option<String>,
pub log_level: Option<String>,
pub shutdown_grace: Option<String>,
}
#[derive(Debug, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct TimeoutConfig {
pub handshake: Option<String>,
pub connect: Option<String>,
}
#[derive(Debug, Clone, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct ListenerUdpConfig {
pub enabled: Option<bool>,
pub mode: Option<String>,
pub bind: Option<String>,
pub advertise: Option<String>,
pub idle_timeout: Option<String>,
pub target_idle_timeout: Option<String>,
pub max_associations: Option<usize>,
pub max_targets_per_association: Option<usize>,
pub max_datagram_size: Option<usize>,
pub client_pin: Option<bool>,
pub allow_private_egress: Option<bool>,
pub max_associations_global: Option<usize>,
#[serde(default)]
pub fixed_target: Option<String>,
}
#[derive(Debug, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct ListenerConfig {
pub name: String,
pub bind: String,
pub protocols: Vec<String>,
#[serde(default)]
pub reuse_port: Option<bool>,
pub connection_limit: Option<u32>,
pub auth: Option<AuthConfig>,
#[serde(default)]
pub udp_enabled: Option<bool>,
#[serde(default)]
pub udp: Option<ListenerUdpConfig>,
#[serde(default)]
pub tls: Option<ListenerTlsConfig>,
#[serde(default)]
pub shadowsocks: Option<ShadowsocksListenerConfig>,
#[serde(default)]
pub ssr: Option<SsrListenerConfig>,
#[serde(default)]
pub trojan: Option<ListenerTrojanConfig>,
#[serde(default)]
pub transparent: Option<TransparentConfig>,
#[serde(default)]
pub unix: Option<UnixListenerConfig>,
#[serde(default)]
pub fixed_target: Option<String>,
#[serde(default)]
pub local_bind: Option<String>,
}
#[derive(Debug, Clone, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct TransparentConfig {
pub enabled: Option<bool>,
pub protocol: Option<String>,
}
#[derive(Debug, Clone, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct UnixListenerConfig {
pub path: String,
pub unlink_existing: Option<bool>,
pub mode: Option<u32>,
}
#[derive(Debug, Clone, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct ShadowsocksListenerConfig {
pub method: String,
pub password: String,
#[serde(default)]
pub auth_prefix: Option<String>,
#[serde(default)]
pub plugins: Vec<String>,
}
#[derive(Debug, Clone, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct SsrListenerConfig {
#[serde(default)]
pub auth_prefix: Option<String>,
#[serde(default)]
pub plugins: Vec<String>,
}
#[derive(Debug, Clone, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct ListenerTrojanConfig {
pub password: String,
#[serde(default)]
pub fallback: Option<String>,
}
#[derive(Debug, Clone, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct ListenerTlsConfig {
pub cert: String,
pub key: String,
#[serde(default)]
pub alpn: Option<Vec<String>>,
}
#[derive(Debug, Clone, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct AuthConfig {
#[serde(rename = "type")]
pub auth_type: String,
pub username: Option<String>,
pub password: Option<String>,
pub password_env: Option<String>,
}
#[derive(Debug, Clone, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct H2UpstreamConfig {
pub max_concurrent_streams: Option<u32>,
pub pool_size: Option<u32>,
pub idle_timeout: Option<String>,
pub keepalive_interval: Option<String>,
pub keepalive_timeout: Option<String>,
pub stream_receive_window: Option<u32>,
pub connection_receive_window: Option<u32>,
pub max_frame_size: Option<u32>,
pub max_header_list_size: Option<u32>,
}
#[derive(Debug, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct UpstreamConfig {
pub id: String,
pub uri: String,
#[serde(default)]
pub health: Option<HealthConfigToml>,
#[serde(default)]
pub h2: Option<H2UpstreamConfig>,
}
#[derive(Debug, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct HealthConfigToml {
pub mode: Option<String>,
pub interval: Option<String>,
pub timeout: Option<String>,
pub failures_to_unhealthy: Option<u32>,
pub successes_to_healthy: Option<u32>,
pub initial_state: Option<String>,
}
#[derive(Debug, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct UpstreamGroupConfig {
pub id: String,
pub scheduler: Option<String>,
pub members: Vec<String>,
pub fallback: Option<String>,
}
#[derive(Debug, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct RuleConfig {
pub id: String,
pub host_exact: Option<String>,
pub host_suffix: Option<String>,
pub host_regex: Option<String>,
pub destination_port_regex: Option<String>,
pub destination_port: Option<u16>,
#[serde(default)]
pub any: Option<bool>,
#[serde(default, rename = "match")]
pub match_expr: Option<MatchExprConfig>,
pub direct: Option<bool>,
pub upstream_group: Option<String>,
pub reject: Option<String>,
}
#[derive(Debug, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct RoutingConfig {
pub default: Option<String>,
}
#[derive(Debug, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct AdminConfig {
pub bind: Option<String>,
pub enabled: Option<bool>,
pub metrics: Option<bool>,
pub auth: Option<AdminAuthConfig>,
pub pac: Option<PacConfigToml>,
pub static_content: Option<Vec<StaticContentToml>>,
}
#[derive(Debug, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct AdminAuthConfig {
pub bearer_token: Option<String>,
pub bearer_token_env: Option<String>,
pub basic_auth: Option<AdminBasicAuthConfig>,
}
#[derive(Debug, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct AdminBasicAuthConfig {
pub user: String,
pub password: Option<String>,
pub password_env: Option<String>,
}
#[derive(Debug, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct PacConfigToml {
pub path: Option<String>,
pub proxy: String,
pub direct_fallback: Option<bool>,
pub direct_hosts: Option<Vec<String>>,
pub direct_suffixes: Option<Vec<String>>,
}
#[derive(Debug, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct StaticContentToml {
pub path: String,
pub content_type: Option<String>,
pub body: Option<String>,
}
#[derive(Debug, Clone, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct ReverseServerConfig {
pub id: String,
pub control_bind: String,
pub external_bind: String,
pub auth_username: Option<String>,
pub auth_password: Option<String>,
pub auth_password_env: Option<String>,
pub max_streams: Option<u32>,
pub heartbeat_interval: Option<String>,
#[serde(default)]
pub pproxy_compat: bool,
}
#[derive(Debug, Clone, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct ReverseClientConfig {
pub id: String,
pub server_addr: String,
#[serde(default)]
pub server_uri: Option<String>,
pub auth_username: Option<String>,
pub auth_password: Option<String>,
pub auth_password_env: Option<String>,
pub reconnect_initial: Option<String>,
pub reconnect_max: Option<String>,
pub heartbeat_interval: Option<String>,
pub parallel_connections: Option<u32>,
pub default_target_host: Option<String>,
pub default_target_port: Option<u16>,
#[serde(default)]
pub pproxy_compat: bool,
}