3

I am trying to develop a socks tunneling application in c# that is able to open a website by using add and modified header requests (something similar to Modify Header Firefox Addon) and tunnel the data through a proxy (socks preferable). Please can anyone specify any resources I might need for this? Or any alternative that can perform the same function, open source that I can build on maybe, etc. Thanks!

ps: the applications should also be able to open https and other common network protocols

Chibueze Opata
  • 9,856
  • 7
  • 42
  • 65

1 Answers1

2

One way is to use HttpSys and create a local proxy server to handle request on the loopback 127.0.0.1 address. You would be change the system proxy to this address/port and sit between client and server.

This would allow you to modify request/response packets & headers. There's an example here of this approach in C#, and I've amended this below to show how it would work.

public class MyProxy
{
    private readonly HttpListener listener;

    public MyProxy()
    {
        listener = new HttpListener();
    }

    public void Start()
    {
        listener.Prefixes.Add("http://*:8888/");
        listener.Prefixes.Add("https://*:8889/");
        listener.Start();
        Console.WriteLine("Proxy started, hit enter to stop");
        listener.BeginGetContext(GetContextCallback, null);
        Console.ReadLine();
        listener.Stop();
    }

    public void GetContextCallback(IAsyncResult result)
    {
        var context = listener.EndGetContext(result);
        listener.BeginGetContext(GetContextCallback, null);

        var request = context.Request;
        var response = context.Response;
        var url = request.Url;

        UriBuilder builder = new UriBuilder(url);
        builder.Port = url.Port == 8888 ? 80 : 443;
        url = builder.Uri;

        WebRequest webRequest = WebRequest.Create(url);

        webRequest.Proxy = GlobalProxySelection.GetEmptyWebProxy();
        WebResponse webResponse = webRequest.GetResponse();
        using (Stream reader = webResponse.GetResponseStream())
        {
            using (Stream writer = response.OutputStream)
            {
                reader.CopyTo(writer);
            }
        }
    }
}

The downside to this approach is it's quite low level, and affects all traffic on the user machine which may not be desirable. You would have to handle SSL requests, and it would also impact any existing configured proxies.

Another alternative approach is to use the Microsoft Internet Controls COM component and to extend the WebBrowser class. There's a SO question here that shows the approach. Unfortunately the version of WebBrowser in the .NET namespace does not implement the request response objects. The interesting bits are below.

public class ExtendedWebBrowser : WebBrowser
{
    ...

    void BeforeNavigate(object pDisp, ref object url, ref object flags,
                       ref object targetFrameName, ref object postData, 
                       ref object headers, ref bool cancel)
    {
         if (!headers.Contains("X-RequestFlag")
         {
             headers += "X-RequestFlag: true\r\n";

             // append custom header here

             // cancel current request
             cancel = true;

             // re-request with amended details
             Navigate((string)url, (string)targetFrameName, (byte[])postData, 
                      (string)headers);
         }
         else
         {
             base.BeforeNavigate(...);
         }
    }
}
Community
  • 1
  • 1
TheCodeKing
  • 19,064
  • 3
  • 47
  • 70
  • Thanks so much for your well written answer. I actually want the application to affect all traffic but I don't know anyway of trying out ssl requests and returning it through the same proxy. I was expecting some code resource close to that. – Chibueze Opata Sep 04 '11 at 10:34
  • You would need to use your own (self-signed?) cert installed as a trusted CA. This allows the client to make SSL requests to your proxy and which you can then decrypt as you know the private key. You then send on the request to the real address over SSL as usual using .NET WebRequest APIs. – TheCodeKing Sep 04 '11 at 10:43
  • I've looked on the Internet for an example without being able to see one. Could you help me with one? Thanks – Chibueze Opata Sep 04 '11 at 19:57
  • Which bit do you need help with? Might be worth a new question? – TheCodeKing Sep 04 '11 at 19:59
  • Thanks. I know how to create self-signed certificates, but I don't know anything about how to send the request to real address over SSL. And your answer is okay, just want to want to see if I will get any more. Thanks – Chibueze Opata Sep 05 '11 at 23:20
  • 1
    There's an example [here](http://stackoverflow.com/questions/6356070/c-sslstream-and-local-proxy) showing how to bind to SSL and read content using `SslStream` - this is so you can have a local SSL proxy. By the time you request the real content (use the Url in the context request) you just need to use `WebRequest/WebResponse` objects as normal, SSL happens behind the scenes. Any probs maybe start a new question. Hope that helps. – TheCodeKing Sep 06 '11 at 20:18
  • 1
    Actually sorry you need to map the ports before making the actual request using `WebRequest`. e.g. proxy 8888 is port 80, 8889 is 443. You also need to ensure you set `webRequest.Proxy=GlobalProxySelection.GetEmptyWebProxy();` – TheCodeKing Sep 06 '11 at 20:38