Skip to content

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).

FieldTypeDefaultAllowed valuesDescription
namestring(required)<string>Unique proxy name.
serverstring(required)<host>OpenVPN server host/IP.
portint(required)<port>Server port.
protostringudpudp | tcpTransport protocol of the OpenVPN tunnel.
devstringtuntunVirtual device type (e.g. `tun`).
cipherstringAES-128-GCMAES-128-GCM | AES-192-GCM | AES-256-GCM | AES-128-CBC | AES-192-CBC | AES-256-CBC | CHACHA20-POLY1305Data-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-fallbackstring(unset)<cipher>Cipher used when the server does not support cipher negotiation (OpenVPN `--data-ciphers-fallback`).
authstringSHA256MD5 | SHA1 | SHA256 | SHA384 | SHA512HMAC digest for the control channel, e.g. `SHA256`.
comp-lzostring(unset)yes | no | adaptiveLZO compression setting.
castring(required)<inline PEM>CA certificate (inline PEM block).
certstring(unset)<inline PEM>Client certificate (inline PEM block).
keystring(unset)<inline PEM>Client private key (inline PEM block).
tls-authstring(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`.
key-directionstring(bidirectional)0 | 1Key direction for `tls-auth`. `0` / `1` select the directional key slots; unset uses the same key in both directions.
tls-cryptstring(unset)<inline static key>tls-crypt static key for control-channel encryption/authentication.
tls-crypt-v2string(unset)<inline PEM client key>Inline PEM-encoded tls-crypt-v2 client key. Mutually exclusive with `tls-auth` and `tls-crypt`.
usernamestring(unset)<string>auth-user-pass username.
passwordstring(unset)<string>auth-user-pass password.
peer-infomap[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.
pingint(unset)<seconds>Keepalive ping interval (seconds).
ping-restartint(unset)<seconds>Restart the tunnel after this many seconds without a ping (seconds).
handshake-timeoutint0 (no limit)<seconds>Abort tunnel establishment when the OpenVPN handshake takes longer than this many seconds. 0 disables the timeout.
mtuint1500<integer>Tunnel MTU.
udpboolfalsetrue | falseAllow UDP traffic through the proxy.
remote-dns-resolveboolfalsetrue | falseResolve destination names using the tunnel's DNS.
dns[]string[][<server>]DNS servers used for the tunnel.

Source: adapter/outbound/openvpn.go:42-72 · pinned at v1.19.29 (e26714a)

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: true

Outbound — 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: true

Notes

  • proto selects the link transport: udp (default) or tcp.
  • Data-channel cipher selection follows OpenVPN 2.5+ semantics: data-ciphers is the negotiation offer (sent as IV_CIPHERS), and the negotiated cipher is the first server-pushed entry that also appears in it. data-ciphers-fallback covers servers that cannot negotiate. When data-ciphers is unset, the single cipher value (default AES-128-GCM) is used.
  • ca is required. cert + key provide certificate authentication; username + password provide auth-user-pass authentication. 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 with key-direction: 0|1 for directional keys), tls-crypt (encrypts and authenticates it with a shared static key), and tls-crypt-v2 (per-client wrapped key, supplied as the inline PEM client key).
  • peer-info adds custom key/value pairs (e.g. IV_HWADDR, UV_*) after the built-in IV_VER / IV_PROTO / IV_CIPHERS entries the client sends during key exchange.
  • handshake-timeout bounds how long tunnel establishment may take; 0 (the default) waits indefinitely.
  • ping sends a keepalive at the given interval; ping-restart tears the tunnel down after that many seconds with no received packet so it can be re-established. Both are expressed in seconds.
  • mtu sets the tunnel MTU and defaults to 1500.
  • remote-dns-resolve routes destination-name lookups through the tunnel using the servers listed in dns; it has no effect unless dns is non-empty.

Cross-core notes

  • OpenVPN is mihomo-specific among these three cores. Neither Xray-core nor sing-box ships an OpenVPN outbound — to bridge an OpenVPN endpoint with those cores you would run a separate OpenVPN client and point a socks/http or TUN inbound at it.

Source: adapter/outbound/openvpn.go:42-72 · v1.19.29 (e26714a)

Core Tutorial by Argsment