Skip to content

Instantly share code, notes, and snippets.

@ergolyam
Last active May 13, 2026 00:49
Show Gist options
  • Select an option

  • Save ergolyam/8e3e0408fc108247620c9ceff9eb25f6 to your computer and use it in GitHub Desktop.

Select an option

Save ergolyam/8e3e0408fc108247620c9ceff9eb25f6 to your computer and use it in GitHub Desktop.
Развёртывание dnstt на VPS в podman quadlet

Развёртывание dnstt на VPS в podman quadlet

Инструкция поднимает связку dnstt-server + SOCKS5-backend в podman-контейнерах через quadlet.

На клиенте вы запускаете dnstt-client и получаете локальный TCP-порт, который работает как вход в удалённый SOCKS5-прокси.

Везде, где указано example.com, подставьте свой домен.

Содержание

Требования и проверки перед стартом

Необходимо

  • VPS с белым IPv4 и доступом по SSH.
  • Домен, у которого вы можете создавать A, и NS записи.
  • Возможность опубликовать 53/udp именно на публичном IP VPS.
  • На VPS установлены:
    • podman версии >= 4.4
    • systemd версии >= 244

Проверка окружения

  1. Убедитесь, что 53/udp сейчас не опубликован на публичном IP VPS:

    ss -ulpn | grep '<public_ipv4>:53\b'
  2. Проверьте версии:

    podman --version
    systemctl --version

Подготовка окружения

1. Подготовьте DNS-зону

  • Создайте записи:
    • A tns.example.com -> IPv4_вашего_VPS
    • NS t.example.com -> tns.example.com

Метки tns и t можно заменить на свои, но t лучше держать короткой, а tns не должен быть поддоменом t. Например, tns.example.com и t.example.com подходят, а ns.t.example.com уже плохой вариант.

2. Создайте рабочие каталоги

mkdir -p /etc/containers/systemd

Системные настройки и сервисы

3. Создайте главный pod

# /etc/containers/systemd/main.pod
[Unit]
After=network-online.target

[Pod]
PublishPort=<public_ipv4>:53:53/udp

[Install]
WantedBy=default.target

Не используйте 0.0.0.0:53:53/udp в этом сценарии. Порт DNS лучше публиковать только на внешнем адресе VPS, чтобы не раздавать его на всех интерфейсах хоста.

4. Создайте сервис dnstt

# /etc/containers/systemd/dnstt.container
[Unit]
PartOf=main-pod.service

[Container]
Environment=DNS_ZONE=t.example.com
Image=ghcr.io/ergolyam/dnstt-docker:latest
AutoUpdate=registry
Pod=main.pod
Volume=dnstt:/data

[Service]
Restart=always
SuccessExitStatus=2

5. Создайте SOCKS5-backend

# /etc/containers/systemd/socks.container
[Unit]
PartOf=main-pod.service

[Container]
Environment=LISTEN_ADDRESS=127.0.0.1
Image=ghcr.io/ergolyam/hev-socks5-server-docker:latest
AutoUpdate=registry
Pod=main.pod

[Service]
Restart=always

Если нужен логин и пароль на SOCKS5, смотрите раздел Практические замечания.

Запуск и проверка

6. Запустите pod и контейнеры

systemctl daemon-reload
systemctl start main-pod.service
systemctl status dnstt.service --no-pager
systemctl status socks.service --no-pager
  • Проверьте, что порт 53/udp опубликован именно на внешнем IP:
    ss -ulpn | grep '<public_ipv4>:53\b'

7. Получите публичный ключ сервера

  • Этот ключ понадобится на клиенте.
    podman exec -it systemd-dnstt cat /data/server.pub

Подключение клиента

8. Скачайте dnstt-client

ARCH=$(uname -m); ARCH=${ARCH/x86_64/amd64}; ARCH=${ARCH/aarch64/arm64}
wget -O ${PREFIX:-$HOME/.local}/bin/dnstt-client "https://dnstt.network/dnstt-client-linux-${ARCH}"
chmod +x ${PREFIX:-$HOME/.local}/bin/dnstt-client

9. Запустите клиент

  • DoH:

    dnstt-client -doh https://1.1.1.1/dns-query -pubkey <PUBLIC_KEY_HEX> -utls random t.example.com 127.0.0.1:2080
  • DoT:

    dnstt-client -dot 1.1.1.1:853 -pubkey <PUBLIC_KEY_HEX> -utls random t.example.com 127.0.0.1:2080
  • UDP DNS:

    dnstt-client -udp 1.1.1.1:53 -pubkey <PUBLIC_KEY_HEX> -utls random t.example.com 127.0.0.1:2080

Plain UDP DNS легче детектируется и фильтруется, но именно он чаще остаётся доступным в ограниченных сетях. Для постоянного использования лучше оставаться на DoH или DoT.

10. Проверьте прокси

  • После запуска клиента проверьте, что локальный SOCKS5 действительно работает:
    curl --socks5-hostname 127.0.0.1:2080 --connect-timeout 10 https://ifconfig.me

Если всё собрано правильно, команда вернёт внешний IP вашего VPS.

Автообновление контейнеров

  • В quadlet уже задано:
    [Container]
    AutoUpdate=registry

    Это позволяет dnstt и socks автоматически подтягивать новые образы и перезапускаться через podman-auto-update.

1. Включите таймер автообновления

systemctl enable --now podman-auto-update.timer

2. Проверьте расписание

systemctl status podman-auto-update.timer --no-pager
systemctl list-timers | grep podman-auto-update

Практические замечания

  • dnstt аутентифицирует сервер, но не аутентифицирует клиента. Если кто-то знает ваш публичный ключ и имя зоны, он теоретически сможет пользоваться туннелем.
  • В этом сценарии 53/udp лучше публиковать адресно, например <public_ipv4>:53:53/udp, а не на 0.0.0.0. Это снижает риск случайно открыть DNS-сервис на лишних интерфейсах.
  • Если хотите закрыть SOCKS5 логином и паролем, добавьте в сервис socks переменные окружения:
    [Container]
    Environment=AUTH_ENABLED=true
    Environment=PROXY_USER=myuser
    Environment=PROXY_PASSWORD=mypassword
  • Тогда проверка на клиенте будет выглядеть так:
    curl --socks5-hostname 127.0.0.1:2080 --proxy-user myuser:mypassword https://ifconfig.me
  • Чем короче зона туннеля, тем больше полезной нагрузки помещается в DNS-запрос. Поэтому t.example.com лучше, чем что-то длинное вроде tunnel-dns.example.com.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment