# Cloudflare Tunnel: SSH через Published Application Route > Обновлено: 2026-09-04 (итог отладки захода на Kraken) > Рабочий case с полными командами: `family/how-to/kraken-access.md` Генерализуемые выводы про то, как сделать **SSH через Cloudflare Tunnel** (`published application route`), чтобы вход работал `ssh user@host — через cloudflared на клиенте`. ## Ключевое правило: hostname должен быть 1-уровневым subdomain (БЕЗ точки до домена) **Симптом:** двухуровневый subdomain вида `ssh.kraken.qentra.top` (`ssh.kraken` + точка + `qentra.top`) НЕ работает как SSH/TLS через Cloudflare. Проверка (решающий факт) — на edge НЕТ TLS-терминации для 2-уровневого hostname: ```bash openssl s_client -connect ssh.kraken.qentra.top:443 -servername ssh.kraken.qentra.top # → SSL alert number 40 (handshake failure), "no peer certificate available" curl -s https://ssh.kraken.qentra.top # ssl=1 handshake failure ``` В отличие от 1-уровневого hostname (`kraken.qentra.top`), который отвечает: ```bash openssl s_client -connect kraken.qentra.top:443 ... # CN=qentra.top, verify ok ``` **Почему:** Universal SSL Cloudflare-зоны покрывает только `*.domain` (1 уровень wildcard) и сам `domain`. Он НЕ покрывает `*.sub.domain` (2 уровень). Для 2-уровневых нужен Advanced Certificate (SAN на полный двухуровневый wildcard) — обычно проще взять **одиночный subdomain**. > ⚠️ ПИТФОЛ: Cloudflare-точка в hostname (`a.b.domain`) = 2 уровня по SSL, точка НЕ безобидна. Рабочая замена — один уровень с дефисом: `ssh-kraken.qentra.top` (покрывается `*.qentra.top`). ## Правильная схема SSH через Tunnel (по доке Cloudflare) **На сервере/туннеле (Zero Trust):** - Tunnels → туннель → **Routes → Add route → Published application** - Service: **SSH** → `localhost:22` (или `:22`) - hostname использовать **одиночный** subdomain (`ssh-kraken.qentra.top`, не `ssh.kraken...`) **В Zero Trust Access:** - Access → **Applications → Add self-hosted** (тип SSH, browser rendering off) на тот же hostname, с политикой (Allow / Service Token). - SSH-route без Access Application не даёт клиенту пройти даже до авторизации: `cloudflared access login ` → `failed to get app info: ... tls: handshake failure`. **На клиенте** (cloudflared установлен): `~/.ssh/config`: ``` Host ssh-kraken.qentra.top HostName ssh-kraken.qentra.top User kraken ProxyCommand cloudflared access ssh --hostname %h ``` Первый раз — авторизация: `cloudflared access login ssh-kraken.qentra.top` (откроет SSO/браузер). Дальше `ssh kraken@ssh-kraken.qentra.top`. ## Client-side подводные камни - `cloudflared access login ` нельзя проверить по `HEAD https://` — SSH-kind hostname НЕ терминирует HTTP/TLS, поэтому `failed to get app info: tls: handshake failure` — ожидаемо, если на маршруте нет Access App. - `~/.cloudflared/*-org-token` = `not-available` означает, что cloudflared НЕ авторизован в Access org — разовый `cloudflared access login` обязателен. - Сам ssh к hostname:22 напрямую (без cloudflared в ProxyCommand) к проксированному DNS не работает — hostname за Cloudflare-Anycast, в туннель трафик попадает только через cloudflared-клиент. - `network_mode: host` (container cloudflared) — сервис напрямую видит локальные порты (sshd на `0.0.0.0:22`). ## Общий паттерн «жив, но шумит» cloudflared на origin без IPv6 Если у origin нет глобального IPv6 (роутер не выдаёт), cloudflared пытается поднять QUIC и по IPv6 → в логах постоянные `ERR ... write udp [::]->198.41.x.x:7844: sendmsg: network is unreachable`, соединения падают/retry. Туннель продолжает работать по IPv4-QUIC. Возможный фикс — заставить cloudflared использовать только IPv4. ## Связанные заметки - `family/how-to/kraken-access.md` — рабочий живой пример (hostname `ssh-kraken.qentra.top`, ingress, команды) - `family/how-to/kraken-portainer-access.md` — деплой cloudflared-контейнера и логи туннеля