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 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)
Now, I can see the current network category for this interface.
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)
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.