Is Ping a reliable way to check if a computer is available? Opinions differ … This blog post is all about ping and arp. Of course with PowerShell. The upcoming script could help you figure out whether a host is really up or not. Remember the Windows Firewall. If ping is not successful what does this actually mean? That the host is down? Not really … Let’s dive in …
Introduction
There are many ways to perform a ping. There is superping, the “normal” ping, other pings 😉 and finally the PowerShell cmdlets Test-Connection and Test-NetConnection. All of the above can only tell you whether ping is successful or not. But they don’t tell you whether the host is up or not.
The Goal
Last week I had an idea. Some of my ideas are dangerous for me because I know that putting them into practice will bring me a lot of work – but also joy. And this idea is definitely a dangerous one ;-). I had the idea to create a function which can tell me the reason why a ping is successful or not. So, ARP hast to come into play.
Only if a ping failed but the corresponding ARP request was successful, it’s pretty sure that the target host is up! Provided that both are in the same subnet.
Back to my idea: Why not create a function that shows me that behavior? Here it is:
Host is up (ICMP and ARP successful)
Firewall is probably blocking Traffic (ARP successful, but ICMP failed)
Host is outside the subnet (ICMP successful, ARP not successful)
It’s possible to ping hosts outside your subnet. That means, that ICMP is successful and ARP is not successful, because the source host will send the ICMP Echo Request to it’s Default Gateway. I do a ping to the IP-Address of cnn.com which is definitely not in my subnet.
Host is down (ICMP, ARP failure)
Oh, before I forget: Here’s the function. 😉
Function Test-ConnectionLocalSubnet
If you like it copy the Code in your PowerShell ISE session.
function Test-ConnectionLocalSubnet { param ([Parameter(Mandatory=$True,Position=1)] [System.Net.IPAddress]$IPAddress) arp -d $entry= Write-Host "Testing $IPAddress ..." $line="_____________________________________________________________" $ping=Test-Connection -ComputerName $IPAddress -Count 3 -Quiet $arp=[boolean](arp -a | Select-String "$IPAddress") If ($ping -and $arp) {$line; Write-Host "ICMP: successful" -ForegroundColor Green`n; Write-Host "ARP : successful" -ForegroundColor Green`n; $line; Write-Host "Host ${IPAddress} is up" -ForegroundColor Green; Write-Host ""} elseif ($ping -and !$arp) {$line; Write-Host "ICMP: successful" -ForegroundColor Green`n; Write-Host "ARP : failure" -ForegroundColor Red`n; $line; Write-Host "Host ${IPAddress} is up, but possibly not on local subnet"; Write-Host ""} elseif (!$ping -and $arp) {$line; Write-Host "ICMP: failure" -ForegroundColor Red`n; Write-Host "ARP : successful" -ForegroundColor Green`n; $line; Write-Host "Possible Cause on ${IPAddress}: Windows Firewall is blocking traffic"; Write-Host ""} else {$line; Write-Host "ICMP: failure" -ForegroundColor Red`n; Write-Host "ARP : failure" -ForegroundColor Red`n; $line; Write-Host "Host ${IPAddress} is down" -ForegroundColor Red; Write-Host "" } }
Notes:
- This was tested on PowerShell 5.1
- You can only use IP-Addresses (Parameter: IPAddress), no host names
- This script is intended for testing reachability of hosts on the local subnet, but also hosts outside the own subnet can be tested
Make it permanent
Create a folder in C:\Program Files\Windows PowerShell\Modules. Name the folder Test-ConnectionLocalSubnet. Save the script there as psm1 file. Make sure the directory name and the file name are equal.
Close Windows PowerShell. Open PowerShell again. The command is now available for all users.
More about Powershell Moduls here: PowerShell Functions: How to create your first PowerShell Module Command
Have fun with Test-ConnectionLocalSubnet!
Categories: PowerShell, Windows 10, Windows Server
Can you please tell how to make it work for a List of IP addresses?
LikeLike
The same as with computer names
LikeLike
Patrick if you don’t mind I added to your script something very important, RDP test, of course this is only working from Powershell 4.0 and beyond, w8 ,w2012. thanks for sharing.
#iptest for icmp,arp, and rdp protocols
function Test-ConnectionLocalSubnet {
param ([Parameter(Mandatory=$True,Position=1)]
[System.Net.IPAddress]$IPAddress)
$entry= Write-Host “Testing $IPAddress …”
$line=”_____________________________________________________________”
$ping=Test-Connection -ComputerName $IPAddress -Count 3 -Quiet
$rdp=test-netconnection -computername $ipaddress -CommonTCPPort rdp
$arp=[boolean](arp -a | Select-String “$IPAddress”)
#waiting sucess in all three protocols
If ($ping -and $arp -and $rdp)
{$line; Write-Host “ICMP: successful” -ForegroundColor Green`n; Write-Host “ARP : successful” -ForegroundColor Green`n; Write-Host “RDP: successful” -ForegroundColor Green`n;$line; Write-Host “Host ${IPAddress} is up” -ForegroundColor Green; Write-Host “”}
#waiting only icmp success and complement with RDP
elseif ($ping -and !$arp )
{$line;write-host “testing also RDP connection”
$rdp=test-netconnection -computername $IPAddress -CommonTCPPort rdp
if ($rdp) {write-host “rdp working and enabled” -ForegroundColor green}
Write-Host “ICMP: successful” -ForegroundColor Green`n; Write-Host “ARP : failure” -ForegroundColor Red`n; Write-Host “RDP : failure” -ForegroundColor Red`n;$line; Write-Host “Host ${IPAddress} is up, but possibly not on local subnet”; Write-Host “”}
#waiting only arp and complement with RDP
elseif (!$ping -and $arp)
{$line;write-host “testing also RDP connection”
$rdp=test-netconnection -computername $IPAddress -CommonTCPPort rdp
if ($rdp) {write-host “rdp working and enabled” -ForegroundColor green}
$line; Write-Host “ICMP: failure” -ForegroundColor Red`n; Write-Host “ARP : successful” -ForegroundColor Green`n; $line; Write-Host “Possible Cause on ${IPAddress}: Firewall is blocking traffic”; Write-Host “”}
#Waiting failure on icmp and arp but still trying rdp
elseif (!$ping -and !$arp -and $rdp)
{$line;write-host “testing also RDP connection”
$rdp=test-netconnection -computername $IPAddress -CommonTCPPort rdp
if ($rdp) {write-host “rdp working and enabled” -ForegroundColor green}
$line; Write-Host “ICMP: failure” -ForegroundColor Red`n; Write-Host “ARP : failure” -ForegroundColor red`n; $line; Write-Host “remote connection to ${IPAddress}: is possible , other ports are closed for ${IPAddress}: on Firewall and blocking traffic”; Write-Host “”}
#complete failure
else
{$line; Write-Host “ICMP: failure” -ForegroundColor Red`n; Write-Host “ARP : failure” -ForegroundColor Red`n; Write-Host “RDP : failure” -ForegroundColor Red`n; $line; Write-Host “Host ${IPAddress} is down” -ForegroundColor Red; Write-Host “”}
}
LikeLiked by 1 person
Thank you for the advice. I’ve fixed it.
LikeLike
Smart post. You got the path for PS Modules wrong though. You have mentioned, “Create a folder in C:\Windows\Program Files\Windows PowerShell\Modules.”
LikeLike