C#本地Tcp代理

时间:2013-05-28 21:31:15

标签: c# .net tcp

我正在做一个本地代理,我在我的系统上重定向浏览器(主要是Chrome和Firefox)。 到目前为止,我已经设法让它工作,但我遇到了一些麻烦。

当我浏览(在浏览器中)某些网站(例如css-tricks.com)时,事情会爆发:

日志

GET http://css-tricks.com/ HTTP/1.1
Host: css-tricks.com
Proxy-Connection: keep-alive
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1521.0 Safari/537.36
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8

HTTP/1.1 301 Moved Permanently
Date: Tue, 28 May 2013 21:00:49 GMT
Server: Apache
X-Pingback: http://css-tricks.com/xmlrpc.php
Expires: Wed, 11 Jan 1984 05:00:00 GMT
Cache-Control: no-cache, must-revalidate, max-age=0
Pragma: no-cache
X-Powered-By: W3 Total Cache/0.9.2.10
Location: http://css-tricks.comhttp/css-tricks.com/
X-Powered-By: PleskLin
Vary: User-Agent,Accept-Encoding
Content-Encoding: gzip
Content-Length: 20
Content-Type: text/html; charset=UTF-8

GET http://css-tricks.comhttp/css-tricks.com/ HTTP/1.1
Host: css-tricks.comhttp
Proxy-Connection: keep-alive
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1521.0 Safari/537.36
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8

Exception: No such host is known.

代码

    private void Listen()
    {
        try
        {
            //server is a TcpListener
            var result = server.BeginAcceptTcpClient(Bridge, server);
        }
        catch (SocketException e)
        {
            log("SocketException: {0}", e);
            server.Stop();
        }
    }

    private void Bridge(IAsyncResult result)
    {
        try
        {
            if (stopped) return;
            var client = server.EndAcceptTcpClient(result);
            var t = new Thread(() => this.Connect(client));
            t.Start();
            this.Listen();
        }
        catch (Exception ex)
        {
            log("Error: {0}", ex.Message);
        }
    }

    private void Connect(TcpClient client)
    {
        using (client)
        {
            client.NoDelay = true;
            client.ReceiveBufferSize = Environment.SystemPageSize;

            using (var stream = client.GetStream())
            {
                var buffer = new byte[client.ReceiveBufferSize];

                using (var ms = new MemoryStream())
                {
                    do
                    {
                        var i = stream.Read(buffer, 0, buffer.Length);
                        ms.Write(buffer, 0, i);
                        Thread.Sleep(1);
                    }
                    while (stream.DataAvailable && stream.CanRead);
                    var data = ms.ToArray();
                    if (data.Length > 0 && stream.CanWrite)
                    {
                        Forward(data, stream);
                    }
                }

            }
        }

    }

    private void Forward(byte[] data, Stream stream_browser)
    {
        var text = Encoding.ASCII.GetString(data);
        string[] lines = Regex.Split(text, "\r\n"), items = lines[0].Split(' ');
        string method = items[0], url = items[1];
        var headers = new Dictionary<string, string>();

        log(text);

        if (method == "CONNECT")
        {
            data = Encoding.ASCII.GetBytes("HTTP/1.1 404 NOT FOUND");
            stream_browser.Write(data, 0, data.Length);
            return;
        }

        for (var i = 1; i < lines.Length; i++)
        {
            var index = lines[i].IndexOf(':');
            if (index < 0) continue;
            string header = lines[i].Remove(index), value = lines[i].Substring(index + 1).TrimStart(' ');
            headers.Add(header.ToLower(), value);
        }

        var host = headers["host"];

        //cache is a ConcurrentDictionary I use to minimize DNS calls
        IPAddress ip;
        if (cache.ContainsKey(host))
        {
            cache.TryGetValue(host, out ip);
        }
        else
        {
            var ips = Dns.GetHostAddresses(host);
            if (ips.Length == 0)
            {
                log("Couldn't resolve the IP of {0}", host);
                return;
            }
            ip = ips[0];
            cache.TryAdd(host, ip);

        }

        using (var client = new TcpClient())
        {
            client.Connect(ip, 80);
            client.NoDelay = true;
            client.ReceiveBufferSize = Environment.SystemPageSize;
            using (var stream = client.GetStream())
            {
                stream.Write(data, 0, data.Length);
                var buffer = new byte[client.ReceiveBufferSize];
                using (stream_browser)
                {
                    int len;
                    while ((len = stream.Read(buffer, 0, buffer.Length)) > 0)
                    {
                        stream_browser.Write(buffer, 0, len);
                        log(Encoding.Default.GetString(buffer));
                    }
                }
            }

        }
    }

感谢。

1 个答案:

答案 0 :(得分:0)

当浏览器发出类似于此

的请求时
GET http://css-tricks.com/ HTTP/1.1
Host: css-tricks.com

我让代理将其修改为

GET / HTTP/1.1
Host: css-tricks.com

目前有效。