Mit Powershell Auf Anderen Rechner Verbinden

PowerShell Remote Connection Calculator

Calculate the optimal configuration for connecting to remote computers with PowerShell

Recommended Configuration

Comprehensive Guide: Connecting to Remote Computers with PowerShell

PowerShell remoting is an essential skill for system administrators and IT professionals who need to manage multiple computers efficiently. This guide covers all aspects of connecting to remote computers using PowerShell, including different protocols, security considerations, and performance optimization.

1. Understanding PowerShell Remoting Protocols

PowerShell supports several protocols for remote connections. Each has its advantages and ideal use cases:

  • WinRM (Windows Remote Management): The default protocol for PowerShell remoting, using WS-Management technology.
  • SSH (Secure Shell): Cross-platform protocol that works on Windows, Linux, and macOS.
  • RDP (Remote Desktop Protocol): Can be used through PowerShell for GUI-based remote management.
  • WS-Management: The underlying protocol that WinRM uses, based on SOAP over HTTP/HTTPS.
Protocol Default Port Encryption Cross-Platform Best For
WinRM (HTTP) 5985 Optional No Internal Windows networks
WinRM (HTTPS) 5986 Yes No Secure internal/external connections
SSH 22 Yes Yes Cross-platform environments
RDP 3389 Yes No GUI-based remote management

2. Setting Up PowerShell Remoting

Before you can connect to remote computers, you need to configure them properly. Here’s how to set up the most common remoting methods:

2.1 Enabling WinRM

WinRM is disabled by default. To enable it:

# Run this on the remote computer (as Administrator)
Enable-PSRemoting -Force

# To configure WinRM for HTTPS (more secure)
$cert = New-SelfSignedCertificate -DnsName $env:COMPUTERNAME -CertStoreLocation Cert:\LocalMachine\My
New-Item -Path WSMan:\LocalHost\Listener -Transport HTTPS -Address * -CertificateThumbPrint $cert.Thumbprint -Force

# Open firewall ports
New-NetFirewallRule -DisplayName "Windows Remote Management (HTTPS-In)" -Name "Windows Remote Management (HTTPS-In)" -Profile Any -LocalPort 5986 -Protocol TCP
            

2.2 Configuring SSH Remoting

For SSH remoting (available in PowerShell 7+ and Windows 10/11):

# Install OpenSSH on Windows
Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0

# Start and enable SSH service
Start-Service sshd
Set-Service -Name sshd -StartupType 'Automatic'

# Add to firewall
New-NetFirewallRule -Name "OpenSSH-Server" -DisplayName "OpenSSH Server" -Enabled True -Direction Inbound -Protocol TCP -Action Allow -LocalPort 22
            

3. Connecting to Remote Computers

Once remoting is configured, you can establish connections using these methods:

3.1 Using Enter-PSSession

For interactive sessions:

# Basic connection (WinRM)
Enter-PSSession -ComputerName RemotePC -Credential (Get-Credential)

# Using SSH
Enter-PSSession -HostName RemotePC -UserName admin -SSHTransport

# To multiple computers
$computers = "PC1", "PC2", "PC3"
Invoke-Command -ComputerName $computers -ScriptBlock { Get-Process } -Credential (Get-Credential)
            

3.2 Running Remote Commands

For non-interactive command execution:

# Single command
Invoke-Command -ComputerName RemotePC -ScriptBlock { Get-Service } -Credential (Get-Credential)

# Script file
Invoke-Command -ComputerName RemotePC -FilePath C:\Scripts\maintenance.ps1

# With parameters
$params = @{ Path = "C:\Logs"; Days = 30 }
Invoke-Command -ComputerName RemotePC -ScriptBlock {
    param($Path, $Days)
    Get-ChildItem -Path $Path | Where-Object { $_.LastWriteTime -lt (Get-Date).AddDays(-$Days) } | Remove-Item -Force
} -ArgumentList $params.Path, $params.Days
            

4. Security Considerations

Security is paramount when dealing with remote connections. Follow these best practices:

  • Use HTTPS instead of HTTP for WinRM connections to encrypt all traffic.
  • Implement Just Enough Administration (JEA) to limit what remote users can do.
  • Use certificate authentication instead of passwords when possible.
  • Enable logging for all remote sessions to track activity.
  • Restrict which users/computers can establish remote connections.
# Configure JEA (Just Enough Administration)
$sessionType = @{
    Path = "$env:ProgramFiles\WindowsPowerShell\Modules\JEA\RoleCapabilities\Maintenance.psrc"
    FunctionDefinitions = @{
        Name = "Get-Process"
        Parameters = @{ Name = "Name"; ValidateSet = "svchost", "lsass" }
    }
}
New-PSSessionConfigurationFile -Path .\Maintenance.pssc -SessionType RestrictedRemoteServer -RunAsVirtualAccount -RoleDefinitions @{ 'COMPUTERNAME\JEA_Operators' = @{ RoleCapabilities = 'Maintenance' } }

# Register the configuration
Register-PSSessionConfiguration -Path .\Maintenance.pssc -Name "MaintenanceEndpoints" -Force
            

5. Performance Optimization

When managing multiple remote computers, performance becomes crucial. Consider these optimization techniques:

Technique When to Use Performance Impact Implementation
ThrottleLimit Large number of computers Reduces resource usage Invoke-Command -ThrottleLimit 32
Persistent Sessions Multiple commands to same computers Reduces connection overhead $session = New-PSSession -ComputerName PC1
Invoke-Command -Session $session -ScriptBlock {...}
AsJob Parameter Long-running commands Non-blocking execution Invoke-Command -AsJob
CIM Sessions WMI queries More efficient than WMI $cim = New-CimSession -ComputerName PC1
Compression Low bandwidth networks Reduces data transfer Configure in WSMan:\localhost\Service

6. Troubleshooting Common Issues

Remote connections can fail for various reasons. Here are solutions to common problems:

  1. Access Denied:
    • Verify credentials are correct
    • Check local administrators group membership
    • Ensure the account isn’t locked out
    • Verify User Account Control (UAC) remote restrictions
  2. Connection Refused:
    • Check if WinRM/SSH service is running
    • Verify firewall rules allow the connection
    • Confirm the correct port is open
    • Check if the computer is reachable (ping)
  3. Authentication Errors:
    • For Kerberos: Check SPN registration
    • For NTLM: Ensure it’s not blocked by policy
    • For certificates: Verify trust chain
    • Check time synchronization between computers
  4. Double Hop Problem:
    • Use CredSSP (not recommended for production)
    • Implement Kerberos constrained delegation
    • Store credentials securely and reuse
    • Use resource-based Kerberos delegation
# Test WinRM connectivity
Test-WSMan -ComputerName RemotePC

# Check WinRM configuration
winrm enumerate winrm/config/listener

# Test SSH connectivity
Test-NetConnection -ComputerName RemotePC -Port 22

# Enable detailed WinRM logging
Set-Item -Path WSMan:\localhost\Tracing\Enabled -Value $true
Set-Item -Path WSMan:\localhost\Tracing\FileName -Value "C:\WinRM\winrm.log"
Set-Item -Path WSMan:\localhost\Tracing\MaxLogFileSize -Value 10485760
Set-Item -Path WSMan:\localhost\Tracing\LogLevel -Value @("Error", "Warning", "Verbose")
            

7. Advanced Scenarios

7.1 Cross-Domain Remoting

Connecting across domains requires special configuration:

# Configure trusted hosts (for workgroup or non-domain scenarios)
Set-Item -Path WSMan:\localhost\Client\TrustedHosts -Value "RemotePC,192.168.1.*" -Force

# For domain environments, establish trust relationships
New-ADTrust -SourceForestName domain1.com -TargetForestName domain2.com -Type Forest -TGTDelegation $true -Confirm:$false

# Use explicit credentials
$cred = Get-Credential -UserName "DOMAIN\admin" -Message "Enter credentials"
Invoke-Command -ComputerName RemotePC -Credential $cred -ScriptBlock { ... }
            

7.2 PowerShell Remoting Over the Internet

For secure internet-based remoting:

  • Always use HTTPS (port 5986) or SSH (port 22)
  • Implement a VPN for additional security
  • Use certificate authentication instead of passwords
  • Configure IP restrictions in your firewall
  • Consider using a jump server/bastion host
# Configure WinRM for internet access
Set-Item -Path WSMan:\localhost\Service\Auth\Certificate -Value $true
Set-Item -Path WSMan:\localhost\Service\AllowUnencrypted -Value $false

# Create a public certificate request
$cert = New-SelfSignedCertificate -DnsName "remote.yourdomain.com" -CertStoreLocation Cert:\LocalMachine\My
$cert | Export-Certificate -FilePath "C:\temp\public.cer"

# Configure the public endpoint (on your firewall/router)
# Forward external port (e.g., 443) to internal port 5986
            

7.3 PowerShell Remoting to Linux/Mac

With PowerShell Core (v6+), you can manage Linux and macOS systems:

# On Linux/macOS (install PowerShell first)
# Ubuntu/Debian
sudo apt update && sudo apt install -y powershell
# RHEL/CentOS
sudo yum install -y powershell

# Configure SSH remoting
sudo powershell -c "Install-Module -Name PowerShellGet -Force -AllowClobber"
sudo powershell -c "Install-Module -Name OpenSSHUtils -Force"
sudo powershell -c "Enable-SSHRemoting -Confirm:$false"

# From Windows to Linux
Enter-PSSession -HostName linux-server -UserName ubuntu -SSHTransport
            

8. Automating Remote Management

PowerShell’s remoting capabilities shine when automated. Here are patterns for common automation scenarios:

8.1 Scheduled Remote Tasks

# Create a scheduled task that runs remotely
$action = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-NoProfile -Command `"`"Invoke-Command -ComputerName RemotePC -ScriptBlock { Get-EventLog -LogName System -Newest 10 } | Out-File C:\Logs\system_events.log`"`""
$trigger = New-ScheduledTaskTrigger -Daily -At 2am
$settings = New-ScheduledTaskSettingsSet -StartWhenAvailable -DontStopOnIdleEnd
Register-ScheduledTask -TaskName "Remote System Log Collection" -Action $action -Trigger $trigger -Settings $settings -User "SYSTEM" -RunLevel Highest

# Alternative: Use PowerShell jobs
$job = Invoke-Command -ComputerName RemotePC -ScriptBlock {
    Start-Sleep -Seconds 30
    Get-Service | Where-Object { $_.Status -eq "Running" }
} -AsJob

# Check job status
Receive-Job -Job $job
Get-Job -Id $job.Id | Format-List *
            

8.2 Bulk Operations Across Multiple Computers

# Import computer list from file
$computers = Get-Content -Path "C:\Scripts\servers.txt"

# Create persistent sessions for better performance
$sessions = New-PSSession -ComputerName $computers -Credential (Get-Credential)

# Run commands in parallel
$results = Invoke-Command -Session $sessions -ScriptBlock {
    $output = @{
        ComputerName = $env:COMPUTERNAME
        OS = (Get-CimInstance -ClassName Win32_OperatingSystem).Caption
        Uptime = (Get-CimInstance -ClassName Win32_OperatingSystem).LastBootUpTime
        DiskSpace = @{
            C = (Get-PSDrive -Name C).Used / 1GB
            D = (Get-PSDrive -Name D).Used / 1GB
        }
    }
    $output
} -ThrottleLimit 50

# Process results
$results | Format-Table -AutoSize
$results | Export-Csv -Path "C:\Reports\system_inventory.csv" -NoTypeInformation

# Clean up sessions
Remove-PSSession -Session $sessions
            

8.3 Remote Monitoring Dashboard

Create a simple monitoring dashboard that collects data from multiple servers:

function Get-RemoteSystemStatus {
    param(
        [Parameter(Mandatory)]
        [string[]]$ComputerNames,

        [System.Management.Automation.PSCredential]$Credential
    )

    $results = Invoke-Command -ComputerName $ComputerNames -Credential $Credential -ScriptBlock {
        $status = @{
            ComputerName = $env:COMPUTERNAME
            Timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
            CPU = (Get-CimInstance -ClassName Win32_Processor | Measure-Object -Property LoadPercentage -Average).Average
            Memory = @{
                Total = (Get-CimInstance -ClassName Win32_ComputerSystem).TotalPhysicalMemory / 1GB
                Free = (Get-CimInstance -ClassName Win32_OperatingSystem).FreePhysicalMemory / 1MB
            }
            Disk = Get-PSDrive -PSProvider FileSystem | Where-Object { $_.Used -gt 0 } | Select-Object Name,
                @{Name="Used(GB)"; Expression={$_.Used / 1GB}},
                @{Name="Free(GB)"; Expression={$_.Free / 1GB}}
            Services = (Get-Service | Where-Object { $_.Status -eq "Running" }).Count
            LastBoot = (Get-CimInstance -ClassName Win32_OperatingSystem).LastBootUpTime
            Uptime = (Get-Date) - (Get-CimInstance -ClassName Win32_OperatingSystem).LastBootUpTime
        }
        $status
    } -ThrottleLimit 100

    return $results
}

# Example usage
$cred = Get-Credential
$servers = Get-Content -Path "servers.txt"
$statusData = Get-RemoteSystemStatus -ComputerNames $servers -Credential $cred

# Display in grid view
$statusData | Out-GridView -Title "System Status Dashboard"

# Or export to HTML report
$statusData | ConvertTo-Html -Property ComputerName, Timestamp, CPU, "Memory.Total", "Memory.Free", Services, LastBoot, Uptime -Title "System Status Report" | Out-File "C:\Reports\status_report.html"
            

9. Security Hardening

To secure your PowerShell remoting environment:

  1. Disable basic authentication:
    Set-Item -Path WSMan:\localhost\Service\Auth\Basic -Value $false
                        
  2. Enable firewall rules only for specific IPs:
    New-NetFirewallRule -DisplayName "WinRM-HTTP-Allow-Specific" -Direction Inbound -LocalPort 5985 -Protocol TCP -Action Allow -RemoteAddress 192.168.1.0/24
                        
  3. Configure session timeouts:
    Set-Item -Path WSMan:\localhost\Shell\MaxIdleTimeout -Value 1800000 # 30 minutes
    Set-Item -Path WSMan:\localhost\Shell\MaxShellsPerUser -Value 5
                        
  4. Implement JEA (Just Enough Administration):
    # Create a role capability file
    New-PSRoleCapabilityFile -Path .\MaintenanceRole.psrc -Function Get-Service, Restart-Service, Get-Process
    
    # Register the JEA endpoint
    New-PSSessionConfigurationFile -Path .\JEAEndpoint.pssc -SessionType RestrictedRemoteServer -RunAsVirtualAccount -RoleDefinitions @{ 'DOMAIN\JEA Users' = @{ RoleCapabilities = 'MaintenanceRole' } }
    Register-PSSessionConfiguration -Path .\JEAEndpoint.pssc -Name "MaintenanceEndpoint" -Force
                        
  5. Enable advanced logging:
    # Enable PowerShell script block logging
    Enable-PSRemoting -Force
    Set-Item -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging" -Name "EnableScriptBlockLogging" -Value 1
    Set-Item -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging" -Name "EnableScriptBlockInvocationLogging" -Value 1
    
    # Enable WinRM event logging
    wevtutil set-log "Microsoft-Windows-WinRM/Operational" /enabled:true /q
                        

10. Performance Benchmarking

To optimize your remote operations, it’s important to benchmark different approaches:

function Measure-RemoteCommand {
    param(
        [string]$ComputerName,
        [scriptblock]$ScriptBlock,
        [int]$Iterations = 10,
        [System.Management.Automation.PSCredential]$Credential,
        [switch]$UseSession
    )

    $results = @()

    if ($UseSession) {
        $session = New-PSSession -ComputerName $ComputerName -Credential $Credential
    }

    for ($i = 0; $i -lt $Iterations; $i++) {
        $measure = if ($UseSession) {
            Measure-Command {
                Invoke-Command -Session $session -ScriptBlock $ScriptBlock | Out-Null
            }
        } else {
            Measure-Command {
                Invoke-Command -ComputerName $ComputerName -Credential $Credential -ScriptBlock $ScriptBlock | Out-Null
            }
        }

        $results += [PSCustomObject]@{
            Iteration = $i + 1
            Milliseconds = $measure.TotalMilliseconds
            Ticks = $measure.Ticks
        }
    }

    if ($UseSession) {
        Remove-PSSession -Session $session
    }

    $stats = @{
        ComputerName = $ComputerName
        AverageMs = ($results.Milliseconds | Measure-Object -Average).Average
        MinMs = ($results.Milliseconds | Measure-Object -Minimum).Minimum
        MaxMs = ($results.Milliseconds | Measure-Object -Maximum).Maximum
        TotalMs = ($results.Milliseconds | Measure-Object -Sum).Sum
        UseSession = $UseSession
    }

    return $stats
}

# Example usage
$cred = Get-Credential
$testScript = { Get-Service | Where-Object { $_.Status -eq "Running" } }

$stats1 = Measure-RemoteCommand -ComputerName "Server1" -ScriptBlock $testScript -Credential $cred
$stats2 = Measure-RemoteCommand -ComputerName "Server1" -ScriptBlock $testScript -Credential $cred -UseSession

[PSCustomObject]@{
    ComputerName = $stats1.ComputerName
    WithoutSession = $stats1.AverageMs
    WithSession = $stats2.AverageMs
    ImprovementPct = [math]::Round((($stats1.AverageMs - $stats2.AverageMs) / $stats1.AverageMs) * 100, 2)
}
            

Leave a Reply

Your email address will not be published. Required fields are marked *