shd-tcp-tools
=============

Author:           Heikki Orsila <heikki.orsila@iki.fi>
Project web page: http://zakalwe.fi/~shd/foss/shd-tcp-tools/

Introduction
============

shd-tcp-tools are miscellaneous tools that operate with IPv4 and IPv6
networks with TCP protocol. These tools can be used to TCP port forwarding,
network load balancing, network rate limiting, and running servers behind
firewalls. The tools are called tcppipe, tcppipe-least, tcp-pf, listentwo,
and connecttwo.

Environment variables
=====================

If environment variable INADDR_DEFAULT is set, each tool will bind incoming
and outgoing sockets to that address.

tcppipe usage
=============

 tcppipe [-b file] [-i secs] [--insert file] [-l rate] [-n file] [-p] [-w x] SOURCE DESTINATION

tcppipe creates one-directional pipe using TCP. There are two operating modes.
The tool moves data from one source to one destination. Both source and
destination can be selected from following alternatives:

 '-'         means stdin for SOURCE and stdout for DESTINATION
 'host port' means network host and its port. The host can be just '.' and
             in that case host is selected from a host file given with -n.
 ':port'     means listening socket on a port


Both SOURCE and DESTINATION may not be sockets.

Thus this tool can be used in a similar way as netcat, but only
one-directional traffic is possible.

OPTIONS:

 -b/--bind-file file    Select local socket address (interface) from a bind
                        host file. The interface with least amount of
                        transfered bytes is selected.
 -h                     Print help
 --insert file          Insert prefix data to the destination connection
 -l/--limit rate        Limit network throughput to a maximum number of bytes
                        per second.
 -i secs                Set host file update interval in seconds. Default 512s.
 -n/--network-file file Select network host from a network host file. The host
                        with least amount of transfered bytes is selected.
 -p                     Print network throughput
 -v/--version           Print version information.
 -w x                   Wait x seconds before connecting incoming connection
                        to the destination address. This could be used to
                        slow port scanners.

The host file has the following format:

ip_1 byte_number_1
ip_2 byte_number_2

The byte amounts are handled with 64 bits internally so they won't overflow.

Example 1: If the host file (~/.stt/default) contains:

10.0.0.1 1024
10.0.0.2 512

then
	tar cv *files* |tcppipe -b ~/.stt/default - targethost targetport

sends a tar stream to the targethost:targetport. The local interfaced used
is the interface with least amount of recorded transfers, which is
10.0.0.2 in this example.

Example 2: Listens to tcp port 1234 (:1234), accepts any incoming connection,
limits the network throughput to 100 KiB/s (-l), prints the network throughput
(-p), and untars the incoming stream.

	tcppipe -p -l 102400 :1234 - |tar xv

Example 3: Bind to port 2345 on an interface with least amount of transfers.
And direct incoming TCP connection to stdout.

	tcppipe -b file :2345 -

Example 5: Send some files to the host with least amount of transfers and
limit rate to 100 KiB/s.

       tar cv *FILES* |tcppipe -n hostfile -l 102400 - . port


tcppipe-least usage
===================

tcppipe-least is a tool to manipulate and read host files (that contain byte
amounts for hosts). It is useful for shell scripting. Read the command line
help for more info:

   tcppipe-least -h

tcp-pf usage
============

 tcp-pf -s port1 [-d host:port2] [-l multiplexfile -p port2] [--lazy]
        [-a allowed_host] [-r rate] [--insert file]

tcp-pf creates a full-duplex relay pipe between two hosts. First it waits for
an incoming connection to port1, and then connects to host2:port2.
Finally it sets up a full duplex tcp pipe between the two hosts.

Alternatively a target host is read from a host file which lists many
potential target hosts. The host with least amount of bytes
in history is selected. This can be used for network load balancing when
a same service is running on every host in the host file.
The format of the host file is the same as with tcppipe tool. Here is an
example:

# file starts
host1.mydomain.com 1000000000
host2.mydomain.com 0

The byte amounts are handled internally with 64 bit counters so they won't
overflow.

In this example, host2.mydomain.com would be chosen as the target, because it
has the least amount of bytes (zero) in recorded history.

Environment variable INADDR_DEFAULT can be used to bind listening port
to any local interface. For example:

   export INADDR_DEFAULT="host3.mydomain.com"
   tcp-pf -s 1234 -d foo.org:2345

tcp-pf binds itself to host3.mydomain.com:1234.

 -a switch can be used to add 'allowed hosts' that are allowed to connect
    to the listening socket. For example:

 tcp-pf -s 1234 -a myfriend.org -d goes.here.org:2345

 -r switch may be used to limit the maximum number of bytes per second going
    through each connection.

 --lazy can be used to simulate lazy connection killing like
        in netcat. Normally connections to both ends are killed when either
        source disconnects from tcp-pf. With --lazy tcp-pf doesn't close the
        remaining connection before a broken pipe condition is noticed on new
        data.

 --insert file is used in the same way as in tcppipe tool. To prefix a
               destination data connection with constant data.

tcp-pf prints the data bandwidth in both directions according to
IEC 60027-2 (2000-11) Ed. 2.0 symbols. KiB == 2^10 bytes, MiB == 2^20 bytes,
GiB == 2^30 bytes, TiB == 2^40 bytes.


listentwo/connecttwo usage
==========================

listentwo and connecttwo tools can be used to run servers behind firewalled
networks by using a third party non-firewalled host.

Assume:
	- machine A is firewalled so that it can't accept incoming connections
	  to port 22 (ssh).
	- machine B is not firewalled.
	- machine C wants to connect to ssh port of machine A.

Host name of machine B is machine_b.

Do this:

First on machine B:
      listentwo -s 1234 -d 1235 --hello-dst

Then on machine A:
     connecttwo -s machine_b:1235 -d 127.0.0.1:22 --hello-from-src

Then C can use ssh:
     ssh -p 1234 user@machine_b


What happens when C uses ssh is:

     B accepts the connection on port 1234 from machine C (process listentwo).
     Meanwhile listentwo has got a connection to port 1235 from machine A
     or not. If not then it waits for connection to port 1235 from machine A.

     When there is a connection on port 1235, the ip/port of machine C is
     informed to the client connecting from machine A.

     When machine A has received the ip/port of machine C from machine B,
     it connects to localhost:22 discarding the ip/port information it got.

     Then the data starts to flow.

     There is no particular reason why machine A should know the ip of
     machine C connecting to B. Without --hello-* that information is
     not relayed to machine A.
