zoukankan      html  css  js  c++  java
  • Http 代理工具 实战 支持网页与QQ代理

    前言:

    有些公司不让员工上Q或封掉某些网站,这时候,干着急没办法,只能鄱墙。
    如果上网搜代理IP,很少能用,用HTTP-Tunnel Client代理软件,免费的也是经常性的掉线。

    正好手头上有N台服务器,如果直接在上面装个CCProxy,也显的太明显了。
    于是自己写个代理软件放上去,一来包装一下好伪装,二来又有代理功能,看着挺好。

    原理解说:

    1:创建一个Socket进行本地端口监听-》一个死循环while语句

    2:收到消息时,产生一个线程处理->多线程处理并发请求

    3:产生一个新的Socket负责转发和接收

    4:原来的Socket负责把新接收的消息发送回客户端

    代码细说

    说明:本次示例在控制台程序里运行。

     

    一:Program.cs

     

    1:简单函数原型

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Diagnostics;
    using System.Net.Sockets;
    using System.Threading;
    namespace TcpProxy
    {
        
    /// <summary>
        
    /// by 路过秋天
        
    /// http://www.cnblogs.com/cyq1162
        
    /// </summary>
        class Program
        {
          
            
    static void Main(string[] args)
            {
                    Listen(
    808);//起始监听808和CCProxy一样。
             }
            
    static void Write(string msg)//简化消息输出
            {
                Console.WriteLine(msg);
            }

            
    static void Listen(int port)//开始监听
             {
               
            }
            
    static void ReListen(TcpListener listener)//监听失败,需要重新换端口监听
            {
               
            }
        }
    }

    2:开始监听

           static void Listen(int port)//开始监听
            {
                Write(
    "准备监听端口:" + port);
                System.Net.IPAddress ipp 
    = System.Net.IPAddress.Parse("0.0.0.0");//监听本地任意IP
                TcpListener tcplistener = new TcpListener(ipp, port);
                
    //端口复用,xp下可以复用[可抢占IIS80端口],win2003下无效。
                tcplistener.Server.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
                
    try
                {
                    tcplistener.Start();
                }
                
    catch (Exception err)
                {
                    Write(err.Message);
                    Write(
    "该端口已被占用,请更换端口号!!!");
                    ReListen(tcplistener);
    //监听失败,切换端口监听
                }
                
    //下面还有代码,暂时省略

            }

    3:监听失败,切换端口监听

           static void ReListen(TcpListener listener)//监听失败,需要重新换端口监听
            {
                
    if (listener != null)
                {
                    listener.Stop();
                    listener 
    = null;
                }
                Write(
    "请输入监听端口号:");
                
    string newPort = Console.ReadLine();
                
    int port;
                
    if (int.TryParse(newPort, out port))
                {
                    Listen(port);
                }
                
    else
                {
                    ReListen(listener);
                }
            }

    4:开始监听,进入死循环

           static void Listen(int port)//开始监听
            {
              
    //上面代码省略......

                Write(
    "成功监听端口:" + port);
                Socket socket;
                
    while (true)
                {
                  socket 
    = tcplistener.AcceptSocket();//获取传送和接收数据的Scoket实例 
                    Proxy proxy = new Proxy(socket);//Proxy类实例化 
                  Thread thread = new Thread(new ThreadStart(proxy.Run));//创建线程 
                    thread.Start();//启动线程 
                }
            }

    作者:路过秋天

    博客:http://cyq1162.cnblogs.com/

    二:Proxy.cs

     

    Proxy简单函数原型:

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Net;
    using System.Net.Sockets;
    using System.IO;

    namespace TcpProxy
    {
        
    /// <summary>
        
    /// by 路过秋天
        
    /// http://www.cnblogs.com/cyq1162
        
    /// </summary>
        public class Proxy
        {
            Socket clientSocket;
    //接收和返回
            byte[] read = null;//存储来自客户端请求数据包
            byte[] sendBytes = null;//存储中转请求发送的数据
            byte[] recvBytes = null;//存储中转请求返回的数据
            bool isConnect = false;
            
    byte[] qqSendBytes=new byte[4096];//QQ发送缓冲
            byte[] qqRecvBytes = new byte[4096];//QQ接收缓冲
            int sendLength = 0, recvLength = 0;//实际发送和接收长度
            public Proxy(Socket socket)//初始化
            {
                clientSocket 
    = socket;
                recvBytes 
    = new Byte[1024 * 1024];
                clientSocket.ReceiveBufferSize 
    = recvBytes.Length;
                clientSocket.SendBufferSize 
    = recvBytes.Length;
            }
            
            
    public void Run(){}//主运行代码
            
    //从请求头里解析出url和端口号
            private string GetUrl(string clientmessage, ref int port){}
            
    //接收客户端的HTTP请求数据
            private int ReadMessage(byte[] readByte, ref Socket s, ref IPAddress ipAddress, ref string host, ref int port){}
            
    //关闭socket
            private void CloseSocket(Socket socket){}
            
    private void CloseSocket(Socket socket, bool shutdown){}
            
    //QQ代理测试返回
            private byte[] QQokProxyData(){}
            
    //firfox默认会发送一些请求,很烦,所以加过滤
            private bool Filter(string url){ }
            private void Write(string msg)
            {
                System.Console.WriteLine(msg);
            }

        }
    }

    Run主函数

     

    A:分解请求头,获取要请求的IP,端口

               #region 获取客户端请求数据
                Write(
    "-----------------------------请求开始---------------------------");

                read 
    = new byte[clientSocket.Available];
                IPAddress ipAddress 
    = IPAddress.Any;
                
    string host = "";//主机
                 int port = 80;//端口

                 
    int bytes = ReadMessage(read, ref clientSocket, ref ipAddress, ref host, ref port);
                
    if (bytes == 0)
                {
                    Write(
    "读取不到数据!");
                    CloseSocket(clientSocket);
                    
    return;
                }
                
    #endregion

    Run函数分解:ReadMessage函数

    ReadMessage函数
     //接收客户端的HTTP请求数据
            private int ReadMessage(byte[] readByte, ref Socket s, ref IPAddress ipAddress, ref string host, ref int port)
            {
                
    try
                {

                    
    int bytes = s.Receive(readByte, readByte.Length, 0);
                    Write(
    "收到原始请求数据:" + readByte.Length);
                    
    string header = Encoding.ASCII.GetString(readByte);


                    host 
    = GetUrl(header, ref port);
                    
    if (Filter(host))
                    {
                        Write(
    "系统过滤:" + host);
                        
    return 0;
                    }
                    Write(header);
                    ipAddress 
    = Dns.GetHostAddresses(host)[0];
                    
    if (!isConnect)
                    {
                        header 
    = header.Replace("http://" + host, "");
                    }
                    sendBytes 
    = Encoding.ASCII.GetBytes(header);
                    System.Threading.Thread.Sleep(
    50);
                    Write(
    "转发请求数据:" + sendBytes.Length);
                    Write(Encoding.ASCII.GetString(sendBytes));
                    
    return bytes;
                }
                
    catch
                {
                    System.Threading.Thread.Sleep(
    300);
                    
    return 0;
                }
            }

    ReadMessage函数分解:GetUrl

    GetUrl函数
           //从请求头里解析出url和端口号
            private string GetUrl(string clientmessage, ref int port)
            {
                
    if (clientmessage.IndexOf("CONNECT"!= -1)
                {
                    isConnect 
    = true;
                }
                
    int index1 = clientmessage.IndexOf(' ');
                
    int index2 = clientmessage.IndexOf(' ', index1 + 1);
                
    if ((index1 == -1|| (index2 == -1))
                {
                    
    return "";
                }
                
    string part1 = clientmessage.Substring(index1 + 1, index2 - index1).Trim();
                
    string url = string.Empty;
                
    if (!part1.Contains("http://"))
                {
                    
    if (part1.Substring(01== "/")
                    {
                        part1 
    = "127.0.0.1" + part1;
                    }
                    part1 
    = "http://" + part1;
                }
                Uri uri 
    = null;
                
    try
                {
                    uri 
    = new Uri(part1);
                }
                
    catch
                {
                    
    return "";
                }
                url 
    = uri.Host;
                port 
    = uri.Port;
                
    return url;
            }

    ReadMessage函数分解:Filter

    Filter函数
           private bool Filter(string url)
            {
                
    switch (url.ToLower())
                {
                    
    case "fffocus.cn":
                        
    return true;
                }
                
    return false;
            }

    Run函数分解:CloseSocket函数

    CloseSocket函数
            private void CloseSocket(Socket socket)
            {
                CloseSocket(socket, 
    true);
            }
            
    private void CloseSocket(Socket socket, bool shutdown)
            {
                
    if (socket != null)
                {
                    
    if (shutdown)
                    {
                        socket.Shutdown(SocketShutdown.Both);
                    }
                    socket.Close();
                }
            }

    B:创建中转Socket及建立连接

              #region 创建中转Socket及建立连接
                IPEndPoint ipEndpoint 
    = new IPEndPoint(ipAddress, port);
                Socket IPsocket 
    = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                
    try
                {
                    IPsocket.Connect(ipEndpoint); Write(
    "-----Socket 建立连接! IP地址:" + ipAddress + "网址:http://" + host);
                }
                
    catch (Exception err)
                {
                    Write(
    "连接失败 :" + err.Message);
                    Write(
    "退出请求!!!");
                    CloseSocket(IPsocket, 
    false);
                    
    return;
                }  
                
    #endregion

    C:QQ代理测试及网页转发

                if (isConnect)//QQ链接方式
                {
                    
    byte[] qqOkData = QQokProxyData();
                    clientSocket.Send(qqOkData, 
    0, qqOkData.Length, 0);
                }
                
    else//正常网页,直接转发
                {
                    IPsocket.Send(sendBytes, 
    0);
                }

    函数分解:QQokProxyData

            private byte[] QQokProxyData()
            {
                
    string data = "HTTP/1.0 200 Connection established";//返回建立成功";
                return System.Text.Encoding.ASCII.GetBytes(data);
            }

    D:针对QQ需要进行重复来回的发送与接收

    QQ转发处理
              #region QQ发送/接收中转请求
                 
    int length = 0, count = 0;
                
    if (isConnect)
                {

                    System.Threading.Thread.Sleep(400);//关键时延
                    
    //循环发送客户端请求,接收服务器返回
                    DateTime start = DateTime.Now;
                    
    while (true)
                    {
                        
    if (IPsocket.Available == 0 && clientSocket.Available == 0)
                        {
                            
    if (((TimeSpan)(DateTime.Now - start)).TotalMinutes > 15)
                            {
                                
    break;//掉线重拔处理
                            }
                        }
                        
    else
                        {
                            start 
    = DateTime.Now;
                        }
                            
                        
                        
    try
                        {
                            
    while (clientSocket.Available != 0)
                            {
                                sendLength 
    = clientSocket.Receive(qqSendBytes, qqSendBytes.Length, 0);
                                IPsocket.Send(qqSendBytes, sendLength, 
    0);
                                Write(
    "发送字节数: " + sendLength.ToString());
                            }

                            System.Threading.Thread.Sleep(
    500);
                            
    while (IPsocket.Available != 0)
                            {
                                recvLength 
    = IPsocket.Receive(qqRecvBytes, qqRecvBytes.Length, 0);
                                clientSocket.Send(qqRecvBytes, recvLength, 
    0);
                                Write(
    "接收字节数: " + recvLength.ToString());
                            }
                        }
                        
    catch
                        {
                        }
                    }
                }
                
    else
                {
                    
    try
                    {
                        
    do
                        {
                            length 
    = IPsocket.Receive(recvBytes, count, IPsocket.Available, 0);
                            count 
    = count + length;
                            Write(
    "接收转发请求返回的数据中..." + length);
                            System.Threading.Thread.Sleep(
    200);//关键点,请求太快数据接收不全
                        }
                        
    while (IPsocket.Available > 0);
                        clientSocket.Send(recvBytes, 
    0, count, 0);
                    }
                    
    catch(Exception err)
                    {
                        Write(err.Message);
                    }
                }
                
    #endregion

    E:结束请求,关闭客户端Socket

                #region 结束请求,关闭客户端Socket
                Write(
    "接收完成。返回客户端数据..." + count);
                CloseSocket(IPsocket);
                CloseSocket(clientSocket);
                recvBytes 
    = null;
                Write(
    "本次请求完成,已关闭连接...");
                Write(
    "-----------------------------请求结束---------------------------");
                
    #endregion

    结言:

    本QQ代理软件在服务器上运行长达三个多月,使用过程未发现异常退出情况。当然前提就我一个人在用了~哈哈~

    附以前写的几篇文章:

    1:简单实现Http代理工具

    2:简单实现Http代理工具--端口复用与QQ代理

    3:简单实现Http代理工具--完善支持QQ代理

    4:C# 控制台程序 不显示在任务栏 只在进程中显示

    看本篇的时候也请支持一下我的开源框架:CYQ.Data 轻量数据层之路 框架开源系列 索引

    版权声明:本文原创发表于 博客园,作者为 路过秋天 本文欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则视为侵权。
    个人微信公众号
    创业QQ群:617713515
    Donation(扫码支持作者):支付宝:
    Donation(扫码支持作者):微信:
  • 相关阅读:
    20155305《网络对抗》Web安全基础实践
    20155305《网络对抗》Web基础
    20155305《网络对抗》网络欺诈技术防范
    20155305《网络对抗》信息搜集与漏洞扫描
    20155305《网络对抗》MSF基础应用
    20155305《网络对抗》恶意代码分析
    20155305《网络对抗》免杀原理与实践
    20155305《网络对抗》后门原理与实践
    20155305《网络对抗》PC平台逆向破解(二)
    20155305乔磊《网络对抗》逆向及Bof基础
  • 原文地址:https://www.cnblogs.com/cyq1162/p/1832329.html
Copyright © 2011-2022 走看看