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); } }
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)); } }
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)); } }
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"); } } }
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"); } } }
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"); } } }
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)); } }
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)); } }
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)); } }
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); } }