Netcat – a couple of useful examples

One of the Linux command line tools I had initially under-estimated is netcat or just nc. By default, netcat creates a TCP socket either in listening mode (server socket) or a socket that is used in order to connect to a server (client mode). Actually, netcat does not care whether the socket is meant to be a server or a client. All it does is to take the data from stdin and transfer it to the other end across the network.

The simplest example of its usage is to create a server-client chat system. Although this is a very primitive way to chat, it shows how netcat works. In the following examples it is assumed that the machine that creates the listening socket (server) has the 192.168.0.1 IP address. So, create the chat server on this machine and set it to listen to 3333 TCP port:

$ nc -l 3333

On the other end, connect to the server with the following:

$ nc 192.168.0.1 3333

In this case, the keyboard acts as the stdin. Anything you type in the server machine’s terminal is transfered to the client machine and vice-versa.

Transfering Files

In the very same way it can be used to transfer files between two computers. You can create a server that serves the file with the following:

$ cat backup.iso | nc -l 3333

Receive backup.iso on the client machine with the following:

$ nc 192.168.0.1 3333 > backup.iso

As you may have noticed, netcat does not show any info about the progress of the data transfer. This is inconvenient when dealing with large files. In such cases, a pipe-monitoring utility like pv can be used to show a progress indicator. For example, the following shows the total amount of data that has been transfered in real-time on the server side:

$ cat backup.iso | pv -b | nc -l 3333

Of course, the same can be implemented on the client side by piping netcat’s output through pv:

$ nc 192.168.0.1 3333 | pv -b > backup.iso

Other Examples

Netcat is extremely useful for creating a partition image and sending it to a remote machine on-the-fly:

$ dd if=/dev/hdb5 | gzip -9 | nc -l 3333

On the remote machine, connect to the server and receive the partition image with the following command:

$ nc 192.168.0.1 3333 | pv -b > myhdb5partition.img.gz

This might not be as classy as the partition backups using partimage, but it is efficient.

Another useful thing is to compress the critical files on the server machine with tar and have them pulled by a remote machine:

$ tar -czf - /etc/ | nc -l 3333

As you can see, there is a dash in the tar options instead of a filename. This is because tar’s output needs to be passed to netcat.

On the remote machine, the backup is pulled in the same way as before:

$ nc 192.168.0.1 3333 | pv -b > mybackup.tar.gz

Security

It is obvious that using netcat in the way described above, the data travels in the clear across the network. This is acceptable in case of a local network, but, in case of transfers across the internet, then it would be a wise choice to do it through an SSH tunnel.

Using an SSH tunnel has two advantages:

  1. The data is transfered inside an encrypted tunnel, so it is well-protected.
  2. You do not need to keep any open ports in the firewall configuration of the machine that will act as the server, as the connections will take place through SSH.

You pipe the file to a listening socket on the server machine in the same way as before. It is assumed that an SSH server runs on this machine too.

$ cat backup.iso | nc -l 3333

On the client machine connect to the listening socket through an SSH tunnel:

$ ssh -f -L 23333:127.0.0.1:3333 me@192.168.0.1 sleep 10; \
        nc 127.0.0.1 23333 | pv -b > backup.iso

This way of creating and using the SSH tunnel has the advantage that the tunnel is automagically closed after file transfer finishes. For more information and explanation about it please read my article about auto-closing SSH tunnels.

Telnet-like Usage

Netcat can be used in order to talk to servers like telnet does. For example, in order to get the definition of the word “server” from the “WordNet” database at the dict.org dictionary server, I’d do:

$ nc dict.org 2628
220 ..............some WELCOME.....
DEFINE wn server
150 1 definitions retrieved
151 "server" wn "WordNet (r) 2.0"
server
     n 1: a person whose occupation is to serve at table (as in a
          restaurant) [syn: {waiter}]
     2: (court games) the player who serves to start a point
     3: (computer science) a computer that provides client stations
        with access to files and printers as shared resources to a
        computer network [syn: {host}]
     4: utensil used in serving food or drink
.
250 ok [d/m/c = 1/0/18; 0.000r 0.000u 0.000s]
QUIT
221 bye [d/m/c = 0/0/0; 16.000r 0.000u 0.000s]

Works as a Port Scanner too

A useful command line flag is -z. When it is used, netcat does not initiate a connection to the server, but just informs about the open port it has found. Also, instead of a single port, it can accept a port-range to scan. For example:

$ nc -z 192.168.0.1 80-90
Connection to 192.168.0.1 80 port [tcp/http] succeeded!

In this example, netcat scanned the 80-90 range of ports and reported that port 80 is open on the remote machine.

The man page contains some more interesting examples, so take the time to read it.

Notes

All the above examples have been performed on Fedora 5/6. Netcat syntax may vary slightly among Linux distributions, so read the man page carefully.

Netcat provides a primitive way to transfer data between two networked computers. I wouldn’t say it’s an absolutely necessary tool in the everyday use, but there are times that this primitive functionality is very useful.

Netcat – a couple of useful examples by George Notaras is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
Copyright © 2006 - Some Rights Reserved

George Notaras avatar

About George Notaras

George Notaras is the editor of the G-Loaded Journal, a technical blog about Free and Open-Source Software. George, among other things, is an enthusiast self-taught GNU/Linux system administrator. He has created this web site to share the IT knowledge and experience he has gained over the years with other people. George primarily uses CentOS and Fedora. He has also developed some open-source software projects in his spare time.

26 responses on “Netcat – a couple of useful examples

  1. anjan bacchu Permalink →

    hi there,

    nice article.

    question : if one already has left the SSH port open, we can as well use scp to get the file. If so, why would we want to use netcat on top of that ?

    BR,
    ~A

    1. Gene Permalink →

      Anjan, this is useful when you’re on host A and can SSH to B and C, but can’t SSH between B and C in either direction. If there are any ports at all between B and C open (checked using nmap), netcat and George’s method is a godsend.

  2. George Notaras Post authorPermalink →

    Exactly. The same functionality can be achieved with other tools and protocols like FTP, SSH, RSync etc. As I have written above, netcat is not a necessary tool in the everyday use, but its primitive functionality could be useful in a particular occasion.

    Using scp is my method of choice in order to transfer files between networked computers. I just wanted to show how to transfer files using netcat through an SSH tunnel. That’s all :)

    Thanks for your comment.

  3. DP Permalink →

    This article is excellent.

    When I tried to listen, I faced some problem. Because in my system, command syntax is different. I have to use netcat -l -p 3333 in my system.

  4. George Notaras Post authorPermalink →

    Thanks for providing an example. CLI option syntax may vary from distribution to distribution. It seems that this syntax difference when setting the listening port is one of the major differences.

  5. anonymous Permalink →

    Here is a fine tutorial on using netcat to pipe audio over a lan.

  6. Traveller Permalink →

    One handy use of netcat I didn’t see mentioned is a fast way to get an bit-for-bit image copy of a working machine’s root partition onto another machine.

    Boot source and destination off live CD’s, make sure source and destination partitions are similar in size with cfdisk and then pipe directly from the source machine’s partition to the destination machine’s partition via netcat. When copy is complete mount the destination partition and tweak IP address, hostname and /etc/iftab. Reboot. You should now have a duplicate working machine.

    Booting off the live CD’s insures that there are no open files in source and destination partition and provides tools for adjusting partition sizes etc. In addition since the partition contents are copied directly no intermediate storage is required.

  7. George Notaras Post authorPermalink →

    Thanks. There are indeed many ways to use netcat effectively. Very interesting.

  8. Cucirca Permalink →

    Thanks for this useful commands ;)

  9. Gary Permalink →

    The main drawback of netcat is that it needs to be started on both sides of the wire to make a transfer work. What I usually do is this:

    tar cz /etc | ssh user@host -c ‘cd /bak ; cat > etc.tgz’

    On the localhost, this will create an archive of /etc, which is piped into an ssh connection. On the remote host, the snippet enclosed in ” is executed: Change to the backup directory, and pipe the content of the connection into a file. If I wanted to extract the files again on the receiving side, I could do:

    tar cz /etc | ssh user@host -c ‘cd /bak ; cat tar xz’

    Note that the ‘-f -‘ given in the article is redundant. If tar is not given a file, it uses STDIN/OUT. The advantage over recursive scp is that this method preserves device nodes and file permissions. The advantage over rsync is that it is using familiar tar semantics on both sides (of course, if you want diffing, you need rsync, which works just fine over SSH).

    Of course, the other direction (pulling files from a host) is equally possible:

    ssh user@host -c ‘tar cz /etc’ > /bak/etc.tgz

  10. Robbert Hamburg Permalink →

    Hmm that comment of gary was very usefull to me !

    Thanks !

  11. Greg Sanders Permalink →

    Thanks for taking time to write this up. It saved me a huge amount of time and frustration trying to move a 40G .vdi file from one machine to another. I’ve added your site to my RSS reader list.

  12. EvilTwin Permalink →

    Nice Write up!

    In the first example it will not work as
    nc -l 3333
    needs to be
    nc -l -p3333

    At least my debian system needs it that way!

  13. LessWire Permalink →

    I want to use netcat like your example to send commands to a yamaha amplifier. It works fine with telnet:

    telnet yamaha 50000
    and i get the replies from the amplifier for each command.

    But with netcat it wont work:

    netcat yamaha 50000
    and i don’t receive any replies to my commands, although your example with dict.org works fine.

    What could there be different to telnet?

  14. LessWire Permalink →

    I found it, the difference is:
    My version of telnet seems to send “\r\n” after each line (for Win compatibility), netcat behaves like it should be and sends only “\n” for line termination.

    So the amplifier didn’t execute the command, better to do something like this:

    “echo -e somecommand\r | netcat yamaha 50000”

    1. Sami Permalink →

      nc -C to use CRLF dos style line endings.

  15. Charlie Hendricks Permalink →

    Thanks. Saved me a bunch of time! Hard to remember these little gems.

  16. antiplex Permalink →

    even after all those years, this article provided me a very interesting insight into this versatile tool.
    i just wish i had read the comments right away before spending hours on going crazy why
    $ netcat -l 10088
    would listen on a random port on my debian wheezy system but not on 10088. lesson learned: use -p 10088

    something else i’ve found quite useful especially in conjunction with netcatting data through ssh tunnels is to bind the listening side to 127.0.0.1 / localhost through using e.g.
    $ nc -l -n -p 30000 -s 127.0.0.1

    last but not least, for transferring files, i’d recommend using garys proposed solution and would like to thank everybody who’s contributed in a useful manner to this article so far.

    1. George Notaras Post authorPermalink →

      Hi antiplex. Glad you found this article useful after all these years. Also, thanks for your feedback ;)

    2. Sami Permalink →

      Incorrect nc usage. On debian, gives the error:
      nc: cannot use -s and -l

  17. Jaime Permalink →

    I feel like a boy that have just received a new gift, until now I have been deploying php server scripts when I needed a simple HTTP server, now I get it with:

    nc -l 8000

    Connect my client to that listening port and just type

    HTTP/1.1 200 OK

    In my listening netcat :D

  18. scrabbler Permalink →

    Nice article!

    I have a question for you. I am trying to launch an LDAP query (udp port 389) from Server A (client), which is in a restricted environment but can get to Server B (bastion) via ssh. Server B is able to launch LDAP queries to Server L (ldap), however, I cannot establish an ssh tunnel from Server B to Server L.

    So the question is: is it possible to set up an ssh tunnel from Server A to Server B, encapsulating port 389, and then set up netcat (or something like it) to take the 389 port data coming in through the ssh tunnel and relay it to to Server L, then taking responses from Server L and returning them to Server A through the ssh tunnel?

    Thanks!

    1. George Notaras Post authorPermalink →

      Hello,

      If I understand it correctly, there should be no need to forward port 389 in this case.

      Provided that (1) the LDAP client is installed on Server B (bastion) and that (2) it can be executed via SSH, then you could execute the Server B’s ldap client from Server A (Client) like this:

      [user@serverA]$ ssh user@bastion.server.B.ip nc -z server.L.ip 389
      

      The nc -zv server.L.ip 389 command should indicate that port 389 is open on Server L. Replace the command with the actual ldap query.

      Hope this helps.

  19. Vasilis C Permalink →

    Hi George
    i am using a program that generates tcp data and i can receive them with another program through port 300 locally in the same pc running debian (ex. ip is 4.4.4.4).
    How can i forward the data to another pc at the same 300 port so the processing of the tcp data takes place in the second pc? (ex. ip is 5.5.5.5)
    i understand i might need some ip tables config on both pc’s, can u help? thanks

    1. George Notaras Post authorPermalink →

      Hi Vasilis,

      If I understand it correctly, you should make sure the program that acts as the server binds on the network interface that has the external IP and that port 300 is open on the same box (for example: iptables -I INPUT -p tcp --dport 300 -j ACCEPT. Then run the client from the other system and connect to the external IP and port 300 of the box on which the server runs.

      I’m not sure if netcat is what you need for this. However, netcat could be used in order to implement something that acts like a transparent proxy and also processes the data while it passes through it. In that case I’m sure I’ve seen such examples (please search Google for that).