In this guide, you will learn how to use Enter-PSSession and Invoke-Command to securely manage remote Windows machines with PowerShell over HTTPS using a self-signed SSL certificate that we create with PowerShell.

Michael Pietroforte

Michael Pietroforte is the founder and editor in chief of 4sysops. He has more than 35 years of experience in IT management and system administration.

Many PowerShell blogs like to mention that WinRM encrypts data and is therefore secure even if you only work with HTTP (which is the default configuration) and not with HTTPS. Indeed, Microsoft’s documentation for Invoke-Command confirms that WS-Management encrypts all transmitted PowerShell data. (An older version of WinRM on Windows Server 2003 R2 doesn’t encrypt.) Unfortunately, if not configured properly, PowerShell Remoting is insecure and it some cases you need to change the default configuration.

Allowing unencrypted PowerShell Remoting ^

First, it is possible to allow unencrypted WS-Management communication. This command configures the WinRM service to allow unencrypted traffic (you need an elevated console as for most things we do in this post):

Allowing unencrypted WSMan traffic on the server

Allowing unencrypted WSMan traffic on the server

And this one does the same on the client side:

Even though WS-Management encrypts all traffic by default, it is possible that someone (unknowingly) transmits unencrypted data because the default configuration has been changed. I guess this is why this Microsoft article about WinRM warns that “under no circumstances should unencrypted HTTP requests be sent through proxy servers.”

Allowing unencrypted WSMan traffic on the client

Allowing unencrypted WSMan traffic on the client

To check how your machines are configured, you can run this command:

Check WinRM configuration

Checking WinRM configuration

You can also view the configuration in PowerShell:

Why HTTPS with Invoke-Command and Enter-PSSession ^

The second and, in my view, bigger problem is that, if you are working with machines that are not in an Active Directory domain, you don’t have any trust relationship with the remote computers. You are then dealing only with symmetric encryption, so man-in-the-middle attacks are theoretically possible because the key has to be transferred first.

In a previous post, I explained that you have to add the remote machines that are not in an Active Directory domain to your TrustedHosts list on the client. However, you don’t improve security just by “defining” IP addresses or computer names as trustworthy. This is just an extra hurdle that Microsoft added so you know that you are about to do something risky.

This is where PowerShell Remoting via SSL comes in. For one, HTTPS traffic is always encrypted. Thus, you can always automate your tasks remotely, free of worry. And, because SSL uses asymmetric encryption and certificates, you can be sure that you are securely and directly connected to your remote machine and not to the computer of an attacker that intercepts and relays your traffic.

On the downside, configuring PowerShell Remoting for use with SSL is a bit more difficult than just running Enable-PSRemoting. Quite a few tutorials exist that explain how to use HTTPS with Enter-PSSession and Invoke-Command, and most of them make this task appear unnecessarily complicated.

The main problem is that you need an SSL certificate. If you just want to manage some standalone servers or workstations, you probably don’t like to acquire a publicly-signed certificate and want to work with a self-signed certificate instead.

Because many of these guides predate PowerShell 4, they recommend using IIS Manager or download tools such as OpenSSL or the Windows SDK, which contains makecert.exe and pvk2pfx.exe that you can use to create a self-signed certificate. I suppose these guides deter many admins from working with SSL and so they choose the easier way of running Invoke-Command and Enter-PSSession over HTTP.

However, you will now see that enabling SSL for WinRM on the client and on the server is not so difficult (although it is not as straightforward as with SSH), and you can do it all with PowerShell’s built-in cmdlets. You don’t even need the notorious winrm Windows command-line tool.

Enabling HTTPS for PowerShell Remoting ^

On the remote computer

The first thing we need to do is create an SSL certificate. (Note that this guide focuses on the usage of a self-signed certificate. If you have a publicly-signed certificate, things are easier and you can use Set-WSManQuickConfig -UseSSL.)

As mentioned above, since the release of PowerShell 4, we don’t require third-party tools for this purpose. The New-SelfSignedCertificate cmdlet is all we need:

It is important to pass the name of the computer that you want to manage remotely to the ‑DnsName parameter. If the computer has a DNS name, you should use the fully qualified domain name (FQDN).

If you want to, you can verify that the certificate has been stored correctly using the certificate add-in of the Microsoft Management Console (MMC). Type mmc on the Start screen and add the Certificates add-in for a computer account and the local computer. The certificate should be in the Personal\Certificates folder. The name of my test computer was “win81.”

Certificate in MMC on the remote computer

Certificate in MMC on the remote computer

We now have to export the certificate to a file because we will have to import it later on our local machine. You can do this with the MMC add-in, but we’ll do it in PowerShell:

The file name doesn’t matter here.

We need the certificate to start the WS-Management HTTPS listener. But we should first enable PowerShell Remoting on the host:

As I’ve learned recently, -SkipNetworkProfileCheck ensures that PowerShell won’t complain if your network connection type is set to Public.

Enable-PSRemoting also starts a WS-Management listener, but only for HTTP. If you want to, you can verify this by reading the contents of the WSMan drive:

Listing WSMan listeners

Listing WSMan listeners

To ensure that nobody uses HTTP to connect to the computer, you can remove the HTTP listener this way:

This command removes all WSMan listeners:

Next, we add our WSMan HTTPS listener:

Adding a WSMan HTTPS listener

Adding a WSMan HTTPS listener

We are using the $Cert variable that we defined before to read the Thumbprint, which allows the New-Item cmdlet to locate the certificate in our certificates store.

The last thing we have to do is configure the firewall on the host because the Enable-PSRemoting cmdlet only added rules for HTTP:

Notice here that we allow inbound traffic on port 5986. WinRM 1.1 (current version is 3.0) used the common HTTPS port 443. You can still use this port if the host is behind a gateway firewall that blocks port 5986:

Of course, you then have to open port 443 in the Windows Firewall. Note that this command won’t work if the network connection type on this machine is set to Public. In this case, you have to change the connection type to private:

For security reasons, you might want to disable the firewall rule for HTTP that Enable-PSRemoting added:

Our remote machine is now ready for PowerShell Remoting via HTTPS, and we can configure our local computer.

On the local computer

Things are a bit easier here. First, you have to copy the certificate file to which we exported our certificate. You can then import the certificate with this command:

Note that we need to store the certificate in the Trusted Root Certification Authorities folder here and not in the Personal folder as we did on the remote computer. Your computer “trusts” all machines that can prove their authenticity with the help of their private keys (stored on the host) and the certificates stored here.

Certificate in MMC on the local computer

Certificate in MMC on the local computer

By the way, this is why we don’t have to add the remote machine to the TrustedHosts list. In contrast to PowerShell Remoting over HTTP, we can be sure that the remote machine is the one it claims to be, which is the main point of using HTTPS instead of HTTP.

We are now ready to enter a PowerShell session on the remote machine via HTTPS:

The crucial parameter here is -UseSSL. Of course, we still have to authenticate on the remote machine with an administrator account.

The Invoke-Command cmdlet also supports the -UseSSL parameter:

If your remote host doesn’t have a DNS entry, you can add its IP to the hosts file on your local computer. To do so, open an elevated Notepad and then navigate to %systemroot%\system32\drivers\etc\. Of course, you can also do it the PowerShell if you are working on an elevated console:

You will have to reboot after that. I have my own private DNS server in the cloud for such cases.

Conclusion ^

Admittedly, the post got a bit longer than I planned. However, once you know how it works, you can complete the entire procedure to configure PowerShell Remoting for HTTPS in a couple of minutes. You just create a self-signed SSL certificate on the host and start an HTTPS listener using this certificate. Then, you create the corresponding firewall rule and export the certificate. On the local computer, you only have to import the certificate.

HTTPS doesn’t just add another encryption layer; its main purpose is to verify the authenticity of the remote machine, thereby preventing man-in-the-middle attacks. Thus, you only need HTTPS if you do PowerShell Remoting through an insecure territory. Inside your local network, with trust relationships between Active Directory domain members, WSMan over HTTP is secure enough.

Join the 4sysops PowerShell group!

8+

Users who have LIKED this post:

  • avatar
Share
49 Comments
  1. th3l0nius 4 months ago

    Thanks for the article. There is no need to only use the FQDN (or not). You can simply use multiple names with the -DnsName parameter just like this:

    The first name goes to the cn field, the rest to the Subject Alternative Name extension.

    1+

  2. Eugene 5 days ago

    Hi Michael thanks a stack for this post.

    I have spend a lot of time in the past trying to use HTTP and use trusted hosts. Even if I follow instructions to the letter for using HTTP on non domain machines it almost never works.

     By using this guide it took me a few minutes and it is actually much easier to configure over HTTPS than using http. Creating an SSL is much easier than what I thought.

    0

    • Author

      Eugene, you are welcome. I wouldn't use PowerShell remoting over HTTP outside an AD domain because it is not secure. I found it amazingly complicated to configure PowerShell remoting with HTTPS. PowerShell should do this automatically if a machine is not a domain member. SSH is still a lot more advanced here.

      0

Leave a reply

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

*

© 4sysops 2006 - 2019

CONTACT US

Please ask IT administration questions in the forums. Any other messages are welcome.

Sending

Log in with your credentials

or    

Forgot your details?

Create Account