Пример #1
0
        private void DisconnectCallbak(IAsyncResult ar)
        {
            var controlClient = (TcpClient)ar.AsyncState;
            var state         = this.GetUdpClientState(controlClient);

            try
            {
                int recv = controlClient.Client.EndReceive(ar);
                if (recv == 0 || !controlClient.Connected)
                {
                    this.OutWrite("Udp {0} disconnect.", state.LocalEndPoint);
                }
            }
            catch (ObjectDisposedException ex)
            {
#if DEBUG
                App.LogInfo(string.Format("Predictable objectDisposed exception: {0}", ex.StackTrace));
#endif
            }
            catch (SocketException ex)
            {
                TunnelExceptionHandler.Handle(ex, controlClient.Client, "Udp disconnect");
            }
            finally
            {
                controlClient.Client.Close();
                this.PopTcpClient(controlClient);
                state.Dispose();
                _udpClients.TryRemove(controlClient, out state);
            }
        }
Пример #2
0
        public void UdpDirectSend(HttpContext context, UdpClient proxyClient, IPEndPoint remoteIpe)
        {
            context.Server.ScriptTimeout = Timeout;
            HttpRequest  Request  = context.Request;
            HttpResponse Response = context.Response;

            Response.AppendHeader(HttpResponseHeader.Connection.ToString(), "keep-alive");

            var httpFile = Request.Files[AgentDirect];

            if (httpFile == null)
            {
                this.ResponseForbidden(context);
            }
            Stream inStream = httpFile.InputStream;

#if DEBUG
            Guid checksum;
            if (!Guid.TryParse(Request.Form[AgentChecksum], out checksum))
            {
                this.ResponseForbidden(context);
            }
            var mem = new MemoryStream();
            inStream.FixedCopyTo(mem, httpFile.ContentLength);
            mem.Position = 0L;
            Guid checkKey = CryptoManaged.MD5Hash(mem);
            if (checksum != checkKey)
            {
                this.ResponseForbidden(context);
            }
            mem.Position = 0L;
            inStream     = mem;
#endif
            bool succeed = false;
            int  length  = (int)inStream.Length;
            try
            {
                var reader = new BinaryReader(inStream);
                proxyClient.Send(reader.ReadBytes(length), length, remoteIpe);
                succeed = true;
                App.LogInfo("UdpDirectSend to {0} {1}bytes.", remoteIpe, length);
            }
            catch (ObjectDisposedException ex)
            {
#if DEBUG
                App.LogInfo(string.Format("Predictable objectDisposed exception: {0}", ex.StackTrace));
#endif
            }
            catch (SocketException ex)
            {
                TunnelExceptionHandler.Handle(ex, proxyClient.Client, "UdpDirectSend");
            }
            if (Response.IsClientConnected)
            {
                Response.Write(Convert.ToByte(succeed));
            }
        }
Пример #3
0
        private void DirectSend(HttpContext context, TcpClient proxyClient)
        {
            context.Server.ScriptTimeout = Timeout;
            HttpRequest  Request  = context.Request;
            HttpResponse Response = context.Response;

            //优化性能
            Response.AppendHeader(HttpResponseHeader.Connection.ToString(), "keep-alive");

            var httpFile = Request.Files[AgentDirect];

            if (httpFile == null)
            {
                this.ResponseForbidden(context);
            }
            Stream inStream = httpFile.InputStream;

#if DEBUG
            Guid checksum;
            if (!Guid.TryParse(Request.Form[AgentChecksum], out checksum))
            {
                this.ResponseForbidden(context);
            }
            var mem = new MemoryStream();
            inStream.FixedCopyTo(mem, httpFile.ContentLength);
            mem.Position = 0L;
            Guid checkKey = CryptoManaged.MD5Hash(mem);
            if (checksum != checkKey)
            {
                this.ResponseForbidden(context);
            }
            mem.Position = 0L;
            inStream     = mem;
#endif
            bool succeed = false;
            if (proxyClient.Connected)
            {
                var proxyStream = proxyClient.GetStream();
                int length      = (int)inStream.Length;
                try
                {
                    inStream.FixedCopyTo(proxyStream, length);
                    succeed = true;
#if DEBUG
                    App.LogInfo("DirectSend to {0} {1}bytes.", proxyClient.Client.RemoteEndPoint, length);
#endif
                }
                catch (IOException ex)
                {
                    TunnelExceptionHandler.Handle(ex, proxyClient.Client, "DirectSend");
                }
            }
            if (Response.IsClientConnected)
            {
                Response.Write(Convert.ToByte(succeed));
            }
        }
Пример #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
        private void DirectReceive(HttpContext context, TcpClient proxyClient)
        {
            context.Server.ScriptTimeout = int.MaxValue;
            HttpRequest  Request  = context.Request;
            HttpResponse Response = context.Response;

            //长连接必须关掉
            Response.AppendHeader(HttpResponseHeader.Connection.ToString(), "close");

            var proxyStream = proxyClient.GetStream();

            while (proxyClient.Connected && Response.IsClientConnected)
            {
                try
                {
                    proxyStream.Read(EmptyBuffer, 0, 0);
                    int length;
                    //阻塞解除后做第2道检查
                    if (!(proxyClient.Connected && Response.IsClientConnected) || (length = proxyClient.Available) == 0)
                    {
                        //服务端主动关闭,发送空包
                        if (Response.IsClientConnected)
                        {
                            Response.OutputStream.Write(EmptyBuffer, 0, 0);
                            Response.Flush();
                        }
                        break;
                    }
                    proxyStream.FixedCopyTo(Response.OutputStream, length);
                    if (Response.IsClientConnected)
                    {
                        Response.Flush();
                    }
#if DEBUG
                    App.LogInfo("DirectReceive from {0} {1}bytes.", proxyClient.Client.RemoteEndPoint, length);
#endif
                }
                catch (IOException ex)
                {
                    TunnelExceptionHandler.Handle(ex, proxyClient.Client, "DirectReceive");
                }
                catch (SocketException ex)
                {
                    TunnelExceptionHandler.Handle(ex, proxyClient.Client, "DirectReceive");
                }
            }
        }
Пример #6
0
        private void ReverseDirectReceive(HttpContext context, ref Guid agentSock)
        {
            context.Server.ScriptTimeout = int.MaxValue;
            HttpRequest  Request  = context.Request;
            HttpResponse Response = context.Response;

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

            var dataQueue = OnlineUsers.GetReverseQueue(agentSock, false);

            while (dataQueue.Connected && Response.IsClientConnected)
            {
                try
                {
                    dataQueue.WaitHandle.WaitOne();
                    Stream outStream;
                    //阻塞解除后做第2道检查
                    if (!dataQueue.TryPop(out outStream) || !(dataQueue.Connected && Response.IsClientConnected))
                    {
                        //服务端主动关闭,发送空包
                        if (Response.IsClientConnected)
                        {
                            Response.OutputStream.Write(EmptyBuffer, 0, 0);
                            Response.Flush();
                        }
                        break;
                    }
                    int length = (int)outStream.Length;
                    outStream.FixedCopyTo(Response.OutputStream, length);
                    if (Response.IsClientConnected)
                    {
                        Response.Flush();
                    }
#if DEBUG
                    App.LogInfo("ReverseDirectReceive from {0} {1}bytes.", dataQueue.RemoteEndPoint, length);
#endif
                }
                catch (IOException ex)
                {
                    TunnelExceptionHandler.Handle(ex, "ReverseDirectReceive");
                }
            }
        }
Пример #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
        private void DirectSend(object state)
        {
            var  args           = (object[])state;
            var  proxyClient    = (TcpClient)args[0];
            Guid?localAgentSock = null;

            if (args.Length == 2)
            {
                localAgentSock = (Guid)args[1];
            }
            if (!proxyClient.Connected)
            {
                return;
            }
            string destIpe = null;

            try
            {
                var localIpe = (IPEndPoint)proxyClient.Client.LocalEndPoint;
                destIpe = this.GetClientState(proxyClient).ToString();
                var proxyStream = proxyClient.GetStream();
                var outStream   = new MemoryStream();
                while (proxyClient.Connected)
                {
                    try
                    {
                        proxyStream.Read(xHttpHandler.EmptyBuffer, 0, 0);
                        int length;
                        //阻塞解除后做第2道检查,先判断连接状态否则proxyClient.Available会引发ObjectDisposedException
                        if (!proxyClient.Connected || (length = proxyClient.Available) == 0)
                        {
                            //客户端主动关闭
                            this.OutWrite("{0} Passive disconnect {1}.", localIpe, destIpe);
                            proxyClient.Close();
                            break;
                        }
                        outStream.Position = 0L;
                        outStream.SetLength(length);
                        proxyStream.FixedCopyTo(outStream, length);
                        outStream.Position = 0L;
                        var tunnel = this.CreateTunnel(TunnelCommand.Send, proxyClient);
                        if (localAgentSock != null)
                        {
                            tunnel.Headers[xHttpHandler.AgentReverse] = localAgentSock.Value.ToString("N");
                        }
#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("{0} Send {1}\t{2}bytes failure.", localIpe, destIpe, length);
                            continue;
                        }
                        this.OutWrite("{0} Send {1}\t{2}bytes.", localIpe, destIpe, length);
                    }
                    catch (WebException ex)
                    {
                        bool isReject;
                        if (TunnelExceptionHandler.Handle(ex, string.Format("DirectSend={0}", destIpe), _output, out isReject))
                        {
                            proxyClient.Client.Close();
                        }
                        if (isReject)
                        {
                            this.OnServerRejected();
                        }
                    }
                    catch (IOException ex)
                    {
                        var sockEx = ex.InnerException as SocketException;
                        if (sockEx != null)
                        {
                            //由于serverPush关闭后,无法将服务端主动关闭信号转发过来,因此proxyStream.Read()会引发Interrupted的异常;
                            //也就是说错误的原因在于调用Close()后,线程恰好继续向网络缓冲区中读取数据,所以引发SocketException。
                            if (sockEx.SocketErrorCode == SocketError.Interrupted)
                            {
#if DEBUG
                                App.LogInfo(string.Format("Predictable interrupted exception: {0}", sockEx.Message));
#endif
                                return;
                            }
                        }
                        TunnelExceptionHandler.Handle(ex, proxyClient.Client, string.Format("DirectSend={0}", destIpe));
                    }
                    catch (SocketException ex)
                    {
                        TunnelExceptionHandler.Handle(ex, proxyClient.Client, string.Format("DirectSend={0}", destIpe));
                    }
                }
            }
            catch (Exception ex)
            {
                TunnelExceptionHandler.Handle(ex, string.Format("DirectSend={0}", destIpe));
            }
        }
Пример #10
0
        private void DirectReceive(object state)
        {
            var  args           = (object[])state;
            var  proxyClient    = (TcpClient)args[0];
            Guid?localAgentSock = null;

            if (args.Length == 2)
            {
                localAgentSock = (Guid)args[1];
            }
            //客户端立即关闭则跳过
            if (!proxyClient.Connected)
            {
                return;
            }
            string destIpe = null;
            ArraySegment <byte> bArray;

            BufferSegment.Instance.Take(out bArray);
            try
            {
                var localIpe = (IPEndPoint)proxyClient.Client.LocalEndPoint;
                destIpe = this.GetClientState(proxyClient).ToString();
                var proxyStream = proxyClient.GetStream();
                var tunnel      = this.CreateTunnel(TunnelCommand.Receive, proxyClient);
                tunnel.SendReceiveTimeout = Timeout.Infinite;
                if (localAgentSock != null)
                {
                    tunnel.Headers[xHttpHandler.AgentReverse] = localAgentSock.Value.ToString("N");
                }
                var response = tunnel.GetResponse(webResponse =>
                {
                    var pushStream = webResponse.GetResponseStream();
                    while (proxyClient.Connected && pushStream.CanRead)
                    {
                        try
                        {
                            //第一个数据包有延迟,故放弃此方式
                            //pushStream.Read(xHttpHandler.EmptyBuffer, 0, 0);
                            //int length = pushSock.Available;
                            //if (length == 0)
                            //{
                            //    break;
                            //}
                            //pushStream.FixedCopyTo(proxyStream, length);

                            int read = pushStream.Read(bArray);
                            //阻塞解除后做第2道检查
                            if (read == 0 || !(proxyClient.Connected && pushStream.CanRead))
                            {
                                //服务端主动关闭
                                this.OutWrite("{0} Initiative disconnect {1}.", destIpe, localIpe);
                                break;
                            }
                            proxyStream.Write(bArray, 0, read);
                            this.OutWrite("{0} Receive {1}\t{2}bytes.", localIpe, destIpe, read);
                        }
                        catch (IOException ex)
                        {
                            TunnelExceptionHandler.Handle(ex, proxyClient.Client, string.Format("DirectReceive={0}", destIpe));
                        }
                        catch (SocketException ex)
                        {
                            TunnelExceptionHandler.Handle(ex, proxyClient.Client, string.Format("DirectReceive={0}", destIpe));
                        }
                    }
                });
                response.Close();
            }
            catch (WebException ex)
            {
                bool isReject;
                if (TunnelExceptionHandler.Handle(ex, string.Format("DirectReceive={0}", destIpe), _output, out isReject))
                {
                    proxyClient.Client.Close(1);
                }
                if (isReject)
                {
                    this.OnServerRejected();
                }
            }
            catch (Exception ex)
            {
                TunnelExceptionHandler.Handle(ex, string.Format("DirectReceive={0}", destIpe));
            }
            finally
            {
                BufferSegment.Instance.Return(ref bArray);
                proxyClient.Client.Close(1);
                this.PopTcpClient(proxyClient);
            }
        }