2

I was reading about torchat which is essentially an anonymous chat program.

It sounded cool so i wanted to experiment with making my own. First i wrote a test to grab a webpage using Http. Sicne .NET doesnt support SOCKS4A/SOCKS5 i used privoxy and my app worked. Then i switch to a TCP echo test and privoxy doesnt support TCP so i searched and installed 6+ proxy apps (freecap, socat, freeproxy, delegate are the ones i can remember from the top of my head, i also played with putty bc i know it supports tunnels and SOCK5) but i couldnt successfully get any of them to work let alone get it running with my http test that privoxy easily and painlessly did.

What may i use to get TCP connections going through TOR? I spent more then 2 hours without success. I don't know if i am looking for a relay, tunnel, forwarder, proxy or a proxychain which all came up in my search. I use the config below for .NET. I need TCP working but i am first testing with http since i know i had it working using privoxy. What apps and configs do i use to get TCP going through tor?

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.net>
    <defaultProxy enabled="true">
      <proxy bypassonlocal="True" proxyaddress="http://127.0.0.1:8118"/>
    </defaultProxy>
    <settings>
      <httpWebRequest useUnsafeHeaderParsing="true"/>
    </settings>
  </system.net>
</configuration>

-edit- Thanks to Bernd i have a solution. Here is the code i ended up writing. It isn't amazing but its fair.

static NetworkStream ConnectSocksProxy(string proxyDomain, short proxyPort, string host, short hostPort, TcpClient tc)
{
    tc.Connect(proxyDomain, proxyPort);
    if (System.Text.RegularExpressions.Regex.IsMatch(host, @"[\:/\\]"))
        throw new Exception("Invalid Host name. Use FQDN such as www.google.com. Do not have http, a port or / in it");
    NetworkStream ns = tc.GetStream();
    var HostNameBuf = new ASCIIEncoding().GetBytes(host);
    var HostPortBuf = BitConverter.GetBytes(IPAddress.HostToNetworkOrder(hostPort));
    if (true) //5
    {
        var bufout = new byte[128];
        var buflen = 0;
        ns.Write(new byte[] { 5, 1, 0 }, 0, 3);
        buflen = ns.Read(bufout, 0, bufout.Length);
        if (buflen != 2 || bufout[0] != 5 || bufout[1] != 0)
            throw new Exception();

        var buf = new byte[] { 5, 1, 0, 3, (byte)HostNameBuf.Length };
        var mem = new MemoryStream();
        mem.Write(buf, 0, buf.Length);
        mem.Write(HostNameBuf, 0, HostNameBuf.Length);
        mem.Write(new byte[] { HostPortBuf[0], HostPortBuf[1] }, 0, 2);
        var memarr = mem.ToArray();
        ns.Write(memarr, 0, memarr.Length);
        buflen = ns.Read(bufout, 0, bufout.Length);
        if (bufout[0] != 5 || bufout[1] != 0)
            throw new Exception();
    }
    else //4a
    {
        var bufout = new byte[128];
        var buflen = 0;
        var mem = new MemoryStream();
        mem.WriteByte(4);
        mem.WriteByte(1);
        mem.Write(HostPortBuf, 0, 2);
        mem.Write(BitConverter.GetBytes(IPAddress.HostToNetworkOrder(1)), 0, 4);
        mem.WriteByte(0);
        mem.Write(HostNameBuf, 0, HostNameBuf.Length);
        mem.WriteByte(0);
        var memarr = mem.ToArray();
        ns.Write(memarr, 0, memarr.Length);
        buflen = ns.Read(bufout, 0, bufout.Length);
        if (buflen != 8 || bufout[0] != 0 || bufout[1] != 90)
            throw new Exception();
    }
    return ns;
}

Usage

using (TcpClient client = new TcpClient())
using (var ns = ConnectSocksProxy("127.0.0.1", 9050, "website.com", 80, client)) {...}
1

1 Answer 1

1

Socks4a is really simple. You can do socks4a by hand in 5 lines of code. Have a look at the socks RFC (or its much simpler explanation on wikipedia).

Essentially you simply make a normal TCP connection to the socks proxy (this means in case of tor you simply connect to 127.0.0.1 port 9050, the connection will be accepted, then you send a very simple request on this connection (example is given in the RFC) and then after some time tor will answer with exactly 8 bytes (the second byte is the status and should be 90 meaning success). Thats all.

After receiving the successful answer from Tor on this connection you continue to use the same connection, at this moment you are already connected with the other side over this socket, from this moment on it behaves like any other TCP connection for all intents and purposes and you can start sending/receiving as if you had connected directly.

Edit: You don't need to study the entire RFC, there is an excellent very short and complete description of Socks 4a in wikipedia (socks 5 would be overkill for your needs and socks 4 cannot resolve hostnames, so 4a is ideal for Tor):

Here it is http://en.wikipedia.org/wiki/SOCKS#SOCKS4a

5
  • That sounds easy, very easy. However no success. First i tried socks5 which i got a success response. It was a http header saying 501 and the html body saying it isn't a http proxy.
    – user274
    Jul 10, 2012 at 17:16
  • Then i tried SOCK4A but i have no idea what the response is suppose to be bc i dont know what RFC or see any documentation. Anyways i tried sending a get request to google (like in SOCK5 or w/o the socks part) and i just get an exception thrown. Probably a closed socket i didnt check. Here is my code pastebin.com/7mHC3ysp
    – user274
    Jul 10, 2012 at 17:19
  • I seem to forgotten the handshake part. So i gave it 3 bytes saying i want no auth. It returned success. Then i told it my request and i got a general SOCKS server failure with no hint as to what went wrong pastebin.com/rbiDijp8
    – user274
    Jul 10, 2012 at 17:47
  • If it is of any help here is the relevant (and working) code from TorChat2: gist.github.com/3086524 (Its written in Pascal but should be easily translated into C# or any other language [beware: pascal strings are indexed beginning with 1 not 0]) here is documentation: en.wikipedia.org/wiki/SOCKS#SOCKS4a Of all socks variants socks 4 and 4a is the simplest and I recommend it because it will not need multiple packets back and forth for the handshake, 4a has only one request and one response. Structure of request and response are explained in the above wikipedia article.
    – Bernd
    Jul 10, 2012 at 22:15
  • I finally figured it out. Weird thing is i couldnt figure out the 4a part until i got 5 working. I think earlier what messed me was my address had http:// at the beginning.
    – user274
    Jul 11, 2012 at 11:10