Lightway CLI

Lightway CLI is a cross-platform Lightway client application written in C. It currently supports the following platforms:

  • Windows (32-bit/64-bit)

  • Mac (x86_64/arm64)

Command Line Options

usage
$ /usr/lib/expressvpn/lightway --help
Usage: lightway [options]

Lightway 1.34.0

    -h, --help            show this help message and exit

Global options
    -c, --config=<str>    Read configuration options from file
    -v, --version         Show copyright and version information and exit
    --color               Enable color mode when printing logs to stdout
    -d, --debug           Set log level to debug
    --trace               Set log level to trace
    --use-wintun          Windows only: Use WinTun instead of TAP driver
    --use-dpapi           Windows only: Use DPAPI to decrypt the config file

Config Format

Lightway CLI loads the VPN configurations from a JSON file on start.

Configuration Keys

Key

Type

Required

Description

ca

string

CA certificate in PEM format, as a string including ----BEGIN CERTIFICATE----- and -----END CERTIFICATE-----. Default: null, the embedded production certificate will be used. In versions prior to v1.48.0, this was only accessible if ENABLE_CONFIG_CA was defined at compile time. Starting from v1.48.0, it is generally available without requiring any special compile-time definition.

keepalive

int

Send keepalive messages to the vpn server every N seconds when connected. This can be used to avoid NAT timing out. The default value is 0, meaning no keepalive messages will be sent.

keepalive_timeout

int

Disconnect and exit with "inactivity timeout" error when keepalive is non-zero AND there's no HE_EVENT_PONG event for N seconds. The default value is 0, meaning no disconnect would occur when there's no HE_EVENT_PONG event. The minimal value of keepalive_timeout is 60 and it shouldn't be smaller than keepalive.

authentication_timeout

int

Specify a timeout in seconds in which authentication must be completed. Disconnect and exit with a “connection timed out” error if authentication is not completed within the given time. The default value is 10 seconds. Value of 0 means there is no timeout for authentication.

initial_packet_timeout

int

Specify a timeout in seconds in which Lightway CLI must have received the HE_EVENT_FIRST_MESSAGE_RECEIVED event from libhelium. Disconnect and exit with a "connection timed out" error with "reason" field is set to HELIUM_ERROR_DETAILS_INITIAL_PACKET_TIMEOUT. The default value is 0 means "no initial packet timeout". Availability: v0.18.0 or later.

route_mode

string

Config Lightway CLI behavior when it's setting up routing tables. Possible values: default: automatically add the default 0/1, 128.0/1 routes when connected. this is the default value even if the "route_mode" is not present in the config lan: same as "default" but also adds the LAN routes. The setting replaced the "add_lan_routes" feature above. noexec: don't add any routes when connected. Availability: v1.24.0

tun_name

string

Specify the preferred name to be set on the tunnel interface. Windows only. Default: "" (empty string) Availability: v0.18 or later

tun_local_ip

string

Specify the local IP address to set on the tun interface. Default: 100.64.100.6 Availability: v1.26.0

tun_peer_ip

string

Specify the peer ip address to set on the tun interface. Default: 100.64.100.5 Availability: v1.26.0

tun_dns_ip

string

Specify the DNS server IP address to set once the VPN is connected. Note: ExpressVPN desktop app always routes all DNS traffic are to the tunnel interface to prevent DNS leaks, therefore this ip address maybe set at the system level, not necessarily at the interface level. See below (to be written) section for details. Default: 100.64.100.1 Availability: v1.26.0

tun_mtu

int

Specify the MTU value of the tun interface. This will override any value supplied by helium. Default: 1350 Availability: After v1.29.2

up

Object (External command)

Defines the external script to run when connected. Helium cli will block until the script finishes running. If the exit status is non-zero, helium should enter the "connection_error" state and exit. Example:

down

Object (External command)

Defines the external script to run when disconnected. Helium cli will block until the script finishes running. If the down script is provided, Lightway CLI will always run the down script before exiting. The down script should be idempotent and not affected by the up script having been run.

endpoints

Array of “Endpoint Object”

Set the endpoints to be used in the connection. Note: * If this is null or empty, Lightway CLI will try to parse the first endpoint using the legacy config format instead. * If there’s multiple endpoints, Lightway CLI currently will only use the first endpoint in the array. (As of Sep 11, 2023) Availability: v1.17.0

sndbuf

int

Set the UDP socket send buffer size. If it's not set, default to the following values on each platform: * Windows: 1310720 * Mac: system default If it's set to 0, use the system default on all platforms. Availability: v0.21.0

rcvbuf

int

Set the UDP socket receive buffer size. If it's not set, default to the following values on each platform: * Windows: 1310720 * Mac: system default If it's set to 0, use the system default on all platforms. Availability: v0.21.0

use_pqc

boolean

Specify if post-quantum KEMs should be used. Default: false, meaning ECC key exchanges will be used. Availability: v1.37.0

enable_pmtud

boolean

Set to true to enable Lightway Dynamic MTU features. Default: false. Availability: v1.39.0

wintun_device_id

string

Set the device id of the WinTun driver. Default: expressvpntun. Availability: v1.40.0 (Windows Only)

traffic_stats_interval

int

Write traffic stats to the logs every N seconds. The default value is 0, meaning no traffic stats will be written. An exception is made when the --debug option is given to the CLI, in which case traffic stats will be written every 60 seconds even when no traffic_stats_interval is provided. Availability: v1.47.0

Example for "up" script:

Note: since we use the same script for both Lightway and Openvpn when setting up the DNS servers, helium will pass the dns server ip as environment variables. The environment variables set for the "up" script should be the same as openvpn. A full list of openvpn Environmental Variables can be found in this document: https://openvpn.net/community-resources/reference-manual-for-openvpn-2-3/ , but we only need "dev", "foreign_option_{n}", "script_type".

Endpoint Object

Key

Type

Required

Description

aggressive_mode

boolean

Enable / disable the aggressive mode of the connection. When aggressive mode is enabled, Lightway will always send multiple packets even after the handshake. The theory here is that even though a user would send more packets, on poor networks, this would actually increase their throughput as there are far fewer packets going missing and hence less TCP retransmits. Default: false (disabled)

auth_token

string

Set the token for the token based authentication. Availability: v1.38.0

ca

string

CA certificate in PEM format, as a string including ----BEGIN CERTIFICATE----- and -----END CERTIFICATE-----. Default: null, the embedded production certificate will be used. This config key is only available when the ENABLE_CONFIG_CA is defined at compile time.

cipher

string

Specify the cipher suite to use for the connection. Helium currently supports two cipher types: "chacha20", "aes". Use "chacha20" when the platform doesn't support AES Hardware Acceleration. If this field is empty, the default "aes" cipher will be used.

mtu

int

Specify the MTU which Helium should use for the outside connection. If it's not set, a default MTU 1500 will be used.

padding_type

String

Sets the padding mode and hence the level of padding (if any) to be used. Available values: * "none" - Tell Helium not to pad packets at all * "full" - Tell Helium to fully pad packets to the MTU, like IPSEC * "450" - Tell Helium to round packets to the nearest 450 bytes The default value is "none" which means no padding at all. Enabling the padding will significantly increase the overhead of Lightway connection.

port

int

YES

Port of the server instance.

protocol

string

Protocol to use when connecting to the lightway server. Possible values: udp, tcp. Default: udp.

server

string

YES

IP address of the helium server instance.

server_dn

string

YES

Server Distinguished Name.

server_hostname

string

If not empty, set the SNI hostname when connecting to Lightway TCP servers. Default: empty (SNI extension will NOT be set in the ClientHello packet at all).

External Command Object

Key

Type

Description

path

string

The full path of the external program.

args

array of strings

Arguments of the external program.

Log Messages

Helium CLI writes log messages to stdout using "structured logging" format. Each log message is a single line string which contains one json object.

Example of Log Messages:

Field

Type

Description

time

string

Timestamp of the message. It must be using the https://www.rfc-editor.org/rfc/rfc3339 format with timezone information.

log_level

string

Level of the log message. Possible values are: * DEBUG * INFO * ERROR

message

string

Content of the log message.

context

object

A predefined json struct which contains various information about the helium connection. Note: not all messages have the context field.

Structure of Context Object

Field

Type

Description

state

string

Current helium connection state. Possible values: * HE_STATE_NONE * HE_STATE_CONNECTING * HE_STATE_DISCONNECTED * HE_STATE_AUTHENTICATING * HE_STATE_LINK_UP * HE_STATE_ONLINE * HE_STATE_DISCONNECTING * HE_STATE_CONFIGURING

event

string

Contains the event name if the log message is triggered by an helium event. Possible values: * HE_EVENT_FIRST_MESSAGE_RECEIVED * HE_EVENT_PONG * HE_EVENT_CLIENT_SENT_FRAGMENTED_PACKETS * HE_EVENT_SECURE_RENEGOTIATION_STARTED * HE_EVENT_SECURE_RENEGOTIATION_COMPLETED * HE_EVENT_NETWORK_CHANGED

elapsed_ms

int64

Time elapsed since CONNECTING in milliseconds. This field is only set for a few state/event messages where the "time since connecting" is useful or appeared in the message content. For example: HE_EVENT_FIRST_MESSAGE_RECEIVED, HE_STATE_LINK_UP, HE_STATE_ONLINE

reason

string

Only set when the state field is HE_STATE_DISCONNECTED. Contains the reason for the disconnect. Any HE_ERR_* or HE_SUCCESS names from he_return_code_t.

dns_ip

string

Only set when the state field is HE_STATE_CONFIGURING. Contains the dns server ip for the connection. Engine will add this IP to firewall exception lists when dns leak guard is enabled.

local_ip

string

Only set when the state field is HE_STATE_CONFIGURING. Contains the local ip of the tunnel.

peer_ip

string

Only set when the state field is HE_STATE_CONFIGURING. Contains the peer ip of the tunnel.

adapter_id

string

Only set when the state field is HE_STATE_ONLINE. Contains the name (mac) or guid (windows) of the tunnel device. N.B.: to make it compatible with current engine, the adapter_id should be in this format on Windows: {5BA4CF1C-2B86-42FC-9F0C-496E2C6F873B}

Note:

  • Helium CLI prints all logs to stdout by default.

  • Error messages are written to stderr in free-form format. The user of helium cli should never interpret those error messages as JSON, even if they might look like it.

States & Events

State / Event

Log Messages

Description

HE_STATE_NONE

N/A

Client has yet to be initialised.

HE_STATE_DISCONNECTED

"Helium is DISCONNECTED"

Client is in a disconnected state. Any resources used for the connection have been released.

HE_STATE_CONNECTING

"Helium is CONNECTING"

Client is currently trying to establish a D/TLS session with the server.

HE_EVENT_FIRST_MESSAGE_RECEIVED

"Helium Initial packet received"

First packet / message was passed to Helium (i.e. a server response)

HE_STATE_AUTHENTICATING

"Authenticating…"

Client has established a D/TLS session and is attempting to authenticate.

HE_STATE_LINK_UP

"Link up - took 34.007000ms"

TLS link is up.

HE_STATE_ONLINE

"Helium ONLINE in 6596.885000ms"

Everything is done - we're online. Added on 22/4/2020: The context JSON of this message should contain "adapter_id".

HE_STATE_DISCONNECTING

"Helium is DISCONNECTING"

Client is currently trying to cleanly disconnect from the server.

HE_STATE_CONFIGURING

"Entered configuring state..."

Configuring - config has been received and config callback will soon be made. Added on 22/4/2020: The context JSON of this message should contain "dns_ip", "local_ip" and "peer_ip".

HE_EVENT_FIRST_MESSAGE_RECEIVED

"Lightway Initial packet received"

Received first packet from server

HE_EVENT_PONG

"Lightway Pong received"

Server replied to a PING request (NAT Keepalive).

HE_EVENT_CLIENT_SENT_FRAGMENTED_PACKETS

"Client sent fragmented packets"

Client has tried to send a fragmented packet

HE_EVENT_SECURE_RENEGOTIATION_STARTED

"Lightway secure renegotiation started"

Helium has started a secure renegotiation

HE_EVENT_SECURE_RENEGOTIATION_COMPLETED

"Lightway secure renegotiation completed"

Helium has completed secure renegotiation

HE_EVENT_NETWORK_CHANGED

“Network change detected”

A change in the device network configuration has been detected and a ping is sent to the VPN server. When pong is received, the connection floated successfully. Otherwise the app should follow the received helium state events and attempt reconnecting.

HE_EVENT_PENDING_SESSION_ACKNOWLEDGED

"Lightway pending session acknowledged"

Pending Session Acknowledged

Traffic Statistics

If the traffic_stats_interval config option is provided it will print traffic statistics to the log every N seconds. If the --debug flag is provided, the Lightway CLI will print the traffic statistics to logs every minute even if no traffic_stats_interval is given.

Example of the traffic statistics log:

Structure of the Traffic Statistics Object

Field

Type

Description

inside_received_{success,error}_bytes

uint64

Number of bytes read from the TUN device since connected.

inside_sent_{success,error}_bytes

uint64

Number of bytes written to the TUN device since connected.

outside_received_{success,error}_bytes

uint64

Number of bytes read from the TCP/UDP socket since connected.

outside_sent_{success,error}_bytes

uint64

Number of bytes written to the TCP/UDP socket since connected.

Last updated