OpenVPN — mihomo
mihomo can dial an OpenVPN server as an outbound, running a userspace client that stands up a tun-style stack device and routes matched traffic through the encrypted tunnel. The control channel is authenticated with certificates (ca / cert / key), optional tls-crypt, and/or auth-user-pass credentials; the data channel is encrypted with the negotiated cipher.
Outbound
Entry under proxies: with type: openvpn. Embeds BasicOption (common outbound fields).
| Field | Type | Default | Allowed values | Description |
|---|---|---|---|---|
name | string | (required) | <string> | Unique proxy name. |
server | string | (required) | <host> | OpenVPN server host/IP. |
port | int | (required) | <port> | Server port. |
proto | string | udp | udp | tcp | Transport protocol of the OpenVPN tunnel. |
dev | string | tun | tun | Virtual device type (e.g. tun). |
cipher | string | AES-128-GCM | AES-128-GCM | AES-192-GCM | AES-256-GCM | AES-128-CBC | AES-192-CBC | AES-256-CBC | CHACHA20-POLY1305 | Data-channel cipher used when data-ciphers is unset. |
data-ciphers | []string | (unset) | [<cipher>] | Data-channel cipher list offered for negotiation (OpenVPN --data-ciphers). The negotiated cipher is the first server-pushed entry that also appears here; when unset, the single cipher value is used. |
data-ciphers-fallback | string | (unset) | <cipher> | Cipher used when the server does not support cipher negotiation (OpenVPN --data-ciphers-fallback). |
auth | string | SHA256 | MD5 | SHA1 | SHA256 | SHA384 | SHA512 | HMAC digest (OpenVPN --auth), e.g. SHA256. Also sets the tls-auth HMAC digest. |
comp-lzo | string | (unset) | yes | no | adaptive | LZO compression setting. |
ca | string | (required) | <inline PEM> | CA certificate (inline PEM block). |
cert | string | (unset) | <inline PEM> | Client certificate (inline PEM block). |
key | string | (unset) | <inline PEM> | Client private key (inline PEM block). |
tls-auth | string | (unset) | <inline static key> | Inline OpenVPN Static key V1 block for tls-auth HMAC protection of the control channel. Mutually exclusive with tls-crypt and tls-crypt-v2. The HMAC digest follows auth. |
key-direction | string | (bidirectional) | 0 | 1 | Key direction for tls-auth. 0 / 1 select the directional key slots; unset uses the same key in both directions. |
tls-crypt | string | (unset) | <inline static key> | tls-crypt static key for control-channel encryption/authentication. |
tls-crypt-v2 | string | (unset) | <inline PEM client key> | Inline PEM-encoded tls-crypt-v2 client key. Mutually exclusive with tls-auth and tls-crypt. |
username | string | (unset) | <string> | auth-user-pass username. |
password | string | (unset) | <string> | auth-user-pass password. |
peer-info | map[string]string | {} | {<key>: <value>} | Extra peer-info key/value pairs (e.g. IV_HWADDR, UV_*) appended to the built-in IV_* entries sent during key exchange. An IV_VER entry replaces the built-in version string. |
ping | int | (unset) | <seconds> | Keepalive ping interval (seconds). |
ping-restart | int | (unset) | <seconds> | Restart the tunnel after this many seconds without a ping (seconds). |
tran-window | *int | 3600 | <seconds> | Seconds an old data key stays usable after a rekey (OpenVPN --tran-window). Unset means 3600; an explicit 0 expires the old key immediately. Match the server's --tran-window. Negative values are rejected. |
handshake-timeout | int | 0 (no limit) | <seconds> | Abort tunnel establishment when the OpenVPN handshake takes longer than this many seconds. 0 disables the timeout. |
mtu | int | 1500 | <integer> | Tunnel MTU. |
udp | bool | false | true | false | Allow UDP traffic through the proxy. |
ip-stack | IPStackOption | (auto) | IPStackOption | Userspace IP stack for the tunnel: { mode: auto|gvisor|mips, congestion-controller: cubic|reno|bbr|bbr3 } — the same block as WireGuard's ip-stack. |
remote-dns-resolve | bool | false | true | false | Resolve destination names using the tunnel's DNS. |
dns | []string | [] | [<server>] | DNS servers used for the tunnel. |
Source: adapter/outbound/openvpn.go:40-73 · pinned at v1.19.31 (ab405ba)
Examples
Outbound — certificate authentication:
yaml
proxies:
- name: ovpn-cert
type: openvpn
server: vpn.example.com
port: 1194
proto: udp
cipher: AES-256-GCM
auth: SHA256
ca: |
-----BEGIN CERTIFICATE-----
<ca-certificate>
-----END CERTIFICATE-----
cert: |
-----BEGIN CERTIFICATE-----
<client-certificate>
-----END CERTIFICATE-----
key: |
-----BEGIN PRIVATE KEY-----
<client-private-key>
-----END PRIVATE KEY-----
udp: trueOutbound — username/password authentication with keepalive:
yaml
proxies:
- name: ovpn-userpass
type: openvpn
server: vpn.example.com
port: 1194
proto: tcp
ca: |
-----BEGIN CERTIFICATE-----
<ca-certificate>
-----END CERTIFICATE-----
username: <username>
password: <password>
ping: 10
ping-restart: 60
udp: trueNotes
protoselects the link transport:udp(default) ortcp.- Data-channel cipher selection follows OpenVPN 2.5+ semantics:
data-ciphersis the negotiation offer (sent asIV_CIPHERS), and the negotiated cipher is the first server-pushed entry that also appears in it.data-ciphers-fallbackcovers servers that cannot negotiate. Whendata-ciphersis unset, the singleciphervalue (defaultAES-128-GCM) is used. cais required.cert+keyprovide certificate authentication;username+passwordprovideauth-user-passauthentication. They can be combined when the server requires both. All key material is given inline (YAML block scalar) — file paths are not read.- The three control-channel wrappers are mutually exclusive:
tls-auth(HMAC-authenticates the control channel; pair withkey-direction: 0|1for directional keys),tls-crypt(encrypts and authenticates it with a shared static key), andtls-crypt-v2(per-client wrapped key, supplied as the inline PEM client key). - The
tls-authHMAC uses theauthdigest (defaultSHA256), as OpenVPN itself does. If the server runs OpenVPN's defaultauth SHA1, setauth: SHA1explicitly. peer-infoadds custom key/value pairs (e.g.IV_HWADDR,UV_*) after the built-inIV_VER/IV_PROTO/IV_CIPHERSentries the client sends during key exchange. A user-suppliedIV_VERreplaces the built-in value;IV_PROTO/IV_CIPHERSare always generated and cannot be overridden.handshake-timeoutbounds how long tunnel establishment may take;0(the default) waits indefinitely.pingsends a keepalive at the given interval;ping-restarttears the tunnel down after that many seconds with no received packet so it can be re-established. Both are expressed in seconds.tran-windowkeeps the previous data key alive for that many seconds after a rekey so in-flight packets still decrypt; leave it unset (3600 s) unless the server uses a non-default--tran-window.mtusets the tunnel MTU and defaults to1500.remote-dns-resolveroutes destination-name lookups through the tunnel using the servers listed indns; it has no effect unlessdnsis non-empty.
Cross-core notes
- Xray-core has no OpenVPN support — to bridge an OpenVPN endpoint with Xray you would run a separate OpenVPN client and point a
socks/httpor TUN inbound at it. sing-box implements OpenVPN as endpoints rather than an outbound (openvpn-clientandopenvpn-server, compatible with standard OpenVPN peers), plus anopenvpnDNS server that uses the DNS options the server pushes. See OpenVPN — sing-box.
Source: adapter/outbound/openvpn.go:40-73 · v1.19.31 (ab405ba)
