Efficiently test if a port is open on Linux? - linux

From a bash script how can I quickly find out whether a port 445 is open/listening on a server.
I have tried a couple of options, but I want something quick:
1. lsof -i :445 (Takes seconds)
2. netstat -an |grep 445 |grep LISTEN (Takes seconds)
3. telnet (it doesn't return)
4. nmap, netcat are not available on the server
It will be nice to know of a way that doesn't enumerate first and greps after that.

A surprise I found out recently is that Bash natively supports tcp connections as file descriptors. To use:
exec 6<>/dev/tcp/ip.addr.of.server/445
echo -e "GET / HTTP/1.0\n" >&6
cat <&6
I'm using 6 as the file descriptor because 0,1,2 are stdin, stdout, and stderr. 5 is sometimes used by Bash for child processes, so 3,4,6,7,8, and 9 should be safe.
As per the comment below, to test for listening on a local server in a script:
exec 6<>/dev/tcp/127.0.0.1/445 || echo "No one is listening!"
exec 6>&- # close output connection
exec 6<&- # close input connection
To determine if someone is listening, attempt to connect by loopback. If it fails, then the port is closed or we aren't allowed access. Afterwards, close the connection.
Modify this for your use case, such as sending an email, exiting the script on failure, or starting the required service.

There's a very short with "fast answer" here : How to test if remote TCP port is opened from Shell script?
nc -z <host> <port>; echo $?
I use it with 127.0.0.1 as "remote" address.
this returns "0" if the port is open and "1" if the port is closed
e.g.
nc -z 127.0.0.1 80; echo $?
-z Specifies that nc should just scan for listening daemons,
without sending any data to them. It is an error to use this option
in conjunc-
tion with the -l option.

You can use netstat this way for much faster results:
On Linux:
netstat -lnt | awk '$6 == "LISTEN" && $4 ~ /\.445$/'
On Mac:
netstat -anp tcp | awk '$6 == "LISTEN" && $4 ~ /\.445$/'
This will output a list of processes listening on the port (445 in this example) or it will output nothing if the port is free.

You can use netcat for this.
nc ip port < /dev/null
connects to the server and directly closes the connection again. If netcat is not able to connect, it returns a non-zero exit code. The exit code is stored in the variable $?. As an example,
nc ip port < /dev/null; echo $?
will return 0 if and only if netcat could successfully connect to the port.

Based on Spencer Rathbun's answer, using bash:
true &>/dev/null </dev/tcp/127.0.0.1/$PORT && echo open || echo closed

they're listed in /proc/net/tcp.
it's the second column, after the ":", in hex:
> cat /proc/net/tcp
sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode
0: 00000000:0016 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 10863 1 ffff88020c785400 99 0 0 10 -1
1: 0100007F:0277 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 7983 1 ffff88020eb7b3c0 99 0 0 10 -1
2: 0500010A:948F 0900010A:2328 01 00000000:00000000 02:00000576 00000000 1000 0 10562454 2 ffff88010040f7c0 22 3 30 5 3
3: 0500010A:E077 5F2F7D4A:0050 01 00000000:00000000 02:00000176 00000000 1000 0 10701021 2 ffff880100474080 41 3 22 10 -1
4: 0500010A:8773 16EC97D1:0050 01 00000000:00000000 02:00000BDC 00000000 1000 0 10700849 2 ffff880104335440 57 3 18 10 -1
5: 0500010A:8772 16EC97D1:0050 01 00000000:00000000 02:00000BF5 00000000 1000 0 10698952 2 ffff88010040e440 46 3 0 10 -1
6: 0500010A:DD2C 0900010A:0016 01 00000000:00000000 02:0006E764 00000000 1000 0 9562907 2 ffff880104334740 22 3 30 5 4
7: 0500010A:AAA4 6A717D4A:0050 08 00000000:00000001 02:00000929 00000000 1000 0 10696677 2 ffff880106cc77c0 45 3 0 10 -1
so i guess one of those :50 in the third column must be stackoverflow :o)
look in man 5 proc for more details. and picking that apart with sed etc is left as an exercise for the gentle reader...

ss -tl4 '( sport = :22 )'
2ms is quick enough ?
Add the colon and this works on Linux

nc -l 8000
Where 8000 is the port number. If the port is free, it will start a server that you can close easily. If it isn't it will throw an error:
nc: Address already in use

Here's one that works for both Mac and Linux:
netstat -aln | awk '$6 == "LISTEN" && $4 ~ "[\\.\:]445$"'

I wanted to check if a port is open on one of our linux test servers.
I was able to do that by trying to connect with telnet from my dev machine to the test server. On you dev machine try to run:
$ telnet test2.host.com 8080
Trying 05.066.137.184...
Connected to test2.host.com
In this example I want to check if port 8080 is open on host test2.host.com

You can use netcat command as well
[location of netcat]/netcat -zv [ip] [port]
or
nc -zv [ip] [port]
-z – sets nc to simply scan for listening daemons, without actually sending any data to them.
-v – enables verbose mode.

tcping is a great tool with a very low overhead.It also has a timeout argument to make it quicker:
[root#centos_f831dfb3 ~]# tcping 10.86.151.175 22 -t 1
10.86.151.175 port 22 open.
[root#centos_f831dfb3 ~]# tcping 10.86.150.194 22 -t 1
10.86.150.194 port 22 user timeout.
[root#centos_f831dfb3 ~]# tcping 1.1.1.1 22 -t 1
1.1.1.1 port 22 closed.

nmap is the right tool.
Simply use nmap example.com -p 80
You can use it from local or remote server.
It also helps you identify if a firewall is blocking the access.

If you're using iptables try:
iptables -nL
or
iptables -nL | grep 445

Related

netstat gives 1 as PID for all ssh connections

In my custom linux image using netstat 1.42 (2001-04-15) from the package net-tools 1.60 I am seeing different behaviors for different linux versions..
On Linux 5.4.28:
# netstat -tnp | grep ESTABLISHED
tcp 0 0 <local_ip>:22 <client_ip>:14321 ESTABLISHED 29342/1
tcp 0 40 <local_ip>:22 <client_ip>:22470 ESTABLISHED 28443/0
On Linux 5.10.65:
# netstat -tnp | grep ESTABLISHED
tcp6 0 52 <local_ip>:22 <client_ip>:22470 ESTABLISHED 1/init
tcp6 0 52 <local_ip>:22 <client_ip>:33679 ESTABLISHED 1/init
The thing to note here is that on Linux 5.10, netstat shows PID as 1 and process as init for all ssh sessions. But in older linux, I am seeing correct PIDs for all ssh sessions. I need to know the client_ip and the PID for every ssh session so I can kill the session for whichever client I want.
From online searches, I could not figure out any fixes.
One alternative that I can see till now is using who to get this output:
# who
root pts/1 00:00 Jan 12 07:16:19 <client_ip>
root pts/2 00:03 Jan 12 08:21:07 <client_ip>
grep this with client_ip then use ps and grep that with the second column, like ps | grep pts/1 for first client.
Is there anything I can do to netstat to fix this though? Because netstat also give the client port which is useful for me.

How to listen for multiple tcp connection using nc

How to create a TCP connection using nc which listens to multiple hosts?
nc -l -p 12345
Simultaneous connections are not possible with netcat. You should use something like ucspi-tcp's tcpserver tool or leverage xinetd since you're on Linux.
See: https://superuser.com/questions/232747/netcat-as-a-multithread-server
Consecutive connections could be handled through a shell script that restarts netcat after it finishes.
ncat can do it.
E.g. ncat --broker --listen -p 12345 will distribute all incoming messages to all other clients (think of it as a hub).
I recommend socat as nc alternative.
For OP's problem, socat - TCP-LISTEN:12345,fork,reuseaddr can do the job.
-k
Forces nc to stay listening for another connection after its current connection is completed. It is an error to use this option without the -l option.
using nc it is not possible to open parallel connections to same port, however you can trick nc to open multiple connections to same port.
To understand this, lets say you start listening on 4444 port using $ nc -l -p 4444 -v. Now, if you check output of $ netstat -anp | grep 4444 you will get its state as LISTEN and in here its pid is 3410.
tcp 0 0 0.0.0.0:4444 0.0.0.0:* LISTEN 3410/nc
Now, after it gets connected to client, lets say you run $ nc localhost 4444 -v, its state will get changed into ESTABLISHED. Now, try running $ netstat -anp | grep 4444 you will get its state as ESTABLISHED, see for same pid 3410, and a client process with pid 3435
tcp 0 0 127.0.0.1:46678 127.0.0.1:4444 ESTABLISHED 3435/nc
tcp 0 0 127.0.0.1:4444 127.0.0.1:46678 ESTABLISHED 3410/nc
Please note that there is no available listening port, so you can't have another client process. However if you run again $ nc -l -p 4444 -v you can have a listening port and can have multiple client process.
see netstat -anp | grep 4444 output after you start listening to same port.
tcp 0 0 0.0.0.0:4444 0.0.0.0:* LISTEN 3476/nc
tcp 0 0 127.0.0.1:46678 127.0.0.1:4444 ESTABLISHED 3435/nc
tcp 0 0 127.0.0.1:4444 127.0.0.1:46678 ESTABLISHED 3410/nc
see netstat -anp | grep 4444 output after you attach new client to same port.
tcp 0 0 127.0.0.1:4444 127.0.0.1:46694 ESTABLISHED 3476/nc
tcp 0 0 127.0.0.1:46678 127.0.0.1:4444 ESTABLISHED 3435/nc
tcp 0 0 127.0.0.1:4444 127.0.0.1:46678 ESTABLISHED 3410/nc
tcp 0 0 127.0.0.1:46694 127.0.0.1:4444 ESTABLISHED 3483/nc
You can say connections behavior is like:
SERVER_PROCESS_1 <---> CLIENT_PROCESS_1
SERVER_PROCESS_2 <---> CLIENT_PROCESS_2
so, you can write some script to simulate this behavior, or use this bash script to modify.
#!/usr/bin/bash
lport="4444"
i=0;
while [ true ]; do
echo "opening socket $(( i++ ))";
if [[ "$(ss sport = :$lport -l -H | wc -l)" -eq 0 ]]; then
nc -l -vv -p $lport &
#do something else to process or attach different command to each diff server process
fi;
if [[ "$(ss sport = :$lport -l -H | wc -l)" -ne 0 ]]; then
watch -n 0.1 -g "ss sport = :$lport -l -H" > /dev/null;
fi;
if [[ i -eq 10 ]]; then
break;
fi;
done;
in here every time client consume a connection this script will start new listen socket.
This behavior is however can be changed in ncat (here, using -k)as you can analyze the with below example:
server is started using $ ncat -l -p 4444 -v -4 -k and 3 clients are started using $ ncat -4 localhost 4444. Now output for $ netstat -anp | grep 4444 is:
tcp 0 0 0.0.0.0:4444 0.0.0.0:* LISTEN 3596/ncat
tcp 0 0 127.0.0.1:4444 127.0.0.1:46726 ESTABLISHED 3596/ncat
tcp 0 0 127.0.0.1:46726 127.0.0.1:4444 ESTABLISHED 3602/ncat
tcp 0 0 127.0.0.1:46722 127.0.0.1:4444 ESTABLISHED 3597/ncat
tcp 0 0 127.0.0.1:4444 127.0.0.1:46724 ESTABLISHED 3596/ncat
tcp 0 0 127.0.0.1:4444 127.0.0.1:46722 ESTABLISHED 3596/ncat
tcp 0 0 127.0.0.1:46724 127.0.0.1:4444 ESTABLISHED 3601/ncat
Every time new client connect, server fork its process to attach to client, so each server process is using same pid. So output of server in this way is shared to every attached clients, however each client can send individual message to server.
You can say connections behavior is like:
SERVER_PROCESS_1 <---> CLIENT_PROCESS_1
SERVER_PROCESS_1 <---> CLIENT_PROCESS_2
SERVER_PROCESS_1 <---> CLIENT_PROCESS_3
without -k, ncat will behave same as nc.
Benefits or loses can be defined on how they are to be needed.
For this example, i used nc or nc.traditional (v1.10-41.1+b1), and ncat (7.80).
This is an incomplete answer, because I haven't got it working. Arguably more of a question, in fact. Maybe someone else can finish it off.
First of all, it seems there are different versions of netcat. I'm on Ubuntu, so I've probably got the version that came with Ubuntu. When I nc -h, it says this:
OpenBSD netcat (Debian patchlevel 1.187-1ubuntu0.1)
When I run man nc, it says this:
-F Pass the first connected socket using sendmsg(2) to stdout and exit. This
is useful in conjunction with -X to have nc perform connection setup with
a proxy but then leave the rest of the connection to another program (e.g.
ssh(1) using the ssh_config(5) ProxyUseFdpass option).
It seems to me that this means that, instead of doing the usual thing with stdin and stdout, it just prints something to stdout. That something could then be used by another process to do the actual connection to the client.
Unfortunately, -F has no effect that I can see. So maybe I'm doing it wrong. Or maybe there's some secret pipe somewhere that I have to listen to, or a supplementary argument they forgot to document. Or maybe I happen to have a broken build of netcat, and it works for everyone else who's on Ubuntu.
In combination with the -k option (or, failing that, a while-true loop), this would allow many different clients to have separate connections. Suppose you have an executable called handle_connection, which takes as arguments an in file descriptor from a client and an out file descriptor to the client, and spawns a subprocess which communicates with the client. Then the server script might look like this:
nc -lkF $host $port | while read in out ; do
handle_connection $in $out ;
done
ncat can do it, but the correct command with ncat is:
ncat --keep-open --listen -p 12345
This will accept multiple connections at the same time.
You can then send the data with multiple clients. e.g. open in two or more terminals, and try typing there:
nc localhost 12345

How to find a free TCP port

How do I find a completely free TCP port on a server? I have tried the command line;
netstat -an
but I am told the ones with a status of LISTENING are already being used.
I also tried a tool called TCPView but again it only showed which TCP ports were being used. I know how to telnet to a port to check its open but I need to find one that is free.
netstat -lntu
This will solve your purpose.
Inspired by https://gist.github.com/lusentis/8453523
Start with a seed port, and increment it till it is usable
BASE_PORT=16998
INCREMENT=1
port=$BASE_PORT
isfree=$(netstat -taln | grep $port)
while [[ -n "$isfree" ]]; do
port=$[port+INCREMENT]
isfree=$(netstat -taln | grep $port)
done
echo "Usable Port: $port"
In Bash you can write simple for loop to check which TCP ports are free, e.g.
$ for i in {1..1024}; do (exec 2>&-; echo > /dev/tcp/localhost/$i && echo $i is open); done
22 is open
25 is open
111 is open
587 is open
631 is open
841 is open
847 is open
1017 is open
1021 is open
For more info, check: Advanced Bash-Scripting Guide: Chapter 29. /dev and /proc

Large amount of http connections from self

I have a relatively high traffic linux/apache webserver running Wordpress (oh the headaches). I think our developer configured the memcache settings incorrectly because when I run this command to look at all incoming httpd connections.
sudo netstat -anp |grep 'tcp\|udp' | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -n
I get:
1 68.106.x.x
1 74.125.x.x
1 74.125.x.x
1 74.125.x.x
1 74.125.x.x
15 0.0.0.0
70 173.0.x.x
194 127.0.0.1
...I see that I have 194 connections from 127.0.0.1, and VERY few from actual public IP's. looking at netstat further I can see those are going to port 11211 (memcache). Even if I restart httpd, it only takes a few seconds for the open memcached connections from 127.0.0.1 to skyrocket up again and almost immediately we are pushing our max httpd process limit (currently MaxClients = 105).
Here are the details for those connections:
tcp 0 0 127.0.0.1:26210 127.0.0.1:11211 ESTABLISHED -
cat /etc/sysconfig/memcached
PORT="11211"
USER="memcached"
MAXCONN="1024"
CACHESIZE="64"
OPTIONS=""

NTPD on arm box version 4.2.6p5

i have managed to cross compile ntpd 4.2.6p5 for my arm box. I have a custom toolchain provided by the manufacturer.
Box is running busybox + some variant of debian linux.
So I have no installation of ntp and did a manual copy, created a conf file for the ntpd and tried to run it.
ntpd always returns this when in debug mode:
~/ntp # ./ntpd -c ntp.conf -d
ntpd 4.2.6p5#1.2349 Mon Apr 7 19:58:25 UTC 2014 (1)
9 Apr 07:39:44 ntpd[3592]: signal_no_reset: signal 13 had flags 4000000
9 Apr 07:39:44 ntpd[3592]: proto: precision = 91.000 usec event at 0 0.0.0.0 c01d 0d
kern kernel time sync enabled
Finished Parsing!!
9 Apr 07:39:44 ntpd[3592]: ntp_io: estimated max descriptors: 1024, initial socket
boundary: 16
9 Apr 07:39:44 ntpd[3592]: Listen and drop on 0 v4wildcard 0.0.0.0 UDP 123
9 Apr 07:39:44 ntpd[3592]: unable to bind to wildcard address :: - another process
may be running - EXITING
before that I had to add into /etc/services also
ntp 123/udp
my ntp.conf looks like:
~/ntp # cat ntp.conf
server 193.2.4.6
server 193.2.4.2
driftfile ntp.drift
So I have checked netstat and nothing is running on port 123, no ntpdate etc...
~/ntp # netstat -rn
Kernel IP routing table
Destination Gateway Genmask Flags MSS Window irtt Iface
0.0.0.0 192.168.3.1 0.0.0.0 UG 0 0 0 eth0
192.168.3.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
~ # netstat -a | grep 123
~ #
Therefore it must be something with the config, or this arm box does not have something configured...
Oh and running manually ntpdate works:
~/ntp # ./ntpdate 193.2.4.6
9 Apr 07:49:16 ntpdate[3614]: step time server 193.2.4.6 offset -0.755704 sec
~/ntp #
So yes i could use ntpdate in cron, but this is not my intent!
Any idea?
Thank you and best regards!
The following error indicates that ntp had trouble binding to the ipv6 wildcard:
9 Apr 07:39:44 ntpd[3592]: unable to bind to wildcard address :: - another process
may be running - EXITING
I think your problem is ipv6 but it is hard to tell because your diagnosticinformation was not very good. Your netstat -a |grep 123 command is useless because netstat would substitute ntp for port 123. Try it again with:
netstat -a -n | grep 123
Along those lines netstat -rn only works with ipv4, try it again with -6:
netstat -r -n -6
Your test ntpdate used an ipv4 host. Does your server support ipv6? What happens when you run:
$ sntp -d -6 time.nist.gov
I used sntp because I do not know if ntpdate has a -6option and sntp does.

Resources