PowerShell Remoting Tip: Setting a Network Category to Private

PowerShell remoting is a great thing once you get it working. You get full access to the CIM cmdlets, you can establish in interactive SSH-like session with a remote server, or you can run a command on 1 or 100 servers. However, the remoting pieces such as the WinRM protocol may not work if Windows detects that you are on a public network. This was a problem in the PowerShell 2.0 days, but now remoting is a bit more forgiving. That said, I still run into problems and you might as well.

In my case, my primary computer belongs to a workgroup, yet all of the computers I want to connect to are in a domain. Authentication issues aside, when I am in my home office everything works because my computer recognizes my IP address and configures my network connection accordingly to a private network. This also affects firewall profiles. When I am traveling, however, I may pick up a different IP address and run into connection issues. I’ve also run into similar issues testing new computers in my network. Windows decides the computer is on a public network, so much of my remote access is restricted. So my solution is to run a PowerShell script that automatically sets the network category to private if a local IP address is detected.
Let me walk you through the manual process. First I need to find my current IPv4 address. I am running Windows 8.1.

The Get-NetIPAddress cmdlet in Windows PowerShell. (Image Credit: Jeff Hicks)
The Get-NetIPAddress cmdlet in Windows PowerShell. (Image Credit: Jeff Hicks)
The 172.16.30.222 address indicates I am on my local network. I use a 255.255.0.0 subnet mask, so any address that starts with 172.16 should be ok. Let me filter and grab that address.
Our IP address. (Image Credit: Jeff Hicks)
Our IP address. (Image Credit: Jeff Hicks)
Now, I can see the current network category for this interface.
The Get-NetConnectionProfile cmdlet in Windows PowerShell. (Image Credit: Jeff Hicks)
The Get-NetConnectionProfile cmdlet in Windows PowerShell. (Image Credit: Jeff Hicks)
Its network category is public, which could be problematic. To change it, can you guess the cmdlet to use?
​
You can only set the network category to public, private, or domain authenticated.

Although from my experience you can't manually set it to domain authenticated unless the computer is a domain member and presumably can authenticate to a domain controller. The domain authenticated assignment appears to happen automatically. But it's done.
To make this easy, I put everything in a script and included some logic.
​
#requires -module NetConnection,NetTCPIP
[cmdletbinding()]
Param(
[Parameter(Position=0)]
[ValidatePattern("^\d{1,3}\.\d{1,3}")]
[string]$IPFragment = "172.16",
[switch]$Passthru
)
Write-Verbose "Starting $($MyInvocation.Mycommand)"
#convert IPFragment to a regular expression pattern
$pattern = "^$($IPFragment.Replace(".","\."))"
#test if desired subnet is active
Write-Verbose "Testing current IPv4 addresses for $IPFragment"
$IP = Get-NetIPAddress -AddressFamily IPv4 | where {$_.IPv4Address -match $pattern}
if ($IP) {
    #get current connection profile
    Write-Verbose "Getting current network connection profile for $($IP.IPAddress)"
    $netprofile = $ip | Get-NetConnectionProfile
    Write-Verbose "Current profile is $($netprofile.NetworkCategory)"
    if ($netprofile.NetworkCategory -eq "Public") {
        #set the connection profile to private if it is public
        Write-Verbose "Setting network category to private"
        $netprofile | Set-NetConnectionProfile -NetworkCategory Private
        if ($Passthru) {
          #write the connection profile to the pipeline
          $netprofile
        }
    } #if public
} #if $IP
else {
    Write-Warning "No matching IPv4 addresses found."
}
Write-Verbose "Ending $($MyInvocation.Mycommand)"

I’ve hard-coded the beginning of my IP address fragement. Notice I am also using a validation pattern to verify that whatever is entered must by 1 to 3 numbers, a literal period followed by another set of 1 to 3 numbers. I don’t force the user to enter in a regular expression pattern, I convert the string they enter.

​
If the network category for the detected IP address is public, the script changes the network category to private. I hope you'll also notice my use of comments to explain what is happening in the script and the use of Write-Verbose statements.

I always recommend including them in your script or function from the very beginning. It makes it easier to troubleshoot your script.
Here's the final result in action.
The Set-MyConnection PowerShell script in action. (Image Credit: Jeff Hicks)
The Set-MyConnection PowerShell script in action. (Image Credit: Jeff Hicks)
I then modified my PowerShell profile to run this script. The end result is that when I start a PowerShell session I automatically get the network session I need if the right IP address is detected. This may be a niche problem, but I expect more than a few readers learned something new and that's my ultimate goal.