PowerShell

WinRM

WinRM seems a very complicated way to access a server. But it can be easier if you know the basics.

Remote Machine – The Server you want to connect to

To start on the machine you want to connect to, you need to set up WinRM and enable PSRemoting (PowerShell Remoting). This can be done as follows:-

PowerShell 5.x

WinRm quickConfig
Enable-PSRemoting -SkipNetworkProfileCheck -Force

Then make sure the WinRM service is started. It’s configured for Manual startup by default. You will need to change it to start Automatically.

get-service winrm 
set-service WinRm -startMode Automatic

PowerShell 7.x

If you want to use PowerShell 7 on the remote server, then you need to open a pwsh terminal

Enable-PSRemoting -SkipNetworkProfileCheck -Force
Get-PSSessionConfiguration | Select-Object Name, PSVersion

This will enable PSRemoting for PowerShell 7, and register endpoints that you can connect to. If you don’t do this, you will always connect to a PowerShell 5.x session, if your modules are in PowerShell 7 they will not be accessible.

Local Machine – the machine you are using to connect to the remote machine

This splits into different directions depending on if your local and remote machines are in the same domain, or not.

In a Domain

If you are in an Active Directory environment you can connect to the remote server using the computer name.

This bit always got me as I thought it needed to be done on the server you are connecting to. However, it’s not, it needs to be done on the local machine. You can just set it to a wildcard (*) as below.

set-item WSman:\localhost\client\trustedhosts -value "*" -Force

But obviously, that cannot happen if you are in a live environment. If the remote server (the machine you are trying to access) is not in a trusted domain, the remote server might not be able to authenticate your credentials. To enable authentication, you need to add the remote server to the list of trusted hosts on your local machine in WinRM. To do this

Set-Item WSMan:\localhost\Client\TrustedHosts -Value "RemoteComputerName" -Force

To check the trusted host’s configuration

Get-item WSman:\localhost\client\trustedhosts

To connect, you’ll need to set some credentials remember you are connecting to a machine in a domain so the username will be domain\username. Or if you are using a local account on the server, RemoteComputerName\username.

$Credentials = Get-Credential
Enter-PSSession -ComputerName RemoteComputerName -Credential $Credentials

This should get you connected if however, it doesn’t try using the IP address.

Computers in workgroups, local authentication

When you are working with machines that are not in your domain, or are a single server with local authentication, it gets a little bit more complicated. You need to either use HTTPS as the transport or add the remote server to the TrustedHosts configuration settings. Reminder! – These commands are on the local machine.

Set-Item WSMan:\localhost\Client\TrustedHosts -Value "RemoteComputerName" -Force

To check the host’s configuration

Get-item WSman:\localhost\client\trustedhosts

Powershell 5.x

$Credentials = Get-Credential
Enter-PSSession -computername 10.1.1.1 -Credential $Credentials

Powershell 7.x

$Credentials = Get-Credential
Enter-PSSession -computername 10.1.1.1 -Credential $Credentials -ConfigurationName Powershell.7

To confirm which version of PowerShell you are using

$PSVersionTable.PSVersion

Troubleshooting

If this doesn’t work it might be down to the authentication, or the certificate not being trusted etc… So many little things that it can be.

You will probably get an error message like this one.

[10.1.1.1] Connecting to remote server 10.1.1.1 failed with the following error message: THe WinRM client cannot process the request. Default authenication may be used with an IP address under the following conditions: the transport is HTTPS or the destination is in the TrustedHosts list, and explicit credentials are provided. Use winrm.cmd to configure TrustedHosts. Note that computers in the Trusted list might not be authenticated. For more information on how to set TrustedHosts run the following command: winrm help config.

A Windows server will normally have two firewall rules for WinRM already set up. They will be set to listen on port 5985 and one of them is only enabled on the public profile and the other is enabled on the domain and private profile. Winrm should be running

You should be able to connect with

$Credentials = Get-Credential
Enter-pssession -computername 1.2.3.4 -Credential $Credentials

If this doesn’t work disable the windows firewall, just the public profile and see if it connected. If it does then you know it’s something to do with the firewall. Re-enable the public profile in the windows firewall. Then add a copy of the existing rule to the firewall. Then delete it. I had this situation where it then started working.

If the authentication is an issue try changing the authentication

$Credentials = Get-Credential
Enter-pssession -computername 1.2.3.4 -Credential $Credentials -authentication Basic

Other issues I have seen are when the connect is checking things, so you can tell it to skip the checks

$sessionoption = new-pssessionoption -skipCAcheck -skipCNcheck -SkipRevocationCheck
Enter-pssession -computername 1.2.3.1 -Credential $Credentials -sessionoption $sessionoption

Or a combination of both

$sessionoption = new-pssessionoption -skipCAcheck -skipCNcheck -SkipRevocationCheck
Enter-pssession -computername 1.2.3.1 -Credential $Credentials -sessionoption $sessionoption -authentication basic

Sometimes it’s just trial and error until you get the right combination. You can of course look at the server to see what it’s set to using

Winrm get winrm/config

One other problem I’ve come across is if your machine has more than one NIC it may not connect. This is down to if one of your NIC is on a public network. In my case, I have a couple of internal networks, separated from each other. There are a handful of machines that connect to both and if they are identified in windows as on a public network WinRM will not allow you to connect.

Use the following command to change it. It shows you the network you are connected to.

Get-netconnectionprofile

Then run the following command to set the network category.

set-netconnectionprofile -interfacealias "ethernet" -networkcategory private

the ethernet is the interface alias of the network card and the network category can be set to private or public

The SetCategory can be set to 0 – public, 1 – private, 2 – domain.

To connect over the secure port 5986 with a self-signed certificate

  • In Winrm, you have to create a new listener on port 5986 using HTTPS so it’s secure, using a self-signed certificate
  • Open up the firewall to allow communication on the new port 5986
  • Configure the authentication.

Here are the steps:-

On the Remote Server, you are trying to connect to

Create the certificate

$newcert = New-selfSignedCertificate -dnsname "1.2.3.4" -CertStoreLocation Cert:\Localmachine\My -keyexportpolicy "exportable"

New-WSmanInstance WinRm/Config/Listener -SelectorSet @{Address="*";Transport="HTTPS"} -valueSet @{Hostname="1.2.3.4";CertificateThumbprint=$($newcert.thumbprint)"}

If you want to export the certificate

$password = ConvertTo-SecureString -String "{password}" -Force -AsPlainText
Export-PfxCertificate -Cert "Cert:LocalMachine\My\$($newcert.thumbprint)" -FilePath "C:\cert.pfx" -Password $password

Add the Firewall Rule to allow access to the server on port 5986.

netsh advfirewall firewall add rule name="WinRm (HTTPS)" protocol=TCP dir=in localport=5986 action=allow

to see the listener use this command:-

get-WSmaninstance  -ResourceURI winrm/config/listener -selectorset @{Address='*';Transport='HTTPS'}

you can change the HTTPS to HTTP to see the other listener.

From the Local Machine

$sessionoption = new-pssessionoption -skipCAcheck -skipCNcheck -SkipRevocationCheck
Enter-pssession -computername 1.2.3.1 -Credential $Credentials -usessl

The useSSL option tells winrm to look for a HTTPS listener but this will fail as the certificate is self-signed. You will need to either download the certificate and install it on your local machine or you can add the session options in. The only one you should need is the -skipCAcheck.

$sessionoption = new-pssessionoption -skipCAcheck -skipCNcheck -SkipRevocationCheck
Enter-pssession -computername 1.2.3.1 -Credential $Credentials -usessl -sessionOption $sessionoption