Test if a port on a remote system is reachable (without telnet)
In the old days, we used telnet to see if a port on a remote host was open: telnet hostname port would attempt to connect to any port on any host and give you access to the raw TCP stream. These days, the systems I work on do not have telnet installed (for security reasons), and all outbound connections to all hosts are blocked by default. Over time, it’s easy to lose track of which ports are open to which hosts. Is there another way to test if a port on a remote system is open – using a Linux system with a limited number of packages installed, and telnet is not available?
I was having this same issue. The answer by @Subhranath Chunder below helped. However, I then found out that installing Telnet was a small matter of running brew install telnet . So I expect Linux users can do the same with yum and apt-get .
When «all outbound connections to all hosts are blocked by default» there will be no way to perform such a test — you are offline
14 Answers 14
Bash has been able to access TCP and UDP ports for a while. From the man page:
/dev/tcp/host/port If host is a valid hostname or Internet address, and port is an integer port number or service name, bash attempts to open a TCP connection to the corresponding socket. /dev/udp/host/port If host is a valid hostname or Internet address, and port is an integer port number or service name, bash attempts to open a UDP connection to the corresponding socket.
So you could use something like this:
However on ports that were not open it timed out after 22 seconds (tried on Ubuntu 14.04 (Trusty Tahr) for a remote server). Interestingly, the timeout period is much shorter than the one for nc (see thnee’s answer).
@lornix, ok, but in this case I have to get the same result with use nc without -z option, but it still does not work: # nc -v -w5 127.0.0.1 18080 Connection to 127.0.0.1 18080 port [tcp/*] succeeded! # cat < /dev/tcp/127.0.0.1/18080 Just hangs without any result. Just want to understand when I can use "/dev/tcp/host/port" option
@Alexandr. actually, «hangs without any result» is pretty much expected behavior. cat is waiting for input. nc has extra smarts to enable it to sense no-data pending and stops trying. cat isn’t quite as smart. Try cat < /dev/tcp/localhost/22 , you should get your sshd header. Evidently, your process on port 18080 waits for something to come in, before sending anything. Port 22 (ssh) greets you with it’s version and whatnot. Try it out!
@lornix, thank you very much for explanation! Now the restriction is clear. I think using nc should be a preferred way to check ports.
This was incredibly helpful when working with a docker container that had nothing installed. Was able to quickly verify that the container had access to non-containerized DB via DNS. Example: cat < /dev/tcp/hostname/5432
Nice and verbose! From the man pages.
Single port:
This hanged when tried on Ubuntu 14.04 (Trusty Tahr) for a remote server (same LAN) for closed ports (it timed out after 127 seconds) — thus not very suitable in scripts. It did work though for a service that had a port open. Using option «-w2» could be the solution.
that’s great, but only if nc is actually installed 😛 the accepted answer via bash works almost everywhere, more GNU/Linux servers have bash than nc
Will output 0 if port 123 is open, and 1 if it’s closed.
This is a far more elegant and scriptable answer than my own. It is unfortunate for me that the security-conscious sysadmins who withheld telnet also withheld nc (though – strangely – not curl or wget ).
This hanged when tried on Ubuntu 14.04 (Trusty Tahr) for a remote server (same LAN) for closed ports (it timed out after about 127 seconds) — thus not very suitable in scripts. It did work though for a service that had a port open, returning 0. Using option «-w2» could be the solution.
The simplest method, without making use of another tool, such as socat , is as described in @lornix’s answer above. This is just to add an actual example of how one would make use of the psuedo-device /dev/tcp/. within Bash if you wanted to, say, test if another server had a given port accessible via the command line.
Examples
Say I have a host on my network named skinner .
$ (echo > /dev/tcp/skinner/22) >/dev/null 2>&1 \ && echo "It's up" || echo "It's down" It's up $ (echo > /dev/tcp/skinner/222) >/dev/null 2>&1 && \ echo "It's up" || echo "It's down" It's down
The reason you want to wrap the echo > /dev/. in parentheses like this, (echo > /dev/. ) is because if you don’t, then with tests of connections that are down, you’ll get these types of messages showing up.
$ (echo > /dev/tcp/skinner/223) && echo hi bash: connect: Connection refused bash: /dev/tcp/skinner/223: Connection refused
These can’t simply be redirected to /dev/null since they’re coming from the attempt to write out data to the device /dev/tcp . So we capture all that output within a sub-command, i.e. (. cmds. ) and redirect the output of the sub-command.
How to check if a certain port is open and unused?
Could you please help and tell how can i find out if port 80 is open and unused so that I can start installation.
For what it’s worth, /etc/services is completely static. Grepping it can tell you if a port is officially designated by IANA or some such, but does not tell whether or not it’s in local use.
9 Answers 9
sudo netstat -anp | grep ':80 '
That should give you pid & name of the process that holds port 80
This can be achieved using the nc command as follows:
It will return TRUE if the port is already in use, or FALSE is it (i.e, available not listening currently).
I don’t recommend lsof or netstat method as it first try to scan all running PIDs to get all bounded ports:
# time lsof -i:8888 real 0m1.194s user 0m0.137s sys 0m1.056s``` # time nc -z 127.0.0.1 8888 real 0m0.014s user 0m0.011s sys 0m0.004s
Here 8888 is an unused port. The nc command is ~85 times faster in the above example.
Eg 1:
$ nc -z 127.0.0.1 80 && echo "IN USE" || echo "FREE" IN USE $ nc -z 127.0.0.1 81 && echo "IN USE" || echo "FREE" FREE
Eg 2:
If you are trying with a remote IP, it is better to add a timeout to auto-exit if it is not accepting connection for the specified time.
Its Google’s IP which is not used, so it will timeout after trying for 2 seconds.
This also works greatly when running inside the Docker image that uses host network. Inside the image, lsof incorrectly reports the port is not in use when it actually is.
The traditional version of nc does not include the -z option. See the differences between traditional and openbsd.
netstat -tln | tail -n +3 | awk '< print $4 >'
This one displays bind addresses of TCP listening endpoints. All other endpoints are free; Also if on Unix and you are not root, then you can’t bind to a ‘privileged’ port number (port number lower than 1024).
Explained in more details:
- netstat -tln — all listening tcp ports
- tail -n +3 — cut off the header of netstat command
- awk ‘< print $4 >‘ — print the fourth column that consists of [ip]:[port]
For the general case you still need to care to cut out all irrelevant interfaces; a listening address 0.0.0.0 is listening on all network cards, if there is an IP address then that’s the specific IP of the network card/network interface.
Check if port is open or closed on a Linux server?
It’s not quite clear what you’re asking. What do you mean by «open»? Do you mean some server is listening on that port? Or do you mean it’s allowed by the system firewall? Or what?
nc -w5 -z -v
A topic that contains an answer also for kernel level services and programs serverfault.com/questions/1078483/…
8 Answers 8
You can check if a process listens on a TCP or UDP port with netstat -tuplen .
To check whether some ports are accessible from the outside (this is probably what you want) you can use a port scanner like Nmap from another system. Running Nmap on the same host you want to check is quite useless for your purpose.
GNU netstat knows the parameters -t , -u , -p , -l , -e , and -n . Thanks to the options parser it can be expressed as -tuplen . linux.die.net/man/8/netstat
Also, the telnet command usually does only supports TCP, so you’re out of luck if the service you want to check runs on another protocol.
According to article: computingforgeeks.com/netstat-vs-ss-usage-guide-linux netstat is deprecated, and ss is it’s replacement, so you can do ss -an , ss -tuplen or for tcp listening sockets ss -ntlp .
Quickest way to test if a TCP port is open (including any hardware firewalls you may have), is to type, from a remote computer (e.g. your desktop):
Which will try to open a connection to port 80 on that server. If you get a time out or deny, the port is not open 🙂
OK, in summary, you have a server that you can log into. You want to see if something is listening on some port. As root, run:
this will show a listing of processes listening on TCP and UDP ports. You can scan (or grep) it for the process you’re interest in,and/or the port numbers you expect to see.
If the process you expect isn’t there, you should start up that process and check netstat again. If the process is there, but it’s listening on a interface and port that you did not expect, then there’s a configuration issue (e.g., it could be listening, but only on the loopback interface, so you would see 127.0.0.1:3306 and no other lines for port 3306, in the case of the default configuration for MySQL).
If the process is up, and it’s listening on the port you expect, you can try running a «telnet» to that port from your Macbook in your office/home, e.g.,
telnet xxxxxxxxxxxx.co.uk 443
That will test if (assuming standard ports) that there’s a web server configured for SSL. Note that this test using telnet is only going to work if the process is listening on a TCP port. If it’s a UDP port, you may as well try with whatever client you were going to use to connect to it. (I see that you used port 224. This is masqdialer, and I have no idea what that is).
If the service is there, but you can’t get to it externally, then there’s a firewall blocking you. In that case, run:
This will show all the firewall rules as defined on your system. You can post that, but, generally, if you’re not allowing everything on the INPUT chain, you probably will need to explicitly allow traffic on the port in question:
iptables -I INPUT -p tcp --dport 224 -j ACCEPT
or something along those lines. Do not run your firewall commands blindly based on what some stranger has told you on the Internet. Consider what you’re doing.
If your firewall on the box is allowing the traffic you want, then your hosting company may be running a firewall (e.g., they’re only allowing SSH (22/tcp), HTTP (80/tcp) and HTTPS (443/tcp) and denying all other incoming traffic). In this case, you will need to open a helpdesk ticket with them to resolve this issue, though I suppose there might be something in your cPanel that may allow it.