OpenSSH'yi Windows Server'a dağıtın


Dün, uzak bir Windows 10 sisteminde ssh sunucu bileşeninin uzaktan kurulumuna ilişkin bazı PowerShell fikirlerini paylaşmıştım. Bu, masaüstünde bir ssh oturumu oluşturmanıza ve hatta ssh üzerinden PowerShell uzaktan iletişimini kullanmanıza olanak tanır. Daha sonra aynı şeyi Windows Sunucuları için yapmaya bakmalıyız.

Windows Sunucusu 2019

Windows Server 2019 kullanıyorsanız, en azından deneyimlerime dayanarak Windows 10 ile kullandığım kodun aynısını kullanabilirsiniz. Windows Server 2019, Add-WindowsCapability ile yükleyebileceğiniz OpenSSH.Server özelliğini içerir. PowerShell 7 ve sshd'yi yüklemek için Windows 10'da kullandığım dağıtım komut dosyasının aynısını kullanabildim. Yaptığım tek değişiklik Yazma İlerleme etkinliğindeydi.

$prog = @{
    Activity = "Deploy SSH Server to Windows 10/Windows Server 2019"
    Status = $Computername.toUpper()
    CurrentOperation = ""
    PercentComplete = 0
}

Aksi takdirde her şey aynı şekilde çalıştı ve birkaç dakika içinde PowerShell 7 ve ssh uzaktan iletişimi kullanıma hazır hale geldi.

Windows Sunucusu 2016

Windows Server 2016 için kurulum biraz farklıdır. Bulabildiğim Microsoft belgelerine göre GitHub'un en son bitlerini yüklemeniz gerekiyor. Bunu Invoke-Webrequest ile yapabilirsiniz. Ancak herhangi bir şey yapmadan önce büyük olasılıkla ağ güvenliğini yapılandırmanız gerekecektir.

[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12

Bunu Windows Server 2016'da yapmazsanız GitHub'a ve PowerShell Galerisine bağlanmaya çalışırken hatalar alırsınız. Zip dosyası indirildikten sonra dosyayı çıkarabilir ve ardından kurulum komut dosyasını çalıştırabilirsiniz. İşte sunucu odaklı PowerShell betiği.

#requires -version 5.1

<#
    setup SSHD on Windows Server 2016
    https://github.com/PowerShell/Win32-OpenSSH/wiki/Install-Win32-OpenSSH

    This script is designed to be run remotely using Invoke-Command

    Sample usage:
    Verbose and Whatif
    invoke-command -FilePath .\Setup-SSHServer2.ps1 -ComputerName srv1 -cred $admin -ArgumentList @("Continue",$True)

    Verbose
    invoke-command -FilePath .\Setup-SSHServer2.ps1 -ComputerName srv1 -cred $admin -ArgumentList @("Continue")
#>

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

$VerbosePreference = $VerboseOption
$WhatIfPreference = $WhatIfOption

[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$url = 'https://github.com/PowerShell/Win32-OpenSSH/releases/latest/'
$request = [System.Net.WebRequest]::Create($url)
$request.AllowAutoRedirect = $false
$response = $request.GetResponse()
$dl = $([String]$response.GetResponseHeader("Location")).Replace('tag', 'download') + '/OpenSSH-Win64.zip'

$zip = "C:\OpenSSH64.zip"
Write-Verbose "download SSH from $dl to $zip"
if ($pscmdlet.ShouldProcess($dl,"Downloading OpenSSH-Win64 Package")) {
    Try {
        Invoke-WebRequest -Uri $dl -OutFile $zip -DisableKeepAlive -ErrorAction Stop
    }
    Catch {
        Throw $_
    }
    if (Test-Path $zip) {
        Write-Verbose "Extract zip file"
        Expand-Archive $zip -DestinationPath "c:\Program Files" -force
    }
    else {
        Return "zip file failed to download"
    }
}

Write-Verbose "Install SSH"
if ($pscmdlet.ShouldProcess("install-sshd.ps1", "Execute")) {
    Push-Location
    Set-Location -Path 'C:\Program Files\OpenSSH-Win64\'
    . .\install-sshd
    Pop-Location
}

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."
}

Write-Verbose "Add the firewall rule"
if ($pscmdlet.ShouldProcess("sshd", "Add firewall rule")) {
    Try {
        $rule = New-NetFirewallRule -Name sshd -DisplayName 'OpenSSH Server (sshd)' -Enabled True -Direction Inbound -Protocol TCP -Action Allow -LocalPort 22 -ErrorAction Stop
        Write-Verbose ($rule | Out-String)
    }
    Catch {
        Throw $_
    }
}

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."

Komut dosyasının Windows 10 sürümünde olduğu gibi, bu da Invoke-Command kullanılarak uzaktan çalıştırılacak şekilde tasarlanmıştır. Ve elbette bir kontrol senaryom var.

#requires -version 5.1

#Deployment control script to setup SSH server on a remote Windows Server 2016
#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 Server 2016"
    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) {
        Write-Verbose "Installing PowerShell 7"
        $prog.currentOperation = "Installing PowerShell 7"
        $prog.percentComplete = 25
        Write-Progress @prog
        #install PowerShell
        if ($pscmdlet.ShouldProcess($Computername.toUpper(), "Install PowerShell 7")) {
            Invoke-Command -ScriptBlock {
                #need to set security protocol to Tls12 for Windows Server 2016 otherwise the installs will fail
                Write-Verbose "Setting network security to Tls12"
                [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
                Write-Verbose "Using Security Protocol $([Net.ServicePointManager]::SecurityProtocol)"
                [void](Install-PackageProvider -Name nuget -force -forcebootstrap -minimumversion '2.8.5.201')
                Install-Module PSReleaseTools -Force -Scope AllUsers -Repository PSGallery
                Install-PowerShell -EnableRemoting -EnableContextMenu -Mode Quiet
            } -Session $sess

            #Installing PowerShell may break the session so rebuild it if necessary
            if ($sess.state -eq 'Broken') {
                Write-Verbose "Rebuilding the temporary PSSession"
                $sess = New-PSSession @PSBoundParameters -ErrorAction Stop
            }
        } #whatif
    } #if install PowerShell 7

    #setup SSH
    $prog.currentOperation = "Installing OpenSSH Server"
    $prog.percentComplete = 50
    Write-Progress @prog
    Invoke-Command -FilePath .\Setup-SSHServer2.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
else {
    #this should never get called
    Write-Warning "Failed to create a temporary session to $Computername."
}

Komut dosyası -Verbose ve -WhatIf'i destekler.

Betik, önceki yazıdan alabileceğiniz sshd_config_default dosyasını kopyalayacaktır. Bir kez yerleştirildikten sonra PowerShell 7'de ssh ile uzaktan iletişim çocuk oyuncağıdır.

Sonraki adımlar

Bu kodun tamamını üretim dışı bir ortamda test etmeli ve gerekiyorsa ayarlamalısınız. Uzaktan iletişimle her oynadığınızda kendinizi savunmasız bırakma riskiyle karşı karşıya kalırsınız. Bu sürecin bir kısmı ssh hakkında daha fazla bilgi edinmeyi içermelidir. Yaptığım tek şey onu kurmak ve PowerShell ile çalışabilmek. Ssh için çok daha fazlası var

Yorum ve sorularınızı bekliyoruz.

İlgili makaleler