Lightway is a modern VPN protocol in Rust, to deliver a VPN experience that’s faster, more secure, and more reliable.
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
Protocol and design documentation can be found in the
docs folder.
Lightway Rust implementation currently supports Linux OS and macOS. Both x86_64 and arm64 platforms are supported and built as part of CI.
Support for other platforms will be added soon.
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 +buildFor running unit-tests,
earthly +testTo format code:
cargo fmtFor more information about the different Earthly targets available, run:
earthly docNote: Lightway can also be built using standard cargo tools
Lightway-server can be configured using config-file as follows:
lightway-server --config-file './tests/server/server_config.yaml'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.
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).
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.ys3QUnhgAfSGm6eM5dhkHa6Oc90kKNpb8bmcCgPsreU7SaNote 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.
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.
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=offThe 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 can also be configured using config-file similar to Lightway-server as follows:
lightway-client --config-file './tests/client/client_config.yaml'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.
Running the client on linux platforms with dns_config_mode: default will require CAP_DAC_OVERRIDE
and  CAP_FOWNER permissions, to properly modify resolv.conf.
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.
Note
macOs has restrictions on tunnel name. It will only allow the format utun[0-9]+.
To avoid guessing the available number, do not provide tun_name config and let the
system decide the tunnel name.
To run all e2e tests:
earthly --allow-privileged +e2eOr to run a single e2e test:
earthly --allow-privileged ./tests+run-tcp-testCheck 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 upThen you can use e.g.
docker compose -f tests/e2e/docker-compose.yml exec client bash
To run things within the containers
Lightway can be built and tested using Nix commands:
nix build .#lightway-server
nix build .#lightway-clientTo run the server or client:
nix run .#lightway-server -- -c config.yaml
nix run .#lightway-client -- -c config.yamlBoth Linux and macOS are supported.
Set up a local development environment using the Nix flake:
nix develop
cargo build --bin lightway-serverThis installs all necessary tools required to develop Lightway.
For nightly toolchain support (needed for fuzzing):
nix develop .#nightlyWe appreciate feedback and contribution to this repository! Before you get started, please see link:
To report security vulnerabilities, please see section on link:
For running both client and server in the same machine and test end to end, follow these steps:
export LW_DANGEROUSLY_DISABLE_PERMISSIONS_CHECKS=1Configuration 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.shThe 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'Then enter into lightway-client namespace and trying pinging google.com
sudo ip netns exec lightway-client bash
ping google.com -c 3Verify wan interface in lightway-remote namespace receiving the packet and replying:
sudo ip netns exec lightway-remote bash
tcpdump -i wan -nvvlRun wireshark within a network namespace:
sudo -E ip netns exec lightway-client su -c wireshark $USERChange 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 vethTo cleanup the test setup after testing, use
sudo ./tests/setup.sh deleteNote: 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.shWill 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-s2mLightway 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.
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
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.