mirror of
https://github.com/FastTunnel/FastTunnel.git
synced 2025-02-08 02:39:29 +08:00
11
This commit is contained in:
parent
d98b7fea76
commit
3e5020b890
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -12,3 +12,4 @@ publish
|
||||||
/SuiDao.Client/Properties/PublishProfiles/FolderProfile.pubxml
|
/SuiDao.Client/Properties/PublishProfiles/FolderProfile.pubxml
|
||||||
/FastTunnel.Core/*.user
|
/FastTunnel.Core/*.user
|
||||||
/build
|
/build
|
||||||
|
/FastTunnel.Server/.config
|
||||||
|
|
|
@ -3,6 +3,7 @@ using Microsoft.Extensions.Logging;
|
||||||
using FastTunnel.Core.Extensions;
|
using FastTunnel.Core.Extensions;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using FastTunnel.Core.Client;
|
using FastTunnel.Core.Client;
|
||||||
|
using System;
|
||||||
|
|
||||||
namespace FastTunnel.Client
|
namespace FastTunnel.Client
|
||||||
{
|
{
|
||||||
|
@ -10,7 +11,14 @@ namespace FastTunnel.Client
|
||||||
{
|
{
|
||||||
public static void Main(string[] args)
|
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) =>
|
public static IHostBuilder CreateHostBuilder(string[] args) =>
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
//"ServerAddr": "my.com",
|
//"ServerAddr": "my.com",
|
||||||
"ServerAddr": "127.0.0.1",
|
"ServerAddr": "127.0.0.1",
|
||||||
// 服务端监听的通信端口
|
// 服务端监听的通信端口
|
||||||
"ServerPort": 1271
|
"ServerPort": 1270
|
||||||
},
|
},
|
||||||
"Webs": [
|
"Webs": [
|
||||||
{
|
{
|
||||||
|
@ -37,11 +37,12 @@
|
||||||
],
|
],
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ssh穿透,ssh访问内网主机/mysql/erp/等任何服务
|
* 端口转发
|
||||||
|
* 访问内网主机/mysql/erp/等任何TCP协议服务
|
||||||
* 远程linux示例:#ssh -oPort=12701 {root}@{ServerAddr} ServerAddr 填入服务端ip,root对应内网用户名
|
* 远程linux示例:#ssh -oPort=12701 {root}@{ServerAddr} ServerAddr 填入服务端ip,root对应内网用户名
|
||||||
* 通过服务端返回的访问方式进行访问即可
|
* 通过服务端返回的访问方式进行访问即可
|
||||||
*/
|
*/
|
||||||
"SSH": [
|
"Forward": [
|
||||||
{
|
{
|
||||||
"LocalIp": "127.0.0.1",
|
"LocalIp": "127.0.0.1",
|
||||||
"LocalPort": 8090,
|
"LocalPort": 8090,
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
using Newtonsoft.Json;
|
using FastTunnel.Core.Config;
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using FastTunnel.Core.Config;
|
|
||||||
using FastTunnel.Core.Models;
|
using FastTunnel.Core.Models;
|
||||||
using System;
|
using System;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
|
@ -15,12 +13,15 @@ using Microsoft.Extensions.Configuration;
|
||||||
using FastTunnel.Core.Server;
|
using FastTunnel.Core.Server;
|
||||||
using FastTunnel.Core.Sockets;
|
using FastTunnel.Core.Sockets;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
|
using System.Net.WebSockets;
|
||||||
|
using System.Text.Json;
|
||||||
|
|
||||||
namespace FastTunnel.Core.Client
|
namespace FastTunnel.Core.Client
|
||||||
{
|
{
|
||||||
public class FastTunnelClient : IFastTunnelClient
|
public class FastTunnelClient : IFastTunnelClient
|
||||||
{
|
{
|
||||||
Socket _client;
|
//Socket _client;
|
||||||
|
private IFastTunnelClientSocket socket;
|
||||||
|
|
||||||
protected ILogger<FastTunnelClient> _logger;
|
protected ILogger<FastTunnelClient> _logger;
|
||||||
|
|
||||||
|
@ -31,19 +32,19 @@ namespace FastTunnel.Core.Client
|
||||||
|
|
||||||
int reTrySpan = 10 * 1000; // 登陆失败后重试间隔
|
int reTrySpan = 10 * 1000; // 登陆失败后重试间隔
|
||||||
HttpRequestHandler _newCustomerHandler;
|
HttpRequestHandler _newCustomerHandler;
|
||||||
NewSSHHandler _newSSHHandler;
|
NewForwardHandler _newSSHHandler;
|
||||||
LogHandler _logHandler;
|
LogHandler _logHandler;
|
||||||
ClientHeartHandler _clientHeartHandler;
|
ClientHeartHandler _clientHeartHandler;
|
||||||
Func<Socket> lastLogin;
|
|
||||||
Message<LogInMassage> loginMsg;
|
Message<LogInMassage> loginMsg;
|
||||||
protected readonly IOptionsMonitor<DefaultClientConfig> _configuration;
|
protected readonly IOptionsMonitor<DefaultClientConfig> _configuration;
|
||||||
|
private readonly CancellationTokenSource cancellationTokenSource = new();
|
||||||
|
|
||||||
public SuiDaoServer Server { get; protected set; }
|
public SuiDaoServer Server { get; protected set; }
|
||||||
|
|
||||||
public FastTunnelClient(
|
public FastTunnelClient(
|
||||||
ILogger<FastTunnelClient> logger,
|
ILogger<FastTunnelClient> logger,
|
||||||
HttpRequestHandler newCustomerHandler,
|
HttpRequestHandler newCustomerHandler,
|
||||||
NewSSHHandler newSSHHandler, LogHandler logHandler,
|
NewForwardHandler newSSHHandler, LogHandler logHandler,
|
||||||
IOptionsMonitor<DefaultClientConfig> configuration,
|
IOptionsMonitor<DefaultClientConfig> configuration,
|
||||||
ClientHeartHandler clientHeartHandler)
|
ClientHeartHandler clientHeartHandler)
|
||||||
{
|
{
|
||||||
|
@ -60,7 +61,7 @@ namespace FastTunnel.Core.Client
|
||||||
timer_heart.Elapsed += HeartElapsed;
|
timer_heart.Elapsed += HeartElapsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void reConn()
|
private async Task reConnAsync()
|
||||||
{
|
{
|
||||||
Close();
|
Close();
|
||||||
|
|
||||||
|
@ -71,7 +72,7 @@ namespace FastTunnel.Core.Client
|
||||||
Thread.Sleep(reTrySpan);
|
Thread.Sleep(reTrySpan);
|
||||||
|
|
||||||
_logger.LogInformation("登录重试...");
|
_logger.LogInformation("登录重试...");
|
||||||
_client = lastLogin.Invoke();
|
socket = await loginAsync(CancellationToken.None);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -90,12 +91,12 @@ namespace FastTunnel.Core.Client
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_client.SendCmd(new Message<HeartMassage> { MessageType = MessageType.Heart, Content = null });
|
socket.SendAsync(new Message<HeartMassage> { MessageType = MessageType.Heart, Content = null }, cancellationTokenSource.Token).Wait();
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
// 与服务端断开连接
|
// 与服务端断开连接
|
||||||
reConn();
|
reConnAsync();
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
@ -108,43 +109,77 @@ namespace FastTunnel.Core.Client
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="T"></typeparam>
|
/// <typeparam name="T"></typeparam>
|
||||||
/// <param name="customLoginMsg">自定义登录信息,可进行扩展业务</param>
|
/// <param name="customLoginMsg">自定义登录信息,可进行扩展业务</param>
|
||||||
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
|
try
|
||||||
{
|
{
|
||||||
_client = lastLogin.Invoke();
|
socket = await loginAsync(cancellationToken);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.LogError(ex.Message);
|
_logger.LogError(ex.Message);
|
||||||
|
|
||||||
reConn();
|
reConnAsync();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = connSuccessAsync();
|
_ = 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<LogInMassage>
|
||||||
|
// {
|
||||||
|
// 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<IFastTunnelClientSocket> loginAsync(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
Server = _configuration.CurrentValue.Server;
|
Server = _configuration.CurrentValue.Server;
|
||||||
|
|
||||||
DnsSocket _client = null;
|
|
||||||
_logger.LogInformation($"正在连接服务端 {Server.ServerAddr}:{Server.ServerPort}");
|
_logger.LogInformation($"正在连接服务端 {Server.ServerAddr}:{Server.ServerPort}");
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// 连接到的目标IP
|
// 连接到的目标IP
|
||||||
if (_client == null)
|
socket = new DefultClientSocket();
|
||||||
{
|
|
||||||
_client = new DnsSocket(Server.ServerAddr, Server.ServerPort);
|
|
||||||
}
|
|
||||||
|
|
||||||
_client.Connect();
|
await socket.ConnectAsync(
|
||||||
|
new Uri($"ws://{_configuration.CurrentValue.Server.ServerAddr}:{_configuration.CurrentValue.Server.ServerPort}"), cancellationToken);
|
||||||
|
|
||||||
_logger.LogInformation("连接成功");
|
_logger.LogInformation("连接成功");
|
||||||
}
|
}
|
||||||
|
@ -159,29 +194,19 @@ namespace FastTunnel.Core.Client
|
||||||
Content = new LogInMassage
|
Content = new LogInMassage
|
||||||
{
|
{
|
||||||
Webs = _configuration.CurrentValue.Webs,
|
Webs = _configuration.CurrentValue.Webs,
|
||||||
SSH = _configuration.CurrentValue.SSH,
|
SSH = _configuration.CurrentValue.Forwards,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
// 登录
|
// 登录
|
||||||
_client.Send(loginMsg);
|
await socket.SendAsync(loginMsg, cancellationToken);
|
||||||
|
return socket;
|
||||||
return _client.Socket;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Close()
|
void Close()
|
||||||
{
|
{
|
||||||
timer_heart.Stop();
|
timer_heart.Stop();
|
||||||
|
socket.CloseAsync();
|
||||||
try
|
|
||||||
{
|
|
||||||
_client?.Shutdown(SocketShutdown.Both);
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
_client?.Close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task connSuccessAsync()
|
private async Task connSuccessAsync()
|
||||||
|
@ -192,7 +217,7 @@ namespace FastTunnel.Core.Client
|
||||||
timer_heart.Start();
|
timer_heart.Start();
|
||||||
|
|
||||||
var th = new Thread(ReceiveServer);
|
var th = new Thread(ReceiveServer);
|
||||||
th.Start(_client);
|
th.Start(socket);
|
||||||
// await new PipeHepler(_client, ProceccLine).ProcessLinesAsync();
|
// await new PipeHepler(_client, ProceccLine).ProcessLinesAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,7 +230,7 @@ namespace FastTunnel.Core.Client
|
||||||
|
|
||||||
private void ReceiveServer(object obj)
|
private void ReceiveServer(object obj)
|
||||||
{
|
{
|
||||||
var client = obj as Socket;
|
var client = obj as IFastTunnelClientSocket;
|
||||||
byte[] buffer = new byte[1024];
|
byte[] buffer = new byte[1024];
|
||||||
|
|
||||||
string lastBuffer = string.Empty;
|
string lastBuffer = string.Empty;
|
||||||
|
@ -215,10 +240,10 @@ namespace FastTunnel.Core.Client
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
n = client.Receive(buffer);
|
n = client.ReceiveAsync(buffer, cancellationTokenSource.Token).GetAwaiter().GetResult();
|
||||||
if (n == 0)
|
if (n == 0)
|
||||||
{
|
{
|
||||||
client.Shutdown(SocketShutdown.Both);
|
client.CloseAsync();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -290,36 +315,38 @@ namespace FastTunnel.Core.Client
|
||||||
_logger.LogInformation("stop receive from server");
|
_logger.LogInformation("stop receive from server");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HandleServerRequest(string words)
|
private void HandleServerRequest(string lineCmd)
|
||||||
{
|
{
|
||||||
Task.Run(() =>
|
Task.Run(() =>
|
||||||
{
|
{
|
||||||
var Msg = JsonConvert.DeserializeObject<Message<JObject>>(words);
|
var cmds = lineCmd.Split("||");
|
||||||
if (Msg.MessageType != MessageType.Heart)
|
var type = cmds[0];
|
||||||
{
|
|
||||||
_logger.LogDebug($"HandleServerRequest {words}");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
TunnelMassage msg = null;
|
||||||
IClientHandler handler;
|
IClientHandler handler;
|
||||||
switch (Msg.MessageType)
|
switch (type)
|
||||||
{
|
{
|
||||||
case MessageType.Heart:
|
case "Heart":
|
||||||
handler = _clientHeartHandler;
|
handler = _clientHeartHandler;
|
||||||
|
msg = JsonSerializer.Deserialize<HeartMassage>(cmds[1]);
|
||||||
break;
|
break;
|
||||||
case MessageType.S_NewCustomer:
|
case "S_NewCustomer":
|
||||||
handler = _newCustomerHandler;
|
handler = _newCustomerHandler;
|
||||||
|
msg = JsonSerializer.Deserialize<NewCustomerMassage>(cmds[1]);
|
||||||
break;
|
break;
|
||||||
case MessageType.S_NewSSH:
|
case "S_NewSSH":
|
||||||
handler = _newSSHHandler;
|
handler = _newSSHHandler;
|
||||||
|
msg = JsonSerializer.Deserialize<NewForwardMessage>(cmds[1]);
|
||||||
break;
|
break;
|
||||||
case MessageType.Log:
|
case "Log":
|
||||||
handler = _logHandler;
|
handler = _logHandler;
|
||||||
|
msg = JsonSerializer.Deserialize<LogMassage>(cmds[1]);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new Exception($"未处理的消息:{Msg.MessageType} {Msg.Content}");
|
throw new Exception($"未处理的消息:{lineCmd}");
|
||||||
}
|
}
|
||||||
|
|
||||||
handler.HandlerMsg(this, Msg);
|
handler.HandlerMsgAsync(this, msg);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,35 +27,37 @@ namespace FastTunnel.Core.Client
|
||||||
public ConcurrentDictionary<string, WebInfo> WebList { get; private set; }
|
public ConcurrentDictionary<string, WebInfo> WebList { get; private set; }
|
||||||
= new ConcurrentDictionary<string, WebInfo>();
|
= new ConcurrentDictionary<string, WebInfo>();
|
||||||
|
|
||||||
public ConcurrentDictionary<int, SSHInfo<SSHHandlerArg>> SSHList { get; private set; }
|
public ConcurrentDictionary<int, ForwardInfo<ForwardHandlerArg>> SSHList { get; private set; }
|
||||||
= new ConcurrentDictionary<int, SSHInfo<SSHHandlerArg>>();
|
= new ConcurrentDictionary<int, ForwardInfo<ForwardHandlerArg>>();
|
||||||
|
|
||||||
readonly ILogger _logger;
|
readonly ILogger _logger;
|
||||||
readonly ClientListenerV2 clientListener;
|
//readonly ClientListenerV2 clientListener;
|
||||||
readonly HttpListenerV2 http_listener;
|
//readonly HttpListenerV2 http_listener;
|
||||||
public readonly IOptionsMonitor<DefaultServerConfig> serverOption;
|
public readonly IOptionsMonitor<DefaultServerConfig> serverOption;
|
||||||
|
public IProxyConfigProvider proxyConfig;
|
||||||
|
|
||||||
public FastTunnelServer(ILogger<FastTunnelServer> logger, IProxyConfigProvider proxyConfig, IOptionsMonitor<DefaultServerConfig> serverSettings)
|
public FastTunnelServer(ILogger<FastTunnelServer> logger, IProxyConfigProvider proxyConfig, IOptionsMonitor<DefaultServerConfig> serverSettings)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
serverOption = serverSettings;
|
serverOption = serverSettings;
|
||||||
|
this.proxyConfig = proxyConfig;
|
||||||
|
|
||||||
clientListener = new ClientListenerV2(this, proxyConfig, "0.0.0.0", serverOption.CurrentValue.BindPort, _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);
|
// http_listener = new HttpListenerV2("0.0.0.0", serverOption.CurrentValue.WebProxyPort, _logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Run()
|
public void Run()
|
||||||
{
|
{
|
||||||
_logger.LogInformation("===== FastTunnel Server Starting =====");
|
_logger.LogInformation("===== FastTunnel Server Starting =====");
|
||||||
|
|
||||||
listenClient();
|
// listenClient();
|
||||||
//listenHttp();
|
// listenHttp();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void listenClient()
|
//private void listenClient()
|
||||||
{
|
//{
|
||||||
clientListener.Start();
|
// clientListener.Start();
|
||||||
}
|
//}
|
||||||
|
|
||||||
//private void listenHttp()
|
//private void listenHttp()
|
||||||
//{
|
//{
|
||||||
|
@ -66,8 +68,8 @@ namespace FastTunnel.Core.Client
|
||||||
{
|
{
|
||||||
_logger.LogInformation("===== FastTunnel Server Stoping =====");
|
_logger.LogInformation("===== FastTunnel Server Stoping =====");
|
||||||
|
|
||||||
clientListener.Stop();
|
//clientListener.Stop();
|
||||||
http_listener.Stop();
|
//http_listener.Stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,12 +2,13 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace FastTunnel.Core.Client
|
namespace FastTunnel.Core.Client
|
||||||
{
|
{
|
||||||
public interface IFastTunnelClient
|
public interface IFastTunnelClient
|
||||||
{
|
{
|
||||||
void Start();
|
Task StartAsync(CancellationToken cancellationToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,6 @@ namespace FastTunnel.Core.Config
|
||||||
|
|
||||||
public IEnumerable<WebConfig> Webs { get; set; }
|
public IEnumerable<WebConfig> Webs { get; set; }
|
||||||
|
|
||||||
public IEnumerable<SSHConfig> SSH { get; set; }
|
public IEnumerable<ForwardConfig> Forwards { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -7,7 +7,7 @@ namespace FastTunnel.Core.Config
|
||||||
{
|
{
|
||||||
public class DefaultServerConfig : IServerConfig
|
public class DefaultServerConfig : IServerConfig
|
||||||
{
|
{
|
||||||
public int BindPort { get; set; }
|
// public int BindPort { get; set; }
|
||||||
|
|
||||||
public string WebDomain { get; set; }
|
public string WebDomain { get; set; }
|
||||||
|
|
||||||
|
@ -17,6 +17,6 @@ namespace FastTunnel.Core.Config
|
||||||
|
|
||||||
public bool WebHasNginxProxy { get; set; } = false;
|
public bool WebHasNginxProxy { get; set; } = false;
|
||||||
|
|
||||||
public bool SSHEnabled { get; set; } = false;
|
public bool EnableForward { get; set; } = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ namespace FastTunnel.Core.Config
|
||||||
|
|
||||||
public IEnumerable<WebConfig> Webs { get; set; }
|
public IEnumerable<WebConfig> Webs { get; set; }
|
||||||
|
|
||||||
public IEnumerable<SSHConfig> SSH { get; set; }
|
public IEnumerable<ForwardConfig> Forwards { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class SuiDaoServer
|
public class SuiDaoServer
|
||||||
|
|
|
@ -6,7 +6,7 @@ namespace FastTunnel.Core.Config
|
||||||
{
|
{
|
||||||
public interface IServerConfig
|
public interface IServerConfig
|
||||||
{
|
{
|
||||||
int BindPort { get; set; }
|
// int BindPort { get; set; }
|
||||||
|
|
||||||
#region Web相关配置
|
#region Web相关配置
|
||||||
|
|
||||||
|
@ -28,6 +28,6 @@ namespace FastTunnel.Core.Config
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
bool SSHEnabled { get; set; }
|
bool EnableForward { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,27 +6,31 @@ using FastTunnel.Core.Server;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
|
using System.Net.WebSockets;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace FastTunnel.Core.Dispatchers
|
namespace FastTunnel.Core.Dispatchers
|
||||||
{
|
{
|
||||||
public class SSHDispatcher : IListenerDispatcher
|
public class ForwardDispatcher : IListenerDispatcher
|
||||||
{
|
{
|
||||||
private FastTunnelServer _server;
|
private FastTunnelServer _server;
|
||||||
private Socket _client;
|
private WebSocket _client;
|
||||||
private SSHConfig _config;
|
private ForwardConfig _config;
|
||||||
|
|
||||||
public SSHDispatcher(FastTunnelServer server, Socket client, SSHConfig config)
|
public ForwardDispatcher(FastTunnelServer server, WebSocket client, ForwardConfig config)
|
||||||
{
|
{
|
||||||
_server = server;
|
_server = server;
|
||||||
_client = client;
|
_client = client;
|
||||||
_config = config;
|
_config = config;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispatch(Socket _socket)
|
public async Task DispatchAsync(Socket _socket)
|
||||||
{
|
{
|
||||||
var msgid = Guid.NewGuid().ToString();
|
var msgid = Guid.NewGuid().ToString();
|
||||||
_client.SendCmd(new Message<NewSSHRequest> { MessageType = MessageType.S_NewSSH, Content = new NewSSHRequest { MsgId = msgid, SSHConfig = _config } });
|
await _client.SendCmdAsync(new Message<NewForwardMessage> { MessageType = MessageType.S_NewSSH, Content = new NewForwardMessage { MsgId = msgid, SSHConfig = _config } });
|
||||||
|
|
||||||
_server.RequestTemp.TryAdd(msgid, new NewRequest
|
_server.RequestTemp.TryAdd(msgid, new NewRequest
|
||||||
{
|
{
|
||||||
CustomerClient = _socket,
|
CustomerClient = _socket,
|
|
@ -3,6 +3,7 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace FastTunnel.Core.Dispatchers
|
namespace FastTunnel.Core.Dispatchers
|
||||||
{
|
{
|
||||||
|
@ -10,6 +11,6 @@ namespace FastTunnel.Core.Dispatchers
|
||||||
{
|
{
|
||||||
void Dispatch(AsyncUserToken token, string words);
|
void Dispatch(AsyncUserToken token, string words);
|
||||||
|
|
||||||
void Dispatch(Socket httpClient);
|
Task DispatchAsync(Socket httpClient);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,7 +1,7 @@
|
||||||
using Newtonsoft.Json;
|
using System;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Text.Json;
|
||||||
|
|
||||||
namespace FastTunnel.Core.Extensions
|
namespace FastTunnel.Core.Extensions
|
||||||
{
|
{
|
||||||
|
@ -9,7 +9,13 @@ namespace FastTunnel.Core.Extensions
|
||||||
{
|
{
|
||||||
public static string ToJson(this object message)
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,7 @@ namespace FastTunnel.Core.Extensions
|
||||||
.AddSingleton<ClientHeartHandler>()
|
.AddSingleton<ClientHeartHandler>()
|
||||||
.AddSingleton<LogHandler>()
|
.AddSingleton<LogHandler>()
|
||||||
.AddSingleton<HttpRequestHandler>()
|
.AddSingleton<HttpRequestHandler>()
|
||||||
.AddSingleton<NewSSHHandler>();
|
.AddSingleton<NewForwardHandler>();
|
||||||
|
|
||||||
services.AddHostedService<ServiceFastTunnelClient>();
|
services.AddHostedService<ServiceFastTunnelClient>();
|
||||||
}
|
}
|
||||||
|
|
30
FastTunnel.Core/Extensions/WebSocketExtension.cs
Normal file
30
FastTunnel.Core/Extensions/WebSocketExtension.cs
Normal file
|
@ -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<T>(this WebSocket socket, Message<T> 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<T>(this WebSocket socket, Message<T> 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -22,14 +22,17 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Compile Remove="Client\FastTunnelClient - Copy.cs" />
|
||||||
<Compile Remove="Client\SuiDaoServer.cs.BASE.cs" />
|
<Compile Remove="Client\SuiDaoServer.cs.BASE.cs" />
|
||||||
<Compile Remove="Client\SuiDaoServer.cs.LOCAL.cs" />
|
<Compile Remove="Client\SuiDaoServer.cs.LOCAL.cs" />
|
||||||
<Compile Remove="Client\SuiDaoServer.cs.REMOTE.cs" />
|
<Compile Remove="Client\SuiDaoServer.cs.REMOTE.cs" />
|
||||||
<Compile Remove="Dispatchers\ClientDispatcher.cs" />
|
<Compile Remove="Dispatchers\ClientDispatcher.cs" />
|
||||||
<Compile Remove="Dispatchers\HttpDispatcher.cs" />
|
<Compile Remove="Dispatchers\HttpDispatcher.cs" />
|
||||||
<Compile Remove="Dispatchers\HttpDispatcherV2.cs" />
|
<Compile Remove="Dispatchers\HttpDispatcherV2.cs" />
|
||||||
|
<Compile Remove="Handlers\Server\SwapMessageHandler.cs" />
|
||||||
<Compile Remove="Listener.cs" />
|
<Compile Remove="Listener.cs" />
|
||||||
<Compile Remove="Listener\ClientListener.cs" />
|
<Compile Remove="Listener\ClientListener.cs" />
|
||||||
|
<Compile Remove="Listener\ClientListenerV2.cs" />
|
||||||
<Compile Remove="Listener\HttpListener.cs" />
|
<Compile Remove="Listener\HttpListener.cs" />
|
||||||
<Compile Remove="Server.cs" />
|
<Compile Remove="Server.cs" />
|
||||||
<Compile Remove="Sockets\AsyncSocketSwap.cs" />
|
<Compile Remove="Sockets\AsyncSocketSwap.cs" />
|
||||||
|
@ -39,7 +42,7 @@
|
||||||
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="6.0.0-preview.6.21352.12" />
|
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="6.0.0-preview.6.21352.12" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="5.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="5.0.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="5.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="5.0.0" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
<PackageReference Include="Microsoft.VisualStudio.Validation" Version="17.0.16-alpha" />
|
||||||
<PackageReference Include="Yarp.ReverseProxy" Version="1.0.0-preview.12.21328.2" />
|
<PackageReference Include="Yarp.ReverseProxy" Version="1.0.0-preview.12.21328.2" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
using FastTunnel.Core.Extensions;
|
using FastTunnel.Core.Extensions;
|
||||||
using FastTunnel.Core.Models;
|
using FastTunnel.Core.Models;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
@ -53,7 +52,6 @@ namespace FastTunnel.Core.Forwarder
|
||||||
|
|
||||||
public async ValueTask<Stream> proxyAsync(string host, CancellationToken cancellation)
|
public async ValueTask<Stream> proxyAsync(string host, CancellationToken cancellation)
|
||||||
{
|
{
|
||||||
|
|
||||||
WebInfo web;
|
WebInfo web;
|
||||||
if (!_fastTunnelServer.WebList.TryGetValue(host, out web))
|
if (!_fastTunnelServer.WebList.TryGetValue(host, out web))
|
||||||
{
|
{
|
||||||
|
@ -63,16 +61,18 @@ namespace FastTunnel.Core.Forwarder
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var RequestId = Guid.NewGuid().ToString().Replace("-", "");
|
var RequestId = Guid.NewGuid().ToString().Replace("-", "");
|
||||||
_logger.LogDebug($"[send swap]:{RequestId}");
|
_logger.LogInformation($"[发送swap指令]:{RequestId}");
|
||||||
|
|
||||||
// 发送指令给客户端,等待建立隧道
|
// 发送指令给客户端,等待建立隧道
|
||||||
web.Socket.SendCmd(new Message<NewCustomerMassage> { MessageType = MessageType.S_NewCustomer, Content = new NewCustomerMassage { MsgId = RequestId, WebConfig = web.WebConfig } });
|
await web.Socket.SendCmdAsync(new Message<NewCustomerMassage> { MessageType = MessageType.S_NewCustomer, Content = new NewCustomerMassage { MsgId = RequestId, WebConfig = web.WebConfig } });
|
||||||
|
|
||||||
// TODO:超时处理
|
// TODO:超时处理
|
||||||
TaskCompletionSource<Stream> task = new(cancellation);
|
TaskCompletionSource<Stream> task = new(cancellation);
|
||||||
|
|
||||||
_fastTunnelServer.ResponseTasks.TryAdd(RequestId, task);
|
_fastTunnelServer.ResponseTasks.TryAdd(RequestId, task);
|
||||||
return await task.Task;
|
|
||||||
|
var res = await task.Task;
|
||||||
|
_logger.LogInformation($"[收到swap指令]:{RequestId}");
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|
15
FastTunnel.Core/Forwarder/IReadWriteStream.cs
Normal file
15
FastTunnel.Core/Forwarder/IReadWriteStream.cs
Normal file
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net.WebSockets;
|
using System.Net.WebSockets;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Yarp.ReverseProxy.Configuration;
|
||||||
|
|
||||||
namespace FastTunnel.Core.MiddleWares
|
namespace FastTunnel.Core.MiddleWares
|
||||||
{
|
{
|
||||||
public class FastTunnelClientHandler
|
public class FastTunnelClientHandler
|
||||||
{
|
{
|
||||||
public static async Task Handle(HttpContext context, Func<Task> next)
|
ILogger<FastTunnelClientHandler> logger;
|
||||||
|
FastTunnelServer fastTunnelServer;
|
||||||
|
|
||||||
|
public FastTunnelClientHandler(ILogger<FastTunnelClientHandler> logger, FastTunnelServer fastTunnelServer)
|
||||||
{
|
{
|
||||||
if (!context.WebSockets.IsWebSocketRequest)
|
this.logger = logger;
|
||||||
|
this.fastTunnelServer = fastTunnelServer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task Handle(HttpContext context, Func<Task> 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();
|
await next();
|
||||||
return;
|
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<Task> 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<IConnectionLifetimeFeature>();
|
||||||
|
var transport = context.Features.Get<IConnectionTransportFeature>();
|
||||||
|
|
||||||
|
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<Task> 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} 客户端断开连接");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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<FastTunnelClientHandler> logger;
|
||||||
|
FastTunnelServer fastTunnelServer;
|
||||||
|
|
||||||
|
public FastTunnelSwapHandler(ILogger<FastTunnelClientHandler> logger, FastTunnelServer fastTunnelServer)
|
||||||
|
{
|
||||||
|
this.logger = logger;
|
||||||
|
this.fastTunnelServer = fastTunnelServer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task Handle(HttpContext context, Func<Task> 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<IConnectionLifetimeFeature>();
|
||||||
|
var transport = context.Features.Get<IConnectionTransportFeature>();
|
||||||
|
|
||||||
|
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<object>();
|
||||||
|
lifetime.ConnectionClosed.Register((task) => { (task as TaskCompletionSource<object>).SetResult(null); }, closedAwaiter);
|
||||||
|
|
||||||
|
await closedAwaiter.Task;
|
||||||
|
logger.LogInformation($"Swap close {requestId}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
28
FastTunnel.Core/Forwarder/SocketReadWriteStream.cs
Normal file
28
FastTunnel.Core/Forwarder/SocketReadWriteStream.cs
Normal file
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
112
FastTunnel.Core/Forwarder/WebSocketStream.cs
Normal file
112
FastTunnel.Core/Forwarder/WebSocketStream.cs
Normal file
|
@ -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<int> ReadAsync(Memory<byte> buffer, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
return this.readStream.ReadAsync(buffer, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
return this.readStream.ReadAsync(buffer, offset, count, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Write(ReadOnlySpan<byte> 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<byte> 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
35
FastTunnel.Core/Forwarder/WebSocktReadWriteStream.cs
Normal file
35
FastTunnel.Core/Forwarder/WebSocktReadWriteStream.cs
Normal file
|
@ -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<byte>(buffer, offset, count), WebSocketMessageType.Binary, true, CancellationToken.None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,18 +1,19 @@
|
||||||
using FastTunnel.Core.Config;
|
using FastTunnel.Core.Config;
|
||||||
using FastTunnel.Core.Client;
|
using FastTunnel.Core.Client;
|
||||||
using FastTunnel.Core.Models;
|
using FastTunnel.Core.Models;
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace FastTunnel.Core.Handlers.Client
|
namespace FastTunnel.Core.Handlers.Client
|
||||||
{
|
{
|
||||||
public class ClientHeartHandler : IClientHandler
|
public class ClientHeartHandler : IClientHandler
|
||||||
{
|
{
|
||||||
public void HandlerMsg(FastTunnelClient cleint, Message<JObject> Msg)
|
public async Task HandlerMsgAsync<T>(FastTunnelClient cleint, T Msg) where T : TunnelMassage
|
||||||
{
|
{
|
||||||
cleint.lastHeart = DateTime.Now;
|
cleint.lastHeart = DateTime.Now;
|
||||||
|
await Task.Yield();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
using FastTunnel.Core.Config;
|
using FastTunnel.Core.Config;
|
||||||
using FastTunnel.Core.Client;
|
using FastTunnel.Core.Client;
|
||||||
using FastTunnel.Core.Models;
|
using FastTunnel.Core.Models;
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
@ -12,6 +11,12 @@ using System.Threading.Tasks;
|
||||||
using FastTunnel.Core.Sockets;
|
using FastTunnel.Core.Sockets;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using FastTunnel.Core.Utility.Extensions;
|
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
|
namespace FastTunnel.Core.Handlers.Client
|
||||||
{
|
{
|
||||||
|
@ -24,9 +29,9 @@ namespace FastTunnel.Core.Handlers.Client
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void HandlerMsg(FastTunnelClient cleint, Message<JObject> Msg)
|
public async Task HandlerMsgAsync<T>(FastTunnelClient cleint, T Msg) where T : TunnelMassage
|
||||||
{
|
{
|
||||||
var request = Msg.Content.ToObject<NewCustomerMassage>();
|
var request = Msg as NewCustomerMassage;
|
||||||
if (request.MsgId.Contains("_"))
|
if (request.MsgId.Contains("_"))
|
||||||
{
|
{
|
||||||
var interval = long.Parse(DateTime.Now.GetChinaTicks()) - long.Parse(request.MsgId.Split('_')[0]);
|
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");
|
_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);
|
var connecter = new DnsSocket(cleint.Server.ServerAddr, cleint.Server.ServerPort);
|
||||||
connecter.Connect();
|
connecter.Connect();
|
||||||
|
// connecter.Send(new Message<SwapMassage> { MessageType = MessageType.C_SwapMsg, Content = new SwapMassage(request.MsgId) });
|
||||||
|
|
||||||
connecter.Send(new Message<SwapMassage> { 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}");
|
_logger.LogDebug($"连接server成功 {request.MsgId}");
|
||||||
var localConnecter = new DnsSocket(request.WebConfig.LocalIp, request.WebConfig.LocalPort);
|
var localConnecter = new DnsSocket(request.WebConfig.LocalIp, request.WebConfig.LocalPort);
|
||||||
|
@ -45,28 +65,25 @@ namespace FastTunnel.Core.Handlers.Client
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
localConnecter.Connect();
|
localConnecter.Connect();
|
||||||
_logger.LogDebug($"连接本地成功 {request.MsgId}");
|
|
||||||
|
|
||||||
new SocketSwap(connecter.Socket, localConnecter.Socket, _logger, request.MsgId).StartSwap();
|
|
||||||
}
|
}
|
||||||
catch (SocketException sex)
|
catch (SocketException sex)
|
||||||
{
|
{
|
||||||
localConnecter.Close();
|
|
||||||
if (sex.ErrorCode == 10061)
|
if (sex.ErrorCode == 10061)
|
||||||
{
|
{
|
||||||
|
_logger.LogInformation($"内网服务不存在:{request.WebConfig.LocalIp}:{request.WebConfig.LocalPort}");
|
||||||
// 内网的站点不存在或无法访问
|
// 内网的站点不存在或无法访问
|
||||||
string statusLine = "HTTP/1.1 200 OK\r\n";
|
//string statusLine = "HTTP/1.1 200 OK\r\n";
|
||||||
string responseHeader = "Content-Type: text/html\r\n";
|
//string responseHeader = "Content-Type: text/html\r\n";
|
||||||
byte[] responseBody;
|
//byte[] responseBody;
|
||||||
responseBody = Encoding.UTF8.GetBytes(TunnelResource.Page_NoSite);
|
//responseBody = Encoding.UTF8.GetBytes(TunnelResource.Page_NoSite);
|
||||||
|
|
||||||
connecter.Send(Encoding.UTF8.GetBytes(statusLine));
|
//connecter.Send(Encoding.UTF8.GetBytes(statusLine));
|
||||||
connecter.Send(Encoding.UTF8.GetBytes(responseHeader));
|
//connecter.Send(Encoding.UTF8.GetBytes(responseHeader));
|
||||||
connecter.Send(Encoding.UTF8.GetBytes("\r\n"));
|
//connecter.Send(Encoding.UTF8.GetBytes("\r\n"));
|
||||||
connecter.Send(responseBody);
|
//connecter.Send(responseBody);
|
||||||
|
|
||||||
connecter.Socket.Disconnect(false);
|
//connecter.Socket.Disconnect(false);
|
||||||
connecter.Socket.Close();
|
//connecter.Socket.Close();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -79,6 +96,31 @@ namespace FastTunnel.Core.Handlers.Client
|
||||||
localConnecter.Close();
|
localConnecter.Close();
|
||||||
throw;
|
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}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
using FastTunnel.Core.Config;
|
using FastTunnel.Core.Config;
|
||||||
using FastTunnel.Core.Client;
|
using FastTunnel.Core.Client;
|
||||||
using FastTunnel.Core.Models;
|
using FastTunnel.Core.Models;
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace FastTunnel.Core.Handlers.Client
|
namespace FastTunnel.Core.Handlers.Client
|
||||||
{
|
{
|
||||||
public interface IClientHandler
|
public interface IClientHandler
|
||||||
{
|
{
|
||||||
public void HandlerMsg(FastTunnelClient cleint, Message<JObject> Msg);
|
Task HandlerMsgAsync<T>(FastTunnelClient cleint, T Msg) where T : TunnelMassage;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
using FastTunnel.Core.Config;
|
using FastTunnel.Core.Config;
|
||||||
using FastTunnel.Core.Models;
|
using FastTunnel.Core.Models;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using System;
|
using System;
|
||||||
using FastTunnel.Core.Extensions;
|
using FastTunnel.Core.Extensions;
|
||||||
using FastTunnel.Core.Client;
|
using FastTunnel.Core.Client;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace FastTunnel.Core.Handlers.Client
|
namespace FastTunnel.Core.Handlers.Client
|
||||||
{
|
{
|
||||||
|
@ -17,11 +17,13 @@ namespace FastTunnel.Core.Handlers.Client
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void HandlerMsg(FastTunnelClient cleint, Message<JObject> Msg)
|
public async Task HandlerMsgAsync<T>(FastTunnelClient cleint, T Msg)
|
||||||
|
where T : TunnelMassage
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var msg = Msg.Content.ToObject<LogMassage>();
|
await Task.Yield();
|
||||||
|
var msg = Msg as LogMassage;
|
||||||
|
|
||||||
switch (msg.MsgType)
|
switch (msg.MsgType)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,33 +1,35 @@
|
||||||
using FastTunnel.Core.Config;
|
using FastTunnel.Core.Config;
|
||||||
using FastTunnel.Core.Client;
|
using FastTunnel.Core.Client;
|
||||||
using FastTunnel.Core.Models;
|
using FastTunnel.Core.Models;
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using FastTunnel.Core.Sockets;
|
using FastTunnel.Core.Sockets;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace FastTunnel.Core.Handlers.Client
|
namespace FastTunnel.Core.Handlers.Client
|
||||||
{
|
{
|
||||||
public class NewSSHHandler : IClientHandler
|
public class NewForwardHandler : IClientHandler
|
||||||
{
|
{
|
||||||
ILogger<NewSSHHandler> _logger;
|
ILogger<NewForwardHandler> _logger;
|
||||||
public NewSSHHandler(ILogger<NewSSHHandler> logger)
|
public NewForwardHandler(ILogger<NewForwardHandler> logger)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void HandlerMsg(FastTunnelClient cleint, Message<JObject> Msg)
|
public async Task HandlerMsgAsync<T>(FastTunnelClient cleint, T Msg)
|
||||||
|
where T : TunnelMassage
|
||||||
{
|
{
|
||||||
var request_ssh = Msg.Content.ToObject<NewSSHRequest>();
|
var request_ssh = Msg as NewForwardMessage;
|
||||||
|
await Task.Yield();
|
||||||
|
|
||||||
var connecter_ssh = new DnsSocket(cleint.Server.ServerAddr, cleint.Server.ServerPort);
|
var connecter_ssh = new DnsSocket(cleint.Server.ServerAddr, cleint.Server.ServerPort);
|
||||||
connecter_ssh.Connect();
|
connecter_ssh.Connect();
|
||||||
connecter_ssh.Send(new Message<SwapMassage> { MessageType = MessageType.C_SwapMsg, Content = new SwapMassage(request_ssh.MsgId) });
|
connecter_ssh.Send(new Message<SwapMassage> { MessageType = MessageType.C_SwapMsg, Content = new SwapMassage(request_ssh.MsgId) });
|
||||||
|
|
||||||
var localConnecter_ssh = new DnsSocket(request_ssh.SSHConfig.LocalIp, request_ssh.SSHConfig.LocalPort);
|
var localConnecter_ssh = new DnsSocket(request_ssh.SSHConfig.LocalIp, request_ssh.SSHConfig.LocalPort);
|
||||||
localConnecter_ssh.Connect();
|
localConnecter_ssh.Connect();
|
||||||
|
|
||||||
new SocketSwap(connecter_ssh.Socket, localConnecter_ssh.Socket, _logger, request_ssh.MsgId).StartSwap();
|
new SocketSwap(connecter_ssh.Socket, localConnecter_ssh.Socket, _logger, request_ssh.MsgId).StartSwap();
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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<LogInMassage>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,11 +1,12 @@
|
||||||
using FastTunnel.Core.Client;
|
using FastTunnel.Core.Client;
|
||||||
using FastTunnel.Core.Extensions;
|
using FastTunnel.Core.Extensions;
|
||||||
using FastTunnel.Core.Models;
|
using FastTunnel.Core.Models;
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
|
using System.Net.WebSockets;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace FastTunnel.Core.Handlers.Server
|
namespace FastTunnel.Core.Handlers.Server
|
||||||
{
|
{
|
||||||
|
@ -13,9 +14,11 @@ namespace FastTunnel.Core.Handlers.Server
|
||||||
{
|
{
|
||||||
public bool NeedRecive => true;
|
public bool NeedRecive => true;
|
||||||
|
|
||||||
public void HandlerMsg(FastTunnelServer server, Socket client, Message<JObject> msg)
|
public async Task<bool> HandlerMsg<T>(FastTunnelServer server, WebSocket client, T msg)
|
||||||
|
where T : TunnelMassage
|
||||||
{
|
{
|
||||||
client.SendCmd(new Message<HeartMassage>() { MessageType = MessageType.Heart, Content = null });
|
await client.SendCmdAsync(new Message<HeartMassage>() { MessageType = MessageType.Heart, Content = new HeartMassage { } });
|
||||||
|
return NeedRecive;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
using FastTunnel.Core.Client;
|
using FastTunnel.Core.Client;
|
||||||
using FastTunnel.Core.Models;
|
using FastTunnel.Core.Models;
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
|
using System.Net.WebSockets;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace FastTunnel.Core.Handlers
|
namespace FastTunnel.Core.Handlers
|
||||||
{
|
{
|
||||||
|
@ -12,6 +13,8 @@ namespace FastTunnel.Core.Handlers
|
||||||
{
|
{
|
||||||
Boolean NeedRecive { get; }
|
Boolean NeedRecive { get; }
|
||||||
|
|
||||||
void HandlerMsg(FastTunnelServer server, Socket client, Message<JObject> msg);
|
Task<bool> HandlerMsg<T>(FastTunnelServer server, WebSocket client, T msg) where T : TunnelMassage;
|
||||||
|
|
||||||
|
//void HandlerMsg(FastTunnelServer server, Socket client, Message<JObject> msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -7,12 +7,13 @@ using FastTunnel.Core.Handlers.Server;
|
||||||
using FastTunnel.Core.Listener;
|
using FastTunnel.Core.Listener;
|
||||||
using FastTunnel.Core.Models;
|
using FastTunnel.Core.Models;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
|
using System.Net.WebSockets;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using Yarp.ReverseProxy.Configuration;
|
using Yarp.ReverseProxy.Configuration;
|
||||||
using Yarp.Sample;
|
using Yarp.Sample;
|
||||||
|
|
||||||
|
@ -23,7 +24,6 @@ namespace FastTunnel.Core.Handlers
|
||||||
ILogger _logger;
|
ILogger _logger;
|
||||||
|
|
||||||
public bool NeedRecive => true;
|
public bool NeedRecive => true;
|
||||||
IConfigHandler _configHandler;
|
|
||||||
|
|
||||||
static object _locker = new object();
|
static object _locker = new object();
|
||||||
IProxyConfigProvider proxyConfig;
|
IProxyConfigProvider proxyConfig;
|
||||||
|
@ -32,47 +32,12 @@ namespace FastTunnel.Core.Handlers
|
||||||
{
|
{
|
||||||
this.proxyConfig = proxyConfig;
|
this.proxyConfig = proxyConfig;
|
||||||
this._logger = logger;
|
this._logger = logger;
|
||||||
|
|
||||||
var custome = FastTunnelGlobal.GetCustomHandler<IConfigHandler>();
|
|
||||||
this._configHandler = custome == null ? new ConfigHandler() : custome;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public LogInMassage GetConfig(JObject content)
|
private async Task HandleLoginAsync(FastTunnelServer server, WebSocket client, LogInMassage requet)
|
||||||
{
|
|
||||||
return _configHandler.GetConfig(content);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void HandlerMsg(FastTunnelServer server, Socket client, Message<JObject> msg)
|
|
||||||
{
|
|
||||||
lock (_locker)
|
|
||||||
{
|
|
||||||
HandleLogin(server, client, GetConfig(msg.Content));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void HandleLogin(FastTunnelServer server, Socket client, LogInMassage requet)
|
|
||||||
{
|
{
|
||||||
bool hasTunnel = false;
|
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<LogMassage>
|
|
||||||
{
|
|
||||||
MessageType = MessageType.Log,
|
|
||||||
Content = new LogMassage(LogMsgType.Error, "认证失败")
|
|
||||||
});
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var sb = new StringBuilder($"{Environment.NewLine}=====隧道已建立成功,可通过以下方式访问内网服务====={Environment.NewLine}{Environment.NewLine}");
|
var sb = new StringBuilder($"{Environment.NewLine}=====隧道已建立成功,可通过以下方式访问内网服务====={Environment.NewLine}{Environment.NewLine}");
|
||||||
sb.Append($"穿透协议 | 映射关系(公网=>内网){Environment.NewLine}");
|
sb.Append($"穿透协议 | 映射关系(公网=>内网){Environment.NewLine}");
|
||||||
if (requet.Webs != null && requet.Webs.Count() > 0)
|
if (requet.Webs != null && requet.Webs.Count() > 0)
|
||||||
|
@ -114,11 +79,11 @@ namespace FastTunnel.Core.Handlers
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (item.RemotePort.Equals(server.serverOption.CurrentValue.BindPort))
|
//if (item.RemotePort.Equals(server.serverOption.CurrentValue.BindPort))
|
||||||
{
|
//{
|
||||||
_logger.LogError($"RemotePort can not be same with BindPort: {item.RemotePort}");
|
// _logger.LogError($"RemotePort can not be same with BindPort: {item.RemotePort}");
|
||||||
continue;
|
// continue;
|
||||||
}
|
//}
|
||||||
|
|
||||||
if (item.RemotePort.Equals(server.serverOption.CurrentValue.WebProxyPort))
|
if (item.RemotePort.Equals(server.serverOption.CurrentValue.WebProxyPort))
|
||||||
{
|
{
|
||||||
|
@ -126,20 +91,20 @@ namespace FastTunnel.Core.Handlers
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
SSHInfo<SSHHandlerArg> old;
|
ForwardInfo<ForwardHandlerArg> old;
|
||||||
if (server.SSHList.TryGetValue(item.RemotePort, out old))
|
if (server.SSHList.TryGetValue(item.RemotePort, out old))
|
||||||
{
|
{
|
||||||
_logger.LogDebug($"Remove Listener {old.Listener.ListenIp}:{old.Listener.ListenPort}");
|
_logger.LogDebug($"Remove Listener {old.Listener.ListenIp}:{old.Listener.ListenPort}");
|
||||||
old.Listener.Stop();
|
old.Listener.Stop();
|
||||||
server.SSHList.TryRemove(item.RemotePort, out SSHInfo<SSHHandlerArg> _);
|
server.SSHList.TryRemove(item.RemotePort, out ForwardInfo<ForwardHandlerArg> _);
|
||||||
}
|
}
|
||||||
|
|
||||||
var ls = new PortProxyListener("0.0.0.0", item.RemotePort, _logger);
|
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
|
// listen success
|
||||||
server.SSHList.TryAdd(item.RemotePort, new SSHInfo<SSHHandlerArg> { Listener = ls, Socket = client, SSHConfig = item });
|
server.SSHList.TryAdd(item.RemotePort, new ForwardInfo<ForwardHandlerArg> { Listener = ls, Socket = client, SSHConfig = item });
|
||||||
_logger.LogDebug($"SSH proxy success: {item.RemotePort} => {item.LocalIp}:{item.LocalPort}");
|
_logger.LogDebug($"SSH proxy success: {item.RemotePort} => {item.LocalIp}:{item.LocalPort}");
|
||||||
|
|
||||||
sb.Append($" TCP | {server.serverOption.CurrentValue.WebDomain}:{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($"SSH proxy error: {item.RemotePort} => {item.LocalIp}:{item.LocalPort}");
|
||||||
_logger.LogError(ex.Message);
|
_logger.LogError(ex.Message);
|
||||||
client.SendCmd(new Message<LogMassage> { MessageType = MessageType.Log, Content = new LogMassage(LogMsgType.Info, ex.Message) });
|
await client.SendCmdAsync(new Message<LogMassage> { MessageType = MessageType.Log, Content = new LogMassage(LogMsgType.Info, ex.Message) });
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -157,13 +122,20 @@ namespace FastTunnel.Core.Handlers
|
||||||
|
|
||||||
if (!hasTunnel)
|
if (!hasTunnel)
|
||||||
{
|
{
|
||||||
client.SendCmd(new Message<LogMassage> { MessageType = MessageType.Log, Content = new LogMassage(LogMsgType.Info, TunnelResource.NoTunnel) });
|
await client.SendCmdAsync(new Message<LogMassage> { MessageType = MessageType.Log, Content = new LogMassage(LogMsgType.Info, TunnelResource.NoTunnel) });
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sb.Append($"{Environment.NewLine}====================================================");
|
sb.Append($"{Environment.NewLine}====================================================");
|
||||||
client.SendCmd(new Message<LogMassage> { MessageType = MessageType.Log, Content = new LogMassage(LogMsgType.Info, sb.ToString()) });
|
await client.SendCmdAsync(new Message<LogMassage> { MessageType = MessageType.Log, Content = new LogMassage(LogMsgType.Info, sb.ToString()) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<bool> HandlerMsg<T>(FastTunnelServer server, WebSocket client, T msg)
|
||||||
|
where T : TunnelMassage
|
||||||
|
{
|
||||||
|
await HandleLoginAsync(server, client, msg as LogInMassage);
|
||||||
|
return NeedRecive;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ using Newtonsoft.Json.Linq;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
|
using System.Net.WebSockets;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
@ -38,7 +39,6 @@ namespace FastTunnel.Core.Handlers.Server
|
||||||
server.ResponseTasks.TryRemove(SwapMsg.msgId, out _);
|
server.ResponseTasks.TryRemove(SwapMsg.msgId, out _);
|
||||||
|
|
||||||
_logger.LogDebug($"SwapMassage:{SwapMsg.msgId}");
|
_logger.LogDebug($"SwapMassage:{SwapMsg.msgId}");
|
||||||
|
|
||||||
response.SetResult(new NetworkStream(client, true));
|
response.SetResult(new NetworkStream(client, true));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -59,5 +59,10 @@ namespace FastTunnel.Core.Handlers.Server
|
||||||
client.Close();
|
client.Close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Task<bool> HandlerMsg(FastTunnelServer server, WebSocket client, Message<JObject> msg)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
19
FastTunnel.Core/HeaderConst.cs
Normal file
19
FastTunnel.Core/HeaderConst.cs
Normal file
|
@ -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";
|
||||||
|
}
|
||||||
|
}
|
|
@ -43,7 +43,7 @@ namespace FastTunnel.Core.Listener
|
||||||
_heartHandler = new HeartMessageHandler();
|
_heartHandler = new HeartMessageHandler();
|
||||||
_swapMsgHandler = new SwapMessageHandler(_logger);
|
_swapMsgHandler = new SwapMessageHandler(_logger);
|
||||||
|
|
||||||
server = new Server.Server(2000, 100, false, _logger);
|
server = new Server.Server(10000, 100, false, _logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Start()
|
public void Start()
|
||||||
|
|
|
@ -108,7 +108,7 @@ namespace FastTunnel.Core.Listener
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// 将此客户端交由Dispatcher进行管理
|
// 将此客户端交由Dispatcher进行管理
|
||||||
_requestDispatcher.Dispatch(accept);
|
_requestDispatcher.DispatchAsync(accept);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|
|
@ -4,7 +4,7 @@ using System.Text;
|
||||||
|
|
||||||
namespace FastTunnel.Core.Models
|
namespace FastTunnel.Core.Models
|
||||||
{
|
{
|
||||||
public class SSHConfig
|
public class ForwardConfig
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 局域网IP地址
|
/// 局域网IP地址
|
|
@ -5,9 +5,9 @@ using System.Text;
|
||||||
|
|
||||||
namespace FastTunnel.Core.Models
|
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; }
|
public Socket LocalClient { get; internal set; }
|
||||||
}
|
}
|
|
@ -2,15 +2,16 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
|
using System.Net.WebSockets;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace FastTunnel.Core.Models
|
namespace FastTunnel.Core.Models
|
||||||
{
|
{
|
||||||
public class SSHInfo<T>
|
public class ForwardInfo<T>
|
||||||
{
|
{
|
||||||
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; }
|
public IListener Listener { get; set; }
|
||||||
}
|
}
|
|
@ -6,5 +6,6 @@ namespace FastTunnel.Core.Models
|
||||||
{
|
{
|
||||||
public class HeartMassage : TunnelMassage
|
public class HeartMassage : TunnelMassage
|
||||||
{
|
{
|
||||||
|
public string Time { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,6 @@ namespace FastTunnel.Core.Models
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 端口转发隧道列表
|
/// 端口转发隧道列表
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IEnumerable<SSHConfig> SSH { get; set; }
|
public IEnumerable<ForwardConfig> SSH { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,10 +4,10 @@ using System.Text;
|
||||||
|
|
||||||
namespace FastTunnel.Core.Models
|
namespace FastTunnel.Core.Models
|
||||||
{
|
{
|
||||||
public class NewSSHRequest : TunnelMassage
|
public class NewForwardMessage : TunnelMassage
|
||||||
{
|
{
|
||||||
public string MsgId { get; set; }
|
public string MsgId { get; set; }
|
||||||
|
|
||||||
public SSHConfig SSHConfig { get; set; }
|
public ForwardConfig SSHConfig { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,11 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace FastTunnel.Core.Models
|
|
||||||
{
|
|
||||||
public enum Protocol
|
|
||||||
{
|
|
||||||
TCP = 0,
|
|
||||||
}
|
|
||||||
}
|
|
90
FastTunnel.Core/Models/TunnelClient.cs
Normal file
90
FastTunnel.Core/Models/TunnelClient.cs
Normal file
|
@ -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<bool> 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<LogInMassage>(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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,13 +1,15 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
|
using System.Net.WebSockets;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace FastTunnel.Core.Models
|
namespace FastTunnel.Core.Models
|
||||||
{
|
{
|
||||||
public class WebInfo
|
public class WebInfo
|
||||||
{
|
{
|
||||||
public Socket Socket { get; set; }
|
public WebSocket Socket { get; set; }
|
||||||
|
|
||||||
public WebConfig WebConfig { get; set; }
|
public WebConfig WebConfig { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
40
FastTunnel.Core/Protocol/TunnelProtocol.cs
Normal file
40
FastTunnel.Core/Protocol/TunnelProtocol.cs
Normal file
|
@ -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<string> 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,7 +7,6 @@ using Microsoft.Extensions.Logging;
|
||||||
using System;
|
using System;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Newtonsoft.Json;
|
|
||||||
using System.Runtime.ExceptionServices;
|
using System.Runtime.ExceptionServices;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
|
||||||
|
@ -31,7 +30,7 @@ namespace FastTunnel.Core.Services
|
||||||
{
|
{
|
||||||
return Task.Run(() =>
|
return Task.Run(() =>
|
||||||
{
|
{
|
||||||
_fastTunnelClient.Start();
|
_fastTunnelClient.StartAsync(cancellationToken);
|
||||||
}, cancellationToken);
|
}, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,7 +45,6 @@ namespace FastTunnel.Core.Services
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_logger.LogError("【UnhandledException】" + e.ExceptionObject);
|
_logger.LogError("【UnhandledException】" + e.ExceptionObject);
|
||||||
_logger.LogError("【UnhandledException】" + JsonConvert.SerializeObject(e.ExceptionObject));
|
|
||||||
var type = e.ExceptionObject.GetType();
|
var type = e.ExceptionObject.GetType();
|
||||||
_logger.LogError("ExceptionObject GetType " + type);
|
_logger.LogError("ExceptionObject GetType " + type);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@ using FastTunnel.Core.Global;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Newtonsoft.Json;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
@ -40,7 +39,6 @@ namespace FastTunnel.Core.Services
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_logger.LogError("【UnhandledException】" + e.ExceptionObject);
|
_logger.LogError("【UnhandledException】" + e.ExceptionObject);
|
||||||
_logger.LogError("【UnhandledException】" + JsonConvert.SerializeObject(e.ExceptionObject));
|
|
||||||
var type = e.ExceptionObject.GetType();
|
var type = e.ExceptionObject.GetType();
|
||||||
_logger.LogError("ExceptionObject GetType " + type);
|
_logger.LogError("ExceptionObject GetType " + type);
|
||||||
}
|
}
|
||||||
|
|
51
FastTunnel.Core/Sockets/DefultClientSocket.cs
Normal file
51
FastTunnel.Core/Sockets/DefultClientSocket.cs
Normal file
|
@ -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<int> ReceiveAsync(byte[] buffer, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var res = await webSocket.ReceiveAsync(buffer, cancellationToken);
|
||||||
|
return res.Count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task SendAsync<T>(Message<T> msg, CancellationToken cancellationToken)
|
||||||
|
where T : TunnelMassage
|
||||||
|
{
|
||||||
|
await webSocket.SendCmdAsync(msg, WebSocketMessageType.Binary, false, cancellationToken);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
22
FastTunnel.Core/Sockets/IFastTunnelClientSocket.cs
Normal file
22
FastTunnel.Core/Sockets/IFastTunnelClientSocket.cs
Normal file
|
@ -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<int> ReceiveAsync(byte[] buffer, CancellationToken cancellationToken);
|
||||||
|
|
||||||
|
Task SendAsync<T>(Message<T> loginMsg, CancellationToken cancellationToken)
|
||||||
|
where T : TunnelMassage;
|
||||||
|
|
||||||
|
Task ConnectAsync(Uri url, CancellationToken cancellationToken);
|
||||||
|
|
||||||
|
Task CloseAsync();
|
||||||
|
}
|
||||||
|
}
|
99
FastTunnel.Core/Sockets/ReadWriteStreamSwap.cs
Normal file
99
FastTunnel.Core/Sockets/ReadWriteStreamSwap.cs
Normal file
|
@ -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}");
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,6 +2,7 @@
|
||||||
using FastTunnel.Core.Utility.Extensions;
|
using FastTunnel.Core.Utility.Extensions;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Buffers;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
|
|
98
FastTunnel.Core/Sockets/StreamSwap.cs
Normal file
98
FastTunnel.Core/Sockets/StreamSwap.cs
Normal file
|
@ -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<HttpRequestHandler> logger;
|
||||||
|
private string msgId;
|
||||||
|
|
||||||
|
public StreamSwap(Stream serverConnection, NetworkStream localConn, ILogger<HttpRequestHandler> 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}");
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,11 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
|
|
||||||
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8" />
|
|
||||||
<title></title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div style="text-align:center;">Coming soon!</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -1,12 +0,0 @@
|
||||||
{
|
|
||||||
"version": 1,
|
|
||||||
"isRoot": true,
|
|
||||||
"tools": {
|
|
||||||
"dotnet-ef": {
|
|
||||||
"version": "3.1.9",
|
|
||||||
"commands": [
|
|
||||||
"dotnet-ef"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -21,10 +21,10 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Update="卸载服务.bat">
|
<None Update="uninstall.bat">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</None>
|
</None>
|
||||||
<None Update="安装服务.bat">
|
<None Update="install.bat">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</None>
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
|
@ -2,6 +2,8 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using FastTunnel.Core.Extensions;
|
using FastTunnel.Core.Extensions;
|
||||||
using FastTunnel.Core.Forwarder;
|
using FastTunnel.Core.Forwarder;
|
||||||
|
using FastTunnel.Core.Forwarder.MiddleWare;
|
||||||
|
using FastTunnel.Core.MiddleWares;
|
||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
|
@ -35,6 +37,8 @@ namespace FastTunnel.Server
|
||||||
|
|
||||||
// ------------------------Custom Business------------------------------
|
// ------------------------Custom Business------------------------------
|
||||||
services.AddSingleton<IForwarderHttpClientFactory, FastTunnelForwarderHttpClientFactory>();
|
services.AddSingleton<IForwarderHttpClientFactory, FastTunnelForwarderHttpClientFactory>();
|
||||||
|
services.AddSingleton<FastTunnelClientHandler, FastTunnelClientHandler>();
|
||||||
|
services.AddSingleton<FastTunnelSwapHandler, FastTunnelSwapHandler>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
// 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<FastTunnelSwapHandler>();
|
||||||
|
var clientHandler = app.ApplicationServices.GetRequiredService<FastTunnelClientHandler>();
|
||||||
|
app.Use(clientHandler.Handle);
|
||||||
|
app.Use(swapHandler.Handle);
|
||||||
|
|
||||||
app.UseRouting();
|
app.UseRouting();
|
||||||
|
|
||||||
app.UseEndpoints(endpoints =>
|
app.UseEndpoints(endpoints =>
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
{
|
{
|
||||||
|
"urls": "http://*:1270;", // Http¼àÌý¶Ë¿Ú
|
||||||
"Logging": {
|
"Logging": {
|
||||||
"LogLevel": {
|
"LogLevel": {
|
||||||
// Trace Debug Information Warning Error
|
// Trace Debug Information Warning Error
|
||||||
|
@ -10,14 +11,11 @@
|
||||||
"AllowedHosts": "*",
|
"AllowedHosts": "*",
|
||||||
"ServerSettings": {
|
"ServerSettings": {
|
||||||
// 监听端口
|
// 监听端口
|
||||||
"BindPort": 1271,
|
//"BindPort": 1271,
|
||||||
|
|
||||||
// 绑定域名
|
// 绑定域名
|
||||||
"WebDomain": "test.cc",
|
"WebDomain": "test.cc",
|
||||||
|
|
||||||
// Http监听端口, 访问自定义域名站点时url为 http://{SubDomain}.{WebDomain}:{WebProxyPort}/
|
|
||||||
"WebProxyPort": 1270,
|
|
||||||
|
|
||||||
// 可选,ngixn反向代理后可省略域名后的端口号进行访问
|
// 可选,ngixn反向代理后可省略域名后的端口号进行访问
|
||||||
"WebHasNginxProxy": false,
|
"WebHasNginxProxy": false,
|
||||||
|
|
||||||
|
@ -25,6 +23,6 @@
|
||||||
"WebAllowAccessIps": [],
|
"WebAllowAccessIps": [],
|
||||||
|
|
||||||
// 可选,是否开启SSH,禁用后不处理SSH类型端口转发.默认false。
|
// 可选,是否开启SSH,禁用后不处理SSH类型端口转发.默认false。
|
||||||
"SSHEnabled": true
|
"EnableForward": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user