add ProxyJump function

This commit is contained in:
redlineo committed 2026-07-23 12:38:13 +03:00
1 parent 56e20e5464
commit 7f0e0fdb23
48 files changed
+3875 -44

No files matched your search

+106
View File
@@ -4,6 +4,8 @@ import (
"fmt"
"strings"
"time"
"ssh-access-tui/internal/model"
)
func genTimestamp() string {
@@ -129,3 +131,107 @@ func RenderConfigUpdateInstructions(username string, forwards []AllocatedForward
b.WriteString("Если что-то не работает — обратитесь к администратору.\n")
return b.String()
}
// RenderInstructionsProxyJump is the ProxyJump-mode counterpart of
// RenderInstructions: same audience and same 4-file archive, but each
// service gets its own "Host <alias>" entry (see
// RenderClientConfigProxyJump) reached with a plain "ssh <alias>" instead of
// one always-open tunnel exposing local ports — steps 3/4 are adapted
// accordingly.
func RenderInstructionsProxyJump(username, keyFileName string, forwards []model.Forward) string {
var b strings.Builder
b.WriteString("КАК ПОДКЛЮЧИТЬСЯ (Windows)\n")
b.WriteString("===========================\n\n")
fmt.Fprintf(&b, "Ваш логин: %s\n\n", username)
b.WriteString("В этом архиве 4 файла:\n")
fmt.Fprintf(&b, " - %s — ваш секретный ключ (никому не передавайте и не пересылайте)\n", keyFileName)
fmt.Fprintf(&b, " - %s.pub — открытая часть ключа (можно не трогать)\n", keyFileName)
b.WriteString(" - config — настройка подключения\n")
b.WriteString(" - INSTRUCTIONS.txt — этот файл\n\n")
b.WriteString("ШАГ 1. Разложите файлы по нужной папке\n")
b.WriteString("---------------------------------------\n")
b.WriteString("Создайте (если её ещё нет) папку:\n\n")
b.WriteString(" C:\\Users\\ВАШЕ_ИМЯ\\.ssh\\\n\n")
fmt.Fprintf(&b, "И скопируйте туда все 3 файла из архива (%s, %s.pub, config).\n", keyFileName, keyFileName)
b.WriteString("Важно: у файла config не должно быть никакого расширения (не config.txt).\n\n")
b.WriteString("ШАГ 2. Настройте доступ к файлу ключа\n")
b.WriteString("----------------------------------------\n")
b.WriteString("Windows откажется использовать секретный ключ, если его может прочитать\n")
b.WriteString("кто-то ещё, кроме вас. Откройте PowerShell и выполните по очереди (это две\n")
b.WriteString("отдельные команды, копируйте и выполняйте одну за другой):\n\n")
fmt.Fprintf(&b, " icacls \"$env:USERPROFILE\\.ssh\\%s\" /inheritance:r\n", keyFileName)
fmt.Fprintf(&b, " icacls \"$env:USERPROFILE\\.ssh\\%s\" /grant:r \"${env:USERNAME}:(R)\"\n\n", keyFileName)
b.WriteString("Если файлы лежат не в стандартной папке .ssh, а где-то ещё — замените путь\n")
b.WriteString("в обеих командах на реальный путь к файлу ключа (в кавычках, как выше).\n\n")
b.WriteString("ШАГ 3. Подключайтесь\n")
b.WriteString("---------------------\n")
b.WriteString("Никакое окно держать открытым не нужно. Когда понадобится один из сервисов\n")
b.WriteString("из списка ниже, просто выполните в PowerShell соответствующую ему команду\n")
b.WriteString("\"ssh <название>\" — она сама пройдёт через промежуточный узел, отдельно\n")
b.WriteString("ничего для этого включать не нужно.\n\n")
b.WriteString("ШАГ 4. Ваши сервисы\n")
b.WriteString("---------------------\n")
aliases := hostAliases(forwards)
for i, f := range forwards {
what := f.ServiceName
if f.Description != "" {
what = fmt.Sprintf("%s (%s)", f.ServiceName, f.Description)
}
fmt.Fprintf(&b, " %d. ssh %s\n", i+1, aliases[i])
fmt.Fprintf(&b, " Это: %s\n", what)
fmt.Fprintf(&b, " Реально находится на: %s:%d\n\n", f.HostName, f.Port)
}
if len(forwards) == 0 {
b.WriteString(" (сервисы ещё не назначены — обратитесь к администратору)\n")
}
b.WriteString("\n")
b.WriteString("ЕСЛИ ЧТО-ТО НЕ РАБОТАЕТ\n")
b.WriteString("------------------------\n")
b.WriteString("Если команда из шага 4 сразу обрывается или пишет ошибку — обратитесь к\n")
b.WriteString("администратору, который выдал вам этот архив. Возможно, изменился список\n")
b.WriteString("сервисов — тогда вам пришлют обновлённый архив.\n")
return b.String()
}
// RenderConfigUpdateInstructionsProxyJump is the ProxyJump-mode counterpart
// of RenderConfigUpdateInstructions.
func RenderConfigUpdateInstructionsProxyJump(username string, forwards []model.Forward) string {
var b strings.Builder
b.WriteString("ОБНОВЛЕНИЕ СПИСКА СЕРВИСОВ\n")
b.WriteString("===========================\n\n")
fmt.Fprintf(&b, "Ваш логин: %s\n\n", username)
b.WriteString("Ваш ключ НЕ менялся — трогать его не нужно, продолжайте пользоваться тем же.\n")
b.WriteString("Изменился только список сервисов, поэтому нужно заменить один файл.\n\n")
b.WriteString("Замените файл config (из этого архива) на:\n\n")
b.WriteString(" C:\\Users\\ВАШЕ_ИМЯ\\.ssh\\config\n\n")
b.WriteString("(тот же путь, что и раньше — просто перезапишите старый файл новым).\n\n")
b.WriteString("Актуальный список сервисов (подключайтесь напрямую соответствующей командой):\n\n")
aliases := hostAliases(forwards)
for i, f := range forwards {
what := f.ServiceName
if f.Description != "" {
what = fmt.Sprintf("%s (%s)", f.ServiceName, f.Description)
}
fmt.Fprintf(&b, " %d. ssh %s\n", i+1, aliases[i])
fmt.Fprintf(&b, " Это: %s\n", what)
fmt.Fprintf(&b, " Реально находится на: %s:%d\n\n", f.HostName, f.Port)
}
if len(forwards) == 0 {
b.WriteString(" (сервисы не назначены — обратитесь к администратору)\n\n")
}
b.WriteString("Если что-то не работает — обратитесь к администратору.\n")
return b.String()
}