You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
206 lines
6.1 KiB
206 lines
6.1 KiB
# Daftarkan SSH public key ke Mikrotik RouterOS |
|
# Usage: .\scripts\setup-ssh-mikrotik.ps1 |
|
# .\scripts\setup-ssh-mikrotik.ps1 -SkipUpload |
|
# |
|
# Catatan: |
|
# - RouterOS 7.5 butuh key RSA (ed25519 user key baru di 7.12+). |
|
# - Setelah import key, RouterOS default menolak password untuk user yang punya key. |
|
# Skrip ini mengaktifkan password-authentication=yes agar password tetap jadi fallback. |
|
|
|
param( |
|
[ValidateSet("ed25519", "rsa")] |
|
[string]$KeyType = "rsa", |
|
[switch]$SkipUpload, |
|
[switch]$NoPasswordFallback |
|
) |
|
|
|
$HostAddr = "10.100.1.1" |
|
$SshPort = 255 |
|
$SshMac = "hmac-sha1" |
|
$SshUser = "admin" |
|
|
|
$KeyFile = if ($KeyType -eq "rsa") { |
|
Join-Path $env:USERPROFILE ".ssh\id_rsa_mikrotik" |
|
} else { |
|
Join-Path $env:USERPROFILE ".ssh\id_ed25519" |
|
} |
|
$PubFile = "$KeyFile.pub" |
|
$RemotePub = "mikrotik_admin.pub" |
|
|
|
$SshOpts = @( |
|
"-o", "MACs=$SshMac", |
|
"-o", "StrictHostKeyChecking=accept-new", |
|
"-o", "IdentitiesOnly=yes" |
|
) |
|
$SshTarget = "${SshUser}@${HostAddr}" |
|
|
|
function Get-MikrotikKeyArgs { |
|
$args = @("-i", $KeyFile) + $SshOpts |
|
if ($KeyType -eq "rsa") { |
|
$args = @("-o", "PubkeyAcceptedAlgorithms=rsa-sha2-256,rsa-sha2-512,ssh-rsa") + $args |
|
} |
|
return $args |
|
} |
|
|
|
function Ensure-KeyPair { |
|
if ((Test-Path $KeyFile) -and (Test-Path $PubFile)) { |
|
return |
|
} |
|
|
|
Write-Host "Membuat key pair $KeyType ..." |
|
$comment = if ($KeyType -eq "rsa") { |
|
"${SshUser}@$(hostname)-mikrotik" |
|
} else { |
|
"${SshUser}@$(hostname)" |
|
} |
|
$keygenCmd = if ($KeyType -eq "rsa") { |
|
"ssh-keygen -t rsa -b 4096 -f `"$KeyFile`" -C `"$comment`" -N `"`" -q" |
|
} else { |
|
"ssh-keygen -t ed25519 -f `"$KeyFile`" -C `"$comment`" -N `"`" -q" |
|
} |
|
cmd /c $keygenCmd |
|
if ($LASTEXITCODE -ne 0) { |
|
throw "ssh-keygen gagal (exit $LASTEXITCODE)." |
|
} |
|
if (-not ((Test-Path $KeyFile) -and (Test-Path $PubFile))) { |
|
throw "Key pair tidak ditemukan setelah ssh-keygen: $KeyFile" |
|
} |
|
} |
|
|
|
function Normalize-PubFile { |
|
$content = (Get-Content $PubFile -Raw).Trim() |
|
if ($content -notmatch '^(ssh-rsa|ssh-ed25519) ') { |
|
throw "Format public key tidak valid: $PubFile" |
|
} |
|
[System.IO.File]::WriteAllText($PubFile, "$content`n", [System.Text.UTF8Encoding]::new($false)) |
|
} |
|
|
|
function Invoke-MikrotikSsh { |
|
param( |
|
[string]$RemoteCmd, |
|
[switch]$UseKey |
|
) |
|
|
|
$args = @("-p", $SshPort, "-m", $SshMac) + $SshOpts |
|
if ($UseKey) { |
|
$args += Get-MikrotikKeyArgs |
|
$args += @("-o", "BatchMode=yes") |
|
} |
|
$args += @($SshTarget, $RemoteCmd) |
|
|
|
$output = & ssh @args 2>&1 |
|
foreach ($line in $output) { |
|
Write-Host $line |
|
} |
|
|
|
return @{ |
|
Output = ($output | Out-String).Trim() |
|
ExitCode = $LASTEXITCODE |
|
} |
|
} |
|
|
|
function Invoke-ScpUpload { |
|
$args = @("-P", $SshPort) + $SshOpts + @($PubFile, "${SshTarget}:$RemotePub") |
|
& scp @args |
|
if ($LASTEXITCODE -ne 0) { |
|
throw "Upload public key gagal (scp exit $LASTEXITCODE)." |
|
} |
|
} |
|
|
|
function Invoke-MikrotikImport { |
|
Write-Host " > hapus key lama user $SshUser (jika ada) ..." |
|
Invoke-MikrotikSsh "/user ssh-keys remove [find user=$SshUser]" | Out-Null |
|
|
|
Write-Host " > /user ssh-keys import ..." |
|
$import = Invoke-MikrotikSsh "/user ssh-keys import public-key-file=$RemotePub user=$SshUser" |
|
if ($import.ExitCode -ne 0) { |
|
throw "Import key gagal (ssh exit $($import.ExitCode))." |
|
} |
|
if ($import.Output -match '(?i)(unable to load|wrong format|failure|error)') { |
|
throw "RouterOS menolak file key: $($import.Output)" |
|
} |
|
|
|
Write-Host " > /user ssh-keys print" |
|
$print = Invoke-MikrotikSsh "/user ssh-keys print" |
|
if ($print.ExitCode -ne 0) { |
|
throw "Gagal membaca daftar key (ssh exit $($print.ExitCode))." |
|
} |
|
if ($print.Output -notmatch '(?i)(ssh-rsa|ssh-ed25519|key-owner=admin|user=admin)') { |
|
throw "Import selesai tanpa error, tapi key admin tidak terlihat. Output:`n$($print.Output)" |
|
} |
|
|
|
if (-not $NoPasswordFallback) { |
|
Write-Host " > /ip ssh set password-authentication=yes" |
|
$sshPolicy = Invoke-MikrotikSsh "/ip ssh set password-authentication=yes" |
|
if ($sshPolicy.ExitCode -ne 0) { |
|
Write-Warning "Gagal set password-authentication=yes. Password bisa terkunci jika key login gagal." |
|
} |
|
} |
|
|
|
Write-Host " > /file remove $RemotePub" |
|
$cleanup = Invoke-MikrotikSsh "/file remove $RemotePub" |
|
if ($cleanup.ExitCode -ne 0) { |
|
Write-Warning "Key terimport, tapi gagal hapus $RemotePub di router." |
|
} |
|
} |
|
|
|
function Test-KeyLogin { |
|
$args = @( |
|
"-o", "BatchMode=yes", |
|
"-p", $SshPort, |
|
"-m", $SshMac |
|
) + (Get-MikrotikKeyArgs) + @( |
|
$SshTarget, |
|
"/system identity print" |
|
) |
|
|
|
$output = & ssh @args 2>&1 |
|
foreach ($line in $output) { |
|
Write-Host $line |
|
} |
|
if ($LASTEXITCODE -ne 0) { |
|
throw @" |
|
Verifikasi key login gagal. |
|
|
|
Jika password admin juga ditolak setelah import key, hapus key di RouterOS: |
|
/user ssh-keys remove [find user=admin] |
|
/ip ssh set password-authentication=yes |
|
|
|
Lalu jalankan ulang skrip ini. |
|
"@ |
|
} |
|
} |
|
|
|
Write-Host "=== Setup SSH key ke Mikrotik ===" |
|
Write-Host "Target : $SshTarget (port $SshPort)" |
|
Write-Host "Key : $KeyFile" |
|
if ($KeyType -eq "ed25519") { |
|
Write-Host "Info : ed25519 butuh RouterOS 7.12+ (router ini RouterOS 7.5 -> gunakan -KeyType rsa)" |
|
} else { |
|
Write-Host "Info : RSA untuk RouterOS 7.5" |
|
} |
|
Write-Host "Info : IdentitiesOnly=yes — hanya key Mikrotik yang dikirim (bukan id_ed25519 dari ssh-agent)" |
|
Write-Host "" |
|
|
|
Ensure-KeyPair |
|
Normalize-PubFile |
|
|
|
if (-not $SkipUpload) { |
|
Write-Host "Langkah 1/3: upload public key (masukkan password admin jika diminta) ..." |
|
Invoke-ScpUpload |
|
} else { |
|
Write-Host "Langkah 1/3: dilewati (-SkipUpload, pakai $RemotePub yang sudah ada di router)" |
|
} |
|
|
|
Write-Host "" |
|
Write-Host "Langkah 2/3: import key di RouterOS (masukkan password admin jika diminta) ..." |
|
Invoke-MikrotikImport |
|
|
|
Write-Host "" |
|
Write-Host "Langkah 3/3: verifikasi login tanpa password ..." |
|
Test-KeyLogin |
|
|
|
Write-Host "" |
|
Write-Host "Selesai. Login berikutnya:" |
|
Write-Host " .\scripts\ssh-mikrotik.ps1" |
|
Write-Host " ssh -i `"$KeyFile`" -o IdentitiesOnly=yes -m $SshMac $SshTarget -p $SshPort"
|
|
|