Note
Этот репозиторий является частью проекта "Феникс" и содержит конфигурацию для автоматической сборки Docker-образа сервера и клиента для протокола TrustTunnel в одном контейнере.
- Образ автоматически пересобирается каждое 1-е число месяца, подтягивая свежую версию TrustTunnel и обновленные зависимости.
- Публикация происходит в GitHub Container Registry —
ghcr.io/octohare/ttunnel-srvcli:latest
Образ ghcr.io/octohare/ttunnel-srvcli:latest собран из официальных репозиториев github.com/TrustTunnel:
TrustTunnel/TrustTunnel— серверная частьTrustTunnel/TrustTunnelClient— клиентская часть
Универсальный Docker-образ «2-в-1» объединяет функционал сервера и клиента TrustTunnel. Это избавляет от необходимости использовать разные образы и упрощает управление инфраструктурой:
- Вы можете поднять как серверную, так и клиентскую часть туннеля из одного и того же образа, просто изменив параметры Stack в Portainer.
- Больше не нужно плодить разные Docker-образы. Запускайте столько изолированных серверов и клиентов TrustTunnel на одном сервере, сколько требуется, используя единый базовый образ.
- Однообразное обновление и единый источник образов упрощают автоматическое поддержание туннелей в актуальном состоянии.
Important
Требования к окружению
Данная инструкция предполагает развертывание сервиса с помощью Stack в графической панели Portainer с использование сертификатов, выпущенных Caddy. Для выполнения описанных шагов на сервере должны быть заранее установлены Docker, Portainer и Caddy.
- Создаём каталог для настроек сервера:
mkdir -p /opt/trusttunnel/server-config
-
Создаём файл
vpn.toml, содержащий основные настройки сервера:listen_address— порт, который будет слушать сервер для входящих подключений.ipv6_available— укажитеtrueилиfalse, доступно ли подключение по IPv6 к данному серверу.
Все остальные параметры можно оставить по умолчанию.
cat << 'EOF' > /opt/trusttunnel/server-config/vpn.toml listen_address = "0.0.0.0:8443" ipv6_available = false allow_private_network_connections = false tls_handshake_timeout_secs = 10 client_listener_timeout_secs = 600 connection_establishment_timeout_secs = 30 tcp_connections_timeout_secs = 604800 udp_connections_timeout_secs = 300 credentials_file = "credentials.toml" rules_file = "rules.toml" [listen_protocols] [listen_protocols.http1] upload_buffer_size = 32768 [listen_protocols.http2] initial_connection_window_size = 8388608 initial_stream_window_size = 131072 max_concurrent_streams = 1000 max_frame_size = 16384 header_table_size = 65536 [listen_protocols.quic] recv_udp_payload_size = 1350 send_udp_payload_size = 1350 initial_max_data = 104857600 initial_max_stream_data_bidi_local = 1048576 initial_max_stream_data_bidi_remote = 1048576 initial_max_stream_data_uni = 1048576 initial_max_streams_bidi = 4096 initial_max_streams_uni = 4096 max_connection_window = 25165824 max_stream_window = 16777216 disable_active_migration = true enable_early_data = true message_queue_capacity = 4096 [forward_protocol] direct = {} EOF
С такими настройками сервер отправляет весь входящий трафик напрямую в интернет. Если необходимо перенаправлять трафик через SOCKS5-прокси, замените в файле
/opt/trusttunnel/server-config/vpn.tomlсекцию:[forward_protocol] direct = {}
на секцию:
[forward_protocol.socks5] address = "127.0.0.1:1080"
Порт для приёма трафика выберите любой свободный.
-
Создаём файл
hosts.tomlс указанием доменного имени и путей к сертификатам.
Заменитеtt_server_urlна ваш домен/субдомен сервера.cat << 'EOF' > /opt/trusttunnel/server-config/hosts.toml [[main_hosts]] hostname = "tt_server_url" cert_chain_path = "/etc/caddy/data/caddy/certificates/acme-v02.api.letsencrypt.org-directory/tt_server_url/tt_server_url.crt" private_key_path = "/etc/caddy/data/caddy/certificates/acme-v02.api.letsencrypt.org-directory/tt_server_url/tt_server_url.key" EOF
⚠️ Для корректного доступа к сертификатам в Portainer Stack отвечающий за Caddy должен отдавать каталог с сертификатами. Убедитесь, что в его конфигурации присутствует volume:volumes: - /etc/caddy/data:/data
-
Создаём файл
credentials.tomlс учётными данными для подключения к серверу.cat << 'EOF' > /opt/trusttunnel/server-config/credentials.toml [[client]] username = "connect_login_on_server" password = "connect_password_on_server" EOF
Дополнительные учётные записи добавляются копированием секции
[[client]]. Пример файла с несколькими пользователями:[[client]] username = "connect_login_on_server1" password = "connect_password_on_server1" [[client]] username = "connect_login_on_server2" password = "connect_password_on_server2" [[client]] username = "connect_login_on_server3" password = "connect_password_on_server3"
Одну учётную запись можно использовать для множества клиентов, если не требуется отдельная статистика и возможность блокировки отдельных подключений.
-
Создаём файл
rules.toml, отвечающий за права доступа. Пока он пустой — всем пользователям разрешено подключение.touch /opt/trusttunnel/server-config/rules.toml
-
Разворачиваем сервер TrustTunnel через Portainer:
- Переходим в раздел "Stacks".
- Нажимаем кнопку "+ Add stack".
- Задаём имя – Name:
tt-server. - В поле Web editor вставляем следующий код:
services: tt-server: image: ghcr.io/octohare/ttunnel-srvcli:latest container_name: tt-server restart: unless-stopped network_mode: host environment: - TT_MODE=server volumes: - /opt/trusttunnel/server-config:/trusttunnel:rw - /etc/caddy/data:/etc/caddy/data:ro logging: driver: "json-file" options: max-size: "10m" max-file: "2" healthcheck: test: ["CMD-SHELL", "ss -ltn | grep -q ':8443 '"] interval: 30s timeout: 5s retries: 3 start_period: 15s
- Нажимаем "Deploy the stack".
⚠️ В секцииhealthcheckобязательно замените порт8443на тот, который вы указали вvpn.tomlв параметреlisten_address.
Клиент можно настроить в двух режимах: SOCKS5-прокси или TUN VPN.
Создаём каталог для конфигурации клиента:
mkdir -p /opt/trusttunnel-client- Создаём файл
client.tomlс настройками подключения к серверу.
cat << 'EOF' > /opt/trusttunnel-client/client.toml loglevel = "info" vpn_mode = "general" [endpoint] hostname = "tt_server_url" addresses = ["tt_server_url:8443"] username = "connect_login_on_server" password = "connect_password_on_server" upstream_protocol = "http2" skip_verification = false has_ipv6 = false [listener.socks] address = "127.0.0.1:1080" EOF
Порт, на который будет отправляться трафик, выберите любой свободный и укажите в строке
address.
-
Разворачиваем клиент через Portainer:
- Переходим в раздел "Stacks".
- Нажимаем кнопку "+ Add stack".
- Задаём имя – Name:
tt-client. - В поле Web editor вставляем код:
services: tt-client-socks: image: ghcr.io/octohare/ttunnel-srvcli:latest container_name: tt-client restart: unless-stopped network_mode: host environment: - TT_MODE=client volumes: - /opt/trusttunnel-client:/trusttunnel:rw logging: driver: "json-file" options: max-size: "10m" max-file: "2" healthcheck: test: ["CMD-SHELL", "ss -ltn | grep -q ':1080 '"] interval: 30s timeout: 5s retries: 3 start_period: 10s
- Нажимаем "Deploy the stack".
⚠️ В секцииhealthcheckзамените порт1080на тот, который вы указали вclient.toml.
-
Создаём файл
client.tomlс настройками TUN-интерфейса.cat << 'EOF' > /opt/trusttunnel-client/client.toml loglevel = "info" vpn_mode = "general" [endpoint] hostname = "tt_server_url" addresses = ["tt_server_url:8443"] username = "connect_login_on_server" password = "connect_password_on_server" upstream_protocol = "http2" skip_verification = false has_ipv6 = false [listener.tun] 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 = 1350 change_system_dns = false EOF
- Разворачиваем клиент через Portainer:
-
Переходим в раздел "Stacks".
-
Нажимаем кнопку "+ Add stack".
-
Задаём имя – Name:
tt-client. -
В поле Web editor вставляем код:
services: tt-client-tun: image: ghcr.io/octohare/ttunnel-srvcli:latest container_name: tt-client restart: unless-stopped network_mode: host environment: - TT_MODE=client cap_add: - NET_ADMIN devices: - /dev/net/tun:/dev/net/tun volumes: - /opt/trusttunnel-client:/trusttunnel:rw logging: driver: "json-file" options: max-size: "10m" max-file: "2" healthcheck: test: ["CMD-SHELL", "ip link | grep -q 'tun'"] interval: 30s timeout: 5s retries: 3 start_period: 10s
-
Нажимаем "Deploy the stack".
-
Note
This repository is part of the "Phoenix" project and contains the configuration for automatic building of a Docker image combining both server and client for the TrustTunnel protocol in one container.
- The image is automatically rebuilt on the 1st of every month, pulling the latest version of TrustTunnel and updated dependencies.
- Published to GitHub Container Registry —
ghcr.io/octohare/ttunnel-srvcli:latest
The ghcr.io/octohare/ttunnel-srvcli:latest image is built from the official repositories at github.com/TrustTunnel:
TrustTunnel/TrustTunnel— the server partTrustTunnel/TrustTunnelClient— the client part
A universal "2-in-1" Docker image combines TrustTunnel server and client functionality. It eliminates the need for separate images and simplifies infrastructure management:
- You can deploy both the server and client sides of a tunnel from the same image by simply changing Stack parameters in Portainer.
- No more multiple Docker images to maintain. Run as many isolated TrustTunnel servers and clients on a single host as needed, using a single base image.
- Consistent updates and a single image source simplify automatic tunnel maintenance.
Important
Environment requirements
This guide assumes deployment of the service using a Stack in the Portainer graphical interface, with certificates issued by Caddy.
The server must have Docker, Portainer, and Caddy pre-installed to follow these steps.
- Create a directory for server configuration:
mkdir -p /opt/trusttunnel/server-config
-
Create the
vpn.tomlfile containing the basic server settings:listen_address— the port the server will listen on for incoming connections.ipv6_available— set totrueorfalse, depending on whether IPv6 connectivity is available to this server.
All other options can be left at their defaults.
cat << 'EOF' > /opt/trusttunnel/server-config/vpn.toml listen_address = "0.0.0.0:8443" ipv6_available = false allow_private_network_connections = false tls_handshake_timeout_secs = 10 client_listener_timeout_secs = 600 connection_establishment_timeout_secs = 30 tcp_connections_timeout_secs = 604800 udp_connections_timeout_secs = 300 credentials_file = "credentials.toml" rules_file = "rules.toml" [listen_protocols] [listen_protocols.http1] upload_buffer_size = 32768 [listen_protocols.http2] initial_connection_window_size = 8388608 initial_stream_window_size = 131072 max_concurrent_streams = 1000 max_frame_size = 16384 header_table_size = 65536 [listen_protocols.quic] recv_udp_payload_size = 1350 send_udp_payload_size = 1350 initial_max_data = 104857600 initial_max_stream_data_bidi_local = 1048576 initial_max_stream_data_bidi_remote = 1048576 initial_max_stream_data_uni = 1048576 initial_max_streams_bidi = 4096 initial_max_streams_uni = 4096 max_connection_window = 25165824 max_stream_window = 16777216 disable_active_migration = true enable_early_data = true message_queue_capacity = 4096 [forward_protocol] direct = {} EOF
With these settings, the server sends all incoming traffic directly to the internet. If you need to forward traffic through a SOCKS5 proxy, replace the section in
/opt/trusttunnel/server-config/vpn.toml:[forward_protocol] direct = {}
with:
[forward_protocol.socks5] address = "127.0.0.1:1080"
Choose any free port for traffic reception.
-
Create the
hosts.tomlfile with the domain name and certificate paths.
Replacett_server_urlwith your server's domain/subdomain.cat << 'EOF' > /opt/trusttunnel/server-config/hosts.toml [[main_hosts]] hostname = "tt_server_url" cert_chain_path = "/etc/caddy/data/caddy/certificates/acme-v02.api.letsencrypt.org-directory/tt_server_url/tt_server_url.crt" private_key_path = "/etc/caddy/data/caddy/certificates/acme-v02.api.letsencrypt.org-directory/tt_server_url/tt_server_url.key" EOF
⚠️ For correct access to certificates, the Portainer Stack responsible for Caddy must expose the certificates directory. Make sure its configuration includes the volume:volumes: - /etc/caddy/data:/data
-
Create the
credentials.tomlfile with authentication data for connecting to the server.cat << 'EOF' > /opt/trusttunnel/server-config/credentials.toml [[client]] username = "connect_login_on_server" password = "connect_password_on_server" EOF
Additional accounts are added by copying the
[[client]]section. Example of a file with multiple users:[[client]] username = "connect_login_on_server1" password = "connect_password_on_server1" [[client]] username = "connect_login_on_server2" password = "connect_password_on_server2" [[client]] username = "connect_login_on_server3" password = "connect_password_on_server3"
One account can be used for multiple clients, if per-client statistics and the ability to block individual connections are not required.
-
Create the
rules.tomlfile responsible for access permissions. While it remains empty, all created users are allowed to connect.touch /opt/trusttunnel/server-config/rules.toml
-
Deploy the TrustTunnel server via Portainer:
- Go to the "Stacks" section.
- Click the "+ Add stack" button.
- Set the name – Name:
tt-server. - In the Web editor field, paste the following code:
services: tt-server: image: ghcr.io/octohare/ttunnel-srvcli:latest container_name: tt-server restart: unless-stopped network_mode: host environment: - TT_MODE=server volumes: - /opt/trusttunnel/server-config:/trusttunnel:rw - /etc/caddy/data:/etc/caddy/data:ro logging: driver: "json-file" options: max-size: "10m" max-file: "2" healthcheck: test: ["CMD-SHELL", "ss -ltn | grep -q ':8443 '"] interval: 30s timeout: 5s retries: 3 start_period: 15s
- Click "Deploy the stack".
⚠️ In thehealthchecksection, make sure to replace the port8443with the one you set invpn.tomlunderlisten_address.
The client can be configured in two modes: SOCKS5 proxy or TUN VPN.
Create a directory for client configuration:
mkdir -p /opt/trusttunnel-client- Create the
client.tomlfile with connection settings to the server.
cat << 'EOF' > /opt/trusttunnel-client/client.toml loglevel = "info" vpn_mode = "general" [endpoint] hostname = "tt_server_url" addresses = ["tt_server_url:8443"] username = "connect_login_on_server" password = "connect_password_on_server" upstream_protocol = "http2" skip_verification = false has_ipv6 = false [listener.socks] address = "127.0.0.1:1080" EOF
Choose any free port for the traffic to be sent to, and specify it in the
addressline.
-
Deploy the client via Portainer:
- Go to the "Stacks" section.
- Click the "+ Add stack" button.
- Set the name – Name:
tt-client. - In the Web editor field, paste the following code:
services: tt-client-socks: image: ghcr.io/octohare/ttunnel-srvcli:latest container_name: tt-client restart: unless-stopped network_mode: host environment: - TT_MODE=client volumes: - /opt/trusttunnel-client:/trusttunnel:rw logging: driver: "json-file" options: max-size: "10m" max-file: "2" healthcheck: test: ["CMD-SHELL", "ss -ltn | grep -q ':1080 '"] interval: 30s timeout: 5s retries: 3 start_period: 10s
- Click "Deploy the stack".
⚠️ In thehealthchecksection, replace the port1080with the one you specified inclient.toml.
-
Create the
client.tomlfile with TUN interface settings.cat << 'EOF' > /opt/trusttunnel-client/client.toml loglevel = "info" vpn_mode = "general" [endpoint] hostname = "tt_server_url" addresses = ["tt_server_url:8443"] username = "connect_login_on_server" password = "connect_password_on_server" upstream_protocol = "http2" skip_verification = false has_ipv6 = false [listener.tun] 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 = 1350 change_system_dns = false EOF
- Deploy the client via Portainer:
- Go to the "Stacks" section.
- Click the "+ Add stack" button.
- Set the name – Name:
tt-client. - In the Web editor field, paste the following code:
services: tt-client-tun: image: ghcr.io/octohare/ttunnel-srvcli:latest container_name: tt-client restart: unless-stopped network_mode: host environment: - TT_MODE=client cap_add: - NET_ADMIN devices: - /dev/net/tun:/dev/net/tun volumes: - /opt/trusttunnel-client:/trusttunnel:rw logging: driver: "json-file" options: max-size: "10m" max-file: "2" healthcheck: test: ["CMD-SHELL", "ip link | grep -q 'tun'"] interval: 30s timeout: 5s retries: 3 start_period: 10s
- Click "Deploy the stack".