[Looking for Charlie's main web site?]

Testing if a port can be reached, using built-in tools other than 'good old telnet'

Have you ever wanted to test (from the command line) whether a port on another machine can be reached from yours? When some app of your can't seem to connect to a given port, you may want to test things from the command line. (The problem may be that the service using that port has stopped or is blocked by a firewall--it may be that you're mistaken in the port you are trying to use, or perhaps even the ip address, domain name, or machine name.)

There are in fact many tools which can help with this task, some of which will be familiar to those on *nix systems, but Windows users who've been around a while (or who learned from such folks) may try to rely on the good ol' telnet command (as in telnet [machine] [port]). Unfortunately, they often find out how Microsoft has disabled that tool by default for over a decade (since Windows Vista), and while it can be easily enabled, they may be prevented or understandably reluctant to do that.

In this post, I want to show a couple of command-line alternatives which can do the job easily, one best suited for powershell users (Test-NetConnection), and and two of which would suit those who prefer the command line (cmd) and which are now built-into Windows (the past few years): ssh and curl. No, this is not their primary job but they will suit for this task and it may surprise some to learn they're even built-in options. I'll conclude with still other options available to those on *nix environments (who of course can also use ssh and curl), especially nc (netcat).

Topics:

Option 1) Powershell's nifty Test-NetConnection

Update: this first section has been added since my original post. Thanks to Mark Gregory for his kind comment suggesting it.

If you're a powershell user (or are ok using it, even if you favor still using the traditional Windows CMD for the command line), there's a nice cmdlet that can do this task of testing a connection to a port, Test-NetConnection, as in:

Test-NetConnection [machine] -port [port]

Of course, machine can be an ip address, domain name, machine name, etc., and it need not be a machine other than yours: it can be your own.

So for instance, someone might test if their SQL Server was reachable on the machine "dbserver" at port 1433 using:

Test-NetConnection dbserver -port 1433

The UI of the tool will appear as it tries to connect, and regardless of its results, in the end it will report true or false, as in:

Response includes TcpTestSucceeded: True

For some readers, that's really all you need to hear and you can stop. For those interested to learn more (who may want to propose other alternatives), please do read on.

What about the long delay if the port is NOT open

You may notice that this Test-NetConnection cmdlet will hang if the port on the machine trying to be reached is not available. That hang-time is as much about your a TCP timeout set at the OS level for your machine (from which you're running the test.) I discuss this more later with regard to curl and ssh (which offer options to override that timeout).

Sadly, at this writing, there's no option to override that timeout for Test-NetConnection. (Others have noticed and raised the concern. See this post for a couple of powershell approaches addressing this issue.)

Other ways do exist to test connectivity to such specific apps

Update: I previously had these few paragraphs in the next section, but I am moving them up to here because they're natural questions following the example I've offered, which I also use for the other variants below.

And yes, I'm well aware that there are other means by which one could test connectivity to something like SQL Server (or mysql or redis, etc.) from the commandline, using dedicated tools offered for each. The point of this post was to present approaches that works with ANY service whose port accessibility you're checking.

Finally, I'm also aware that there are other ways to find what ports are open on a given machine (port scanning tools) as well as whether and what ports are open on your machine, such as via good ol' netstat or UI tools like curports, to the more modern tool built into Windows (since Vista) called Resource Monitor. The focus here is again on a cli approach to test the accessibility of a port on any machine--versus finding if its one of many open ports, valuable though that info may be.

Anyway, moving on, for those who may still favor CMD (the command prompt) over powershell, you won't find it offering that nifty Test-NetConnection (though again you can call powershell commands from cmd). Instead, you may find some comfort in using curl or ssh, instead, which are covered in the remainder of this post.

Yes, Windows has included ssh and curl for a few years!

So as for ssh and curl, let me point out first some news which may have been missed by many (including those who try to help others or who write about IT matters). You don't NEED to "install putty" anymore: Windows has included ssh (an openssh client) for a few years, since later versions of Windows 10 and Server 2019. And the same is true of curl (a command-line browser).

If you want to confirm this, just open a Windows command prompt and type ssh (it should be found within your Windows path, and so should run), which will return brief help for the command. Same with curl!

Now granted, I realize that using curl or ssh to test the availability of a port (especially on another server) is not the real purpose of those tools--any more than it was the purpose of telnet. But the point is that these generally do "work" well, so they're tools to consider for one's arsenal. And again, I'll cover other tools that you may be able to obtain or find in some Linux distros (or MacOS or Unix) at the end of this post.

Considering also that you find either curl or ssh to suit you better for some situations, I will discuss them both. And I could have presented either one first. I offer curl first as some may be more comfortable with that, if they don't have much experience with ssh. Again the key point is that both these tools should be available to everyone reading this, unless they're on very old deployments of Windows.

Option 2) Using curl to test connectivity to a port

So let's look first at using curl to test if a port can be reached (though really, I'd recommend option 1 above or option 3 below, for reasons which will become clear):

curl [machine]:[port]

Note there's a colon between the machine and the port. Again, machine could be an ip address, domain name, machine name, etc.

So for instance, someone might test if their SQL Server was reachable on the machine "dbserver" at port 1433 using:

curl dbserver:1433

So let's talk about what one may see depending on whether the connection via curl can or cannot be made. Of course, normally one uses curl to visit a given page on a given site, but again we're just "hacking" it to have it try to merely connect.

How the curl command responds if the port CANNOT be reached, and dealing with hang time

If somehow that machine (or ip address or domain name) cannot be reached, the request will hang (more on that in a moment) and then the curl command will respond with this error:

curl: (28) Failed to connect to [machine]: [port] after [duration]: ms: Couldn't connect to server

The key is that this tells us that that the port could not be reached. (As for "why not", neither curl nor ssh can help with that. I discuss that at the end.)

As for this "hang time" waiting to connect, this is something telnet did also. The amount of time it will wait is technically defined by your OS, and is known generically as the TCP timeout time. A difference with curl versus telnet is that you CAN control how long you're willing for the curl command to await using the command's optional connect-timeout flag, as in the following example to set a 1-second timeout:

curl --connect-timeout 1 [machine]:[port]

Finally, if you find it does not stop trying to connect within the number of seconds indicated, do beware that the curl tool may be attempting different additional connections than you may realize. Add the -v arg to the command, to see more verbose output, including details of the connections it's attempting.

curl -v --connect-timeout 1 [machine]:[port]

So that's how the tool can tell us (or be tweaked regarding) the failure to connect. Let's move on to what it may show if it CAN connect.

How the curl command responds if the port CAN be reached

Remembering that curl is first and foremost a command-line http client, if the connection is successful AND there's a web server on the other end (with a default web page to satisfy this request), the command will respond showing us the output of the page, whatever it is. :-) Or if it does not exist, it will perhaps show the content returned in the form of some sort of 404 error page. (And yes, there are ways to pipe its output to a file or the bit bucket, but I leave you to check out the docs for that.)

If instead the port being tested could be reached but it is NOT for a web server (which may be more common for folks seeking to "test a port's accessibility"), then the curl command will respond (immediately) with an error:

curl: (52) Empty reply from server

And given that our goal again is just to know if the port can be reached, there's value in getting that immediate error: the port CAN be reached.

(Another beneficial difference of this over the old telnet approach is that with that, a successful connection would show a blank screen if the connection, awaiting commands. You'd have to know telnet keystrokes and commands to break out of that, or you might close the terminal window if testing the port was your only reason for opening it.)

But maybe you feel itchy about using curl for this task. Well, if you can be persuaded, there is again the alternative of using ssh...

Option 3) Using ssh to test connectivity to a port

As for using ssh to test if a port can be reached, you could do something like this:

ssh -p [port] [machine]

Again, machine could be an ip address, domain name, machine name, etc. (And those two values of machine and port are indeed the reverse order of both the curl above and the traditional telnet.)

How the ssh command responds if the port CANNOT be reached, and dealing with hang time

If the port CANNOT be reached, then (like with curl and telnet) the command will hang for an extended period of time before failing with an error like:

ssh: connect to host [machine] port [port]: Connection timed out

So with my example above, I'd receive this if SQL Server was not listening or inaccessible:

ssh: connect to host dbserver port 1433: Connection timed out

And as in the case of curl, if you want to override that long TCP timeout time for your OS, you can do that with the command's optional ConnectTimeout flag. The following to set a 1-second timeout:

ssh -o ConnectTimeout=1 -p [port] [machine]

(And as with curl, if you find it does not stop trying to connect within the number of seconds indicated, do beware that the ssh tool may be attempting different connections than you realize. add the -v arg to the command, to see more details of the connections it's attempting.)

Again, as for "why" it can't be reached, see the end of this port for ideas to consider.

How the ssh command responds if the port CAN be reached

If on the other hand the port CAN be reached, the ssh command will respond immediately, which is nice. And that's what makes this (like curl) indeed a helpful tool (.

That said, note that if the port you're checking is technically not an ssh port, the command will also report an "error":

kex_exchange_identification: Connection closed by remote host

In the case of using the command for this test of port connectivity, we can ignore that error. Again, at least this confirms that the port could be reached, which was our primary goal.

Using other cli tools on Linux, Unix, MacOS

Before wrapping up this post, I mentioned at the open how this this technique may appeal to Windows users more than those on *nix OS's, as they not only already have long had the two tools above, but they have still other tools they can use for this task of testing for whether a port can be reached, such as netcat/nc, which could handle this just as simply:

nc -zv [machine] [port]

And as for port-scanning (the broader process of determining what ports are open on a given machine), there is the classic (and powerful) nmap command, but it's beyond the scope of this post (as its related tool ncat, which is not the same as netcat above).

On understanding WHY the port being checked could not be reached

Finally, I realize some may wonder how to know WHY a port can't be reached, but neither of these tools can help with that: they merely respond one way if the port CAN be reached and another if it cannot.

As I noted at the opening, the reach a port may not be open is that the service you're trying to reach is not enabled. Or maybe there's a firewall blocking access to it (which blocking could be specific to your machine from you are attempting to make the connection). There may be a firewall in the OS of the machine you're talking to, or one that's been installed there as software, or there may be one on the network you're connecting to, etc.

Or you may simply have the wrong value for the port you are testing, or the ip address, domain name, machine name, etc.

Before we wrap up, note that sometimes you may find that a given machine can be identified any of many different ways--such that a port may be "open" to you if you try a way that's different from what you're trying (so try an ip address if you have a domain name, or vice-versa, or perhaps try a subdomain if you know of one, and so on).

Often, you will need to get on the server itself (which you can't reach) and attempt these or other tools THERE, to find out if the port is correct in the first place.

Conclusion

I hope I've helped you see how curl and ssh (and nc) can be handy tools to have in your arsenal, when you just want to quickly test port accessibility from the commandline. For those on Windows, you can stop trying to install telnet to do a quick port test: just use curl or ssh! :-) That was really the primary motivation of my post here.

And let me know how it goes.

Indeed, this is one of those topics where there may be dark corners, edge cases, and unexpected situations where results differ. I'm sure some people have more experience to share, whether other gotchas or tips, or still other tools that may be built-in to Windows or *nix. As for other tools one might obtain, those are less interesting as again the post here is about built-in tools, because often people are working in environments (especially on servers or containers) where they're not necessarily free to/wanting to install software.

As always I welcome comments.

For more content like this from Charlie Arehart: Need more help with problems?
  • If you may prefer direct help, rather than digging around here/elsewhere or via comments, he can help via his online consulting services
  • See that page for more on how he can help a) over the web, safely and securely, b) usually very quickly, c) teaching you along the way, and d) with satisfaction guaranteed
Comments
Thanks for the writeup!
There is also the option of using Powershell:
Test-NetConnection 127.0.0.1 -port 8500

Response includes TcpTestSucceeded: True (or False)
# Posted By Mark Gregory | 10/6/23 12:50 PM
Nice one, Mark. Thanks. It has some nice UI touches as well. I'll leave readers to try it.

And for the sake of completeness, I could (and perhaps should) also have offered ps equivalents to the curl and ssh, though the former does differ.

Let me take ssh first. Some good news is that it works identically in ps as in cmd: the help for each shows identical args and the example I'd offered in the post above returns the exact same results in either (in my testing).

As for curl, as some may know it works in powershell as an alias to the Invoke-WebRequest cmdlet. That said, you DO have to provide the protocol (like https://) when using curl in ps, which looks even more odd if requesting a port of something like sql server. Here's the powershell equivalent of my curl above calling to sql server:

curl http://dbserver:1433...

Again, I explained that using curl for a non-web server is rather obtuse. I only offered it first above as it might be more familiar to some than using SSH. (Your Test-NetConnection is indeed a nicer alternative.)

Anyway, the curl in ps will report the html (and more) if it can reach a web server. And if it can't connect it will return ("Unable to connect to the remote server"), but that's regardless of whether the port is reachable or not! Recall that the curl at the CMD line would get "Empty reply from server", as I noted above. Another reason to lean on your Test-NetConnection instead, if using ps.

I appreciate that some have moved to powershell as their main way of working at the command line in Windows--and MS is even pushing that. Some die-hards always gravitate to cmd instead (and I'm one of them), so I admit my focus here leaned that way. Thanks for the nudge to speak from a ps perspective as well, and especially for your offer of the even more nifty Test-NetConnection. I think I will modify my post to offer that as a first alternative, for those who may find it the most elegant option (on Windows).
Pure bash option:

: < /dev/tcp/google.com/80 && echo OK || echo ERROR
# Posted By Snawoot | 10/7/23 3:16 PM
Snawoot, if you find that memorable, great. :-) Then again, I was focused more on options to suit Windows users. And I'd said I realized there may be even more to suit *nix users, though these and/or netcat might suit them and be simple. Still, thanks for sharing your thought.
It's funny: I'm coming across more than one blog post written recently by others addressing the same topic, such as:

https://www.baeldung...

https://www.saotn.or...

Great minds. :-) And I'd not seen the others beforehand, or I'd have referenced them for additional perspective, which is why I mention them now.

I suppose this could seem like when you buy a car and suddenly notice "so many others driving it". But actually they showed up on feeds for those sites, which I follow. The odd thing is that multiples of us would write on it around the same time. There was nothing recent about what we were reporting. Just odd. :-)
Thank you for this nice post. Just letting you know that anchor link for the 1st topic is not working :)
Thanks. George. Fixed. It was just missing the #. FWIW, that "first" section was added when I updated the post per a comment offered. Bummer that typo slipped by in the effort. Thanks for the heads-up.
Copyright ©2024 Charlie Arehart
Carehart Logo
BlogCFC was created by Raymond Camden. This blog is running version 5.005.
(Want to validate the html in this page?)

Managed Hosting Services provided by
Managed Dedicated Hosting