Sunday, April 5, 2015

PowerShell Networking Cheat Sheet

Foreward

I haven't located a good cheat sheet for basic PowerShell commands to manage your Network Card/IP stack, so I thought I should make one. If you like this please share it with your mom because I'm sure she's been waiting to set a static IP address via PowerShell for some time. Also you should call her more.


My campaign against stock photography continues.

Assumptions


  • Windows 2012/Windows 8 or higher
  • Administrator access to the machine in question
  • Powershell ran as administrator on the machine in question


CMDLet List:

Most of the commands used to manipulate IP settings can be found by typing Get-Command -Module NetTCPIP

PS C:\WINDOWS\system32> Get-Command -Module NetTCPIP

CommandType     Name                                               ModuleName
-----------     ----                                               ----------
Function        Find-NetRoute                                      NetTCPIP
Function        Get-NetCompartment                                 NetTCPIP
Function        Get-NetIPAddress                                   NetTCPIP
Function        Get-NetIPConfiguration                             NetTCPIP
Function        Get-NetIPInterface                                 NetTCPIP
Function        Get-NetIPv4Protocol                                NetTCPIP
Function        Get-NetIPv6Protocol                                NetTCPIP
Function        Get-NetNeighbor                                    NetTCPIP
Function        Get-NetOffloadGlobalSetting                        NetTCPIP
Function        Get-NetPrefixPolicy                                NetTCPIP
Function        Get-NetRoute                                       NetTCPIP
Function        Get-NetTCPConnection                               NetTCPIP
Function        Get-NetTCPSetting                                  NetTCPIP
Function        Get-NetTransportFilter                             NetTCPIP
Function        Get-NetUDPEndpoint                                 NetTCPIP
Function        Get-NetUDPSetting                                  NetTCPIP
Function        New-NetIPAddress                                   NetTCPIP
Function        New-NetNeighbor                                    NetTCPIP
Function        New-NetRoute                                       NetTCPIP
Function        New-NetTransportFilter                             NetTCPIP
Function        Remove-NetIPAddress                                NetTCPIP
Function        Remove-NetNeighbor                                 NetTCPIP
Function        Remove-NetRoute                                    NetTCPIP
Function        Remove-NetTransportFilter                          NetTCPIP
Function        Set-NetIPAddress                                   NetTCPIP
Function        Set-NetIPInterface                                 NetTCPIP
Function        Set-NetIPv4Protocol                                NetTCPIP
Function        Set-NetIPv6Protocol                                NetTCPIP
Function        Set-NetNeighbor                                    NetTCPIP
Function        Set-NetOffloadGlobalSetting                        NetTCPIP
Function        Set-NetRoute                                       NetTCPIP
Function        Set-NetTCPSetting                                  NetTCPIP
Function        Set-NetUDPSetting                                  NetTCPIP
Function        Test-NetConnection                                 NetTCPIP
To find out more about any given command, type Get-Help <cmdlet name>

Common Tasks


Here are walkthroughs of some of the more common tasks you may want to perform.

List Network Adapters

Gets a list of all adapters in the machine; you'll need to know your adapter name or index # (both listed) for some of the commands below.
Get-NetAdapter

Change an Adapter Friendly Name

You may want to consider changing the friendly name of the adapter you intend to manipulate. By giving it shorter, more meaningful name you'll have an easier time going forward. Use the old name you got from the last command. Syntax is Rename-NetAdapter -Name "<Current Name>" -NewName <"New Name">
Rename-NetAdapter -Name "Local Area Connection" -NewName WiFi

Get the Current IP Address

Gets all IPv4 addresses on the machine; you'll almost always have multiple as your loopback interface (127.0.0.1) will be listed. Ignore that guy.
Get-NetIPAddress -AddressFamily ipv4
Optionally, you can specify -InterfaceAlias <friendly name> or -InterfaceIndex <index #> to limit the command to a single adapter.

Assign a Static IP Address to your Network Adapter

This command will set the one and only (overwriting what is there) IP address for the specified network adapter. You also can (and should) set the subnet mask with this command. The subnet mask is set via CIDR using the -PrefixLength; see the link for more info about CIDR, but if you're not familiar with CIDR it is likely that you want -PrefixLength 24 which translates to 255.255.255.0 meaning the first three octets are the network while the last is the host. Syntax is New-NetIPAddress -InterfaceAlias <name> -IPAddress <IP address> -PrefixLength <CIDR> -DefaultGateway <Gateway IP>  . You can substitute -InterfaceIndex <index #> for -InterfaceAlias .
New-NetIPAddress -InterfaceAlias WiFi -IPAddress 192.168.1.10 -PrefixLength 24 -DefaultGateway 192.168.1.1
Note: You will get an error if you already have a static IP address with a default gateway. To fix this problem see "Delete Existing Static IP" below and then try again.
Note2: We're not using "Set-NetIPAddress" here because it doesn't allow you to set a default gateway. BOOOO.

Set DNS Servers for your Adapter

To look up names you'll need to set DNS server(s). Syntax is Set-DNSClientServerAddress -InterfaceAlias <name> -ServerAddresses ("<IP Address 1","IP Address 2") . You can set as many DNS servers as you like. You can substitute -InterfaceIndex <index #> for -InterfaceAlias .
Set-DNSClientServerAddress –interfaceAlias WiFi –ServerAddresses (“192.168.1.5”,”192.168.1.6”)

Set a Default Gateway

It's generally easier to set the default gateway as part of the New-NetIPAddress command above, but if you want to set one separately see "Set a Static Route" below.

Delete Existing Static IP (to prep for a new)

This is a two step process; you need to delete the IP, then the gateway. No need to worry about the DNS servers here as it works to overwrite them with the command above. You will need to know the IP address you want to delete first; use get-netipaddress (above) to get it (write it down to use below if necessary). You'll then need to know the NextHop of the gateway. To get this, use the get-netroute command and write down the entry(ies) that have a nexthop of the gateway you intend to remove (see screenshot).



The syntax for these commands are
Remove-NetAddress <IPAddress> -Confirm:$False
Remove-NetRoute -NextHop <Gateway IPAddress> -Confirm:$False

Remove-NetAddress 192.168.1.10 -Confirm:$False
Remove-NetRoute -NextHop 192.168.1.1 -Confirm:$False
Note: If you have multiple routes set with that default gateway it will delete them all. If you haven't manually set routes, don't worry about it (you just have the one).

Set Your Adapter to Use DHCP

This is another two step process; first set the desired adapter IP/Gateway to DHCP then set the DNS servers to pull from DHCP as well.

The syntax for these commands are:
Set-NetIPInterface -InterfaceAlias <name> -Dhcp Enabled
Set-DNSClientServerAddress -InterfaceAlias <name> -ResetServerAddress
You can substitute -InterfaceIndex <index #> for -IterfaceAlias if you prefer.
Set-NetIPInterface -InterfaceAlias WiFi -Dhcp Enabled
Set-DNSClientServerAddress -InterfaceAlias Wifi -ResetServerAddress
Note: If you have a static gateway set you'll need to perform the second step "Remove-NetRoute" from the step above as well. 


Advanced Tasks


Here are walkthroughs of some of the more common tasks you may want to perform. My assumption here is that you know what you want to do so I won't be discussing the details of what each of these means.

Add/Delete a Static Route

Add: (use -RouteMetric to specify metric or -PolicyStore to control persistence through reboots)
New-NetRoute -DestinationPrefix 192.168.2.0/24 -InterfaceAlias WiFi -NextHop 192.168.2.1
Add default route:
New-NetRoute -DestinationPrefix 0.0.0.0/0 -InterfaceAlias WiFi -NextHop 192.168.2.1
Delete: (while this command is very specific you can be more generic; see above)
Remove-NetRoute -DestinationPrefix 192.168.2.0/24 -InterfaceAlias WiFi -NextHop 192.168.2.1

Test Network Connectivity (Ping)

Test-Connection replaces ping.exe. In addition to the ping functionality Test-Connection supports authentication (if firewall is set accordingly), multiple targets in a single command, running as a job, as well as more detailed returns.
Test-Connection myhost.mydomain.com

Assign a DNS Suffix

This is the domain under which your IP will be registered and under most circumstances will be used to append to hostname searches. Note this is per-adapter. You can substitute InterfaceIndex for InterfaceAlias if you like.
Set-DnsClient -InterfaceAlias WiFi -ConnectionSpecificSuffix mydomain.com

Assign an Additional IP Address to your NIC

If you want to add another IP (usually only applicable on a server)
New-NetIPAddress -InterfaceAlias Ethernet1 -IPAddress 192.168.1.101 -PrefixLength 24


References/More Information

TechNet: Net TCP/IP Cmdlets in Windows PowerShell
TechNet: DNS Client Cmdlets in Windows PowerShell
TechNet: Network Adapter Cmdlets

You did it, hug a puppy!

Saturday, January 3, 2015

Remotely Restart Serivices via PowerShell Without Admin Credentials

Scope


Ever wanted to allow a non-admin to remotely restart a service? No? K.

.... well if sometime you feel like it, this article is for you. We'll walk through enabling PowerShell Remoting (part of WinRM), allowing the non-administrators to connect, and allowing the specified user or group to restart the service in question.


(Install and) Enable PowerShell Remoting


On Windows server 2012, this step is already completed by default. On earlier versions of Windows you may need to install software and then enable connection. That is an article in and of itself, but fortunately it has already been published by Ian Farr. Consult that article to determine what software, if any, you need to install.

After installs:

Note: This may not be necessary on 2012 and up but will not hurt none the less.
  1. Remote to the server you wish to remotely manipulate services on
  2. Open an elevated PowerShell prompt


  3. Run the Enable-PSRemoting cmdlet


  4. For each query, type "y" and press enter.


The Enable-PSRemoting cmdlet will run a few different sub cmdlets to enable the proper services and setup initial permissions.


Set up Security Principals and Grant Permissions to use PowerShell Remoting


Caution: This grants access to connect to the PSRemote interface and attempt to issue commands. While this isn't enough to stop services, etc. by itself it should be done with caution.

There are two levels of security you will need to address with this operation: the ability to connect to the PSRemote interface/attempt to issue commands, and the permissions on the service to be restarted. It is important to consider that these two groups may not be the same; there is a lot one can do with PSRemoting outside of restarting a specific service. Thus it is likely you will want to create a larger (in scope and size) group to access PSRemoting and a smaller group to restart this specific service.

If you don't much care and just want to get going you can just make the principals the same... even just a single user. With that said:

  1. Determine what security principals you want to have access to PSRemoting and create them if necessary. I use an Active Directory group named appropriately and populated with the desired users, but you could use anything down to a single user if you like.


  2. Ensure you still have the PowerShell prompt open on your target server; if not open it as in the section above.
  3. Execute Set-PSSessionConfiguration -ShowSecurityDescriptorUI -Name Microsoft.PowerShell which will bring up the Windows security dialog box.


  4. Add your desired security principal (AD Group, Local Group, User, etc) and grant it "Full Control" access.


  5. Click "OK" to close the box and apply the permissions, then answer y + <enter> to restart the service.

Note that on 64-bit systems where you have elected to use the 32-bit version of PowerShell you will also need to execute steps 3-5 using the Set-PSSessionConfiguration -ShowSecurityDescriptorUI -Name Microsoft.PowerShell32 command as well. 

Now you can hit the PSRemote interface with the specified accounts; if you haven't figured it out yet this could be used for many things other than just restarting a service... this is why PSRemoting is so great!


Grant Service Restart Access to the Appropriate Security Principal


In my example my service will be called "MyService". Normally this is an operation that would be somewhat complex with the built-in Windows tools, so I'm going to offer up a simpler way.

  1. Download and install Carbon (more below) on your target server(s). 
  2. Per the install instructions, unblock the zip, extract, and import the module after install with Import-Module Carbon or the import-carbon.ps1 script. (Note: You may need to set-executionpolicy unrestricted to use Carbon; make sure you set-executionpolicy Restricted when you're done)


  3. Execute the Grant-ServiceControlPermission, i.e. Grant-ServiceControlPermission -ServiceName MyService -Identity MyDomain\MyGroup where MyService is the short name of the target service and MyDomain\MyGroup is the target security principal. 


Aaron Jensen has done a great job with the Carbon module and I highly recommend it to anyone operating in a DevOps space on Windows Server. That one command in point #3 could have been an article about SDDLs in and of itself.


Test and Provide Restart Commands to Target User(s)


Rather than having your target users learn the appropriate PowerShell commands, it may be easier to provide them with a script. Here's a sample one that can restart multiple services on multiple servers after executing the steps above on each.



$servers="Server1","Server2"
$services="MyService1","MyService2"

Write-Warning 'What would you like this script to do? '
Write-Warning '1. Stop Services'
Write-Warning '2. Start Services'
Write-Warning '3. Re-start Services'
Write-Warning '4. Quit'
while($ActionType.length -lt 1)
{
 $ActionType=Read-Host "Enter the number to correspond with your desired action. " 
 $ActionType=[string]$ActionType.trim()
}
 
switch ($ActionType)
{
 1 
 {
  $stop=$true
  $start=$false
 }
 2 
 {
  $stop=$false
  $start=$true
 }
 3
 {
  $stop=$true
  $start=$true
 }
 4 {Exit}
 default {throw ("Unexpected input from action type inquriy.")}
}
 
foreach ($server in $servers)
{
 if ($stop)
 {
  foreach ($service in $services)
  {
   Write-Debug "Stopping $service on $Server"
   Invoke-Command -ComputerName $server -ScriptBlock {Stop-Service -Name $args[0]} -ArgumentList $service
   if ($? -eq $false){throw "TERMINATING SCRIPT; UNABLE TO STOP SERVICE. Check permissions and ensure target machine $server is up"}
   Write-Warning "Service $service stopped on $server"
  }
 }
 start-sleep -Milliseconds 500

 if ($start)
 {
  #Start Services
  foreach ($service in $services)
  {
   Write-Debug "Starting $service on $server"
   Invoke-Command -ComputerName $server -ScriptBlock {Start-Service -Name $args[0]} -ArgumentList $service
   if ($? -eq $false){throw "TERMINATING SCRIPT; UNABLE TO START SERVICE. Check permissions and ensure target machine $server is up"}
   Write-Warning "Service $service started on $server"
  }
 }
}
Write-Warning "All actions complete!"

This script is really just a starting point; there are many different directions you could take it based on your needs. For example, you could use the get-credential cmdlet to allow the user to enter alternative credentials. To use it as-is simply replace the server(s) and service(s) names at the top of the script with those you are targeting.

... and that's it! Thanks to carbon and a couple simple commands this operation is pretty easy to achieve. This has been a big help in lower environments for letting users, developers, etc. restart services as needed without having to interrupt their support personnel. Hopefully it helps you as well.

References/Additional Information


TechNet: Enable-PSRemoting
Stack Overflow: WSMan and Basic Authorization
Stack Overflow: PowerShell Remoting Giving Access is Denied Error
TechNet: Introduction to WinRM
Ondrej Sevecek: Enabling remote WMI and PowerShell access over WinRM for non-administrators (Much of the inspiration for this article)
Carbon (PowerShell Dev-Ops module by Aaron Jensen)