Exemplo n.º 1
0
 public void OnPackageReceived(object sender, PackageEventArgs <ClientPackageInfo> e)
 {
     Task.Run(() =>
     {
         //先gzip压缩  再转为16进制字符串
         var body = DataHelper.Compress(e.Package.Data);
         var pack = new PackJson()
         {
             Host    = PackJson.Host,
             UserId  = PackJson.UserId,
             Content = body
         };
         var json      = JsonHelper.Instance.Serialize(pack);
         var jsonBytes = Encoding.UTF8.GetBytes(json);
         //03 02 数据长度(4) 正文数据(n)   ---tcp响应包
         var sendBytes = new List <byte>()
         {
             0x3, 0x2
         };
         sendBytes.AddRange(BitConverter.GetBytes(jsonBytes.Length).Reverse());
         sendBytes.AddRange(jsonBytes);
         //转发给服务器
         NatClient.Send(sendBytes.ToArray());
         HandleLog.WriteLine($"<---- {PackJson.UserId} 收到报文{e.Package.Data.Length}字节");
     });
 }
Exemplo n.º 2
0
        public void Stop()
        {
            reConnectThread?.Abort();
            reConnectThread = null;

            heartThread?.Abort();
            heartThread = null;

            NatClient?.Close();
            NatClient = null;
        }
Exemplo n.º 3
0
        static void OnPackageReceived(Socket socket, NatPackageInfo packageInfo)
        {
            Task.Run(() =>
            {
                switch (packageInfo.Body.Type)
                {
                case (byte)JsonType.NAT:
                    NatClient.ProcessData(socket, packageInfo);
                    break;

                case (byte)JsonType.HTTP:
                    HttpClientProxy.ProcessData(NatClient, packageInfo);
                    break;

                case (byte)JsonType.TCP:
                    {
                        int waitTimes = 50;
                        var tcpModel  = packageInfo.Body.Data.FromJson <TcpModel>();
                        TcpClientProxy clientProxy = null;
                        mark:
                        clientProxy = TcpClientProxyList.Find(c => c.RemoteSession.SessionId == tcpModel.SessionId);
                        if (packageInfo.Body.Action == (int)TcpAction.TransferData)
                        {
                            if ((clientProxy == null || !clientProxy.IsConnected) && waitTimes >= 0)
                            {
                                HandleLog.WriteLine($"----> {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 ClientOptions()
                            {
                                Ip           = ip,
                                Port         = port,
                                NoDelay      = true,
                                ProtocolType = ProtocolType.Tcp
                            })
                            {
                                NatClient = NatClient
                            };
                        }
                        clientProxy.ProcessData(NatClient, packageInfo);
                        break;
                    }
                }
            });
        }
Exemplo n.º 4
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);
        }
Exemplo n.º 5
0
        static void OnClientConnected(object sender, EventArgs e)
        {
            //HandleLog.WriteLine($"【{NatClient.LocalEndPoint}】已连接到服务器【{NatClient.Socket.RemoteEndPoint}】");
            //发送注册包
            var packBytes = new List <byte>()
            {
                0x1, 0x1
            };
            var lenBytes = BitConverter.GetBytes(RegPack.Length).Reverse();

            packBytes.AddRange(lenBytes);
            packBytes.AddRange(RegPack);
            NatClient.Send(packBytes.ToArray());
        }
Exemplo n.º 6
0
 static void ConnectNatServer()
 {
     try
     {
         if (IsStop)
         {
             return;
         }
         HandleLog.WriteLine($"正在连接服务器...");
         NatClient?.Close();
         NatClient = null;
         NatClient = new EasyClient <NatPackageInfo>()
         {
             NoDelay  = true,
             Security = new SecurityOption()
             {
                 EnabledSslProtocols          = System.Security.Authentication.SslProtocols.Tls12,
                 AllowNameMismatchCertificate = true,
                 AllowCertificateChainErrors  = true,
                 AllowUnstrustedCertificate   = true
             }
         };
         NatClient.Initialize(new NatReceiveFilter());
         NatClient.Connected          += OnClientConnected;
         NatClient.NewPackageReceived += OnPackageReceived;
         NatClient.Error  += OnClientError;
         NatClient.Closed += OnClientClosed;
         //解析主机名
         IPHostEntry ipInfo   = Dns.GetHostEntry(ServerUrl);
         var         serverIp = ipInfo.AddressList.Any() ? ipInfo.AddressList[0].ToString() : throw new Exception($"域名【{ServerUrl}】无法解析");
         //连接NAT转发服务
         var res = NatClient.ConnectAsync(new IPEndPoint(IPAddress.Parse(serverIp), NatPort)).Result;
         if (!res)
         {
             Thread.Sleep(2000);
             ConnectNatServer();
         }
     }
     catch (Exception ex)
     {
         HandleLog.WriteLine($"连接服务器失败:{ex}");
         Thread.Sleep(1000);
         ConnectNatServer();
     }
 }
Exemplo n.º 7
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);
         }
     }
 }
Exemplo n.º 8
0
        static async void ConnectNatServer()
        {
            try
            {
                if (!IsReConnect)
                {
                    return;
                }
                HandleLog.WriteLine($"正在连接服务器...");
                NatClient = null;
                //解析主机名
                IPHostEntry ipInfo   = Dns.GetHostEntry(ServerUrl);
                var         serverIp = ipInfo.AddressList.Any() ? ipInfo.AddressList[0].ToString() : throw new Exception($"域名【{ServerUrl}】无法解析");
                NatClient = new NatClient(new ClientOptions()
                {
                    Ip           = serverIp,
                    Port         = NatPort,
                    NoDelay      = true,
                    ProtocolType = ProtocolType.Tcp,
                    Security     = SslProtocols.Tls12,
                    SslClientAuthenticationOptions = new SslClientAuthenticationOptions
                    {
                        EnabledSslProtocols = SslProtocols.Tls12,
                        TargetHost          = serverIp,
                        ClientCertificates  = new X509CertificateCollection()
                        {
                            new X509Certificate(CertFile, CertPassword)
                        }
                    }
                });
                NatClient.Initialize(new NatReceiveFilter());
                NatClient.OnConnected += OnClientConnected;
                NatClient.OnReceived  += OnPackageReceived;
                NatClient.OnClosed    += OnClientClosed;

                await NatClient.ConnectAsync();
            }
            catch (Exception ex)
            {
                HandleLog.WriteLine($"连接服务器失败:{ex}");
                Thread.Sleep(1000);
                ConnectNatServer();
            }
        }
Exemplo n.º 9
0
 static void SendHeart()
 {
     while (!IsStop)
     {
         Thread.Sleep(30000);
         if (NatClient.IsConnected)
         {
             //发送心跳包
             var packBytes = new List <byte>()
             {
                 0x1, 0x2
             };
             var lenBytes = BitConverter.GetBytes(RegPack.Length).Reverse();
             packBytes.AddRange(lenBytes);
             packBytes.AddRange(RegPack);
             NatClient.Send(packBytes.ToArray());
         }
     }
 }
Exemplo n.º 10
0
        public void CloseRemouteClient()
        {
            var pack = new PackJson()
            {
                Host   = PackJson.Host,
                UserId = PackJson.UserId
            };
            var json      = JsonHelper.Instance.Serialize(pack);
            var jsonBytes = Encoding.UTF8.GetBytes(json);
            //03 03 数据长度(4) 正文数据(n)   ---tcp连接关闭包
            var sendBytes = new List <byte>()
            {
                0x3, 0x3
            };

            sendBytes.AddRange(BitConverter.GetBytes(jsonBytes.Length).Reverse());
            sendBytes.AddRange(jsonBytes);
            //转发给服务器
            NatClient.Send(sendBytes.ToArray());
        }
Exemplo n.º 11
0
        public void ProcessData(NatClient natClient, NatPackageInfo packageInfo)
        {
            try
            {
                var tcpModel = packageInfo.Body.Data.FromJson <TcpModel>();
                switch (packageInfo.Body.Action)
                {
                case (int)TcpAction.Connect:
                {
                    //tcp注册包  发起连接到内网服务器
                    RemoteSession = tcpModel;
                    ConectLocalServer();
                }
                break;

                case (int)TcpAction.TransferData:
                {
                    //先讲16进制字符串转为byte数组  再gzip解压
                    var request = DataHelper.Decompress(tcpModel.Content);
                    //发送原始包
                    Send(request);
                    HandleLog.WriteLine($"----> {RemoteSession.SessionId} 发送报文{request.Length}字节");
                }
                break;

                case (int)TcpAction.Close:
                {
                    //tcp连接关闭包
                    ClientHandler.TcpClientProxyList.Remove(this);
                    HandleLog.WriteLine($"本地连接【{RemoteSession.SessionId},{Local}】关闭成功");
                    Close();
                }
                break;
                }
            }
            catch (Exception ex)
            {
                HandleLog.WriteLine($"客户端处理TCP穿透业务异常,{ex}");
            }
        }
Exemplo n.º 12
0
        /// <summary>
        /// 处理请求
        /// </summary>
        /// <param name="e"></param>
        static void HandleRequest(PackageEventArgs <NatPackageInfo> e)
        {
            Task.Run(() =>
            {
                try
                {
                    var packJson    = JsonHelper.Instance.Deserialize <PackJson>(e.Package.BodyRaw);
                    var headers     = packJson.Headers;
                    var contentType = headers.ContainsKey("Content-Type") ? headers["Content-Type"] : null;
                    var data        = packJson.Content == null ? "" : Encoding.UTF8.GetString(packJson.Content);
                    if (!string.IsNullOrEmpty(contentType))
                    {
                        var index = contentType.IndexOf(";");
                        if (index > 0)
                        {
                            //去掉; charset=utf-8
                            contentType = contentType.Substring(0, index);
                        }
                    }
                    var map = MapList.Find(c => c.remote == packJson.Host);
                    if (map == null)
                    {
                        HandleLog.WriteLine($"映射不存在,外网访问地址:{packJson.Host}");
                        return;
                    }
                    var res = HttpHelper.Request(packJson.Method, $"{map.protocol}://{map.local}{packJson.Route}", data, headers: headers, contentType: contentType);
                    if (res == null)
                    {
                        HandleLog.WriteLine("服务器返回NULL");
                        return;
                    }
                    using (res)
                    {
                        using var stream   = res.Content.ReadAsStreamAsync().Result;
                        var result         = DataHelper.StreamToBytes(stream);
                        var rawResult      = Encoding.UTF8.GetString(result);
                        StringBuilder resp = new StringBuilder();
                        resp.Append($"{map.protocol.ToUpper()}/{res.Version} {(int)res.StatusCode} {res.StatusCode.ToString()}\r\n");
                        foreach (var item in res.Headers)
                        {
                            if (item.Key != "Transfer-Encoding")
                            {
                                resp.Append($"{item.Key}: {string.Join(";", item.Value)}\r\n");
                            }
                        }
                        foreach (var item in res.Content.Headers)
                        {
                            resp.Append($"{item.Key}: {string.Join(";", item.Value)}\r\n");
                        }
                        if (packJson.Method.ToUpper() == "OPTIONS")
                        {
                            resp.Append("Access-Control-Allow-Credentials: true\r\n");
                            if (packJson.Headers.ContainsKey("Access-Control-Request-Headers"))
                            {
                                resp.Append($"Access-Control-Allow-Headers: {packJson.Headers["Access-Control-Request-Headers"]}\r\n");
                            }
                            resp.Append("Access-Control-Allow-Methods: *\r\n");
                            resp.Append($"Access-Control-Allow-Origin: {packJson.Headers["Origin"]}\r\n");
                        }
                        if (!res.Content.Headers.Contains("Content-Length"))
                        {
                            resp.Append($"Content-Length: {result.Length}\r\n");
                        }
                        resp.Append($"Date: {DateTime.Now}\r\n");
                        resp.Append("Connection:close\r\n\r\n");

                        var response = Encoding.UTF8.GetBytes(resp.ToString()).ToList();
                        response.AddRange(result);

                        //先gzip压缩  再转为16进制字符串
                        var body = DataHelper.Compress(response.ToArray());
                        var pack = new PackJson()
                        {
                            Host         = packJson.Host,
                            UserId       = packJson.UserId,
                            Content      = body,
                            ResponseInfo = $"{map.name} {packJson.Method} {packJson.Route} {(int)res.StatusCode} {res.StatusCode.ToString()}"
                        };
                        var json      = JsonHelper.Instance.Serialize(pack);
                        var jsonBytes = Encoding.UTF8.GetBytes(json);
                        //请求头 01 03 长度(4)
                        var sendBytes = new List <byte>()
                        {
                            0x1, 0x3
                        };
                        sendBytes.AddRange(BitConverter.GetBytes(jsonBytes.Length).Reverse());
                        sendBytes.AddRange(jsonBytes);
                        NatClient.Send(sendBytes.ToArray());
                        HandleLog.WriteLine(pack.ResponseInfo);
                    }
                }
                catch (Exception ex)
                {
                    HandleLog.WriteLine($"处理请求异常:{ex}");
                }
            });
        }
Exemplo n.º 13
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);
            }
        }