vey-proxy User Guide
September 3, 2026 ยท View on GitHub
Table of Contents
- Installation
- Basic Concepts
- Basic Usage
- HTTP Proxy
- SOCKS Proxy
- TCP Mapping
- UDP Mapping
- TLS Offloading
- TLS Encapsulation
- SNI Proxy
- Transparent Proxy
- Route Binding
- Proxy Chaining
- Connection Rate Limits
- Process-Wide Rate Limits
- DNS Resolution
- Secure DNS Resolution
- Failover DNS Resolution
- User Authentication and Authorization
- LDAP User Authentication
- User Rate Limits and Bandwidth Limits
- User Blocking
- Advanced Usage
- mTLS Client
- Guomi TLCP Offloading
- Multiplexing Multiple Protocols on One Port
- Listening on Multiple Ports
- Enabling PROXY Protocol on a Listening Port
- Guomi TLCP Encapsulation
- SOCKS5 UDP IP Mapping
- Secure Reverse Proxy
- DNS Resolution Overrides
- Dynamic Route Binding
- Dynamic Proxy Chaining
- Per-User Site Monitoring
- Per-User Site TLS MITM Configuration
- Traffic Auditing
- Exporting Decrypted TLS Traffic
- Task Idle Detection
- Performance Optimization
- Scenario Design
Installation
vey-proxy currently supports Linux only. Packaging is supported for distributions such as Debian and RHEL. After building a package by following the Release and Packaging Steps, install it directly on the target system.
Basic Concepts
Service Management
You can deploy multiple vey-proxy services on a single host and manage them through systemd template units. Each
instance corresponds to one vey-proxy process group (daemon_group), and each process group exposes a Unix socket for
local RPC management.
Each service has one entry configuration file in YAML format. The file suffix can be changed, but all referenced configuration files must use the same suffix. In this guide, main.yml refers to the entry configuration file.
If you install from the native distribution package, the systemd templated service file is installed automatically. The
template parameter is the process group name, and the entry configuration file is located at
/etc/vey-proxy/<daemon_group>/main.yml.
If you install without using a package, see vey-proxy@.service and design your own service management workflow.
Hot Upgrades
The default systemd service configuration supports hot upgrades:
- Install the new package.
- Run
systemctl daemon-reloadto reload the updated unit files. - Run
systemctl restart vey-proxy@<daemon_group>to start the new process and tell the old process to drain.
After the old process starts draining, it waits for existing tasks to finish, or it is forced offline after a timeout (10 hours by default).
This works similarly to nginx reload. Because of operating system behavior, there is still a chance that new
connections may be dropped when sockets are released. Linux 5.14 and later introduced the
tcp_migrate_req option, which can prevent those drops.
Configuration Structure
vey-proxy uses a modular design. The main functional modules are:
-
Server
Accepts and processes client requests. It can call into the Escaper, UserGroup, and Auditor modules. A Port server can be chained in front of a non-port server.
-
Escaper
Connects to and controls the target address. It can call into the Resolver module. A Route escaper can be chained in front of other escapers.
-
Resolver
Provides DNS resolution. A Failover resolver can be chained in front of other resolvers.
-
UserGroup
Provides authentication and authorization.
-
Auditor
Provides traffic auditing.
These modules can be defined together in main.yml, or split into separate configuration files. Split files can be reloaded independently.
Settings outside those modules, such as threads, logging, and monitoring, must still be defined in main.yml.
For a single-file example, see examples/inspect_http_proxy. For a split-file example, see examples/hybrid_https_proxy.
The examples below show only the relevant fragments, not full configurations. For complete examples, see examples.
Monitoring
To integrate with different observability stacks, the VEY project uses StatsD as its metrics output protocol. You can choose any StatsD implementation that fits your environment, such as gostatsd, then connect that to your own monitoring system.
Configure monitoring for vey-proxy in main.yml:
stat:
target:
udp: 127.0.0.1:8125 # StatsD UDP socket
# unix: /run/statsd.sock
prefix: vey-proxy # Metric prefix, for example server.task.total becomes vey-proxy.server.task.total
emit_interval: 200ms # Emission interval
Metric definitions are under metrics. Generating the Sphinx HTML documentation makes them easier to browse.
Basic Usage
HTTP Proxy
To enable an HTTP proxy entry point, add an HttpProxy server:
server:
- name: http # Must be unique; used by logs and metrics
escaper: default # Required; can point to any escaper type
type: http_proxy
listen:
address: "[::]:8080"
tls_client: { } # Enables layer-7 HTTPS forward support
SOCKS Proxy
To enable a SOCKS proxy entry point, add a SocksProxy server:
server:
- name: socks # Must be unique; used by logs and metrics
escaper: default # Required; can point to any escaper type
type: socks_proxy
listen:
address: "[::]:10086"
enable_udp_associate: true # Use standard UDP Associate; otherwise use simplified UDP Connect (single peer only)
udp_socket_buffer: 512K # Client-side bidirectional UDP socket buffer size
TCP Mapping
To map a local TCP port to a specific port on the target host, add a TcpStream server:
server:
- name: tcp # Must be unique; used by logs and metrics
escaper: default # Required; can point to any escaper type
type: tcp_stream
listen:
address: "[::1]:10086"
proxy_pass: # One or more target addresses
- "127.0.0.1:5201"
- "127.0.0.1:5202"
upstream_pick_policy: rr # Load-balancing policy; default is random
UDP Mapping
To map a local UDP port to a specific port on the target host, add a UdpStream server:
server:
- name: udp # Must be unique; used by logs and metrics
escaper: default # Required; it should support the UdpConnect method
type: udp_stream
listen:
address: "[::1]:10086"
proxy_pass: # One or more target addresses
- "127.0.0.1:5201"
- "127.0.0.1:5202"
upstream_pick_policy: rr # Load-balancing policy; default is random
TLS Offloading
To map a local TCP port to a TLS port on the target host, use a TcpStream server:
server:
- name: tcp # Must be unique; used by logs and metrics
escaper: default # Required; can point to any escaper type
type: tcp_stream
listen: "[::1]:80"
proxy_pass: "127.0.0.1:443"
tls_client: { } # Use TLS to connect upstream; configure CA, client certs (mTLS), and so on
TLS Encapsulation
To map a local TLS port to a specific port on the target host, add a TlsStream server:
server:
- name: tls # Must be unique; used by logs and metrics
escaper: default # Required; can point to any escaper type
type: tls_stream
listen:
address: "[::1]:10443"
tls_server: # TLS settings
cert_pairs:
certificate: /path/to/cert
private_key: /path/to/key
enable_client_auth: true # Optional: enable mTLS
proxy_pass: # One or more target addresses
- "127.0.0.1:5201"
- "127.0.0.1:5202"
upstream_pick_policy: rr # Load-balancing policy; default is random
You can also chain a PlainTlsPort in front of a TcpStream server:
server:
- name: tcp
escaper: default
type: tcp_stream
proxy_pass:
- "127.0.0.1:5201"
- "127.0.0.1:5202"
upstream_pick_policy: rr
- name: tls
type: plain_tls_port
listen:
address: "[::1]:10443"
tls_server:
cert_pairs:
certificate: /path/to/cert
private_key: /path/to/key
enable_client_auth: true # Optional: enable mTLS
server: tcp # Forward to the tcp_stream server
SNI Proxy
To detect the target automatically from the TLS SNI or HTTP Host header and forward the connection, add an
SniProxy server:
server:
- name: sni # Must be unique; used by logs and metrics
escaper: default # Required; can point to any escaper type
type: sni_proxy
listen:
address: "[::]:443" # Can handle both TLS and HTTP traffic on port 443
Transparent Proxy
On a gateway device, you can redirect the TCP traffic to a TcpTProxy server or redirect the UDP traffic to a '
UdpTProxy' so the proxy can forward them transparently:
server:
- name: transparent_tcp
escaper: default
auditor: default # Needed for protocol inspection, TLS interception, and similar features
type: tcp_tproxy
listen: "127.0.0.1:1234"
- name: transparent_udp
escaper: default
auditor: default # Needed for protocol inspection, TLS interception, and similar features
type: udp_tproxy
listen: "127.0.0.1:1234"
The required system configuration depends on the operating system:
- Linux TPROXY
- FreeBSD ipfw fwd
- OpenBSD pf divert-to
Route Binding
If a machine has multiple network paths and you need to force outbound traffic onto one of them, set a bind IP on the
escaper. Using DirectFixed as an example:
escaper:
- name: default
type: direct_fixed
resolver: default
resolve_strategy: IPv4First # Happy Eyeballs is supported; prefer IPv4 when resolving
bind_ip: 192.168.10.1 # You can use a list to set multiple addresses
resolver:
- name: default
type: c-ares
server: 223.5.5.5
bind_ipv4: 192.168.10.1 # Bind DNS queries to the same path to keep resolution local
Proxy Chaining
If you need to forward traffic through another proxy, use a Proxy escaper. ProxyHttps is shown below:
escaper:
- name: next_proxy
type: proxy_https
resolver: default # Required when proxy_addr contains a domain name
proxy_addr: next-proxy.example.net:8443 # You can also provide multiple proxy addresses
http_forward_capability:
forward_ftp: true # Forward FTP-over-HTTP requests to the next proxy instead of handling FTP locally
forward_https: true # Forward HTTPS CONNECT traffic to the next proxy instead of doing the TLS handshake locally
tls_client:
ca_certificate: rootCA.pem # CA used to verify the next proxy; defaults to the system CA store
tls_name: example.com # Required for DNS-name validation if proxy_addr does not contain a domain name
Username Parameters to Derive the Next-Hop Address
For HTTP and SOCKS5 proxy servers, you can append ordered key-value pairs to the username and use them to derive the
next-hop proxy address dynamically: base-key1-val1-key2-val2-....
Example:
server:
- name: http-in
type: http_proxy
escaper: chain
username_params: # All keys are added to the egress context
required_keys: host
optional_keys: session-id
param_separator: '_'
escaper:
- name: comply_http
type: comply_context # Extract values from the egress context and set the dynamic next-hop address
next: proxy_http
use_egress_upstream:
default_port: 8080
host_key: host
domain_suffix: example.net
resolve_sticky_key: session-id
- name: proxy_http
type: proxy_http # Uses the dynamic address set by comply_http
proxy_addr: 127.0.0.1:3128 # Default address
The client can then connect with:
http://my_name-host-proxy1-session_id-1234:password@xxx
The actual next-hop proxy becomes proxy1.example.net, and sticky resolution uses 1234 as its sticky key.
Connection Rate Limits
Per-connection bandwidth limits are supported on the server, escaper, and user levels. The configuration keys are
the same in all three places:
tcp_sock_speed_limit: 10M/s
udp_sock_speed_limit: 10M/s
For server and user, the limits apply to client-to-proxy connections. For escaper, they apply to proxy-to-target
connections.
Process-Wide Rate Limits
User configuration also supports process-wide bandwidth limits:
tcp_all_download_speed_limit: 100M/s
tcp_all_upload_speed_limit: 100M/s
udp_all_download_speed_limit: 100M/s
udp_all_upload_speed_limit: 100M/s
DNS Resolution
To use the system default /etc/resolv.conf:
resolver:
- name: default
type: c-ares
To use specific DNS servers:
resolver:
- name: c-ares
type: c-ares
server:
- 1.1.1.1
- 1.0.0.1
- name: hickory
type: hickory
server:
- 8.8.8.8
- 8.8.4.4
Secure DNS Resolution
If you need encrypted access to upstream recursive DNS servers, use the hickory resolver:
resolver:
- name: default
type: hickory
server: 1.1.1.1
encryption: dns-over-https # Also supports dns-over-tls, dns-over-quic, and dns-over-h3
Failover DNS Resolution
If a single upstream recursive DNS server is unreliable, use a Failover resolver:
resolver:
- name: virtual
type: fail_over
primary: alidns
standby: dnspod
- name: alidns
type: c-ares
server: 223.5.5.5 223.6.6.6
- name: dnspod
type: c-ares
server: 119.29.29.29
User Authentication and Authorization
Both HTTP proxy and SOCKS5 proxy support user authentication. This requires a UserGroup configuration. For a complete
example, see examples/simple_user_auth. A sample user group is shown below:
user_group:
- name: default
static_users:
- name: root
# password: toor
token: # Authentication token
salt: 113323bdab6fd2cc
md5: 5c81f2becadde7fa5fde9026652ccc84
sha1: ff9d5c1a14328dd85ee95d4e574bd0558a1dfa96
dst_port_filter: # Allowed ports
- 80
- 443
dst_host_filter_set: # Allowed destinations
exact:
- ipinfo.io # Allow access to ipinfo.io
- 1.1.1.1
child:
- "ipip.net" # Allow access to myip.ipip.net
regex:
- "lum[a-z]*[.]com$" # Allow access to lumtest.com
source: # Dynamic users; static users take precedence
type: file # Can also be loaded and cached through Lua or Python scripts
path: dynamic_users.json
Use scripts/passphrase_hash.py to generate the authentication token fields.
LDAP User Authentication
User password verification can also be delegated to a remote LDAP service:
user_group:
- name: default
type: ldap
ldap_url: ldap://ldap.forumsys.com/dc=example,dc=com
pool:
min_idle_count: 1
static_users:
- name: gauss
# No token is required; this user can still have explicit configuration
source: # Dynamic user configuration
type: file
path: dynamic_users.json
unmanaged_user: # Template for users that pass LDAP auth but have no local config
name: unmanaged
User Rate Limits and Bandwidth Limits
At the user level, you can enforce per-connection bandwidth limits, request-rate limits, and concurrency limits:
tcp_sock_speed_limit: 10M/s # 10M/s in each direction for a single TCP connection
udp_sock_speed_limit: 10M/s # 10M/s in each direction for a single UDP connection
tcp_conn_rate_limit: 1000/s # Rate limit for new client-to-proxy TCP connections
request_rate_limit: 2000/s # Rate limit for new proxy requests
request_max_alive: 2000 # Maximum number of active tasks
User Blocking
Deleting a user does not terminate that user's existing tasks by default. To terminate them, mark the user as blocked. Existing tasks will be cleaned up within at most two Task Idle Detection intervals.
Configure a blocked user like this:
- name: foo
block_and_delay: 1s # Block the user and delay new responses by the configured duration
# Other settings can remain unchanged
Advanced Usage
mTLS Client
Several examples in this guide refer to tls_client. To enable mutual TLS as a client, use:
tls_client:
certificate: /path/to/cert.crt # Client certificate
private_key: /path/to/pkey.key # Client private key
ca_certificate: /path/to/ca/cert.crt # CA used to verify the server certificate; defaults to the system CA store
Guomi TLCP Offloading
This feature requires the vendored-tongsuo feature to be enabled at build time.
Some environments require the Guomi protocol, but many clients do not support it. vey-proxy can translate between protocols:
- TLCP to layer-4 TCP
server:
- name: l4tcp
type: tcp_stream
listen: "[::1]:10086"
upstream: "127.0.0.1:443" # Remote Guomi server address; domains are supported
tls_client:
protocol: tlcp
ca_certificate: /path/to/ca.cert # CA certificate
# You can also add mTLS settings here
upstream_tls_name: target.host.domain # Used for peer verification; optional if upstream already uses a domain
- TLCP to layer-4 TLS
server:
- name: l4tls
type: tls_stream
tls_server:
cert_pairs:
- certificate: /path/to/cert
private_key: /path/to/key
# Other settings are the same as the tcp_stream example above
- TLCP to layer-7 HTTP
site_group:
- name: local
static_sites:
- id: origin
set_default: true
upstream: "127.0.0.1:443"
tls_client:
protocol: tlcp
ca_certificate: /path/to/ca.cert
# You can also add mTLS settings here
tls_name: target.host.domain # Used for peer verification; optional if upstream already uses a domain
server:
- name: l7http
type: http_expose
listen: "[::1]:80"
site_group: local
- TLCP to layer-7 HTTPS
site_group:
- name: local
static_sites:
- id: origin
set_default: true
upstream: "127.0.0.1:443"
tls_client:
protocol: tlcp
ca_certificate: /path/to/ca.cert
# You can also add mTLS settings here
tls_name: target.host.domain # Used for peer verification; optional if upstream already uses a domain
tls_server: # TLS configuration for this site
cert_pairs:
- certificate: /path/to/cert
private_key: /path/to/key
server:
- name: l7http
type: http_expose
listen: "[::1]:443"
site_group: local
enable_tls_server: true
# global_tls_server can define the default TLS configuration for sites that do not set tls_server
Multiplexing Multiple Protocols on One Port
If you want a single port to accept both HttpProxy and SocksProxy, use an IntelliProxy port:
server:
- name: intelli
type: intelli_proxy
listen: "[::]:8080"
http_server: http # HTTP requests go to the http server
socks_server: socks # SOCKS requests go to the socks server
- name: http
type: HttpProxy
listen: "127.0.0.1:2001" # Bind locally to prevent direct external use
- name: socks
type: SocksProxy
listen: "127.0.0.1:2002" # Bind locally to prevent direct external use
Listening on Multiple Ports
If the same service needs to listen on multiple ports, chain a Port server in front of it.
Example: make SniProxy listen on both 443 and 80:
server:
- name: sni
escaper: default
type: sni_proxy
listen:
address: "[::]:443"
- name: port80
type: plain_tcp_port
listen: "[::]:80"
server: sni_proxy
Example: expose both plaintext and TLS ports for an HTTP proxy:
server:
- name: http
escaper: default
type: http_proxy
listen: "[::]:8080"
tls_client: { }
- name: tls
type: plain_tls_port
listen: "[::]:8443"
server: http
tls_server:
cert_pairs:
certificate: /path/to/certificate
private_key: /path/to/private_key
enable_client_auth: true # Optional: enable mTLS
Port-type servers have their own listener metrics only. Traffic metrics and logs are emitted by the next-hop server, so choose between port chaining and separate servers based on how you want to observe the service.
Enabling PROXY Protocol on a Listening Port
In a chained deployment, if you need to preserve the original client address, use the PROXY Protocol. PlainTcpPort
and PlainTlsPort can expose dedicated ports that accept PROXY Protocol:
server:
- name: real_http
listen: "[127.0.0.1]:1234" # Optional
type: http_proxy
ingress_network_filter: { } # Filter for the source address carried in the PROXY header
# ... other settings
- name: pp_for_http
type: plain_tcp_port
listen: "[::]:8080"
server: real_http
proxy_protocol: v2
ingress_network_filter: { } # Filter for the original peer socket address
Guomi TLCP Encapsulation
This feature requires the vendored-tongsuo feature to be enabled at build time.
You can use UsualTlsPort to encapsulate Guomi TLCP:
server:
- name: real_http
listen: "[127.0.0.1]:1234" # Optional
type: http_proxy
# ... other settings
- name: tlcp
type: usual_tls_port
listen: "[::]:443"
tls_server:
tlcp_cert_pairs: # Enables Guomi TLCP
sign_certificate: /path/to/sign.crt
sign_private_key: /path/to/sign.key
enc_certificate: /path/to/enc.crt
enc_private_key: /path/to/enc.key
enable_client_auth: true # Optional: enable mTLS
server: real_http
proxy_protocol: v2 # Optional: enable PROXY Protocol
SOCKS5 UDP IP Mapping
When handling SOCKS5 UDP, the server must tell the client which address to use for the UDP data channel. Normally this
is the proxy's local IP:Port, but sometimes the client cannot reach that local IP directly. In that case, configure a
mapping table on the SOCKS server:
transmute_udp_echo_ip:
"192.168.10.2": "192.168.30.2"
Secure Reverse Proxy
Many applications expose HTTP APIs or metrics endpoints with only minimal built-in protection. The following pattern can be used to harden them:
site_group:
- name: local
static_sites:
- id: service1
exact_match: service1.example.net # Match this hostname
upstream: 127.0.0.1:8081 # Forward all paths
- id: service2
exact_match: service2.example.net # Match this hostname
set_default: true # Use as the default site if no hostname matches
upstream: 127.0.0.1:8082 # Forward all paths
server:
- name: plain
escaper: default
user-group: default # Enable user authentication
type: http_expose
listen:
address: "[::]:80"
site_group: local
no_early_error_reply: true # Do not return errors until the request is validated; helps resist port scans
# You can enable TLS with tls_server, or add a separate TLS port through a fronting plain_tls_port
DNS Resolution Overrides
Sometimes you need to bypass normal DNS resolution and apply custom name resolution rules. You can do that in the user configuration:
resolve_redirection:
- exact: t1.example.net # Force to a specific IP
to: 192.168.10.1
- exact: t2.example.net # CNAME-style rewrite
to: t1.example.net
- child: example.com # Rewrite *.example.com to *.example.net
to: example.net
Dynamic Route Binding
Some machines get their IPs dynamically, for example through DHCP or PPP. Those addresses can be published into a
DirectFloat escaper at runtime.
Proxy configuration:
escaper:
- name: float
type: direct_float
resolver: default
Publish an updated address with:
vey-proxy-ctl -G <daemon_group> -p <pid> escaper float publish "{\"ipv4\": \"192.168.10.1\"}"
Dynamic Proxy Chaining
In crawling scenarios, upstream proxy addresses are often short-lived. You can put a stable intermediary proxy in front and let a helper process keep updating the real upstream proxy when it expires. Clients then only need one fixed proxy address.
Proxy configuration:
escaper:
- name: float
type: proxy_float
source:
type: passive # Accept pushed updates; can also be configured to read periodically from Redis
Publish an updated upstream proxy with:
vey-proxy-ctl -G <daemon_group> -p <pid> escaper float publish '{"type":"socks5","addr":"127.0.0.1:11080", "expire": "<rfc3339 datetime>"}'
The type field can also be http or https.
Per-User Site Monitoring
Within a user configuration, you can define site-specific rules and attach independent metrics or settings:
explicit_sites:
- id: example-net
suffix_match: example.net
emit_stats: true # Emit separate metrics; id becomes part of the metric name
resolve_strategy:
query: ipv4only # Resolve IPv4 only
Per-User Site TLS MITM Configuration
Within a user-site rule, you can customize how the TLS client behaves when TLS interception is enabled:
explicit_sites:
- id: example-net
suffix_match: example.net
tls_client:
ca_certificate: xxx # PEM CA certificate
cert_pairs:
certificate: xxx # PEM client certificate
private_key: xxx # PEM client private key
# Other tls_client settings
Traffic Auditing
For a complete example of traffic auditing, see examples/inspect_http_proxy. A typical auditor configuration looks like this:
auditor:
- name: default
protocol_inspection: { } # Enable protocol detection with default settings
tls_cert_generator: { } # Enable TLS interception with default settings; peer defaults to 127.0.0.1:2999
tls_interception_client: { } # Optional TLS client settings for upstream connections made during interception
h1_interception: { } # HTTP/1.0 parsing settings
h2_interception: { } # HTTP/2 parsing settings
icap_reqmod_service: icap://xxx # ICAP REQMOD service
icap_respmod_service: icap://xxx # ICAP RESPMOD service
application_audit_ratio: 1.0 # Fraction of application traffic to audit
This feature requires a TLS certificate generator. A reference implementation is vey-dcgen; see vey-dcgen simple conf for an example configuration.
Exporting Decrypted TLS Traffic
If traffic auditing and TLS interception are both enabled, you can export decrypted TLS traffic to udpdump.
For the detailed configuration, see examples/inspect_http_proxy.
Task Idle Detection
Every successful task can exit automatically after being idle for too long. Two settings control this behavior: the idle check interval and the allowed idle count. Both can be configured on the server:
- name: foo
type: xxx # Applies to any server type
task_idle_check_interval: 1m # Default is 1 minute
task_idle_max_count: 5 # Default maximum is 5; the task is terminated when the count is reached
The allowed idle count can also be set per user, overriding the server setting:
- name: foo
task_idle_max_count: 5
Performance Optimization
By default, the proxy uses all CPU cores and may schedule work across cores. In some environments, pinning workers to specific CPUs improves performance.
Configure workers in main.yml:
worker:
thread_number: 8 # Defaults to the full CPU core count if omitted
sched_affinity: true # Pin workers to CPUs in order by default; you can also provide an explicit worker-to-CPU map
When configuring a listener, you can also make it listen separately in each worker:
listen: "[::]:8080"
listen_in_worker: true
Scenario Design
Multi-Region Acceleration
You can combine existing vey-proxy modules to build cross-region acceleration.
For a three-region deployment, the topology looks like this:
flowchart LR
%% Paste to https://mermaid.live/ to see the graph
subgraph Area1
a1_client[Client]
a1_site[Site]
subgraph Proxy1
a1_proxy[GW]
a1_relay[relay]
a1_route[route]
a1_proxy -.-> a1_route
end
a1_client --> a1_proxy
a1_route -- local --> a1_site
a1_relay -- local --> a1_site
end
subgraph Area2
a2_client[Client]
a2_site[Site]
subgraph Proxy2
a2_proxy[GW]
a2_relay[relay]
a2_route[route]
a2_proxy -.-> a2_route
end
a2_client --> a2_proxy
a2_route -- local --> a2_site
a2_relay -- local --> a2_site
end
subgraph Area3
a3_client[Client]
a3_site[Site]
subgraph Proxy3
a3_proxy[GW]
a3_relay[relay]
a3_route[route]
a3_proxy -.-> a3_route
end
a3_client --> a3_proxy
a3_route -- local --> a3_site
a3_relay -- local --> a3_site
end
a1_route -- mTLS to a2 ----> a2_relay
a1_route -- mTLS to a3 ----> a3_relay
a2_route -- mTLS to a1 ----> a1_relay
a2_route -- mTLS to a3 ----> a3_relay
a3_route -- mTLS to a1 ----> a1_relay
a3_route -- mTLS to a2 ----> a2_relay
Each node's proxy typically has the following roles:
-
GW
Handles local user requests. For layer-4 acceleration you can use SNI Proxy; for layer-7 acceleration you can use Secure Reverse Proxy.
Minimal example:
server: - name: port443 type: sni_proxy escaper: route - name: port80 type: http_expose escaper: route -
relay
Handles requests from other regions over an internal protocol, such as mTLS.
Minimal example:
server: - name: relay type: http_proxy escaper: local tls_server: {} # Configure TLS settings -
route
Chooses the path for local user requests. You need at least one route-type escaper, one local escaper, and one proxy escaper for each remote region.
Minimal example:
escaper: - name: route type: route_query # Can query an external agent for routing, or you can use another route escaper query_allowed_next: - a1_proxy - a2_proxy - local fallback_node: local # ... agent configuration - name: local type: direct_fixed # ... local escaper configuration - name: a1_proxy type: proxy_https tls_client: {} # Configure TLS settings # ... point this at the relay endpoint in area a1 - name: a2_proxy type: proxy_https tls_client: {} # Configure TLS settings # ... point this at the relay endpoint in area a2
Dual-Exit Failover
If a single IDC has multiple public egress POPs, or any comparable setup with at least two non-local network paths to the target site, you can build automatic primary/standby failover like this:
flowchart LR
%% Paste to https://mermaid.live/ to see the graph
subgraph IDC
i1_client[Client]
subgraph Proxy
i1_proxy[GW]
i1_route[route]
i1_proxy -.-> i1_route
end
i1_client --> i1_proxy
end
subgraph POP1
p1_proxy[relay]
end
subgraph POP2
p2_proxy[relay]
end
internet[Internet]
i1_route -- proxy to pop1 --> p1_proxy
i1_route -- proxy to pop2 --> p2_proxy
p1_proxy -- local ---> internet
p2_proxy -- local ---> internet
Each node's proxy typically has the following roles:
-
GW
Handles client requests. It can be any server type, such as a forward proxy, reverse proxy, or TCP mapping service.
-
relay
Handles requests from other nodes over an internal protocol, such as mTLS.
Minimal example:
server: - name: relay type: http_proxy escaper: local tls_server: {} # Configure TLS settingsIf the GW inside the IDC must support SOCKS5 UDP, then the relay should also be a UDP-capable proxy. In that case, use SOCKS Proxy.
-
route
Chooses the path for local user requests. You need at least one route-type escaper plus one proxy escaper for each POP.
Minimal example:
escaper: - name: route type: route_failover primary_next: p1_proxy standby_next: p2_proxy fallback_delay: 100ms # Start the standby attempt after this delay if the primary has not succeeded - name: p1_proxy type: proxy_https # Must match the relay server type used by POP1 tls_client: {} # Configure TLS settings # ... point this at the relay endpoint in POP1 - name: p2_proxy type: proxy_https # Must match the relay server type used by POP2 tls_client: {} # Configure TLS settings # ... point this at the relay endpoint in POP2