Merge in ADGUARD-CORE-LIBS/vpn-libs-endpoint from feature/AG-20619 to master
Squashed commit of the following:
commit aa0c25b0bdd80327b444cbdb428b2fafa440ef1b
Author: Sergei Gunchenko <s.gunchenko@adguard.com>
Date: Mon Apr 3 15:01:52 2023 +0300
do not touch mutex on every iteration
commit 2250458d809dbb6183450c34e17979c73eeefd3e
Author: Sergei Gunchenko <s.gunchenko@adguard.com>
Date: Mon Apr 3 12:59:52 2023 +0300
fix typo
commit 8b96d36e1fd1d7d635fb23a7f269d97864c0eadd
Merge: dac08a6 a9aebd7
Author: Sergei Gunchenko <s.gunchenko@adguard.com>
Date: Mon Apr 3 11:29:26 2023 +0300
Merge remote-tracking branch 'origin/master' into feature/AG-20619
commit dac08a667aaa7e44c73142a7174697c17b1842bf
Author: Sergei Gunchenko <s.gunchenko@adguard.com>
Date: Fri Mar 31 18:14:32 2023 +0300
lib: fix upload eof handling
commit 0a6d0f90b3920fb48320e0e1eac48d91acc71b48
Author: Sergei Gunchenko <s.gunchenko@adguard.com>
Date: Fri Mar 31 16:43:19 2023 +0300
flush sink pipe half on eof
commit 4b5121fff54cc3fb352aec5d0912646fab65e29b
Author: Sergei Gunchenko <s.gunchenko@adguard.com>
Date: Fri Mar 31 10:04:15 2023 +0300
tunnel tests
commit 66bdba1ec66f690a04b4eae5155232054f81bcb5
Author: Sergei Gunchenko <s.gunchenko@adguard.com>
Date: Thu Mar 30 10:48:54 2023 +0300
reuse things
commit cc3396ff3ba59bbb1d5087239dc1fe2006587aac
Author: Sergei Gunchenko <s.gunchenko@adguard.com>
Date: Thu Mar 30 10:28:04 2023 +0300
minor
commit 1a655463029f2f34073910601b7b50ec4f09dfea
Author: Sergei Gunchenko <s.gunchenko@adguard.com>
Date: Thu Mar 30 10:27:55 2023 +0300
fix docs
commit 69f34abf611b4e55d1821d34a5dcc22cc2ef42e7
Merge: ba7dba8 69e6356
Author: Sergei Gunchenko <s.gunchenko@adguard.com>
Date: Wed Mar 29 19:33:04 2023 +0300
Merge branch 'feature/AG-20424' into feature/AG-20619
commit 69e6356026e04798c2e985ede166c60bc77e4453
Author: Sergei Gunchenko <s.gunchenko@adguard.com>
Date: Wed Mar 29 19:27:50 2023 +0300
update docs
commit 2a0ba9fc26df6b715b9c6089574e23e4c34d5bea
Author: Sergei Gunchenko <s.gunchenko@adguard.com>
Date: Wed Mar 29 19:19:22 2023 +0300
review
commit fb4682f7b42c08f48e249e2ed2a5135624816553
Merge: 1dec351 45b856a
Author: Sergei Gunchenko <s.gunchenko@adguard.com>
Date: Wed Mar 29 18:51:25 2023 +0300
Merge remote-tracking branch 'origin/master' into feature/AG-20424
commit ba7dba85ef5c9b53e5a5c70b927da5c2e97f166f
Author: Sergei Gunchenko <s.gunchenko@adguard.com>
Date: Wed Mar 29 17:40:27 2023 +0300
minor
commit e4aa5038fae681ff4757b53e5a79f53efb4ad265
Author: Sergei Gunchenko <s.gunchenko@adguard.com>
Date: Wed Mar 29 17:14:20 2023 +0300
lib: tests
commit 1155ecf196e28ea1f340c7852bbfd987a79c2cbf
Author: Sergei Gunchenko <s.gunchenko@adguard.com>
Date: Wed Mar 29 17:13:41 2023 +0300
lib: fix huge timeout for connection establishment procedure
commit 87ae4ba9a919a29e3ca714fc7b985d4fbf023fc5
Author: Sergei Gunchenko <s.gunchenko@adguard.com>
Date: Wed Mar 29 17:12:27 2023 +0300
lib: fix UDP packets decoding
commit 435f49495e98f7ab05662f375f590f3b0c274de9
Author: Sergei Gunchenko <s.gunchenko@adguard.com>
Date: Fri Mar 24 18:50:31 2023 +0300
less verbose logs for tests
commit 3b8d6a6be7110ed1b2c2c54db9705d7fd1a6c58d
Author: Sergei Gunchenko <s.gunchenko@adguard.com>
Date: Fri Mar 24 18:46:14 2023 +0300
grammar
commit 50b0e0250e5f2474003e1594bd390b119042806b
Author: Sergei Gunchenko <s.gunchenko@adguard.com>
Date: Fri Mar 24 18:40:45 2023 +0300
lib: expand tests
... and 17 more commits
8.9 KiB
AdGuard VPN endpoint
Building the library
Prerequisites
- Rust 1.67 or higher: use a preferred way from https://www.rust-lang.org/tools/install
Building
Execute the following commands in Terminal:
cargo build
to build the debug version, or
cargo build --release
to build the release version.
Features description
Traffic forwarding
As for now, the endpoint can demultiplex client's connections multiplexed in either HTTP/1, or
HTTP/2, or HTTP/3 session. An application can set up how the endpoint forwards the demultiplexed
client's connection by setting Settings.forward_protocol. The available options
(see settings.ForwardProtocolSettings) are:
- routing a connection directly to its target host
- routing a connection though a SOCKS5 proxy
ICMP forwarding
As an optional feature, the endpoint can also forward ICMP packets from a client. This feature
can be set up by setting Settings.icmp. An application MUST set up an interface name to bind
the ICMP socket to, and MAY tweak some other settings, like the timeouts and message queue size.
Reverse proxy
Client's connection is treated as a reverse proxy stream in the following cases:
- A TLS session or QUIC connection has the SNI set to the host name equal to one
from
TlsHostsSettings.reverse_proxy. - An HTTP/1.1 request has
Upgradeheader and its path starts withReverseProxySettings.path_mask. - An HTTP/3 request has path starting with
ReverseProxySettings.path_mask.
The stream is used for mutual client and endpoint notifications and some control messages. The endpoint does TLS termination on such connections and translates HTTP/x traffic into HTTP/1.1 protocol towards the server and back into original HTTP/x towards the client. Like this:
(client) TLS(HTTP/x) <--(endpoint)--> (server) HTTP/1.1
The translated HTTP/1.1 requests have the custom header X-Original-Protocol appended.
For now, its value can be either HTTP1, or HTTP3.
Authentication
Client authentication options
SNI authentication
A client connects to the endpoint with SNI set to hash.domain_name, where:
hash-md5(application_id + ':' + token + ':' + credentials)domain_name- the endpoint's original domain name (e.g.myvpn.org)
Proxy authentication
A client connects to the endpoint using the proxy HTTP authentication mechanism with
the "basic" scheme: Proxy-Authorization: Basic base64(token + ':' + credentials).
Endpoint authentication methods
An application can set up the authentication method being used by the endpoint
by setting Settings.authenticator. The application can provide its own authenticator
implementation (see the authentication.Authenticator trait), or use one of the implementations
provided by the library:
authentication.DummyAuthenticator- authenticates any requestauthentication.file_based.FileBasedAuthenticator- authenticates a request basing on the file containing credentials (see here)authentication.radius.RadiusAuthenticator- delegates authentication to an authenticator communicating with it by the RADIUS protocol (see here)- SOCKS5 authentication - delegates authentication to the SOCKS5 forwarder (see here)
Please note, that the first 2 are very simple authenticator implementations which are intended mostly for testing purposes and do not respect network security practices.
File based authenticator
The file must contain an application id (applicationId: <string>), token (token: <string>),
and credentials (credentials: <string>).
Each one must be on a new line. The order does not matter.
RADIUS authenticator
This authenticator implementation communicates with an authentication server by the Microsoft EAP CHAP Extensions Protocol, Version 2 over the Extensible Authentication Protocol over the RADIUS protocol.
Successful authentication procedure diagram:
sequenceDiagram
participant Endpoint
participant Authenticator
Endpoint ->> Authenticator: RADIUS: code=AccessRequest[EAP: code=Response, type=Identity, user_name]
Authenticator ->> Endpoint: RADIUS: code=AccessChallenge[EAP: code=Request, type=MsAuth[MS-CHAP-V2: code=Challenge]]
Endpoint ->> Endpoint: MS-CHAP-V2::GenerateNTResponse()
Endpoint ->> Authenticator: RADIUS: code=AccessRequest[EAP: code=Response, type=MsAuth[MS-CHAP-V2: code=Response]]
Authenticator ->> Authenticator: Verify MS-CHAP-V2 response
Authenticator ->> Authenticator: Authenticate
Authenticator ->> Endpoint: RADIUS: code=AccessChallenge[EAP: code=Request, type=MsAuth[MS-CHAP-V2: code=SuccessRequest]]
Endpoint ->> Endpoint: MS-CHAP-V2::CheckAuthenticatorResponse()
Endpoint ->> Authenticator: RADIUS: code=AccessRequest[EAP: code=Response, type=MsAuth[MS-CHAP-V2: code=SuccessResponse]]
Authenticator ->> Endpoint: RADIUS: code=AccessAccept[EAP: code=Success, type=MsAuth]
Depending on the client-side authentication way, the user_name and password are as follows:
- SNI authentication:
user_name=sni@<id>@<hash[0..6]>- a special value which indicates the authentication way<id>- the id of the current authentication session<hash[0..6]>- the first 6 characters of the SNI
password=hash- corresponds tohash, as in SNI authentication
- Proxy authentication:
user_nameandpasswordcorrespond totokenandcredentials, as in Proxy authentication
The endpoint caches the authentication status and repeats the procedure for the client after
the cache TTL (see RadiusAuthenticatorSettings.cache_ttl).
SOCKS5 authenticator
Standard authentication
In case Socks5ForwarderSettings.extended_auth is set to false, the endpoint performs
the standard authentication procedure according to the
RFC 1929.
Depending on the client-side authentication way, the username and password are as follows:
-
- both
usernameandpassword=hash- corresponds tohash, as in SNI authentication
- both
-
usernamecorresponds totoken, as in Proxy authenticationpasswordcorresponds tocredentials, as in Proxy authentication
Extended authentication
The extended authentication uses 0x80 as an authentication method.
After a server selects this authentication method, a client sends an authentication
request in the following format:
+-----+-----------+-----+--------+
| VER | EXT(0) | | EXT(n) |
+-----+-----------+ ... +--------+
| 1 | see below | | |
+-----+-----------+-----+--------+
Where:
VER- the current extended authentication version: 0x01EXT[i]- an extension in the following format:
Where:+------+--------+----------+ | TYPE | LENGTH | VALUE | +------+--------+----------+ | 1 | 2 | Variable | +------+--------+----------+TYPE- a type of the extension value (see [ExtendedAuthenticationValue])LENGTH- the length of the extension valueVALUE- the extension value
Available extensions:
TERM: type = 0x00, length = 0 - terminating extension, marks a message endDOMAIN: type = 0x01, length = (0..MAX], value = UTF-8 string - hostname which a client used for the TLS session (SNI)CLIENT_ADDRESS: type = 0x02, length = [4|16], value = Bytes - public IP address of the VPN clientUSER_AGENT: type = 0x03, length = (0..MAX], value = UTF-8 string - user agent of the VPN clientPROXY_AUTH: type = 0x04, length = (0..MAX], value = base64 string -<credentials>part of the Proxy-Authorization headerSNI_AUTH: type = 0x05, length = 0 - marks that the VPN client tries to authenticate using SNI
A message MUST end with the TERM extension.
The server responds with a standard message as in the RFC.
Metrics collecting
In order to collect some metrics of a running endpoint, an application can set up it to listen for
the metrics collecting requests (see Settings.metrics). An endpoint running with this feature
will listen on the configured address (MetricsSettings.address) for plain HTTP/1 requests.
The following paths are available:
/health-check- used for pinging the endpoint, so it will respond with200 OK/metrics- used for metrics collecting, so it will respond with a bunch of values according to the prometheus specification
License
Apache 2.0