This document provides a detailed explanation of the config.yaml file used by the proxy.
The ioParams section allows fine-tuning of input/output operations. These settings are optional, and the proxy will use default values if this section is omitted. It's recommended not to change these unless you have a clear understanding of their impact.
bufferSize(integer): Defines the size of the buffer (in bytes) used for I/O operations.- Default value:
65536(64KB)
- Default value:
useSplice(boolean): Toggles the use of thesplice()system call on Linux for zero-copy data transfer between kernel buffers. This can improve performance by avoiding data copying between user space and kernel space.- Default value:
true - Note: This setting is effective only on Linux systems that support
splice().
- Default value:
Example:
ioParams:
bufferSize: 65536
useSplice: trueThe entire metrics section is optional. The metrics section configures an HTTP endpoint for exposing Prometheus-compatible metrics and potentially a web UI.
api_prefix(string, optional): Specifies the URL prefix for the metrics API.- Default value:
/api - If you change this, the metrics endpoint will be available at
http://<bind_address><api_prefix>/metrics.
- Default value:
ui(string, optional): Defines the path to static files for a web UI. If the proxy is compiled with theembedded-uifeature, the default value is"<embedded>"to use the built-in UI. Otherwise, it defaults to being disabled (equivalent tonull). You can specify a local directory path (e.g.,./ui) to serve custom UI files.bind(string): The IP address and port on which the metrics and UI server will listen.- Example:
"0.0.0.0:8888"will listen on port 8888 on all available network interfaces.
- Example:
history_size(integer, optional): Specifies the maximum number of entries to keep in the connection history accessible via the API (e.g.,/api/history).- Default value:
100
- Default value:
cors(string, optional): Configures theAccess-Control-Allow-Originheader for the metrics and API endpoints.- Default value:
"*"(allows all origins)
- Default value:
Example:
metrics:
# api_prefix: /api
# ui: ./ui # or "<embedded>" if compiled with embedded-ui feature
# history_size: 100
# cors: "*"
bind: "0.0.0.0:8888"The timeouts section allows you to define global timeout values for connections.
idle(integer): Specifies the timeout in seconds for idle connections. If a connection (e.g., TCP) remains inactive for this duration, it will be closed.- Default value:
600seconds (10 minutes), as indicated by comments in the exampleconfig.yaml. The example shows10.
- Default value:
udp(integer): Specifies the timeout in seconds for UDP associations. If a UDP session sees no traffic for this duration, it will be considered stale and resources may be cleaned up.- Default value:
600seconds (10 minutes), as indicated by comments in the exampleconfig.yaml. The example shows10.
- Default value:
Note: The example config.yaml shows these values set to 10. Ensure you are using values appropriate for your environment. The default values mentioned in the comments (600) might be from the application's internal defaults if these fields are omitted, while the 10 in the example is an explicit override.
Example:
timeouts:
idle: 10 # unit: seconds, default value: 600
udp: 10 # unit: seconds, default value: 600The listeners section is a list that defines how the proxy listens for incoming connections. Each item in the list is a listener configuration object.
Most listener types share some common parameters:
name(string): A descriptive name for the listener. If thetypeparameter is omitted, the proxy may attempt to infer the listener type from thisname(e.g., a name like "http" might imply an HTTP listener).bind(string): The IP address and port on which the listener will accept connections.- Example:
"0.0.0.0:8080"will listen on port 8080 on all available network interfaces.
- Example:
protocol(string, optional): Specifies the transport protocol for the listener.- Common values:
tcp(default),udp. - The default is usually
tcpif not specified.
- Common values:
type(string, optional): Explicitly defines the type of the listener. If omitted, the type might be inferred from thenamefield. It's good practice to specify thetypefor clarity.
Availability: This listener type is only available when the proxy is compiled for Linux or Android systems.
The tproxy listener allows the proxy to intercept traffic transparently, often used in gateway setups. This typically requires specific system configurations (e.g., iptables rules on Linux) to redirect traffic to this listener.
type: tproxy(or inferred fromname)- Common Parameters:
bind,protocol(can betcporudp).
When protocol is udp, tproxy has additional options:
udpFullCone(boolean):- Default value:
false. - If
false(restrictive NAT), the proxy maintains a mapping based on source IP/port and destination IP/port. This is generally faster and allows filtering by destination address. - If
true(full cone NAT), the proxy maintains a mapping based only on the source IP/port, allowing any external host to send packets to the client once the client has sent a packet out. This is slower and cannot filter by destination address. - Note: The
config.yamlcomments state that SOCKS5 upstreams only support full cone NAT.
- Default value:
udpMaxSocket(integer):- Default value:
128. - Only applicable when
udpFullConeistrue. - Controls the number of sockets cached for sending UDP replies. Increasing this might be necessary for high-traffic full cone NAT scenarios.
- Default value:
System Requirements for UDP TProxy:
The comments in config.yaml note that UDP tproxy listeners require CAP_NET_ADMIN capabilities (e.g., set with setcap cap_net_admin+ep <your_proxy_binary> or by running as root).
Examples:
# TCP tproxy listener
listeners:
- name: tproxy # type 'tproxy' is inferred
bind: 0.0.0.0:8080
protocol: tcp # default if not specified and type is tproxy
# UDP tproxy listener
- name: tproxy-udp
type: tproxy
bind: 0.0.0.0:8080 # Can be the same bind as TCP if differentiated by protocol
protocol: udp
udpFullCone: false
udpMaxSocket: 256The reverse listener acts as a reverse proxy, forwarding incoming connections to a predefined target server.
type: reverse- Common Parameters:
bind,protocol(can betcporudp). target(string): The address and port of the upstream server to which traffic should be forwarded.- Format:
"host:port"or"domain_name:port". - Example:
"1.1.1.1:53"or"one.one.one.one:53".
- Format:
Example:
listeners:
- name: udp-reverse
type: reverse
bind: 0.0.0.0:8053
target: one.one.one.one:53 # Forwards to Cloudflare DNS
protocol: udpThe http listener acts as an HTTP proxy. It can handle plain HTTP connections and can be configured for HTTPS by adding a tls section.
type: http(or inferred ifnameis "http" or "https")- Common Parameters:
bind. The protocol is implicitly TCP for HTTP/S.
To enable HTTPS, add a tls object to the listener configuration.
tls: Container for TLS settings.cert(string): Path to the server's SSL/TLS certificate file (e.g.,test.crt).key(string): Path to the server's private key file (e.g.,test.key).client(object, optional): Configures client certificate authentication (mTLS). If this block is omitted, client certificates are not requested.ca(string): Path to the Certificate Authority (CA) certificate file used to verify client certificates (e.g.,ca.crt).required(boolean, optional): Iftrue, clients must present a valid certificate signed by the specified CA. Iffalseor omitted, client certificates are requested but not strictly required for the connection.- Default value:
false(when theclientblock is present).
- Default value:
protocol(object, optional, added in v0.11.0): TLS protocol version configuration.tls_1_2(boolean, optional): Enable TLS 1.2 support. Default:truetls_1_3(boolean, optional): Enable TLS 1.3 support. Default:true
security(object, optional, added in v0.11.0): Advanced TLS security options.sni(object, optional): Server Name Indication configuration.enable(boolean, optional): Enable SNI support. Default:falsecertificates(object, optional): Map of hostnames to certificate configurations.
ocsp_stapling(boolean, optional): Enable OCSP stapling for certificate validation. Default:falserequire_sni(boolean, optional): Require SNI extension from clients. Default:false
Examples:
listeners:
# Plain HTTP listener
- name: http
bind: 0.0.0.0:8081
# HTTPS listener with client certificate authentication
- name: https # type 'http' can be inferred
type: http # Explicitly setting type
bind: 0.0.0.0:8082
tls:
cert: test.crt
key: test.key
client:
ca: ca.crt
required: true # Example showing strict requirement
# Advanced HTTPS listener with SNI support
- name: https-sni
type: http
bind: 0.0.0.0:8443
tls:
cert: default.crt # Default certificate
key: default.key
protocol:
tls_1_3: true # Enable only TLS 1.3
tls_1_2: false # Disable TLS 1.2
security:
sni:
enable: true
certificates:
"example.com":
cert: "example.com.crt"
key: "example.com.key"
"api.example.com":
cert: "api.example.com.crt"
key: "api.example.com.key"
ocsp_stapling: true
require_sni: trueThe socks listener implements a SOCKS5 proxy server. This listener can be configured to use TLS for secure SOCKS5 connections (SOCKS over TLS) by including the tls section.
type: socks(or inferred ifnamecontains "socks")- Common Parameters:
bind. Protocol is implicitly TCP for SOCKS5 handshake, UDP can be enabled for associations. allowUdp(boolean):- Default value:
true. - Enables UDP associate command handling in SOCKS5, allowing UDP traffic to be proxied.
- Default value:
enforceUdpClient(boolean):- Default value:
false. - Relevant when
allowUdpistrue. - The SOCKS5 RFC1928 (page 6) states: "The server MAY use this information [client IP and port in UDP request] to limit access to the association." If
true, the proxy might enforce that UDP packets come from the client IP/port that established the association. Iffalse, it might be more permissive.
- Default value:
overrideUdpAddress(string, optional):- Example:
"127.0.0.1". - If set, this IP address will be returned to the SOCKS client in the BND.ADDR field for UDP associations, instead of the server's actual IP address. This is useful if the proxy server is behind a NAT and the external IP needs to be specified.
- Example:
allowBind(boolean, optional): Enables or disables the SOCKS BIND command support.- Default value:
false. - When
true, clients can use the SOCKS BIND command to create listening sockets for incoming connections. - When
false, BIND requests are rejected with an appropriate SOCKS error response. - The BIND command is commonly used by FTP clients and other protocols requiring reverse connections.
- Default value:
enforceBindAddress(boolean, optional): Controls whether the listener ignores client-requested bind addresses for security.- Default value:
true. - Only effective when
allowBindistrue. - When
false, the proxy honors the client's requested bind address and port (normal SOCKS behavior). - When
true, the proxy ignores the client's request and forces system-allocated addresses (0.0.0.0:0 or :::0). - Setting to
true(default) provides additional security by preventing clients from binding to specific addresses or ports.
- Default value:
auth(object, optional): Configures SOCKS5 authentication.required(boolean):- Default value:
false. - If
true, the client MUST use Username/Password authentication (Method 0x02). The proxy will check credentials against theuserslist orcmd. - If
false, Username/Password authentication is still offered to the client, but the credentials are not necessarily validated against the list/cmd. The comment suggests this is "to satisfy some strange software that do not work with NoAuth option of SOCKS5."
- Default value:
users(list of objects, optional): A list of predefined username/password credentials.- Each object has
username(string) andpassword(string).
- Each object has
cmd(list of strings, optional): A command to execute for validating username/password. The proxy will substitute#USER#and#PASS#with the client's provided credentials. The command should exit with status 0 for success.- Example:
["test", "#USER#", "==", "#PASS#"]
- Example:
cache(object, optional): Configures caching for authentication results fromcmd.timeout(integer): Time in seconds to cache the authentication result.- Default value:
300(seconds).
- Default value:
tls(object, optional): If present, configures TLS for the SOCKS listener (SOCKS over TLS). The structure is the same as the TLS configuration for HTTPS listeners (see Section 4.3), requiringcertandkey, and optionallyclientfor mTLS.
Example:
listeners:
- name: socks
bind: 0.0.0.0:1080
allowUdp: true # Default
enforceUdpClient: false
# overrideUdpAddress: 127.0.0.1
allowBind: false # Default - enable to support SOCKS BIND command
enforceBindAddress: true # Default - force system-allocated addresses (security mode)
auth:
required: false # Default
users:
- username: a
password: a
# cmd:
# - test
# - "#USER#"
# - ==
# - "#PASS#"
cache:
timeout: 300 # Default
# tls: # Optional SOCKS over TLS
# cert: server.crt
# key: server.key
# client:
# ca: client_ca.crt
# required: falseAvailability: This listener type is only available when the proxy is compiled with the quic feature.
The quic listener allows the proxy to accept connections over the QUIC protocol. QUIC is a modern transport protocol that offers multiplexing and security by default (TLS).
type: quic- Common Parameters:
bind. bbr(boolean, optional): Enables or disables the BBR congestion control algorithm for QUIC connections.- Default value:
true.
- Default value:
tls(object): QUIC inherently uses TLS, so this configuration is mandatory.cert(string): Path to the server's SSL/TLS certificate file (e.g.,test.crt).key(string): Path to the server's private key file (e.g.,test.key).- Note: Unlike HTTP listeners, client certificate authentication options are not shown in the example for QUIC listeners but might be supported if the underlying TLS library allows.
Example:
listeners:
- name: quic
bind: 0.0.0.0:4433
# bbr: true
tls:
cert: test.crt
key: test.keyAvailability: This listener type is only available when the proxy is compiled with the ssh feature.
The ssh listener accepts SSH connections and forwards tunneled traffic through the proxy chain using SSH's direct-tcpip channel forwarding mechanism.
type: ssh- Common Parameters:
bind. hostKeyPath(string): Path to the SSH server's private host key file (e.g.,/etc/ssh/ssh_host_ed25519_key).authorizedKeysPath(string, optional): Path to the authorized_keys file for public key authentication (e.g.,/home/user/.ssh/authorized_keys).allowPassword(boolean, optional): Enables password authentication.- Default value:
false.
- Default value:
passwordUsers(object, optional): Map of username to password for password authentication. Only effective whenallowPasswordistrue.- Example:
{"alice": "secret123", "bob": "pass456"}
- Example:
inactivityTimeoutSecs(integer, optional): SSH session inactivity timeout in seconds.- Default value:
300(5 minutes).
- Default value:
Note: At least one authentication method (authorizedKeysPath or allowPassword with passwordUsers) must be configured.
Example:
listeners:
- name: ssh-tunnel
type: ssh
bind: 0.0.0.0:2222
hostKeyPath: /etc/ssh/ssh_host_ed25519_key
# Public key authentication
authorizedKeysPath: /home/user/.ssh/authorized_keys
# Password authentication (optional)
allowPassword: true
passwordUsers:
alice: secret123
bob: pass456
inactivityTimeoutSecs: 300With this, the documentation for all listener types in the example config.yaml is complete.
The connectors section is a list that defines how the proxy makes outgoing connections to destination servers or other proxies. These are used by rules to determine the outbound path for a request.
Similar to listeners, some parameters are common across different connector types:
name(string): A descriptive name for the connector. This name is used in therulessection to specify which connector to use.type(string, optional): Explicitly defines the type of the connector. If omitted, the type might be inferred from thenamefield (e.g., "direct" might imply a direct connection). It's good practice to specifytypefor clarity.
The loadbalance connector distributes outgoing connections across a list of other configured connectors based on a specified algorithm.
type: loadbalance(or inferred ifnameis "loadbalance")connectors(list of strings): A list of names of other connectors defined in theconnectorssection that this load balancer will use.- Example:
["direct", "http"]
- Example:
algorithm(object or string): Defines the load balancing algorithm. This can be a predefined string or an object for more complex configurations.- Default value:
roundRobin - Possible string values:
random: Chooses a connector randomly from the list.roundRobin(orrr): Chooses connectors in a round-robin sequence.
- Object value (for hash-based balancing):
{hashBy: "script_string"}: Uses a Milu script to generate a string, which is then hashed to select a connector. The script has access to therequestobject.- Example:
algorithm: {hashBy: "request.source.host"}
- Example:
- Default value:
Example:
connectors:
- name: loadbalance
connectors:
- direct
- http # These should be names of other connectors defined elsewhere
algorithm: {hashBy: "request.source.host"} # or algorithm: roundRobinThe direct connector makes a direct connection to the target host.
type: direct(or inferred ifnameis "direct")bind(string, optional): Specifies a source IP address to bind to for outgoing connections and BIND operations.- Example:
"192.168.100.1" - This setting affects all connection types: TCP forward, UDP forward/bind, and TCP BIND operations.
- For BIND operations, if specified, creates the listening socket on this interface; otherwise uses the target address.
- Example:
overrideBindAddress(string, optional): Override the bind address reported to SOCKS clients for NAT scenarios.- Example:
"203.0.113.1" - Only affects the address reported in SOCKS BIND responses, not the actual bind interface.
- Useful when the proxy is behind NAT and clients need to connect to the external IP address.
- The actual listener still uses the address determined by the
bindfield or target address.
- Example:
dns(object, optional): Configures DNS resolution for this connector.servers(string): A comma-separated list of DNS server IP addresses, optionally with port numbers (e.g.,8.8.8.8:53). Special values likesystem,google,cloudflaremight also be supported to use system resolvers or predefined public DNS servers.- Default value:
"system"(uses the system's configured DNS resolvers). Other special string values"google"and"cloudflare"can also be used. - Example:
"system"or"192.168.100.1:5353,1.1.1.1,8.8.8.8:53"
- Default value:
family(string): Specifies the preferred IP address family for DNS resolution.- Possible values:
V4Only,V6Only,V4First,V6First(default). V4Only: Resolve only A records.V6Only: Resolve only AAAA records.V4First: Try A records first, then AAAA records.V6First: Try AAAA records first, then A records (this is the default).
- Possible values:
fwmark(integer, optional): If supported by the OS (Linux-specific), sets thefwmark(firewall mark) on outgoing packets from this connector. This can be used for advanced routing policies.- Availability: Linux only.
keepalive(boolean, optional): Enables or disables TCP keepalive probes for connections made by this connector.- Default value:
true.
- Default value:
Example:
connectors:
- name: direct
# bind: 192.168.100.1 # Optional source IP for all connections and BIND operations
# overrideBindAddress: 203.0.113.1 # Optional NAT override for SOCKS BIND responses
dns:
servers: system
# servers: 192.168.100.1:5353,1.1.1.1,8.8.8.8:53
family: V4Only
# fwmark: 123
# keepalive: trueThe http connector forwards traffic to an upstream HTTP or HTTPS proxy.
type: http(or inferred ifnameis "http" or "https")server(string): The hostname or IP address of the upstream proxy server.- Example:
"192.168.100.1"
- Example:
port(integer): The port number of the upstream proxy server.- Example:
7081(for HTTP) or3333(for HTTPS in the example)
- Example:
forceConnect(boolean, optional): Forces all requests to use HTTP CONNECT tunneling instead of HTTP forward proxy.- Default value:
false. - When
false, GET/POST/PUT/DELETE requests are forwarded directly as HTTP requests. - When
true, all requests (including GET/POST/PUT/DELETE) are tunneled through HTTP CONNECT. - This option is useful for compatibility with upstream proxies that only support CONNECT method.
- Default value:
tls(object, optional): If present, this section configures TLS for connecting to an HTTPS proxy.insecure(boolean):- Default value:
false. - If
true, the proxy will not verify the upstream proxy's TLS certificate. This is useful for proxies with self-signed certificates but introduces security risks (man-in-the-middle attacks).
- Default value:
ca(string, optional): Path to a CA certificate file used to verify the upstream proxy's certificate. If not provided, system CAs might be used.auth(object, optional): Configures client certificate authentication (mTLS) for connecting to the upstream proxy. This block is optional.cert(string): Path to the client certificate file.key(string): Path to the client private key file.
disableEarlyData(boolean, optional): Disables 0-RTT data in TLS 1.3 for connections to the upstream proxy.- Default value:
false.
- Default value:
Examples:
connectors:
# HTTP Connector
- name: http
server: 192.168.100.1
port: 7081
# forceConnect: false # Default: use HTTP forward proxy when possible
# HTTPS Connector with CONNECT-only mode
- name: https # 'type: http' is inferred
type: http # Can be explicitly set
server: 192.168.100.1
port: 3333
forceConnect: true # Force all requests to use CONNECT tunneling
tls:
insecure: true # Example allows self-signed certs for the upstream proxy
ca: ca.crt # Optional custom CA for upstream proxy
auth: # Optional mTLS to upstream proxy
cert: proxy.crt
key: proxy.key
# disableEarlyData: falseThe socks connector forwards traffic to an upstream SOCKS5 proxy. This can optionally be secured with TLS.
type: socks(or inferred ifnamecontains "socks")version(integer, optional): Specifies the SOCKS protocol version.- Supported values:
4,5. - Default value:
5.
- Supported values:
server(string): The hostname or IP address of the upstream SOCKS5 proxy server.- Example:
"192.168.100.1"
- Example:
port(integer): The port number of the upstream SOCKS5 proxy server.- Example:
1080(for plain SOCKS5) or9123(for SOCKS5 over TLS in the example)
- Example:
auth(object, optional): Configures username/password authentication for the upstream SOCKS5 proxy.username(string): The username for the SOCKS5 proxy.password(string): The password for the SOCKS5 proxy.
tls(object, optional): If present, this section configures TLS for connecting to a SOCKS5 proxy that supports TLS encryption (SOCKS over TLS).insecure(boolean):- Default value:
false. - If
true, the proxy will not verify the upstream SOCKS5 server's TLS certificate. - Note: The example shows
insecure: truefor thesocks-tlsconnector.
- Default value:
auth(object, optional): Configures client certificate authentication (mTLS) for the TLS connection to the upstream SOCKS proxy. This block is optional.cert(string): Path to the client certificate file.key(string): Path to the client private key file.
disableEarlyData(boolean, optional): Disables 0-RTT data in TLS 1.3 for the TLS connection to the upstream SOCKS proxy.- Default value:
false.
- Default value:
Examples:
connectors:
# Plain SOCKS5 Connector
- name: socks5-example
type: socks
version: 5
server: 192.168.100.1
port: 1080
# auth: # Optional authentication
# username: proxy
# password: somepassword
# SOCKS5 over TLS Connector
- name: socks-tls-example
type: socks
version: 5
server: 192.168.100.1
port: 9123
auth:
username: proxy
password: fuckgfw # Example credentials
tls:
insecure: true # Example allows self-signed certs for the upstream SOCKS-TLS server
# auth: # Optional mTLS for the TLS layer
# cert: client.crt
# key: client.key
# disableEarlyData: falseAvailability: This connector type is only available when the proxy is compiled with the quic feature.
The quic connector forwards traffic to an upstream server using the QUIC protocol. This is typically used when the upstream server is also a QUIC-enabled proxy or endpoint.
type: quicserver(string): The hostname or IP address of the upstream QUIC server.- Example:
"192.168.100.1"
- Example:
port(integer): The port number of the upstream QUIC server.- Example:
7081
- Example:
bind(string, optional): Specifies the local IP address and port to bind to for outgoing QUIC connections.- Default value:
"[::]:0"(any available IPv6 address, any port).
- Default value:
bbr(boolean, optional): Enables or disables the BBR congestion control algorithm for outgoing QUIC connections.- Default value:
true.
- Default value:
inline_udp(boolean, optional):- Default value:
false. - If
true, UDP traffic being forwarded over this QUIC connection will use reliable QUIC streams instead of QUIC datagrams. This can be useful if QUIC datagrams are unreliable or blocked, but it changes the nature of UDP transport (adds reliability and ordering). - If
false(default), UDP traffic is typically forwarded using QUIC datagrams, preserving the unreliable nature of UDP.
- Default value:
tls(object): QUIC connections are inherently secured with TLS.insecure(boolean):- Default value:
false. - If
true, the proxy will not verify the upstream QUIC server's TLS certificate. This is useful for servers with self-signed certificates but carries security risks. - Note: The example shows
insecure: true.
- Default value:
disableEarlyData(boolean, optional): Disables 0-RTT data in TLS 1.3 for connections to the upstream QUIC server.- Default value:
false.
- Default value:
- Client certificate authentication (mTLS) options are not shown in the example but might be configurable depending on the proxy's capabilities.
Example:
connectors:
- name: quic-example
type: quic
server: 192.168.100.1
port: 7081
# bind: "[::]:0"
# bbr: true
inline_udp: false
tls:
insecure: true
# disableEarlyData: falseAvailability: This connector type is only available when the proxy is compiled with the ssh feature.
The ssh connector tunnels traffic to upstream servers through an SSH connection using direct-tcpip channel forwarding. Each connection creates a new SSH session to avoid head-of-line blocking issues inherent in SSH's TCP-based transport.
type: sshserver(string): The hostname or IP address of the SSH server.- Example:
"ssh.example.com"
- Example:
port(integer): The SSH server port.- Default value:
22.
- Default value:
username(string): SSH username for authentication.auth(object): SSH authentication configuration.- Password Authentication:
type: passwordpassword(string): The password for authentication.
- Private Key Authentication:
type: privateKeypath(string): Path to the private key file (e.g.,~/.ssh/id_ed25519).passphrase(string, optional): Passphrase for encrypted private keys.
- Password Authentication:
serverKeyVerification(object): Server key verification configuration.- Fingerprint Verification (recommended for production):
type: fingerprintfingerprint(string): Expected SHA256 fingerprint of the server's host key (e.g.,"SHA256:xUnNap5CE8FOAAr6+lhzLgkXBgYRoUexlLotEOhDgr4").
- Insecure Mode (development only):
type: insecureAcceptAny⚠️ Warning: This disables host key verification and should ONLY be used in development environments.
- Fingerprint Verification (recommended for production):
inactivityTimeoutSecs(integer, optional): SSH session inactivity timeout in seconds.- Default value:
60.
- Default value:
Getting SSH Server Fingerprints:
Use ssh-keyscan to get the server's fingerprint:
# Get SHA256 fingerprint
ssh-keyscan -H example.com 2>/dev/null | ssh-keygen -lf - -E sha256
# Output: 256 SHA256:xUnNap5CE8FOAAr6+lhzLgkXBgYRoUexlLotEOhDgr4 example.com (ED25519)Example:
connectors:
# Password authentication
- name: ssh-password
type: ssh
server: ssh.example.com
port: 22
username: proxyuser
auth:
type: password
password: secretpass123
serverKeyVerification:
type: fingerprint
fingerprint: "SHA256:xUnNap5CE8FOAAr6+lhzLgkXBgYRoUexlLotEOhDgr4"
inactivityTimeoutSecs: 60
# Private key authentication
- name: ssh-key
type: ssh
server: ssh.example.com
port: 22
username: proxyuser
auth:
type: privateKey
path: ~/.ssh/id_ed25519
# passphrase: optional_passphrase
serverKeyVerification:
type: fingerprint
fingerprint: "SHA256:xUnNap5CE8FOAAr6+lhzLgkXBgYRoUexlLotEOhDgr4"
# Development mode (INSECURE - do not use in production!)
- name: ssh-dev
type: ssh
server: test-server.local
port: 22
username: testuser
auth:
type: password
password: testpass
serverKeyVerification:
type: insecureAcceptAny # ⚠️ Development only!With this, the documentation for all connector types in the example config.yaml is complete.
The rules section is a list that defines how incoming requests are processed and routed to different connectors. Rules are evaluated in the order they are defined. The first rule that matches a request determines its fate.
Each rule object in the list consists of a filter (optional) and a target.
filter(string, optional): An expression that is evaluated against the request's properties. If the expression evaluates to true, the rule matches. Iffilteris omitted, the rule matches all requests (acting as a default or fallback rule).- Filter Expressions: The expressions can use variables related to the request and various functions.
- Available Variables (based on example comments):
request.source: Likely a string representing the source IP and port (e.g., "192.168.1.100:12345").request.target.host: The requested hostname or IP address.request.target.port: The requested port number (as an integer).request.target.type: The type of the target, e.g., "domain", "ipv4", "ipv6".request.listener: The name of the listener that received the request.request.feature: Special features associated with the request, e.g., "UdpForward" for SOCKS5 UDP associations.
- Operators:
==(equality)!=(inequality)=~(regex match, e.g.,request.source =~ "127.0.0.1")||(logical OR)and(logical AND) - Note: example usesand, typical YAML/ scripting might also support&&.
- Available Functions (based on example comments):
cidr_match(request.target.host, "127.0.0.0/8"): Matches if the host IP falls within the given CIDR range.split(str, delimiter) -> [str]: Splits a string into a list of strings.to_string(any) -> str: Converts a value to a string.to_integer(str) -> int: Converts a string to an integer.
- Available Variables (based on example comments):
- Note: The exact syntax and available properties/functions should be verified from the proxy's core logic or more detailed developer documentation if available.
- Filter Expressions: The expressions can use variables related to the request and various functions.
target(string): Specifies the action to take if the filter matches.- This is usually the
nameof a connector defined in theconnectorssection. The request will be forwarded using that connector. - Special Target
deny: Iftargetis set to"deny", the request is explicitly blocked.
- This is usually the
Rule Evaluation Logic:
- Rules are processed from top to bottom.
- The first rule where the
filterevaluates totrue(or if the filter is absent) is applied. - If a request does not match any rule in the list, access is denied by default. Therefore, it's common to have a final "catch-all" rule (e.g., one with no filter or
filter: true) that specifies a default connector.
Examples from config.yaml:
rules:
# Deny requests to loopback CIDR or localhost domain
# - filter: cidr_match(request.target.host,"127.0.0.0/8") || request.target.host == "localhost"
# target: deny
# Route requests for domain type targets to 'loadbalance' connector
# - filter: request.target.type == "domain"
# target: loadbalance
# Route SOCKS5 UDP forwarding requests to 'quic' connector
- filter: request.feature == "UdpForward"
target: quic
# Route requests from localhost to 'direct' connector
- filter: request.source.host == "127.0.0.1"
target: direct
# Route requests from 127.0.0.1 to google.com via 'direct' connector
- filter: request.source =~ "127.0.0.1" and request.target =~ "google.com"
target: direct
# Route IPv6 targets to 'https' connector
- filter: request.target.type == "ipv6"
target: https
# Deny requests to "deny-me.com"
- filter: request.target =~ "deny-me.com"
target: deny
# Default rule: all other requests go to 'direct' connector
- target: directThe SOCKS BIND command allows clients to create listening sockets for incoming connections, commonly used by FTP clients and other protocols requiring reverse connections. This section provides practical configuration examples for different BIND scenarios.
listeners:
- name: socks-with-bind
type: socks
bind: "0.0.0.0:1080"
allowBind: true # Enable BIND command support
enforceBindAddress: false # Allow client bind requests (less secure, but normal SOCKS behavior)
allowUdp: true # Standard UDP associate support
connectors:
- name: direct
type: direct
# Uses target address for BIND operations by default
rules:
- target: direct # Default rule for all requestslisteners:
- name: socks-bind-controlled
type: socks
bind: "0.0.0.0:1081"
allowBind: true
enforceBindAddress: false
connectors:
- name: direct-with-bind
type: direct
bind: "192.168.1.100" # BIND operations will use this interface
dns:
servers: system
rules:
- target: direct-with-bindlisteners:
- name: socks-nat-bind
type: socks
bind: "0.0.0.0:1082"
allowBind: true
enforceBindAddress: false
connectors:
- name: direct-nat
type: direct
bind: "192.168.1.100" # Internal interface for actual binding
overrideBindAddress: "203.0.113.50" # External IP reported to clients
rules:
- target: direct-natlisteners:
# Standard BIND for internal clients
- name: socks-internal-bind
type: socks
bind: "192.168.1.1:1080"
allowBind: true
enforceBindAddress: false
# Strict BIND for external clients
- name: socks-external-bind
type: socks
bind: "0.0.0.0:1081"
allowBind: true
enforceBindAddress: true # Force system-allocated addresses (security mode)
auth:
required: true
users:
- username: external_user
password: secure_pass
connectors:
- name: direct-internal
type: direct
bind: "192.168.1.1"
- name: direct-external
type: direct
bind: "203.0.113.50"
overrideBindAddress: "203.0.113.50"
rules:
# Route internal network to internal connector
- filter: 'request.listener == "socks-internal-bind"'
target: direct-internal
# Route external clients to external connector
- filter: 'request.listener == "socks-external-bind"'
target: direct-externallisteners:
- name: socks-secure-bind
type: socks
bind: "0.0.0.0:1443"
allowBind: true
enforceBindAddress: false
auth:
required: true
users:
- username: bind_user
password: bind_pass
cache:
timeout: 600
tls:
cert: socks_server.crt
key: socks_server.key
client:
ca: client_ca.crt
required: true
connectors:
- name: direct-secure
type: direct
bind: "10.0.0.100"
rules:
- target: direct-securelisteners:
- name: socks-no-bind
type: socks
bind: "0.0.0.0:1080"
allowBind: false # BIND requests will be rejected (default)
allowUdp: true # UDP associate still works
connectors:
- name: direct
type: direct
rules:
- target: directlisteners:
- name: socks-lb-bind
type: socks
bind: "0.0.0.0:1080"
allowBind: true
enforceBindAddress: false
connectors:
- name: direct-primary
type: direct
bind: "192.168.1.10"
- name: direct-secondary
type: direct
bind: "192.168.1.20"
- name: bind-loadbalancer
type: loadbalance
connectors: ["direct-primary", "direct-secondary"]
algorithm: roundRobin
rules:
# Use load balancer for BIND operations
- filter: 'request.feature == "TcpBind"'
target: bind-loadbalancer
# Regular connections use primary
- target: direct-primaryConfiguration Notes:
-
Security: Always use authentication (
auth.required: true) for BIND-enabled listeners exposed to untrusted networks. -
NAT Scenarios: Use
overrideBindAddresswhen the proxy is behind NAT to ensure clients connect to the correct external address. -
Interface Selection: The
bindfield in DirectConnector now consistently affects all operations including TCP BIND. -
Address Control: Setting
enforceBindAddress: true(default) forces system-allocated addresses for security. Setting tofalsehonors client bind requests. -
Protocol Support: BIND currently supports TCP connections. UDP BIND operations depend on the connector's UDP capabilities.
The entire accessLog section is optional. The accessLog section configures how and where access logs are written.
path(string): Specifies the file path where access logs will be written.- Example:
access.log(writes to a file namedaccess.login the proxy's working directory).
- Example:
format(string or object): Defines the format of the log entries. This can be a simple string or a structured object depending on the desired format.- JSON Format: To output logs in JSON.
- Example:
format: json
- Example:
- Script Format: To use a custom Milu script template for formatting. The script should evaluate to a string.
- Example:
format: script: "`src=${request.source} dst=${request.target} listener=${request.listener} connector=${request.connector}`"
- Note: The Milu script has access to the same
requestobject available in rule filters.
- Example:
- JSON Format: To output logs in JSON.
Example:
accessLog:
path: access.log
# Example for JSON format
format: json
# Example for Script format
# format:
# script: "`src=${request.source} dst=${request.target} listener=${request.listener} connector=${request.connector}`"[end of CONFIG_GUIDE.md]