SSH подключение к Linux из Windows PowerShell


Функция удаленного взаимодействия PowerShell обычно использует WinRM для передачи данных. Теперь протокол SSH доступен на платформах Linux и Windows, что позволяет осуществлять многоплатформенное удаленное взаимодействие с PowerShell. Начиная с PowerShell 6 и выше можно работать по WinRM между Windows и Linux машинами, так-же можно работать непосредственно по SSH, при условии, что на Windows машине установлен SSH клиент.
На сегодня PS доступен в 7-ой версии для Windows, Linux, macOS платформ, последние версии доступны на ОФИЦИАЛЬНОЙ СТРАНИЦЕ POWERSHELL в GitHub. Сегодня рассмотрим несколько сценариев работы / подключения к Linux из PowerShell Windows, участники эксперимента:
- Windows Server 2016
- CentOS 7 + PSRP (WinRM)
- Ubuntu 18 (SSH)
- PowerShell (последний релиз, на сегодня 7.0.0)
Содержимое
Сценарии подключения
- Использование PSRP (WinRM)
- Использование SSH клиента из Powershell (более лаконочиный и предпочитаемый сценарий)
Небольшое предисловие — это ознакомительная статья, использование PS на Linux проде, это хороший вопрос, который требуется хорошо обдумать, прежде, чем использовать. По ходу статьи будут приведены ссылки на те или иные материалы / аббревиатуры, так что будем считать, что вводная на используемые технологии дана в той или иной мере.
Сценарий 1
Использование OMI сервера, работа по WINRM (PSRP) (детали ниже).
Установка последней версии PowerShell в Windows
Устанавливается одной командой:
1
|
iex "& { $(irm https://aka.ms/install-powershell.ps1) } -UseMSI"
|
После установки запускается командой (Ctrl +R):
1
|
pwsh
|
Смотрим детали по установленному релизу PS:
1
|
$PSVersionTable
|

Установка PowerShell в Linux
Устанавливается досточно просто, необходимо скопировать MS репо-конфиг из официального репозитория:
1
|
curl https://packages.microsoft.com/config/rhel/7/prod.repo > /etc/yum.repos.d/microsoft.repo
|
Установить PowerShell:
1
|
yum install powershell
|
Запустить командой:
1
|
pwsh
|
Проверить версию:
1
|
$PSVersionTable
|

Установка PSRP в CentOS
Что такое PSRP — PowerShell Remoting Protocol который используется в Открытой Инфраструктуре Управления (Open Management Infrastructure (OMI))
В данном случае достаточно будет установить в наш CentOS — PSRP Server. Rpm пакет можно загрузить из официльного репозитория PSRP, в моем случае на момент написание статьи этот вариант так-же работоспособен:
1
|
yum install https://github.com/PowerShell/psl-omi-provider/releases/download/v1.4.1-28/psrp-1.4.1-28.universal.x64.rpm
|
После установки в системе появляется и запускается новый system unit — omid:
1
2
3
4
5
6
7
|
systemctl status omid
● omid.service - OMI CIM Server
Loaded: loaded (/usr/lib/systemd/system/omid.service; enabled; vendor preset: disabled)
Active: active (running) since Sun 2020-04-19 09:18:08 EDT; 13min ago
Process: 4558 ExecStart=/opt/omi/bin/omiserver -d (code=exited, status=0/SUCCESS)
Process: 4457 ExecStartPre=/opt/omi/bin/support/installssllinks (code=exited, status=0/SUCCESS)
...
|
Появляется новый листенер на порту 5986 (кто не знает, это WinRM):

×В моем случае используется IPv4 (по умолчанию OMI сервер использует IPv6, если он включен.
Разрешаем порт в firewalld:
1
|
firewall-cmd --permanent --add-port=5986/tcp
|
1
|
firewall-cmd --reload
|
Подключение PowerShell SSH (Windows > Linux)
Создаем объект для хранения SSH кред:
1
|
$creds = Get-Credential
|
Объект с параметрами подключения:
1
|
$opt = New-PSSessionOption -SkipCACheck -SkipRevocationCheck -SkipCNCheck
|
Подключаемся к Linux машине:
1
|
Enter-PSSession -ComputerName 'xxx.xxx.xx.x' -Credential $creds -Authentication basic -UseSSL -SessionOption $opt
|

Пример удаленного вызова команды
Здесь подразумеваю Invoke-Command:
1
|
Invoke-Command -ComputerName xxx.xxx.xx.x -ScriptBlock { Get-Process } -Authentication Basic -SessionOption $opt -Credential $creds -UseSSL | Select-Object -First 5
|


Удаленный запуск скриптов
На стороне Windows можно создать скрипт и исполнить его на удаленной Linux машине, например PS скрипт, который отображает информацию о сетевых интерфейсах:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
function Get-IPConfig {
[System.Net.NetworkInformation.NetworkInterface]::GetAllNetworkInterfaces() | ForEach-Object {
$ipProperties = $_.GetIPProperties()
$addresses = $ipProperties.UnicastAddresses |
Where-Object {
$_.Address.AddressFamily -eq 'InterNetwork'
} | ForEach-Object {
"$($_.Address) $($_.IPv4Mask)"
}
$gateway = $ipProperties.GatewayAddresses.Address |
Where-Object {
$_.AddressFamily -eq 'InterNetwork' -and
$_ -ne '0.0.0.0'
}
[PSCustomObject]@{
Name = $_.Name
Id = $_.Id
Addresses = $addresses
Gateway = $gateway
}
} | Where-Object { $_.Addresses }
}
Get-IPConfig
|
Далее можно вызвать этот скрипт используя Invoke-Command:
1
|
Invoke-Command -ComputerName xxx.xxx.xx.x -FilePath 'c:\test\get-linuxip.ps1' -Authentication Basic -SessionOption $opt -Credential $creds -UseSS
|

Проблемы OMID SSL
На одной из тестовых машин, во время подключения стало возникать сообщение о том, что срок действия сертификата истек, решение — перейти в каталог:
1
|
cd /etc/opt/omi/ssl/
|
Создаем резервные копии, того, что есть:
1
2
3
|
mv omikey.pem omikey.pem.bak
mv omi.pem omi.pem.bak
mv ssl.cnf.pem ssl.cnf.bak
|
В конфиг ssl.conf добавляем следующие параметры:
1
2
3
4
5
|
[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = digitalSignature, keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth, clientAuth
subjectAltName = DNS: Linux-Server-Name, IP:xxx.xxx.xx.x
|
Генерируем SSL сертификаты:
1
2
3
|
openssl genrsa -out omikey.pem 2048
openssl req -new -key omikey.pem -out Request.csr -config ssl.cnf
openssl x509 -req -days 365 -signkey omikey.pem -in Request.csr -out omi.pem -extensions v3_req -extfile ssl.cnf
|
Перезапускаем omid:
1
|
systemctl restart omid
|
Сценарий 2
Лаконичный, работоспособный сценарий для работы PowerShell через SSH клиента. Нет лишних телодвижений, единственное, после установки PowerShell в Linux необходимо будет добавить один параметр в sshd конфиг.
Установка Windows SSH клиента
В этом сценарии будет использоваться менеджер пакетов CHOCOLATELY, установить его можно следующим образом:
1
|
Set-ExecutionPolicy Bypass -Scope Process -Force; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))
|
Далее необходимо произвести несколько настроек:
1
|
$env:ChocolateyInstall = Convert-Path "$((Get-Command choco).Path)\..\.."
|
1
|
Import-Module "$env:ChocolateyInstall\helpers\chocolateyProfile.psm1"
|
Установить SSH клиент:
1
|
choco install openssh
|
Обновить переменные окружения:
1
|
refreshenv
|
На стороне Linux
В данном случае, для разнообразия используется Ubuntu, здесь так-же необходимо установить PowerShell:
1
2
3
4
5
|
wget -q https://packages.microsoft.com/config/ubuntu/18.04/packages-microsoft-prod.deb
sudo dpkg -i packages-microsoft-prod.deb
sudo apt-get update
sudo add-apt-repository universe
sudo apt-get install -y powershell
|
×Детали по установке для различных дистрбутивов СМОТРИ НА ОФИЦИАЛЬНОМ САЙТЕ.
Добавить в:
1
|
nano /etc/ssh/sshd_config
|
Параметр:
1
|
Subsystem powershell /usr/bin/pwsh -sshs -NoLogo -NoProfile
|
Перезапустить sshd:
1
|
systemctl restart sshd
|
Подключение по SSH
На стороне Windows используя командлет Enter-PSSession тестируем подключение:
1
|
Enter-PSSession -HostName xxx.xxx.xx.x -UserName user
|

Или можно создать сессию подключения:
1
|
$session = New-PSSession -HostName xxx.xxx.xxx.x -UserName user -SSHTransport
|
Далее использовать ее по назначению:
1
|
Enter-PSSession $session
|
Или вызвать команду:
1
|
Invoke-Command -Session $session -ScriptBlock { Get-Process } | Select-Object -First 5
|
Или скрипт:
1
|
Invoke-Command -Session $session -FilePath 'c:\test\get-linuxip.ps1'
|

Устранение ошибки A remote session might have ended.
Возникает в момент подключения, выглядит следующим образом:
1
|
<pre class="inline:true decode:1 " >Enter-PSSession : An error has occurred which PowerShell cannot handle. A remote session might have ended.
|
Решается добавлением в ручную переменной окружения ssh:

Использование SSH клиента из командной строки
Использование ssh клиента, можно использовать из командной строки в рамках обычного ssh подключения:
1
|
ssh USER@XXX.XXX.XX.x
|