コード例 #1
0
ファイル: TcpClientProxy.cs プロジェクト: RyanFu/SuperNAT
 private void OnPackageReceived(Socket socket, NatPackageInfo packageInfo)
 {
     Task.Run(() =>
     {
         var tcpModel = packageInfo.Raw;
         //先gzip压缩  再转为16进制字符串
         var body = DataHelper.Compress(packageInfo.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);
         HandleLog.WriteLine($"<---- {RemoteSession.SessionId} 收到报文{packageInfo.Raw.Length}字节");
     });
 }
コード例 #2
0
 private void Received(TcpSession session, NatRequestInfo 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));
             HandleLog.WriteLine($"<---- {session.SessionId} 收到报文{body.Length}字节");
         }
         catch (Exception ex)
         {
             HandleLog.WriteLine($"【{session.Local}】请求参数:{requestInfo.Raw.ToHexWithSpace()},处理发生异常:{ex}");
         }
     });
 }
コード例 #3
0
        public static void ChangeMap(int type, Map map)
        {
            try
            {
                map.ChangeType = type;
                ChangeMapList(map);

                var natClient = NATServer.GetSingle(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)
            {
                HandleLog.WriteLine($"映射更新异常:{ex},参数为:{JsonHelper.Instance.Serialize(map)}");
            }
        }
コード例 #4
0
ファイル: HomeController.cs プロジェクト: marstc1/TopTrumps
        public ActionResult Index()
        {
            ViewBag.Message = "Top Trumps is the card game that brings your favourite things to life, whether it's fast cars, football or Star Wars.";

            packHelper.CreatePack();

            return(View());
        }
コード例 #5
0
        static void OnClientConnected(Socket socket)
        {
            //发送注册包给服务端
            var pack = PackHelper.CreatePack(new JsonData()
            {
                Type   = (int)JsonType.NAT,
                Action = (int)NatAction.Connect,
                Data   = Secret
            });

            NatClient?.Send(pack);
        }
コード例 #6
0
ファイル: NatServer.cs プロジェクト: vebin/SuperNAT
        public void SendServerMessage(NatSession session, ServerMessage serverMessage)
        {
            HandleLog.WriteLine(serverMessage.Message);
            var pack = new JsonData()
            {
                Type   = (int)JsonType.NAT,
                Action = (int)NatAction.ServerMessage,
                Data   = serverMessage.ToJson()
            };

            //转发给客户端
            session?.Send(PackHelper.CreatePack(pack));
        }
コード例 #7
0
 private void Received(HttpSession session, HttpRequestInfo requestInfo)
 {
     try
     {
         var httpModel = new HttpModel
         {
             RequestTime = DateTime.Now,
             ServerId    = ServerId,
             SessionId   = session.SessionId
         };
         var filter = ReceiveFilter as HttpReceiveFilter;
         filter.DecodePackage(ref httpModel);
         //转发请求
         var natSession = NATServer.GetSingle(c => c.MapList.Any(c => c.remote_endpoint == httpModel.Host));
         if (natSession == null)
         {
             //TODO 错误页面
             HandleLog.WriteLine($"穿透客户端未连接到服务器,请求地址:{httpModel.Host}{httpModel.Path}");
             var response = new HttpResponse()
             {
                 Status      = 404,
                 ContentType = "text/html",
                 Body        = Encoding.UTF8.GetBytes("nat client not found")
             };
             //把处理信息返回到客户端
             session.Send(response.Write());
         }
         else
         {
             //转发数据
             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)
     {
         HandleLog.WriteLine($"【{session.Local}】请求地址:{requestInfo.BaseUrl}{requestInfo.Path},处理发生异常:{ex}");
     }
 }
コード例 #8
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);
         }
     }
 }
コード例 #9
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));
        }
コード例 #10
0
        private void Connected(TcpSession session)
        {
            try
            {
                //转发连接请求
                var natSession = ServerHanlder.NATServer.GetSingle(c => c.MapList?.Any(m => m.remote_port == ServerOption.Port) ?? false);
                if (natSession == null)
                {
                    session?.Close();
                    HandleLog.WriteLine($"请求:{session.Local}失败,Nat客户端连接不在线!");
                    return;
                }
                var map = natSession.MapList?.Find(c => c.remote_port == ServerOption.Port);
                if (map == null)
                {
                    session?.Close();
                    HandleLog.WriteLine($"请求:{session.Local}失败,映射{session.Local}不存在!");
                    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;
                HandleLog.WriteLine($"客户端【{session.SessionId},{session.Remote}】已连接【{session.Local}】");
            }
            catch (Exception ex)
            {
                HandleLog.WriteLine($"连接【{session.SessionId},{session.Local}】发生异常:{ex}");
            }
        }
コード例 #11
0
ファイル: HttpsServer.cs プロジェクト: vebin/SuperNAT
 private void Received(HttpSession session, HttpRequestInfo requestInfo)
 {
     Task.Run(() =>
     {
         try
         {
             if (!requestInfo.Success)
             {
                 HandleLog.WriteLine($"http请求解析异常,ip地址:{session.Remote}");
                 session.Write("request parse error");
                 return;
             }
             var httpModel = new HttpModel
             {
                 RequestTime = DateTime.Now,
                 ServerId    = ServerId,
                 SessionId   = session.SessionId
             };
             var filter = ReceiveFilter as HttpReceiveFilter;
             filter.DecodePackage(ref httpModel);
             session.RequestInfo = requestInfo;
             var map             = ServerHanlder.MapList.Find(c => c.remote_endpoint == httpModel.Host || (c.remote == httpModel.Host && c.remote_port == 80));
             if (map == null)
             {
                 HandleLog.WriteLine($"映射不存在,请求:{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 = ServerHanlder.NATServer.GetSingle(c => c.MapList.Any(c => c.remote_endpoint == httpModel.Host || (c.remote == httpModel.Host && c.remote_port == 80)));
             if (natSession == null)
             {
                 HandleLog.WriteLine($"穿透客户端未连接到服务器,请求地址:{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)
         {
             HandleLog.WriteLine($"【{session.Local}】请求地址:{requestInfo.BaseUrl}{requestInfo.Path},处理发生异常:{ex}");
             //把处理信息返回到客户端
             session.Write("server error");
         }
     });
 }
コード例 #12
0
        public static async void ProcessData(NatClient natClient, NatPackageInfo packageInfo)
        {
            try
            {
                switch (packageInfo.Body.Action)
                {
                case (byte)HttpAction.Request:
                {
                    var httpModel = packageInfo.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)
                    {
                        HandleLog.WriteLine($"映射不存在,外网访问地址:{httpModel.Host}");
                        return;
                    }
                    using HttpRequestMessage httpRequest = new HttpRequestMessage()
                          {
                              Method     = new HttpMethod(httpModel.Method),
                              RequestUri = new Uri($"{map.protocol}://{map.local_endpoint}{httpModel.Path}")
                          };
                    HandleLog.WriteLine($"{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 = new StringContent(bodyStr, Encoding.UTF8, httpModel.ContentType.Split(";")[0]);
                    }
                    HandleLog.WriteLine($"{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.ToString()}";
                    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);
                    HandleLog.WriteLine($"{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)
            {
                HandleLog.WriteLine($"处理请求异常:{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);
            }
        }
コード例 #13
0
ファイル: NatServer.cs プロジェクト: vebin/SuperNAT
        public void ProcessData(NatSession session, NatRequestInfo requestInfo)
        {
            try
            {
                switch (requestInfo.Body.Action)
                {
                case (int)NatAction.Connect:
                {
                    //注册包
                    var secret = requestInfo.Body.Data.ToString();
                    HandleLog.WriteLine($"收到连接{session.Remote}的注册包,密钥为:{secret},当前映射个数:{session.MapList.Count}", false);
                    var bll    = new ClientBll();
                    var client = bll.GetOne(secret).Data;
                    if (client == null)
                    {
                        HandleLog.WriteLine($"主机【{session.Remote}】密钥不正确!!");
                        SendServerMessage(session, new ServerMessage()
                            {
                                Message = "主机密钥不正确,请确认是否填写正确!"
                            });
                        return;
                    }
                    var checkSessions = GetList(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
                            });
                            HandleLog.WriteLine($"更新主机【{session.Client.name}】在线状态结果:{updateRst.Message}", false);
                        });
                }
                break;

                case (int)NatAction.Heart:
                {
                    //心跳包
                    var secret = requestInfo.Body.Data.ToString();
                    HandleLog.WriteLine($"收到连接{session.Remote}的心跳包,密钥为:{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
                            });
                            HandleLog.WriteLine($"更新主机【{session.Client.name}】在线状态结果:{updateRst.Message}", false);
                        });
                }
                break;
                }
            }
            catch (Exception ex)
            {
                HandleLog.WriteLine($"穿透处理异常,{ex}");
            }
        }
コード例 #14
0
ファイル: HttpServer.cs プロジェクト: vebin/SuperNAT
        private void OnHandleContext(IAsyncResult ar)
        {
            try
            {
                //继续异步监听下一次请求
                HttpListener.BeginGetContext(OnHandleContext, HttpListener);

                //当前请求上下文
                var context = HttpListener.EndGetContext(ar);
                //转发请求
                var natSession = NATServer.GetSingle(c => c.MapList.Any(c => c.remote_endpoint == context.Request.Url.Authority));
                if (natSession == null)
                {
                    //TODO 错误页面
                    HandleLog.WriteLine($"穿透客户端未连接到服务器,请求地址:{context.Request.Url.AbsoluteUri}");
                    context.Response.StatusCode = 404;
                    var returnByteArr = Encoding.UTF8.GetBytes("nat client not found");
                    using var stream = context.Response.OutputStream;
                    //把处理信息返回到客户端
                    stream.WriteAsync(returnByteArr, 0, returnByteArr.Length);
                }
                else
                {
                    var sessionId = Guid.NewGuid().ToString();
                    ContextDict.Add(sessionId, context);

                    var map       = natSession.MapList.Find(c => c.remote_endpoint == context.Request.Url.Authority);
                    var httpModel = new HttpModel()
                    {
                        RequestTime = DateTime.Now,
                        ServerId    = ServerId,
                        HttpVersion = $"{map?.protocol.ToUpper()}/{context.Request.ProtocolVersion.ToString()}",
                        Host        = context.Request.Url.Authority,
                        SessionId   = sessionId,
                        Method      = context.Request.HttpMethod,
                        Path        = context.Request.RawUrl,
                        Headers     = context.Request.Headers.ToDictionary(),
                        ContentType = context.Request.ContentType
                    };

                    var byteList = new List <byte>();
                    int readLen  = 0;
                    int len      = 0;
                    if (context.Request.HttpMethod != "Get")
                    {
                        var byteArr = new byte[2048];
                        do
                        {
                            readLen = context.Request.InputStream.Read(byteArr, 0, byteArr.Length);
                            len    += readLen;
                            byteList.AddRange(byteArr);
                        } while (readLen != 0);

                        var byteData = byteList.CloneRange(0, len);
                        var req      = byteData.ToUTF8String();

                        if (byteData.Length > 0)
                        {
                            //压缩请求数据
                            var body = DataHelper.Compress(byteData);
                            httpModel.Content = body;
                        }
                    }

                    natSession?.Send(PackHelper.CreatePack(new JsonData()
                    {
                        Type   = (int)JsonType.HTTP,
                        Action = (int)HttpAction.Request,
                        Data   = httpModel.ToJson()
                    }));
                }
            }
            catch (Exception ex)
            {
                HandleLog.WriteLine($"HttpServer OnHandleContext穿透处理异常,{ex}");
            }
        }