Пример #1
0
        public byte[] ToPackets()
        {
            var bPack = new List <byte>();

            switch (this.Phase)
            {
            case Socks5Phase.spGreeting:
                if (this.Credential == null)
                {
                    //匿名代理
                    bPack.Add(5);
                    bPack.Add(1);
                    bPack.Add(0);
                    this.Phase = Socks5Phase.spConnecting;
                }
                else
                {
                    //匿名或用户名密码代理
                    bPack.Add(5);
                    bPack.Add(2);
                    bPack.Add(0);
                    bPack.Add(2);
                    this.Phase = Socks5Phase.spAuthenticating;
                }
                break;

            case Socks5Phase.spAuthenticating:
                if (this.Credential == null)
                {
                    throw new ProxyAuthException(403, "Socks5 Server request a credential");
                }

                bPack.Add(1);

                bPack.Add(Convert.ToByte(this.Credential.UserName.Length));
                bPack.AddRange(Encoding.ASCII.GetBytes(this.Credential.UserName));

                bPack.Add(Convert.ToByte(this.Credential.Password.Length));
                bPack.AddRange(Encoding.ASCII.GetBytes(this.Credential.Password));
                this.Phase = Socks5Phase.spConnecting;
                break;

            case Socks5Phase.spConnecting:
                bPack.Add(5);
                bPack.Add((byte)this.Command);
                bPack.Add(0);
                bPack.Add((byte)((this.EndPoint is DnsEndPoint) ? 3 : 1));

                Socks4Request.PackIn(bPack, this.EndPoint);
                break;
            }
            return(bPack.ToArray());
        }
Пример #2
0
        public byte[] ToPackets()
        {
            var bPack = new List <byte>();

            bPack.Add(0x00);

            bPack.Add((byte)this.Status);

            Socks4Request.PackIn(bPack, this.RemoteEndPoint, false);

            return(bPack.ToArray());
        }
Пример #3
0
        public void ParsePack(byte[] bPack)
        {
            switch (this.Phase)
            {
            case Socks5Request.Socks5Phase.spGreeting:
                if (bPack[0] != 5)
                {
                    throw new ProxyAuthException(403, "Only Socks5 response are supported");
                }
                if (bPack[1] == 0xFF)
                {
                    throw new ProxyAuthException(0xFF, "Authentication method not supported");
                }

                if (this.Anonymous = bPack[1] == 0)
                {
                    this.Phase = Socks5Request.Socks5Phase.spConnecting;
                }
                else
                {
                    this.Phase = Socks5Request.Socks5Phase.spAuthenticating;
                }
                break;

            case Socks5Request.Socks5Phase.spAuthenticating:
                if (bPack[0] != 1)
                {
                    throw new ProxyAuthException(403, "Only Socks5 response are supported");
                }

                this.Phase = Socks5Request.Socks5Phase.spConnecting;

                this.Status = (ResponseStatus)bPack[1];
                if (this.Status != ResponseStatus.Success)
                {
                    throw new ProxyAuthException((int)this.Status, this.Status.ToDescription());
                }
                break;

            case Socks5Request.Socks5Phase.spConnecting:
                if (bPack[0] != 5)
                {
                    throw new ProxyAuthException(403, "Only Socks5 response are supported");
                }

                int        offset = 4;
                IPEndPoint ipe;
                Socks4Request.PackOut(bPack, ref offset, out ipe);
                this.RemoteEndPoint = ipe;
                break;
            }
        }
Пример #4
0
        public void UdpDirectReceive(HttpContext context, UdpClient proxyClient)
        {
            context.Server.ScriptTimeout = int.MaxValue;
            HttpRequest  Request  = context.Request;
            HttpResponse Response = context.Response;

            Response.AppendHeader(HttpResponseHeader.Connection.ToString(), "close");

            var bPack = new List <byte>();

            while (Response.IsClientConnected)
            {
                try
                {
                    var    remoteIpe = new IPEndPoint(IPAddress.Any, IPEndPoint.MinPort);
                    byte[] data      = proxyClient.Receive(ref remoteIpe);
                    if (!Response.IsClientConnected)
                    {
                        break;
                    }
                    bPack.Clear();
                    Socks4Request.PackIn(bPack, remoteIpe);
                    bPack.AddRange(data);
                    byte[] bData = bPack.ToArray();
                    Response.OutputStream.Write(bData, 0, bData.Length);
                    Response.Flush();
                    App.LogInfo("UdpDirectReceive from {0} {1}bytes.", remoteIpe, data.Length);
                }
                catch (ObjectDisposedException ex)
                {
#if DEBUG
                    App.LogInfo(string.Format("Predictable objectDisposed exception: {0}", ex.StackTrace));
#endif
                }
                catch (IOException ex)
                {
                    TunnelExceptionHandler.Handle(ex, proxyClient.Client, "UdpDirectReceive");
                }
                catch (SocketException ex)
                {
                    if (ex.SocketErrorCode == SocketError.Interrupted)
                    {
#if DEBUG
                        App.LogInfo(string.Format("Predictable interrupted exception: {0}", ex.Message));
#endif
                        return;
                    }
                    TunnelExceptionHandler.Handle(ex, proxyClient.Client, "UdpDirectReceive");
                }
            }
        }
Пример #5
0
        public byte[] ToPackets()
        {
            var bPack = new List <byte>();

            switch (this.Phase)
            {
            case Socks5Request.Socks5Phase.spGreeting:
                if (this.Anonymous)
                {
                    bPack.Add(5);
                    bPack.Add(0);
                    this.Phase = Socks5Request.Socks5Phase.spConnecting;
                }
                else
                {
                    bPack.Add(5);
                    bPack.Add(2);
                    this.Phase = Socks5Request.Socks5Phase.spAuthenticating;
                }
                break;

            case Socks5Request.Socks5Phase.spAuthenticating:
                if (this.Status != ResponseStatus.Success)
                {
                    throw new ProxyAuthException(403, "Authentication failure, connection must be closed");
                }

                bPack.Add(1);
                bPack.Add((byte)this.Status);
                this.Phase = Socks5Request.Socks5Phase.spConnecting;
                break;

            case Socks5Request.Socks5Phase.spConnecting:
                bPack.Add(5);
                bPack.Add(0);
                bPack.Add(0);
                bPack.Add(1);

                Socks4Request.PackIn(bPack, this.RemoteEndPoint);
                break;
            }
            return(bPack.ToArray());
        }
Пример #6
0
        public void ParsePack(byte[] bPack)
        {
            if (bPack[0] != 0x00)
            {
                throw new ProxyAuthException(403, "Only Socks4/4a response are supported");
            }

            var response = this;

            response.Status = (ResponseStatus)bPack[1];

            int        offset = 2;
            IPEndPoint ipe;

            Socks4Request.PackOut(bPack, ref offset, out ipe, false);
            response.RemoteEndPoint = ipe;

            if (response.Status != Socks4Response.ResponseStatus.RequestGranted)
            {
                throw new ProxyAuthException((int)response.Status, response.Status.ToDescription());
            }
        }
Пример #7
0
        private void UdpDirectReceive(object state)
        {
            var controlClient = (TcpClient)state;

            if (!controlClient.Connected)
            {
                return;
            }
            IPEndPoint remoteIpe = null;

            try
            {
                var currentState = this.GetUdpClientState(controlClient);
                //Udp无连接先发送后接收
                currentState.WaitOnce();
                var tunnel = this.CreateTunnel(TunnelCommand.UdpReceive, controlClient);
                tunnel.SendReceiveTimeout = Timeout.Infinite;
                var response = tunnel.GetResponse(webResponse =>
                {
                    var pushStream = webResponse.GetResponseStream();
                    byte[] data    = new byte[(int)BufferSizeof.MaxSocket];
                    //00 00 00 01
                    data[3] = 1;
                    while (controlClient.Connected && pushStream.CanRead)
                    {
                        try
                        {
                            int offset = 4;
                            int read   = pushStream.Read(data, offset, data.Length - offset);
                            if (read == 0 || !(controlClient.Connected && pushStream.CanRead))
                            {
                                break;
                            }
                            //4-10 中间6字节为remoteIpe
                            Socks4Request.PackOut(data, ref offset, out remoteIpe);
                            if (!currentState.HasRemoteEndPoint(remoteIpe))
                            {
                                this.OutWrite("Udp Receive Discard {0} {1}bytes.", remoteIpe, read);
                                App.LogInfo("Udp Receive Discard 非法远程端点.");
                                continue;
                            }

                            int length = 4 + read;
                            int sent   = currentState.Client.Send(data, length, currentState.LocalEndPoint);
                            if (length != sent)
                            {
                                throw new InvalidOperationException("Udp数据包错误");
                            }
                            this.OutWrite("Udp {0} Receive {1}\t{2}bytes.", currentState.LocalEndPoint, remoteIpe, read);
                        }
                        catch (ObjectDisposedException ex)
                        {
#if DEBUG
                            App.LogInfo(string.Format("Predictable objectDisposed exception: {0}", ex.StackTrace));
#endif
                            return;
                        }
                        catch (IOException ex)
                        {
                            TunnelExceptionHandler.Handle(ex, controlClient.Client, string.Format("UdpDirectReceive={0}", remoteIpe));
                        }
                        catch (SocketException ex)
                        {
                            TunnelExceptionHandler.Handle(ex, controlClient.Client, string.Format("UdpDirectReceive={0}", remoteIpe));
                        }
                    }
                });
                response.Close();
            }
            catch (WebException ex)
            {
                bool isRejected;
                TunnelExceptionHandler.Handle(ex, string.Format("UdpDirectReceive={0}", remoteIpe), _output, out isRejected);
                if (isRejected)
                {
                    this.OnServerRejected();
                }
            }
            catch (Exception ex)
            {
                TunnelExceptionHandler.Handle(ex, string.Format("UdpDirectReceive={0}", remoteIpe));
            }
        }
Пример #8
0
        private void UdpDirectSend(object state)
        {
            var controlClient = (TcpClient)state;

            if (!controlClient.Connected)
            {
                return;
            }
            string destIpe = null;

            try
            {
                var currentState = this.GetUdpClientState(controlClient);
                while (controlClient.Connected)
                {
                    try
                    {
                        var    localIpe = new IPEndPoint(IPAddress.Any, IPEndPoint.MinPort);
                        byte[] data     = currentState.Client.Receive(ref localIpe);
                        if (!controlClient.Connected)
                        {
                            break;
                        }
                        if (data.IsNullOrEmpty() || !(data[0] == 0 && data[1] == 0 && data[2] == 0))
                        {
                            this.OutWrite("Udp Send Discard {0} {1}bytes.", localIpe, data == null ? -1 : data.Length);
                            App.LogInfo("Udp Send Discard 非法数据包.");
                            continue;
                        }
                        else if (!currentState.LocalEndPoint.Equals(localIpe))
                        {
                            this.OutWrite("Udp Send Discard {0} {1}bytes.", localIpe, data == null ? -1 : data.Length);
                            App.LogInfo("Udp Send Discard 非法本地端点.");
                            continue;
                        }

                        int offset = 4;
                        if (data[3] == 3)
                        {
                            DnsEndPoint de;
                            Socks4Request.PackOut(data, ref offset, out de);
                            currentState.AddRemoteEndPoint(de);
                            destIpe = string.Format("{0}:{1}", de.Host, de.Port);
                        }
                        else
                        {
                            IPEndPoint ipe;
                            Socks4Request.PackOut(data, ref offset, out ipe);
                            currentState.AddRemoteEndPoint(ipe);
                            destIpe = ipe.ToString();
                        }
                        var tunnel = this.CreateTunnel(TunnelCommand.UdpSend, controlClient);
                        tunnel.Headers[xHttpHandler.AgentDirect] = destIpe;
                        var outStream = new MemoryStream(data, offset, data.Length - offset);
#if DEBUG
                        tunnel.Form[xHttpHandler.AgentChecksum] = CryptoManaged.MD5Hash(outStream).ToString();
                        outStream.Position = 0L;
#endif
                        tunnel.Files.Add(new HttpFileContent(xHttpHandler.AgentDirect, xHttpHandler.AgentDirect, outStream));
                        var response = tunnel.GetResponse();
                        if (response.GetResponseText() != "1")
                        {
                            this.OutWrite("Udp {0} Send {1}\t{2}bytes failure.", currentState.LocalEndPoint, destIpe, outStream.Length);
                            return;
                        }
                        this.OutWrite("Udp {0} Send {1}\t{2}bytes.", currentState.LocalEndPoint, destIpe, outStream.Length);

                        //开始接收数据
                        currentState.SetOnce();
                    }
                    catch (ObjectDisposedException ex)
                    {
#if DEBUG
                        App.LogInfo(string.Format("Predictable objectDisposed exception: {0}", ex.StackTrace));
#endif
                    }
                    catch (WebException ex)
                    {
                        bool isRejected;
                        if (TunnelExceptionHandler.Handle(ex, string.Format("UdpDirectSend={0}", destIpe), _output, out isRejected))
                        {
                            controlClient.Client.Close();
                        }
                        if (isRejected)
                        {
                            this.OnServerRejected();
                        }
                    }
                    catch (SocketException ex)
                    {
                        if (ex.SocketErrorCode == SocketError.Interrupted)
                        {
#if DEBUG
                            App.LogInfo(string.Format("Predictable interrupted exception: {0}", ex.Message));
#endif
                            return;
                        }
                        TunnelExceptionHandler.Handle(ex, controlClient.Client, string.Format("UdpDirectSend={0}", destIpe));
                    }
                }
            }
            catch (Exception ex)
            {
                TunnelExceptionHandler.Handle(ex, string.Format("UdpDirectSend={0}", destIpe));
            }
        }
Пример #9
0
        public void ParsePack(byte[] bPack)
        {
            switch (this.Phase)
            {
            case Socks5Phase.spGreeting:
            {
                if (bPack[0] != 5)
                {
                    throw new ProxyAuthException(403, "Only Socks5 request are supported");
                }

                //要求匿名代理
                if (bPack[1] == 1 && bPack[2] == 0)
                {
                    this.Credential = null;
                    this.Phase      = Socks5Phase.spConnecting;
                }
                //要求匿名或用户名密码代理
                else
                {
                    this.Credential = new NetworkCredential();
                    this.Phase      = Socks5Phase.spAuthenticating;
                }
            }
            break;

            case Socks5Phase.spAuthenticating:
            {
                if (bPack[0] != 1)
                {
                    throw new ProxyAuthException(403, "Only Socks5 request are supported");
                }
                if (this.Credential == null)
                {
                    throw new ProxyAuthException(403, "Socks5Phase.spAuthenticating");
                }

                int length = Convert.ToInt32(bPack[1]);
                this.Credential.UserName = Encoding.ASCII.GetString(bPack, 2, length);

                int offset = 2 + length;
                length = Convert.ToInt32(bPack[offset]);
                this.Credential.Password = Encoding.ASCII.GetString(bPack, offset + 1, length);
                this.Phase = Socks5Phase.spConnecting;
            }
            break;

            case Socks5Phase.spConnecting:
            {
                if (bPack[0] != 5 || bPack[2] != 0)
                {
                    throw new ProxyAuthException(403, "Only Socks5 request are supported");
                }

                this.Command = (Socks5Command)bPack[1];

                int offset = 4;
                if (bPack[3] == 3)
                {
                    DnsEndPoint de;
                    Socks4Request.PackOut(bPack, ref offset, out de);
                    this.EndPoint = de;
                }
                else
                {
                    IPEndPoint ipe;
                    Socks4Request.PackOut(bPack, ref offset, out ipe);
                    this.EndPoint = ipe;
                }
            }
            break;
            }
        }
Пример #10
0
        private void AcceptCallback(IAsyncResult ar)
        {
            if (_listener == null)
            {
                return;
            }
            _listener.BeginAcceptTcpClient(this.AcceptCallback, null);

            var proxyClient = _listener.EndAcceptTcpClient(ar);

            if (_runType.HasValue)
            {
                var    proxySock = proxyClient.Client;
                byte[] buffer    = new byte[256];
                try
                {
                    switch (_runType.Value)
                    {
                    case SocksProxyType.Socks4:
                    case SocksProxyType.Socks4a:
                    {
                        int recv    = proxySock.Receive(buffer);
                        var request = new Socks4Request();
                        request.ParsePack(buffer);
                        if (request.Command == Socks4Command.Bind)
                        {
                            App.LogInfo("{0} {1}协议错误: Bind命令暂不支持", proxySock.LocalEndPoint, _runType);
                            goto default;
                        }
                        var resIpe   = new IPEndPoint(request.RemoteIP, request.RemotePort);
                        var response = new Socks4Response(resIpe);
                        response.Status = Socks4Response.ResponseStatus.RequestGranted;
                        proxySock.Send(response.ToPackets());
                        var destIpe = request.ProxyType == SocksProxyType.Socks4a ? (EndPoint) new DnsEndPoint(request.RemoteHost, request.RemotePort) : resIpe;
                        this.PushTcpClient(proxyClient, destIpe);
                    }
                    break;

                    case SocksProxyType.Socks5:
                    {
                        var request  = new Socks5Request();
                        var response = new Socks5Response();
                        proxySock.Receive(buffer);
                        request.ParsePack(buffer);
                        if (request.Credential == null)
                        {
                            //请求匿名
                            response.Anonymous = true;
                            proxySock.Send(response.ToPackets());
                        }
                        else
                        {
                            response.Anonymous = false;
                            proxySock.Send(response.ToPackets());
                            proxySock.Receive(buffer);
                            request.ParsePack(buffer);
                            var cred = request.Credential;
                            //验证凭证
                            //if (!true)
                            //{
                            //    goto default;
                            //}
                            response.Status = Socks5Response.ResponseStatus.Success;
                            proxySock.Send(response.ToPackets());
                        }
                        proxySock.Receive(buffer);
                        request.ParsePack(buffer);
                        bool isDns  = request.EndPoint is DnsEndPoint;
                        var  resIpe = isDns ? new IPEndPoint(IPAddress.Any, IPEndPoint.MinPort) : (IPEndPoint)request.EndPoint;
                        switch (request.Command)
                        {
                        case Socks5Command.TcpBind:
                            App.LogInfo("{0} {1}协议错误: Bind命令暂不支持", proxySock.LocalEndPoint, _runType);
                            goto default;

                        case Socks5Command.UdpAssociate:
                            //客户端预备开放的Udp端口
                            int clientPort = isDns ? ((DnsEndPoint)request.EndPoint).Port : ((IPEndPoint)request.EndPoint).Port;
                            //服务端开放的Udp端点
                            IPEndPoint localIpe;
                            this.PushUdpClient(proxyClient, clientPort, out localIpe);
                            response.RemoteEndPoint = localIpe;
                            proxySock.Send(response.ToPackets());
                            return;

                        default:
                            response.RemoteEndPoint = resIpe;
                            proxySock.Send(response.ToPackets());
                            this.PushTcpClient(proxyClient, request.EndPoint);
                            break;
                        }
                    }
                    break;

                    case SocksProxyType.Http:
                    {
                        //GoAgent集成不做任何协议处理
                        this.PushTcpClient(proxyClient, xHttpHandler.GoAgent);
                    }
                    break;

                    default:
                        proxyClient.Close();
                        return;
                    }
                }
                catch (Exception ex)
                {
                    this.OutWrite("{0} {1}协议错误: {2}", proxySock.LocalEndPoint, _runType, ex.Message);
                    App.LogError(ex, "代理协议错误");
                    proxyClient.Close();
                    return;
                }
            }
            else
            {
                this.PushTcpClient(proxyClient, _remoteEndPoint);
            }
            TaskHelper.Factory.StartNew(this.DirectReceive, new object[] { proxyClient });
            TaskHelper.Factory.StartNew(this.DirectSend, new object[] { proxyClient });
        }