Network - netcat (nc, ncat)
About
netcat 1) is a net client/server command line tool for TCP or UDP protocol.
It can:
- reads and writes data across network connections
- acts as a client but also as a server
Example
Testing a port
An utility function to control that the service is up by controlling that we can make a tcp connection to the service port
Simple if statement
TOMCAT_PORT=6006
if [[ $(nc -z localhost ${TOMCAT_PORT}) -eq 0 ]]; then
echo "Tomcat is up"
else
echo "Tomcat is shutdown"
fi
While Statement
- while A port may be not open but still locked by a process. See the second statement
while [[ $(nc -z localhost ${TOMCAT_PORT}) -eq 1 ]]; do
echo "Waiting for the tomcat port ${INFA_TOMCAT_PORT} to be closed before starting"
sleep 5 # wait 5 second before check again
done
###############################################################
# It seems that a port may returns 0 even if a process is still bound to a port
###############################################################
while [[ ! $(netstat -t|grep ${TOMCAT_PORT} | wc -l) -eq 0 ]];
do
echo "Waiting for the tomcat port ${INFA_TOMCAT_PORT} to be closed before starting"
sleep 5 # wait 5 second before check again
done
Wait function with timeout
# usage
# wait_for_service service_name port
wait_for_service() {
local SERVICE_NAME=$1
local PORT=$2
SERVICE_WAIT_TIMEOUT_SEC=20
echo "Waiting for $SERVICE_NAME to start..."
local CURRENT_WAIT_TIME=0
while [[ $(echo | nc -w1 localhost $PORT >/dev/null 2>&1 ;echo $?) -ne 0 ]]; do
printf '.'
sleep 1
if [ $((++CURRENT_WAIT_TIME)) -eq $SERVICE_WAIT_TIMEOUT_SEC ]; then
printf "\nError: timed out while waiting for $SERVICE_NAME to start.\n"
exit 1
fi
done
printf '\n'
echo "$SERVICE_NAME has started";
}
Wait for it
For a full functional example, see wait-for-it.sh
Send a HTTP request to a process
After having created a tcp connection, an application:
- send a standard input (on a io level) to the host via the connection (ie a request)
- receive the result as a standard output.
As netcat creates a tcp connection, you can for instance send HTTP get request. Example:
GET / HTTP/1.1
Host: gerardnico.com
we can send it as standard input with echo to a connection created with netcat
For SSL connection, you need to use another utility such as openssl because netcat does not support it. For HTTPS, you may use CURL
echo -e "GET / HTTP/1.1\nHost: gerardnico.com\n" | nc gerardnico.com 80
and you should get a redirection response telling you that you need to go to https://gerardnico.com/
HTTP/1.1 301 Moved Permanently
Date: Mon, 13 Apr 2020 12:26:26 GMT
Transfer-Encoding: chunked
Connection: keep-alive
Cache-Control: max-age=3600
Expires: Mon, 13 Apr 2020 13:26:26 GMT
Location: https://gerardnico.com/
Server: cloudflare
CF-RAY: 58352ceb1ba9bf78-AMS
Send a directory between two computers
- On the source server, pipe the result of a tar (archive) to a connection created witn nc
tar -cz . | nc -l -p $PORT
# l for listen
# p to define the port
- On the remote server, read the connection and untar.
nc -w 10 $REMOTE_HOST $PORT | tar -xz
Syntax
After a connection is established, the standard input is sent to the host, and anything that comes back across the connection is sent to your standard output.
Client
To create a TCP connection:
- Linux
nc host port
- Windows
ncat host port
Server
Netcat can also function as a server, by listening for inbound connections on arbitrary ports
- Linux
nc -l -p port
Why not telnet
- Telnet has the “standard input EOF” problem. ie it will shut everything down and exit after an end-of-file on the standard input.
- Telnet will not transfer arbitrary binary data, because certain characters are interpreted as telnet options
- Telnet also emits some of its diagnostic messages to standard output, where netcat keeps such things separated from its *output*
- Telnet is incapable of listening for inbound connections, or using UDP instead.
Installation
Windows
- install nmap on Windows
Linux
apt-get install -y netcat
# centos, Redhat
yum install nmap