Zum Hauptinhalt springen

Powershell-Remoting

Powershell Remoting wurde mit Powershell 2.0 eingeführt und verwendet Windows Remoteverwaltung (kurz WinRM) für die Verbindung mit anderen Computern. WinRM wiederum verwendet WSMan oder Web-Service Management, ein http-basiertes Protokoll zur Steuerung von Computern über das Netzwerk.

Da Powershell Remoting die Datenübertragung über einen Webdienst implementiert, der die Daten per http im XML-Format überträgt, hat Microsoft mit Windows Server 2008 R2 und Windows 7 Powershell Remoting auf den Standard http-Ports laufen lassen, also TCP Port 80 bzw. Port 443. Diese Entscheidung hat sich als relativ unglücklich erwiesen, da es nicht ohne Installation von zusätzlichen Tools möglich war, Powershell Remoting auf einem Rechner zu nutzen, der bereits Web-Dienste verwendet. Seit Windows Server 2012 und Windows 8 sind die Standard-Ports daher auf TCP 5985 und TCP 5986 (SSL) umgelegt worden. Es ist aber möglich, die Port-Konfiguration für WinRM anzupassen.

Seit Windows Server 2012 ist Powershell Remoting auf Servern standardmäßig aktiviert, während es auf Clients noch eingeschaltet werden muss. Dies kann auf manuellem Weg durch das Cmdlet Enable-PSRemoting geschehen: 

Enable-PSRemoting

Alternativ kann man das Batch-Script Winrm.cmd mit dem Parameter /qc (für Quick-Config) verwen-den:

WinRm.cmd /qc

Achten Sie darauf, dass sich die Netzwerkkarte in Privaten- oder Domänenverbindungsprofil befinden muss, damit Remoting aktiviert werden kann. Die Verbindungsprofile können Sie sich mit Get-NetconnectionProfile anzeigen lassen, mit Set-NetconnectionProfile können Sie das Profil einer Netzwerkkarte zwischen Privat und Öffentlich umschalten. Domänenprofile werden automatisch erkannt und können manuell nicht konfiguriert werden.

Enable-PSRemoting
Get-NetConnectionProfile
Set-NetConnectionProfile -InterfaceAlias 'Ethernet' -NetworkCategory Private
Get-NetConnectionProfile | Set-NetConnectionProfile -NetworkCategory Private

Enable-PSRemoting führt folgende Aufgaben aus:

  • Den Dienst WinRM (Windows Remoteverwaltung) auf den Starttyp automatisch setzen und starten
  • Den Listener (Ports) anlegen
  • Die vordefinierten Ausnahmeregeln für die Windows-Firewall konfigurieren. Die Regeln für den Kompatibiltätsmodus schalten Port 80 und Port 443 für WinRM frei.
  • Anlegen der Standard-Endpunkte (s. weiter unten)
  • Setzen des LocalAccountTokenFilterPolicy (auf Computern, die nicht Mitglied einer Domäne sind)

Image 119

Wenn Sie innerhalb einer Domäne arbeiten, können Sie nun direkt loslegen, da Powershell Remoting Kerberos-Authentifizierung verwendet, um die Anmeldung abzusichern. Sobald die Benutzerauthentifizierung abgeschlossen ist, wird die gesamte Sitzung per AES 256 Ende zu Ende verschlüsselt, kann also als absolut sicher angesehen werden.

Wenn Sie mit Computern arbeiten, die sich nicht in der gleichen Domäne befinden, muss der Datenverkehr per TLS abgesichert werden. Hierfür benötigen Sie auf dem Zielserver ein SSL-Zertifikat. Das können Sie sich von einer internen oder externen Zertifizierungsstelle ausstellen lassen, oder Sie erstellen sich ein selbstsigniertes Zertifikat mit dem Cmdlet New-SelfsignedCertificate:

$Cert = New-SelfSignedCertificate -DnsName Server1 -Subject Server1 
Set-Location -Path WSMan:\localhost\Listener
New-Item -Path .\ -Transport https -Port 5986 -CertificateThumbPrint $cert.Thumbprint -Address * -Force

Set-Location in Zeile 2 ist wichtig, um in den richtigen Kontext ("Ordner") zu wechseln, da Set-Item Ihnen sonst die Parameter Port, Transport und CertificateThumbPrint nicht anbietet. Nachdem Sie den https-Listener erstellt haben, sollten Sie den http-Listener noch entfernen, damit keine unverschlüsselten Verbindungen mehr möglich sind.

get-item -path * |
   Where-Object { $_.keys -like "Transport=Http" } | 
   Remove-Item -Force

Für Testsysteme steht Ihnen noch eine weitere Lösung zur Verfügung – Sie können die Verschlüsselung einfach deaktivieren, indem Sie auf dem Client den Zielserver in die Liste der TrustedHosts aufnehmen:

Set-Item -Path WSMan:\localhost\Client\TrustedHosts -Value * -Force

Dies geschieht über die Konfiguration des Remote-Management, die über den WSMan-Provider von Powershell aus konfiguriert werden kann. Der Schlüssel TrustedHosts definiert Server, zu denen der Client eine vertrauenswürdige Verbindung herstellen kann. Da die Daten unverschlüsselt und ohne Authentifizierung des Servers über die Leitung gehen, sollten Sie TrustedHosts ausschließlich für Testumgebungen werden. Achten Sie außerdem darauf, dass es sich um eine Client-Konfiguration handelt – der Server kann den Client über die Anmeldeinformationen identifizieren, die bei der Verbindungsherstellung eingegeben werden, aber der Client hat keine Möglichkeit, ohne Zertifikat oder Kerberos die Iden-tität des Servers zu prüfen, mit dem er verbunden ist.

Die Verbindung zum Remotesystem kann nun über das Cmdlet Enter-PSSession hergestellt werden:

Enter-PSSession -ComputerName Server1
[Server1] PS > Exit

Wenn Sie die Verbindung per https herstellen wollen, müssen Sie das explizit mit dem Parameter UseSSL angeben:

Enter-PSSession -ComputerName Srv1 -UseSSL -Credential Srv1\admin

Der Name des Remote-Computers wird im Prompt in eckigen Klammern angezeigt. Um die Sitzung zu beenden, geben Sie Exit ein.

Sie können eine Remotesitzung öffnen, ohne direkt in sie zu wechseln. So können Sie eine ganze Reihe von Sitzung parallel offenhalten. Verwenden Sie hierfür das Cmdlet New-PSSession:

$SessionServer1 = New-PSSession -ComputerName Server1 -Credential netz-weise\admin Get-PSSession
Enter-PSSession -Session $SessionServer1 
Exit
Get-PSSession | Remove-PSSession

Im Beispiel sehen Sie, wie eine neue Sitzung geöffnet und in der Variablen $SessionServer1 gespeichert wird. Haben Sie vergessen, die Sitzung in einer Variablen aufzufangen, können Sie eine einzelne oder alle offenen Sitzungen mit Get-PSSession anzeigen.

Um in eine offene Sitzung zu springen, können Sie mit Enter-PSSession mit dem Parameter -Session aufrufen und die Sitzungsvariable übergeben. Um die Sitzung wieder zu verlassen, benutzen Sie Exit. Zum Schließen aller offenen Sessions pipen Sie die Sitzungen einfach an Remove-PSSession.

Sie können über Remoting auch Dateien kopieren. Nutzen Sie hierfür den Parameter -ToSession des Cmdlets Copy-Item:

Copy-Item -Path C:\Temp\Tool.ini -Destination c:\temp\ -ToSession $SessionServer1

Richtig spannend ist Powershell-Remoting mit dem Cmdlet Invoke-Command, denn Invoke-Command erlaubt, ein Kommando auf mehreren Systemen parallel auszuführen. Dieses Verfahren wird auch als Fan-Out bezeichnet. Invoke-Command kann Skriptblöcke oder Skript-Dateien ausführen.

$Computer = "Server1","Server2","Server3"
Invoke-Command -ComputerName $Computer -Credential netz-weise\admin -ScriptBlock {Get-Eventlog -LogName Application -EntryType error }

Mit diesem Kommando führen Sie den im Parameter -Scriptblock angegebenen Befehl auf allen Computern aus, die im Parameter -Computername angegeben sind. Die Ausführung findet dabei parallel statt. Wie viele Sitzungen parallel verarbeitet werden können, wird über den Parameter ThrottleLimit angegeben, der einen Standardwert von 32 hat.

$Computer = Get-ADComputer -Filter (OperatingSystem -like '*Server*')
Invoke-Command -ComputerName $Computer.DNSHostName -Credential netz-weise\admin -ScriptBlock { Get-Eventlog -LogName Application } -ThrottleLimit 16

In diesem Beispiel wird der Parameter -Computername über eine Abfrage von Get-ADComputer befüllt. Throttlelimit legt fest, dass die Abfrage immer nur an maximal 16 Computer parallel weitergeleitet wird.

Da der Parameter -Scriptblock einen Scriptblock an den Remotecomputer übergibt, ohne dass dieser die lokalen Variablen des ausführenden Rechners kennt, schlägt folgendes Kommando fehl:

$LogName= 'Application'
Invoke-Command -ComputerName Server1 -ScriptBlock { Get-EventLog -LogName $LogName -EntryType Error }

Die Variable $Logname wird hier lokal auf dem aufrufenden System konfiguriert, ist aber auf dem Zielsystem nicht vorhanden. Ab Powershell 3 kann der neue Variablen-Scope using: verwendet werden, um eine Variable in den Skriptblock zu übertragen:

$LogName= 'Application'
Invoke-Command -ComputerName Server1 -ScriptBlock { Get-EventLog -LogName $using:LogName -EntryType Error }

 In Powershell 2 können Sie die Variablen als Parameter an den Skriptblock übergeben, indem Sie im Skriptblock einen param-Block einfügen und die Variablen über den Parameter -Argumentlist übergeben:

 

$LogName= 'Application'
Invoke-Command -ComputerName Server1 -ArgumentList $LogName -ScriptBlock { 
   param($LogName)
   Get-EventLog -LogName $using:LogName -EntryType Error
} 

 Achten Sie darauf, dass Sie mit der Argumentenliste nur die Argumente, aber nicht die Parameternamen übergeben können. 

Statt eines Skriptblocks können Sie auch eine Skriptdatei zur Remoteausführung bringen:

Invoke-Command -FilePath c:\skripte\GetEventlog.ps1 -ComputerName $computer

Wenn Sie eine Remotesitzung öffnen, wird auf dem Zielsystem eine Powershell geöffnet. Sie können die Remote-Powershell anhand Ihres Namens identifizieren. Der Prozess heißt "wsmprovhost":

Enter-PSSession -ComputerName Server1 -Credential 'netz-weise\admin'
[NWFS]: PS C:\> $PID # $PID enthaelt die Prozess-ID des Powershell-Prozesses
> 4576
[NWFS]: PS C:\> Get-Process -Name wsmprovhost

Handles  NPM(K)  PM(K)  WS(K)  CPU(s)  Id   SI ProcessName 
-------  ------  -----  -----  ------  --   -- -----------  
587      27      53696  73404  0.91    4576 0  wsmprovhost

Auf dem Beispielsystem hat der Remote-Prozess die Prozess-ID 4576. Wenn Sie sich in der Remotesitzung alle Prozesse mit Namen "wsmprovhost" anzeigen lassen, finden Sie in der Spalte die ProzessID jedes Prozesses.

Ist eine Sitzung längere Zeit geöffnet unbenutzt, wird Sie automatisch geschlossen. Die Timeout-Zeit können Sie über den WSMAN-Provider anzeigen lassen:

Get-Item -Path wsman:\localhost\shell\idletimeout

Über den Provider können Sie noch viel mehr Einstellungen vornehmen. Eine Auflistung aller Konfigurationsparameter finden Sie unter Installation und Konfiguration für Windows-Remoteverwaltung.

 
Enter-PSSession -ComputerName Server1 -Credential 'netz-weise\admin'
[NWFS]: PS C:\> $PID # $PID enthaelt die Prozess-ID des Powershell-Prozesses
> 4576
[NWFS]: PS C:\> Get-Process -Name wsmprovhost

Handles  NPM(K)  PM(K)  WS(K)  CPU(s)  Id   SI ProcessName 
-------  ------  -----  -----  ------  --   -- -----------  
587      27      53696  73404  0.91    4576 0   wsmprovhost