Beispiel #1
0
 private void Received(TcpSession session, TcpRequestInfo requestInfo)
 {
     Task.Run(() =>
     {
         try
         {
             while (session.NatSession == null)
             {
                 Thread.Sleep(50);
             }
             //先gzip压缩  再转为16进制字符串
             var body = DataHelper.Compress(requestInfo.Raw);
             //转发数据
             var pack = new JsonData()
             {
                 Type   = (int)JsonType.TCP,
                 Action = (int)TcpAction.TransferData,
                 Data   = new TcpModel()
                 {
                     ServerId  = ServerId,
                     Host      = session.Map?.remote_endpoint,
                     Local     = session.Map?.local_endpoint,
                     SessionId = session.SessionId,
                     Content   = body
                 }.ToJson()
             };
             session.NatSession.Send(PackHelper.CreatePack(pack));
             LogHelper.Info($"{session.Map.name} {session.Map.protocol} {session.Map.remote_endpoint} --> {session.Map.local_endpoint} 收到报文{body.Length}字节");
         }
         catch (Exception ex)
         {
             LogHelper.Error($"{session.Map.name} {session.Map.protocol} {session.Map.remote_endpoint} --> {session.Map.local_endpoint} 请求参数:{requestInfo.Raw.ToHexWithSpace()},处理发生异常:{ex}");
         }
     });
 }
Beispiel #2
0
        public static void ChangeMap(int type, Map map)
        {
            try
            {
                map.ChangeType = type;
                ChangeMapList(map);

                var natClient = NATServer.GetSingleSession(c => c.Client?.id == map.client_id);
                if (natClient == null)
                {
                    return;
                }
                ChangeMap(map, natClient);
                var pack = PackHelper.CreatePack(new JsonData()
                {
                    Type   = (int)JsonType.NAT,
                    Action = (int)NatAction.MapChange,
                    Data   = map.ToJson()
                });
                natClient.Send(pack);
            }
            catch (Exception ex)
            {
                LogHelper.Error($"映射更新异常:{ex},参数为:{map.ToJson()}");
            }
        }
Beispiel #3
0
 private void OnPackageReceived(object sender, TcpRequestInfo tcpRequestInfo)
 {
     Task.Run(() =>
     {
         var tcpModel = tcpRequestInfo.Raw;
         //先gzip压缩  再转为16进制字符串
         var body = DataHelper.Compress(tcpRequestInfo.Raw);
         var pack = PackHelper.CreatePack(new JsonData()
         {
             Type   = (int)JsonType.TCP,
             Action = (int)TcpAction.TransferData,
             Data   = new TcpModel()
             {
                 ServerId  = RemoteSession.ServerId,
                 Host      = RemoteSession.Host,
                 Local     = RemoteSession.Local,
                 SessionId = RemoteSession.SessionId,
                 Content   = body
             }.ToJson()
         });
         //转发给服务器
         NatClient.Send(pack);
         LogHelper.Info($"{Map.name} {Map.protocol} {Map.remote_endpoint} --> {Map.local_endpoint} 收到报文{tcpRequestInfo.Raw.Length}字节");
     });
 }
Beispiel #4
0
        static void OnClientConnected(object sender)
        {
            //发送注册包给服务端
            var pack = PackHelper.CreatePack(new JsonData()
            {
                Type   = (int)JsonType.NAT,
                Action = (int)NatAction.Connect,
                Data   = Secret
            });

            NatClient?.Send(pack);
        }
Beispiel #5
0
        public void SendServerMessage(NatSession session, ServerMessage serverMessage)
        {
            LogHelper.Info(serverMessage.Message);
            var pack = new JsonData()
            {
                Type   = (int)JsonType.NAT,
                Action = (int)NatAction.ServerMessage,
                Data   = serverMessage.ToJson()
            };

            //转发给客户端
            session?.Send(PackHelper.CreatePack(pack));
        }
Beispiel #6
0
 static void SendHeart()
 {
     while (IsReConnect)
     {
         Thread.Sleep(50000);
         if (NatClient.IsConnected)
         {
             //发送心跳包给服务端
             var pack = PackHelper.CreatePack(new JsonData()
             {
                 Type   = (int)JsonType.NAT,
                 Action = (int)NatAction.Heart,
                 Data   = Secret
             });
             NatClient?.Send(pack);
         }
     }
 }
Beispiel #7
0
        public void CloseLocalClient(TcpSession session)
        {
            var pack = new JsonData()
            {
                Type   = (int)JsonType.TCP,
                Action = (int)TcpAction.Close,
                Data   = new TcpModel()
                {
                    ServerId  = ServerId,
                    Host      = session.Map?.remote_endpoint,
                    Local     = session.Map?.local_endpoint,
                    SessionId = session.SessionId
                }.ToJson()
            };

            //转发给客户端
            session.NatSession?.Send(PackHelper.CreatePack(pack));
        }
Beispiel #8
0
        private void Connected(TcpSession session)
        {
            try
            {
                //转发连接请求
                var natSession = ServerManager.NATServer.GetSingleSession(c => c.MapList?.Any(m => m.remote_port == ServerOption.Port) ?? false);
                if (natSession == null)
                {
                    session?.Close();
                    LogHelper.Error($"请求:{session.LocalEndPoint}失败,Nat客户端连接不在线!");
                    return;
                }
                var map = natSession.MapList?.Find(c => c.remote_port == ServerOption.Port);
                if (map == null)
                {
                    session?.Close();
                    LogHelper.Error($"请求:{session.LocalEndPoint}失败,映射{session.LocalEndPoint}不存在!");
                    return;
                }
                session.Map = map;
                //tcp连接注册包
                var pack = new JsonData()
                {
                    Type   = (int)JsonType.TCP,
                    Action = (int)TcpAction.Connect,
                    Data   = new TcpModel()
                    {
                        ServerId  = ServerId,
                        Host      = map?.remote_endpoint,
                        Local     = map?.local_endpoint,
                        SessionId = session.SessionId
                    }.ToJson()
                };
                natSession.Send(PackHelper.CreatePack(pack));

                session.NatSession = natSession;
                LogHelper.Info($"{session.Map.name} {session.Map.protocol} {session.Map.remote_endpoint} --> {session.Map.local_endpoint} 客户端【{session.RemoteEndPoint}】已连接到服务器");
            }
            catch (Exception ex)
            {
                LogHelper.Error($"连接【{session.SessionId},{session.RemoteEndPoint},{session.LocalEndPoint}】发生异常:{ex}");
            }
        }
Beispiel #9
0
 private void Received(HttpSession session, HttpRequestInfo requestInfo)
 {
     Task.Run(() =>
     {
         try
         {
             if (!requestInfo.Success)
             {
                 LogHelper.Error($"http请求解析异常,ip地址:{session.RemoteEndPoint}");
                 session.Write("request parse error");
                 return;
             }
             session.RequestInfo = requestInfo;
             var httpModel       = new HttpModel
             {
                 RequestTime = DateTime.Now,
                 ServerId    = ServerId,
                 SessionId   = session.SessionId,
                 HttpVersion = requestInfo.HttpVersion,
                 Method      = requestInfo.Method,
                 Path        = requestInfo.Path,
                 Headers     = requestInfo.Headers,
                 Host        = requestInfo.BaseUrl,
                 ContentType = requestInfo.ContentType,
                 Content     = requestInfo.Body
             };
             var map = ServerManager.MapList.Find(c => c.remote_endpoint == httpModel.Host || (c.remote == httpModel.Host && c.remote_port == 80));
             if (map == null)
             {
                 LogHelper.Error($"映射不存在,请求:{httpModel.Host}{httpModel.Path} {httpModel.Headers.ToJson()} {httpModel.Content.ToUTF8String()}");
                 //把处理信息返回到客户端
                 session.Write("map not found");
                 return;
             }
             //正向代理www.supernat.cn
             if (map.proxy_type == (int)proxy_type.正向代理)
             {
                 ForwardProxy(session, httpModel, map);
                 return;
             }
             //转发请求
             var natSession = ServerManager.NATServer.GetSingleSession(c => c.MapList.Any(c => c.remote_endpoint == httpModel.Host || (c.remote == httpModel.Host && c.remote_port == 80)));
             if (natSession == null)
             {
                 LogHelper.Error($"穿透客户端未连接到服务器,请求地址:{httpModel.Host}{httpModel.Path}");
                 //把处理信息返回到客户端
                 session.Write("nat client not found");
             }
             else
             {
                 //压缩Body
                 httpModel.Content = requestInfo.ContentLength > 0 ? DataHelper.Compress(requestInfo.Body) : null;
                 //转发数据
                 var pack = new JsonData()
                 {
                     Type   = (int)JsonType.HTTP,
                     Action = (int)HttpAction.Request,
                     Data   = httpModel.ToJson()
                 };
                 natSession.Send(PackHelper.CreatePack(pack));
                 session.NatSession = natSession;
             }
         }
         catch (Exception ex)
         {
             LogHelper.Error($"【{session.LocalEndPoint}】请求地址:{requestInfo.BaseUrl}{requestInfo.Path},处理发生异常:{ex}");
             //把处理信息返回到客户端
             session.Write("server error");
         }
     });
 }
Beispiel #10
0
        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);
            }
        }
Beispiel #11
0
        public void ProcessData(NatSession session, NatRequestInfo requestInfo)
        {
            try
            {
                switch (requestInfo.Body.Action)
                {
                case (int)NatAction.Connect:
                {
                    //注册包
                    var secret = requestInfo.Body.Data.ToString();
                    LogHelper.Info($"收到连接{session.RemoteEndPoint}的注册包,密钥为:{secret},当前映射个数:{session.MapList.Count}", false);
                    var bll    = new ClientBll();
                    var client = bll.GetOne(secret).Data;
                    if (client == null)
                    {
                        LogHelper.Error($"主机【{session.RemoteEndPoint}】密钥不正确!!");
                        SendServerMessage(session, new ServerMessage()
                            {
                                Message = "主机密钥不正确,请确认是否填写正确!"
                            });
                        return;
                    }
                    var checkSessions = GetSessionList(c => c.Client?.secret == secret && c.SessionId != session.SessionId);
                    if (checkSessions.Any())
                    {
                        checkSessions.ForEach(c =>
                            {
                                SendServerMessage(c, new ServerMessage()
                                {
                                    Message = "该主机密钥已被其它主机使用,您已被迫下线!"
                                });
                                Thread.Sleep(500);
                                c.Close();
                            });
                    }

                    var mapBll = new MapBll();
                    session.MapList = mapBll.GetMapList(secret).Data ?? new List <Map>();
                    client.MapList  = session.MapList;
                    session.Client  = client;
                    //原样返回回复客户端注册成功
                    requestInfo.Body.Data = client.ToJson();
                    session.Send(PackHelper.CreatePack(requestInfo.Body));
                    Task.Run(() =>
                        {
                            //更新在线状态
                            var bll       = new ClientBll();
                            var updateRst = bll.UpdateOnlineStatus(new Client()
                            {
                                secret = session.Client.secret, is_online = true, last_heart_time = DateTime.Now
                            });
                            LogHelper.Info($"更新主机【{session.Client.name}】在线状态结果:{updateRst.Message}", false);
                        });
                }
                break;

                case (int)NatAction.Heart:
                {
                    //心跳包
                    var secret = requestInfo.Body.Data.ToString();
                    LogHelper.Info($"收到连接{session.RemoteEndPoint}的心跳包,密钥为:{secret},当前映射个数:{session.MapList.Count}", false);
                    Task.Run(() =>
                        {
                            //更新在线状态
                            var bll       = new ClientBll();
                            var updateRst = bll.UpdateOnlineStatus(new Client()
                            {
                                secret = session.Client.secret, is_online = true, last_heart_time = DateTime.Now
                            });
                            LogHelper.Info($"更新主机【{session.Client.name}】在线状态结果:{updateRst.Message}", false);
                        });
                }
                break;
                }
            }
            catch (Exception ex)
            {
                LogHelper.Error($"穿透处理异常,{ex}");
            }
        }