Windows SSH远程登录

Włączenie zdalnego dostępu SSH w systemie Windows zwykle wymaga użycia funkcji OpenSSH systemu Windows. Poniżej znajdują się szczegółowe instrukcje:

Sprawdzenie i zainstalowanie OpenSSH

  1. Sprawdzenie, czy OpenSSH jest zainstalowany

    • Otwórz „Ustawienia” > „Aplikacje” > „Aplikacje i funkcje” > „Zarządzaj opcjonalnymi funkcjami”。
    • Na liście zainstalowanych funkcji poszukaj „Serwer OpenSSH”。Jeśli istnieje, oznacza to, że został już zainstalowany.
  2. Zainstalowanie OpenSSH

    • Jeśli nie znajdziesz serwera OpenSSH, na stronie „Zarządzaj opcjonalnymi funkcjami” kliknij „Dodaj funkcję”, a następnie na liście znajdź „Serwer OpenSSH” i kliknij „Zainstaluj”。

Uruchomienie i skonfigurowanie usługi OpenSSH

  1. Uruchomienie usługi OpenSSH

    • Po zakończeniu instalacji otwórz wiersz polecenia (uruchom jako administrator).
    • Wpisz net start sshd, aby uruchomić usługę OpenSSH. Jeśli chcesz, aby usługa automatycznie uruchamiała się przy każdym uruchomieniu komputera, wpisz sc config sshd start= auto.
  2. Konfiguracja zapory

    • Upewnij się, że Zapora Windows zezwala na połączenia SSH. Możesz to zrobić przez przejście do „Panelu sterowania” > „System i zabezpieczenia” > „Zapora Windows Defender” > „Ustawienia zaawansowane”, a następnie utworzyć nową regułę przychodzącego ruchu, aby zezwolić na połączenia TCP na porcie 22.

Uzyskanie adresu IP i przetestowanie połączenia

  1. Uzyskanie adresu IP

    • Aby połączyć się z komputera, na którym włączono usługę SSH, z innego komputera, musisz znać jego adres IP. Możesz to sprawdzić w wierszu polecenia za pomocą polecenia ipconfig.
  2. Testowanie połączenia

    • Na innym komputerze lub urządzeniu mobilnym użyj klienta SSH (np. PuTTY, Termius itp.), aby spróbować połączyć się z Twoim komputerem z systemem Windows, używając formatu ssh nazwa_użytkownika@adres_ip. Gdzie nazwa_użytkownika to nazwa konta Windows, na które chcesz się zalogować, a adres_ip to adres IP, który wcześniej sprawdziłeś.

Modyfikacja konfiguracji

Należy unikać logowania się za pomocą hasła, jest to absolutny problem. Należy koniecznie używać klucza publicznego do logowania. Musimy zmodyfikować ustawienia, aby wyłączyć logowanie za pomocą hasła i umożliwić logowanie za pomocą klucza publicznego.

Ten plik konfiguracyjny nie jest wygodny do modyfikacji, wymaga on specjalnych uprawnień, a jednocześnie wymaga, aby uprawnienia katalogu i pliku były określonej wartości. Oto zalecane użycie skryptu do modyfikacji.

# Sprawdzenie uprawnień administratora
$elevated = [bool]([System.Security.Principal.WindowsPrincipal]::new(
    [System.Security.Principal.WindowsIdentity]::GetCurrent()
).IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator))

if (-not $elevated) {
    Write-Error "Uruchom ten skrypt jako administrator"
    exit 1
}

# 1. Sprawdzenie i zainstalowanie serwera OpenSSH
Write-Host "Sprawdzanie stanu instalacji serwera OpenSSH..."
$capability = Get-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0

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

# 2. Uruchomienie i skonfigurowanie automatycznego uruchamiania usługi SSH
Write-Host "Konfigurowanie usługi SSH..."
$service = Get-Service sshd -ErrorAction SilentlyContinue
if (-not $service) {
    Write-Error "Nie udało się zainstalować usługi OpenSSH"
    exit 1
}

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

# 3. Modyfikacja pliku konfiguracyjnego
$configPath = "C:\ProgramData\ssh\sshd_config"
if (Test-Path $configPath) {
    Write-Host "Tworzenie kopii zapasowej oryginalnego pliku konfiguracyjnego..."
    Copy-Item $configPath "$configPath.bak" -Force
} else {
    Write-Error "Nie znaleziono pliku konfiguracyjnego: $configPath"
    exit 1
}

Write-Host "Modyfikowanie konfiguracji SSH..."
$config = Get-Content -Path $configPath -Raw

# Włączenie uwierzytelniania kluczem publicznym i wyłączenie logowania hasłem
$config = $config -replace '^#?PubkeyAuthentication .*$','PubkeyAuthentication yes' `
                  -replace '^#?PasswordAuthentication .*$','PasswordAuthentication no'

# Upewnienie się, że zawiera niezbędne ustawienia
if ($config -notmatch 'PubkeyAuthentication') {
    $config += "`nPubkeyAuthentication yes"
}
if ($config -notmatch 'PasswordAuthentication') {
    $config += "`nPasswordAuthentication no"
}

# Zapisanie pliku konfiguracyjnego
$config | Set-Content -Path $configPath -Encoding UTF8

Potwierdzenie uprawnień pliku authorized_keys

# normal user
$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"

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

Ustawienia reguł zapory

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

Dodanie klucza publicznego

Zwykły użytkownik

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

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

# Ustawienie uprawnień katalogu .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

# Dodanie klucza publicznego
if (Test-Path $PublicKeyPath) {
    $pubKey = Get-Content -Path $PublicKeyPath -Raw
    if ($pubKey) {
        # Upewnienie się, że klucz publiczny kończy się znakiem nowej linii
        if (-not $pubKey.EndsWith("`n")) {
            $pubKey += "`n"
        }

        # Dołączenie klucza publicznego
        Add-Content -Path $authorizedKeysPath -Value $pubKey -Encoding UTF8

        # Ustawienie uprawnień pliku
        $acl = Get-Acl $authorizedKeysPath
        $acl.SetSecurityDescriptorRule(
            (New-Object System.Security.AccessControl.FileSystemAccessRule(
                $currentUser, "FullControl", "None", "None", "Allow"
            ))
        )
        Set-Acl $authorizedKeysPath $acl
    }
} else {
    Write-Error "Plik klucza publicznego nie istnieje: $PublicKeyPath"
    exit 1
}

# Restart usługi SSH
Write-Host "Restartowanie usługi SSH..."
Restart-Service sshd

Użytkownik administrator

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

# Utworzenie katalogu SSH administratora
if (-not (Test-Path $adminSshDir)) {
    New-Item -ItemType Directory -Path $adminSshDir | Out-Null
}

# Ustawienie uprawnień katalogu SSH administratora
$adminAcl = Get-Acl $adminSshDir
$adminRule = New-Object System.Security.AccessControl.FileSystemAccessRule(
    "Administrators", "FullControl", "ContainerInherit,ObjectInherit", "None", "Allow"
)
$adminAcl.AddAccessRule($adminRule)
Set-Acl $adminSshDir $adminAcl

# Dodanie klucza publicznego administratora
if (Test-Path $adminPublicKeyPath) {
    $adminPubKey = Get-Content -Path $adminPublicKeyPath -Raw
    if ($adminPubKey) {
        # Upewnienie się, że klucz publiczny kończy się znakiem nowej linii
        if (-not $adminPubKey.EndsWith("`n")) {
            $adminPubKey += "`n"
        }

        # Dołączenie klucza publicznego
        Add-Content -Path $adminAuthKeysPath -Value $adminPubKey -Encoding UTF8

        # Ustawienie uprawnień pliku
        $adminAcl = Get-Acl $adminAuthKeysPath
        $adminAcl.SetSecurityDescriptorRule(
            (New-Object System.Security.AccessControl.FileSystemAccessRule(
                "Administrators", "FullControl", "None", "None", "Allow"
            ))
        )
        Set-Acl $adminAuthKeysPath $adminAcl
    }
} else {
    Write-Error "Plik klucza publicznego administratora nie istnieje: $adminPublicKeyPath"
    exit 1
}

# Restart usługi SSH
Write-Host "Restartowanie usługi SSH..."
Restart-Service sshd