OpenVPN — sing-box
sing-box speaks OpenVPN natively through two endpoints — openvpn-client and openvpn-server under endpoints[] — plus an openvpn DNS server that resolves through the resolvers a server pushes to the client. Both endpoints interoperate with standard OpenVPN peers, including static-key mode, legacy ciphers and digests, and OpenVPN-style certificate checks.
Build tags
OpenVPN is only compiled in with the with_openvpn build tag; the default internal network stack (system: false) also needs with_gvisor. Without them the endpoints and the DNS server fail at startup with a rebuild hint.
Shared interface fields
Both endpoints embed these fields:
| Field | Type | Default | Allowed values | Description |
|---|---|---|---|---|
system | bool | false | true | false | Use a system interface (needs privileges and must not clash with an existing interface). Addresses and MTU are configured on it, but no operating-system routes or DNS. false uses the internal network stack. |
name | string | (auto, ovpn…) | <interface name> | Interface name when system is true. |
mtu | uint32 | 1500 | <bytes> | Tunnel interface MTU. On the client, 1500 is used until the server pushes a value. |
udp_mapping | UDPNATBehavior | endpoint_independent | endpoint_independent | address_dependent | address_and_port_dependent | UDP NAT mapping: reuse one mapping per source address and port for all destinations (default), or a separate mapping per destination address / address and port. |
udp_filtering | UDPNATBehavior | endpoint_independent | endpoint_independent | address_dependent | address_and_port_dependent | UDP NAT filtering: accept packets from any remote endpoint (default), or only from addresses / address-and-port pairs already sent to. |
udp_nat_max | uint32 | 0 (auto) | <uint32> | Maximum number of UDP NAT sessions; the least recently used one is closed when full. 0 means 4096 on iOS, otherwise 4096–16384 based on total memory. |
Source: option/openvpn.go:10-17 · pinned at v1.14.2 (af6e64c)
Client endpoint (openvpn-client)
type: "openvpn-client" under endpoints[]. Besides the fields below it takes server / server_port (conflicting with servers) and the dial fields, which apply to the connection to the OpenVPN server.
Connection and addressing
| Field | Type | Default | Allowed values | Description |
|---|---|---|---|---|
mode | string | tls | tls | static_key | Session mode. static_key is a deprecated compatibility mode without a TLS control channel or forward secrecy; it ignores tls, username/password, pulled options and renegotiation. |
network | string | udp | udp | tcp | udp4 | udp6 | tcp4 | tcp6 | Default transport to the server. Applies to server and to servers entries without their own network. |
servers | []OpenVPNRemoteOptions | [] | [{server, server_port, network}] | Servers tried in order, moving on when a connection fails. Each entry needs server and server_port and may override network. Conflicts with the top-level server; one of the two is required. |
remote_random | bool | false | true | false | Shuffle servers before connecting. |
address | badoption.Listable[netip.Prefix] | [] | [<CIDR>] | Local IPv4 / IPv6 tunnel prefixes. Required in static_key mode; optional in TLS mode, where the server can push them. |
peer_address | *badoption.Addr | (unset) | <IPv4> | IPv4 tunnel peer and VPN gateway. Required with an IPv4 address in static_key mode. |
peer_address_ipv6 | *badoption.Addr | (unset) | <IPv6> | IPv6 tunnel peer and VPN gateway. Required with an IPv6 address in static_key mode. |
topology | string | (pushed) | net30 | p2p | subnet | Tunnel topology. Empty uses the topology pushed by the server in TLS mode. |
udp_timeout | UDPTimeoutCompat | 5m | <duration> | UDP NAT session timeout for traffic through the tunnel. |
explicit_exit_notify | uint32 | 0 | <count> | Number of exit notifications sent one second apart when closing a UDP connection. 0 disables them. |
Source: option/openvpn.go:19-73 · pinned at v1.14.2 (af6e64c)
Authentication and keys
| Field | Type | Default | Allowed values | Description |
|---|---|---|---|---|
username | string | (unset) | <string> | Username for OpenVPN username/password authentication. TLS mode only. |
password | string | (unset) | <string> | Password for username/password authentication. |
auth_retry | string | none | none | nointeract | interact | Behaviour after an authentication failure: none treats it as final; nointeract and interact allow retries. |
static_challenge | string | (unset) | <text> | Static challenge text shown when an authentication response (for example a one-time code) is requested. |
static_challenge_echo | bool | false | true | false | Show the static-challenge response as plain text while it is entered. |
static_key | badoption.Listable[string] | (unset) | <key content> | OpenVPN static key content. Required in static_key mode unless static_key_path is set; conflicts with it. |
static_key_path | string | (unset) | <path> | Path to the OpenVPN static key file. Conflicts with static_key. |
key_direction | string | (bidirectional) | server | client | Static key direction, static_key mode only. Empty uses the key in both directions. |
tls | *OpenVPNOutboundTLSOptions | (required in tls mode) | OpenVPNOutboundTLSOptions | Control-channel TLS configuration; see the tls table below. |
Source: option/openvpn.go:19-73 · pinned at v1.14.2 (af6e64c)
Data channel
| Field | Type | Default | Allowed values | Description |
|---|---|---|---|---|
cipher | string | BF-CBC | <cipher name> | Data-channel cipher for static_key mode only. The upstream default BF-CBC is a legacy 64-bit-block cipher — set the server's cipher explicitly. NONE gives no confidentiality. |
data_ciphers | badoption.Listable[string] | AES-256-GCM, AES-128-GCM, CHACHA20-POLY1305 | [<cipher name>] | Data-channel ciphers allowed during negotiation. TLS mode only. Legacy CBC / CFB / OFB ciphers and NONE exist but are not enabled by default. |
data_ciphers_fallback | string | (disabled) | <cipher name> | Cipher used with servers that cannot negotiate one. TLS mode only. |
auth | string | SHA1 | <digest name> | Data-channel HMAC digest. Only applies to non-AEAD ciphers and tls_auth; legacy digests such as MD5 and RIPEMD160 are accepted when set explicitly. |
mss_fix | uint32 | (OpenVPN default) | <bytes> | Maximum OpenVPN packet size used to clamp the MSS of TCP connections in the tunnel. Empty uses the upstream default: fragment if set, otherwise 1492 or the configured tunnel MTU. |
mss_fix_disabled | bool | false | true | false | Disable MSS clamping, including the default clamp. Conflicts with mss_fix and mss_fix_mode. |
mss_fix_mode | string | (encapsulation-aware) | mtu | fixed | How an explicit mss_fix is interpreted: mtu also counts the outer IP and UDP/TCP headers; fixed treats it as an inner IPv4 packet size. Requires mss_fix. |
fragment | uint32 | 0 | 0 | >= 68 | Maximum UDP packet size for OpenVPN's own data-channel fragmentation. 0 disables it; not allowed with a TCP transport. |
replay_window | uint32 | 64 | <= 65536 | UDP data-channel replay window size. TCP always requires consecutive packet IDs. |
replay_window_time | badoption.Duration | 15s | <= 10m, whole seconds | UDP data-channel replay window duration. |
compression | string | (disabled) | none | no | lz4 | lz4-v2 | stub | stub-v2 | disabled | off | OpenVPN compress framing. Compression can weaken confidentiality; prefer stub / stub-v2 when only framing compatibility is needed. |
compression_lzo | string | (disabled) | none | no | yes | adaptive | asym | disabled | off | OpenVPN comp-lzo mode. Enable it only when the server requires it. |
allow_compression | string | no | no | asym | yes | Policy for compression pushed by the server: no allows only stub framing; asym accepts compressed packets but never compresses outgoing ones; yes is a legacy alias for asym. |
Source: option/openvpn.go:19-73 · pinned at v1.14.2 (af6e64c)
Pushed options and routing
| Field | Type | Default | Allowed values | Description |
|---|---|---|---|---|
route_no_pull | bool | false | true | false | Ignore routes, DNS / DHCP options, route metrics, redirect-gateway, redirect-private, block-ipv6 and block-outside-dns pushed by the server. Addressing, topology and MTU are still applied. |
pull_filters | []OpenVPNPullFilterOptions | [] | [{action, text}] | Ordered filters for pushed options; see the pull_filters[] table below. |
routes | badoption.Listable[netip.Prefix] | [] | [<CIDR>] | Extra prefixes preferred for this endpoint in sing-box routing, on top of routes accepted from the server. No operating-system routes are installed. |
route_gateway | *badoption.Addr | (pushed gateway) | <IPv4> | IPv4 gateway for routes through the endpoint. Kept for OpenVPN compatibility; route preference is prefix-based. |
route_metric | int | 0 | <int> | Default route metric. Kept for OpenVPN compatibility; no system route is installed. |
redirect_gateway | bool | false | true | false | Prefer this endpoint for all IPv4 destinations in sing-box routing. No operating-system default route is installed. |
redirect_gateway_flags | badoption.Listable[string] | [] | !ipv4 | def1 | ipv6 | local | autolocal | OpenVPN redirect-gateway flags: !ipv4 drops the IPv4 preference, def1 expresses it as two /1 prefixes, ipv6 also prefers IPv6. block-local is unsupported; bypass-dhcp / bypass-dns do not apply. |
redirect_private | bool | false | true | false | Accept redirect_gateway_flags without adding a default-route preference. |
block_ipv6 | bool | false | true | false | Reject IPv6 traffic locally instead of sending it through the VPN. |
Source: option/openvpn.go:19-73 · pinned at v1.14.2 (af6e64c)
Timers and renegotiation
| Field | Type | Default | Allowed values | Description |
|---|---|---|---|---|
ping_interval | badoption.Duration | (disabled) | <duration> | Send a data-channel ping after this long without sending to the server. A server-pushed ping overrides it. Whole seconds. |
ping_restart | badoption.Duration | 120s (UDP, pull) | <duration> | Reconnect after this long without receiving a packet. A server-pushed ping-restart overrides it; TCP has no default. Whole seconds. |
ping_restart_disabled | bool | false | true | false | Disable the initial 120s UDP pull timeout and any local ping_restart. Conflicts with ping_restart. |
renegotiate_interval | badoption.Duration | 1h | <duration> | TLS renegotiation interval. |
renegotiate_disabled | bool | false | true | false | Disable time-based TLS renegotiation, including the default interval. Conflicts with renegotiate_interval. |
renegotiate_bytes | uint64 | 0 | <bytes> | Renegotiate data-channel keys after this many bytes. 0 uses the cipher-dependent OpenVPN default. |
renegotiate_packets | uint64 | 0 | <packets> | Renegotiate data-channel keys after this many packets. 0 uses the cipher-dependent OpenVPN default. |
tls_timeout | badoption.Duration | 2s | <duration> | Initial retransmission timeout for TLS control packets. |
handshake_window | badoption.Duration | 1m | <duration> | Maximum time for the initial TLS handshake and each renegotiation. |
Source: option/openvpn.go:19-73 · pinned at v1.14.2 (af6e64c)
pull_filters[]
| Field | Type | Default | Allowed values | Description |
|---|---|---|---|---|
action | string | (required) | accept | ignore | reject | accept applies the matched option, ignore discards it, reject terminates the connection. |
text | string | (required) | <prefix> | Case-sensitive prefix of the complete pushed option. The first matching filter wins; unmatched options are accepted. "route " matches pushed IPv4 routes but not route-gateway. |
Source: option/openvpn.go:117-120 · pinned at v1.14.2 (af6e64c)
tls
| Field | Type | Default | Allowed values | Description |
|---|---|---|---|---|
server_name | string | (unset) | <name> | Expected server certificate name. Empty disables the name check; the chain or fingerprint and the certificate purpose are still verified. |
server_name_type | string | name | subject | name | name-prefix | Certificate field matched by server_name: the full subject, the exact common name, or a common-name prefix. |
certificate | badoption.Listable[string] | (unset) | <PEM> | Trusted CA certificate content. One of certificate, certificate_path or peer_fingerprint is required; conflicts with certificate_path. |
certificate_path | string | (unset) | <path> | Trusted CA certificate path. Conflicts with certificate. |
client_certificate | badoption.Listable[string] | (unset) | <PEM> | Client certificate content; set it together with a client key. Conflicts with client_certificate_path. |
client_certificate_path | string | (unset) | <path> | Client certificate path. Conflicts with client_certificate. |
client_key | badoption.Listable[string] | (unset) | <PEM> | Client private key content. Conflicts with client_key_path. |
client_key_path | string | (unset) | <path> | Client private key path. Conflicts with client_key. |
peer_fingerprint | badoption.Listable[string] | [] | [<64 lowercase hex chars>] | Allowed SHA-256 fingerprints of the server leaf certificate. With a trusted CA both are checked; without one the chain itself is not verified. |
crl_path | string | (unset) | <path> | PEM or DER certificate revocation list used to reject revoked server certificates. |
remote_certificate_ku | badoption.Listable[string] | [] | [<hex mask>] | Required key-usage masks in OpenVPN remote-cert-ku format; the certificate must contain all bits of at least one mask. |
remote_certificate_eku | string | (unset) | <OID or name> | server | client | Required extended key usage. Replaces the default remote_certificate_tls check and conflicts with an explicit one. |
remote_certificate_tls | string | server | server | client | none | Certificate purpose check on the server certificate; none disables it. |
certificate_profile | string | legacy | insecure | legacy | preferred | suiteb | Certificate strength profile: insecure also accepts MD5 / SHA-1 chains and small keys, legacy accepts SHA-1 but not MD5, preferred requires stronger signatures and keys, suiteb defaults the TLS 1.2 ciphers to Suite B. |
ns_certificate_type | string | (disabled) | server | client | Deprecated Netscape certificate type check. Prefer remote_certificate_tls. |
version_min | string | 1.2 | 1.0 | 1.1 | 1.2 | 1.3 | Minimum TLS version. |
version_max | string | (highest supported) | 1.0 | 1.1 | 1.2 | 1.3 | Maximum TLS version; cannot be lower than version_min. |
cipher | string | (default suites) | <OpenSSL names, colon-separated> | Cipher suites for TLS 1.2 and earlier. TLS 1.3 suites are not affected. |
groups | string | (default groups) | X25519 | SECP256R1 | SECP384R1 | SECP521R1 | Key-exchange groups in preference order, colon-separated. |
control_wrap | *OpenVPNControlWrapOptions | (disabled) | OpenVPNControlWrapOptions | Control-channel wrapping (tls-auth / tls-crypt / tls-crypt-v2); see the next table. |
Source: option/openvpn.go:122-143 · pinned at v1.14.2 (af6e64c)
tls.control_wrap
| Field | Type | Default | Allowed values | Description |
|---|---|---|---|---|
type | string | (required when set) | tls_auth | tls_crypt | tls_crypt_v2 | Wrapping type, matching OpenVPN tls-auth, tls-crypt and tls-crypt-v2. |
key | badoption.Listable[string] | (unset) | <key content> | Wrapping key content. Conflicts with key_path. |
key_path | string | (unset) | <path> | Wrapping key path. Conflicts with key. |
direction | string | (bidirectional) | server | client | tls_auth key direction; only with type tls_auth. Empty uses the key in both directions. |
Source: option/openvpn.go:169-174 · pinned at v1.14.2 (af6e64c)
Server endpoint (openvpn-server)
type: "openvpn-server" under endpoints[], plus the listen fields (listen, listen_port, and udp_timeout for UDP NAT sessions).
Session and addressing
| Field | Type | Default | Allowed values | Description |
|---|---|---|---|---|
mode | string | tls | tls | static_key | Session mode. static_key serves a single peer without TLS or forward secrecy and ignores tls, users, push and renegotiation options. |
network | string | udp | udp | tcp | Transport served by this endpoint. One network per endpoint — use two endpoints with separate address subnets to serve both. |
remote | string | (unset) | <address> | Fixed peer address for a UDP static_key server, required together with remote_port. TCP servers take the peer from the accepted socket. |
remote_port | uint16 | (unset) | <port> | Fixed peer port for a UDP static_key server. |
max_clients | int | 1024 | < 16777216 | Maximum established plus pending TLS sessions. static_key mode supports one peer, so it must be 0 or 1 there. |
address | badoption.Listable[netip.Prefix] | (required) | [<CIDR>] | Server prefixes, at most one IPv4 and one IPv6. The prefix address goes on the server interface and the masked prefix becomes the client pool and route. In static_key mode these are the local tunnel prefixes. |
peer_address | *badoption.Addr | (unset) | <IPv4> | IPv4 tunnel peer address. Required with an IPv4 address in static_key mode. |
peer_address_ipv6 | *badoption.Addr | (unset) | <IPv6> | IPv6 tunnel peer address. Required with an IPv6 address in static_key mode. |
topology | string | subnet (tls) / p2p (static_key) | subnet | p2p | net30 | Topology pushed to clients. |
duplicate_cn | bool | false | true | false | Allow several active clients with the same certificate common name or username. When off, a new session replaces the old one and reuses its address. TLS mode only. |
users | []auth.User | [] | [{username, password}] | Username/password users. When set, clients must pass this check in addition to the certificate policy. TLS mode only. |
Source: option/openvpn.go:75-110 · pinned at v1.14.2 (af6e64c)
Keys and data channel
| Field | Type | Default | Allowed values | Description |
|---|---|---|---|---|
static_key | badoption.Listable[string] | (unset) | <key content> | OpenVPN static key content. Required in static_key mode unless static_key_path is set; conflicts with it. |
static_key_path | string | (unset) | <path> | Path to the OpenVPN static key file. Conflicts with static_key. |
key_direction | string | (bidirectional) | server | client | Static key direction, static_key mode only. Conventionally the server uses server and the peer uses client. |
tls | *OpenVPNInboundTLSOptions | (required in tls mode) | OpenVPNInboundTLSOptions | Control-channel TLS configuration; see the server tls table below. |
cipher | string | BF-CBC | <cipher name> | Data-channel cipher for static_key mode only. BF-CBC is the legacy upstream default; NONE gives no confidentiality. |
data_ciphers | badoption.Listable[string] | AES-256-GCM, AES-128-GCM, CHACHA20-POLY1305 | [<cipher name>] | Data-channel ciphers offered during negotiation. TLS mode only. Legacy ciphers exist but are not enabled by default. |
data_ciphers_fallback | string | (disabled) | <cipher name> | Cipher for legacy clients that cannot negotiate one (OpenVPN data-ciphers-fallback). TLS mode only. |
auth | string | SHA1 | <digest name> | Data-channel HMAC digest, matching the upstream default. Only applies to non-AEAD ciphers and tls_auth. |
mss_fix | uint32 | (OpenVPN default) | <bytes> | Maximum encapsulated packet size used to clamp TCP MSS; the default calculation uses 1492 with the default MTU. |
mss_fix_disabled | bool | false | true | false | Disable MSS clamping, including the default clamp. |
mss_fix_mode | string | (encapsulation-aware) | mtu | fixed | How an explicit mss_fix is interpreted. Requires mss_fix. |
replay_window | uint32 | 64 | <= 65536 | UDP data-channel replay window size; TCP packet IDs stay strictly consecutive. |
replay_window_time | badoption.Duration | 15s | <duration> | UDP replay window duration. Whole seconds. |
Source: option/openvpn.go:75-110 · pinned at v1.14.2 (af6e64c)
Push and timers
| Field | Type | Default | Allowed values | Description |
|---|---|---|---|---|
push | *OpenVPNPushOptions | (unset) | OpenVPNPushOptions | Options pushed to clients; see the push table below. |
ping_interval | badoption.Duration | (disabled) | <duration> | Server side: send a ping after this long without sending to a client. Use push.ping_interval for clients. Whole seconds. |
ping_restart | badoption.Duration | (disabled) | <duration> | Server side: close a client session after this long without receiving from it. Keep it longer than the client's timeout. Whole seconds. |
renegotiate_interval | badoption.Duration | 1h | <duration> | TLS renegotiation interval. TLS mode only. |
renegotiate_disabled | bool | false | true | false | Disable time-based TLS renegotiation, including the default interval. TLS mode only. |
renegotiate_bytes | uint64 | 0 | <bytes> | Renegotiate data-channel keys after this many bytes; 0 uses the cipher-dependent default. TLS mode only. |
renegotiate_packets | uint64 | 0 | <packets> | Renegotiate data-channel keys after this many packets; 0 uses the cipher-dependent default. TLS mode only. |
handshake_window | badoption.Duration | 1m | <duration> | Maximum time for the initial TLS handshake and each renegotiation. TLS mode only. |
Source: option/openvpn.go:75-110 · pinned at v1.14.2 (af6e64c)
tls
| Field | Type | Default | Allowed values | Description |
|---|---|---|---|---|
certificate | badoption.Listable[string] | (required) | <PEM> | Server certificate content. certificate or certificate_path is required; they conflict. |
certificate_path | string | (required) | <path> | Server certificate path. Conflicts with certificate. |
key | badoption.Listable[string] | (required) | <PEM> | Server private key content. key or key_path is required; they conflict. |
key_path | string | (required) | <path> | Server private key path. Conflicts with key. |
client_certificate | badoption.Listable[string] | (unset) | <PEM> | CA certificate content used to verify client certificates. With verify_client_certificate require or optional, one of client_certificate, client_certificate_path or peer_fingerprint is required. |
client_certificate_path | string | (unset) | <path> | CA certificate path used to verify client certificates. Conflicts with client_certificate. |
verify_client_certificate | string | require | require | optional | none | Client certificate policy: optional verifies a certificate when one is presented, none does not request one. users are still checked when set. |
client_name | string | (unset) | <name> | Expected client certificate name. Empty disables the check. |
client_name_type | string | name | subject | name | name-prefix | Certificate field matched by client_name. |
peer_fingerprint | badoption.Listable[string] | [] | [<64 lowercase hex chars>] | Allowed SHA-256 fingerprints of client leaf certificates; works without a client CA. |
crl_path | string | (unset) | <path> | Certificate revocation list used to reject revoked client certificates. |
remote_certificate_ku | badoption.Listable[string] | [] | [<hex mask>] | Required client key-usage masks in OpenVPN remote-cert-ku format. |
remote_certificate_eku | string | (unset) | <OID or name> | server | client | Required client extended key usage. Conflicts with an explicit remote_certificate_tls. |
remote_certificate_tls | string | client | server | client | none | Certificate purpose check on client certificates; none disables it. |
certificate_profile | string | legacy | insecure | legacy | preferred | suiteb | Certificate strength profile, same meaning as on the client. |
ns_certificate_type | string | (disabled) | server | client | Deprecated Netscape certificate type check. |
version_min | string | 1.2 | 1.0 | 1.1 | 1.2 | 1.3 | Minimum TLS version. |
version_max | string | (highest supported) | 1.0 | 1.1 | 1.2 | 1.3 | Maximum TLS version. |
cipher | string | (default suites) | <OpenSSL names, colon-separated> | Cipher suites for TLS 1.2 and earlier. TLS 1.3 suites are not affected. |
groups | string | (default groups) | X25519 | SECP256R1 | SECP384R1 | SECP521R1 | Key-exchange groups in preference order, colon-separated. |
control_wrap | *OpenVPNInboundControlWrapOptions | (disabled) | OpenVPNInboundControlWrapOptions | Control-channel wrapping; see the next table. |
Source: option/openvpn.go:145-167 · pinned at v1.14.2 (af6e64c)
tls.control_wrap
| Field | Type | Default | Allowed values | Description |
|---|---|---|---|---|
type | string | (required) | tls_auth | tls_crypt | tls_crypt_v2 | Wrapping type. For tls_crypt_v2 the key is the server key. |
key | badoption.Listable[string] | (unset) | <key content> | Wrapping key content. key or key_path is required; they conflict. |
key_path | string | (unset) | <path> | Wrapping key path. Conflicts with key. |
direction | string | (bidirectional) | server | client | tls_auth key direction: server maps to OpenVPN key-direction 0, client to 1. Empty uses the key in both directions. |
force_cookie | bool | false | true | false | tls_crypt_v2 only: require UDP clients to support stateless session cookies. When off, clients without cookie support are still accepted. |
Source: option/openvpn.go:176-182 · pinned at v1.14.2 (af6e64c)
push
| Field | Type | Default | Allowed values | Description |
|---|---|---|---|---|
routes | badoption.Listable[netip.Prefix] | [] | [<CIDR>] | Routes pushed to clients; IPv4 and IPv6 may be mixed. |
dns | badoption.Listable[netip.Addr] | [] | [<IP>] | DNS servers pushed as legacy dhcp-option DNS / DNS6. A pushed modern server group overrides them on compatible clients. |
dns_servers | []OpenVPNPushDNSServerOptions | [] | [{priority, addresses, resolve_domains, dnssec, transport, sni}] | Modern DNS server groups. addresses take IP or IP:port ([IPv6]:port); transport is plain, dot or doh; dnssec is yes, optional or no. Clients use only the group with the lowest priority number. |
search_domains | badoption.Listable[string] | [] | [<domain>] | Modern search domains to push. |
dhcp_options | badoption.Listable[string] | [] | [<option>] | Extra legacy dhcp-option values, without the dhcp-option prefix. |
redirect_gateway | bool | false | true | false | Push redirect-gateway so clients route their traffic through the VPN. |
redirect_gateway_flags | badoption.Listable[string] | def1 | [<flag>] | redirect-gateway flags to push; only used with redirect_gateway. |
block_outside_dns | bool | false | true | false | Push block-outside-dns, which blocks DNS outside the VPN on Windows clients. |
ping_interval | badoption.Duration | (disabled) | <duration> | OpenVPN ping interval pushed to clients. Whole seconds. |
ping_restart | badoption.Duration | (disabled) | <duration> | OpenVPN ping-restart timeout pushed to clients. Whole seconds. |
Source: option/openvpn.go:184-195 · pinned at v1.14.2 (af6e64c)
DNS server (openvpn)
type: "openvpn" under dns.servers[]:
| Field | Type | Default | Allowed values | Description |
|---|---|---|---|---|
endpoint | string | (required) | <openvpn-client tag> | Tag of the openvpn-client endpoint whose pushed resolvers are used. Queries are sent through that endpoint. |
accept_default_resolvers | bool | false | true | false | Use the pushed resolvers for queries that match no pushed resolve-domains, DOMAIN-ROUTE or search-domain suffix. When off, such queries get NXDOMAIN. |
accept_search_domain | bool | false | true | false | Retry single-label queries (such as intranet) with each pushed search domain until one resolves. |
Source: option/openvpn.go:206-210 · pinned at v1.14.2 (af6e64c)
Examples
Client with certificate authentication and tls-crypt, routing one subnet through the tunnel and resolving the server's internal names through the pushed resolvers:
{
"endpoints": [
{
"type": "openvpn-client",
"tag": "ovpn-client",
"server": "vpn.example.com",
"server_port": 1194,
"network": "udp",
"tls": {
"certificate_path": "/etc/openvpn/ca.crt",
"client_certificate_path": "/etc/openvpn/client.crt",
"client_key_path": "/etc/openvpn/client.key",
"control_wrap": { "type": "tls_crypt", "key_path": "/etc/openvpn/tc.key" }
}
}
],
"dns": {
"servers": [
{ "type": "local", "tag": "local" },
{ "type": "openvpn", "tag": "ovpn-dns", "endpoint": "ovpn-client", "accept_default_resolvers": true }
],
"rules": [
{ "preferred_by": "ovpn-dns", "action": "route", "server": "ovpn-dns" }
],
"final": "local"
},
"route": {
"rules": [
{ "ip_cidr": ["10.8.0.0/16"], "outbound": "ovpn-client" }
]
}
}Server on UDP 1194 that hands out 10.8.0.0/24 and pushes a default route:
{
"endpoints": [
{
"type": "openvpn-server",
"tag": "ovpn-server",
"listen": "::",
"listen_port": 1194,
"network": "udp",
"address": ["10.8.0.1/24"],
"tls": {
"certificate_path": "/etc/openvpn/server.crt",
"key_path": "/etc/openvpn/server.key",
"client_certificate_path": "/etc/openvpn/ca.crt",
"control_wrap": { "type": "tls_crypt", "key_path": "/etc/openvpn/tc.key" }
},
"push": {
"redirect_gateway": true,
"dns": ["1.1.1.1"]
}
}
]
}Notes
- Endpoints sit under
endpoints[]and are selected by tag in route rules, just like outbounds. Neither endpoint installs operating-system routes or DNS settings:routes,redirect_gatewayand pushed routes only shape which destinations sing-box prefers to send through the endpoint. - The client's dial fields apply to its connection to the OpenVPN server; that control connection never follows the endpoint's own routes, so the redirect-gateway flags
local/autolocalneed no route exception. static_keymode exists only for compatibility with peers that cannot be upgraded — it has no TLS control channel and no forward secrecy. Prefertls.- Interactive authentication (challenge / response,
auth_retry: "interact") is completed through the sing-box graphical clients or the Dashboard, under Tools › Endpoints. - DNS options pushed by the server are never written into the operating system. Use the
openvpnDNS server to consume them: only the pushed server group with the lowest priority number is active, legacydhcp-option DNSis used when no modern group exists, and a group that requires DNSSEC (dnssec yes) is rejected because this transport does not validate DNSSEC. - Durations such as
ping_interval,ping_restartandreplay_window_timemust be whole seconds.
Cross-core notes
- mihomo has an OpenVPN client only: a
type: openvpnoutbound whose keys mirror.ovpndirectives (ca/cert/key,tls-auth/tls-crypt,username/password, …). It has no OpenVPN server. mihomo defaultsauthto SHA256 while sing-box follows upstream OpenVPN's SHA1 — setauthexplicitly on both sides when mixing implementations. See OpenVPN — mihomo. - Xray-core has no OpenVPN support.
Source: option/openvpn.go:10-210 · v1.14.2 (af6e64c)
