There are few things more frustrating in IT than troubleshooting weird network problems. Especially when those weird network problems, impact browsing to normal everyday websites where our other tools live. It’s a pain point we can all identify with.
Inevitably, when you complain you can’t reach a website you’ll be greeted with one of the following questions:
– Have you tried pinging it?
– Have you cleared the cache on your browser?
– Try a different browser
Of course, you try all of these and either none of them work, or some of them do, or a confusing array of both happens. Over the course of this post, we are going to move from a simple ping network test to programmatic testing using PowerShell, and GO.
Wait what am I going to learn here?
Essentially, writing network tests is hard, doubly so when you have to test against over 100 sites. We are going to show you how you can test network connections with Ping, PowerShell and GO. Additionally, you’ll walk away with a couple of PowerShell snippets you can re-use, some GO code, and a very, very fast network tester app for all of the websites and ports Patch My PC uses.
Let’s dive into network testing, and what it looks like.
Let’s face it, networking is hard. Right wrong or indifferent the language everyone has been conditioned to use is either “the internet works”, or “the internet doesn’t work”. When it comes to corporate network environments this is rarely the case. Here is a fun example where I used the windows firewall to block a couple of Googles IP Addresses. The resulting behavior is interesting.
There are a TON of ways to test a network connector. Each of these methods has their own strengths and weakness’s. There is no one size fits all when it comes to testing network connections, because of how flexible networking has grown to be. The methods below are by no means exhaustive.
Good Ole Ping
The first method people typically learn is good ole “ping” through the command prompt. Ping is a fantastic tool, it’s included on almost every machine in the world. Windows, Linux, Mac Ping doesn’t care it’s there for you.
Let’s try it out.
As you can see above Ping sent four packets of data using what’s called ICMP (Internet Control Message Protocol). What’s important to know about this is ICMP is ephemeral, IE it’s not port specific. This can cause you to miss certain types of blocks when performing tests, especially if a firewall is only blocking specific ports.
While Ping doesn’t support testing specific ports, there are a ton of other useful options you can use to better test the availability of the network including some useful options below.
There are a bunch of other options, and you can learn more about them here: ping | Microsoft Learn
Test-connection is effectively a wrapper cmdlet for ping, and as a result conveys a lot of the same information, with a lot of the same limitations (IE can only test for ICMP). What makes Test-Connection special is how it returns objects of type: ‘Win32_PingStatus’
Because the feedback from test-connection is an object as presented above, you can actively evaluate the information that was returned from the attempted ICMP communication and then make decisions based on the details of the results.
Test-NetConnection provides some of the granularity for network tests ping is missing. This cmdlet instead produces an object of TestNetConnectionResult. One thing to note about Test-NetConnection, the cmdlet always displays information about the test while it’s running by default unless you configure the $ProgressPreference environment variable. This variable cannot be set at run time, and instead must be set for the environment.
The most important thing about Test-NetConnection, is the ability to specify your desired port using the port parameter.
What if you have a ton of websites you need to test? Programmatic Testing
A question we commonly get asked at Patch My PC, is do you have an allow list available to better understand what ports we would need to open in our network? Conveniently we do have a list:
However, that list is quite large, 864 different URLS in fact! Testing all of those will take surely take some time. Unless you automate it!
PowerShell Bulk Testing
Something you could surely do with some simple PowerShell.
However, it will take a significant portion of time as each action must be done in serial order. If you’re familiar with PowerShell we could of course look at using the parallelization features available in PowerShell 7.1+, assuming it’s available for you to use.
Go Bulk Testing
The code above combines two core concepts in GO. Routines, and a wait group. A wait group, indicates that we should wait for the routines to finish. All of these routines within the wait group then run completely independent of each other.
While GO supports Types and Methods, there is no Type Hierarchy, and more interestingly, as long as you have the GO environment you do not have to compile the code to run it for testing purposes.
Your First GO Network Test
In order to make a functional test, we’ll need to ensure we import three default packages.
With these we can quickly write a test to validate if we can get to google!
This works great if we want to painstakingly go through a ton of URL’s and ports. What if instead we wanted to say download a URL from a website that was in CSV Format and already had all of the websites and ports we would need? Well no problem we can do that!
A Patch My PC Network Tester
A while back, we had a pretty common occurrence where customers would be unable to download content due to network filtering rules. Troubleshooting this, and providing logs that help showcase it can be challenging especially in complex environments where things like user based proxies come into play. Instead of walking people through building PowerShell scripts unique to their environment a simplified network tester was born.
However, we need a few things to make it work.
First a function/package to download a file if we give it a URL.
Next a function to log everything that happens, in our favorite log format CMTrace.
And then finally let’s pull it all together with our main function.
Now we could run this entire test by simply using the go run command as seen in other examples earlier on, but that assumes the go runtime environment exists on the device running the test, a bad assumption. Instead we are going to use the build command to generate a compiled file that can be run anywhere. Don’t worry, you won’t have to build it you can download and find all the code available to you here.
The release is a signed binary file.
One final takeaway about how this is written is the sheer speed involved with the execution of the tests. Even using the previously mentioned PowerShell Parallelization methods doesn’t come close to how fast compiled code in parallel can run.
For the purposes of demonstration, a host’s file edit has been made on the server to force all GitHub.com requests to re-direct to a non-existent IP address. I hope this was helpful, and as always happy patching.
Jordan Benzing loves patching and has had the opportunity to present on stages all around the world including the Midwestern Management Summit in Minneapolis, on subjects such as reporting, patching, and that wonderful thing no one likes doing: documentation. Jordan has been an avid content creator, and educator since 2016. Jordan has been fortunate enough to earn the Microsoft MVP award from 2020-2023 in the Enterprise Mobility category. He also has six, yes that’s right, six dogs. Two Golden Retrievers, a Shiba Inu, two german shepherds, and a Belgian Malinois.