Reverse ftp using netcat and wget

If you're connected to the Internet by a DSL or cable modem, you have undoubtedly discovered that the world is still stuck in the old business model where the ISP provides the information, and you are the consumer of the information. Instead of a two-way connection, many of them provide a crippled connection with a NATed, unroutable IP address, like 192.168.1.1. A computer with an unroutable IP can make outbound connections easily enough, but incoming connection attempts just disappear into the ether. So one day your job depends on a PowerPoint presentation, and you find that the office secretary has used your only CD containing the file as a Christmas tree decoration. Or your boss has taken your disk by mistake and gone off to Costa Rica to bugger the local children. The only copy is on your home computer. What to do?

This page describes two procedures for connecting to your home computer and copying files. The first is an interactive method using netcat. The second uses wput and wget, which are command-line utilities that send and retrieve files from a Web server or an ftp server non-interactively. Both of these methods also work for getting files from computers behind a firewall. The netcat method requires a port that is not blocked by the firewall. Usually, any port between 1024 and 65535, with a few specific exceptions, is left open. If your work computer isn't running a Web server, you can use 80 or 8080, which are rarely blocked by any firewall.

Building netcat

Download a copy of netcat from http://www.vulnwatch.org/netcat/ or other security site. If you're using Linux, you may need to add the following lines to netcat.c after the line
#include <fcntl.h>              /* O_WRONLY et al */
before netcat will compile.
#include <netinet/in.h>
#include <arpa/nameser.h>
#include <resolv.h>
On the remote home computer, change the cflags line in Makefile to
CFLAGS = -O -DGAPING_SECURITY_HOLE
Do this step on the remote, firewalled version only, not on the version in the office. The GAPING_SECURITY_HOLE argument enables the -e option in netcat that allows you to execute a program when the connection is made. It's called a GAPING_SECURITY_HOLE for a very good reason, but since you can't make connections to your home computer anyway (which is why you need netcat), it hopefully shouldn't be too much of a problem.

Compile netcat to produce the binary nc. In Linux:
make linux
mv nc netcat

Testing netcat

Netcat is unique in that either end of the connection can act as a server or a client. First check to make sure it's possible to make a connection. On the server type:
netcat -vv -l -p 15600
Pick a port between 1024 and 65535, in this case 15600.

On the remote (home) computer, type
netcat -vv whatever.the.server.is.called.com 15600 
This creates a two-way connection. Anything typed on one computer should appear on the other. (Remember to hit Enter after typing if you're used to Windows.) If it works, it means the port isn't blocked. So far so good, although all we have so far is a chat session between you and yourself.

Now we will prepare to send files. On the remote (home) computer, type
netcat -vv whatever.the.server.is.called.com  15600 -e /bin/bash
Everything that is typed on the server end, instead of being printed on the remote home computer's screen, is now given to the shell on your home computer and executed. It is now possible to execute Unix commands such as cat, ls, and mv. The results will appear on the work computer, just as in a telnet session. This is fine for transferring text files; however, binary files are difficult to transfer this way, because they mess up the terminal and may break the connection. Although you can execute any command on your home computer from work, you can't use file transfer commands that use password exchange, such as sftp and ftp, because the password still shows up only on the remote home client. And if you should happen to type "exit", your connection is gone.

Configuring netcat for reverse telnet

Netcat is usually used with input redirection. To transfer file to the server, on the server you would type:
netcat -l -p 15600 > carbon.txt
and on the client you would type
netcat whatever.the.server.is.called.com 15600 < carbon.txt
The file carbon.txt then goes from home to server.

For remote access, it's necessary to set up a connection in advance and leave it connected. (If your ISP disconnects you after 15 minutes of inactivity, you can add the remote command to your crontab. Or, you can configure netcat to use UDP instead of TCP, so that a continuous connection isn't needed). Type the following command and leave it running continuously on the server. It will tie up an xterm, which is what you need in order to send commands.
netcat -vv -l -p 15600 | tee stuff
Before you go to work, start the following on the remote computer that is behind the DSL/firewall:
netcat -vv whatever.the.server.is.called.com 15600 -e /bin/bash
This will make an outbound connection to your server at work. From work, type
uuencode mypresentation.ppt mypresentation.ppt > mypresentation.uu
Uuencode is part of the uulib utilities. (It is getting hard to find it as the Windoze mentality takes root among Linux users. However, old versions of most Linux distributions still have it.)

From the remote (work) terminal, type
cat mypresentation.uu
The uuencoded file from home will be sent both to your screen at work and to the file on your work computer called "stuff". To retrieve it, simply type
uudecode stuff
et voilà, mypresentation.ppt appears as if by magic. Yes, it's a pain. But if you don't like pain, why are you using computers?

Alternatives

The problem with using netcat is that many ISPs break your network connection after a certain period of inactivity. It also ties up an xterm.

A more reliable way to transfer files to and from a computer behind a crippled DSL line is with a command-line Web file utility such as w3c, curl, wget, or wput. You set the utility to connect from the crippled home computer to your Web server at work at regular intervals and download a set of instructions from a list. To retrieve a file from your home computer, you simply put the name of the file in the list. The file will be automatically uploaded or downloaded the next time the utility program connects.

Using wget and wput to communicate with a machine behind a firewall

For convenience we'll call the machine on the crippled DSL line or restrictive firewall "computer B" and the computer with a real network connection "computer A". Computer A must be running an ftp server.

Save the script below in a file named "wftp" and make it executable. Set it to run on computer B as a cron job every 20 minutes or so. Every 20 minutes, computer B will then connect to computer A to determine whether any file transfers are needed. When you need to transfer some files to or from computer B, simply add the word "get" or "put" plus the filenames to a file named "files.txt" in your home directory on computer A. This filename can include wildcards. The next time computer B checks in, it will read the list and upload or download the specified files. A typical files.txt file might look like this:
cd text/presentations
put mypresentation.ppt
get manuscript.pdf
cd ../../images
ls *.jpg
put k*.jpg
Notice that you use "put" if you want the remote computer to send you the file and "get" if you want it to retrieve a file. Change the script if this is confusing.

Here is the script:
#!/bin/bash
username=$LOGNAME
# put your password and the name of computer A here
password=mypassword
server=name_of_computer_A
rm files.txt
/usr/bin/wget ftp://$username:$password@$server/files.txt
cat files.txt | \
while read line
do
    whattodo=`echo $line | cut -d ' ' -f1`
    filename=`echo $line | cut -d ' ' -f2`
    echo 
    echo next command: $whattodo $filename
    echo
    case ${whattodo} in
    get)
        echo getting $filename ...
        /usr/bin/wget ftp://$username:$password@$server/$filename
       ;;
    put)
        echo putting $filename ...
        /usr/local/bin/wput $filename ftp://$username:$password@$server
    ;;
    cd)
        cd  $filename 
        pwd
        ;;
    ls)
        ls -l > results.txt
        /usr/local/bin/wput results.txt ftp://$username:$password@$server
        ;;
    done)
        echo finished
        ;;
    esac
done
echo done > files.txt
/usr/local/bin/wput files.txt ftp://$username:$password@$server
rm files.txt

The last two lines replace the file list, so that the file transfer is not made repeatedly. The script needs a Bourne or Korn shell for $LOGNAME and for the cat/while loop.

It is obvious that this method has a a couple of disadvantages. Your password will appear briefly in the clear in the process table on computer A, and is in the script file. I know of no easy way to avoid this without opening up anonymous file uploading--which creates even worse problems. Also, you will have to wait an average of 10 minutes to get the file, depending on how frequently computer B checks in. However, it works completely in the background and doesn't depend on a continuous network connection.

Of course, the best solution would be for ISPs to provide a fully functional network connection so that these tricks are not necessary. Unfortunately, that appears to be beyond their ability at present. Until companies like Verizon and Comcast learn that there's a market for creating functioning networks, these little utilities can provide some of the necessary functionality.


Back