commit c5175e52e93884aaccf1878ef77a5f77844116c5 Author: SpringHgui <740360381@qq.com> Date: Mon Dec 16 10:29:06 2019 +0800 init project diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2cd48b4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +bin +obj +.vs diff --git a/FastTunnel.Client/Appsettings.cs b/FastTunnel.Client/Appsettings.cs new file mode 100644 index 0000000..63c3286 --- /dev/null +++ b/FastTunnel.Client/Appsettings.cs @@ -0,0 +1,14 @@ +using FastTunnel.Core.Client; +using FastTunnel.Core.Config; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace FastTunnel.Client +{ + public class Appsettings + { + public ClientConfig ClientSettings { get; set; } + } +} diff --git a/FastTunnel.Client/FastTunnel.Client.csproj b/FastTunnel.Client/FastTunnel.Client.csproj new file mode 100644 index 0000000..5785046 --- /dev/null +++ b/FastTunnel.Client/FastTunnel.Client.csproj @@ -0,0 +1,27 @@ + + + + Exe + netcoreapp3.1 + + + + + + + + + + + + + + + + + + Always + + + + diff --git a/FastTunnel.Client/Program.cs b/FastTunnel.Client/Program.cs new file mode 100644 index 0000000..f2ac9a9 --- /dev/null +++ b/FastTunnel.Client/Program.cs @@ -0,0 +1,40 @@ +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using FastTunnel.Core; +using FastTunnel.Core.Client; +using FastTunnel.Core.Logger; +using System; +using System.IO; +using System.Net; +using System.Net.Sockets; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace FastTunnel.Client +{ + class Program + { + static void Main(string[] args) + { + Console.WriteLine("Client Start!"); + + var conf = new ConfigurationBuilder() + .SetBasePath(Directory.GetCurrentDirectory()) + .AddJsonFile("appsettings.json", true, true) + .Build(); + + var settings = conf.Get(); + + Run(settings); + } + + private static void Run(Appsettings settings) + { + var FastTunnelClient = new FastTunnelClient(settings.ClientSettings, new ConsoleLogger()); + FastTunnelClient.Login(); + + Console.ReadLine(); + } + } +} diff --git a/FastTunnel.Client/SuiDao.Client.csproj.user b/FastTunnel.Client/SuiDao.Client.csproj.user new file mode 100644 index 0000000..966b4ff --- /dev/null +++ b/FastTunnel.Client/SuiDao.Client.csproj.user @@ -0,0 +1,6 @@ + + + + true + + \ No newline at end of file diff --git a/FastTunnel.Client/appsettings.json b/FastTunnel.Client/appsettings.json new file mode 100644 index 0000000..309bf91 --- /dev/null +++ b/FastTunnel.Client/appsettings.json @@ -0,0 +1,31 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" + } + }, + "ClientSettings": { + "Common": { + // 服务端公网ip + "ServerAddr": "127.0.0.1", + + // 服务端通信端口 + "ServerPort": 1271 + }, + "Webs": [ + { + // 本地站点所在内网的ip + "LocalIp": "127.0.0.1", + + // 站点监听的端口号 + "LocalPort": 9000, + + // 子域名 + "SubDomain": "test" + } + ] + + } +} \ No newline at end of file diff --git a/FastTunnel.Core/Client/SuiDaoClient.cs b/FastTunnel.Core/Client/SuiDaoClient.cs new file mode 100644 index 0000000..a1aaba3 --- /dev/null +++ b/FastTunnel.Core/Client/SuiDaoClient.cs @@ -0,0 +1,126 @@ +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using FastTunnel.Core.Config; +using FastTunnel.Core.Logger; +using FastTunnel.Core.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Sockets; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace FastTunnel.Core.Client +{ + public class FastTunnelClient + { + ClientConfig _clientConfig; + + Connecter connecter; + + ILogger _logger; + + public FastTunnelClient(ClientConfig clientConfig, ILogger logger) + { + _logger = logger; + _clientConfig = clientConfig; + connecter = new Connecter(_clientConfig.Common.ServerAddr, _clientConfig.Common.ServerPort); + } + + public void Login() + { + //连接到的目标IP + connecter.Connect(); + + // 登录 + connecter.Send(new Message { MessageType = MessageType.C_LogIn, Content = new LogInRequest { WebList = _clientConfig.Webs } }); + + _logger.Info("登录成功"); + Thread th = new Thread(ReceiveServer); + th.IsBackground = true; + th.Start(connecter.Client); + } + + private void ReceiveServer(object obj) + { + var client = obj as Socket; + byte[] buffer = new byte[1024]; + + string lastBuffer = string.Empty; + while (true) + { + int n = client.Receive(buffer); + string words = Encoding.UTF8.GetString(buffer, 0, n); + if (!string.IsNullOrEmpty(lastBuffer)) + { + words = lastBuffer + words; + lastBuffer = null; + } + + _logger.Info($"收到服务端 {words}"); + var msgs = words.Split("\n"); + + try + { + foreach (var item in msgs) + { + if (!string.IsNullOrEmpty(item)) + { + if (item.EndsWith("}")) + { + HandleServerRequest(item); + } + else + { + lastBuffer = item; + } + } + } + } + catch (Exception ex) + { + _logger.Error(ex.Message); + continue; + } + } + } + + private void HandleServerRequest(string words) + { + Message Msg; + + try + { + Msg = JsonConvert.DeserializeObject>(words); + } + catch (Exception ex) + { + throw; + } + + _logger.Info($"收到服务端指令 {Msg.MessageType}"); + + switch (Msg.MessageType) + { + case MessageType.C_Heart: + break; + case MessageType.S_NewCustomer: + var request = (Msg.Content as JObject).ToObject(); + var connecter = new Connecter(_clientConfig.Common.ServerAddr, _clientConfig.Common.ServerPort); + connecter.Connect(); + connecter.Send(new Message { MessageType = MessageType.C_NewRequest, Content = request.MsgId }); + + var localConnecter = new Connecter(request.WebConfig.LocalIp, request.WebConfig.LocalPort); + localConnecter.Connect(); + + new SocketSwap(connecter.Client, localConnecter.Client).StartSwap(); + break; + case MessageType.C_NewRequest: + case MessageType.C_LogIn: + default: + throw new Exception("参数异常"); + } + } + } +} diff --git a/FastTunnel.Core/Config/ClientConfig.cs b/FastTunnel.Core/Config/ClientConfig.cs new file mode 100644 index 0000000..01058ad --- /dev/null +++ b/FastTunnel.Core/Config/ClientConfig.cs @@ -0,0 +1,22 @@ +using FastTunnel.Core.Models; +using System; +using System.Collections.Generic; +using System.Text; + +namespace FastTunnel.Core.Config +{ + public class ClientConfig + { + public ServerCommon Common { get; set; } + + public IEnumerable Webs { get; set; } + } + + public class ServerCommon + { + public string ServerAddr { get; set; } + + + public int ServerPort { get; set; } + } +} diff --git a/FastTunnel.Core/Config/ServerConfig.cs b/FastTunnel.Core/Config/ServerConfig.cs new file mode 100644 index 0000000..ed787e4 --- /dev/null +++ b/FastTunnel.Core/Config/ServerConfig.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace FastTunnel.Core.Config +{ + public class ServerConfig + { + public string BindAddr { get; set; } + + public int BindPort { get; set; } + + public int ProxyPort_HTTP { get; set; } + + public string Domain { get; set; } + } +} diff --git a/FastTunnel.Core/Connecter.cs b/FastTunnel.Core/Connecter.cs new file mode 100644 index 0000000..ffee401 --- /dev/null +++ b/FastTunnel.Core/Connecter.cs @@ -0,0 +1,44 @@ +using FastTunnel.Core.Extensions; +using FastTunnel.Core.Models; +using System; +using System.Collections.Generic; +using System.Net; +using System.Net.Sockets; +using System.Text; + +namespace FastTunnel.Core +{ + public class Connecter + { + private string _ip; + private int _port; + + public Socket Client { get; set; } + + public Connecter(string v1, int v2) + { + this._ip = v1; + this._port = v2; + + Client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + } + + public void Connect() + { + IPAddress ip = IPAddress.Parse(_ip); + IPEndPoint point = new IPEndPoint(ip, _port); + + Client.Connect(point); + } + + private void Send(string msg) + { + Client.Send(Encoding.UTF8.GetBytes(msg)); + } + + public void Send(Message msg) + { + Send(msg.ToJson()); + } + } +} diff --git a/FastTunnel.Core/Exceptions/ClienOffLineException.cs b/FastTunnel.Core/Exceptions/ClienOffLineException.cs new file mode 100644 index 0000000..c061cbb --- /dev/null +++ b/FastTunnel.Core/Exceptions/ClienOffLineException.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace FastTunnel.Core.Exceptions +{ + public class ClienOffLineException : Exception + { + public ClienOffLineException(string message) + : base(message) + { + } + } +} diff --git a/FastTunnel.Core/Extensions/MessageExtension.cs b/FastTunnel.Core/Extensions/MessageExtension.cs new file mode 100644 index 0000000..b34904a --- /dev/null +++ b/FastTunnel.Core/Extensions/MessageExtension.cs @@ -0,0 +1,16 @@ +using Newtonsoft.Json; +using FastTunnel.Core.Models; +using System; +using System.Collections.Generic; +using System.Text; + +namespace FastTunnel.Core.Extensions +{ + public static class MessageExtension + { + public static string ToJson(this Message message) + { + return JsonConvert.SerializeObject(message, Formatting.None); + } + } +} diff --git a/FastTunnel.Core/Extensions/SocketExtension.cs b/FastTunnel.Core/Extensions/SocketExtension.cs new file mode 100644 index 0000000..17cb860 --- /dev/null +++ b/FastTunnel.Core/Extensions/SocketExtension.cs @@ -0,0 +1,16 @@ +using FastTunnel.Core.Models; +using System; +using System.Collections.Generic; +using System.Net.Sockets; +using System.Text; + +namespace FastTunnel.Core.Extensions +{ + public static class SocketExtension + { + public static void Send(this Socket socket, Message message) + { + socket.Send(Encoding.UTF8.GetBytes(message.ToJson() + "\n")); + } + } +} diff --git a/FastTunnel.Core/FastTunnel.Core.csproj b/FastTunnel.Core/FastTunnel.Core.csproj new file mode 100644 index 0000000..77a27e0 --- /dev/null +++ b/FastTunnel.Core/FastTunnel.Core.csproj @@ -0,0 +1,14 @@ + + + + Library + netcoreapp3.1 + + + + + + + + + diff --git a/FastTunnel.Core/Listener.cs b/FastTunnel.Core/Listener.cs new file mode 100644 index 0000000..37ed8b7 --- /dev/null +++ b/FastTunnel.Core/Listener.cs @@ -0,0 +1,57 @@ +using System; +using System.Collections.Generic; +using System.Net; +using System.Net.Sockets; +using System.Text; +using System.Threading; + +namespace FastTunnel.Core +{ + public class Listener + { + private string _ip; + private int _port; + Action handler; + Socket socket; + + + public Listener(string ip, int port, Action acceptCustomerHandler) + { + this._ip = ip; + this._port = port; + handler = acceptCustomerHandler; + + + IPAddress ipa = IPAddress.Parse(_ip); + IPEndPoint ipe = new IPEndPoint(ipa, _port); + + socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + socket.Bind(ipe); + + } + + public void Listen() + { + socket.Listen(100); + ThreadPool.QueueUserWorkItem((state) => + { + var _socket = state as Socket; + while (true) + { + Socket client = _socket.Accept(); + string point = client.RemoteEndPoint.ToString(); + Console.WriteLine($"收到请求 {point}"); + + ThreadPool.QueueUserWorkItem(ReceiveCustomer, client); + } + + }, socket); + } + + private void ReceiveCustomer(object state) + { + var client = state as Socket; + handler.Invoke(client); + } + } +} diff --git a/FastTunnel.Core/Logger/ConsoleLogger.cs b/FastTunnel.Core/Logger/ConsoleLogger.cs new file mode 100644 index 0000000..4a6ab78 --- /dev/null +++ b/FastTunnel.Core/Logger/ConsoleLogger.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace FastTunnel.Core.Logger +{ + public class ConsoleLogger : ILogger + { + public void Debug(string msg) + { + Console.WriteLine(string.Format("Debug - {0}", msg)); + } + + public void Error(string msg) + { + Console.WriteLine(string.Format("Erro - {0}", msg)); + } + + public void Info(string msg) + { + Console.WriteLine(string.Format("Info - {0}", msg)); + } + + public void Warning(string msg) + { + Console.WriteLine(string.Format("Warn - {0}", msg)); + } + } +} diff --git a/FastTunnel.Core/Logger/ILogger.cs b/FastTunnel.Core/Logger/ILogger.cs new file mode 100644 index 0000000..b85a27e --- /dev/null +++ b/FastTunnel.Core/Logger/ILogger.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace FastTunnel.Core.Logger +{ + public interface ILogger + { + void Error(string msg); + + void Warning(string msg); + + void Debug(string msg); + + void Info(string msg); + } +} diff --git a/FastTunnel.Core/Models/LogInRequest.cs b/FastTunnel.Core/Models/LogInRequest.cs new file mode 100644 index 0000000..0401636 --- /dev/null +++ b/FastTunnel.Core/Models/LogInRequest.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace FastTunnel.Core.Models +{ + public class LogInRequest + { + public IEnumerable WebList { get; set; } + } +} diff --git a/FastTunnel.Core/Models/Message.cs b/FastTunnel.Core/Models/Message.cs new file mode 100644 index 0000000..eb685e3 --- /dev/null +++ b/FastTunnel.Core/Models/Message.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace FastTunnel.Core.Models +{ + public class Message + { + public MessageType MessageType { get; set; } + + public T Content { get; set; } + } + + public enum MessageType + { + // client use below + C_LogIn, + C_Heart, + C_NewRequest, + + // server use below + S_NewCustomer, + } +} diff --git a/FastTunnel.Core/Models/NewCustomerRequest.cs b/FastTunnel.Core/Models/NewCustomerRequest.cs new file mode 100644 index 0000000..2f46e1f --- /dev/null +++ b/FastTunnel.Core/Models/NewCustomerRequest.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace FastTunnel.Core.Models +{ + public class NewCustomerRequest + { + public string MsgId { get; set; } + + public WebConfig WebConfig { get; set; } + } +} diff --git a/FastTunnel.Core/Models/NewRequest.cs b/FastTunnel.Core/Models/NewRequest.cs new file mode 100644 index 0000000..eee11a6 --- /dev/null +++ b/FastTunnel.Core/Models/NewRequest.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Net.Sockets; +using System.Text; + +namespace FastTunnel.Core.Models +{ + public class NewRequest + { + public Socket CustomerClient { get; set; } + public byte[] Buffer { get; set; } + } +} diff --git a/FastTunnel.Core/Models/WebConfig.cs b/FastTunnel.Core/Models/WebConfig.cs new file mode 100644 index 0000000..de5f1b6 --- /dev/null +++ b/FastTunnel.Core/Models/WebConfig.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace FastTunnel.Core.Models +{ + public class WebConfig + { + public string SubDomain { get; set; } + + public string LocalIp { get; set; } + + public int LocalPort { get; set; } + } +} diff --git a/FastTunnel.Core/Models/WebInfo.cs b/FastTunnel.Core/Models/WebInfo.cs new file mode 100644 index 0000000..a41c64c --- /dev/null +++ b/FastTunnel.Core/Models/WebInfo.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Net.Sockets; +using System.Text; + +namespace FastTunnel.Core.Models +{ + public class WebInfo + { + public Socket Socket { get; set; } + public WebConfig WebConfig { get; set; } + } +} diff --git a/FastTunnel.Core/Server/SuiDaoServer.cs b/FastTunnel.Core/Server/SuiDaoServer.cs new file mode 100644 index 0000000..01d30a0 --- /dev/null +++ b/FastTunnel.Core/Server/SuiDaoServer.cs @@ -0,0 +1,205 @@ +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using FastTunnel.Core.Config; +using FastTunnel.Core.Exceptions; +using FastTunnel.Core.Extensions; +using FastTunnel.Core.Logger; +using FastTunnel.Core.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Sockets; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; + +namespace FastTunnel.Core.Server +{ + public class FastTunnelServer + { + Dictionary WebList = new Dictionary(); + Dictionary newRequest = new Dictionary(); + + private ServerConfig serverSettings; + ILogger _logger; + + public FastTunnelServer(ServerConfig serverSettings, ILogger logger) + { + _logger = logger; + this.serverSettings = serverSettings; + } + + public void Run() + { + ListenFastTunnelClient(); + ListenCustomer(); + } + + private void ListenFastTunnelClient() + { + var listener = new Listener(serverSettings.BindAddr, serverSettings.BindPort, ReceiveClient); + listener.Listen(); + _logger.Debug($"监听客户端 -> {serverSettings.BindAddr}:{serverSettings.BindPort}"); + } + + private void ListenCustomer() + { + var listener = new Listener(serverSettings.BindAddr, serverSettings.ProxyPort_HTTP, ReceiveCustomer); + listener.Listen(); + + _logger.Debug($"监听HTTP -> {serverSettings.BindAddr}:{serverSettings.ProxyPort_HTTP}"); + } + + + //接收消息 + void ReceiveCustomer(object o) + { + Socket client = o as Socket; + _logger.Debug("新的HTTP请求"); + + try + { + //定义byte数组存放从客户端接收过来的数据 + byte[] buffer = new byte[1024]; + + int count; + try + { + count = client.Receive(buffer); + if (count == 0) + { + client.Close(); + return; + } + } + catch (SocketException) + { + if (client.Connected) + client.Close(); + return; + } + catch (Exception) + { + throw; + } + + //将字节转换成字符串 + string words = Encoding.UTF8.GetString(buffer, 0, count); + + // 正则获取Host + String Host = string.Empty; + var pattern = @"Host:.+"; + var collection = Regex.Matches(words, pattern); + if (collection.Count == 0) + { + // TODO: + throw new Exception("不支持使用ip直接访问"); + } + else + { + Host = collection[0].Value; + } + + var domain = Host.Split(":")[1].Trim(); + + _logger.Debug($"Host: {domain}"); + + WebInfo web; + if (!WebList.TryGetValue(domain, out web)) + { + throw new ClienOffLineException("客户端不存在"); + } + + var msgid = Guid.NewGuid().ToString(); + + byte[] bytes = new byte[count]; + Array.Copy(buffer, bytes, count); + + newRequest.Add(msgid, new NewRequest + { + CustomerClient = client, + Buffer = bytes + }); + + web.Socket.Send(new Message { MessageType = MessageType.S_NewCustomer, Content = new NewCustomerRequest { MsgId = msgid, WebConfig = web.WebConfig } }); + } + catch (Exception ex) + { + throw; + } + } + + private void ReceiveClient(object obj) + { + Socket client = obj as Socket; + //定义byte数组存放从客户端接收过来的数据 + byte[] buffer = new byte[1024 * 1024]; + + int length; + try + { + length = client.Receive(buffer); + } + catch (Exception ex) + { + if (client.Connected) + { + client.Close(); + } + return; + } + + //将字节转换成字符串 + string words = Encoding.UTF8.GetString(buffer, 0, length); + var msg = JsonConvert.DeserializeObject>(words); + + _logger.Debug($"收到客户端指令:{msg.MessageType}"); + switch (msg.MessageType) + { + case MessageType.C_LogIn: + var requet = (msg.Content as JObject).ToObject(); + if (requet.WebList != null && requet.WebList.Count() > 0) + { + foreach (var item in requet.WebList) + { + var key = $"{item.SubDomain }.{serverSettings.Domain}"; + if (WebList.ContainsKey(key)) + { + WebList.Remove(key); + WebList.Add(key, new WebInfo { Socket = client, WebConfig = item }); + } + else + { + WebList.Add(key, new WebInfo { Socket = client, WebConfig = item }); + } + } + } + break; + case MessageType.C_Heart: + break; + case MessageType.C_NewRequest: + var msgId = (msg.Content as string); + NewRequest request; + if (newRequest.TryGetValue(msgId, out request)) + { + // Join + Task.Run(() => + { + (new SocketSwap(request.CustomerClient, client)) + .BeforeSwap(() => { client.Send(request.Buffer); }) + .StartSwap(); + }); + } + else + { + // 未找到,关闭连接 + throw new Exception($"未找到请求:{msgId}"); + } + break; + case MessageType.S_NewCustomer: + default: + throw new Exception("参数异常"); + } + } + } +} diff --git a/FastTunnel.Core/SocketSwap.cs b/FastTunnel.Core/SocketSwap.cs new file mode 100644 index 0000000..2b92664 --- /dev/null +++ b/FastTunnel.Core/SocketSwap.cs @@ -0,0 +1,94 @@ +using System; +using System.Collections.Generic; +using System.Net.Sockets; +using System.Text; +using System.Threading; + +namespace FastTunnel.Core +{ + public class SocketSwap + { + private Socket _sockt1; + private Socket _sockt2; + bool Swaped = false; + + private class Channel + { + public Socket Send { get; set; } + + public Socket Receive { get; set; } + } + + public SocketSwap(Socket sockt1, Socket sockt2) + { + _sockt1 = sockt1; + _sockt2 = sockt2; + } + + public void StartSwap() + { + Swaped = true; + ThreadPool.QueueUserWorkItem(swapCallback, new Channel + { + Send = _sockt1, + Receive = _sockt2 + }); + + ThreadPool.QueueUserWorkItem(swapCallback, new Channel + { + Send = _sockt2, + Receive = _sockt1 + }); + } + + private void swapCallback(object state) + { + var chanel = state as Channel; + while (true) + { + try + { + byte[] result = new byte[1024]; + int num = chanel.Receive.Receive(result, result.Length, SocketFlags.None); + if (num == 0) + { + if (chanel.Send.Connected) + { + chanel.Send.Close(); + } + if (chanel.Receive.Connected) + { + chanel.Receive.Close(); + } + break; + } + + chanel.Send.Send(result, num, SocketFlags.None); + } + catch (SocketException) + { + if (chanel.Send.Connected) + chanel.Send.Close(); + if (chanel.Receive.Connected) + chanel.Receive.Close(); + break; + } + catch (Exception) + { + throw; + } + } + } + + internal SocketSwap BeforeSwap(Action fun) + { + if (Swaped) + { + throw new Exception("BeforeSwap must be invoked before StartSwap!"); + } + + fun?.Invoke(); + return this; + } + } +} diff --git a/FastTunnel.Core/SuiDao.Core.csproj.user b/FastTunnel.Core/SuiDao.Core.csproj.user new file mode 100644 index 0000000..966b4ff --- /dev/null +++ b/FastTunnel.Core/SuiDao.Core.csproj.user @@ -0,0 +1,6 @@ + + + + true + + \ No newline at end of file diff --git a/FastTunnel.Server/Appsettings.cs b/FastTunnel.Server/Appsettings.cs new file mode 100644 index 0000000..ed08285 --- /dev/null +++ b/FastTunnel.Server/Appsettings.cs @@ -0,0 +1,15 @@ +using FastTunnel.Core.Client; +using FastTunnel.Core.Config; +using FastTunnel.Core.Server; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace FastTunnel.Server +{ + public class Appsettings + { + public ServerConfig ServerSettings { get; set; } + } +} diff --git a/FastTunnel.Server/FastTunnel.Server.csproj b/FastTunnel.Server/FastTunnel.Server.csproj new file mode 100644 index 0000000..2f2d6f4 --- /dev/null +++ b/FastTunnel.Server/FastTunnel.Server.csproj @@ -0,0 +1,25 @@ + + + + Exe + netcoreapp3.1 + + + + + + + + + + + + + + + + Always + + + + diff --git a/FastTunnel.Server/Program.cs b/FastTunnel.Server/Program.cs new file mode 100644 index 0000000..016057d --- /dev/null +++ b/FastTunnel.Server/Program.cs @@ -0,0 +1,40 @@ +using Microsoft.Extensions.Configuration; +using FastTunnel.Core; +using FastTunnel.Core.Logger; +using FastTunnel.Core.Server; +using System; +using System.Collections.Generic; +using System.IO; +using System.Net; +using System.Net.Sockets; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; + +namespace FastTunnel.Server +{ + class Program + { + static void Main(string[] args) + { + Console.WriteLine("Server Start!"); + + var conf = new ConfigurationBuilder() + .SetBasePath(Directory.GetCurrentDirectory()) + .AddJsonFile("appsettings.json", true, true) + .Build(); + + var settings = conf.Get(); + Run(settings); + } + + private static void Run(Appsettings settings) + { + var server = new FastTunnelServer(settings.ServerSettings, new ConsoleLogger()); + server.Run(); + + Console.ReadLine(); + } + } +} diff --git a/FastTunnel.Server/SuiDao.Server.csproj.user b/FastTunnel.Server/SuiDao.Server.csproj.user new file mode 100644 index 0000000..966b4ff --- /dev/null +++ b/FastTunnel.Server/SuiDao.Server.csproj.user @@ -0,0 +1,6 @@ + + + + true + + \ No newline at end of file diff --git a/FastTunnel.Server/appsettings.json b/FastTunnel.Server/appsettings.json new file mode 100644 index 0000000..0f944ac --- /dev/null +++ b/FastTunnel.Server/appsettings.json @@ -0,0 +1,16 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" + } + }, + "ServerSettings": { + "BindAddr": "0.0.0.0", + "BindPort": 1271, + "Domain": "test.cc", + + "ProxyPort_HTTP": 1270 + } +} \ No newline at end of file diff --git a/FastTunnel.sln b/FastTunnel.sln new file mode 100644 index 0000000..472314a --- /dev/null +++ b/FastTunnel.sln @@ -0,0 +1,37 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29519.181 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FastTunnel.Client", "FastTunnel.Client\FastTunnel.Client.csproj", "{29DA74AE-FFBD-4A24-82B9-B5675593B63A}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FastTunnel.Core", "FastTunnel.Core\FastTunnel.Core.csproj", "{C8ADFEB1-59DB-4CE3-8D04-5B547107BCCB}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FastTunnel.Server", "FastTunnel.Server\FastTunnel.Server.csproj", "{DEF2E322-9075-4C3F-9967-7EAF0EE28CEB}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {29DA74AE-FFBD-4A24-82B9-B5675593B63A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {29DA74AE-FFBD-4A24-82B9-B5675593B63A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {29DA74AE-FFBD-4A24-82B9-B5675593B63A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {29DA74AE-FFBD-4A24-82B9-B5675593B63A}.Release|Any CPU.Build.0 = Release|Any CPU + {C8ADFEB1-59DB-4CE3-8D04-5B547107BCCB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C8ADFEB1-59DB-4CE3-8D04-5B547107BCCB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C8ADFEB1-59DB-4CE3-8D04-5B547107BCCB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C8ADFEB1-59DB-4CE3-8D04-5B547107BCCB}.Release|Any CPU.Build.0 = Release|Any CPU + {DEF2E322-9075-4C3F-9967-7EAF0EE28CEB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DEF2E322-9075-4C3F-9967-7EAF0EE28CEB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DEF2E322-9075-4C3F-9967-7EAF0EE28CEB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DEF2E322-9075-4C3F-9967-7EAF0EE28CEB}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {3D9C6B44-6706-4EE8-9043-802BBE474A2E} + EndGlobalSection +EndGlobal diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README.md b/README.md new file mode 100644 index 0000000..71e475b --- /dev/null +++ b/README.md @@ -0,0 +1,7 @@ +# FastTunnel + +FastTunnel是一款内网络代理工具,能够快速进行内网穿透。 + +# 已实现功能 + +* 通过自定义域名访问部署于内网的 web 服务