Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

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)) {...}
share|improve this question

closed as off-topic by Michael Hampton Oct 22 '13 at 21:53

This question appears to be off-topic. The users who voted to close gave this specific reason:

  • "Questions must be relevant to professional system administration. Server Fault is a site dedicated to professionals; novice questions are off-topic. Please see the Help Center for more information on topicality. The best advice we can give you is to hire a professional to help you out." – Michael Hampton
If this question can be reworded to fit the rules in the help center, please edit the question.

    
Programming questions should be directed to our sister site Stack Overflow. –  Michael Hampton Oct 22 '13 at 21:54
add comment

1 Answer

up vote 1 down vote accepted

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

share|improve this answer
    
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. –  acidzombie24 Jul 10 '12 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 –  acidzombie24 Jul 10 '12 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 –  acidzombie24 Jul 10 '12 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 '12 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. –  acidzombie24 Jul 11 '12 at 11:10
add comment

Not the answer you're looking for? Browse other questions tagged or ask your own question.