Pull request 110: Validate ip:port address during exporting client config

Squashed commit of the following:

commit 5e7fca63fc7dd9b53ffad0532191e859973eca40
Author: Andrey Yakushin <a.yakushin@adguard.com>
Date:   Tue Dec 23 13:22:47 2025 +0400

    Update docs

commit 86df6fd518ff998b944fddc5decbe4fe2379b953
Author: Andrey Yakushin <a.yakushin@adguard.com>
Date:   Tue Dec 23 13:13:54 2025 +0400

    Allow to specify address without port for client config

commit 1b9572bb0c05823628fe998c5eb3f5d87f286ceb
Author: Andrey Yakushin <a.yakushin@adguard.com>
Date:   Mon Dec 22 22:15:22 2025 +0400

    Validate ip:port address during exporting client config
This commit is contained in:
Andrey Yakushin
2025-12-23 13:01:22 +03:00
parent 99c497db25
commit cd656928bd
5 changed files with 27 additions and 12 deletions

View File

@@ -67,6 +67,9 @@ The endpoint binary accepts the following command line arguments:
./trusttunnel_endpoint vpn.toml hosts.toml --logfile /var/log/trusttunnel.log
# Export client configuration
./trusttunnel_endpoint vpn.toml hosts.toml -c username -a 203.0.113.1
# Export client configuration with explicit port
./trusttunnel_endpoint vpn.toml hosts.toml -c username -a 203.0.113.1:443
```

View File

@@ -211,9 +211,10 @@ To generate the configuration, run the following command:
```shell
# <client_name> - name of the client those credentials will be included in the configuration
# <public_ip_and_port> - `ip:port` that the user will use to connect to the endpoint
# <public_ip> - `ip` or `ip:port` that the user will use to connect to the endpoint
# If only `ip` is specified, the port from the `listen_address` field will be used
cd /opt/trusttunnel/
./trusttunnel_endpoint vpn.toml hosts.toml -c <client_name> -a <public_ip_and_port>
./trusttunnel_endpoint vpn.toml hosts.toml -c <client_name> -a <public_ip>
```
This will print the configuration with the credentials for the client named

View File

@@ -1,4 +1,6 @@
use log::{error, info, LevelFilter};
use std::net::SocketAddr;
use std::str::FromStr;
use std::sync::Arc;
use tokio::signal;
use trusttunnel::authentication::registry_based::RegistryBasedAuthenticator;
@@ -134,15 +136,23 @@ fn main() {
if args.contains_id(CLIENT_CONFIG_PARAM_NAME) {
let username = args.get_one::<String>(CLIENT_CONFIG_PARAM_NAME).unwrap();
let addresses: Vec<String> = args
let addresses: Vec<SocketAddr> = args
.get_many::<String>(ADDRESS_PARAM_NAME)
.map(Iterator::cloned)
.map(Iterator::collect)
.expect("Addresses should be specified");
.expect("At least one address should be specified")
.map(|x| {
SocketAddr::from_str(x)
.or_else(|_| {
SocketAddr::from_str(&format!("{}:{}", x, settings.get_listen_address().port()))
})
.unwrap_or_else(|_| {
panic!("Failed to parse address. Expected `ip` or `ip:port` format, found: `{}`", x);
})
})
.collect();
let client_config = client_config::build(
&username,
&addresses,
addresses,
settings.get_clients(),
&tls_hosts_settings,
);

View File

@@ -2,11 +2,12 @@ use crate::{authentication::registry_based, settings::TlsHostsSettings, utils::T
#[cfg(feature = "rt_doc")]
use macros::{Getter, RuntimeDoc};
use once_cell::sync::Lazy;
use std::net::SocketAddr;
use toml_edit::{value, Document};
pub fn build(
client: &String,
addresses: &Vec<String>,
addresses: Vec<SocketAddr>,
username: &Vec<registry_based::Client>,
hostsettings: &TlsHostsSettings,
) -> ClientConfig {
@@ -22,7 +23,7 @@ pub fn build(
ClientConfig {
hostname: host.hostname.clone(),
addresses: addresses.clone(),
addresses: addresses,
has_ipv6: true, // Hardcoded to true, client could change this himself
username: user.username.clone(),
password: user.password.clone(),
@@ -40,7 +41,7 @@ pub struct ClientConfig {
/// Endpoint host name, used for TLS session establishment
hostname: String,
/// Endpoint addresses.
addresses: Vec<String>,
addresses: Vec<SocketAddr>,
/// Whether IPv6 traffic can be routed through the endpoint
has_ipv6: bool,
/// Username for authorization
@@ -65,7 +66,7 @@ impl ClientConfig {
pub fn compose_toml(&self) -> String {
let mut doc: Document = TEMPLATE.parse().unwrap();
doc["hostname"] = value(&self.hostname);
let vec = toml_edit::Array::from_iter(self.addresses.iter());
let vec = toml_edit::Array::from_iter(self.addresses.iter().map(|x| x.to_string()));
doc["addresses"] = value(vec);
doc["has_ipv6"] = value(self.has_ipv6);
doc["username"] = value(&self.username);

View File

@@ -74,7 +74,7 @@ fn main() {
--hosts-settings hosts.toml
# After setup, export client configuration:
./trusttunnel_endpoint vpn.toml hosts.toml -c admin -a 203.0.113.1:443
./trusttunnel_endpoint vpn.toml hosts.toml -c admin -a 203.0.113.1
For detailed configuration options, see:
https://github.com/TrustTunnel/TrustTunnel/blob/master/CONFIGURATION.md