Private/Wissen/B_Basic/B34_Remoting.ps1

<#
 
# Remoting
 
PowerShell-Interaktion zwischen Client- und Remote-Hosts. Mit PowerShell 7 können folgende Remote-Host existieren: Windows, Linux und MacOS.
 
- **Hashtags** Remoting WinRM Troubleshooting
 
- **Version** 2020.05.23
 
#>


# ! PowerShell-Remoting wird mittels einem WebDienst bereitgestellt. Dieser wird über den Dienst **WinRM** gesteuert (Default: StartType=Manuell, Status=Stopped)

Get-Service -Name 'WinRM' | Select-Object -Property 'Name', 'Status', 'DisplayName', 'StartType'

# ! In div. Nicht-Windows-Firewalls muss der Port 5985 TCP (HTTP) bzw. 5986 TCP (HTTPS) freigeschallten sein. In Windows erfolgt dies automatisch durch das aktivieren einer Regel.

# TIPP - In der Praxis sollten die folgenden Schritte per GPO umgesetzt werden.

# TIPP - Die PowerShell ist im System verwurzelt. Daher sorgt ein generelles Blockieren nur für schein­bare Sicherheit. Den besten Schutz versprechen letztlich die **Schutz­mechanismen von PowerShell** selbst. Neben Mitteln, die den Missbrauch von PowerShell unterbinden, stehen auch solche zur Verfügung, um verdächtigen und unerwünschten Aktivitäten zu **protokollieren** und diese auf die Spur zu kommen. Weitere Details im Aufbau-Teil bzgl. ScriptBlockLogging und JEA.

# READ Weiterführende und Nachschlage-Informationen:

Get-Help 'about_*remote_*'
Get-Command -Noun 'PSSession'

#region 1. PowerShell-Remoting einrichten

# ! 1.1 ALLE Netzwerkprofile müssen ungleich Public sein:

Get-NetConnectionProfile | Set-NetConnectionProfile -NetworkCategory 'Private' -PassThru

# ! 1.2 WinRM für Quell- und Zielhost aktivieren:

Enable-PSRemoting

# Dann auch im Public-Netzwerkprofil möglich:
Enable-PSRemoting -SkipNetworkProfileCheck -Force

# ! 1.3 Die Client- und Zielhost-Vertrauensstellung einrichten:

Get-Item -Path 'WSMan:\localhost\Client\TrustedHosts' # TIPP DEFAULT-Value -eq ""
Set-Item -Path 'WSMan:\localhost\Client\TrustedHosts' -Value '*' -Force

# TIPP Alternativen sind: SqlServer01, ADS01.abc.local, 192.168.50.50, *.abc.local, 192.168.50.0, *

#endregion

#region 2. PowerShell-Remoting verwenden

# TIPP PowerShell-Remoting-Verbindungen kommu­nizieren stan­dard­mäßig über HTTP. Aller­dings ver­schlüsselt dabei WinRM die über­tragenen Daten. Zusätz­liche Sicher­heit erlangt man speziell in Work­groups durch HTTPS. Siehe weiter unten!

# ! Vorbereitung:

# TODO Eigene IP-Adresse ermitteln:
Get-NetIPAddress -Type 'Unicast' -AddressState 'Preferred' | Select-Object -Property IPAddress, InterfaceIndex, InterfaceAlias

# TODO Ziel-Remote-Hosts, z.B. linker und rechter Nachbar:
$ips = '192.168.103.102', '192.168.103.113'

# ! REMOTING VERWENDEN - Simple:

Enter-PSSession -ComputerName $ips[0]
New-Item -Path 'C:\Temp\Attila_WasHere.Simple' -ItemType 'File'
Exit-PSSession

# ! REMOTING VERWENDEN - Complex:

$admin = Get-Credential -Message "Anmeldung für Server X & Y" -UserName 'Administrator' # Passw0rd
$serverX = New-PSSession -ComputerName $ips[0] -Credential $admin -Name 'ServerX'
$serverY = New-PSSession -ComputerName $ips[1] -Credential $admin -Name 'ServerY'
Get-PSSession

Enter-PSSession -Session $serverX
New-Item -Path 'C:\Temp\Attila_WasHere.ComplexA' -ItemType 'File'
Exit-PSSession

Enter-PSSession -Session $serverY
New-Item -Path 'C:\Temp\Attila_WasHere.ComplexB' -ItemType 'File'
Exit-PSSession

Remove-PSSession -Session $serverX, $serverY
Get-PSSession

# ! REMOTING VERWENDEN - 1-zu-n :

Invoke-Command -ComputerName $ips -ScriptBlock { Get-Process } -AsJob -JobName 'lfdProcHosts'
Get-Job
Receive-Job -Name 'lfdProcHosts' -Keep

# TODO OPTIONAL - PowerShell Remoting dauerhaft zurückbauen und deaktivieren:

Set-Item -Path 'WSMan:\localhost\Client\TrustedHosts' -Value ([string]::Empty) -Force
Disable-PSRemoting -Force
Get-NetConnectionProfile | Set-NetConnectionProfile -NetworkCategory 'Public'

#endregion

#region PowerShell Remoting über HTTPS

# ! PowerShell Remoting über HTTPS mit einem selbstsignierten SSL-Zertifikat
# ! https://www.windowspro.de/script/powershell-remoting-ueber-https-einem-selbstsignierten-ssl-zertifikat
# ! https://docs.microsoft.com/de-de/powershell/scripting/learn/remoting/ssh-remoting-in-powershell-core?view=powershell-7

#endregion

#region Remoting Troubleshooting

# READ Weiterführende und Nachschlage-Informationen:

Get-Help -Name 'about_Remote_FAQ' -ShowWindow
Get-Help -Name 'about_Remote_Requirements' -ShowWindow
Get-Help -Name 'about_Remote_Troubleshooting' -ShowWindow

# TODO Vorbereitung:

$MyTargetComputer = 'PickPick', '192.168.178.56'

# ? Remote-Zugriff auf Remote-CIM möglich:

Get-CimInstance -ClassName 'Win32_BIOS' -ComputerName '192.168.178.34'

# ? Remoteunterstützung in der Windows-Firewall aktive (Enabled):

Get-NetFirewallRule -DisplayGroup 'Remoteunterstützung'  | Where-Object 'Profile' -In 'Private', 'Domain' # TODO | Set-NetFirewallRule -Enabled True

# ? Namenauflösung prüfen:

[System.Net.Dns]::GetHostByName($MyTargetComputer[0])
[System.Net.Dns]::GetHostByAddress($MyTargetComputer[1])

# ? Netzwerkprofil private oder Domain?

Get-NetConnectionProfile | Select-Object -Property 'NetworkCategory', 'Name', 'InterfaceAlias', 'InterfaceIndex'

# ? Remoteregistrierungs-Dienst (RemoteRegistry) läuft:

Get-Process -ComputerName $MyTargetComputer[0] # ? Remote-Zugriff erfolgreich ?
Get-Service -Name 'RemoteRegistry' -ComputerName $MyTargetComputer[0] | Select-Object -Property 'Name', 'Status', 'DisplayName', 'StartType'
Set-Service -Name 'RemoteRegistry' -StartupType 'Automatic' -Status 'Running' -ComputerName $MyTargetComputer[0] -WhatIf

# ? Windows Remotemanagement-Dienst (WinRM) läuft:

Get-Service -Name 'WinRM' | Select-Object -Property 'Name', 'Status', 'DisplayName', 'StartType'
Get-Service -Name 'WinRM' -ComputerName $MyTargetComputer[0] | Select-Object -Property 'Name', 'Status', 'DisplayName', 'StartType'

# ? Korrekte und passende Credential?

$cred = Get-Credential -Message 'Anmelde-Credential für Server ....' -UserName 'Administrator'
$cred

# ? LocalAccountTokenFilterPolicy wenn UAC an ist werden Admin-Rechte entfernt:

Get-ItemPropertyValue -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System' -Name 'LocalAccountTokenFilterPolicy'
Set-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System' -Name 'LocalAccountTokenFilterPolicy' -Value 1 -Type 'DWord' -WhatIf

# ? Ports überprüfen:

function Test-OpenPort {
    param (
        [string]$Target='localhost'
    )
    $ports = @"
20,FTP
21,FTP
22,SSH
23,TelNet
25,Smtp
135,RPC
137,NetBIOS-Namensauflösung
138,NetBIOS-Namensauflösung
139,NetBIOS-Namensauflösung
161,SNMP
162,SNMP
445,SMB Freigabe+ADS+CIM/WMI
464,Kerberos Change/SetPassword
5985,PowerShellRemoting (HTTP)
5986,PowerShellRemoting (HTTPS)
"@

    $ports | ConvertFrom-Csv -Header 'Port', 'Function' | ForEach-Object -Process {
        $tnc = Test-NetConnection -ComputerName $Target -Port $_.Port -WarningAction 'SilentlyContinue'
        return [PSCustomObject]@{
            Target        = $tnc.ComputerName
            RemoteAddress = $tnc.RemoteAddress
            Port          = $tnc.RemotePort
            Function      = $_.Function
            Status        = $tnc.tcpTestSucceeded
        }
    }
}
Test-OpenPort -Target $MyTargetComputer[0]

#endregion

# TODO QUIZ - https://attilakrick.com/schlagwort/powershell-remoting/

<# TODO ÜBUNG
 
# Übung A
 
A1. Sammeln Sie von mindestens zwei Remote-Computern die MAC-Adressen. (OPTIONAL Die Ausgabe der MAC-Adresse sollen ohne "-" (Bindestrichen) erfolgen.)
 
# Übung B
 
1. Erstellen Sie auf mindestens zwei Remote-Rechnern 2 neue lokale Benutzer MIT Passwort.
 
2. Überprüfen Sie ob diese neu angelegten Benutzerkonten auf dem Remote-Rechner erstellt wurden und aktiv sind.
 
3. Löschen Sie die gerade erstellten Benutzerkonten wieder von den Remote-Rechnern (-WhatIf).
 
TIPPS - Get-NetAdapter; $ips; Invoke-Command; ForEach-Object ; -replace; New-LocalUser; Invoke-Command; Get-LocalUser; ConvertTo-SecureString; Remove-LocalUser; Get-Job; Receive-Job; Remove-Job
 
#>