mirror of
https://github.com/TrustTunnel/TrustTunnel.git
synced 2026-04-20 18:02:01 +00:00
Squashed commit of the following: commit 52522b5b230f0abf1acb085432b181db6214006a Merge:2ad57499d0de3eAuthor: Sergey Fionov <sfionov@adguard.com> Date: Thu Feb 26 09:48:16 2026 +0200 Merge remote-tracking branch 'origin/master' into TRUST-268-support-dual-stack-hostname-only-connection-to-server commit2ad5749fffAuthor: Ilia Zhirov <i.zhirov@adguard.com> Date: Thu Feb 19 16:31:55 2026 +0500 Fix formatting commitab0597f558Author: Ilia Zhirov <i.zhirov@adguard.com> Date: Thu Feb 19 16:11:13 2026 +0500 Code cleanup commitd8329217cfAuthor: Ilia Zhirov <i.zhirov@adguard.com> Date: Thu Feb 19 15:52:08 2026 +0500 Update changelog commitc90821b4c8Author: Ilia Zhirov <i.zhirov@adguard.com> Date: Thu Feb 19 15:14:45 2026 +0500 Support hostnames in deeplinks commitf7e184a5e8Merge:71fdf978d5f207Author: Ilia Zhirov <i.zhirov@adguard.com> Date: Thu Feb 19 14:36:29 2026 +0500 Merge branch 'master' into TRUST-268-support-dual-stack-hostname-only-connection-to-server # Conflicts: # CHANGELOG.md # README.md # endpoint/src/main.rs # lib/src/client_config.rs commit71fdf97343Author: Ilia Zhirov <i.zhirov@adguard.com> Date: Fri Feb 13 19:43:24 2026 +0500 Explicitly set IPV6_V6ONLY=false for dual-stack listen sockets Change addresses type from Vec<SocketAddr> to Vec<String> Accept domain names in -a flag for client config export Warn when -a domain does not match any hostname in hosts.toml Update -a flag documentation to reflect domain name support Add unit tests for parse_endpoint_address Code quality improvements Unmap IPv6-mapped IPv4 addresses (::ffff:a.b.c.d) before rules evaluation Add more tests Code cleanup
TrustTunnel Deep-Link Library
A standalone Rust library for encoding and decoding TrustTunnel configuration deep-links using the tt:// URI scheme.
Features
- Complete TLV encoding/decoding - Implements the full TrustTunnel deep-link specification
- Error handling - Comprehensive error types with helpful messages
- Base64url encoding - URL-safe, compact representation
- Certificate support - PEM/DER conversion utilities
- Property-based testing - Verified with proptest for correctness
Installation
Add to your Cargo.toml:
[dependencies]
trusttunnel-deeplink = { git = "https://github.com/TrustTunnel/TrustTunnel/deeplink" }
Quick Start
Encoding a Configuration
use trusttunnel_deeplink::{encode, DeepLinkConfig};
use std::net::SocketAddr;
let config = DeepLinkConfig::builder()
.hostname("vpn.example.com".to_string())
.addresses(vec!["1.2.3.4:443".parse::<SocketAddr>().unwrap()])
.username("alice".to_string())
.password("secret123".to_string())
.build()
.unwrap();
let uri = encode(&config).unwrap();
println!("Deep-link: {}", uri);
// Output: tt://AQ92cG4uZXhhbXBsZS5jb20CAzEuMi4zLjQ6NDQzBQVhbGljZQYJc2VjcmV0MTIz
Decoding a Deep-Link
use trusttunnel_deeplink::decode;
let uri = "tt://AQ92cG4uZXhhbXBsZS5jb20CAzEuMi4zLjQ6NDQzBQVhbGljZQYJc2VjcmV0MTIz";
let config = decode(uri).unwrap();
println!("Hostname: {}", config.hostname);
println!("Username: {}", config.username);
Configuration Fields
The DeepLinkConfig struct supports the following fields:
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
hostname |
String |
Yes | - | Server hostname |
addresses |
Vec<SocketAddr> |
Yes | - | Server addresses (IP:port) |
username |
String |
Yes | - | Authentication username |
password |
String |
Yes | - | Authentication password |
custom_sni |
Option<String> |
No | None | Custom SNI for TLS |
has_ipv6 |
bool |
No | true |
IPv6 support enabled |
skip_verification |
bool |
No | false |
Skip certificate verification |
certificate |
Option<Vec<u8>> |
No | None | DER-encoded certificate chain |
upstream_protocol |
Protocol |
No | Http2 |
Upstream protocol (HTTP/2 or HTTP/3) |
anti_dpi |
bool |
No | false |
Anti-DPI measures enabled |
Advanced Usage
Working with Certificates
use trusttunnel_deeplink::cert::{pem_to_der, der_to_pem};
// Convert PEM certificate to DER
let pem = "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----";
let der = pem_to_der(pem).unwrap();
// Convert DER back to PEM
let pem_again = der_to_pem(&der).unwrap();
Builder Pattern
use trusttunnel_deeplink::{DeepLinkConfig, Protocol};
let config = DeepLinkConfig::builder()
.hostname("vpn.example.com".to_string())
.addresses(vec!["1.2.3.4:443".parse().unwrap()])
.username("user".to_string())
.password("pass".to_string())
.custom_sni(Some("cdn.example.org".to_string()))
.has_ipv6(false)
.upstream_protocol(Protocol::Http3)
.anti_dpi(true)
.build()
.unwrap();
Error Handling
The library uses a custom DeepLinkError type with specific error variants:
use trusttunnel_deeplink::{decode, DeepLinkError};
match decode("invalid://uri") {
Ok(config) => println!("Success!"),
Err(DeepLinkError::InvalidScheme(scheme)) => {
println!("Invalid URI scheme: {}", scheme);
}
Err(DeepLinkError::MissingRequiredField(field)) => {
println!("Missing required field: {}", field);
}
Err(e) => println!("Other error: {}", e),
}
Testing
Run the test suite:
# Unit tests
cargo test -p trusttunnel-deeplink
# Integration tests (roundtrip)
cargo test -p trusttunnel-deeplink --test roundtrip
# Python compatibility tests
cargo test -p trusttunnel-deeplink --test python_compat
# Property-based tests
cargo test -p trusttunnel-deeplink --test proptest