mirror of
https://github.com/FastTunnel/FastTunnel.git
synced 2025-02-08 02:39:29 +08:00
更新通讯协议
This commit is contained in:
parent
ff32f44223
commit
b6a1aaeb71
|
@ -15,6 +15,10 @@
|
|||
// 服务端监听的通信端口
|
||||
"ServerPort": 1270
|
||||
},
|
||||
/**
|
||||
* 通过自定义域名访问内网服务,需要有自己的域名
|
||||
* 可穿透所有TCP上层协议
|
||||
*/
|
||||
"Webs": [
|
||||
{
|
||||
// 本地站点所在内网的ip
|
||||
|
@ -37,8 +41,8 @@
|
|||
],
|
||||
|
||||
/**
|
||||
* 端口转发
|
||||
* 访问内网主机/mysql/erp/等任何TCP协议服务
|
||||
* 端口转发 通过专用端口代理,不需要有自己的域名
|
||||
* 可穿透所有TCP上层协议
|
||||
* 远程linux示例:#ssh -oPort=12701 {root}@{ServerAddr} ServerAddr 填入服务端ip,root对应内网用户名
|
||||
* 通过服务端返回的访问方式进行访问即可
|
||||
*/
|
||||
|
|
|
@ -15,38 +15,38 @@ using Microsoft.Extensions.Options;
|
|||
using System.Net.WebSockets;
|
||||
using System.Text.Json;
|
||||
using FastTunnel.Core.Protocol;
|
||||
using Microsoft.AspNetCore.DataProtection;
|
||||
|
||||
namespace FastTunnel.Core.Client
|
||||
{
|
||||
public class FastTunnelClient : IFastTunnelClient
|
||||
{
|
||||
private IFastTunnelClientSocket socket;
|
||||
private ClientWebSocket socket;
|
||||
protected ILogger<FastTunnelClient> _logger;
|
||||
public DateTime lastHeart;
|
||||
|
||||
HttpRequestHandler _newCustomerHandler;
|
||||
NewForwardHandler _newSSHHandler;
|
||||
ForwardHandler _newCustomerHandler;
|
||||
LogHandler _logHandler;
|
||||
ClientHeartHandler _clientHeartHandler;
|
||||
Message<LogInMassage> loginMsg;
|
||||
protected readonly IOptionsMonitor<DefaultClientConfig> _configuration;
|
||||
|
||||
public DefaultClientConfig ClientConfig { get; private set; }
|
||||
private readonly CancellationTokenSource cancellationTokenSource = new();
|
||||
|
||||
public SuiDaoServer Server { get; protected set; }
|
||||
|
||||
public FastTunnelClient(
|
||||
ILogger<FastTunnelClient> logger,
|
||||
HttpRequestHandler newCustomerHandler,
|
||||
NewForwardHandler newSSHHandler, LogHandler logHandler,
|
||||
ForwardHandler newCustomerHandler,
|
||||
LogHandler logHandler,
|
||||
IOptionsMonitor<DefaultClientConfig> configuration,
|
||||
ClientHeartHandler clientHeartHandler)
|
||||
{
|
||||
_logger = logger;
|
||||
_newCustomerHandler = newCustomerHandler;
|
||||
_newSSHHandler = newSSHHandler;
|
||||
_logHandler = logHandler;
|
||||
_clientHeartHandler = clientHeartHandler;
|
||||
_configuration = configuration;
|
||||
ClientConfig = configuration.CurrentValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -59,23 +59,26 @@ namespace FastTunnel.Core.Client
|
|||
CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, this.cancellationTokenSource.Token);
|
||||
|
||||
_logger.LogInformation("===== FastTunnel Client Start =====");
|
||||
socket = await loginAsync(cancellationToken);
|
||||
await loginAsync(cancellationToken);
|
||||
_logger.LogInformation($"通讯已建立");
|
||||
await ReceiveServerAsync(socket);
|
||||
await ReceiveServerAsync();
|
||||
}
|
||||
|
||||
protected virtual async Task<IFastTunnelClientSocket> loginAsync(CancellationToken cancellationToken)
|
||||
protected virtual async Task loginAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
Server = _configuration.CurrentValue.Server;
|
||||
Server = ClientConfig.Server;
|
||||
_logger.LogInformation($"正在连接服务端 {Server.ServerAddr}:{Server.ServerPort}");
|
||||
|
||||
try
|
||||
{
|
||||
// 连接到的目标IP
|
||||
socket = new DefultClientSocket();
|
||||
socket = new ClientWebSocket();
|
||||
socket.Options.RemoteCertificateValidationCallback = delegate { return true; };
|
||||
socket.Options.SetRequestHeader(HeaderConst.FASTTUNNEL_FLAG, "2.0.0");
|
||||
socket.Options.SetRequestHeader(HeaderConst.FASTTUNNEL_TYPE, HeaderConst.TYPE_CLIENT);
|
||||
|
||||
await socket.ConnectAsync(
|
||||
new Uri($"ws://{_configuration.CurrentValue.Server.ServerAddr}:{_configuration.CurrentValue.Server.ServerPort}"), cancellationToken);
|
||||
new Uri($"ws://{ClientConfig.Server.ServerAddr}:{ClientConfig.Server.ServerPort}"), cancellationToken);
|
||||
|
||||
_logger.LogInformation("连接成功");
|
||||
}
|
||||
|
@ -84,70 +87,48 @@ namespace FastTunnel.Core.Client
|
|||
throw;
|
||||
}
|
||||
|
||||
loginMsg = new Message<LogInMassage>
|
||||
{
|
||||
MessageType = MessageType.C_LogIn,
|
||||
Content = new LogInMassage
|
||||
{
|
||||
Webs = _configuration.CurrentValue.Webs,
|
||||
Forwards = _configuration.CurrentValue.Forwards,
|
||||
},
|
||||
};
|
||||
|
||||
// 登录
|
||||
await socket.SendAsync(loginMsg, cancellationToken);
|
||||
return socket;
|
||||
await socket.SendCmdAsync(MessageType.LogIn, new LogInMassage
|
||||
{
|
||||
Webs = ClientConfig.Webs,
|
||||
Forwards = ClientConfig.Forwards,
|
||||
}.ToJson());
|
||||
}
|
||||
|
||||
private async Task ReceiveServerAsync(IFastTunnelClientSocket client)
|
||||
private async Task ReceiveServerAsync()
|
||||
{
|
||||
byte[] buffer = new byte[512];
|
||||
var tunnelProtocol = new TunnelProtocol();
|
||||
byte[] buffer = new byte[128];
|
||||
|
||||
while (true)
|
||||
{
|
||||
var res = await client.ReceiveAsync(buffer, CancellationToken.None);
|
||||
var cmds = tunnelProtocol.HandleBuffer(buffer, 0, res);
|
||||
|
||||
if (cmds == null)
|
||||
continue;
|
||||
|
||||
foreach (var item in cmds)
|
||||
{
|
||||
HandleServerRequestAsync(item);
|
||||
}
|
||||
var res = await socket.ReceiveAsync(buffer, CancellationToken.None);
|
||||
var type = buffer[0];
|
||||
var content = Encoding.UTF8.GetString(buffer, 1, res.Count - 1);
|
||||
HandleServerRequestAsync(type, content);
|
||||
}
|
||||
}
|
||||
|
||||
private async void HandleServerRequestAsync(string lineCmd)
|
||||
private async void HandleServerRequestAsync(byte cmd, string ctx)
|
||||
{
|
||||
try
|
||||
{
|
||||
var cmds = lineCmd.Split("||");
|
||||
var type = cmds[0];
|
||||
|
||||
_logger.LogInformation($"处理 {type}");
|
||||
TunnelMassage msg = null;
|
||||
IClientHandler handler;
|
||||
switch (type)
|
||||
switch ((MessageType)cmd)
|
||||
{
|
||||
case "S_NewCustomer":
|
||||
case MessageType.SwapMsg:
|
||||
handler = _newCustomerHandler;
|
||||
msg = JsonSerializer.Deserialize<NewCustomerMassage>(cmds[1]);
|
||||
break;
|
||||
case "S_NewSSH":
|
||||
handler = _newSSHHandler;
|
||||
msg = JsonSerializer.Deserialize<NewForwardMessage>(cmds[1]);
|
||||
case MessageType.Forward:
|
||||
handler = _newCustomerHandler;
|
||||
break;
|
||||
case "Log":
|
||||
case MessageType.Log:
|
||||
handler = _logHandler;
|
||||
msg = JsonSerializer.Deserialize<LogMassage>(cmds[1]);
|
||||
break;
|
||||
default:
|
||||
throw new Exception($"未处理的消息:{lineCmd}");
|
||||
throw new Exception($"未处理的消息:cmd={cmd}");
|
||||
}
|
||||
|
||||
await handler.HandlerMsgAsync(this, msg);
|
||||
await handler.HandlerMsgAsync(this, ctx);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
|
|
@ -36,8 +36,8 @@ namespace FastTunnel.Core.Extensions
|
|||
services.AddSingleton<IFastTunnelClient, FastTunnelClient>()
|
||||
.AddSingleton<ClientHeartHandler>()
|
||||
.AddSingleton<LogHandler>()
|
||||
.AddSingleton<HttpRequestHandler>()
|
||||
.AddSingleton<NewForwardHandler>();
|
||||
.AddSingleton<ForwardHandler>()
|
||||
.AddSingleton<ForwardHandler>();
|
||||
|
||||
services.AddHostedService<ServiceFastTunnelClient>();
|
||||
}
|
||||
|
|
|
@ -12,19 +12,13 @@ namespace FastTunnel.Core.Extensions
|
|||
{
|
||||
public static class WebSocketExtensions
|
||||
{
|
||||
public static async Task SendCmdAsync<T>(this WebSocket socket, Message<T> message,
|
||||
WebSocketMessageType webSocketMessage, bool end, CancellationToken cancellationToken)
|
||||
where T : TunnelMassage
|
||||
public static async Task SendCmdAsync(this WebSocket socket, MessageType type, string content)
|
||||
{
|
||||
var msg = Encoding.UTF8.GetBytes($"{message.MessageType.ToString()}||{message.Content.ToJson()}\n");
|
||||
await socket.SendAsync(msg, webSocketMessage, end, cancellationToken);
|
||||
}
|
||||
var buffer = Encoding.UTF8.GetBytes((char)type + content + "\n");
|
||||
if (type != MessageType.LogIn && buffer.Length > 128)
|
||||
throw new ArgumentOutOfRangeException(nameof(content));
|
||||
|
||||
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);
|
||||
await socket.SendAsync(buffer, WebSocketMessageType.Binary, false, CancellationToken.None);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -64,7 +64,7 @@ namespace FastTunnel.Core.Forwarder
|
|||
_logger.LogInformation($"[发送swap指令]:{RequestId}");
|
||||
|
||||
// 发送指令给客户端,等待建立隧道
|
||||
await web.Socket.SendCmdAsync(new Message<NewCustomerMassage> { MessageType = MessageType.S_NewCustomer, Content = new NewCustomerMassage { MsgId = RequestId, WebConfig = web.WebConfig } });
|
||||
await web.Socket.SendCmdAsync(MessageType.SwapMsg, $"{RequestId}|{web.WebConfig.LocalIp}:{web.WebConfig.LocalPort}");
|
||||
|
||||
// TODO:超时处理
|
||||
TaskCompletionSource<Stream> task = new(cancellation);
|
||||
|
|
|
@ -36,57 +36,15 @@ namespace FastTunnel.Core.MiddleWares
|
|||
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}");
|
||||
}
|
||||
await handleClient(context, next);
|
||||
}
|
||||
|
||||
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)
|
||||
private async Task handleClient(HttpContext context, Func<Task> next)
|
||||
{
|
||||
using var webSocket = await context.WebSockets.AcceptWebSocketAsync();
|
||||
var client = new TunnelClient(logger, webSocket, fastTunnelServer);
|
||||
|
||||
this.logger.LogInformation($"{client} 客户端连接成功");
|
||||
this.logger.LogInformation($"{webSocket} 客户端连接成功");
|
||||
|
||||
try
|
||||
{
|
||||
|
|
|
@ -10,7 +10,7 @@ namespace FastTunnel.Core.Handlers.Client
|
|||
{
|
||||
public class ClientHeartHandler : IClientHandler
|
||||
{
|
||||
public async Task HandlerMsgAsync<T>(FastTunnelClient cleint, T Msg) where T : TunnelMassage
|
||||
public async Task HandlerMsgAsync(FastTunnelClient cleint, string msg)
|
||||
{
|
||||
cleint.lastHeart = DateTime.Now;
|
||||
await Task.Yield();
|
||||
|
|
49
FastTunnel.Core/Handlers/Client/ForwardDispatcher.cs
Normal file
49
FastTunnel.Core/Handlers/Client/ForwardDispatcher.cs
Normal file
|
@ -0,0 +1,49 @@
|
|||
using FastTunnel.Core.Client;
|
||||
using FastTunnel.Core.Dispatchers;
|
||||
using FastTunnel.Core.Extensions;
|
||||
using FastTunnel.Core.Models;
|
||||
using Microsoft.AspNetCore.Hosting.Server;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net.Sockets;
|
||||
using System.Net.WebSockets;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FastTunnel.Core.Dispatchers
|
||||
{
|
||||
public class ForwardDispatcher
|
||||
{
|
||||
private FastTunnelServer _server;
|
||||
private WebSocket _client;
|
||||
private ForwardConfig _config;
|
||||
|
||||
public ForwardDispatcher(FastTunnelServer server, WebSocket client, ForwardConfig config)
|
||||
{
|
||||
_server = server;
|
||||
_client = client;
|
||||
_config = config;
|
||||
}
|
||||
|
||||
public async void DispatchAsync(Socket _socket)
|
||||
{
|
||||
try
|
||||
{
|
||||
var msgid = Guid.NewGuid().ToString();
|
||||
await _client.SendCmdAsync(MessageType.Forward, $"{msgid}|{_config.LocalIp }:{_config.LocalPort}");
|
||||
|
||||
var tcs = new TaskCompletionSource<Stream>();
|
||||
_server.ResponseTasks.TryAdd(msgid, tcs);
|
||||
|
||||
using var stream1 = await tcs.Task;
|
||||
using var stream2 = new NetworkStream(_socket, true);
|
||||
await Task.WhenAll(stream1.CopyToAsync(stream2), stream2.CopyToAsync(stream1));
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,49 +1,71 @@
|
|||
using FastTunnel.Core.Client;
|
||||
using FastTunnel.Core.Dispatchers;
|
||||
using FastTunnel.Core.Extensions;
|
||||
using FastTunnel.Core.Config;
|
||||
using FastTunnel.Core.Client;
|
||||
using FastTunnel.Core.Models;
|
||||
using Microsoft.AspNetCore.Hosting.Server;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net.Sockets;
|
||||
using System.Net.WebSockets;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using FastTunnel.Core.Sockets;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using FastTunnel.Core.Utility.Extensions;
|
||||
using System.Net.WebSockets;
|
||||
using FastTunnel.Core.Forwarder;
|
||||
using Microsoft;
|
||||
using Microsoft.AspNetCore.DataProtection;
|
||||
using System.Data.Common;
|
||||
|
||||
namespace FastTunnel.Core.Dispatchers
|
||||
namespace FastTunnel.Core.Handlers.Client
|
||||
{
|
||||
public class ForwardHandler
|
||||
public class ForwardHandler : IClientHandler
|
||||
{
|
||||
private FastTunnelServer _server;
|
||||
private WebSocket _client;
|
||||
private ForwardConfig _config;
|
||||
ILogger<ForwardHandler> _logger;
|
||||
|
||||
public ForwardHandler(FastTunnelServer server, WebSocket client, ForwardConfig config)
|
||||
public ForwardHandler(ILogger<ForwardHandler> logger)
|
||||
{
|
||||
_server = server;
|
||||
_client = client;
|
||||
_config = config;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public async void DispatchAsync(Socket _socket)
|
||||
public async Task HandlerMsgAsync(FastTunnelClient cleint, string msg)
|
||||
{
|
||||
try
|
||||
{
|
||||
var msgid = Guid.NewGuid().ToString();
|
||||
await _client.SendCmdAsync(new Message<NewForwardMessage> { MessageType = MessageType.S_NewSSH, Content = new NewForwardMessage { MsgId = msgid, SSHConfig = _config } });
|
||||
var msgs = msg.Split('|');
|
||||
|
||||
var tcs = new TaskCompletionSource<Stream>();
|
||||
_server.ResponseTasks.TryAdd(msgid, tcs);
|
||||
_logger.LogDebug($"开始转发 {msgs[0]}");
|
||||
|
||||
using var stream1 = await tcs.Task;
|
||||
using var stream2 = new NetworkStream(_socket, true);
|
||||
await Task.WhenAll(stream1.CopyToAsync(stream2), stream2.CopyToAsync(stream1));
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
await Task.Yield();
|
||||
|
||||
using Stream serverConn = await server(msgs[0], cleint);
|
||||
using Stream localConn = await local(msgs[0], msgs[1]);
|
||||
|
||||
var taskX = serverConn.CopyToAsync(localConn, CancellationToken.None);
|
||||
var taskY = localConn.CopyToAsync(serverConn, CancellationToken.None);
|
||||
|
||||
await Task.WhenAny(taskX, taskY);
|
||||
}
|
||||
|
||||
private async Task<Stream> local(string requestId, string localhost)
|
||||
{
|
||||
_logger.LogDebug($"连接本地成功 {requestId}");
|
||||
var localConnecter = new DnsSocket(localhost.Split(":")[0], int.Parse(localhost.Split(":")[1]));
|
||||
await localConnecter.ConnectAsync();
|
||||
|
||||
return new NetworkStream(localConnecter.Socket, ownsSocket: true);
|
||||
}
|
||||
|
||||
private async Task<Stream> server(string requestId, FastTunnelClient cleint)
|
||||
{
|
||||
var connecter = new DnsSocket(cleint.Server.ServerAddr, cleint.Server.ServerPort);
|
||||
await connecter.ConnectAsync();
|
||||
|
||||
_logger.LogDebug($"连接server成功 {requestId}");
|
||||
Stream serverConn = new NetworkStream(connecter.Socket, ownsSocket: true);
|
||||
var reverse = $"PROXY /{requestId} HTTP/1.1\r\nHost: {cleint.Server.ServerAddr}:{cleint.Server.ServerPort}\r\n\r\n";
|
||||
|
||||
var requestMsg = Encoding.ASCII.GetBytes(reverse);
|
||||
await serverConn.WriteAsync(requestMsg, CancellationToken.None);
|
||||
return serverConn;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,70 +0,0 @@
|
|||
using FastTunnel.Core.Config;
|
||||
using FastTunnel.Core.Client;
|
||||
using FastTunnel.Core.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using FastTunnel.Core.Sockets;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using FastTunnel.Core.Utility.Extensions;
|
||||
using System.Net.WebSockets;
|
||||
using FastTunnel.Core.Forwarder;
|
||||
using Microsoft;
|
||||
using Microsoft.AspNetCore.DataProtection;
|
||||
using System.Data.Common;
|
||||
|
||||
namespace FastTunnel.Core.Handlers.Client
|
||||
{
|
||||
public class HttpRequestHandler : IClientHandler
|
||||
{
|
||||
ILogger<HttpRequestHandler> _logger;
|
||||
|
||||
public HttpRequestHandler(ILogger<HttpRequestHandler> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public async Task HandlerMsgAsync<T>(FastTunnelClient cleint, T Msg) where T : TunnelMassage
|
||||
{
|
||||
var request = Msg as NewCustomerMassage;
|
||||
|
||||
await Task.Yield();
|
||||
|
||||
using Stream serverConn = await Server(cleint, request);
|
||||
using Stream localConn = await local(request);
|
||||
|
||||
_logger.LogDebug($"开始转发 {request.MsgId}");
|
||||
var taskX = serverConn.CopyToAsync(localConn, CancellationToken.None);
|
||||
var taskY = localConn.CopyToAsync(serverConn, CancellationToken.None);
|
||||
|
||||
await Task.WhenAny(taskX, taskY);
|
||||
}
|
||||
|
||||
private async Task<Stream> local(NewCustomerMassage request)
|
||||
{
|
||||
_logger.LogDebug($"连接server成功 {request.MsgId}");
|
||||
var localConnecter = new DnsSocket(request.WebConfig.LocalIp, request.WebConfig.LocalPort);
|
||||
await localConnecter.ConnectAsync();
|
||||
|
||||
_logger.LogDebug($"连接本地成功 {request.MsgId}");
|
||||
|
||||
return new NetworkStream(localConnecter.Socket, ownsSocket: true);
|
||||
}
|
||||
|
||||
private async Task<Stream> Server(FastTunnelClient cleint, NewCustomerMassage request)
|
||||
{
|
||||
var connecter = new DnsSocket(cleint.Server.ServerAddr, cleint.Server.ServerPort);
|
||||
await connecter.ConnectAsync();
|
||||
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);
|
||||
await serverConn.WriteAsync(requestMsg, CancellationToken.None);
|
||||
return serverConn;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -10,6 +10,6 @@ namespace FastTunnel.Core.Handlers.Client
|
|||
{
|
||||
public interface IClientHandler
|
||||
{
|
||||
Task HandlerMsgAsync<T>(FastTunnelClient cleint, T Msg) where T : TunnelMassage;
|
||||
Task HandlerMsgAsync(FastTunnelClient cleint, string msg);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,33 +17,10 @@ namespace FastTunnel.Core.Handlers.Client
|
|||
_logger = logger;
|
||||
}
|
||||
|
||||
public async Task HandlerMsgAsync<T>(FastTunnelClient cleint, T Msg)
|
||||
where T : TunnelMassage
|
||||
public async Task HandlerMsgAsync(FastTunnelClient cleint, string msg)
|
||||
{
|
||||
try
|
||||
{
|
||||
await Task.Yield();
|
||||
var msg = Msg as LogMassage;
|
||||
|
||||
switch (msg.MsgType)
|
||||
{
|
||||
case LogMsgType.Info:
|
||||
_logger.LogInformation($"[Server Info]:{msg.Msg}");
|
||||
break;
|
||||
case LogMsgType.Error:
|
||||
_logger.LogError($"[Server Error]:{msg.Msg}");
|
||||
break;
|
||||
case LogMsgType.Debug:
|
||||
_logger.LogDebug($"[Server Debug]:{msg.Msg}");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex);
|
||||
}
|
||||
_logger.LogInformation(msg.Replace("\n", string.Empty));
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,55 +0,0 @@
|
|||
using FastTunnel.Core.Config;
|
||||
using FastTunnel.Core.Client;
|
||||
using FastTunnel.Core.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using FastTunnel.Core.Sockets;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Threading.Tasks;
|
||||
using System.IO;
|
||||
using System.Net.Sockets;
|
||||
using System.Threading;
|
||||
|
||||
namespace FastTunnel.Core.Handlers.Client
|
||||
{
|
||||
public class NewForwardHandler : IClientHandler
|
||||
{
|
||||
ILogger<NewForwardHandler> _logger;
|
||||
public NewForwardHandler(ILogger<NewForwardHandler> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public async Task HandlerMsgAsync<T>(FastTunnelClient cleint, T Msg)
|
||||
where T : TunnelMassage
|
||||
{
|
||||
var request = Msg as NewForwardMessage;
|
||||
await Task.Yield();
|
||||
|
||||
using var stream1 = await Server(cleint, request);
|
||||
using var stream2 = await local(request);
|
||||
|
||||
await Task.WhenAll(stream1.CopyToAsync(stream2), stream2.CopyToAsync(stream1));
|
||||
}
|
||||
|
||||
private async Task<Stream> local(NewForwardMessage request)
|
||||
{
|
||||
var localConnecter = new DnsSocket(request.SSHConfig.LocalIp, request.SSHConfig.LocalPort);
|
||||
await localConnecter.ConnectAsync();
|
||||
return new NetworkStream(localConnecter.Socket, true);
|
||||
}
|
||||
|
||||
private async Task<Stream> Server(FastTunnelClient cleint, NewForwardMessage request)
|
||||
{
|
||||
var connecter = new DnsSocket(cleint.Server.ServerAddr, cleint.Server.ServerPort);
|
||||
await connecter.ConnectAsync();
|
||||
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);
|
||||
await serverConn.WriteAsync(requestMsg, CancellationToken.None);
|
||||
return serverConn;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -37,8 +37,7 @@ namespace FastTunnel.Core.Handlers
|
|||
{
|
||||
bool hasTunnel = false;
|
||||
|
||||
var sb = new StringBuilder($"{Environment.NewLine}=====隧道已建立成功,可通过以下方式访问内网服务====={Environment.NewLine}{Environment.NewLine}");
|
||||
sb.Append($"穿透协议 | 映射关系(公网=>内网){Environment.NewLine}");
|
||||
await client.SendCmdAsync(MessageType.Log, $"穿透协议 | 映射关系(公网=>内网){Environment.NewLine}");
|
||||
if (requet.Webs != null && requet.Webs.Count() > 0)
|
||||
{
|
||||
hasTunnel = true;
|
||||
|
@ -51,8 +50,8 @@ namespace FastTunnel.Core.Handlers
|
|||
server.WebList.AddOrUpdate(hostName, info, (key, oldInfo) => { return info; });
|
||||
(proxyConfig as InMemoryConfigProvider).AddWeb(hostName);
|
||||
|
||||
sb.Append($" HTTP | http://{hostName}{(server.serverOption.CurrentValue.WebHasNginxProxy ? string.Empty : ":" + server.serverOption.CurrentValue.WebProxyPort)} => {item.LocalIp}:{item.LocalPort}");
|
||||
sb.Append(Environment.NewLine);
|
||||
await client.SendCmdAsync(MessageType.Log, $" HTTP | http://{hostName}{(server.serverOption.CurrentValue.WebHasNginxProxy ? string.Empty : ":" + server.serverOption.CurrentValue.WebProxyPort)} => {item.LocalIp}:{item.LocalPort}");
|
||||
|
||||
if (item.WWW != null)
|
||||
{
|
||||
foreach (var www in item.WWW)
|
||||
|
@ -62,8 +61,9 @@ namespace FastTunnel.Core.Handlers
|
|||
|
||||
server.WebList.AddOrUpdate(www, info, (key, oldInfo) => { return info; });
|
||||
(proxyConfig as InMemoryConfigProvider).AddWeb(hostName);
|
||||
sb.Append($" HTTP | http://{www}{(server.serverOption.CurrentValue.WebHasNginxProxy ? string.Empty : ":" + server.serverOption.CurrentValue.WebProxyPort)} => {item.LocalIp}:{item.LocalPort}");
|
||||
sb.Append(Environment.NewLine);
|
||||
|
||||
await client.SendCmdAsync(MessageType.Log, $" HTTP | http://{www}{(server.serverOption.CurrentValue.WebHasNginxProxy ? string.Empty : ":" + server.serverOption.CurrentValue.WebProxyPort)} => {item.LocalIp}:{item.LocalPort}");
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -93,34 +93,26 @@ namespace FastTunnel.Core.Handlers
|
|||
|
||||
var ls = new PortProxyListener("0.0.0.0", item.RemotePort, _logger);
|
||||
|
||||
ls.Start(new ForwardHandler(server, client, item));
|
||||
ls.Start(new ForwardDispatcher(server, client, item));
|
||||
|
||||
// listen success
|
||||
server.ForwardList.TryAdd(item.RemotePort, new ForwardInfo<ForwardHandlerArg> { Listener = ls, Socket = client, SSHConfig = item });
|
||||
_logger.LogDebug($"SSH proxy success: {item.RemotePort} => {item.LocalIp}:{item.LocalPort}");
|
||||
|
||||
sb.Append($" TCP | {server.serverOption.CurrentValue.WebDomain}:{item.RemotePort} => {item.LocalIp}:{item.LocalPort}");
|
||||
sb.Append(Environment.NewLine);
|
||||
await client.SendCmdAsync(MessageType.Log, $" TCP | {server.serverOption.CurrentValue.WebDomain}:{item.RemotePort} => {item.LocalIp}:{item.LocalPort}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError($"SSH proxy error: {item.RemotePort} => {item.LocalIp}:{item.LocalPort}");
|
||||
_logger.LogError(ex.Message);
|
||||
await client.SendCmdAsync(new Message<LogMassage> { MessageType = MessageType.Log, Content = new LogMassage(LogMsgType.Info, ex.Message) });
|
||||
await client.SendCmdAsync(MessageType.Log, ex.Message);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasTunnel)
|
||||
{
|
||||
await client.SendCmdAsync(new Message<LogMassage> { MessageType = MessageType.Log, Content = new LogMassage(LogMsgType.Info, TunnelResource.NoTunnel) });
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.Append($"{Environment.NewLine}====================================================");
|
||||
await client.SendCmdAsync(new Message<LogMassage> { MessageType = MessageType.Log, Content = new LogMassage(LogMsgType.Info, sb.ToString()) });
|
||||
}
|
||||
await client.SendCmdAsync(MessageType.Log, TunnelResource.NoTunnel);
|
||||
}
|
||||
|
||||
public async Task<bool> HandlerMsg<T>(FastTunnelServer server, WebSocket client, T msg)
|
||||
|
|
|
@ -1,10 +1,14 @@
|
|||
using FastTunnel.Core.Dispatchers;
|
||||
using FastTunnel.Core.Models;
|
||||
using Microsoft.AspNetCore.Hosting.Server;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FastTunnel.Core.Listener
|
||||
{
|
||||
|
@ -19,7 +23,7 @@ namespace FastTunnel.Core.Listener
|
|||
int m_numConnectedSockets;
|
||||
|
||||
bool shutdown = false;
|
||||
ForwardHandler _requestDispatcher;
|
||||
ForwardDispatcher _requestDispatcher;
|
||||
Socket listenSocket;
|
||||
public IList<Socket> ConnectedSockets = new List<Socket>();
|
||||
|
||||
|
@ -36,7 +40,7 @@ namespace FastTunnel.Core.Listener
|
|||
listenSocket.Bind(localEndPoint);
|
||||
}
|
||||
|
||||
public void Start(ForwardHandler requestDispatcher)
|
||||
public void Start(ForwardDispatcher requestDispatcher)
|
||||
{
|
||||
shutdown = false;
|
||||
_requestDispatcher = requestDispatcher;
|
||||
|
@ -120,6 +124,7 @@ namespace FastTunnel.Core.Listener
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private void AcceptEventArg_Completed(object sender, SocketAsyncEventArgs e)
|
||||
{
|
||||
ProcessAccept(e);
|
||||
|
|
|
@ -4,25 +4,18 @@ using System.Text;
|
|||
|
||||
namespace FastTunnel.Core.Models
|
||||
{
|
||||
public class Message<T>
|
||||
public struct Message<T>
|
||||
{
|
||||
public MessageType MessageType { get; set; }
|
||||
|
||||
public T Content { get; set; }
|
||||
}
|
||||
|
||||
public enum MessageType
|
||||
public enum MessageType : byte
|
||||
{
|
||||
// client use below
|
||||
C_LogIn,
|
||||
Heart,
|
||||
C_SwapMsg,
|
||||
|
||||
// server use below
|
||||
S_NewCustomer,
|
||||
S_NewSSH,
|
||||
|
||||
// twoway
|
||||
Log,
|
||||
LogIn = 1, // client
|
||||
SwapMsg = 2,
|
||||
Forward = 3,
|
||||
Log = 4,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,22 +57,9 @@ namespace FastTunnel.Core.Models
|
|||
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;
|
||||
default:
|
||||
throw new Exception($"未知的通讯指令 {lineCmd}");
|
||||
}
|
||||
|
||||
return await handler.HandlerMsg(fastTunnelServer, webSocket, msg);
|
||||
var msg = JsonSerializer.Deserialize<LogInMassage>(lineCmd.Substring(1));
|
||||
return await _loginHandler.HandlerMsg(fastTunnelServer, webSocket, msg);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
|
|
@ -1,51 +0,0 @@
|
|||
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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -14,10 +14,10 @@ namespace FastTunnel.Core.Sockets
|
|||
{
|
||||
private Stream stream1;
|
||||
private Stream stream2;
|
||||
private ILogger<HttpRequestHandler> logger;
|
||||
private ILogger<ForwardHandler> logger;
|
||||
private string msgId;
|
||||
|
||||
public StreamSwap(Stream serverConnection, NetworkStream localConn, ILogger<HttpRequestHandler> logger, string msgId)
|
||||
public StreamSwap(Stream serverConnection, NetworkStream localConn, ILogger<ForwardHandler> logger, string msgId)
|
||||
{
|
||||
this.stream1 = serverConnection;
|
||||
this.stream2 = localConn;
|
||||
|
|
|
@ -37,12 +37,12 @@ namespace FastTunnel.Server
|
|||
.ConfigureWebHostDefaults(webBuilder =>
|
||||
{
|
||||
webBuilder.UseStartup<Startup>();
|
||||
})
|
||||
.ConfigureLogging((HostBuilderContext context, ILoggingBuilder logging) =>
|
||||
{
|
||||
logging.ClearProviders();
|
||||
logging.SetMinimumLevel(LogLevel.Trace);
|
||||
logging.AddLog4Net();
|
||||
});
|
||||
//.ConfigureLogging((HostBuilderContext context, ILoggingBuilder logging) =>
|
||||
//{
|
||||
// logging.ClearProviders();
|
||||
// logging.SetMinimumLevel(LogLevel.Trace);
|
||||
// logging.AddLog4Net();
|
||||
//});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
"Logging": {
|
||||
"LogLevel": {
|
||||
// Trace Debug Information Warning Error
|
||||
"Default": "Trace",
|
||||
"Default": "Debug",
|
||||
"Microsoft": "Warning",
|
||||
"Microsoft.Hosting.Lifetime": "Information"
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user