From 3e5020b890a0e29ff2f050475553a4f60875be0e Mon Sep 17 00:00:00 2001 From: SpringHgui <740360381@qq.com> Date: Sun, 1 Aug 2021 18:32:32 +0800 Subject: [PATCH] 11 --- .gitignore | 1 + FastTunnel.Client/Program.cs | 10 +- FastTunnel.Client/appsettings.json | 7 +- FastTunnel.Core/Client/FastTunnelClient.cs | 137 +++++++++++------- FastTunnel.Core/Client/FastTunnelServer.cs | 30 ++-- FastTunnel.Core/Client/IFastTunnelClient.cs | 3 +- FastTunnel.Core/Config/DefaultClientConfig.cs | 2 +- FastTunnel.Core/Config/DefaultServerConfig.cs | 4 +- FastTunnel.Core/Config/IClientConfig.cs | 2 +- FastTunnel.Core/Config/IServerConfig.cs | 4 +- ...{SSHDispatcher.cs => ForwardDispatcher.cs} | 16 +- .../Dispatchers/IListenerDispatcher.cs | 3 +- .../Extensions/MessageExtension.cs | 12 -- .../Extensions/ObjectExtensions.cs | 12 +- .../Extensions/ServicesExtensions.cs | 2 +- .../Extensions/WebSocketExtension.cs | 30 ++++ FastTunnel.Core/FastTunnel.Core.csproj | 5 +- .../FastTunnelForwarderHttpClientFactory.cs | 12 +- FastTunnel.Core/Forwarder/IReadWriteStream.cs | 15 ++ .../MiddleWare/FastTunnelClientHandler.cs | 85 ++++++++++- .../MiddleWare/FastTunnelSwapHandler.cs | 60 ++++++++ .../Forwarder/SocketReadWriteStream.cs | 28 ++++ FastTunnel.Core/Forwarder/WebSocketStream.cs | 112 ++++++++++++++ .../Forwarder/WebSocktReadWriteStream.cs | 35 +++++ .../Handlers/Client/ClientHeartHandler.cs | 5 +- .../Handlers/Client/HttpRequestHandler.cs | 78 +++++++--- .../Handlers/Client/IClientHandler.cs | 4 +- FastTunnel.Core/Handlers/Client/LogHandler.cs | 8 +- ...{NewSSHHandler.cs => NewForwardHandler.cs} | 16 +- .../Handlers/Server/ConfigHandler.cs | 16 -- .../Handlers/Server/HeartMessageHandler.cs | 9 +- .../Handlers/Server/IClientMessageHandler.cs | 7 +- .../Handlers/Server/IConfigHandler.cs | 13 -- .../Handlers/Server/LoginHandler.cs | 72 +++------ .../Handlers/Server/SwapMessageHandler.cs | 7 +- FastTunnel.Core/HeaderConst.cs | 19 +++ FastTunnel.Core/Listener/ClientListenerV2.cs | 2 +- FastTunnel.Core/Listener/PortProxyListener.cs | 2 +- .../Models/{SSHConfig.cs => ForwardConfig.cs} | 2 +- ...{SSHHandlerArg.cs => ForwardHandlerArg.cs} | 4 +- .../Models/{SSHInfo.cs => ForwardInfo.cs} | 7 +- .../Models/Massage/HeartMassage.cs | 1 + .../Models/Massage/LogInMassage.cs | 2 +- .../NewForwardMessage.cs} | 4 +- FastTunnel.Core/Models/Protocol.cs | 11 -- FastTunnel.Core/Models/TunnelClient.cs | 90 ++++++++++++ FastTunnel.Core/Models/WebInfo.cs | 4 +- FastTunnel.Core/Protocol/TunnelProtocol.cs | 40 +++++ .../Services/ServiceFastTunnelClient.cs | 4 +- .../Services/ServiceFastTunnelServer.cs | 2 - FastTunnel.Core/Sockets/DefultClientSocket.cs | 51 +++++++ .../Sockets/IFastTunnelClientSocket.cs | 22 +++ .../Sockets/ReadWriteStreamSwap.cs | 99 +++++++++++++ FastTunnel.Core/Sockets/SocketSwap.cs | 1 + FastTunnel.Core/Sockets/StreamSwap.cs | 98 +++++++++++++ FastTunnel.Core/Views/Home/index.cshtml | 11 -- FastTunnel.Server/.config/dotnet-tools.json | 12 -- FastTunnel.Server/FastTunnel.Server.csproj | 4 +- FastTunnel.Server/Startup.cs | 11 ++ FastTunnel.Server/config/appsettings.json | 8 +- 60 files changed, 1085 insertions(+), 288 deletions(-) rename FastTunnel.Core/Dispatchers/{SSHDispatcher.cs => ForwardDispatcher.cs} (59%) delete mode 100644 FastTunnel.Core/Extensions/MessageExtension.cs create mode 100644 FastTunnel.Core/Extensions/WebSocketExtension.cs create mode 100644 FastTunnel.Core/Forwarder/IReadWriteStream.cs create mode 100644 FastTunnel.Core/Forwarder/MiddleWare/FastTunnelSwapHandler.cs create mode 100644 FastTunnel.Core/Forwarder/SocketReadWriteStream.cs create mode 100644 FastTunnel.Core/Forwarder/WebSocketStream.cs create mode 100644 FastTunnel.Core/Forwarder/WebSocktReadWriteStream.cs rename FastTunnel.Core/Handlers/Client/{NewSSHHandler.cs => NewForwardHandler.cs} (69%) delete mode 100644 FastTunnel.Core/Handlers/Server/ConfigHandler.cs delete mode 100644 FastTunnel.Core/Handlers/Server/IConfigHandler.cs create mode 100644 FastTunnel.Core/HeaderConst.cs rename FastTunnel.Core/Models/{SSHConfig.cs => ForwardConfig.cs} (94%) rename FastTunnel.Core/Models/{SSHHandlerArg.cs => ForwardHandlerArg.cs} (67%) rename FastTunnel.Core/Models/{SSHInfo.cs => ForwardInfo.cs} (58%) rename FastTunnel.Core/Models/{NewSSHRequest.cs => Massage/NewForwardMessage.cs} (61%) delete mode 100644 FastTunnel.Core/Models/Protocol.cs create mode 100644 FastTunnel.Core/Models/TunnelClient.cs create mode 100644 FastTunnel.Core/Protocol/TunnelProtocol.cs create mode 100644 FastTunnel.Core/Sockets/DefultClientSocket.cs create mode 100644 FastTunnel.Core/Sockets/IFastTunnelClientSocket.cs create mode 100644 FastTunnel.Core/Sockets/ReadWriteStreamSwap.cs create mode 100644 FastTunnel.Core/Sockets/StreamSwap.cs delete mode 100644 FastTunnel.Core/Views/Home/index.cshtml delete mode 100644 FastTunnel.Server/.config/dotnet-tools.json diff --git a/.gitignore b/.gitignore index 82e1eb2..cd61c10 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,4 @@ publish /SuiDao.Client/Properties/PublishProfiles/FolderProfile.pubxml /FastTunnel.Core/*.user /build +/FastTunnel.Server/.config diff --git a/FastTunnel.Client/Program.cs b/FastTunnel.Client/Program.cs index 2acd84f..3d7fb6b 100644 --- a/FastTunnel.Client/Program.cs +++ b/FastTunnel.Client/Program.cs @@ -3,6 +3,7 @@ using Microsoft.Extensions.Logging; using FastTunnel.Core.Extensions; using Microsoft.Extensions.DependencyInjection; using FastTunnel.Core.Client; +using System; namespace FastTunnel.Client { @@ -10,7 +11,14 @@ namespace FastTunnel.Client { public static void Main(string[] args) { - CreateHostBuilder(args).Build().Run(); + try + { + CreateHostBuilder(args).Build().Run(); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } } public static IHostBuilder CreateHostBuilder(string[] args) => diff --git a/FastTunnel.Client/appsettings.json b/FastTunnel.Client/appsettings.json index c22829e..7d8ed91 100644 --- a/FastTunnel.Client/appsettings.json +++ b/FastTunnel.Client/appsettings.json @@ -13,7 +13,7 @@ //"ServerAddr": "my.com", "ServerAddr": "127.0.0.1", // 服务端监听的通信端口 - "ServerPort": 1271 + "ServerPort": 1270 }, "Webs": [ { @@ -37,11 +37,12 @@ ], /** - * ssh穿透,ssh访问内网主机/mysql/erp/等任何服务 + * 端口转发 + * 访问内网主机/mysql/erp/等任何TCP协议服务 * 远程linux示例:#ssh -oPort=12701 {root}@{ServerAddr} ServerAddr 填入服务端ip,root对应内网用户名 * 通过服务端返回的访问方式进行访问即可 */ - "SSH": [ + "Forward": [ { "LocalIp": "127.0.0.1", "LocalPort": 8090, diff --git a/FastTunnel.Core/Client/FastTunnelClient.cs b/FastTunnel.Core/Client/FastTunnelClient.cs index a717f76..ccdeed0 100644 --- a/FastTunnel.Core/Client/FastTunnelClient.cs +++ b/FastTunnel.Core/Client/FastTunnelClient.cs @@ -1,6 +1,4 @@ -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using FastTunnel.Core.Config; +using FastTunnel.Core.Config; using FastTunnel.Core.Models; using System; using System.Net.Sockets; @@ -15,12 +13,15 @@ using Microsoft.Extensions.Configuration; using FastTunnel.Core.Server; using FastTunnel.Core.Sockets; using Microsoft.Extensions.Options; +using System.Net.WebSockets; +using System.Text.Json; namespace FastTunnel.Core.Client { public class FastTunnelClient : IFastTunnelClient { - Socket _client; + //Socket _client; + private IFastTunnelClientSocket socket; protected ILogger _logger; @@ -31,19 +32,19 @@ namespace FastTunnel.Core.Client int reTrySpan = 10 * 1000; // 登陆失败后重试间隔 HttpRequestHandler _newCustomerHandler; - NewSSHHandler _newSSHHandler; + NewForwardHandler _newSSHHandler; LogHandler _logHandler; ClientHeartHandler _clientHeartHandler; - Func lastLogin; Message loginMsg; protected readonly IOptionsMonitor _configuration; + private readonly CancellationTokenSource cancellationTokenSource = new(); public SuiDaoServer Server { get; protected set; } public FastTunnelClient( ILogger logger, HttpRequestHandler newCustomerHandler, - NewSSHHandler newSSHHandler, LogHandler logHandler, + NewForwardHandler newSSHHandler, LogHandler logHandler, IOptionsMonitor configuration, ClientHeartHandler clientHeartHandler) { @@ -60,7 +61,7 @@ namespace FastTunnel.Core.Client timer_heart.Elapsed += HeartElapsed; } - private void reConn() + private async Task reConnAsync() { Close(); @@ -71,7 +72,7 @@ namespace FastTunnel.Core.Client Thread.Sleep(reTrySpan); _logger.LogInformation("登录重试..."); - _client = lastLogin.Invoke(); + socket = await loginAsync(CancellationToken.None); break; } @@ -90,12 +91,12 @@ namespace FastTunnel.Core.Client try { - _client.SendCmd(new Message { MessageType = MessageType.Heart, Content = null }); + socket.SendAsync(new Message { MessageType = MessageType.Heart, Content = null }, cancellationTokenSource.Token).Wait(); } catch (Exception) { // 与服务端断开连接 - reConn(); + reConnAsync(); } finally { @@ -108,43 +109,77 @@ namespace FastTunnel.Core.Client /// /// /// 自定义登录信息,可进行扩展业务 - public void Start() + public async Task StartAsync(CancellationToken cancellationToken) { - _logger.LogInformation("===== FastTunnel Client Start ====="); + CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, this.cancellationTokenSource.Token); - lastLogin = login; + _logger.LogInformation("===== FastTunnel Client Start ====="); try { - _client = lastLogin.Invoke(); + socket = await loginAsync(cancellationToken); } catch (Exception ex) { _logger.LogError(ex.Message); - reConn(); + reConnAsync(); return; } _ = connSuccessAsync(); } + //protected virtual Socket login() + //{ + // Server = _configuration.CurrentValue.Server; - protected virtual Socket login() + // DnsSocket _client = null; + // _logger.LogInformation($"正在连接服务端 {Server.ServerAddr}:{Server.ServerPort}"); + + // try + // { + // // 连接到的目标IP + // if (_client == null) + // { + // _client = new DnsSocket(Server.ServerAddr, Server.ServerPort); + // } + + // _client.Connect(); + + // _logger.LogInformation("连接成功"); + // } + // catch (Exception) + // { + // throw; + // } + + // loginMsg = new Message + // { + // MessageType = MessageType.C_LogIn, + // Content = new LogInMassage + // { + // Webs = _configuration.CurrentValue.Webs, + // SSH = _configuration.CurrentValue.SSH, + // }, + // }; + + // // 登录 + // _client.Send(loginMsg); + + // return _client.Socket; + //} + protected virtual async Task loginAsync(CancellationToken cancellationToken) { Server = _configuration.CurrentValue.Server; - - DnsSocket _client = null; _logger.LogInformation($"正在连接服务端 {Server.ServerAddr}:{Server.ServerPort}"); try { // 连接到的目标IP - if (_client == null) - { - _client = new DnsSocket(Server.ServerAddr, Server.ServerPort); - } + socket = new DefultClientSocket(); - _client.Connect(); + await socket.ConnectAsync( + new Uri($"ws://{_configuration.CurrentValue.Server.ServerAddr}:{_configuration.CurrentValue.Server.ServerPort}"), cancellationToken); _logger.LogInformation("连接成功"); } @@ -159,29 +194,19 @@ namespace FastTunnel.Core.Client Content = new LogInMassage { Webs = _configuration.CurrentValue.Webs, - SSH = _configuration.CurrentValue.SSH, + SSH = _configuration.CurrentValue.Forwards, }, }; // 登录 - _client.Send(loginMsg); - - return _client.Socket; + await socket.SendAsync(loginMsg, cancellationToken); + return socket; } void Close() { timer_heart.Stop(); - - try - { - _client?.Shutdown(SocketShutdown.Both); - } - catch (Exception) - { - } - - _client?.Close(); + socket.CloseAsync(); } private async Task connSuccessAsync() @@ -192,7 +217,7 @@ namespace FastTunnel.Core.Client timer_heart.Start(); var th = new Thread(ReceiveServer); - th.Start(_client); + th.Start(socket); // await new PipeHepler(_client, ProceccLine).ProcessLinesAsync(); } @@ -205,7 +230,7 @@ namespace FastTunnel.Core.Client private void ReceiveServer(object obj) { - var client = obj as Socket; + var client = obj as IFastTunnelClientSocket; byte[] buffer = new byte[1024]; string lastBuffer = string.Empty; @@ -215,10 +240,10 @@ namespace FastTunnel.Core.Client { try { - n = client.Receive(buffer); + n = client.ReceiveAsync(buffer, cancellationTokenSource.Token).GetAwaiter().GetResult(); if (n == 0) { - client.Shutdown(SocketShutdown.Both); + client.CloseAsync(); break; } } @@ -290,36 +315,38 @@ namespace FastTunnel.Core.Client _logger.LogInformation("stop receive from server"); } - private void HandleServerRequest(string words) + private void HandleServerRequest(string lineCmd) { Task.Run(() => { - var Msg = JsonConvert.DeserializeObject>(words); - if (Msg.MessageType != MessageType.Heart) - { - _logger.LogDebug($"HandleServerRequest {words}"); - } + var cmds = lineCmd.Split("||"); + var type = cmds[0]; + TunnelMassage msg = null; IClientHandler handler; - switch (Msg.MessageType) + switch (type) { - case MessageType.Heart: + case "Heart": handler = _clientHeartHandler; + msg = JsonSerializer.Deserialize(cmds[1]); break; - case MessageType.S_NewCustomer: + case "S_NewCustomer": handler = _newCustomerHandler; + msg = JsonSerializer.Deserialize(cmds[1]); break; - case MessageType.S_NewSSH: + case "S_NewSSH": handler = _newSSHHandler; + msg = JsonSerializer.Deserialize(cmds[1]); break; - case MessageType.Log: + case "Log": handler = _logHandler; + msg = JsonSerializer.Deserialize(cmds[1]); break; default: - throw new Exception($"未处理的消息:{Msg.MessageType} {Msg.Content}"); + throw new Exception($"未处理的消息:{lineCmd}"); } - handler.HandlerMsg(this, Msg); + handler.HandlerMsgAsync(this, msg); }); } } diff --git a/FastTunnel.Core/Client/FastTunnelServer.cs b/FastTunnel.Core/Client/FastTunnelServer.cs index e2d2ede..542c4fa 100644 --- a/FastTunnel.Core/Client/FastTunnelServer.cs +++ b/FastTunnel.Core/Client/FastTunnelServer.cs @@ -27,35 +27,37 @@ namespace FastTunnel.Core.Client public ConcurrentDictionary WebList { get; private set; } = new ConcurrentDictionary(); - public ConcurrentDictionary> SSHList { get; private set; } - = new ConcurrentDictionary>(); + public ConcurrentDictionary> SSHList { get; private set; } + = new ConcurrentDictionary>(); readonly ILogger _logger; - readonly ClientListenerV2 clientListener; - readonly HttpListenerV2 http_listener; + //readonly ClientListenerV2 clientListener; + //readonly HttpListenerV2 http_listener; public readonly IOptionsMonitor serverOption; + public IProxyConfigProvider proxyConfig; public FastTunnelServer(ILogger logger, IProxyConfigProvider proxyConfig, IOptionsMonitor serverSettings) { _logger = logger; serverOption = serverSettings; + this.proxyConfig = proxyConfig; - clientListener = new ClientListenerV2(this, proxyConfig, "0.0.0.0", serverOption.CurrentValue.BindPort, _logger); - http_listener = new HttpListenerV2("0.0.0.0", serverOption.CurrentValue.WebProxyPort, _logger); + // clientListener = new ClientListenerV2(this, proxyConfig, "0.0.0.0", serverOption.CurrentValue.BindPort, _logger); + // http_listener = new HttpListenerV2("0.0.0.0", serverOption.CurrentValue.WebProxyPort, _logger); } public void Run() { _logger.LogInformation("===== FastTunnel Server Starting ====="); - listenClient(); - //listenHttp(); + // listenClient(); + // listenHttp(); } - private void listenClient() - { - clientListener.Start(); - } + //private void listenClient() + //{ + // clientListener.Start(); + //} //private void listenHttp() //{ @@ -66,8 +68,8 @@ namespace FastTunnel.Core.Client { _logger.LogInformation("===== FastTunnel Server Stoping ====="); - clientListener.Stop(); - http_listener.Stop(); + //clientListener.Stop(); + //http_listener.Stop(); } } } diff --git a/FastTunnel.Core/Client/IFastTunnelClient.cs b/FastTunnel.Core/Client/IFastTunnelClient.cs index 27c3c9d..e052f04 100644 --- a/FastTunnel.Core/Client/IFastTunnelClient.cs +++ b/FastTunnel.Core/Client/IFastTunnelClient.cs @@ -2,12 +2,13 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using System.Threading; using System.Threading.Tasks; namespace FastTunnel.Core.Client { public interface IFastTunnelClient { - void Start(); + Task StartAsync(CancellationToken cancellationToken); } } diff --git a/FastTunnel.Core/Config/DefaultClientConfig.cs b/FastTunnel.Core/Config/DefaultClientConfig.cs index 79fcdd1..d71aff1 100644 --- a/FastTunnel.Core/Config/DefaultClientConfig.cs +++ b/FastTunnel.Core/Config/DefaultClientConfig.cs @@ -12,6 +12,6 @@ namespace FastTunnel.Core.Config public IEnumerable Webs { get; set; } - public IEnumerable SSH { get; set; } + public IEnumerable Forwards { get; set; } } } \ No newline at end of file diff --git a/FastTunnel.Core/Config/DefaultServerConfig.cs b/FastTunnel.Core/Config/DefaultServerConfig.cs index f7955ed..0ace5d4 100644 --- a/FastTunnel.Core/Config/DefaultServerConfig.cs +++ b/FastTunnel.Core/Config/DefaultServerConfig.cs @@ -7,7 +7,7 @@ namespace FastTunnel.Core.Config { public class DefaultServerConfig : IServerConfig { - public int BindPort { get; set; } + // public int BindPort { get; set; } public string WebDomain { get; set; } @@ -17,6 +17,6 @@ namespace FastTunnel.Core.Config public bool WebHasNginxProxy { get; set; } = false; - public bool SSHEnabled { get; set; } = false; + public bool EnableForward { get; set; } = false; } } diff --git a/FastTunnel.Core/Config/IClientConfig.cs b/FastTunnel.Core/Config/IClientConfig.cs index 8e00420..ebc76fc 100644 --- a/FastTunnel.Core/Config/IClientConfig.cs +++ b/FastTunnel.Core/Config/IClientConfig.cs @@ -13,7 +13,7 @@ namespace FastTunnel.Core.Config public IEnumerable Webs { get; set; } - public IEnumerable SSH { get; set; } + public IEnumerable Forwards { get; set; } } public class SuiDaoServer diff --git a/FastTunnel.Core/Config/IServerConfig.cs b/FastTunnel.Core/Config/IServerConfig.cs index c88d076..a99cc17 100644 --- a/FastTunnel.Core/Config/IServerConfig.cs +++ b/FastTunnel.Core/Config/IServerConfig.cs @@ -6,7 +6,7 @@ namespace FastTunnel.Core.Config { public interface IServerConfig { - int BindPort { get; set; } + // int BindPort { get; set; } #region Web相关配置 @@ -28,6 +28,6 @@ namespace FastTunnel.Core.Config #endregion - bool SSHEnabled { get; set; } + bool EnableForward { get; set; } } } diff --git a/FastTunnel.Core/Dispatchers/SSHDispatcher.cs b/FastTunnel.Core/Dispatchers/ForwardDispatcher.cs similarity index 59% rename from FastTunnel.Core/Dispatchers/SSHDispatcher.cs rename to FastTunnel.Core/Dispatchers/ForwardDispatcher.cs index 4d6878e..a13960f 100644 --- a/FastTunnel.Core/Dispatchers/SSHDispatcher.cs +++ b/FastTunnel.Core/Dispatchers/ForwardDispatcher.cs @@ -6,27 +6,31 @@ using FastTunnel.Core.Server; using System; using System.Collections.Generic; using System.Net.Sockets; +using System.Net.WebSockets; using System.Text; +using System.Threading; +using System.Threading.Tasks; namespace FastTunnel.Core.Dispatchers { - public class SSHDispatcher : IListenerDispatcher + public class ForwardDispatcher : IListenerDispatcher { private FastTunnelServer _server; - private Socket _client; - private SSHConfig _config; + private WebSocket _client; + private ForwardConfig _config; - public SSHDispatcher(FastTunnelServer server, Socket client, SSHConfig config) + public ForwardDispatcher(FastTunnelServer server, WebSocket client, ForwardConfig config) { _server = server; _client = client; _config = config; } - public void Dispatch(Socket _socket) + public async Task DispatchAsync(Socket _socket) { var msgid = Guid.NewGuid().ToString(); - _client.SendCmd(new Message { MessageType = MessageType.S_NewSSH, Content = new NewSSHRequest { MsgId = msgid, SSHConfig = _config } }); + await _client.SendCmdAsync(new Message { MessageType = MessageType.S_NewSSH, Content = new NewForwardMessage { MsgId = msgid, SSHConfig = _config } }); + _server.RequestTemp.TryAdd(msgid, new NewRequest { CustomerClient = _socket, diff --git a/FastTunnel.Core/Dispatchers/IListenerDispatcher.cs b/FastTunnel.Core/Dispatchers/IListenerDispatcher.cs index d543414..d1ec089 100644 --- a/FastTunnel.Core/Dispatchers/IListenerDispatcher.cs +++ b/FastTunnel.Core/Dispatchers/IListenerDispatcher.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; using System.Net.Sockets; using System.Text; +using System.Threading.Tasks; namespace FastTunnel.Core.Dispatchers { @@ -10,6 +11,6 @@ namespace FastTunnel.Core.Dispatchers { void Dispatch(AsyncUserToken token, string words); - void Dispatch(Socket httpClient); + Task DispatchAsync(Socket httpClient); } } diff --git a/FastTunnel.Core/Extensions/MessageExtension.cs b/FastTunnel.Core/Extensions/MessageExtension.cs deleted file mode 100644 index a46f527..0000000 --- a/FastTunnel.Core/Extensions/MessageExtension.cs +++ /dev/null @@ -1,12 +0,0 @@ -using Newtonsoft.Json; -using FastTunnel.Core.Models; -using System; -using System.Collections.Generic; -using System.Text; - -namespace FastTunnel.Core.Extensions -{ - public static class MessageExtension - { - } -} diff --git a/FastTunnel.Core/Extensions/ObjectExtensions.cs b/FastTunnel.Core/Extensions/ObjectExtensions.cs index 82cddee..d9b6187 100644 --- a/FastTunnel.Core/Extensions/ObjectExtensions.cs +++ b/FastTunnel.Core/Extensions/ObjectExtensions.cs @@ -1,7 +1,7 @@ -using Newtonsoft.Json; -using System; +using System; using System.Collections.Generic; using System.Text; +using System.Text.Json; namespace FastTunnel.Core.Extensions { @@ -9,7 +9,13 @@ namespace FastTunnel.Core.Extensions { public static string ToJson(this object message) { - return JsonConvert.SerializeObject(message, Formatting.None); + if (message == null) + { + return null; + } + + var jsonOptions = new JsonSerializerOptions { WriteIndented = false }; + return JsonSerializer.Serialize(message, message.GetType(), jsonOptions); } } } diff --git a/FastTunnel.Core/Extensions/ServicesExtensions.cs b/FastTunnel.Core/Extensions/ServicesExtensions.cs index 7e016b5..c2e4870 100644 --- a/FastTunnel.Core/Extensions/ServicesExtensions.cs +++ b/FastTunnel.Core/Extensions/ServicesExtensions.cs @@ -37,7 +37,7 @@ namespace FastTunnel.Core.Extensions .AddSingleton() .AddSingleton() .AddSingleton() - .AddSingleton(); + .AddSingleton(); services.AddHostedService(); } diff --git a/FastTunnel.Core/Extensions/WebSocketExtension.cs b/FastTunnel.Core/Extensions/WebSocketExtension.cs new file mode 100644 index 0000000..c8c6fac --- /dev/null +++ b/FastTunnel.Core/Extensions/WebSocketExtension.cs @@ -0,0 +1,30 @@ +using FastTunnel.Core.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Sockets; +using System.Net.WebSockets; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace FastTunnel.Core.Extensions +{ + public static class WebSocketExtension + { + public static async Task SendCmdAsync(this WebSocket socket, Message message, + WebSocketMessageType webSocketMessage, bool end, CancellationToken cancellationToken) + where T : TunnelMassage + { + var msg = Encoding.UTF8.GetBytes($"{message.MessageType.ToString()}||{message.Content.ToJson()}\n"); + await socket.SendAsync(msg, webSocketMessage, end, cancellationToken); + } + + public static async Task SendCmdAsync(this WebSocket socket, Message message) + where T : TunnelMassage + { + var msg = Encoding.UTF8.GetBytes($"{message.MessageType.ToString()}||{message.Content.ToJson()}\n"); + await socket.SendAsync(msg, WebSocketMessageType.Binary, false, CancellationToken.None); + } + } +} diff --git a/FastTunnel.Core/FastTunnel.Core.csproj b/FastTunnel.Core/FastTunnel.Core.csproj index adeeb08..f619b16 100644 --- a/FastTunnel.Core/FastTunnel.Core.csproj +++ b/FastTunnel.Core/FastTunnel.Core.csproj @@ -22,14 +22,17 @@ + + + @@ -39,7 +42,7 @@ - + diff --git a/FastTunnel.Core/Forwarder/FastTunnelForwarderHttpClientFactory.cs b/FastTunnel.Core/Forwarder/FastTunnelForwarderHttpClientFactory.cs index 4290eb5..53dd8d3 100644 --- a/FastTunnel.Core/Forwarder/FastTunnelForwarderHttpClientFactory.cs +++ b/FastTunnel.Core/Forwarder/FastTunnelForwarderHttpClientFactory.cs @@ -2,7 +2,6 @@ using FastTunnel.Core.Extensions; using FastTunnel.Core.Models; using Microsoft.Extensions.Logging; -using Newtonsoft.Json.Linq; using System; using System.Collections.Concurrent; using System.Collections.Generic; @@ -53,7 +52,6 @@ namespace FastTunnel.Core.Forwarder public async ValueTask proxyAsync(string host, CancellationToken cancellation) { - WebInfo web; if (!_fastTunnelServer.WebList.TryGetValue(host, out web)) { @@ -63,16 +61,18 @@ namespace FastTunnel.Core.Forwarder try { var RequestId = Guid.NewGuid().ToString().Replace("-", ""); - _logger.LogDebug($"[send swap]:{RequestId}"); + _logger.LogInformation($"[发送swap指令]:{RequestId}"); // 发送指令给客户端,等待建立隧道 - web.Socket.SendCmd(new Message { MessageType = MessageType.S_NewCustomer, Content = new NewCustomerMassage { MsgId = RequestId, WebConfig = web.WebConfig } }); + await web.Socket.SendCmdAsync(new Message { MessageType = MessageType.S_NewCustomer, Content = new NewCustomerMassage { MsgId = RequestId, WebConfig = web.WebConfig } }); // TODO:超时处理 TaskCompletionSource task = new(cancellation); - _fastTunnelServer.ResponseTasks.TryAdd(RequestId, task); - return await task.Task; + + var res = await task.Task; + _logger.LogInformation($"[收到swap指令]:{RequestId}"); + return res; } catch (Exception ex) { diff --git a/FastTunnel.Core/Forwarder/IReadWriteStream.cs b/FastTunnel.Core/Forwarder/IReadWriteStream.cs new file mode 100644 index 0000000..00d5558 --- /dev/null +++ b/FastTunnel.Core/Forwarder/IReadWriteStream.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace FastTunnel.Core.Forwarder +{ + public interface IReadWriteStream + { + int Read(byte[] buffer); + + void Write(byte[] buffer, int index, int num); + } +} diff --git a/FastTunnel.Core/Forwarder/MiddleWare/FastTunnelClientHandler.cs b/FastTunnel.Core/Forwarder/MiddleWare/FastTunnelClientHandler.cs index 42f13db..e62fa66 100644 --- a/FastTunnel.Core/Forwarder/MiddleWare/FastTunnelClientHandler.cs +++ b/FastTunnel.Core/Forwarder/MiddleWare/FastTunnelClientHandler.cs @@ -1,24 +1,103 @@ -using Microsoft.AspNetCore.Http; +using FastTunnel.Core.Client; +using FastTunnel.Core.Forwarder; +using FastTunnel.Core.Models; +using Microsoft.AspNetCore.Connections.Features; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Logging; using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Net.WebSockets; using System.Text; using System.Threading.Tasks; +using Yarp.ReverseProxy.Configuration; namespace FastTunnel.Core.MiddleWares { public class FastTunnelClientHandler { - public static async Task Handle(HttpContext context, Func next) + ILogger logger; + FastTunnelServer fastTunnelServer; + + public FastTunnelClientHandler(ILogger logger, FastTunnelServer fastTunnelServer) { - if (!context.WebSockets.IsWebSocketRequest) + this.logger = logger; + this.fastTunnelServer = fastTunnelServer; + } + + public async Task Handle(HttpContext context, Func next) + { + if (!context.WebSockets.IsWebSocketRequest + || !context.Request.Headers.TryGetValue(HeaderConst.FASTTUNNEL_FLAG, out var version) + || !context.Request.Headers.TryGetValue(HeaderConst.FASTTUNNEL_TYPE, out var type)) { await next(); return; }; + if (HeaderConst.TYPE_CLIENT.Equals(type)) + { + await Client(context, next); + } + else if (HeaderConst.TYPE_SWAP.Equals(type)) + { + await Swap(context, next); + } + else + { + logger.LogError($"参数异常,ConnectionType类型为{type}"); + } + } + private async Task Swap(HttpContext context, Func next) + { + var requestId = context.Request.Path.Value.Trim('/'); + if (!fastTunnelServer.ResponseTasks.TryGetValue(requestId, out var response)) + { + logger.LogError($"requestId不存在:{requestId}"); + return; + }; + + var lifetime = context.Features.Get(); + var transport = context.Features.Get(); + + if (lifetime == null || transport == null) + { + await next(); + return; + } + + using var stream = new WebSocketStream(lifetime, transport); + response.TrySetResult(stream); + + logger.LogInformation($"Swap Set {requestId}"); + + var closedAwaiter = new TaskCompletionSource(); + lifetime.ConnectionClosed.Register((task) => { (task as TaskCompletionSource).SetResult(); }, closedAwaiter); + + await closedAwaiter.Task; + + logger.LogInformation($"Swap Completion {requestId}"); + } + + private async Task Client(HttpContext context, Func next) + { + using var webSocket = await context.WebSockets.AcceptWebSocketAsync(); + var client = new TunnelClient(logger, webSocket, fastTunnelServer); + + this.logger.LogInformation($"{client} 客户端连接成功"); + + try + { + await client.ReviceAsync(); + } + catch (Exception ex) + { + logger.LogError(ex, "通信异常"); + } + + this.logger.LogInformation($"{client} 客户端断开连接"); } } } diff --git a/FastTunnel.Core/Forwarder/MiddleWare/FastTunnelSwapHandler.cs b/FastTunnel.Core/Forwarder/MiddleWare/FastTunnelSwapHandler.cs new file mode 100644 index 0000000..fdbb08e --- /dev/null +++ b/FastTunnel.Core/Forwarder/MiddleWare/FastTunnelSwapHandler.cs @@ -0,0 +1,60 @@ +using FastTunnel.Core.Client; +using FastTunnel.Core.MiddleWares; +using Microsoft.AspNetCore.Connections.Features; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace FastTunnel.Core.Forwarder.MiddleWare +{ + public class FastTunnelSwapHandler + { + ILogger logger; + FastTunnelServer fastTunnelServer; + + public FastTunnelSwapHandler(ILogger logger, FastTunnelServer fastTunnelServer) + { + this.logger = logger; + this.fastTunnelServer = fastTunnelServer; + } + + public async Task Handle(HttpContext context, Func next) + { + if (context.Request.Method != "PROXY") + { + await next(); + return; + } + + var requestId = context.Request.Path.Value.Trim('/'); + if (!fastTunnelServer.ResponseTasks.TryRemove(requestId, out var responseAwaiter)) + { + logger.LogError($"requestId不存在:{requestId}"); + return; + }; + + var lifetime = context.Features.Get(); + var transport = context.Features.Get(); + + if (lifetime == null || transport == null) + { + await next(); + return; + } + + logger.LogInformation($"Swap Set {requestId}"); + using var reverseConnection = new WebSocketStream(lifetime, transport); + responseAwaiter.TrySetResult(reverseConnection); + + var closedAwaiter = new TaskCompletionSource(); + lifetime.ConnectionClosed.Register((task) => { (task as TaskCompletionSource).SetResult(null); }, closedAwaiter); + + await closedAwaiter.Task; + logger.LogInformation($"Swap close {requestId}"); + } + } +} diff --git a/FastTunnel.Core/Forwarder/SocketReadWriteStream.cs b/FastTunnel.Core/Forwarder/SocketReadWriteStream.cs new file mode 100644 index 0000000..cd9a2c4 --- /dev/null +++ b/FastTunnel.Core/Forwarder/SocketReadWriteStream.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Sockets; +using System.Text; +using System.Threading.Tasks; + +namespace FastTunnel.Core.Forwarder +{ + public class SocketReadWriteStream : IReadWriteStream + { + Socket socket; + public SocketReadWriteStream(Socket socket) + { + this.socket = socket; + } + + public int Read(byte[] buffer) + { + return socket.Receive(buffer); + } + + public void Write(byte[] buffer, int index, int num) + { + socket.Send(buffer, index, num, SocketFlags.None); + } + } +} diff --git a/FastTunnel.Core/Forwarder/WebSocketStream.cs b/FastTunnel.Core/Forwarder/WebSocketStream.cs new file mode 100644 index 0000000..d7a35ef --- /dev/null +++ b/FastTunnel.Core/Forwarder/WebSocketStream.cs @@ -0,0 +1,112 @@ +using Microsoft; +using Microsoft.AspNetCore.Connections.Features; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net.WebSockets; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace FastTunnel.Core.Forwarder +{ + sealed class WebSocketStream : Stream + { + private readonly Stream readStream; + private readonly Stream wirteStream; + private readonly IConnectionLifetimeFeature lifetimeFeature; + + public WebSocketStream(IConnectionLifetimeFeature lifetimeFeature, IConnectionTransportFeature transportFeature) + { + this.readStream = transportFeature.Transport.Input.AsStream(); + this.wirteStream = transportFeature.Transport.Output.AsStream(); + this.lifetimeFeature = lifetimeFeature; + } + + public WebSocketStream(Stream stream) + { + this.readStream = stream; + this.wirteStream = stream; + this.lifetimeFeature = null; + } + + public override bool CanRead => true; + + public override bool CanSeek => false; + + public override bool CanWrite => true; + + public override long Length => throw new NotSupportedException(); + + public override long Position + { + get => throw new NotSupportedException(); + set => throw new NotSupportedException(); + } + + public override void Flush() + { + this.wirteStream.Flush(); + } + + public override Task FlushAsync(CancellationToken cancellationToken) + { + return this.wirteStream.FlushAsync(cancellationToken); + } + + public override long Seek(long offset, SeekOrigin origin) + { + throw new NotSupportedException(); + } + + public override void SetLength(long value) + { + throw new NotSupportedException(); + } + + public override int Read(byte[] buffer, int offset, int count) + { + return this.readStream.Read(buffer, offset, count); + } + public override void Write(byte[] buffer, int offset, int count) + { + this.wirteStream.Write(buffer, offset, count); + } + public override ValueTask ReadAsync(Memory buffer, CancellationToken cancellationToken = default) + { + return this.readStream.ReadAsync(buffer, cancellationToken); + } + + public override Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) + { + return this.readStream.ReadAsync(buffer, offset, count, cancellationToken); + } + + public override void Write(ReadOnlySpan buffer) + { + this.wirteStream.Write(buffer); + } + + public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) + { + return this.wirteStream.WriteAsync(buffer, offset, count, cancellationToken); + } + + public override async ValueTask WriteAsync(ReadOnlyMemory buffer, CancellationToken cancellationToken = default) + { + await this.wirteStream.WriteAsync(buffer, cancellationToken); + } + + protected override void Dispose(bool disposing) + { + this.lifetimeFeature?.Abort(); + } + + public override ValueTask DisposeAsync() + { + this.lifetimeFeature?.Abort(); + return ValueTask.CompletedTask; + } + } +} diff --git a/FastTunnel.Core/Forwarder/WebSocktReadWriteStream.cs b/FastTunnel.Core/Forwarder/WebSocktReadWriteStream.cs new file mode 100644 index 0000000..9bc0f1f --- /dev/null +++ b/FastTunnel.Core/Forwarder/WebSocktReadWriteStream.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using System.Net.WebSockets; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace FastTunnel.Core.Forwarder +{ + public class WebSocktReadWriteStream : IReadWriteStream + { + WebSocket webSocket; + public WebSocktReadWriteStream(WebSocket webSocket) + { + this.webSocket = webSocket; + } + + public int Read(byte[] buffer) + { + if (this.webSocket.CloseStatus.HasValue) + { + return 0; + } + + return webSocket.ReceiveAsync(buffer, CancellationToken.None).GetAwaiter().GetResult().Count; + } + + public void Write(byte[] buffer, int offset, int count) + { + this.webSocket.SendAsync(new ArraySegment(buffer, offset, count), WebSocketMessageType.Binary, true, CancellationToken.None); + } + } +} diff --git a/FastTunnel.Core/Handlers/Client/ClientHeartHandler.cs b/FastTunnel.Core/Handlers/Client/ClientHeartHandler.cs index 34610ba..440b5de 100644 --- a/FastTunnel.Core/Handlers/Client/ClientHeartHandler.cs +++ b/FastTunnel.Core/Handlers/Client/ClientHeartHandler.cs @@ -1,18 +1,19 @@ using FastTunnel.Core.Config; using FastTunnel.Core.Client; using FastTunnel.Core.Models; -using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; using System.Text; +using System.Threading.Tasks; namespace FastTunnel.Core.Handlers.Client { public class ClientHeartHandler : IClientHandler { - public void HandlerMsg(FastTunnelClient cleint, Message Msg) + public async Task HandlerMsgAsync(FastTunnelClient cleint, T Msg) where T : TunnelMassage { cleint.lastHeart = DateTime.Now; + await Task.Yield(); } } } diff --git a/FastTunnel.Core/Handlers/Client/HttpRequestHandler.cs b/FastTunnel.Core/Handlers/Client/HttpRequestHandler.cs index 5662479..6d0a390 100644 --- a/FastTunnel.Core/Handlers/Client/HttpRequestHandler.cs +++ b/FastTunnel.Core/Handlers/Client/HttpRequestHandler.cs @@ -1,7 +1,6 @@ using FastTunnel.Core.Config; using FastTunnel.Core.Client; using FastTunnel.Core.Models; -using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; using System.IO; @@ -12,6 +11,12 @@ using System.Threading.Tasks; using FastTunnel.Core.Sockets; using Microsoft.Extensions.Logging; using FastTunnel.Core.Utility.Extensions; +using System.Net.WebSockets; +using FastTunnel.Core.Forwarder; +using Microsoft; +using Microsoft.AspNetCore.DataProtection; +using FastTunnel.Core.Server; +using System.Data.Common; namespace FastTunnel.Core.Handlers.Client { @@ -24,9 +29,9 @@ namespace FastTunnel.Core.Handlers.Client _logger = logger; } - public void HandlerMsg(FastTunnelClient cleint, Message Msg) + public async Task HandlerMsgAsync(FastTunnelClient cleint, T Msg) where T : TunnelMassage { - var request = Msg.Content.ToObject(); + var request = Msg as NewCustomerMassage; if (request.MsgId.Contains("_")) { var interval = long.Parse(DateTime.Now.GetChinaTicks()) - long.Parse(request.MsgId.Split('_')[0]); @@ -34,10 +39,25 @@ namespace FastTunnel.Core.Handlers.Client _logger.LogDebug($"Start SwapMassage {request.MsgId} 服务端耗时:{interval}ms"); } + //var webSocket = new ClientWebSocket(); + //webSocket.Options.RemoteCertificateValidationCallback = delegate { return true; }; + //webSocket.Options.SetRequestHeader(HeaderConst.FASTTUNNEL_FLAG, "2.0.0"); + //webSocket.Options.SetRequestHeader(HeaderConst.FASTTUNNEL_TYPE, HeaderConst.TYPE_SWAP); + + //var uri = new Uri($"ws://{cleint.Server.ServerAddr}:{cleint.Server.ServerPort}/{request.MsgId}"); + //webSocket.ConnectAsync(uri, CancellationToken.None); + + await Task.Yield(); + var connecter = new DnsSocket(cleint.Server.ServerAddr, cleint.Server.ServerPort); connecter.Connect(); + // connecter.Send(new Message { MessageType = MessageType.C_SwapMsg, Content = new SwapMassage(request.MsgId) }); - connecter.Send(new Message { MessageType = MessageType.C_SwapMsg, Content = new SwapMassage(request.MsgId) }); + Stream serverConn = new NetworkStream(connecter.Socket, ownsSocket: true); + var reverse = $"PROXY /{request.MsgId} HTTP/1.1\r\nHost: {cleint.Server.ServerAddr}:{cleint.Server.ServerPort}\r\n\r\n"; + + var requestMsg = Encoding.ASCII.GetBytes(reverse); + serverConn.WriteAsync(requestMsg, CancellationToken.None).GetAwaiter().GetResult(); _logger.LogDebug($"连接server成功 {request.MsgId}"); var localConnecter = new DnsSocket(request.WebConfig.LocalIp, request.WebConfig.LocalPort); @@ -45,28 +65,25 @@ namespace FastTunnel.Core.Handlers.Client try { localConnecter.Connect(); - _logger.LogDebug($"连接本地成功 {request.MsgId}"); - - new SocketSwap(connecter.Socket, localConnecter.Socket, _logger, request.MsgId).StartSwap(); } catch (SocketException sex) { - localConnecter.Close(); if (sex.ErrorCode == 10061) { + _logger.LogInformation($"内网服务不存在:{request.WebConfig.LocalIp}:{request.WebConfig.LocalPort}"); // 内网的站点不存在或无法访问 - string statusLine = "HTTP/1.1 200 OK\r\n"; - string responseHeader = "Content-Type: text/html\r\n"; - byte[] responseBody; - responseBody = Encoding.UTF8.GetBytes(TunnelResource.Page_NoSite); + //string statusLine = "HTTP/1.1 200 OK\r\n"; + //string responseHeader = "Content-Type: text/html\r\n"; + //byte[] responseBody; + //responseBody = Encoding.UTF8.GetBytes(TunnelResource.Page_NoSite); - connecter.Send(Encoding.UTF8.GetBytes(statusLine)); - connecter.Send(Encoding.UTF8.GetBytes(responseHeader)); - connecter.Send(Encoding.UTF8.GetBytes("\r\n")); - connecter.Send(responseBody); + //connecter.Send(Encoding.UTF8.GetBytes(statusLine)); + //connecter.Send(Encoding.UTF8.GetBytes(responseHeader)); + //connecter.Send(Encoding.UTF8.GetBytes("\r\n")); + //connecter.Send(responseBody); - connecter.Socket.Disconnect(false); - connecter.Socket.Close(); + //connecter.Socket.Disconnect(false); + //connecter.Socket.Close(); return; } else @@ -79,6 +96,31 @@ namespace FastTunnel.Core.Handlers.Client localConnecter.Close(); throw; } + + _logger.LogDebug($"连接本地成功 {request.MsgId}"); + //var streamServer = new WebSocktReadWriteStream(webSocket); + //var streamLocal = new SocketReadWriteStream(localConnecter.Socket); + + var localConn = new NetworkStream(localConnecter.Socket, ownsSocket: true); + + _logger.LogDebug($"开始转发 {request.MsgId}"); + var taskX = serverConn.CopyToAsync(localConn, CancellationToken.None); + var taskY = localConn.CopyToAsync(serverConn, CancellationToken.None); + + await Task.WhenAny(taskX, taskY); + + try + { + localConn.Close(); + serverConn.Close(); + + _logger.LogDebug($"转发结束 {request.MsgId}"); + } + catch (Exception ex) + { + _logger.LogDebug(ex, $"转发结束 {request.MsgId}"); + } } + } } diff --git a/FastTunnel.Core/Handlers/Client/IClientHandler.cs b/FastTunnel.Core/Handlers/Client/IClientHandler.cs index 582bb48..52a5570 100644 --- a/FastTunnel.Core/Handlers/Client/IClientHandler.cs +++ b/FastTunnel.Core/Handlers/Client/IClientHandler.cs @@ -1,15 +1,15 @@ using FastTunnel.Core.Config; using FastTunnel.Core.Client; using FastTunnel.Core.Models; -using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; using System.Text; +using System.Threading.Tasks; namespace FastTunnel.Core.Handlers.Client { public interface IClientHandler { - public void HandlerMsg(FastTunnelClient cleint, Message Msg); + Task HandlerMsgAsync(FastTunnelClient cleint, T Msg) where T : TunnelMassage; } } diff --git a/FastTunnel.Core/Handlers/Client/LogHandler.cs b/FastTunnel.Core/Handlers/Client/LogHandler.cs index 5f73bc6..6381ffd 100644 --- a/FastTunnel.Core/Handlers/Client/LogHandler.cs +++ b/FastTunnel.Core/Handlers/Client/LogHandler.cs @@ -1,10 +1,10 @@ using FastTunnel.Core.Config; using FastTunnel.Core.Models; using Microsoft.Extensions.Logging; -using Newtonsoft.Json.Linq; using System; using FastTunnel.Core.Extensions; using FastTunnel.Core.Client; +using System.Threading.Tasks; namespace FastTunnel.Core.Handlers.Client { @@ -17,11 +17,13 @@ namespace FastTunnel.Core.Handlers.Client _logger = logger; } - public void HandlerMsg(FastTunnelClient cleint, Message Msg) + public async Task HandlerMsgAsync(FastTunnelClient cleint, T Msg) + where T : TunnelMassage { try { - var msg = Msg.Content.ToObject(); + await Task.Yield(); + var msg = Msg as LogMassage; switch (msg.MsgType) { diff --git a/FastTunnel.Core/Handlers/Client/NewSSHHandler.cs b/FastTunnel.Core/Handlers/Client/NewForwardHandler.cs similarity index 69% rename from FastTunnel.Core/Handlers/Client/NewSSHHandler.cs rename to FastTunnel.Core/Handlers/Client/NewForwardHandler.cs index bf0b62a..28e323c 100644 --- a/FastTunnel.Core/Handlers/Client/NewSSHHandler.cs +++ b/FastTunnel.Core/Handlers/Client/NewForwardHandler.cs @@ -1,33 +1,35 @@ using FastTunnel.Core.Config; using FastTunnel.Core.Client; using FastTunnel.Core.Models; -using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; using System.Text; using FastTunnel.Core.Sockets; using Microsoft.Extensions.Logging; +using System.Threading.Tasks; namespace FastTunnel.Core.Handlers.Client { - public class NewSSHHandler : IClientHandler + public class NewForwardHandler : IClientHandler { - ILogger _logger; - public NewSSHHandler(ILogger logger) + ILogger _logger; + public NewForwardHandler(ILogger logger) { _logger = logger; } - public void HandlerMsg(FastTunnelClient cleint, Message Msg) + public async Task HandlerMsgAsync(FastTunnelClient cleint, T Msg) + where T : TunnelMassage { - var request_ssh = Msg.Content.ToObject(); + var request_ssh = Msg as NewForwardMessage; + await Task.Yield(); + var connecter_ssh = new DnsSocket(cleint.Server.ServerAddr, cleint.Server.ServerPort); connecter_ssh.Connect(); connecter_ssh.Send(new Message { MessageType = MessageType.C_SwapMsg, Content = new SwapMassage(request_ssh.MsgId) }); var localConnecter_ssh = new DnsSocket(request_ssh.SSHConfig.LocalIp, request_ssh.SSHConfig.LocalPort); localConnecter_ssh.Connect(); - new SocketSwap(connecter_ssh.Socket, localConnecter_ssh.Socket, _logger, request_ssh.MsgId).StartSwap(); } } diff --git a/FastTunnel.Core/Handlers/Server/ConfigHandler.cs b/FastTunnel.Core/Handlers/Server/ConfigHandler.cs deleted file mode 100644 index 2911126..0000000 --- a/FastTunnel.Core/Handlers/Server/ConfigHandler.cs +++ /dev/null @@ -1,16 +0,0 @@ -using FastTunnel.Core.Models; -using Newtonsoft.Json.Linq; -using System; -using System.Collections.Generic; -using System.Text; - -namespace FastTunnel.Core.Handlers.Server -{ - public class ConfigHandler : IConfigHandler - { - public LogInMassage GetConfig(JObject content) - { - return content.ToObject(); - } - } -} diff --git a/FastTunnel.Core/Handlers/Server/HeartMessageHandler.cs b/FastTunnel.Core/Handlers/Server/HeartMessageHandler.cs index 2cd4579..4688500 100644 --- a/FastTunnel.Core/Handlers/Server/HeartMessageHandler.cs +++ b/FastTunnel.Core/Handlers/Server/HeartMessageHandler.cs @@ -1,11 +1,12 @@ using FastTunnel.Core.Client; using FastTunnel.Core.Extensions; using FastTunnel.Core.Models; -using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; using System.Net.Sockets; +using System.Net.WebSockets; using System.Text; +using System.Threading.Tasks; namespace FastTunnel.Core.Handlers.Server { @@ -13,9 +14,11 @@ namespace FastTunnel.Core.Handlers.Server { public bool NeedRecive => true; - public void HandlerMsg(FastTunnelServer server, Socket client, Message msg) + public async Task HandlerMsg(FastTunnelServer server, WebSocket client, T msg) + where T : TunnelMassage { - client.SendCmd(new Message() { MessageType = MessageType.Heart, Content = null }); + await client.SendCmdAsync(new Message() { MessageType = MessageType.Heart, Content = new HeartMassage { } }); + return NeedRecive; } } } diff --git a/FastTunnel.Core/Handlers/Server/IClientMessageHandler.cs b/FastTunnel.Core/Handlers/Server/IClientMessageHandler.cs index e206f99..11fcb05 100644 --- a/FastTunnel.Core/Handlers/Server/IClientMessageHandler.cs +++ b/FastTunnel.Core/Handlers/Server/IClientMessageHandler.cs @@ -1,10 +1,11 @@ using FastTunnel.Core.Client; using FastTunnel.Core.Models; -using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; using System.Net.Sockets; +using System.Net.WebSockets; using System.Text; +using System.Threading.Tasks; namespace FastTunnel.Core.Handlers { @@ -12,6 +13,8 @@ namespace FastTunnel.Core.Handlers { Boolean NeedRecive { get; } - void HandlerMsg(FastTunnelServer server, Socket client, Message msg); + Task HandlerMsg(FastTunnelServer server, WebSocket client, T msg) where T : TunnelMassage; + + //void HandlerMsg(FastTunnelServer server, Socket client, Message msg); } } \ No newline at end of file diff --git a/FastTunnel.Core/Handlers/Server/IConfigHandler.cs b/FastTunnel.Core/Handlers/Server/IConfigHandler.cs deleted file mode 100644 index 8a3f3ca..0000000 --- a/FastTunnel.Core/Handlers/Server/IConfigHandler.cs +++ /dev/null @@ -1,13 +0,0 @@ -using FastTunnel.Core.Models; -using Newtonsoft.Json.Linq; -using System; -using System.Collections.Generic; -using System.Text; - -namespace FastTunnel.Core.Handlers -{ - public interface IConfigHandler - { - LogInMassage GetConfig(JObject content); - } -} diff --git a/FastTunnel.Core/Handlers/Server/LoginHandler.cs b/FastTunnel.Core/Handlers/Server/LoginHandler.cs index ed609ec..f75edad 100644 --- a/FastTunnel.Core/Handlers/Server/LoginHandler.cs +++ b/FastTunnel.Core/Handlers/Server/LoginHandler.cs @@ -7,12 +7,13 @@ using FastTunnel.Core.Handlers.Server; using FastTunnel.Core.Listener; using FastTunnel.Core.Models; using Microsoft.Extensions.Logging; -using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; using System.Linq; using System.Net.Sockets; +using System.Net.WebSockets; using System.Text; +using System.Threading.Tasks; using Yarp.ReverseProxy.Configuration; using Yarp.Sample; @@ -23,7 +24,6 @@ namespace FastTunnel.Core.Handlers ILogger _logger; public bool NeedRecive => true; - IConfigHandler _configHandler; static object _locker = new object(); IProxyConfigProvider proxyConfig; @@ -32,47 +32,12 @@ namespace FastTunnel.Core.Handlers { this.proxyConfig = proxyConfig; this._logger = logger; - - var custome = FastTunnelGlobal.GetCustomHandler(); - this._configHandler = custome == null ? new ConfigHandler() : custome; } - public LogInMassage GetConfig(JObject content) - { - return _configHandler.GetConfig(content); - } - - public void HandlerMsg(FastTunnelServer server, Socket client, Message msg) - { - lock (_locker) - { - HandleLogin(server, client, GetConfig(msg.Content)); - } - } - - public void HandleLogin(FastTunnelServer server, Socket client, LogInMassage requet) + private async Task HandleLoginAsync(FastTunnelServer server, WebSocket client, LogInMassage requet) { bool hasTunnel = false; - var filters = FastTunnelGlobal.GetFilters(typeof(IAuthenticationFilter)); - if (filters.Count() > 0) - { - foreach (IAuthenticationFilter item in filters) - { - var result = item.Authentication(server, requet); - if (!result) - { - client.SendCmd(new Message - { - MessageType = MessageType.Log, - Content = new LogMassage(LogMsgType.Error, "认证失败") - }); - - return; - } - } - } - var sb = new StringBuilder($"{Environment.NewLine}=====隧道已建立成功,可通过以下方式访问内网服务====={Environment.NewLine}{Environment.NewLine}"); sb.Append($"穿透协议 | 映射关系(公网=>内网){Environment.NewLine}"); if (requet.Webs != null && requet.Webs.Count() > 0) @@ -114,11 +79,11 @@ namespace FastTunnel.Core.Handlers { try { - if (item.RemotePort.Equals(server.serverOption.CurrentValue.BindPort)) - { - _logger.LogError($"RemotePort can not be same with BindPort: {item.RemotePort}"); - continue; - } + //if (item.RemotePort.Equals(server.serverOption.CurrentValue.BindPort)) + //{ + // _logger.LogError($"RemotePort can not be same with BindPort: {item.RemotePort}"); + // continue; + //} if (item.RemotePort.Equals(server.serverOption.CurrentValue.WebProxyPort)) { @@ -126,20 +91,20 @@ namespace FastTunnel.Core.Handlers continue; } - SSHInfo old; + ForwardInfo old; if (server.SSHList.TryGetValue(item.RemotePort, out old)) { _logger.LogDebug($"Remove Listener {old.Listener.ListenIp}:{old.Listener.ListenPort}"); old.Listener.Stop(); - server.SSHList.TryRemove(item.RemotePort, out SSHInfo _); + server.SSHList.TryRemove(item.RemotePort, out ForwardInfo _); } var ls = new PortProxyListener("0.0.0.0", item.RemotePort, _logger); - ls.Start(new SSHDispatcher(server, client, item)); + ls.Start(new ForwardDispatcher(server, client, item)); // listen success - server.SSHList.TryAdd(item.RemotePort, new SSHInfo { Listener = ls, Socket = client, SSHConfig = item }); + server.SSHList.TryAdd(item.RemotePort, new ForwardInfo { Listener = ls, Socket = client, SSHConfig = item }); _logger.LogDebug($"SSH proxy success: {item.RemotePort} => {item.LocalIp}:{item.LocalPort}"); sb.Append($" TCP | {server.serverOption.CurrentValue.WebDomain}:{item.RemotePort} => {item.LocalIp}:{item.LocalPort}"); @@ -149,7 +114,7 @@ namespace FastTunnel.Core.Handlers { _logger.LogError($"SSH proxy error: {item.RemotePort} => {item.LocalIp}:{item.LocalPort}"); _logger.LogError(ex.Message); - client.SendCmd(new Message { MessageType = MessageType.Log, Content = new LogMassage(LogMsgType.Info, ex.Message) }); + await client.SendCmdAsync(new Message { MessageType = MessageType.Log, Content = new LogMassage(LogMsgType.Info, ex.Message) }); continue; } } @@ -157,13 +122,20 @@ namespace FastTunnel.Core.Handlers if (!hasTunnel) { - client.SendCmd(new Message { MessageType = MessageType.Log, Content = new LogMassage(LogMsgType.Info, TunnelResource.NoTunnel) }); + await client.SendCmdAsync(new Message { MessageType = MessageType.Log, Content = new LogMassage(LogMsgType.Info, TunnelResource.NoTunnel) }); } else { sb.Append($"{Environment.NewLine}===================================================="); - client.SendCmd(new Message { MessageType = MessageType.Log, Content = new LogMassage(LogMsgType.Info, sb.ToString()) }); + await client.SendCmdAsync(new Message { MessageType = MessageType.Log, Content = new LogMassage(LogMsgType.Info, sb.ToString()) }); } } + + public async Task HandlerMsg(FastTunnelServer server, WebSocket client, T msg) + where T : TunnelMassage + { + await HandleLoginAsync(server, client, msg as LogInMassage); + return NeedRecive; + } } } diff --git a/FastTunnel.Core/Handlers/Server/SwapMessageHandler.cs b/FastTunnel.Core/Handlers/Server/SwapMessageHandler.cs index 7755fcf..cbc255a 100644 --- a/FastTunnel.Core/Handlers/Server/SwapMessageHandler.cs +++ b/FastTunnel.Core/Handlers/Server/SwapMessageHandler.cs @@ -8,6 +8,7 @@ using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; using System.Net.Sockets; +using System.Net.WebSockets; using System.Text; using System.Threading.Tasks; @@ -38,7 +39,6 @@ namespace FastTunnel.Core.Handlers.Server server.ResponseTasks.TryRemove(SwapMsg.msgId, out _); _logger.LogDebug($"SwapMassage:{SwapMsg.msgId}"); - response.SetResult(new NetworkStream(client, true)); } else @@ -59,5 +59,10 @@ namespace FastTunnel.Core.Handlers.Server client.Close(); } } + + public Task HandlerMsg(FastTunnelServer server, WebSocket client, Message msg) + { + throw new NotImplementedException(); + } } } diff --git a/FastTunnel.Core/HeaderConst.cs b/FastTunnel.Core/HeaderConst.cs new file mode 100644 index 0000000..48746a8 --- /dev/null +++ b/FastTunnel.Core/HeaderConst.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace FastTunnel.Core +{ + public class HeaderConst + { + public const string FASTTUNNEL_FLAG = "FASTTUNNEL_VERSION"; + public const string FASTTUNNEL_TYPE = "FASTTUNNEL_TYPE"; + public const string FASTTUNNEL_MSGID = "FASTTUNNEL_MSGID"; + + public const string TYPE_CLIENT = "CLIENT"; + + public const string TYPE_SWAP = "SWAP"; + } +} diff --git a/FastTunnel.Core/Listener/ClientListenerV2.cs b/FastTunnel.Core/Listener/ClientListenerV2.cs index f31fa1f..1207a33 100644 --- a/FastTunnel.Core/Listener/ClientListenerV2.cs +++ b/FastTunnel.Core/Listener/ClientListenerV2.cs @@ -43,7 +43,7 @@ namespace FastTunnel.Core.Listener _heartHandler = new HeartMessageHandler(); _swapMsgHandler = new SwapMessageHandler(_logger); - server = new Server.Server(2000, 100, false, _logger); + server = new Server.Server(10000, 100, false, _logger); } public void Start() diff --git a/FastTunnel.Core/Listener/PortProxyListener.cs b/FastTunnel.Core/Listener/PortProxyListener.cs index af5e4de..fe9b7ab 100644 --- a/FastTunnel.Core/Listener/PortProxyListener.cs +++ b/FastTunnel.Core/Listener/PortProxyListener.cs @@ -108,7 +108,7 @@ namespace FastTunnel.Core.Listener try { // 将此客户端交由Dispatcher进行管理 - _requestDispatcher.Dispatch(accept); + _requestDispatcher.DispatchAsync(accept); } catch (Exception ex) { diff --git a/FastTunnel.Core/Models/SSHConfig.cs b/FastTunnel.Core/Models/ForwardConfig.cs similarity index 94% rename from FastTunnel.Core/Models/SSHConfig.cs rename to FastTunnel.Core/Models/ForwardConfig.cs index e528b0c..bfba184 100644 --- a/FastTunnel.Core/Models/SSHConfig.cs +++ b/FastTunnel.Core/Models/ForwardConfig.cs @@ -4,7 +4,7 @@ using System.Text; namespace FastTunnel.Core.Models { - public class SSHConfig + public class ForwardConfig { /// /// 局域网IP地址 diff --git a/FastTunnel.Core/Models/SSHHandlerArg.cs b/FastTunnel.Core/Models/ForwardHandlerArg.cs similarity index 67% rename from FastTunnel.Core/Models/SSHHandlerArg.cs rename to FastTunnel.Core/Models/ForwardHandlerArg.cs index bd906d5..2800d6f 100644 --- a/FastTunnel.Core/Models/SSHHandlerArg.cs +++ b/FastTunnel.Core/Models/ForwardHandlerArg.cs @@ -5,9 +5,9 @@ using System.Text; namespace FastTunnel.Core.Models { - public class SSHHandlerArg + public class ForwardHandlerArg { - public SSHConfig SSHConfig { get; internal set; } + public ForwardConfig SSHConfig { get; internal set; } public Socket LocalClient { get; internal set; } } diff --git a/FastTunnel.Core/Models/SSHInfo.cs b/FastTunnel.Core/Models/ForwardInfo.cs similarity index 58% rename from FastTunnel.Core/Models/SSHInfo.cs rename to FastTunnel.Core/Models/ForwardInfo.cs index ac893ef..919c636 100644 --- a/FastTunnel.Core/Models/SSHInfo.cs +++ b/FastTunnel.Core/Models/ForwardInfo.cs @@ -2,15 +2,16 @@ using System; using System.Collections.Generic; using System.Net.Sockets; +using System.Net.WebSockets; using System.Text; namespace FastTunnel.Core.Models { - public class SSHInfo + public class ForwardInfo { - public Socket Socket { get; set; } + public WebSocket Socket { get; set; } - public SSHConfig SSHConfig { get; set; } + public ForwardConfig SSHConfig { get; set; } public IListener Listener { get; set; } } diff --git a/FastTunnel.Core/Models/Massage/HeartMassage.cs b/FastTunnel.Core/Models/Massage/HeartMassage.cs index 3573e8c..8590aff 100644 --- a/FastTunnel.Core/Models/Massage/HeartMassage.cs +++ b/FastTunnel.Core/Models/Massage/HeartMassage.cs @@ -6,5 +6,6 @@ namespace FastTunnel.Core.Models { public class HeartMassage : TunnelMassage { + public string Time { get; set; } } } diff --git a/FastTunnel.Core/Models/Massage/LogInMassage.cs b/FastTunnel.Core/Models/Massage/LogInMassage.cs index e8c3bff..adced8e 100644 --- a/FastTunnel.Core/Models/Massage/LogInMassage.cs +++ b/FastTunnel.Core/Models/Massage/LogInMassage.cs @@ -15,6 +15,6 @@ namespace FastTunnel.Core.Models /// /// 端口转发隧道列表 /// - public IEnumerable SSH { get; set; } + public IEnumerable SSH { get; set; } } } diff --git a/FastTunnel.Core/Models/NewSSHRequest.cs b/FastTunnel.Core/Models/Massage/NewForwardMessage.cs similarity index 61% rename from FastTunnel.Core/Models/NewSSHRequest.cs rename to FastTunnel.Core/Models/Massage/NewForwardMessage.cs index de0e232..022e24e 100644 --- a/FastTunnel.Core/Models/NewSSHRequest.cs +++ b/FastTunnel.Core/Models/Massage/NewForwardMessage.cs @@ -4,10 +4,10 @@ using System.Text; namespace FastTunnel.Core.Models { - public class NewSSHRequest : TunnelMassage + public class NewForwardMessage : TunnelMassage { public string MsgId { get; set; } - public SSHConfig SSHConfig { get; set; } + public ForwardConfig SSHConfig { get; set; } } } diff --git a/FastTunnel.Core/Models/Protocol.cs b/FastTunnel.Core/Models/Protocol.cs deleted file mode 100644 index bdcc5c6..0000000 --- a/FastTunnel.Core/Models/Protocol.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace FastTunnel.Core.Models -{ - public enum Protocol - { - TCP = 0, - } -} diff --git a/FastTunnel.Core/Models/TunnelClient.cs b/FastTunnel.Core/Models/TunnelClient.cs new file mode 100644 index 0000000..3bf7f96 --- /dev/null +++ b/FastTunnel.Core/Models/TunnelClient.cs @@ -0,0 +1,90 @@ +using FastTunnel.Core.Client; +using FastTunnel.Core.Extensions; +using FastTunnel.Core.Handlers; +using FastTunnel.Core.Handlers.Server; +using FastTunnel.Core.Protocol; +using Microsoft.Extensions.Logging; +using System; +using System.Buffers; +using System.Collections.Generic; +using System.Linq; +using System.Net.WebSockets; +using System.Text; +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; +using Yarp.ReverseProxy.Configuration; + +namespace FastTunnel.Core.Models +{ + public class TunnelClient + { + readonly LoginHandler _loginHandler; + readonly HeartMessageHandler _heartHandler; + //readonly SwapMessageHandler _swapMsgHandler; + FastTunnelServer fastTunnelServer; + ILogger logger; + WebSocket webSocket; + + public TunnelClient(ILogger logger, WebSocket webSocket, FastTunnelServer fastTunnelServer) + { + this.webSocket = webSocket; + this.logger = logger; + this.fastTunnelServer = fastTunnelServer; + this._loginHandler = new LoginHandler(logger, fastTunnelServer.proxyConfig); + this._heartHandler = new HeartMessageHandler(); + // this._swapMsgHandler = new SwapMessageHandler(logger); + } + + public async Task ReviceAsync() + { + var buffer = new byte[512]; + var tunnelProtocol = new TunnelProtocol(); + + while (true) + { + var res = await webSocket.ReceiveAsync(buffer, CancellationToken.None); + var cmds = tunnelProtocol.HandleBuffer(buffer, 0, res.Count); + foreach (var item in cmds) + { + if (!await HandleCmdAsync(webSocket, item)) + { + return; + }; + } + } + } + + private async Task HandleCmdAsync(WebSocket webSocket, string lineCmd) + { + try + { + logger.LogInformation($"client:{lineCmd}"); + var cmds = lineCmd.Split("||"); + var type = cmds[0]; + + TunnelMassage msg = null; + IClientMessageHandler handler = null; + switch (type) + { + case "C_LogIn": // 登录 + handler = _loginHandler; + msg = JsonSerializer.Deserialize(cmds[1]); + break; + case "Heart": // 心跳 + handler = _heartHandler; + break; + default: + throw new Exception($"未知的通讯指令 {lineCmd}"); + } + + return await handler.HandlerMsg(fastTunnelServer, webSocket, msg); + } + catch (Exception ex) + { + logger.LogError(ex, $"处理客户端消息失败:cmd={lineCmd}"); + return false; + } + } + } +} diff --git a/FastTunnel.Core/Models/WebInfo.cs b/FastTunnel.Core/Models/WebInfo.cs index a41c64c..93b0725 100644 --- a/FastTunnel.Core/Models/WebInfo.cs +++ b/FastTunnel.Core/Models/WebInfo.cs @@ -1,13 +1,15 @@ using System; using System.Collections.Generic; using System.Net.Sockets; +using System.Net.WebSockets; using System.Text; namespace FastTunnel.Core.Models { public class WebInfo { - public Socket Socket { get; set; } + public WebSocket Socket { get; set; } + public WebConfig WebConfig { get; set; } } } diff --git a/FastTunnel.Core/Protocol/TunnelProtocol.cs b/FastTunnel.Core/Protocol/TunnelProtocol.cs new file mode 100644 index 0000000..ff7bde2 --- /dev/null +++ b/FastTunnel.Core/Protocol/TunnelProtocol.cs @@ -0,0 +1,40 @@ +using FastTunnel.Core.Extensions; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace FastTunnel.Core.Protocol +{ + public class TunnelProtocol + { + string massgeTemp; + string m_sectionFlag = "\n"; + + public IEnumerable HandleBuffer(byte[] buffer, int offset, int count) + { + var words = buffer.GetString(offset, count); + var sum = massgeTemp + words; + + if (sum.Contains(m_sectionFlag)) + { + var array = (sum).Split(m_sectionFlag); + massgeTemp = null; + var fullMsg = words.EndsWith(m_sectionFlag); + + if (!fullMsg) + { + massgeTemp = array[array.Length - 1]; + } + + return array.Take(array.Length - 1); + } + else + { + massgeTemp = sum; + return null; + } + } + } +} diff --git a/FastTunnel.Core/Services/ServiceFastTunnelClient.cs b/FastTunnel.Core/Services/ServiceFastTunnelClient.cs index ecee314..30024d3 100644 --- a/FastTunnel.Core/Services/ServiceFastTunnelClient.cs +++ b/FastTunnel.Core/Services/ServiceFastTunnelClient.cs @@ -7,7 +7,6 @@ using Microsoft.Extensions.Logging; using System; using System.Threading; using System.Threading.Tasks; -using Newtonsoft.Json; using System.Runtime.ExceptionServices; using System.IO; @@ -31,7 +30,7 @@ namespace FastTunnel.Core.Services { return Task.Run(() => { - _fastTunnelClient.Start(); + _fastTunnelClient.StartAsync(cancellationToken); }, cancellationToken); } @@ -46,7 +45,6 @@ namespace FastTunnel.Core.Services try { _logger.LogError("【UnhandledException】" + e.ExceptionObject); - _logger.LogError("【UnhandledException】" + JsonConvert.SerializeObject(e.ExceptionObject)); var type = e.ExceptionObject.GetType(); _logger.LogError("ExceptionObject GetType " + type); } diff --git a/FastTunnel.Core/Services/ServiceFastTunnelServer.cs b/FastTunnel.Core/Services/ServiceFastTunnelServer.cs index fb1d228..1b9ba77 100644 --- a/FastTunnel.Core/Services/ServiceFastTunnelServer.cs +++ b/FastTunnel.Core/Services/ServiceFastTunnelServer.cs @@ -5,7 +5,6 @@ using FastTunnel.Core.Global; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; -using Newtonsoft.Json; using System; using System.Collections.Generic; using System.IO; @@ -40,7 +39,6 @@ namespace FastTunnel.Core.Services try { _logger.LogError("【UnhandledException】" + e.ExceptionObject); - _logger.LogError("【UnhandledException】" + JsonConvert.SerializeObject(e.ExceptionObject)); var type = e.ExceptionObject.GetType(); _logger.LogError("ExceptionObject GetType " + type); } diff --git a/FastTunnel.Core/Sockets/DefultClientSocket.cs b/FastTunnel.Core/Sockets/DefultClientSocket.cs new file mode 100644 index 0000000..a0b973f --- /dev/null +++ b/FastTunnel.Core/Sockets/DefultClientSocket.cs @@ -0,0 +1,51 @@ +using FastTunnel.Core.Extensions; +using FastTunnel.Core.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Sockets; +using System.Net.WebSockets; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace FastTunnel.Core.Sockets +{ + public class DefultClientSocket : IFastTunnelClientSocket + { + ClientWebSocket webSocket; + + public DefultClientSocket() + { + webSocket = new ClientWebSocket(); + webSocket.Options.RemoteCertificateValidationCallback = delegate { return true; }; + webSocket.Options.SetRequestHeader(HeaderConst.FASTTUNNEL_FLAG, "2.0.0"); + webSocket.Options.SetRequestHeader(HeaderConst.FASTTUNNEL_TYPE, HeaderConst.TYPE_CLIENT); + } + + public async Task ConnectAsync(Uri url, CancellationToken cancellationToken) + { + await webSocket.ConnectAsync(url, cancellationToken); + } + + public async Task CloseAsync() + { + if (webSocket.State == WebSocketState.Closed) + return; + + await webSocket.CloseAsync(WebSocketCloseStatus.Empty, null, CancellationToken.None); + } + + public async Task ReceiveAsync(byte[] buffer, CancellationToken cancellationToken) + { + var res = await webSocket.ReceiveAsync(buffer, cancellationToken); + return res.Count; + } + + public async Task SendAsync(Message msg, CancellationToken cancellationToken) + where T : TunnelMassage + { + await webSocket.SendCmdAsync(msg, WebSocketMessageType.Binary, false, cancellationToken); + } + } +} diff --git a/FastTunnel.Core/Sockets/IFastTunnelClientSocket.cs b/FastTunnel.Core/Sockets/IFastTunnelClientSocket.cs new file mode 100644 index 0000000..8e8c513 --- /dev/null +++ b/FastTunnel.Core/Sockets/IFastTunnelClientSocket.cs @@ -0,0 +1,22 @@ +using FastTunnel.Core.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace FastTunnel.Core.Sockets +{ + public interface IFastTunnelClientSocket + { + Task ReceiveAsync(byte[] buffer, CancellationToken cancellationToken); + + Task SendAsync(Message loginMsg, CancellationToken cancellationToken) + where T : TunnelMassage; + + Task ConnectAsync(Uri url, CancellationToken cancellationToken); + + Task CloseAsync(); + } +} diff --git a/FastTunnel.Core/Sockets/ReadWriteStreamSwap.cs b/FastTunnel.Core/Sockets/ReadWriteStreamSwap.cs new file mode 100644 index 0000000..1f5fff4 --- /dev/null +++ b/FastTunnel.Core/Sockets/ReadWriteStreamSwap.cs @@ -0,0 +1,99 @@ +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Channels; +using System.Threading; +using System.Threading.Tasks; +using System.Net.Sockets; +using FastTunnel.Core.Forwarder; + +namespace FastTunnel.Core.Sockets +{ + public class ReadWriteStreamSwap + { + IReadWriteStream stream; + IReadWriteStream stream1; + ILogger logger; + string msgId; + + public ReadWriteStreamSwap(IReadWriteStream stream, IReadWriteStream stream1, ILogger logger, string msgId) + { + this.stream = stream; + this.stream1 = stream1; + + this.logger = logger; + this.msgId = msgId; + } + + public async Task StartSwapAsync() + { + logger.LogDebug($"[StartSwapStart] {msgId}"); + var task = new Task(() => + { + work(stream, stream1); + }); + + var task1 = new Task(() => + { + work(stream1, stream); + }); + + await Task.WhenAll(task1, task); + logger.LogDebug($"[StartSwapEnd] {msgId}"); + } + + private void work(IReadWriteStream streamRevice, IReadWriteStream streamSend) + { + byte[] buffer = new byte[512]; + + while (true) + { + int num; + + try + { + try + { + num = streamRevice.Read(buffer); + Console.WriteLine($"{Encoding.UTF8.GetString(buffer, 0, num)}"); + } + catch (Exception) + { + close("Revice Fail"); + break; + } + + if (num == 0) + { + close("Normal Close"); + break; + } + + try + { + streamSend.Write(buffer, 0, num); + } + catch (Exception) + { + close("Send Fail"); + break; + } + } + catch (Exception ex) + { + logger.LogCritical(ex, "致命异常"); + break; + } + } + } + + private void close(string msg) + { + logger.LogError($"Sarp Error {msg}"); + + } + } +} diff --git a/FastTunnel.Core/Sockets/SocketSwap.cs b/FastTunnel.Core/Sockets/SocketSwap.cs index 5bb0f59..83d85b1 100644 --- a/FastTunnel.Core/Sockets/SocketSwap.cs +++ b/FastTunnel.Core/Sockets/SocketSwap.cs @@ -2,6 +2,7 @@ using FastTunnel.Core.Utility.Extensions; using Microsoft.Extensions.Logging; using System; +using System.Buffers; using System.Collections.Generic; using System.Diagnostics; using System.Net.Sockets; diff --git a/FastTunnel.Core/Sockets/StreamSwap.cs b/FastTunnel.Core/Sockets/StreamSwap.cs new file mode 100644 index 0000000..c0d550b --- /dev/null +++ b/FastTunnel.Core/Sockets/StreamSwap.cs @@ -0,0 +1,98 @@ +using FastTunnel.Core.Handlers.Client; +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net.Sockets; +using System.Text; +using System.Threading.Tasks; + +namespace FastTunnel.Core.Sockets +{ + public class StreamSwap + { + private Stream stream1; + private Stream stream2; + private ILogger logger; + private string msgId; + + public StreamSwap(Stream serverConnection, NetworkStream localConn, ILogger logger, string msgId) + { + this.stream1 = serverConnection; + this.stream2 = localConn; + + this.logger = logger; + this.msgId = msgId; + } + + public async Task StartSwapAsync() + { + logger.LogDebug($"[StartSwapStart] {msgId}"); + var task = new Task(() => + { + work(stream1, stream2); + }); + + var task1 = new Task(() => + { + work(stream2, stream1); + }); + + await Task.WhenAll(task1, task); + + logger.LogDebug($"[StartSwapEnd] {msgId}"); + } + + private void work(Stream streamRevice, Stream streamSend) + { + byte[] buffer = new byte[512]; + + while (true) + { + int num; + + try + { + try + { + num = streamRevice.Read(buffer); + Console.WriteLine($"{Encoding.UTF8.GetString(buffer, 0, num)}"); + } + catch (Exception) + { + close("Revice Fail"); + break; + } + + if (num == 0) + { + close("Normal Close"); + break; + } + + try + { + streamSend.Write(buffer, 0, num); + } + catch (Exception) + { + close("Send Fail"); + break; + } + } + catch (Exception ex) + { + logger.LogCritical(ex, "致命异常"); + break; + } + } + } + + private void close(string msg) + { + logger.LogError($"Sarp Error {msg}"); + + } + } +} diff --git a/FastTunnel.Core/Views/Home/index.cshtml b/FastTunnel.Core/Views/Home/index.cshtml deleted file mode 100644 index 435c794..0000000 --- a/FastTunnel.Core/Views/Home/index.cshtml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - -
Coming soon!
- - \ No newline at end of file diff --git a/FastTunnel.Server/.config/dotnet-tools.json b/FastTunnel.Server/.config/dotnet-tools.json deleted file mode 100644 index c6f5df7..0000000 --- a/FastTunnel.Server/.config/dotnet-tools.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "version": 1, - "isRoot": true, - "tools": { - "dotnet-ef": { - "version": "3.1.9", - "commands": [ - "dotnet-ef" - ] - } - } -} \ No newline at end of file diff --git a/FastTunnel.Server/FastTunnel.Server.csproj b/FastTunnel.Server/FastTunnel.Server.csproj index fbe13a6..8fbb4df 100644 --- a/FastTunnel.Server/FastTunnel.Server.csproj +++ b/FastTunnel.Server/FastTunnel.Server.csproj @@ -21,10 +21,10 @@ - + PreserveNewest - + PreserveNewest diff --git a/FastTunnel.Server/Startup.cs b/FastTunnel.Server/Startup.cs index c5f86ad..830cc4a 100644 --- a/FastTunnel.Server/Startup.cs +++ b/FastTunnel.Server/Startup.cs @@ -2,6 +2,8 @@ using System; using System.Collections.Generic; using FastTunnel.Core.Extensions; using FastTunnel.Core.Forwarder; +using FastTunnel.Core.Forwarder.MiddleWare; +using FastTunnel.Core.MiddleWares; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; @@ -35,6 +37,8 @@ namespace FastTunnel.Server // ------------------------Custom Business------------------------------ services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. @@ -44,6 +48,13 @@ namespace FastTunnel.Server { } + app.UseWebSockets(); + + var swapHandler = app.ApplicationServices.GetRequiredService(); + var clientHandler = app.ApplicationServices.GetRequiredService(); + app.Use(clientHandler.Handle); + app.Use(swapHandler.Handle); + app.UseRouting(); app.UseEndpoints(endpoints => diff --git a/FastTunnel.Server/config/appsettings.json b/FastTunnel.Server/config/appsettings.json index 3946b13..b1f5e01 100644 --- a/FastTunnel.Server/config/appsettings.json +++ b/FastTunnel.Server/config/appsettings.json @@ -1,4 +1,5 @@ { + "urls": "http://*:1270;", // Http˿ "Logging": { "LogLevel": { // Trace Debug Information Warning Error @@ -10,14 +11,11 @@ "AllowedHosts": "*", "ServerSettings": { // ˿ - "BindPort": 1271, + //"BindPort": 1271, // "WebDomain": "test.cc", - // Http˿, ԶվʱurlΪ http://{SubDomain}.{WebDomain}:{WebProxyPort}/ - "WebProxyPort": 1270, - // ѡngixnʡĶ˿ںŽз "WebHasNginxProxy": false, @@ -25,6 +23,6 @@ "WebAllowAccessIps": [], // ѡǷSSHú󲻴SSHͶ˿ת.Ĭfalse - "SSHEnabled": true + "EnableForward": true } }