Skip to content

expressvpn/lightway

Repository files navigation

Lightway

Lightway is a modern VPN protocol in Rust, to deliver a VPN experience that’s faster, more secure, and more reliable.

Structure

This repository contains multiple crates as follows:

  • lightway-core - Core VPN protocol library
  • lightway-client - Client application
  • lightway-server - Server application

In addition there is:

  • tests - dev and e2e test infrastructure

Documentation

Protocol and design documentation can be found in the docs folder.

Supported platforms

Lightway Rust implementation currently supports Linux OS. Both x86_64 and arm64 platforms are supported and built as part of CI.

Support for other platforms will be added soon.

Development steps

Lightway core and reference applications can be built using Earthly without setting up the complete development environment locally.

Refer to Earthly documentation on how to install earthly.

earthly +build

For running unit-tests,

earthly +test

To format code:

cargo fmt

For more information about the different Earthly targets available, run:

earthly doc

Note: Lightway can also be built using standard cargo tools

Configuration

Lightway-server

Lightway-server can be configured using config-file as follows:

lightway-server --config-file './tests/server/server_config.yaml'

Example config file:

We can also override configs (except config-file), either by using env variables or by using cli arguments. Env variables should have the prefix LW_SERVER_. Cli arguments has the highest priority.

Authentication

Users are authenticated either using username and password or JWT tokens. Both schemes may be used simultaneously but each connection is authorized by one or the other (chosen by the client).

User / Password

A user database may be provided via the user_db option. This is in a format compatible with Apache htpasswd files and so can be managed using htpasswd(1) or the tool of your choice.

The format is one user per line with username and password hash separated by a colon, e.g.: username:hash(password).

$ htpasswd -B -c lwpasswd my_user
New password:
Re-type new password:
Adding password for user my_user
$ cat lwpasswd
my_user:$2y$05$V6da9E.ys3QUnhgAfSGm6eM5dhkHa6Oc90kKNpb8bmcCgPsreU7Sa

Note that only the hashes supported by the pwhash crate are supported and that this notably excludes the custom Apache MD5 hash which htpasswd(1) uses by default. Use an option such as -B, -2 or -5 to pick a different algorithm.

Caution

The widely used but basic htpasswd(1) username / password database format was chosen here to provide an easy-to-setup reference implementation of Lightway. Users are encouraged to modify this implementation with more advanced username / password authentication mechanisms and their own choice of password hashing algorithms to suit their security needs.

Please note that when providing env variables it should be in upper case and using "_" as a word separator, while using as cli config, it should be in lower case with "-" as the word separator.

Caution

Passing the --password option on the CLI will expose your password to other users on the system. It is recommended to provide the password via the configuration file or via LW_CLIENT_PASSWORD environment variable.

JWT Token

An RSA public key may be provided using the token_rsa_pub_key_pem option. Any JWT (see RFC 7519) with algorithm type "RS256" signed with the corresponding private key will be authorized to connect.

The token's header must consist of at least:

{
  "alg": "RS256",
  "typ": "JWT"
}

The token's payload must contain at least a valid (in the future) "exp" claim:

{
  "exp": 123456789,
}

The keys and tokens can be generated by any RSA and JWT tooling.

For example:

  • https://mkjwk.org/ can generate suitable key. Using "Show X.509" presents the public and private key in PEM format as required.
  • https://jwt.io/ can then be used to generate individual tokens. (Note that by default the "alg" field is "HS256" not "RS256" as required here.

Example:

LW_SERVER_LOG_LEVEL=trace lightway-server --config-file './tests/server/server_config.yaml'

The above command loads the config file and then overrides the log_level from env variable to trace level.

LW_SERVER_LOG_LEVEL=trace lightway-server --config-file './tests/server/server_config.yaml' --log-level=off

The above command loads the config file and then overrides the log_level from cli args to off level. Since cli arguments have the highest priority, env variable config will be ignored.

Lightway-client

Lightway-client can also be configured using config-file similar to Lightway-server as follows:

lightway-client --config-file './tests/client/client_config.yaml'

Example config file:

Lightway-client also supports overriding the config using either env variables or cli arguments. Env variables should have the prefix LW_CLIENT_.

By default the client will use the existing MTU on the tunnel device, this can be overridden with the --inside-mtu option but note that this requires additional privileges, specifically the CAP_SYS_ADMIN capability.

Caution

Passing the --password option on the CLI will expose your password to other users on the system. It is recommended to provide the password via the configuration file or via LW_CLIENT_PASSWORD environment variable.

E2E Testing

To run all e2e tests:

earthly --allow-privileged +e2e

Or to run a single e2e test:

earthly --allow-privileged ./tests+run-tcp-test

Check tests/Earthfile or earthly doc ./tests for other run-*-test targets.

To start the stack for your own testing:

earthly -P ./tests/+save-all-test-containers  && SERVER_ARGS="--config-file server_config.yaml" CLIENT_ARGS="--config-file client_config.yaml" docker compose -f tests/e2e/docker-compose.yml up

Then you can use e.g.

docker compose -f tests/e2e/docker-compose.yml exec client bash

To run things within the containers

Contributing

We appreciate feedback and contribution to this repository! Before you get started, please see link:

CONTRIBUTING

Reporting a vulnerability

To report security vulnerabilities, please see section on link:

Reporting a vulnerability

Dev-Testing

For running both client and server in the same machine and test end to end, follow these steps:

export LW_DANGEROUSLY_DISABLE_PERMISSIONS_CHECKS=1

Configuration files must be trustworthy (per fs-mistrust's definition) but many path elements are owned by the user while the tests are run as root via sudo. For dev test we disable those checks.

Then:

sudo ./tests/setup.sh

The above script by default creates four network namespaces: - lightway-server - lightway-middle - lightway-client - lightway-remote

The lightway-remote namespace simulates "The Internet". Run any services which you'd like the client to access over the tunnel here.

The lightway-middle namespace facilitates a multi-hop network path: client <-> middle <-> server. Settings can be modified in the middle namespace to simulate interesting network conditions (e.g. lower path MTU, see below)

Start server using this command,

cargo build --bin lightway-server && sudo -E ip netns exec lightway-server ./target/debug/lightway-server --config-file './tests/server/server_config.yaml'

Start client using this command,

cargo build --bin lightway-client && sudo -E ip netns exec lightway-client ./target/debug/lightway-client --config-file './tests/client/client_config.yaml' --server server:27690

Then enter into lightway-client namespace and trying pinging google.com

sudo ip netns exec lightway-client bash
ping google.com -c 3

Verify wan interface in lightway-remote namespace receiving the packet and replying:

sudo ip netns exec lightway-remote bash
tcpdump -i wan -nvvl

Run wireshark within a network namespace:

sudo -E ip netns exec lightway-client su -c wireshark $USER

Change the client's source address:

sudo ip netns exec lightway-client ip addr add 192.168.0.3/24 dev veth
sudo ip netns exec lightway-client ip addr del 192.168.0.2/24 dev veth

To cleanup the test setup after testing, use

sudo ./tests/setup.sh delete

Note: This will work only on linux machine with kernel supporting network namespaces. And sudo permission is required to run all netns commands

To setup multiple additional namespaces:

sudo env EXTRA_CLIENTS=3 ./tests/setup.sh

Will create lightway-client1, lightway-client2 and lightway-client3 in addition to the base lightway-client.

To test Path MTU Discovery (UDP only) you can set the second hop MTU with e.g.

sudo ip netns exec lightway-middle ip link set mtu 1300 dev veth-s2m
sudo ip netns exec lightway-server ip link set mtu 1300 dev veth-s2m

Testing with PROXY protocol enabled

Lightway server supports the PROXY protocol via the proxy_protocol configuration option.

In the containerized test environment this can be tested by running a proxy protocol frontend.

For example using https://pypi.org/project/proxy-protocol/ to proxy from TCPv4 port 443 to a lightway server listening on TCPv6 localhost:

python3 -m venv --prompt proxy-protocol proxy-protocol
./proxy-protocol/bin/pip3 install proxy-protocol
sudo ip netns exec lightway-server ./proxy-protocol/bin/proxyprotocol-server --service 0.0.0.0:443 '[::1]:443'

Then configure lightway-server with bind_address: [::1]:443 and proxy_protocol: true. The client can connect to server:443 via TCPv4 as usual.

Speeding up development with Earthly Satellites

Please refer to official documentation for Earthly Satellites.

If you are a member of ExpressVPN, you can get access to the same Earthly organization used in our CI. The organization is named expressvpn, inside which contains a satellite named lightway.

If you are not a member of ExpressVPN, you may set up your own Earthly satellite according the official instructions above.

Debugging

Decrypting TLS1.3 data packets

Lightway-client supports creating a keylog file, which can be used in Wireshark for decrypting the TLS1.3 data traffic. Note that this is supported only with feature debug enabled.

For example:

cargo run --features debug --bin lightway-client -- --config-file=tests/client_conf.yaml --keylog "/tmp/client.log"

The resulting file can then be exported to Wireshark to decrypt data traffic. The following wireshark documentations explains about exporting keylog file:

https://www.wireshark.org/docs/wsug_html_chunked/ChIOExportSection.html#ChIOExportTLSSessionKeys https://wiki.wireshark.org/TLS#using-the-pre-master-secret

WolfSSL debug logging

Both lightway-client and lightway-server support a --tls-debug option when built with their respective debug feature enabled. This enables WolfSSL's debug logging.

About

Lightway Rust Open Source Workspace

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published