Inicio de sesión remoto SSH en Windows

Habilitar el acceso remoto SSH en Windows generalmente requiere el uso de la función OpenSSH de Windows. A continuación se muestra una explicación detallada de los pasos:

Verificar e instalar OpenSSH

  1. Verificar si OpenSSH está instalado:

    • Abra “Configuración” > “Aplicaciones” > “Aplicaciones y funciones” > “Administrar características opcionales”.
    • En la lista de instalados busque “Servidor OpenSSH”. Si aparece, significa que ya está instalado.
  2. Instalar OpenSSH:

    • Si no encuentra el Servidor OpenSSH, en la página “Administrar características opcionales” haga clic en “Agregar característica” y luego en la lista busque “Servidor OpenSSH” y haga clic en “Instalar”.

Iniciar y configurar el servicio OpenSSH

  1. Iniciar el servicio OpenSSH:

    • Después de la instalación, abra el símbolo del sistema (ejecútelo como administrador).
    • Ingrese net start sshd para iniciar el servicio OpenSSH. Si desea que el servicio se inicie automáticamente cada vez que arranque el equipo, ingrese sc config sshd start= auto.
  2. Configurar el firewall:

    • Asegúrese de que el Firewall de Windows permita conexiones SSH. Puede hacerlo a través de “Panel de control” > “Sistema y seguridad” > “Firewall de Windows Defender” > “Configuración avanzada”, luego cree una nueva regla de entrada para permitir la conexión en el puerto TCP 22.

Obtener la dirección IP y realizar la prueba de conexión

  1. Obtener la dirección IP:

    • Para conectarse desde otro equipo a este equipo Windows con el servicio SSH habilitado, necesita saber su dirección IP. Puede usar el comando ipconfig en el símbolo del sistema para ver la dirección IP de su equipo.
  2. Prueba de conexión:

    • En otro equipo o dispositivo móvil use un cliente SSH (por ejemplo: PuTTY, Termius, etc.) para intentar conectarse a su PC Windows, usando el formato ssh nombredeusuario@su_direccion_ip. Donde nombredeusuario es el nombre de la cuenta de Windows con la que desea iniciar sesión y su_direccion_ip es la dirección IP que consultó anteriormente.

Modificar la configuración

Tenga cuidado de evitar usar el inicio de sesión por contraseña, esto es un peligro absoluto. Asegúrese de usar la clave pública para iniciar sesión. Debemos modificar la configuración, deshabilitar el inicio de sesión por contraseña y permitir el inicio de sesión por clave pública.

No es conveniente modificar este archivo de configuración, se requiere permisos especiales para modificarlo y también se debe garantizar que los permisos del directorio y del archivo sean valores específicos. Aquí se recomienda usar un script para realizar la modificación.

# Verificar permisos de administrador
$elevated = [bool]([System.Security.Principal.WindowsPrincipal]::new(
    [System.Security.Principal.WindowsIdentity]::GetCurrent()
).IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator))

if (-not $elevated) {
    Write-Error "Ejecute este script como administrador"
    exit 1
}

# 1. Verificar e instalar el servidor OpenSSH
Write-Host "Verificando el estado de instalación del servidor OpenSSH..."
$capability = Get-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0

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

# 2. Iniciar y configurar el arranque automático del servicio SSH
Write-Host "Configurando el servicio SSH..."
$service = Get-Service sshd -ErrorAction SilentlyContinue
if (-not $service) {
    Write-Error "Error al instalar el servicio OpenSSH"
    exit 1
}

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

# 3. Modificar el archivo de configuración
$configPath = "C:\ProgramData\ssh\sshd_config"
if (Test-Path $configPath) {
    Write-Host "Creando copia de seguridad del archivo de configuración original..."
    Copy-Item $configPath "$configPath.bak" -Force
} else {
    Write-Error "No se encuentra el archivo de configuración: $configPath"
    exit 1
}

Write-Host "Modificando la configuración SSH..."
$config = Get-Content -Path $configPath -Raw

# Habilitar la autenticación por clave pública y deshabilitar el inicio de sesión por contraseña
$config = $config -replace '^#?PubkeyAuthentication .*$','PubkeyAuthentication yes' `
                  -replace '^#?PasswordAuthentication .*$','PasswordAuthentication no'

# Asegurar que incluya la configuración necesaria
if ($config -notmatch 'PubkeyAuthentication') {
    $config += "`nPubkeyAuthentication yes"
}
if ($config -notmatch 'PasswordAuthentication') {
    $config += "`nPasswordAuthentication no"
}

# Escribir el archivo de configuración
$config | Set-Content -Path $configPath -Encoding UTF8

Confirmación de permisos del archivo authorized_keys

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

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

Configurar reglas del firewall

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

Agregar clave pública

Usuario normal

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

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

# Establecer permisos del directorio .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

# Agregar clave pública
if (Test-Path $PublicKeyPath) {
    $pubKey = Get-Content -Path $PublicKeyPath -Raw
    if ($pubKey) {
        # Asegurar que la clave pública termine con un salto de línea
        if (-not $pubKey.EndsWith("`n")) {
            $pubKey += "`n"
        }

        # Adjuntar la clave pública
        Add-Content -Path $authorizedKeysPath -Value $pubKey -Encoding UTF8

        # Establecer permisos del archivo
        $acl = Get-Acl $authorizedKeysPath
        $acl.SetSecurityDescriptorRule(
            (New-Object System.Security.AccessControl.FileSystemAccessRule(
                $currentUser, "FullControl", "None", "None", "Allow"
            ))
        )
        Set-Acl $authorizedKeysPath $acl
    }
} else {
    Write-Error "El archivo de clave pública no existe: $PublicKeyPath"
    exit 1
}

# Reiniciar el servicio SSH
Write-Host "Reiniciando el servicio SSH..."
Restart-Service sshd

Usuario administrador

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

# Crear el directorio SSH del administrador
if (-not (Test-Path $adminSshDir)) {
    New-Item -ItemType Directory -Path $adminSshDir | Out-Null
}

# Establecer permisos del directorio SSH del administrador
$adminAcl = Get-Acl $adminSshDir
$adminRule = New-Object System.Security.AccessControl.FileSystemAccessRule(
    "Administrators", "FullControl", "ContainerInherit,ObjectInherit", "None", "Allow"
)
$adminAcl.AddAccessRule($adminRule)
Set-Acl $adminSshDir $adminAcl

# Agregar clave pública del administrador
if (Test-Path $adminPublicKeyPath) {
    $adminPubKey = Get-Content -Path $adminPublicKeyPath -Raw
    if ($adminPubKey) {
        # Asegurar que la clave pública termine con un salto de línea
        if (-not $adminPubKey.EndsWith("`n")) {
            $adminPubKey += "`n"
        }

        # Adjuntar la clave pública
        Add-Content -Path $adminAuthKeysPath -Value $adminPubKey -Encoding UTF8

        # Establecer permisos del archivo
        $adminAcl = Get-Acl $adminAuthKeysPath
        $adminAcl.SetSecurityDescriptorRule(
            (New-Object System.Security.AccessControl.FileSystemAccessRule(
                "Administrators", "FullControl", "None", "None", "Allow"
            ))
        )
        Set-Acl $adminAuthKeysPath $adminAcl
    }
} else {
    Write-Error "El archivo de clave pública del administrador no existe: $adminPublicKeyPath"
    exit 1
}

# Reiniciar el servicio SSH
Write-Host "Reiniciando el servicio SSH..."
Restart-Service sshd