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
$ /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 fileConfig 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}
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