Weboldal keresés

Telepítse az OpenSSH-kiszolgálót a Windows 10 rendszerre


A PowerShell 7 számos nyomós okot kínál az elfogadásra. Az egyik legjobb az SSH támogatása PowerShell távoli protokollként. Sajnos ez a téma nem jellemzően a Windows-központú IT-szakemberek számára jön elő. Tudom, hogy ez határozottan igaz az én esetemre, és egy hiányosságon dolgoztam. Pozitívum, hogy a Windows 10 az OpenSSH-klienst telepítve és használatra készen szállítja. De mi a helyzet az OpenSSH szerverrel? Windows platformokon engedélyeznie kell és konfigurálnia kell ezt az elemet, ha SSH-távolítást szeretne használni a PowerShellben. Természetesen szeretném ezt PowerShell-lel és távolról is megtenni. Először is szeretném megmutatni, hogyan kell beállítani az OpenSSH Server összetevőt Windows 10 rendszeren.

Kézi beállítás

Az OpenSSH Server összetevő Windows 10 rendszerben történő telepítéséhez szükséges PowerShell-parancsok meglehetősen egyszerűek. Először is szükségem van a képességekre. Ezeket a parancsokat interaktívan futtatom.

Get-WindowsCapability -online -name openssh.server* | Add-WindowsCapability -online

A Get-WindowsCapability-t helyettesítő karakterrel használom arra az esetre, ha a verziószám valamikor megváltozna. Látom ez működött.

Ezzel beállítja az sshd szolgáltatást, amely nem fut, és kézi indításra van beállítva. Be szeretném állítani, hogy a szolgáltatás automatikusan elinduljon és elinduljon.

Set-Service -Name sshd -StartupType Automatic
Start-Service -Name sshd

Egy dolgot tanultam az ssh-ről, különösen, ha PowerShell távvezérléssel szeretné használni, ez pedig az, hogy ellenőrizze, hogy az ssh működik-e a PowerShell-en kívül.

ssh localhost

Előfordulhat, hogy a rendszer felkéri a kulcsok elfogadására és a jelszó megadására. Ha a beállítás olyan, mint az enyém, akkor CMD-prompt jelenik meg. De lehet, hogy más shellt szeretne, amikor ssh-n keresztül csatlakozik. Vegye figyelembe, hogy még nem beszélek a PowerShell ssh-n keresztüli távirányításáról. Módosíthatja a rendszerleíró adatbázist a számítógépén.

$regPath = "HKLM:\SOFTWARE\OpenSSH\"
$regProperty = "DefaultShell"
$regValue = (Get-Command powershell.exe).source
Set-ItemProperty -Path $regPath -Name $regProperty -Value $regValue

A változtatásnak azonnalinak kell lennie, és nem szükséges az sshd szolgáltatás újraindítása. Az ssh használatával a localhosthoz való csatlakozáshoz most Windows PowerShell munkamenetet kapok. Nem sokba kerülne egy egyszerű PowerShell-szkript összeállítása a parancsok interaktív futtatásához.

Távoli telepítés

De ezt távolról szeretném megtenni. Van néhány Windows 10 virtuális gépem, amelyekhez ssh-val szeretnék csatlakozni. Hagyományos PowerShell távvezérlést kell használnom. Igen, használhat harmadik féltől származó eszközt, például a psexec.exe-t vagy valami olyasmit, mint a Desired State Configuration, de szeretnék ragaszkodni azokhoz az eszközökhöz és készségekhez, amelyek valószínűleg már rendelkeznek.

Miközben ezen dolgoztam, volt egy egyszerű PowerShell-szkriptem, amely az imént bemutatott lépéseket futtatta. Arra jutottam, hogy nem kell mást tennem, mint futtatni a szkriptet az Invoke-Command segítségével. Dehogy. Kiderült, hogy az Add-WindowsCapability parancs nem működik távoli munkamenetben. Ez nyilvánvalóan az igény szerinti telepítés ismert korlátozása. De nem hagytam, hogy ez megállítson. A végső megoldás egy ideiglenes ütemezett feladat létrehozása volt, amely hozzáadja az OpenSSH.Server-t RENDSZERként.

$Time = New-ScheduledTaskTrigger -At 23:59 -Once
$User = New-ScheduledTaskPrincipal System
$action = New-ScheduledTaskAction -Execute "PowerShell.exe" -Argument '-noprofile -command "& { Get-WindowsCapability -online -name openssh.server* | Add-WindowsCapability -online}"'
$tmpTask = Register-ScheduledTask -taskpath \ -TaskName "AddTask" -Trigger $Time -Principal $user -Action $Action
Start-ScheduledTask -TaskName AddTask

#give the task a chance to finish
Start-Sleep -Seconds 20

$tmpTask | Unregister-ScheduledTask -confirm:$false

Az aktiválási idő irreleváns, mert kézzel fogom elindítani a feladatot, majd eltávolítom. Amíg nem futok ilyen közel éjfélhez, rendben kell lennem.

Azt is szerettem volna, hogy a szkriptem támogassa a -WhatIf-et és Verbose kimenetet kínáljon, bár a kód távolról futott. Íme a forgatókönyv, amit kitaláltam.

#requires -version 5.1

<#
This is used to setup SSHD on a Windows 10 Client through PowerShell remoting

Sample usage
Verbose and Whatif
invoke-command -FilePath .\Setup-SSHServer.ps1 -ComputerName win10 -cred $artd -ArgumentList @("Continue",$True)

Verbose
invoke-command -FilePath .\Setup-SSHServer.ps1 -ComputerName win10 -cred $artd -ArgumentList @("Continue")
#>

[cmdletbinding(SupportsShouldProcess)]
param ([string]$VerboseOption = "SilentlyContinue", [bool]$WhatIfOption = $False)

$VerbosePreference = $VerboseOption
$WhatIfPreference = $WhatIfOption

Write-Verbose "Starting SSHD setup process"
Try {
    Write-Verbose "Testing for sshd service"
    $svc = Get-Service -Name sshd -ErrorAction Stop
    if ($svc.status -eq 'Running') {
        Write-Verbose "sshd service appears to be installed and running"
    }
    else {
        Write-Warning "sshd service found but it isn't running"
    }
    #take no further action
    Return "OpenSSH Server installation appears to be complete."
}
Catch {
    Write-Verbose "sshd service not found. Continuing with installation"
}

Write-Verbose "Testing OpenSSH.Server Windows capability"
if (-Not $svc) {
    Try {
        $cap = Get-WindowsCapability -Name OpenSSH.Server* -Online -ErrorAction Stop
        $cap | Out-String | Write-Verbose
    }
    Catch {
        Throw $_
    }
}

if ($cap.State -eq 'NotPresent' -And $cap.name -match "OpenSSH") {
    #install capability
    Try {
        Write-Verbose "Adding $($cap.name)"
        if ($pscmdlet.ShouldProcess($cap.Name)) {
            #installing with a Scheduledtask as System to get around the limitation
            #with Add-WindowsCapability in a PowerShell remoting session
            $Time = New-ScheduledTaskTrigger -At 23:59 -Once
            $User = New-ScheduledTaskPrincipal System
            $action = New-ScheduledTaskAction -Execute "PowerShell.exe" -Argument '-noprofile -command "& { Get-WindowsCapability -online -name openssh.server* | Add-WindowsCapability -online}"'
            $tmpTask = Register-ScheduledTask -taskpath \ -TaskName "AddTask" -Trigger $Time -Principal $user -Action $Action
            Start-ScheduledTask -TaskName AddTask

            #give the task a chance to finish
            Start-Sleep -Seconds 20

            $tmpTask | Unregister-ScheduledTask -confirm:$false
        } #Whatif
    }
    Catch {
        Throw $_
    }
}

Write-Verbose "Set sshd to auto start"
Try {
    if ($pscmdlet.ShouldProcess("sshd", "Configure service")) {
        Set-Service -Name sshd -StartupType Automatic -ErrorAction stop
        Write-Verbose "Start the sshd service"
        Start-Service -Name sshd -ErrorAction Stop
        Get-Service sshd | Select-Object -Property * | Out-String | Write-Verbose
    }
}
Catch {
    Write-Warning "There was a problem configuring the sshd service."
}

if (-Not $WhatIfOption) {
    #only display the summary if not using -WhatIf
    $msg = @"
SSH setup complete. Edit $ENV:ProgramData\ssh\sshd_config for additional configurations options
or to enable remoting under PowerShell 7.

You will need to restart the sshd service for changes to take effect.

"@
    Write-Host $msg -ForegroundColor green
}

Write-Verbose "Ending SSHD setup process."

A kód egy kicsit eltér attól, amit interaktívan futtatnál. Amikor futtatja az Invoke-Command parancsot, és megad egy fájlt, a PowerShell a fájl tartalmát szkriptblokkként kezeli, és egy távoli futási területen futtatja. Ezért a paraméterek nem tipikus függvényparaméterek. A Verbose és a WhatIf beállításokat az eredeti parancsból átadom a szkriptnek.

Invoke-Command -FilePath .\Setup-SSHServer.ps1 -ComputerName win10 -cred $artd -ArgumentList @("Continue", $True)

Ezzel Verbose és Whatif kimenetet kapok a távoli Windows 10 gépről. A szkript alapértelmezett értékekkel történő futtatása jól működik. Ha szeretné, hozzáadhatja a beállításjegyzék sorait az alapértelmezett shell beállításához. De végül be akarom állítani a PowerShell távvezérlést ssh-n keresztül, így nincs szükségem rájuk.

PowerShell 7 SSH távvezérlés

Van még egy utolsó lépés a távvezérlés ssh használatára való konfigurálásához, és ez a távoli gépen történik. Módosítania kell az sshd_config fájlt, amely a $env:ProgramData\ssh fájlban található. Íme az én példányom, amelyet a szükséges PowerShell-követelmények szerint szerkesztettek.

# This is the sshd server system-wide configuration file.  See
# sshd_config(5) for more information.

# The strategy used for options in the default sshd_config shipped with
# OpenSSH is to specify options with their default value where
# possible, but leave them commented.  Uncommented options override the
# default value.

#Port 22
#AddressFamily any
#ListenAddress 0.0.0.0
#ListenAddress ::

#HostKey __PROGRAMDATA__/ssh/ssh_host_rsa_key
#HostKey __PROGRAMDATA__/ssh/ssh_host_dsa_key
#HostKey __PROGRAMDATA__/ssh/ssh_host_ecdsa_key
#HostKey __PROGRAMDATA__/ssh/ssh_host_ed25519_key

# Ciphers and keying
#RekeyLimit default none

# Logging
#SyslogFacility AUTH
#LogLevel INFO

# Authentication:

#LoginGraceTime 2m
#PermitRootLogin prohibit-password
#StrictModes yes
#MaxAuthTries 6
#MaxSessions 10

#ENABLED
PubkeyAuthentication yes

# The default is to check both .ssh/authorized_keys and .ssh/authorized_keys2
# but this is overridden so installations will only check .ssh/authorized_keys
AuthorizedKeysFile	.ssh/authorized_keys

#AuthorizedPrincipalsFile none

# For this to work you will also need host keys in %programData%/ssh/ssh_known_hosts
#HostbasedAuthentication no
# Change to yes if you don't trust ~/.ssh/known_hosts for
# HostbasedAuthentication
#IgnoreUserKnownHosts no
# Don't read the user's ~/.rhosts and ~/.shosts files
#IgnoreRhosts yes

# To disable tunneled clear text passwords, change to no here!
# ENABLED: Set this to YES for PowerShell remoting
PasswordAuthentication yes

#PermitEmptyPasswords no

#AllowAgentForwarding yes
#AllowTcpForwarding yes
#GatewayPorts no
#PermitTTY yes
#PrintMotd yes
#PrintLastLog yes
#TCPKeepAlive yes
#UseLogin no
#PermitUserEnvironment no
#ClientAliveInterval 0
#ClientAliveCountMax 3
#UseDNS no
#PidFile /var/run/sshd.pid
#MaxStartups 10:30:100
#PermitTunnel no
#ChrootDirectory none
#VersionAddendum none

# no default banner path
#Banner none

# override default of no subsystems
Subsystem	sftp	sftp-server.exe
#ADDED
Subsystem     powershell c:\progra~1\powershell\7\pwsh.exe -sshs -NoLogo

# Example of overriding settings on a per-user basis
#Match User anoncvs
#	AllowTcpForwarding no
#	PermitTTY no
#	ForceCommand cvs server

Match Group administrators
       AuthorizedKeysFile __PROGRAMDATA__/ssh/administrators_authorized_keys

A szervezettől függően további változtatásokra lehet szükség. A PowerShell segítségével átmásolhatom ezt a fájlt a távoli számítógépre, feltéve, hogy az OpenSSH.Server és a PowerShell 7 telepítve van.

Copy-Item -Path .\sshd_config_default -Destination $env:ProgramData\ssh\sshd_config -ToSession $sess

Az sshd szolgáltatást újra kell indítani, hogy a változtatások életbe lépjenek.

Telepítés

Az utolsó lépés az, hogy mindezt összevonjuk egy fő vezérlőszkriptbe. Úgy döntöttem, hogy hozzáadok kódot a PowerShell 7 telepítéséhez a PSReleaseTools modul segítségével.

#requires -version 5.1

#Deployment control script to setup SSH server on a remote Windows 10 desktop
#It is assumed PowerShell 7 is, or will be, installed.

[cmdletbinding(SupportsShouldProcess)]
Param(
    [Parameter(Position = 0, Mandatory)]
    [string]$Computername,
    [pscredential]$Credential,
    [switch]$InstallPowerShell
)

#remove parameters from PSBoundparameter that don't apply to New-PSSession
if ($PSBoundParameters.ContainsKey("InstallPowerShell")) {
    [void]($PSBoundParameters.remove("InstallPowerShell"))
}

if ($PSBoundParameters.ContainsKey("WhatIf")) {
    [void]($PSBoundParameters.remove("WhatIf"))
}

#parameters for Write-Progress
$prog = @{
    Activity = "Deploy SSH Server to Windows 10"
    Status = $Computername.toUpper()
    CurrentOperation = ""
    PercentComplete = 0
}
#create the PSSession
Try {
    Write-Verbose "Creating a PSSession to $Computername"
    $prog.CurrentOperation = "Creating a temporary PSSession"
    $prog.PercentComplete = 10
    Write-Progress @prog
    $sess = New-PSSession @PSBoundParameters -ErrorAction Stop
}
Catch {
    Throw $_
}

if ($sess) {
    if ($InstallPowerShell) {
        $prog.currentOperation = "Installing PowerShell 7"
        $prog.percentComplete = 25
        Write-Progress @prog
        #install PowerShell
        if ($pscmdlet.ShouldProcess($Computername.toUpper(),"Install PowerShell 7")) {

            Invoke-Command -ScriptBlock {
                [void](Install-PackageProvider -Name nuget -force -forcebootstrap)
                Install-Module PSReleaseTools -Force
                Install-PowerShell -EnableRemoting -EnableContextMenu -mode Quiet
            } -session $sess
        } #whatif
    }

    #setup SSH
    $prog.currentOperation = "Installing OpenSSH Server"
    $prog.percentComplete = 50
    Write-Progress @prog
    Invoke-Command -FilePath .\Setup-SSHServer.ps1 -Session $sess -ArgumentList @($VerbosePreference, $WhatIfPreference)

    #copy the sshd_config file. This assumes you've installed PowerShell 7 on the remote computer
    Write-Verbose "Copying sshd_config to target"
    $prog.currentOperation = "Copying default sshd_config to target"
    $prog.percentcomplete = 60
    Write-Progress @prog
    Copy-Item -Path .\sshd_config_default -Destination $env:ProgramData\ssh\sshd_config -ToSession $sess

    #restart the service
    Write-Verbose "Restarting the sshd service on the target"
    $prog.currentOperation = "Restarting the ssh service target"
    $prog.percentComplete = 75
    Write-Progress @prog
    if ($pscmdlet.ShouldProcess("sshd","Restart service")) {
        Invoke-Command { Restart-Service -Name sshd } -Session $sess
    }

    Write-Verbose "Removing the temporary PSSession"
    $prog.currentOperation = "Removing temporary PSSession"
    $prog.percentComplete = 90
    Write-Progress @prog
    $sess | Remove-PSSession

    Write-Progress @prog -completed
    $msg = @"

SSH Server deployment complete for $($Computername.toUpper()).

If PowerShell 7 is installed remotely, you should be able to test
with an expression like:

Enter-PSSession -hostname $Computername -username <user> -sshtransport

"@

    Write-Host $msg -ForegroundColor yellow
} #if $sess

Valószínűleg jobb hibakezelést kellene hozzáadnom az sshd szolgáltatás konfigurálásához, de ennek be kell állítania mindent, hogy ezt megtehessem:

Következő lépések

Az ssh-val és a PowerShell-lel végzett Windows-utazásom következő része a Windows-kiszolgálóim konfigurálása. Ha ez megtörtént, szinte mindenre használhatom a PowerShell távvezérlést ssh-n keresztül. holnap belemerülök ebbe.

Kapcsolódó cikkek