Accesso remoto SSH su Windows

Per abilitare l’accesso remoto SSH su Windows è solitamente necessario utilizzare la funzionalità OpenSSH di Windows. Di seguito sono riportati i passaggi dettagliati:

Verifica e installazione di OpenSSH

  1. Verifica se OpenSSH è già installato:

    • Apri “Impostazioni” > “App” > “App e funzionalità” > “Gestisci funzionalità facoltative”.
    • Nell’elenco delle funzionalità già installate cerca “Server OpenSSH”. Se presente, significa che è già stato installato.
  2. Installa OpenSSH:

    • Se non trovi il Server OpenSSH, puoi cliccare su “Aggiungi una funzionalità” nella pagina “Gestisci funzionalità facoltative”, quindi cercare “Server OpenSSH” nell’elenco e cliccare su “Installa”.

Avvia e configura il servizio OpenSSH

  1. Avvia il servizio OpenSSH:

    • Dopo l’installazione, apri il Prompt dei comandi (eseguito come amministratore).
    • Digita net start sshd per avviare il servizio OpenSSH. Per far sì che il servizio si avvii automaticamente all’accensione, digita sc config sshd start= auto.
  2. Configura il firewall:

    • Assicurati che il Firewall di Windows consenta le connessioni SSH. Puoi accedere a “Pannello di controllo” > “Sistema e sicurezza” > “Windows Defender Firewall” > “Impostazioni avanzate”, quindi creare una nuova regola in entrata per consentire le connessioni sulla porta TCP 22.

Ottieni l’indirizzo IP e testa la connessione

  1. Ottieni l’indirizzo IP:

    • Per connetterti da un altro computer a questo PC Windows con SSH attivo, devi conoscere il suo indirizzo IP. Puoi visualizzare l’indirizzo IP del tuo computer usando il comando ipconfig nel Prompt dei comandi.
  2. Test della connessione:

    • Su un altro computer o dispositivo mobile, usa un client SSH (ad esempio: PuTTY, Termius, ecc.) per provare a connetterti al tuo PC Windows, usando il formato ssh nome_utente@indirizzo_ip. Dove nome_utente è il nome dell’account Windows a cui desideri accedere e indirizzo_ip è l’indirizzo IP che hai trovato in precedenza.

Modifica della configurazione

Attenzione a non utilizzare l’accesso con password, questo è un assoluto tabù. È fondamentale utilizzare la chiave pubblica per l’accesso. Dobbiamo modificare le impostazioni, disabilitare l’accesso con password e consentire l’accesso con chiave pubblica.

Questo file di configurazione è scomodo da modificare, richiede permessi speciali e inoltre è necessario garantire che le autorizzazioni della directory e del file siano specifiche. Si consiglia di utilizzare uno script per la modifica.

# Controlla i permessi di amministratore
$elevated = [bool]([System.Security.Principal.WindowsPrincipal]::new(
    [System.Security.Principal.WindowsIdentity]::GetCurrent()
).IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator))

if (-not $elevated) {
    Write-Error "Esegui questo script come amministratore"
    exit 1
}

# 1. Controlla e installa il server OpenSSH
Write-Host "Sto verificando lo stato di installazione del server OpenSSH..."
$capability = Get-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0

if ($capability.State -ne 'Installed') {
    Write-Host "Sto installando il server OpenSSH..."
    Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0 | Out-Null
}

# 2. Avvia e configura il servizio SSH per l'avvio automatico
Write-Host "Sto configurando il servizio SSH..."
$service = Get-Service sshd -ErrorAction SilentlyContinue
if (-not $service) {
    Write-Error "Installazione del servizio OpenSSH fallita"
    exit 1
}

if ($service.Status -ne 'Running') {
    Start-Service sshd
}
Set-Service sshd -StartupType Automatic

# 3. Modifica il file di configurazione
$configPath = "C:\ProgramData\ssh\sshd_config"
if (Test-Path $configPath) {
    Write-Host "Sto creando il backup del file di configurazione originale..."
    Copy-Item $configPath "$configPath.bak" -Force
} else {
    Write-Error "File di configurazione non trovato: $configPath"
    exit 1
}

Write-Host "Sto modificando la configurazione SSH..."
$config = Get-Content -Path $configPath -Raw

# Abilita l'autenticazione con chiave pubblica e disabilita l'accesso con password
$config = $config -replace '^#?PubkeyAuthentication .*$','PubkeyAuthentication yes' `
                  -replace '^#?PasswordAuthentication .*$','PasswordAuthentication no'

# Assicurati che contenga le configurazioni necessarie
if ($config -notmatch 'PubkeyAuthentication') {
    $config += "`nPubkeyAuthentication yes"
}
if ($config -notmatch 'PasswordAuthentication') {
    $config += "`nPasswordAuthentication no"
}

# Scrivi nuovamente il file di configurazione
$config | Set-Content -Path $configPath -Encoding UTF8

Conferma autorizzazioni file authorized_keys

# utente normale
$authKeys = "$env:USERPROFILE\.ssh\authorized_keys"
icacls $authKeys /inheritance:r /grant "$($env:USERNAME):F" /grant "SYSTEM:F"
icacls "$env:USERPROFILE\.ssh" /inheritance:r /grant "$($env:USERNAME):F" /grant "SYSTEM:F"

# amministratore
$adminAuth = "C:\ProgramData\ssh\administrators_authorized_keys"
icacls $adminAuth /inheritance:r /grant "Administrators:F" /grant "SYSTEM:F"

Configurazione regole firewall

# Consenti porta SSH
New-NetFirewallRule -DisplayName "OpenSSH Server (sshd)" -Direction Inbound -Protocol TCP -Action Allow -LocalPort 22

Aggiunta chiavi pubbliche

Utente normale

# utente normale
$userProfile = $env:USERPROFILE
$sshDir = Join-Path $userProfile ".ssh"
$authorizedKeysPath = Join-Path $sshDir "authorized_keys"
$PublicKeyPath = "D:\public_keys\id_rsa.pub"

# Crea directory .ssh
if (-not (Test-Path $sshDir)) {
    New-Item -ItemType Directory -Path $sshDir | Out-Null
}

# Imposta autorizzazioni directory .ssh
$currentUser = "$env:USERDOMAIN\$env:USERNAME"
$acl = Get-Acl $sshDir
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule(
    $currentUser, "FullControl", "ContainerInherit,ObjectInherit", "None", "Allow"
)
$acl.AddAccessRule($rule)
Set-Acl $sshDir $acl

# Aggiungi chiave pubblica
if (Test-Path $PublicKeyPath) {
    $pubKey = Get-Content -Path $PublicKeyPath -Raw
    if ($pubKey) {
        # Assicurati che la chiave pubblica termini con un carattere di nuova riga
        if (-not $pubKey.EndsWith("`n")) {
            $pubKey += "`n"
        }

        # Aggiungi la chiave pubblica
        Add-Content -Path $authorizedKeysPath -Value $pubKey -Encoding UTF8

        # Imposta autorizzazioni file
        $acl = Get-Acl $authorizedKeysPath
        $acl.SetSecurityDescriptorRule(
            (New-Object System.Security.AccessControl.FileSystemAccessRule(
                $currentUser, "FullControl", "None", "None", "Allow"
            ))
        )
        Set-Acl $authorizedKeysPath $acl
    }
} else {
    Write-Error "File chiave pubblica non trovato: $PublicKeyPath"
    exit 1
}

# Riavvia servizio SSH
Write-Host "Sto riavviando il servizio SSH..."
Restart-Service sshd

Utente amministratore

# amministratore
$adminSshDir = "C:\ProgramData\ssh"
$adminAuthKeysPath = Join-Path $adminSshDir "administrators_authorized_keys"
$adminPublicKeyPath = "D:\public_keys\id_rsa.pub"

# Crea directory SSH amministratore
if (-not (Test-Path $adminSshDir)) {
    New-Item -ItemType Directory -Path $adminSshDir | Out-Null
}

# Imposta autorizzazioni directory SSH amministratore
$adminAcl = Get-Acl $adminSshDir
$adminRule = New-Object System.Security.AccessControl.FileSystemAccessRule(
    "Administrators", "FullControl", "ContainerInherit,ObjectInherit", "None", "Allow"
)
$adminAcl.AddAccessRule($adminRule)
Set-Acl $adminSshDir $adminAcl

# Aggiungi chiave pubblica amministratore
if (Test-Path $adminPublicKeyPath) {
    $adminPubKey = Get-Content -Path $adminPublicKeyPath -Raw
    if ($adminPubKey) {
        # Assicurati che la chiave pubblica termini con un carattere di nuova riga
        if (-not $adminPubKey.EndsWith("`n")) {
            $adminPubKey += "`n"
        }

        # Aggiungi la chiave pubblica
        Add-Content -Path $adminAuthKeysPath -Value $adminPubKey -Encoding UTF8

        # Imposta autorizzazioni file
        $adminAcl = Get-Acl $adminAuthKeysPath
        $adminAcl.SetSecurityDescriptorRule(
            (New-Object System.Security.AccessControl.FileSystemAccessRule(
                "Administrators", "FullControl", "None", "None", "Allow"
            ))
        )
        Set-Acl $adminAuthKeysPath $adminAcl
    }
} else {
    Write-Error "File chiave pubblica amministratore non trovato: $adminPublicKeyPath"
    exit 1
}

# Riavvia servizio SSH
Write-Host "Sto riavviando il servizio SSH..."
Restart-Service sshd