4

I'm trying to write a tcp stream 'tunnel' (similar to the ones SSH handles by default) but with one exception, I have to rewrite certain information as it flows through.

I'm certain there's something similar out there but I have not been able to find it. I have three main questions:

  • Is there an easy way to save a tcp stream for observation? (ie using netcat, or a ssh -r/-l/-D, or using some other utility alltogether)
  • how hard is it to rewrite the stream on the fly?

Edit: The information being rewritten would be just the initial authentication.

Achille
  • 446
  • 3
  • 8
  • Why would you want to rewrite certain information? and what kind of information are you talking about exactly... – t0mm13b Jan 30 '10 at 01:23
  • The difficulty of rewriting depends on *what* you're rewriting. Packet headers? Easy. Application layer data? Not so much. – pestilence669 Jan 30 '10 at 02:23
  • Another option is cobbling together something in Go. Its standard library is well suited for low-level stream manipulation, so I think it's the best choice. You could throw something together in less than 100 lines. – 1110101001 Jan 09 '23 at 01:37

4 Answers4

11

A straight pass-through tunnel with logging can be cobbled together from existing (or easily found) utilities.

socat -v -x tcp-l:8080,fork,reuseaddr tcp:localhost:80 2>log

In this example, connecting to http://localhost:8080/ will pass through to http://localhost:80/, and log data transferred to log.

The tool TCPreen is specialized for this exact purpose.

If you have root privileges, there are many analyzers such as tcpdump and tcpflow which can capture packets directly from the network, without having to redirect traffic.

socat can also do some very basic stream modification with the ,cr and ,crnl options, which strip/add/replace \r characters.

In any case, back to the original question… It's been ages since I've written any Java, and this is totally untested, but a tunnel that can modify traffic before retransmitting isn't difficult.

public class ForwardAndChangeCaseThread extends Thread {
    private Socket in, out;
    public ForwardAndChangeCaseThread(Socket in, Socket out) {
        this.in = in; this.out = out;
    }
    public void run() {
        byte[] buf = new byte[4096];
        InputStream in = this.in.getInputStream();
        OutputStream out = this.out.getOutputStream();
        int count;
        while ((count = in.read(buf)) > 0) {
            for (int i = 0; i < count; i++)
                if (buf[i] >= 0x40) buf[i] ^= 0x20;
            out.write(buf, 0, count);
        }
    }
}
public class TcpForwarder {
    public static void main(String[] args) {
        ServerSocket listen = new ServerSocket(8080, 1);
        for (;;) {
            Socket local = listen.accept();
            Socket remote = new Socket("localhost", 80);
            new ForwardAndChangeCaseThread(local, remote).start();
            new ForwardAndChangeCaseThread(remote, local).start();
        }
    }
}
ephemient
  • 198,619
  • 38
  • 280
  • 391
  • 1
    Oh wow Thanks. I'm always impressed by the level of quality of answers here. – Achille Jan 30 '10 at 04:03
  • 1
    More versatile than the venerable "network swiss army knife" netcat: socat has replaced most of my usages of netcat, telnet, proxytunnel, rlwrap, and many other little utilities. I'm glad to share excellent tools :-) – ephemient Jan 30 '10 at 06:08
  • Couldn't you do stream rewriting via 2 socat? One that takes the input and writes it to a unix domain socket. Then you have a program in your favorite language that reads from that, munges it, and writes to another socket. Then a final socat to forward the contents to the destination. – 1110101001 Jan 07 '23 at 23:34
2

Pretty sure Ettercap supports rewriting of TCP streams.

tcpdump can write out packet captures, which you could then later analyze using Wireshark

If you want to do it programmatically, you could inspect their respective sources to get ideas of where to start.

Steven Schlansker
  • 37,580
  • 14
  • 81
  • 100
1

Not to toot my own horn, but I wrote some code to do exactly this in a framework I wrote a long time ago for asynchronous IO. There are a lot of things about the code that are kind of dated now, but it does work. Here's a link to the web page on it:

The thing I wrote that does the tunnel thing you want is called PortForward, and there's also something there that will dump out a TCP stream, but I forgot what I called it. They can be easily combined because of how the framework works.

I'll come back if you want help using it to accomplish that goal. As others have pointed out, it is impossible to re-write an SSL stream on the fly. So if your connection is using encryption and/or MACs (one way this would be true is if it were SSL) you're out of luck.

Matthieu
  • 2,736
  • 4
  • 57
  • 87
Omnifarious
  • 54,333
  • 19
  • 131
  • 194
0

I'm not sure if this is what you are asking, but ...

You cannot rewrite an SSL stream on the fly unless you have the private key for the server's SSL cert ... or you can intercept it at some point (in the client or server address space) where it is not SSL protected. If you could, SSL would be a waste of time.

Similarly, if you capture the entire contents of an SSL stream (in both directions), it will do you no good, unless you have the relevant private keys.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • 1
    You can do this, if you also control the client - because you can tell the client to accept *your* certificate. – caf Jan 30 '10 at 04:36
  • Ah yes ... but what about the fact that the stream is encrypted? Don't you need the server's private key to figure out what session key the client is using to encrypt the stuff it sends? – Stephen C Jan 30 '10 at 04:54
  • Imagine `socat ssl-l:4443 ssl:host:443`; or equivalently, a `stunnel` daemon wrapping a `stunnel` client; or equivalently, an `openssl s_server` joined to an `openssl s_client`. This is two completely independent SSL streams, one from client to proxy and one from proxy to server. – ephemient Jan 30 '10 at 05:09