static void OnPackageReceived(object sender, NatRequestInfo natRequestInfo) { Task.Run(() => { switch (natRequestInfo.Body.Type) { case (byte)JsonType.NAT: NatClient.ProcessData(natRequestInfo); break; case (byte)JsonType.HTTP: HttpClientProxy.ProcessData(NatClient, natRequestInfo); break; case (byte)JsonType.TCP: { int waitTimes = 50; var tcpModel = natRequestInfo.Body.Data.FromJson <TcpModel>(); TcpClientProxy clientProxy = null; mark: clientProxy = TcpClientProxyList.Find(c => c.RemoteSession.SessionId == tcpModel.SessionId); if (natRequestInfo.Body.Action == (int)TcpAction.TransferData) { if ((clientProxy == null || !clientProxy.IsConnected) && waitTimes >= 0) { LogHelper.Warning($"----> {tcpModel.SessionId} 未连接 IsConnected={clientProxy?.IsConnected.ToString() ?? "NULL"} ProxyCount={TcpClientProxyList.Count}"); Thread.Sleep(100); waitTimes--; goto mark; } } if (clientProxy == null) { var arr = tcpModel.Local.Split(":"); var ip = arr[0]; int.TryParse(arr[1], out int port); clientProxy = new TcpClientProxy(new ClientOption() { Ip = ip, Port = port, NoDelay = true, ProtocolType = ProtocolType.Tcp }) { NatClient = NatClient }; } clientProxy.ProcessData(NatClient, natRequestInfo); break; } } }); }
public void ProcessData(NatClient natClient, NatRequestInfo natRequestInfo) { try { var tcpModel = natRequestInfo.Body.Data.FromJson <TcpModel>(); switch (natRequestInfo.Body.Action) { case (int)TcpAction.Connect: { //tcp注册包 发起连接到内网服务器 RemoteSession = tcpModel; Map = natClient.Client.MapList.Find(c => c.remote_endpoint == tcpModel.Host); if (Map == null) { throw new Exception($"{Map.name} {Map.protocol} {Map.remote_endpoint} --> {Map.local_endpoint} 映射不存在"); } ConectLocalServerAsync(); } break; case (int)TcpAction.TransferData: { if (RemoteSession == null) { return; } //gzip解压 var request = DataHelper.Decompress(tcpModel.Content); //发送原始包 Send(request); LogHelper.Info($"{Map.name} {Map.protocol} {Map.remote_endpoint} --> {Map.local_endpoint} 发送报文{request.Length}字节"); } break; case (int)TcpAction.Close: { //tcp连接关闭包 ClientManager.TcpClientProxyList.Remove(this); Close(); } break; } } catch (Exception ex) { LogHelper.Error($"{Map.name} {Map.protocol} {Map.remote_endpoint} --> {Map.local_endpoint} 客户端处理TCP穿透业务异常,{ex}"); } }
public void ProcessData(NatSession session, NatRequestInfo requestInfo, TcpModel tcpModel) { try { switch (requestInfo.Body.Action) { case (int)TcpAction.TransferData: { //响应请求 int count = 0; mark: var tcpSession = GetSingleSession(c => c.SessionId == tcpModel.SessionId); if (tcpSession == null) { count++; Thread.Sleep(500); if (count < 5) { goto mark; } LogHelper.Warning($"tcpSession【{tcpModel.SessionId}】不存在"); return; } //先讲16进制字符串转为byte数组 再gzip解压 var response = DataHelper.Decompress(tcpModel.Content); tcpSession.Send(response); LogHelper.Info($"{tcpSession.Map.name} {tcpSession.Map.protocol} {tcpSession.Map.remote_endpoint} --> {tcpSession.Map.local_endpoint} 发送报文{response.Length}字节"); } break; case (int)TcpAction.Close: { //关闭请求 var tcpSession = GetSingleSession(c => c.SessionId == tcpModel.SessionId); if (tcpSession != null) { tcpSession.Close(); LogHelper.Info($"连接【{tcpSession.SessionId},{tcpSession.RemoteEndPoint}】关闭成功"); } } break; } } catch (Exception ex) { LogHelper.Error($"TcpServer穿透处理异常,{ex}"); } }
private static void Received(NatSession session, NatRequestInfo requestInfo) { Task.Run(() => { try { switch (requestInfo.Body.Type) { case (byte)JsonType.NAT: { LogHelper.Info($"NAT收到数据:{requestInfo.Raw.ToHexWithSpace()},正文内容: {requestInfo.Body.ToJson()}", false); NATServer.ProcessData(session, requestInfo); break; } case (byte)JsonType.HTTP: { var httpModel = requestInfo.Body.Data.FromJson <HttpModel>(); var server = HttpServerList.Find(c => c.ServerId == httpModel.ServerId); server?.ProcessData(session, requestInfo, httpModel); break; } case (byte)JsonType.TCP: { var tcpModel = requestInfo.Body.Data.FromJson <TcpModel>(); var server = TcpServerList.Find(c => c.ServerId == tcpModel.ServerId); server?.ProcessData(session, requestInfo, tcpModel); break; } } } catch (Exception ex) { LogHelper.Error($"穿透传输连接【{session.RemoteEndPoint},{session.Client?.name}】响应请求异常:{ex}"); } }); }
public void ProcessData(NatSession session, NatRequestInfo requestInfo, HttpModel httpModel) { try { switch (requestInfo.Body.Action) { case (int)HttpAction.Response: { var context = GetSingleSession(c => c.SessionId == httpModel.SessionId); if (context == null) { LogHelper.Error($"未找到上下文context,SessionId={httpModel.SessionId}"); return; } HttpResponse httpResponse = new HttpResponse() { HttpVersion = httpModel.HttpVersion, Headers = httpModel.Headers, Status = httpModel.StatusCode, StatusMessage = httpModel.StatusMessage }; if (httpModel.Content?.Length > 0) { //解压 var byteData = DataHelper.Decompress(httpModel.Content); httpResponse.ContentType = httpModel.ContentType; httpResponse.Body = byteData; } //把处理信息返回到客户端 context.Send(httpResponse.Write()); var response_time = DateTime.Now; var timeSpan = (response_time - httpModel.RequestTime); var totalSize = (httpResponse.Body?.Length ?? 0) * 1.00 / 1024; var map = session.MapList.Find(c => c.remote_endpoint == httpModel.Host); LogHelper.Info($"{session.Client.user_name} {session.Client.name} {map?.name} {httpModel.Method} {httpModel.Path} {httpModel.StatusCode} {httpModel.StatusMessage} {Math.Round(totalSize, 1)}KB {timeSpan.TotalMilliseconds}ms"); var request = new Request { request_url = $"{map.protocol}://{map.remote_endpoint}{httpModel.Path}", request_method = httpModel.Method, client_ip = session.RemoteEndPoint.ToString(), user_id = session.Client.user_id, request_time = httpModel.RequestTime, response_time = response_time, handle_time = Convert.ToInt64(timeSpan.TotalMilliseconds), //ms create_time = DateTime.Now, requet_content = context.RequestInfo.Body == null ? null : Encoding.UTF8.GetString(context.RequestInfo.Body), response_content = httpResponse.Body.Length <= 1024 ? Encoding.UTF8.GetString(httpResponse.Body) : "", status_code = httpModel.StatusCode, status_message = httpModel.StatusMessage, total_size = httpResponse.Body?.Length ?? 0, speed = Math.Round(totalSize / (timeSpan.TotalMilliseconds / 1000), 2),//KB/s map_id = map.id }; lock (RequestQueue) RequestQueue.Enqueue(request); } break; } } catch (Exception ex) { LogHelper.Error($"HttpsServer ProcessData穿透处理异常,{ex}"); } }
public static async void ProcessData(NatClient natClient, NatRequestInfo natRequestInfo) { try { switch (natRequestInfo.Body.Action) { case (byte)HttpAction.Request: { var httpModel = natRequestInfo.Body.Data.FromJson <HttpModel>(); var map = natClient.Client.MapList.Find(c => c.remote_endpoint == httpModel.Host || (c.remote == httpModel.Host && c.remote_port == 80)); if (map == null) { LogHelper.Error($"映射不存在,外网访问地址:{httpModel.Host}"); return; } using HttpRequestMessage httpRequest = new HttpRequestMessage() { Method = new HttpMethod(httpModel.Method), RequestUri = new Uri($"{map.protocol}://{map.local_endpoint}{httpModel.Path}") }; LogHelper.Info($"{map.name} {httpModel.Method} {httpRequest.RequestUri.AbsoluteUri} {httpModel.Headers.ToJson()}{Environment.NewLine}"); string bodyStr = string.Empty; if (httpRequest.Method != HttpMethod.Get && httpModel.Content?.Length > 0) { var body = DataHelper.Decompress(httpModel.Content); //解压 bodyStr = body.ToUTF8String(); httpRequest.Content = httpModel.ContentType == null ? new StringContent(bodyStr, Encoding.UTF8) : new StringContent(bodyStr, Encoding.UTF8, httpModel.ContentType.Split(";")[0]); } LogHelper.Info($"{map.name} {httpModel.Method} {httpRequest.RequestUri.AbsoluteUri}{Environment.NewLine}【Header】{httpModel.Headers.ToJson()}{$"{Environment.NewLine}【Body】{bodyStr}".If(httpModel.Content?.Length < 1024)}{Environment.NewLine}"); using HttpClient _httpClient = new HttpClient(); //替换Host 不然400 Bad Request httpModel.Headers["Host"] = map.local_endpoint; foreach (var item in httpModel.Headers) { if (!item.Key.EqualsWhithNoCase("Content-Type")) { if (!httpRequest.Content?.Headers.TryAddWithoutValidation(item.Key, item.Value) ?? true) { _httpClient.DefaultRequestHeaders.TryAddWithoutValidation(item.Key, item.Value); } } } if (map.protocol == "https") { ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls; } var response = await _httpClient.SendAsync(httpRequest); //回传给服务器 httpModel.HttpVersion = $"{map.protocol.ToUpper()}/{response.Version}"; httpModel.StatusCode = (int)response.StatusCode; httpModel.StatusMessage = response.StatusCode.ToString(); httpModel.Local = map.local_endpoint; httpModel.Headers = response.Headers.ToDictionary(); httpModel.ResponseTime = DateTime.Now; foreach (var item in response.Content.Headers) { if (item.Key.EqualsWhithNoCase("Content-Type")) { httpModel.ContentType = string.Join(";", item.Value); } else { if (item.Key.EqualsWhithNoCase("Content-Length")) { continue; } httpModel.Headers.Add(item.Key, string.Join(";", item.Value)); } } httpModel.Headers.Remove("Transfer-Encoding"); //response收到的是完整的 这个响应头要去掉 不然浏览器解析出错 var returnContent = DataHelper.StreamToBytes(response.Content.ReadAsStreamAsync().Result); if (returnContent.Length > 0) { httpModel.Content = DataHelper.Compress(returnContent); } var pack = PackHelper.CreatePack(new JsonData() { Type = (int)JsonType.HTTP, Action = (int)HttpAction.Response, Data = httpModel.ToJson() }); natClient?.Send(pack); LogHelper.Info($"{map.name} {httpModel.Method} {httpRequest.RequestUri.AbsoluteUri}{$"{returnContent.ToUTF8String()}".If(returnContent.Length < 1024)} {httpModel.StatusCode} {httpModel.StatusMessage} {Math.Round(returnContent.Length * 1.00 / 1024, 1)}KB{Environment.NewLine}"); break; } } } catch (Exception ex) { LogHelper.Error($"处理请求异常:{ex}"); var pack = PackHelper.CreatePack(new JsonData() { Type = (int)JsonType.HTTP, Action = (int)HttpAction.Response, Data = new HttpModel() { StatusCode = (int)HttpStatusCode.BadRequest, ContentType = "text/html", Content = DataHelper.Compress(Encoding.UTF8.GetBytes($"server error")) }.ToJson() }); natClient?.Send(pack); } }