桌面共享使用打洞或者服务器中继进行代理

This commit is contained in:
少年郎秃头呀
2024-05-06 15:07:55 +08:00
parent 4e31b7ebe5
commit d27742afcd
11 changed files with 151 additions and 71 deletions

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<project ver="10" name="cmonitor.viewer.client.win" libEmbed="true" icon="D:\desktop\cmonitor\cmonitor\favicon.ico" ui="win" output="cmonitor.viewer.client.win.exe" CompanyName="snltty" FileDescription="cmonitor.viewer.client.win" LegalCopyright="Copyright (C) snltty 2024" ProductName="cmonitor.viewer.client.win" InternalName="cmonitor.viewer.client.win" FileVersion="0.0.0.41" ProductVersion="0.0.0.41" publishDir="/dist/" dstrip="false"> <project ver="10" name="cmonitor.viewer.client.win" libEmbed="true" icon="C:\Users\snltty\Desktop\cmonitor\cmonitor\favicon.ico" ui="win" output="cmonitor.viewer.client.win.exe" CompanyName="snltty" FileDescription="cmonitor.viewer.client.win" LegalCopyright="Copyright (C) snltty 2024" ProductName="cmonitor.viewer.client.win" InternalName="cmonitor.viewer.client.win" FileVersion="0.0.0.42" ProductVersion="0.0.0.42" publishDir="/dist/" dstrip="false">
<file name="main.aardio" path="main.aardio" comment="main.aardio"/> <file name="main.aardio" path="main.aardio" comment="main.aardio"/>
<folder name="资源文件" path="res" embed="true"/> <folder name="资源文件" path="res" embed="true"/>
<folder name="窗体文件" path="dlg" comment="目录" embed="true"/> <folder name="窗体文件" path="dlg" comment="目录" embed="true"/>

View File

@@ -51,9 +51,9 @@ mainForm.connect = function(){
mainForm.show(); mainForm.show();
if(!_STUDIO_INVOKED) if(!_STUDIO_INVOKED)
{ {
mainForm.fullscreen(); //mainForm.fullscreen();
mainForm.modifyStyleEx(0x40000/*_WS_EX_APPWINDOW*/,0x80/*_WS_EX_TOOLWINDOW*/); //mainForm.modifyStyleEx(0x40000/*_WS_EX_APPWINDOW*/,0x80/*_WS_EX_TOOLWINDOW*/);
::SetWindowPos(mainForm.hwnd,-1/*_HWND_TOPMOST*/,0,0,0,0,0x2/*_SWP_NOMOVE*/ + 0x1/*_SWP_NOSIZE*/); //::SetWindowPos(mainForm.hwnd,-1/*_HWND_TOPMOST*/,0,0,0,0,0x2/*_SWP_NOMOVE*/ + 0x1/*_SWP_NOSIZE*/);
} }
mainForm.setInterval( mainForm.setInterval(

View File

@@ -38,7 +38,7 @@ namespace cmonitor.plugins.relay
public async Task<RelayTransportState> ConnectAsync(string remoteMachineName, string transactionId, string secretKey) public async Task<RelayTransportState> ConnectAsync(string remoteMachineName, string transactionId, string secretKey)
{ {
IEnumerable<ITransport> _transports = transports.OrderBy(c => c.Name); IEnumerable<ITransport> _transports = transports.OrderBy(c => c.Name);
foreach (RelayCompactInfo item in config.Data.Client.Relay.Servers.Where(c=>c.Disabled == false)) foreach (RelayCompactInfo item in config.Data.Client.Relay.Servers.Where(c => c.Disabled == false))
{ {
ITransport transport = _transports.FirstOrDefault(c => c.Name == item.Name); ITransport transport = _transports.FirstOrDefault(c => c.Name == item.Name);
if (transport == null) if (transport == null)
@@ -61,7 +61,7 @@ namespace cmonitor.plugins.relay
Socket socket = await transport.RelayAsync(relayInfo); Socket socket = await transport.RelayAsync(relayInfo);
if (socket != null) if (socket != null)
{ {
return new RelayTransportState { Info = relayInfo, Socket = socket }; return new RelayTransportState { Info = relayInfo, Socket = socket, Direction = RelayTransportDirection.Forward };
} }
} }
catch (Exception ex) catch (Exception ex)
@@ -79,7 +79,7 @@ namespace cmonitor.plugins.relay
Socket socket = await _transports.OnBeginAsync(relayInfo); Socket socket = await _transports.OnBeginAsync(relayInfo);
if (socket != null) if (socket != null)
{ {
OnConnected(new RelayTransportState { Info = relayInfo, Socket = socket }); OnConnected(new RelayTransportState { Info = relayInfo, Socket = socket, Direction = RelayTransportDirection.Reverse });
return true; return true;
} }
} }

View File

@@ -30,9 +30,9 @@ namespace cmonitor.plugins.relay.messenger
private readonly Config config; private readonly Config config;
private readonly MessengerSender messengerSender; private readonly MessengerSender messengerSender;
private readonly SignCaching signCaching; private readonly SignCaching signCaching;
private readonly ConcurrentDictionary<ulong, TaskCompletionSource<IConnection>> dic = new ConcurrentDictionary<ulong, TaskCompletionSource<IConnection>>(); private readonly ConcurrentDictionary<ulong, TcsWrap> dic = new ConcurrentDictionary<ulong, TcsWrap>();
private ulong flowingId = 0; private ulong flowingId = 0;
public RelayServerMessenger(Config config, MessengerSender messengerSender, SignCaching signCaching) public RelayServerMessenger(Config config, MessengerSender messengerSender, SignCaching signCaching)
{ {
@@ -59,24 +59,24 @@ namespace cmonitor.plugins.relay.messenger
} }
info.FlowingId = Interlocked.Increment(ref flowingId); info.FlowingId = Interlocked.Increment(ref flowingId);
TaskCompletionSource<IConnection> tcs = new TaskCompletionSource<IConnection>(); TcsWrap tcsWrap = new TcsWrap { Connection = connection, Tcs = new TaskCompletionSource<IConnection>() };
dic.TryAdd(info.FlowingId, tcs); dic.TryAdd(info.FlowingId, tcsWrap);
try try
{ {
MessageResponeInfo resp = await messengerSender.SendReply(new MessageRequestWrap bool res = await messengerSender.SendOnly(new MessageRequestWrap
{ {
Connection = cache.Connection, Connection = cache.Connection,
MessengerId = (ushort)RelayMessengerIds.Relay, MessengerId = (ushort)RelayMessengerIds.Relay,
Payload = MemoryPackSerializer.Serialize(info) Payload = MemoryPackSerializer.Serialize(info)
}); });
if (resp.Code != MessageResponeCodes.OK || resp.Data.Span.SequenceEqual(Helper.TrueArray) == false) if (res == false)
{ {
connection.Write(Helper.FalseArray); connection.Write(Helper.FalseArray);
return; return;
} }
IConnection targetConnection = await tcs.Task.WaitAsync(TimeSpan.FromMilliseconds(3000)); IConnection targetConnection = await tcsWrap.Tcs.Task.WaitAsync(TimeSpan.FromMilliseconds(3000));
connection.TcpTargetSocket = targetConnection.TcpSourceSocket; connection.TcpTargetSocket = targetConnection.TcpSourceSocket;
targetConnection.TcpTargetSocket = connection.TcpSourceSocket; targetConnection.TcpTargetSocket = connection.TcpSourceSocket;
connection.Write(Helper.TrueArray); connection.Write(Helper.TrueArray);
@@ -92,9 +92,9 @@ namespace cmonitor.plugins.relay.messenger
} }
else else
{ {
if (dic.TryRemove(info.FlowingId, out TaskCompletionSource<IConnection> tcs)) if (dic.TryRemove(info.FlowingId, out TcsWrap tcsWrap))
{ {
tcs.SetResult(connection); tcsWrap.Tcs.SetResult(connection);
connection.Write(Helper.TrueArray); connection.Write(Helper.TrueArray);
} }
else else
@@ -104,6 +104,12 @@ namespace cmonitor.plugins.relay.messenger
return; return;
} }
} }
public sealed class TcsWrap
{
public TaskCompletionSource<IConnection> Tcs { get; set; }
public IConnection Connection { get; set; }
}
} }

View File

@@ -29,10 +29,18 @@ namespace cmonitor.plugins.relay.transport
} }
public enum RelayTransportDirection : byte
{
Forward = 0,
Reverse = 1
}
public sealed class RelayTransportState public sealed class RelayTransportState
{ {
public RelayInfo Info { get; set; } public RelayInfo Info { get; set; }
public RelayTransportDirection Direction { get; set; } = RelayTransportDirection.Reverse;
public Socket Socket { get; set; } public Socket Socket { get; set; }
} }
} }

View File

@@ -82,6 +82,7 @@ namespace cmonitor.plugins.tunnel
TunnelTransportState state = await transport.ConnectAsync(tunnelTransportInfo); TunnelTransportState state = await transport.ConnectAsync(tunnelTransportInfo);
if (state != null) if (state != null)
{ {
state.Direction = TunnelTransportDirection.Forward;
_OnConnected(state); _OnConnected(state);
return state; return state;
} }

View File

@@ -105,6 +105,8 @@ namespace cmonitor.plugins.tunnel.transport
public string TransportName { get; set; } public string TransportName { get; set; }
public ProtocolType TransportType { get; set; } public ProtocolType TransportType { get; set; }
public TunnelTransportDirection Direction { get; set; } = TunnelTransportDirection.Reverse;
[JsonIgnore] [JsonIgnore]
public object ConnectedObject { get; set; } public object ConnectedObject { get; set; }
} }

View File

@@ -185,14 +185,14 @@ namespace cmonitor.plugins.viewer.proxy
if (token.TargetSocket != null) if (token.TargetSocket != null)
{ {
//发送连接请求包 //发送连接请求包
await SendToTarget(e, token); await SendToTarget(e, token).ConfigureAwait(false);
token.Proxy.Step = ProxyStep.Forward; token.Proxy.Step = ProxyStep.Forward;
token.Proxy.TargetEP = null; token.Proxy.TargetEP = null;
//发送后续数据包 //发送后续数据包
token.Proxy.Data = data; token.Proxy.Data = data;
await SendToTarget(e, token); await SendToTarget(e, token).ConfigureAwait(false);
//绑定 //绑定
dic.TryAdd(new ConnectId(token.Proxy.ConnectId, token.TargetSocket.GetHashCode()), token.SourceSocket); dic.TryAdd(new ConnectId(token.Proxy.ConnectId, token.TargetSocket.GetHashCode()), token.SourceSocket);
@@ -205,7 +205,7 @@ namespace cmonitor.plugins.viewer.proxy
else else
{ {
token.Proxy.Data = data; token.Proxy.Data = data;
await SendToTarget(e, token); await SendToTarget(e, token).ConfigureAwait(false);
} }
} }
private async Task SendToTarget(SocketAsyncEventArgs e, AsyncUserToken token) private async Task SendToTarget(SocketAsyncEventArgs e, AsyncUserToken token)
@@ -225,7 +225,6 @@ namespace cmonitor.plugins.viewer.proxy
} }
} }
protected virtual async Task Connect(AsyncUserToken token, ProxyInfo proxyInfo) protected virtual async Task Connect(AsyncUserToken token, ProxyInfo proxyInfo)
{ {
await Task.CompletedTask; await Task.CompletedTask;
@@ -235,7 +234,13 @@ namespace cmonitor.plugins.viewer.proxy
{ {
try try
{ {
BindReceiveTarget(new AsyncUserToken { TargetSocket = targetSocket, SourceSocket = sourceSocket, Proxy = new ProxyInfo { Direction = ProxyDirection.UnPack } }); BindReceiveTarget(new AsyncUserToken
{
TargetSocket = targetSocket,
SourceSocket = sourceSocket,
Buffer = new ReceiveDataBuffer(),
Proxy = new ProxyInfo { Direction = ProxyDirection.UnPack }
});
return true; return true;
} }
@@ -245,8 +250,6 @@ namespace cmonitor.plugins.viewer.proxy
} }
return false; return false;
} }
private void IO_CompletedTarget(object sender, SocketAsyncEventArgs e) private void IO_CompletedTarget(object sender, SocketAsyncEventArgs e)
{ {
switch (e.LastOperation) switch (e.LastOperation)
@@ -291,7 +294,7 @@ namespace cmonitor.plugins.viewer.proxy
int offset = e.Offset; int offset = e.Offset;
int length = e.BytesTransferred; int length = e.BytesTransferred;
await ReadPacketTarget(e, token, e.Buffer.AsMemory(offset, length)); await ReadPacketTarget(e, token, e.Buffer.AsMemory(offset, length)).ConfigureAwait(false);
if (token.TargetSocket.Available > 0) if (token.TargetSocket.Available > 0)
{ {
@@ -300,7 +303,7 @@ namespace cmonitor.plugins.viewer.proxy
length = token.TargetSocket.Receive(e.Buffer); length = token.TargetSocket.Receive(e.Buffer);
if (length > 0) if (length > 0)
{ {
await ReadPacketTarget(e, token, e.Buffer.AsMemory(0, length)); await ReadPacketTarget(e, token, e.Buffer.AsMemory(0, length)).ConfigureAwait(false);
} }
else else
{ {
@@ -341,58 +344,103 @@ namespace cmonitor.plugins.viewer.proxy
//A 到 B //A 到 B
if (token.Proxy.Direction == ProxyDirection.UnPack) if (token.Proxy.Direction == ProxyDirection.UnPack)
{ {
token.Proxy.DeBytes(data); //是一个完整的包
if (token.Proxy.Step == ProxyStep.Request) if (token.Buffer.Size == 0 && data.Length > 4)
{ {
Socket socket = new Socket(token.Proxy.TargetEP.AddressFamily, SocketType.Stream, ProtocolType.Tcp); int packageLen = data.ToInt32();
socket.KeepAlive(); if (packageLen == data.Length - 4)
await socket.ConnectAsync(token.Proxy.TargetEP);
dic.TryAdd(new ConnectId(token.Proxy.ConnectId, token.TargetSocket.GetHashCode()), socket);
BindReceiveTarget(new AsyncUserToken
{ {
TargetSocket = socket, token.Proxy.DeBytes(data.Slice(0, packageLen + 4));
SourceSocket = token.TargetSocket, await ReadPacketTarget(e, token).ConfigureAwait(false);
Proxy = new ProxyInfo return;
{ }
Direction = ProxyDirection.Pack,
ConnectId = token.Proxy.ConnectId,
Step = ProxyStep.Forward
}
});
} }
else
{
ConnectId connectId = new ConnectId(token.Proxy.ConnectId, token.TargetSocket.GetHashCode());
if (dic.TryGetValue(connectId, out Socket source))
{
try
{
await source.SendAsync(token.Proxy.Data);
}
catch (Exception)
{
CloseClientSocket(e);
} //不是完整包
token.Buffer.AddRange(data);
do
{
int packageLen = token.Buffer.Data.ToInt32();
if (packageLen > token.Buffer.Size - 4)
{
break;
}
token.Proxy.DeBytes(token.Buffer.Data.Slice(0, packageLen + 4));
await ReadPacketTarget(e, token).ConfigureAwait(false);
token.Buffer.RemoveRange(0, packageLen + 4);
} while (token.Buffer.Size > 4);
}
else
{
token.Proxy.Data = data;
await SendToSource(e, token).ConfigureAwait(false);
}
}
private async Task ReadPacketTarget(SocketAsyncEventArgs e, AsyncUserToken token)
{
if (token.Proxy.Step == ProxyStep.Request)
{
await ConnectBind(e, token).ConfigureAwait(false);
}
else
{
await SendToSource(e, token).ConfigureAwait(false);
}
}
private async Task ConnectBind(SocketAsyncEventArgs e, AsyncUserToken token)
{
Socket socket = new Socket(token.Proxy.TargetEP.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
socket.KeepAlive();
await socket.ConnectAsync(token.Proxy.TargetEP);
dic.TryAdd(new ConnectId(token.Proxy.ConnectId, token.TargetSocket.GetHashCode()), socket);
BindReceiveTarget(new AsyncUserToken
{
TargetSocket = socket,
SourceSocket = token.TargetSocket,
Proxy = new ProxyInfo
{
Direction = ProxyDirection.Pack,
ConnectId = token.Proxy.ConnectId,
Step = ProxyStep.Forward
}
});
}
private async Task SendToSource(SocketAsyncEventArgs e, AsyncUserToken token)
{
if(token.Proxy.Direction == ProxyDirection.UnPack)
{
ConnectId connectId = new ConnectId(token.Proxy.ConnectId, token.TargetSocket.GetHashCode());
if (dic.TryGetValue(connectId, out Socket source))
{
try
{
await source.SendAsync(token.Proxy.Data);
}
catch (Exception)
{
CloseClientSocket(e);
} }
} }
} }
else else
{ {
token.Proxy.Data = data; byte[] connectData = token.Proxy.ToBytes(out int length);
byte[] bytes = token.Proxy.ToBytes(out int length);
try try
{ {
await token.TargetSocket.SendAsync(bytes.AsMemory(0, length), SocketFlags.None); await token.SourceSocket.SendAsync(connectData.AsMemory(0, length), SocketFlags.None);
} }
catch (Exception) catch (Exception)
{ {
CloseClientSocket(e); CloseClientSocket(e);
} }
token.Proxy.Return(bytes); finally
{
token.Proxy.Return(connectData);
}
} }
} }
@@ -444,7 +492,7 @@ namespace cmonitor.plugins.viewer.proxy
{ {
int ipLength = TargetEP == null ? 0 : (TargetEP.AddressFamily == AddressFamily.InterNetwork ? 4 : 16) + 2; int ipLength = TargetEP == null ? 0 : (TargetEP.AddressFamily == AddressFamily.InterNetwork ? 4 : 16) + 2;
length = 8 + 1 length = 4 + 8 + 1
+ 1 + ipLength + 1 + ipLength
+ Data.Length; + Data.Length;
@@ -452,7 +500,12 @@ namespace cmonitor.plugins.viewer.proxy
Memory<byte> memory = bytes.AsMemory(); Memory<byte> memory = bytes.AsMemory();
int index = 0; int index = 0;
ConnectId.ToBytes(memory);
(length - 4).ToBytes(memory);
index += 4;
ConnectId.ToBytes(memory.Slice(index));
index += 8; index += 8;
bytes[index] = (byte)Step; bytes[index] = (byte)Step;
@@ -483,10 +536,10 @@ namespace cmonitor.plugins.viewer.proxy
public void DeBytes(Memory<byte> memory) public void DeBytes(Memory<byte> memory)
{ {
int index = 0; int index = 4;
Span<byte> span = memory.Span; Span<byte> span = memory.Span;
ConnectId = memory.ToUInt64(); ConnectId = memory.Slice(index).ToUInt64();
index += 8; index += 8;
Step = (ProxyStep)span[index]; Step = (ProxyStep)span[index];
@@ -512,11 +565,14 @@ namespace cmonitor.plugins.viewer.proxy
public ProxyInfo Proxy { get; set; } public ProxyInfo Proxy { get; set; }
public ReceiveDataBuffer Buffer { get; set; }
public void Clear() public void Clear()
{ {
SourceSocket?.SafeClose(); SourceSocket?.SafeClose();
SourceSocket = null; SourceSocket = null;
Buffer?.Clear();
//TargetSocket?.SafeClose(); //TargetSocket?.SafeClose();
//TargetSocket = null; //TargetSocket = null;

View File

@@ -46,6 +46,7 @@ namespace cmonitor.plugins.viewer.proxy
} }
} }
RelayTransportState relayState = await relayTransfer.ConnectAsync(runningConfig.Data.Viewer.ServerMachine, "viewer", config.Data.Client.Relay.SecretKey); RelayTransportState relayState = await relayTransfer.ConnectAsync(runningConfig.Data.Viewer.ServerMachine, "viewer", config.Data.Client.Relay.SecretKey);
if (relayState != null) if (relayState != null)
{ {
tunnelSocket = relayState.Socket; tunnelSocket = relayState.Socket;
@@ -64,14 +65,14 @@ namespace cmonitor.plugins.viewer.proxy
{ {
tunnelTransfer.OnConnected += (TunnelTransportState state) => tunnelTransfer.OnConnected += (TunnelTransportState state) =>
{ {
if (state != null && state.TransportType == ProtocolType.Tcp && state.TransactionId == "viewer") if (state != null && state.TransportType == ProtocolType.Tcp && state.TransactionId == "viewer" && state.Direction == TunnelTransportDirection.Reverse)
{ {
BindReceiveTarget(state.ConnectedObject as Socket, null); BindReceiveTarget(state.ConnectedObject as Socket, null);
} }
}; };
relayTransfer.OnConnected += (RelayTransportState state) => relayTransfer.OnConnected += (RelayTransportState state) =>
{ {
if (state != null && state.Info.TransactionId == "viewer") if (state != null && state.Info.TransactionId == "viewer" && state.Direction == RelayTransportDirection.Reverse)
{ {
BindReceiveTarget(state.Socket, null); BindReceiveTarget(state.Socket, null);
} }

View File

@@ -14,7 +14,7 @@ namespace cmonitor.server
private Socket socket; private Socket socket;
private UdpClient socketUdp; private UdpClient socketUdp;
private CancellationTokenSource cancellationTokenSource; private CancellationTokenSource cancellationTokenSource;
private Memory<byte> relayFLagData = Encoding.UTF8.GetBytes("snltty.relay"); private Memory<byte> relayFLagCData = Encoding.UTF8.GetBytes("snltty.relay");
public Func<IConnection, Task> OnPacket { get; set; } = async (connection) => { await Task.CompletedTask; }; public Func<IConnection, Task> OnPacket { get; set; } = async (connection) => { await Task.CompletedTask; };
public Action<int> OnDisconnected { get; set; } public Action<int> OnDisconnected { get; set; }
@@ -185,7 +185,10 @@ namespace cmonitor.server
int length = e.BytesTransferred; int length = e.BytesTransferred;
bool res = await ReadPacket(token, e.Buffer, offset, length); bool res = await ReadPacket(token, e.Buffer, offset, length);
if (res == false) return; if (res == false)
{
return;
}
if (token.Socket.Available > 0) if (token.Socket.Available > 0)
{ {
@@ -195,7 +198,10 @@ namespace cmonitor.server
if (length > 0) if (length > 0)
{ {
res = await ReadPacket(token, e.Buffer, 0, length); res = await ReadPacket(token, e.Buffer, 0, length);
if (res == false) return; if (res == false)
{
return;
}
} }
else else
{ {
@@ -240,7 +246,7 @@ namespace cmonitor.server
await token.Connection.TcpTargetSocket.SendAsync(data.AsMemory(offset, length), SocketFlags.None); await token.Connection.TcpTargetSocket.SendAsync(data.AsMemory(offset, length), SocketFlags.None);
return true; return true;
} }
else if (length == relayFLagData.Length && data.AsSpan(offset, length).SequenceEqual(relayFLagData.Span)) else if (length == relayFLagCData.Length && data.AsSpan(offset, relayFLagCData.Length).SequenceEqual(relayFLagCData.Span))
{ {
return false; return false;
} }