Windows SSHリモートログイン

Windows で SSH リモートアクセスを有効にするには、通常 Windows の OpenSSH 機能を使用する必要があります。以下は詳細な手順の説明です:

OpenSSH の確認とインストール

  1. OpenSSH がインストールされているか確認

    • 「設定」>「アプリ」>「アプリと機能」>「オプション機能の管理」を開く。
    • 既にインストールされたリストで「OpenSSH サーバー」を探す。存在すれば、すでにインストールされていることを意味する。
  2. OpenSSH のインストール

    • OpenSSH サーバーが見つからない場合は、「オプション機能の管理」ページで「機能の追加」をクリックし、リストから「OpenSSH サーバー」を見つけて「インストール」をクリックする。

OpenSSH サービスの起動と設定

  1. OpenSSH サービスの起動

    • インストールが完了したら、コマンドプロンプトを管理者として実行する。
    • net start sshd を入力して OpenSSH サービスを起動する。起動時に自動でサービスを開始したい場合は sc config sshd start= auto を入力する。
  2. ファイアウォールの設定

    • Windows ファイアウォールが SSH 接続を許可していることを確認する。「コントロールパネル」>「システムとセキュリティ」>「Windows Defender ファイアウォール」>「詳細設定」から入ってくるルールを作成し、TCP ポート 22 の接続を許可する。

IP アドレスの取得と接続テスト

  1. IP アドレスの取得

    • SSH サービスが有効化された Windows PC に別のマシンから接続するには、IP アドレスを知る必要がある。コマンドプロンプトで ipconfig コマンドを使用して、ローカルマシンの IP アドレスを確認できる。
  2. 接続テスト

    • 別の PC やモバイルデバイスで SSH クライアント(例:PuTTY、Termius など)を使用して、Windows PC に接続を試みる。フォーマットは ssh ユーザー名@IPアドレス で、ユーザー名 はログインしたい Windows アカウント名、IPアドレス は前述で取得した IP アドレスである。

設定の変更

パスワードログインの使用は絶対に避けるべき危険な行為です。必ず公開鍵を使用してログインしてください。パスワードログインを無効化し、公開鍵ログインを許可する設定を変更する必要があります。

この設定ファイルは通常の方法で変更するのは面倒です。特別な権限が必要で、ディレクトリとファイルの権限が特定の値である必要があります。ここではスクリプトを使用して変更することを推奨します。

# 管理者権限の確認
$elevated = [bool]([System.Security.Principal.WindowsPrincipal]::new(
    [System.Security.Principal.WindowsIdentity]::GetCurrent()
).IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator))

if (-not $elevated) {
    Write-Error "このスクリプトは管理者権限で実行してください"
    exit 1
}

# 1. OpenSSH サーバーの確認とインストール
Write-Host "OpenSSH サーバーのインストール状態を確認しています..."
$capability = Get-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0

if ($capability.State -ne 'Installed') {
    Write-Host "OpenSSH サーバーをインストールしています..."
    Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0 | Out-Null
}

# 2. SSH サービスの起動と自動起動設定
Write-Host "SSH サービスを設定しています..."
$service = Get-Service sshd -ErrorAction SilentlyContinue
if (-not $service) {
    Write-Error "OpenSSH サービスのインストールに失敗しました"
    exit 1
}

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

# 3. 設定ファイルの変更
$configPath = "C:\ProgramData\ssh\sshd_config"
if (Test-Path $configPath) {
    Write-Host "元の設定ファイルをバックアップしています..."
    Copy-Item $configPath "$configPath.bak" -Force
} else {
    Write-Error "設定ファイルが見つかりません: $configPath"
    exit 1
}

Write-Host "SSH 設定を変更しています..."
$config = Get-Content -Path $configPath -Raw

# 公開鍵認証を有効化し、パスワードログインを無効化
$config = $config -replace '^#?PubkeyAuthentication .*$','PubkeyAuthentication yes' `
                  -replace '^#?PasswordAuthentication .*$','PasswordAuthentication no'

# 必要な設定が含まれていることを確認
if ($config -notmatch 'PubkeyAuthentication') {
    $config += "`nPubkeyAuthentication yes"
}
if ($config -notmatch 'PasswordAuthentication') {
    $config += "`nPasswordAuthentication no"
}

# 設定ファイルに書き戻す
$config | Set-Content -Path $configPath -Encoding UTF8

authorized_keys ファイルの権限確認

# 通常ユーザー
$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"

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

ファイアウォールルールの設定

# SSH ポートを許可
New-NetFirewallRule -DisplayName "OpenSSH Server (sshd)" -Direction Inbound -Protocol TCP -Action Allow -LocalPort 22

公開鍵の追加

通常ユーザー

# 通常ユーザー
$userProfile = $env:USERPROFILE
$sshDir = Join-Path $userProfile ".ssh"
$authorizedKeysPath = Join-Path $sshDir "authorized_keys"
$PublicKeyPath = "D:\public_keys\id_rsa.pub"

# .ssh ディレクトリを作成
if (-not (Test-Path $sshDir)) {
    New-Item -ItemType Directory -Path $sshDir | Out-Null
}

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

# 公開鍵を追加
if (Test-Path $PublicKeyPath) {
    $pubKey = Get-Content -Path $PublicKeyPath -Raw
    if ($pubKey) {
        # 公開鍵の末尾に改行があることを確認
        if (-not $pubKey.EndsWith("`n")) {
            $pubKey += "`n"
        }

        # 公開鍵を追加
        Add-Content -Path $authorizedKeysPath -Value $pubKey -Encoding UTF8

        # ファイルの権限を設定
        $acl = Get-Acl $authorizedKeysPath
        $acl.SetSecurityDescriptorRule(
            (New-Object System.Security.AccessControl.FileSystemAccessRule(
                $currentUser, "FullControl", "None", "None", "Allow"
            ))
        )
        Set-Acl $authorizedKeysPath $acl
    }
} else {
    Write-Error "公開鍵ファイルが存在しません: $PublicKeyPath"
    exit 1
}

# SSH サービスを再起動
Write-Host "SSH サービスを再起動しています..."
Restart-Service sshd

管理者ユーザー

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

# 管理者 SSH ディレクトリを作成
if (-not (Test-Path $adminSshDir)) {
    New-Item -ItemType Directory -Path $adminSshDir | Out-Null
}

# 管理者 SSH ディレクトリの権限を設定
$adminAcl = Get-Acl $adminSshDir
$adminRule = New-Object System.Security.AccessControl.FileSystemAccessRule(
    "Administrators", "FullControl", "ContainerInherit,ObjectInherit", "None", "Allow"
)
$adminAcl.AddAccessRule($adminRule)
Set-Acl $adminSshDir $adminAcl

# 管理者公開鍵を追加
if (Test-Path $adminPublicKeyPath) {
    $adminPubKey = Get-Content -Path $adminPublicKeyPath -Raw
    if ($adminPubKey) {
        # 公開鍵の末尾に改行があることを確認
        if (-not $adminPubKey.EndsWith("`n")) {
            $adminPubKey += "`n"
        }

        # 公開鍵を追加
        Add-Content -Path $adminAuthKeysPath -Value $adminPubKey -Encoding UTF8

        # ファイルの権限を設定
        $adminAcl = Get-Acl $adminAuthKeysPath
        $adminAcl.SetSecurityDescriptorRule(
            (New-Object System.Security.AccessControl.FileSystemAccessRule(
                "Administrators", "FullControl", "None", "None", "Allow"
            ))
        )
        Set-Acl $adminAuthKeysPath $adminAcl
    }
} else {
    Write-Error "管理者公開鍵ファイルが存在しません: $adminPublicKeyPath"
    exit 1
}

# SSH サービスを再起動
Write-Host "SSH サービスを再起動しています..."
Restart-Service sshd