新增特性:ssh访问内网主机

This commit is contained in:
SpringHgui 2019-12-20 22:14:43 +08:00
parent 95b91548ef
commit 60ed66e961
7 changed files with 96 additions and 30 deletions

View File

@ -9,6 +9,8 @@
"ClientSettings": {
"Common": {
// ip, BindAddr
// "ServerAddr": "144.202.109.110",
"ServerAddr": "127.0.0.1",
// BindPort
@ -23,17 +25,30 @@
"LocalPort": 80,
// , 访url http://{SubDomain}.{Domain}:{ProxyPort_HTTP}/
"SubDomain": "yz"
},
{
"LocalIp": "127.0.0.1",
"LocalPort": 80,
"SubDomain": "test"
},
{
"LocalIp": "127.0.0.1",
"LocalPort": 80,
"SubDomain": "test1"
},
"SubDomain": "tgjmini"
}
],
/**
* ssh穿ssh访
* 访 #ssh -oPort=12701 {root}@{ServerAddr}
* ServerAddr iproot
*/
"SSH": [
{
"LocalIp": "127.0.0.1",
"LocalPort": 80,
"SubDomain": "test2"
"LocalPort": 22,
"RemotePort": 12701
}
]
}

View File

@ -34,7 +34,7 @@ namespace FastTunnel.Core.Client
connecter.Connect();
// 登录
connecter.Send(new Message<LogInRequest> { MessageType = MessageType.C_LogIn, Content = new LogInRequest { WebList = _clientConfig.Webs } });
connecter.Send(new Message<LogInRequest> { MessageType = MessageType.C_LogIn, Content = new LogInRequest { ClientConfig = _clientConfig } });
_logger.Debug("登录成功");
ReceiveServer(connecter.Client);
@ -108,14 +108,25 @@ namespace FastTunnel.Core.Client
var request = (Msg.Content as JObject).ToObject<NewCustomerRequest>();
var connecter = new Connecter(_clientConfig.Common.ServerAddr, _clientConfig.Common.ServerPort);
connecter.Connect();
connecter.Send(new Message<string> { MessageType = MessageType.C_NewRequest, Content = request.MsgId });
connecter.Send(new Message<string> { MessageType = MessageType.C_SwapMsg, Content = request.MsgId });
var localConnecter = new Connecter(request.WebConfig.LocalIp, request.WebConfig.LocalPort);
localConnecter.Connect();
new SocketSwap(connecter.Client, localConnecter.Client).StartSwap();
break;
case MessageType.C_NewRequest:
case MessageType.S_NewSSH:
var request_ssh = (Msg.Content as JObject).ToObject<NewSSHRequest>();
var connecter_ssh = new Connecter(_clientConfig.Common.ServerAddr, _clientConfig.Common.ServerPort);
connecter_ssh.Connect();
connecter_ssh.Send(new Message<string> { MessageType = MessageType.C_SwapMsg, Content = request_ssh.MsgId });
var localConnecter_ssh = new Connecter(request_ssh.SSHConfig.LocalIp, request_ssh.SSHConfig.LocalPort);
localConnecter_ssh.Connect();
new SocketSwap(connecter_ssh.Client, localConnecter_ssh.Client).StartSwap();
break;
case MessageType.C_SwapMsg:
case MessageType.C_LogIn:
default:
throw new Exception("参数异常");

View File

@ -10,6 +10,8 @@ namespace FastTunnel.Core.Config
public ServerCommon Common { get; set; }
public IEnumerable<WebConfig> Webs { get; set; }
public IEnumerable<SSHConfig> SSH { get; set; }
}
public class ServerCommon

View File

@ -7,26 +7,26 @@ using System.Threading;
namespace FastTunnel.Core
{
public class Listener
public class Listener<T>
{
private string _ip;
private int _port;
Action<Socket> handler;
Action<Socket, T> handler;
Socket socket;
T _data;
public Listener(string ip, int port, Action<Socket> acceptCustomerHandler)
public Listener(string ip, int port, Action<Socket, T> acceptCustomerHandler, T data)
{
_data = data;
this._ip = ip;
this._port = port;
handler = acceptCustomerHandler;
IPAddress ipa = IPAddress.Parse(_ip);
IPEndPoint ipe = new IPEndPoint(ipa, _port);
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.Bind(ipe);
}
public void Listen()
@ -50,7 +50,7 @@ namespace FastTunnel.Core
private void ReceiveCustomer(object state)
{
var client = state as Socket;
handler.Invoke(client);
handler.Invoke(client, _data);
}
}
}

View File

@ -1,4 +1,5 @@
using System;
using FastTunnel.Core.Config;
using System;
using System.Collections.Generic;
using System.Text;
@ -6,6 +7,6 @@ namespace FastTunnel.Core.Models
{
public class LogInRequest
{
public IEnumerable<WebConfig> WebList { get; set; }
public ClientConfig ClientConfig { get; set; }
}
}

View File

@ -16,9 +16,10 @@ namespace FastTunnel.Core.Models
// client use below
C_LogIn,
C_Heart,
C_NewRequest,
C_SwapMsg,
// server use below
S_NewCustomer,
S_NewSSH,
}
}

View File

@ -18,6 +18,7 @@ namespace FastTunnel.Core.Server
public class FastTunnelServer
{
Dictionary<string, WebInfo> WebList = new Dictionary<string, WebInfo>();
Dictionary<int, SSHInfo<SSHHandlerArg>> SSHList = new Dictionary<int, SSHInfo<SSHHandlerArg>>();
Dictionary<string, NewRequest> newRequest = new Dictionary<string, NewRequest>();
private ServerConfig serverSettings;
@ -37,23 +38,22 @@ namespace FastTunnel.Core.Server
private void ListenFastTunnelClient()
{
var listener = new Listener(serverSettings.BindAddr, serverSettings.BindPort, ReceiveClient);
var listener = new Listener<object>(serverSettings.BindAddr, serverSettings.BindPort, ReceiveClient, null);
listener.Listen();
_logger.Debug($"监听客户端 -> {serverSettings.BindAddr}:{serverSettings.BindPort}");
}
private void ListenCustomer()
{
var listener = new Listener(serverSettings.BindAddr, serverSettings.ProxyPort_HTTP, ReceiveCustomer);
var listener = new Listener<object>(serverSettings.BindAddr, serverSettings.ProxyPort_HTTP, ReceiveCustomer, null);
listener.Listen();
_logger.Debug($"监听HTTP -> {serverSettings.BindAddr}:{serverSettings.ProxyPort_HTTP}");
}
//接收消息
void ReceiveCustomer(object o)
void ReceiveCustomer(Socket client, object _)
{
Socket client = o as Socket;
_logger.Debug("新的HTTP请求");
try
@ -132,13 +132,12 @@ namespace FastTunnel.Core.Server
}
catch (Exception ex)
{
throw;
_logger.Error(ex);
}
}
private void ReceiveClient(object obj)
private void ReceiveClient(Socket client, object _)
{
Socket client = obj as Socket;
//定义byte数组存放从客户端接收过来的数据
byte[] buffer = new byte[1024 * 1024];
@ -156,7 +155,7 @@ namespace FastTunnel.Core.Server
return;
}
//将字节转换成字符串
// 将字节转换成字符串
string words = Encoding.UTF8.GetString(buffer, 0, length);
var msg = JsonConvert.DeserializeObject<Message<object>>(words);
@ -165,9 +164,9 @@ namespace FastTunnel.Core.Server
{
case MessageType.C_LogIn:
var requet = (msg.Content as JObject).ToObject<LogInRequest>();
if (requet.WebList != null && requet.WebList.Count() > 0)
if (requet.ClientConfig.Webs != null && requet.ClientConfig.Webs.Count() > 0)
{
foreach (var item in requet.WebList)
foreach (var item in requet.ClientConfig.Webs)
{
var key = $"{item.SubDomain}.{serverSettings.Domain}".Trim();
if (WebList.ContainsKey(key))
@ -184,26 +183,52 @@ namespace FastTunnel.Core.Server
}
}
}
if (requet.ClientConfig.SSH != null && requet.ClientConfig.SSH.Count() > 0)
{
foreach (var item in requet.ClientConfig.SSH)
{
if (SSHList.ContainsKey(item.RemotePort))
SSHList.Remove(item.RemotePort);
try
{
var ls = new Listener<SSHHandlerArg>("0.0.0.0", item.RemotePort, SSHHandler, new SSHHandlerArg { LocalClient = client, SSHConfig = item });
ls.Listen();
// listen success
SSHList.Add(item.RemotePort, new SSHInfo<SSHHandlerArg> { Listener = ls, Socket = client, SSHConfig = item });
_logger.Debug($"SSH proxy success on {item.RemotePort} -> {item.LocalIp}:{item.LocalPort}");
}
catch (Exception ex)
{
_logger.Error($"SSH proxy error on {item.RemotePort} -> {item.LocalIp}:{item.LocalPort}");
_logger.Error(ex);
continue;
}
}
}
break;
case MessageType.C_Heart:
break;
case MessageType.C_NewRequest:
case MessageType.C_SwapMsg:
var msgId = (msg.Content as string);
NewRequest request;
if (newRequest.TryGetValue(msgId, out request))
if (!string.IsNullOrEmpty(msgId) && newRequest.TryGetValue(msgId, out request))
{
// Join
Task.Run(() =>
{
(new SocketSwap(request.CustomerClient, client))
.BeforeSwap(() => { client.Send(request.Buffer); })
.BeforeSwap(() => { if (request.Buffer != null) client.Send(request.Buffer); })
.StartSwap();
});
}
else
{
// 未找到,关闭连接
throw new Exception($"未找到请求:{msgId}");
_logger.Error($"未找到请求:{msgId}");
}
break;
case MessageType.S_NewCustomer:
@ -211,5 +236,16 @@ namespace FastTunnel.Core.Server
throw new Exception("参数异常");
}
}
private void SSHHandler(Socket client, SSHHandlerArg local)
{
var msgid = Guid.NewGuid().ToString();
local.LocalClient.Send(new Message<NewSSHRequest> { MessageType = MessageType.S_NewSSH, Content = new NewSSHRequest { MsgId = msgid, SSHConfig = local.SSHConfig } });
newRequest.Add(msgid, new NewRequest
{
CustomerClient = client,
});
}
}
}