fix: pin verified host key in saved PuTTY sessions
Some checks failed
Bash syntax / syntax (push) Successful in 19s
Bash syntax / panel-catalog (push) Failing after 27s
Bash syntax / syntax (pull_request) Successful in 20s
Bash syntax / panel-catalog (pull_request) Failing after 3s

This commit is contained in:
ochenstarik-ui 2026-10-24 16:14:12 +07:00
parent 65a99b1939
commit d4e7e67905
3 changed files with 6 additions and 5 deletions

View file

@ -81,7 +81,7 @@ function Get-PanelRegistryPlan($Record, [string]$KeyPath) {
$entry = ConvertTo-PanelSession $Record $entry = ConvertTo-PanelSession $Record
if ([string]::IsNullOrWhiteSpace($KeyPath) -or $KeyPath -match '[\x00-\x1f]') { throw 'Select your existing private key file.' } if ([string]::IsNullOrWhiteSpace($KeyPath) -or $KeyPath -match '[\x00-\x1f]') { throw 'Select your existing private key file.' }
return [pscustomobject]@{ return [pscustomobject]@{
Strings=@{HostName=$entry.HostName; Protocol='ssh'; UserName=$entry.UserName; PublicKeyFile=$KeyPath; PortForwardings=('L127.0.0.1:' + $entry.LocalPort + '=127.0.0.1:' + $entry.RemotePort)} Strings=@{HostName=$entry.HostName; Protocol='ssh'; UserName=$entry.UserName; PublicKeyFile=$KeyPath; SSHManualHostKeys=$entry.Fingerprint; PortForwardings=('L127.0.0.1:' + $entry.LocalPort + '=127.0.0.1:' + $entry.RemotePort)}
Numbers=@{PortNumber=$entry.PortNumber; LocalPortAcceptAll=0; RemotePortAcceptAll=0; SshNoShell=1; PingInterval=0; PingIntervalSecs=30; TCPKeepalives=1; AgentFwd=0; GssapiFwd=0; ProxyMethod=0; LogType=0} Numbers=@{PortNumber=$entry.PortNumber; LocalPortAcceptAll=0; RemotePortAcceptAll=0; SshNoShell=1; PingInterval=0; PingIntervalSecs=30; TCPKeepalives=1; AgentFwd=0; GssapiFwd=0; ProxyMethod=0; LogType=0}
Arguments=('-load ' + $entry.Name + ' -N -hostkey ' + $entry.Fingerprint) Arguments=('-load ' + $entry.Name + ' -N -hostkey ' + $entry.Fingerprint)
PanelUrl=('http://127.0.0.1:' + $entry.LocalPort + $entry.PanelPath) PanelUrl=('http://127.0.0.1:' + $entry.LocalPort + $entry.PanelPath)

View file

@ -1,4 +1,4 @@
Панели 3x-ui: общий установщик сессий PuTTY для Windows Панели 3x-ui: общий установщик сессий PuTTY для Windows
БЫСТРОЕ НАЧАЛО БЫСТРОЕ НАЧАЛО
1. Распакуйте ZIP целиком в отдельную папку. Не запускайте файл внутри ZIP. 1. Распакуйте ZIP целиком в отдельную папку. Не запускайте файл внутри ZIP.
@ -51,9 +51,9 @@ connections.example.json — только шаблон. Его адрес и о
Для восстановления сессии импортируйте соответствующий *-previous.reg; старый ярлык Для восстановления сессии импортируйте соответствующий *-previous.reg; старый ярлык
скопируйте из той же backup-папки на рабочий стол. Остальные серверы не переустанавливаются. скопируйте из той же backup-папки на рабочий стол. Остальные серверы не переустанавливаются.
Если установка остановится, окно покажет уже установленные записи и папку резервных копий. Если установка остановится, окно покажет уже установленные записи и папку резервных копий.
Ярлык PuTTY передаёт -hostkey с точным отпечатком и открывает forwarding только на127.0.0.1. Проверенный отпечаток сохраняется в сессии PuTTY и передаётся ярлыком через -hostkey.
При ручном запуске сохранённой сессии из самого PuTTY также сверяйте host key; Предыдущий список разрешённых ручных ключей этой сессии заменяется точным отпечатком.
не нажимайте Accept при неожиданной смене ключа. Туннель использует удалённый127.0.0.1. Forwarding слушает только 127.0.0.1. При смене ключа проверьте его в консоли сервера. Туннель использует удалённый127.0.0.1.
Если локальный порт занят, закройте прежнее окно туннеля этой панели либо выберите другой порт. Если локальный порт занят, закройте прежнее окно туннеля этой панели либо выберите другой порт.
Система с корпоративным запретом PowerShell/WinForms может блокировать запуск: Система с корпоративным запретом PowerShell/WinForms может блокировать запуск:
общие ограничения безопасности установщик не отключает. общие ограничения безопасности установщик не отключает.

View file

@ -53,6 +53,7 @@ $plan=Get-PanelRegistryPlan $catalog.Sessions[2] $key
Assert-Panel ($plan.Strings.PublicKeyFile -ceq $key) 'Key path with spaces must remain data.' Assert-Panel ($plan.Strings.PublicKeyFile -ceq $key) 'Key path with spaces must remain data.'
Assert-Panel ($plan.Strings.PortForwardings -ceq 'L127.0.0.1:18055=127.0.0.1:2053') 'Tunnel must bind loopback and target remote loopback.' Assert-Panel ($plan.Strings.PortForwardings -ceq 'L127.0.0.1:18055=127.0.0.1:2053') 'Tunnel must bind loopback and target remote loopback.'
Assert-Panel ($plan.Numbers.LocalPortAcceptAll -eq 0 -and $plan.Numbers.AgentFwd -eq 0 -and $plan.Numbers.ProxyMethod -eq 0) 'Unsafe forwarding/proxy settings.' Assert-Panel ($plan.Numbers.LocalPortAcceptAll -eq 0 -and $plan.Numbers.AgentFwd -eq 0 -and $plan.Numbers.ProxyMethod -eq 0) 'Unsafe forwarding/proxy settings.'
Assert-Panel ($plan.Strings.SSHManualHostKeys -ceq $catalog.Sessions[2].Fingerprint) 'Saved session must replace any previous manual host key allowlist.'
Assert-Panel ($plan.Arguments -ceq ('-load KAgent-DK-panel -N -hostkey SHA256:'+('A'*43))) 'Shortcut must pin the exact host key.' Assert-Panel ($plan.Arguments -ceq ('-load KAgent-DK-panel -N -hostkey SHA256:'+('A'*43))) 'Shortcut must pin the exact host key.'
Assert-Panel ($plan.PanelUrl -ceq 'http://127.0.0.1:18055/private-panel/') 'Browser URL must stay loopback.' Assert-Panel ($plan.PanelUrl -ceq 'http://127.0.0.1:18055/private-panel/') 'Browser URL must stay loopback.'
Expect-Rejection { Get-PanelRegistryPlan $ru '' } 'Missing key path must be rejected.' Expect-Rejection { Get-PanelRegistryPlan $ru '' } 'Missing key path must be rejected.'