Files
Ilia Zhirov 356ab493c7 Pull request 672: AG-45460 investigate a possible memory leakage in tcp ip exacerbated by a large tcp wnd
Squashed commit of the following:

commit d42104fb3d981c63b7fd43dc737dd6ee892c084e
Author: Ilia Zhirov <i.zhirov@adguard.com>
Date:   Fri May 1 00:00:36 2026 +0500

    Add missing tcp buffer fields to test initializer

commit e6621d489e473bbe0622b80a9171b912ca5d5722
Author: Ilia Zhirov <i.zhirov@adguard.com>
Date:   Thu Apr 30 23:38:18 2026 +0500

    Fix dead_code warning in setup_wizard template

commit bb55ad9f624db71d6dc693d2d083f40595e75423
Merge: 3d9054bc 07ea7045
Author: Ilia Zhirov <i.zhirov@adguard.com>
Date:   Thu Apr 30 23:34:51 2026 +0500

    Merge branch 'master' into AG-45460-investigate-a-possible-memory-leakage-in-tcp-ip-exacerbated-by-a-large-tcp_wnd
    
    # Conflicts:
    #	CHANGELOG.md

commit 3d9054bc25d2ead3666e56580b3b1508e9883f70
Author: Ilia Zhirov <i.zhirov@adguard.com>
Date:   Thu Apr 30 23:32:37 2026 +0500

    Update CHANGELOG, README, and setup_wizard template with new fields

commit 280303cb0620ef836a9d498d645553be21c78918
Author: Ilia Zhirov <i.zhirov@adguard.com>
Date:   Fri Apr 24 21:12:09 2026 +0500

    Increase trimming interval to 30 minutes

commit 32f5b6dea2a48e26b7c4fdcf59d1de860ad77fe3
Author: Ilia Zhirov <i.zhirov@adguard.com>
Date:   Fri Apr 24 15:54:22 2026 +0500

    Remove tcp_active_pcbs guard

commit 61c2fdb9bf98a26dd3802b9332069c541ecf742e
Author: Ilia Zhirov <i.zhirov@adguard.com>
Date:   Mon Apr 20 21:39:57 2026 +0500

    Use runtime GetProcAddress for HeapSetInformation on Windows

commit f63455eee7
Author: Ilia Zhirov <i.zhirov@adguard.com>
Date:   Thu Apr 16 17:07:00 2026 +0500

    Set trim interval to 3 minutes

commit ae95ade304
Author: Ilia Zhirov <i.zhirov@adguard.com>
Date:   Thu Apr 16 14:22:07 2026 +0500

    Fix build

commit c9cbda67d1
Author: Ilia Zhirov <i.zhirov@adguard.com>
Date:   Wed Apr 15 20:43:14 2026 +0500

    Use proper Windows way to reclaim memory

commit 313925709f
Author: Ilia Zhirov <i.zhirov@adguard.com>
Date:   Wed Apr 15 16:55:51 2026 +0500

    Add cross-platform heap trimming (macOS, Windows)

commit 0ba49793d7
Author: Ilia Zhirov <i.zhirov@adguard.com>
Date:   Tue Apr 14 22:59:47 2026 +0500

    Use proper glibc guard

commit 70b9583348
Author: Ilia Zhirov <i.zhirov@adguard.com>
Date:   Tue Apr 14 21:00:16 2026 +0500

    Add runtime TCP buffer size configuration

commit 29f93f4275
Author: Ilia Zhirov <i.zhirov@adguard.com>
Date:   Mon Apr 13 23:05:10 2026 +0500

    Increase TCP buffer sizes from 32KB to 256KB

commit 8120df6faf
Author: Ilia Zhirov <i.zhirov@adguard.com>
Date:   Mon Apr 13 21:14:58 2026 +0500

    Call malloc_trim to release heap pages after TCP connections close
2026-05-04 12:27:49 +00:00

11 KiB

TrustTunnel CLI Client

TrustTunnel CLI Client is an application built on top of the TrustTunnel Client Libraries. It provides an easy-to-use interface to configure and connect to a TrustTunnel endpoint. The client supports Linux, macOS, and Windows platforms.


Building

To build the TrustTunnel CLI Client, follow development instructions. The built executable will be available in the <project_root>/build/trusttunnel_client directory.


Configuration

The TrustTunnel CLI Client accepts a TOML-formatted configuration file. You can use the setup wizard tool to generate a basic configuration file.

Setup Wizard Tool

Usage

For quick setup, please follow Getting Started instructions.

For a more customized configuration experience, follow the steps below:

  1. Build the setup wizard tool.

  2. Launch the setup wizard:

    ./setup_wizard
    

    The setup wizard will guide you through the configuration process, allowing you to customize the settings according to your preferences.

Note: The configuration file created by the setup wizard contains all available settings, including descriptions. Feel free to modify them if you have a good understanding of the configuration.

Setup Wizard CLI Options

Usage: setup_wizard [OPTIONS]

Options:
  -m, --mode <mode>           Wizard running mode [default: interactive]
                              * interactive - guided setup with prompts
                              * non-interactive - automated setup from CLI args
  -a, --address <address>     Endpoint address (can be specified multiple times)
  -n, --hostname <host>       Endpoint hostname for TLS session
  -c, --creds <creds>         Credentials as <username>:<password>
      --cert <cert>           Path to endpoint certificate file
      --settings <settings>   Output path for settings file (required in non-interactive mode)
  -e, --endpoint_config <path>
                              Path to config generated by endpoint (conflicts with -a, -n, -c)
  -h, --help                  Print help

Examples

Interactive mode (guided setup):

./setup_wizard

Non-interactive with endpoint config (recommended):

./setup_wizard --mode non-interactive \
    --endpoint_config <endpoint_config.toml> \
    --settings trusttunnel_client.toml

Non-interactive with manual parameters:

./setup_wizard --mode non-interactive \
    --address 192.168.1.100:443 \
    --hostname vpn.example.com \
    --creds myuser:mypassword \
    --cert server.pem \
    --settings trusttunnel_client.toml

Configuration Reference

The configuration file uses TOML format. Below are all available settings.

Top-Level Settings

Variable Type Default Description
loglevel string "info" Logging level: info, debug, trace
vpn_mode string "general" Routing policy: general (route all except exclusions) or selective (route only exclusions)
killswitch_enabled bool true Block traffic when VPN connection is lost
killswitch_allow_ports array[int] [] Local ports to allow inbound connections when kill switch is active
post_quantum_group_enabled bool true Enable post-quantum key exchange in TLS handshakes
exclusions array[string] [] Domains/IPs to route specially based on vpn_mode
dns_upstreams array[string] [] Legacy. Kept only for backward compatibility with old configs; prefer [endpoint].dns_upstreams instead

Endpoint Settings ([endpoint])

Variable Type Default Description
hostname string required Endpoint hostname for TLS session establishment
addresses array[string] required Endpoint addresses as IP:port or hostname:port (pinger selects best)
has_ipv6 bool true Whether IPv6 traffic can be routed through endpoint
username string required Authorization username
password string required Authorization password
client_random string "" TLS client random prefix and mask (hex, format: prefix[/mask])
skip_verification bool false Skip endpoint certificate verification (accepts any cert)
certificate string null Endpoint certificate in PEM format (uses system store if empty)
upstream_protocol string "http2" Protocol: http2 or http3
anti_dpi bool false Enable anti-DPI (Deep Packet Inspection) measures
dns_upstreams array[string] [] DNS resolvers for queries routed through VPN. If empty, AdGuard DNS unfiltered is used

TUN Listener Settings ([listener.tun])

Variable Type Default Description
bound_if string auto-detected Network interface for VPN client connections (Linux/Windows/macOS: auto)
included_routes array[string] ["0.0.0.0/0", "2000::/3"] Routes in CIDR notation to set to the virtual interface
excluded_routes array[string] ["0.0.0.0/8", "10.0.0.0/8", "169.254.0.0/16", "172.16.0.0/12", "192.168.0.0/16", "224.0.0.0/3"] Routes in CIDR notation to exclude from VPN routing
mtu_size int 1280 MTU size on the virtual interface
tcp_recv_buf_size int 0 TCP receive window size in bytes. 0 = optimized default (256 KB). Adjust only for constrained environments
tcp_send_buf_size int 0 TCP send buffer size in bytes. 0 = optimized default (256 KB). Adjust only for constrained environments
change_system_dns bool true Allow changing system DNS servers
device_name string "" On Linux, the TUN interface name (empty = kernel-assigned). On Windows, the Wintun adapter name (empty = auto-generated from hostname). On macOS, request a specific utun<N> unit (empty = kernel-assigned).
use_existing bool false Attach to a pre-existing TUN device named device_name instead of creating one. Requires device_name. Linux only.

To disable route management on any supported platform, set included_routes = []. On Linux this also suppresses cleanup of table 880 and the associated ip rule entries; on Windows, DNS-only route handling remains controlled by change_system_dns.

SOCKS Listener Settings ([listener.socks])

Variable Type Default Description
address string "127.0.0.1:1080" IP address and port to bind the SOCKS5 proxy
username string null Username for SOCKS authentication (optional)
password string null Password for SOCKS authentication (optional)

Exclusions Syntax

The exclusions array supports the following formats:

  • Domain name: example.com — matches example.com and www.example.com
  • Wildcard domain: *.example.com — matches any subdomain (e.g., sub.example.com), but not the domain itself
  • IPv4 address: 192.168.1.1 or 192.168.1.1:443 (port optional)
  • IPv6 address: [::1] or [::1]:443 or 2001:db8::1
  • CIDR range: 192.168.0.0/16 or 2001:db8::/32
  • Wildcard port: *:80 — matches any connection to the specified port regardless of destination address

DNS Upstreams Syntax

The dns_upstreams array supports the following formats:

  • Plain DNS: 8.8.8.8:53
  • DNS over TCP: tcp://8.8.8.8:53
  • DNS over TLS: tls://1.1.1.1
  • DNS over HTTPS: https://dns.adguard.com/dns-query
  • DNS over QUIC: quic://dns.adguard.com:8853
  • DNS Stamp: sdns://... (see DNS Stamps specification)

Example Configuration

loglevel = "info"
vpn_mode = "general"
killswitch_enabled = true
killswitch_allow_ports = []
post_quantum_group_enabled = true
exclusions = []

[endpoint]
hostname = "vpn.example.com"
addresses = ["192.168.1.100:443"]
has_ipv6 = true
username = "myuser"
password = "mypassword"
client_random = ""
skip_verification = false
certificate = ""
dns_upstreams = ["tls://1.1.1.1"]
upstream_protocol = "http2"
anti_dpi = false

[listener.tun]
bound_if = ""
# For OpenWrt with external policy routing (`pbr`, `mwan3`):
# device_name = "tt0"
# use_existing = true
# included_routes = []
included_routes = ["0.0.0.0/0", "2000::/3"]
excluded_routes = ["10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16"]
mtu_size = 1280
# Uncomment to tune TCP window size (bytes). Default 0 uses optimized values (256 KB).
# It is recommended to leave defaults unless you have specific requirements.
# tcp_recv_buf_size = 0
# tcp_send_buf_size = 0

Usage

Windows specific: For tunnel listener to work, wintun.dll must be in the DLL search path. Basically, you could download it, extract the file (from the folder matching your architecture, like amd64) and place it into the same directory as trusttunnel_client executable.

To run the TrustTunnel CLI Client, execute the following command:

./trusttunnel_client --config <path/to/configuration/file.toml>

Replace <path/to/configuration/file.toml> with the actual path to your configuration file. You may need to run the command with superuser privileges if a TUN device is selected.


Windows Service (Windows Only)

The TrustTunnel CLI Client can be installed as a Windows service, allowing it to run in the background without requiring an interactive console session.

Note

: Both install and uninstall commands require Administrator privileges. Run the command from an elevated Command Prompt or PowerShell.

Installing the Service

trusttunnel_client --service-install --config <path/to/trusttunnel_client.toml>

The command validates the configuration file before registering the service. If validation fails, the service is not installed. The config path is resolved to an absolute path and baked into the service registration — the service will always start with that config file.

The service is registered with automatic start type (SERVICE_AUTO_START) and is started immediately after installation.

Starting and Stopping the Service

After installation, use the standard Windows service management commands:

cmd.exe:

sc start TrustTunnelClient
sc stop TrustTunnelClient

PowerShell:

Start-Service TrustTunnelClient
Stop-Service TrustTunnelClient

Querying Service Status

cmd.exe:

sc query TrustTunnelClient

PowerShell:

Get-Service TrustTunnelClient

Disabling Auto-Start

To switch the service to manual start:

cmd.exe:

sc config TrustTunnelClient start= demand

PowerShell:

Set-Service TrustTunnelClient -StartupType Manual

Uninstalling the Service

trusttunnel_client --service-uninstall

If the service is currently running, it will be stopped automatically before removal.

Notes

  • If the configuration file is moved or deleted after installation, the service will fail to start. Reinstall the service with the new config path.
  • The --service-install and --service-uninstall options are only available on Windows builds.