This commit is contained in:
snltty
2024-04-21 08:56:46 +08:00
parent 08c37367bb
commit 035a4a1b0c
29 changed files with 627 additions and 114 deletions

View File

@@ -3,9 +3,4 @@
<PropertyGroup>
<_LastSelectedProfileId>D:\desktop\cmonitor\cmonitor.viewer.server.win\Properties\PublishProfiles\FolderProfile.pubxml</_LastSelectedProfileId>
</PropertyGroup>
<ItemGroup>
<Compile Update="MainForm.cs">
<SubType>Form</SubType>
</Compile>
</ItemGroup>
</Project>

View File

@@ -13,18 +13,18 @@
</div>
<div class="body flex flex-1">
<div class="private">
<CheckBoxWrap ref="privateProcess" :data="state.privateProcess" :items="state.privateProcessItems" label="Name" text="Name" title="私有程序组"></CheckBoxWrap>
<CheckBoxWrap v-if="state.showCheck" ref="privateProcess" :data="state.privateProcess" :items="state.privateProcessItems" label="Name" text="Name" title="私有程序组"></CheckBoxWrap>
</div>
<div class="flex-1"></div>
<div class="public">
<CheckBoxWrap ref="publicProcess" :data="state.publicProcess" :items="state.publicProcessItems" label="Name" text="Name" title="公共程序组"></CheckBoxWrap>
<CheckBoxWrap v-if="state.showCheck" ref="publicProcess" :data="state.publicProcess" :items="state.publicProcessItems" label="Name" text="Name" title="公共程序组"></CheckBoxWrap>
</div>
</div>
</div>
</template>
<script>
import { computed, reactive, ref, watch } from 'vue';
import { computed, nextTick, reactive, ref, watch } from 'vue';
import CheckBoxWrap from '../../../boxs/CheckBoxWrap.vue'
import { ElMessage } from 'element-plus';
import { updateRule } from '../../../../../apis/hijack'
@@ -78,6 +78,18 @@ export default {
}, 300);
}
});
watch(()=>state.privateProcessItems,()=>{
state.showCheck = false;
nextTick(()=>{
state.showCheck = true;
})
});
watch(()=>state.publicProcessItems,()=>{
state.showCheck = false;
nextTick(()=>{
state.showCheck = true;
})
});
const privateProcess = ref(null);
const publicProcess = ref(null);

View File

@@ -101,7 +101,7 @@ namespace cmonitor.config
{
PluginNames = value.ToList().Concat(new List<string>
{
"client","server","api","web","plugins.signin",
"client","server","api","web","serializes","plugins.signin",
"plugins.watch","plugins.devices","plugins.report",
"plugins.share","plugins.rule","plugins.modes",
}).Select(c => $".{c}.").ToArray();

View File

@@ -7,6 +7,7 @@ using common.libs.winapis;
using System.Text;
using System.Buffers.Binary;
using common.libs;
using common.libs.extends;
namespace cmonitor.plugins.hijack.report.hijack
{
@@ -256,7 +257,6 @@ namespace cmonitor.plugins.hijack.report.hijack
IPHostEntry entry = await Dns.GetHostEntryAsync(domain);
foreach (IPAddress item in entry.AddressList)
{
if (domainIPs.ContainsKey(item) == false)
domainIPs[item] = AllowType.Denied;
}
@@ -372,7 +372,7 @@ namespace cmonitor.plugins.hijack.report.hijack
ushort type = BinaryPrimitives.ReadUInt16BigEndian(span.Slice(index));
index += 2; //type
if (type != 1)
if (type != 1 && type != 28)
{
return null; //不是A查询
}
@@ -391,7 +391,7 @@ namespace cmonitor.plugins.hijack.report.hijack
int dataLength = BinaryPrimitives.ReadUInt16BigEndian(span.Slice(index));
index += 2;
if (type == 1) //是A回应其它的不要
if (type == 1 || type == 28) //是A回应其它的不要
{
ips[i] = new IPAddress(span.Slice(index, dataLength));
}
@@ -423,7 +423,6 @@ namespace cmonitor.plugins.hijack.report.hijack
if (ip != null && domainIPs.TryGetValue(ip, out type))
{
if (type == AllowType.Denied && domainKill)
{
try

View File

@@ -18,7 +18,7 @@ namespace cmonitor.plugins.share.report
public ShareReport(Config config, ShareMemory shareMemory)
{
#if RELEASE
if (config.Common.BlueProtect && OperatingSystem.IsWindows())
//if (config.Data.Common.BlueProtect && OperatingSystem.IsWindows())
{
//ProcessBlueProtection.Protect();
//SystemEvents.SessionEnding += SystemEvents_SessionEnding;

View File

@@ -1,9 +1,12 @@
using cmonitor.config;
using cmonitor.plugins.tunnel.compact;
using cmonitor.plugins.tunnel.messenger;
using cmonitor.plugins.tunnel.server;
using cmonitor.plugins.tunnel.transport;
using cmonitor.startup;
using common.libs;
using Microsoft.Extensions.DependencyInjection;
using System.Net;
using System.Reflection;
namespace cmonitor.plugins.tunnel
@@ -14,11 +17,22 @@ namespace cmonitor.plugins.tunnel
{
serviceCollection.AddSingleton<CompactTransfer>();
serviceCollection.AddSingleton<CompactSelfHost>();
serviceCollection.AddSingleton<TunnelClientMessenger>();
serviceCollection.AddSingleton<TunnelBindServer>();
serviceCollection.AddSingleton<ITransport, TransportTcpNutssb>();
Logger.Instance.Info($"tunnel route level getting.");
config.Data.Client.Tunnel.RouteLevel = NetworkHelper.GetRouteLevel(out List<IPAddress> ips);
Logger.Instance.Info($"tunnel route level:{config.Data.Client.Tunnel.RouteLevel}");
}
public void AddServer(ServiceCollection serviceCollection, Config config, Assembly[] assemblies)
{
serviceCollection.AddSingleton<TunnelServer>();
serviceCollection.AddSingleton<TunnelServerMessenger>();
}
public void UseClient(ServiceProvider serviceProvider, Config config, Assembly[] assemblies)

View File

@@ -1,4 +1,6 @@
using common.libs.extends;
using cmonitor.plugins.tunnel.server;
using common.libs.extends;
using MemoryPack;
using System.Net;
using System.Net.Sockets;
@@ -8,7 +10,7 @@ namespace cmonitor.plugins.tunnel.compact
{
public string Type => "self";
public async Task<CompactIPEndPoint> GetTcpExternalIPAsync(IPEndPoint server)
public async Task<TunnelCompactIPEndPoint> GetTcpExternalIPAsync(IPEndPoint server)
{
Socket socket = new Socket(server.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
socket.Reuse(true);
@@ -17,47 +19,31 @@ namespace cmonitor.plugins.tunnel.compact
byte[] bytes = new byte[20];
int length = await socket.ReceiveAsync(bytes.AsMemory(), SocketFlags.None);
if (length == 0) return null;
return new CompactIPEndPoint { Local = socket.LocalEndPoint as IPEndPoint, Remote = ReadData(bytes) };
if (length == 0)
{
return null;
}
public async Task<CompactIPEndPoint> GetUdpExternalIPAsync(IPEndPoint server)
TunnelExternalIPInfo tunnelExternalIPInfo = MemoryPackSerializer.Deserialize<TunnelExternalIPInfo>(bytes.AsSpan(0,length));
return new TunnelCompactIPEndPoint { Local = socket.LocalEndPoint as IPEndPoint, Remote = tunnelExternalIPInfo.ExternalIP };
}
public async Task<TunnelCompactIPEndPoint> GetUdpExternalIPAsync(IPEndPoint server)
{
using UdpClient udpClient = new UdpClient();
udpClient.Client.Reuse(true);
await udpClient.SendAsync(new byte[1] { 0 }, server);
var result = await udpClient.ReceiveAsync().WaitAsync(TimeSpan.FromSeconds(5));
if (result.Buffer.Length == 0) return null;
return new CompactIPEndPoint { Local = udpClient.Client.LocalEndPoint as IPEndPoint, Remote = ReadData(result.Buffer) };
}
private IPEndPoint ReadData(byte[] bytes)
if (result.Buffer.Length == 0)
{
int index = 0;
AddressFamily family = (AddressFamily)bytes[index];
index++;
int ipLength = family switch
{
AddressFamily.InterNetwork => 4,
AddressFamily.InterNetworkV6 => 16,
_ => 0,
};
if (ipLength > 0)
{
IPAddress ip = new IPAddress(bytes.AsSpan(0, ipLength));
index += ipLength;
ushort port = bytes.AsSpan(index).ToUInt16();
IPEndPoint iPEndPoint = new IPEndPoint(ip, port);
return iPEndPoint;
}
return null;
}
TunnelExternalIPInfo tunnelExternalIPInfo = MemoryPackSerializer.Deserialize<TunnelExternalIPInfo>(result.Buffer);
return new TunnelCompactIPEndPoint { Local = udpClient.Client.LocalEndPoint as IPEndPoint, Remote = tunnelExternalIPInfo.ExternalIP };
}
}
}

View File

@@ -31,9 +31,9 @@ namespace cmonitor.plugins.tunnel.compact
Logger.Instance.Warning($"load tunnel compacts:{string.Join(",", compacts.Select(c => c.Type))}");
}
public async Task<CompactIPEndPoint[]> GetExternalIPAsync(ProtocolType protocolType)
public async Task<TunnelCompactIPEndPoint[]> GetExternalIPAsync(ProtocolType protocolType)
{
CompactIPEndPoint[] endpoints = new CompactIPEndPoint[config.Data.Client.Tunnel.Servers.Length];
TunnelCompactIPEndPoint[] endpoints = new TunnelCompactIPEndPoint[config.Data.Client.Tunnel.Servers.Length];
for (int i = 0; i < config.Data.Client.Tunnel.Servers.Length; i++)
{
@@ -46,12 +46,12 @@ namespace cmonitor.plugins.tunnel.compact
IPEndPoint server = NetworkHelper.GetEndPoint(item.Host, 3478);
if (protocolType == ProtocolType.Tcp)
{
CompactIPEndPoint externalIP = await compact.GetTcpExternalIPAsync(server);
TunnelCompactIPEndPoint externalIP = await compact.GetTcpExternalIPAsync(server);
endpoints[i] = externalIP;
}
else if (protocolType == ProtocolType.Udp)
{
CompactIPEndPoint externalIP = await compact.GetUdpExternalIPAsync(server);
TunnelCompactIPEndPoint externalIP = await compact.GetUdpExternalIPAsync(server);
endpoints[i] = externalIP;
}
}

View File

@@ -5,11 +5,11 @@ namespace cmonitor.plugins.tunnel.compact
public interface ICompact
{
public string Type { get; }
public Task<CompactIPEndPoint> GetTcpExternalIPAsync(IPEndPoint server);
public Task<CompactIPEndPoint> GetUdpExternalIPAsync(IPEndPoint server);
public Task<TunnelCompactIPEndPoint> GetTcpExternalIPAsync(IPEndPoint server);
public Task<TunnelCompactIPEndPoint> GetUdpExternalIPAsync(IPEndPoint server);
}
public sealed class CompactIPEndPoint
public sealed class TunnelCompactIPEndPoint
{
public IPEndPoint Local { get; set; }
public IPEndPoint Remote { get; set; }

View File

@@ -1,4 +1,6 @@
namespace cmonitor.config
using System.Text.Json.Serialization;
namespace cmonitor.config
{
public partial class ConfigClientInfo
{
@@ -15,6 +17,9 @@
{
new TunnelCompactInfo { Type="self", Host="127.0.0.1:1804" }
};
[JsonIgnore]
public int RouteLevel { get; set; }
}
public sealed class TunnelConfigServerInfo

View File

@@ -1,12 +1,66 @@
using cmonitor.server;
using cmonitor.config;
using cmonitor.plugins.signin.messenger;
using cmonitor.plugins.tunnel.transport;
using cmonitor.server;
using MemoryPack;
using System.Buffers;
namespace cmonitor.plugins.tunnel.messenger
{
public sealed class TunnelMessenger : IMessenger
public sealed class TunnelClientMessenger : IMessenger
{
public TunnelMessenger()
private readonly ITransport transport;
private readonly Config config;
public TunnelClientMessenger(ITransport transport, Config config)
{
this.transport = transport;
this.config = config;
}
[MessengerId((ushort)TunnelMessengerIds.Begin)]
public async Task Begin(IConnection connection)
{
TunnelTransportInfo tunnelTransportInfo = MemoryPackSerializer.Deserialize<TunnelTransportInfo>(connection.ReceiveRequestWrap.Payload.Span);
tunnelTransportInfo.RouteLevel = config.Data.Client.Tunnel.RouteLevel;
TunnelTransportInfo info = await transport.OnBegin(tunnelTransportInfo);
connection.Write(MemoryPackSerializer.Serialize(info));
}
}
public sealed class TunnelServerMessenger : IMessenger
{
private readonly MessengerSender messengerSender;
private readonly SignCaching signCaching;
public TunnelServerMessenger(MessengerSender messengerSender, SignCaching signCaching)
{
this.messengerSender = messengerSender;
this.signCaching = signCaching;
}
[MessengerId((ushort)TunnelMessengerIds.BeginForward)]
public async Task BeginForward(IConnection connection)
{
TunnelTransportInfo tunnelTransportInfo = MemoryPackSerializer.Deserialize<TunnelTransportInfo>(connection.ReceiveRequestWrap.Payload.Span);
if (signCaching.Get(tunnelTransportInfo.ToMachineName, out SignCacheInfo cache))
{
MessageResponeInfo resp = await messengerSender.SendReply(new MessageRequestWrap
{
Connection = cache.Connection,
MessengerId = (ushort)TunnelMessengerIds.Begin,
Payload = connection.ReceiveRequestWrap.Payload
});
if (resp.Code == MessageResponeCodes.OK)
{
byte[] bytes = ArrayPool<byte>.Shared.Rent(resp.Data.Length);
resp.Data.CopyTo(bytes);
connection.Write(bytes.AsMemory(0, resp.Data.Length));
ArrayPool<byte>.Shared.Return(bytes);
}
}
}
}
}

View File

@@ -3,7 +3,10 @@
public enum TunnelMessengerIds : ushort
{
Update = 2000,
Begin = 2001,
BeginForward = 2002,
Reverse = 2003,
ReverseForward = 2004,
None = 2001
}
}

View File

@@ -0,0 +1,117 @@
using common.libs;
using common.libs.extends;
using System.Net;
using System.Net.Sockets;
namespace cmonitor.plugins.tunnel.server
{
public sealed class TunnelBindServer
{
private SocketAsyncEventArgs acceptEventArg;
private Socket socket;
private UdpClient socketUdp;
public Action<object, Socket> OnTcpConnected { get; set; } = (state, socket) => { };
public Action<object, UdpClient> OnUdpConnected { get; set; } = (state, udpClient) => { };
public void Bind(IPEndPoint local, object state)
{
try
{
socket = new Socket(local.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
socket.IPv6Only(local.AddressFamily, false);
socket.ReuseBind(local);
socket.Listen(int.MaxValue);
acceptEventArg = new SocketAsyncEventArgs
{
UserToken = new AsyncUserToken
{
SourceSocket = socket,
State = state
},
SocketFlags = SocketFlags.None,
};
acceptEventArg.Completed += IO_Completed;
StartAccept(acceptEventArg);
socketUdp = new UdpClient();
socketUdp.Client.ReuseBind(local);
socketUdp.Client.EnableBroadcast = true;
socketUdp.Client.WindowsUdpBug();
IAsyncResult result = socketUdp.BeginReceive(ReceiveCallbackUdp, state);
}
catch (Exception ex)
{
Logger.Instance.Error(ex);
}
}
private void StartAccept(SocketAsyncEventArgs acceptEventArg)
{
acceptEventArg.AcceptSocket = null;
AsyncUserToken token = (AsyncUserToken)acceptEventArg.UserToken;
try
{
if (token.SourceSocket.AcceptAsync(acceptEventArg) == false)
{
ProcessAccept(acceptEventArg);
}
}
catch (Exception)
{
token.Clear();
}
}
private void IO_Completed(object sender, SocketAsyncEventArgs e)
{
switch (e.LastOperation)
{
case SocketAsyncOperation.Accept:
ProcessAccept(e);
break;
default:
break;
}
}
private void ProcessAccept(SocketAsyncEventArgs e)
{
if (e.AcceptSocket != null)
{
AsyncUserToken token = e.UserToken as AsyncUserToken;
OnTcpConnected(token.State, e.AcceptSocket);
StartAccept(e);
}
}
private void ReceiveCallbackUdp(IAsyncResult result)
{
try
{
IPEndPoint ep = new IPEndPoint(IPAddress.Any, IPEndPoint.MinPort);
byte[] _ = socketUdp.EndReceive(result, ref ep);
OnUdpConnected(result.AsyncState, socketUdp);
}
catch (Exception)
{
}
}
public sealed class AsyncUserToken
{
public Socket SourceSocket { get; set; }
public object State { get; set; }
public void Clear()
{
SourceSocket?.SafeClose();
SourceSocket = null;
GC.Collect();
}
}
}
}

View File

@@ -1,6 +1,6 @@
using common.libs;
using common.libs.extends;
using System.Buffers;
using MemoryPack;
using System.Net;
using System.Net.Sockets;
@@ -88,20 +88,10 @@ namespace cmonitor.plugins.tunnel.server
if (token.SourceSocket != null)
{
IPEndPoint ep = token.SourceSocket.RemoteEndPoint as IPEndPoint;
Memory<byte> memory = MemoryPackSerializer.Serialize(new TunnelExternalIPInfo { ExternalIP = ep });
byte[] bytes = ArrayPool<byte>.Shared.Rent(20);
await token.SourceSocket.SendAsync(memory);
int index = 0;
bytes[index] = (byte)ep.Address.AddressFamily;
index++;
ep.Address.TryWriteBytes(bytes.AsSpan(index), out int bytesWritten);
index += bytesWritten;
((ushort)ep.Port).ToBytes(bytes.AsMemory(index));
index += 2;
await token.SourceSocket.SendAsync(bytes.AsMemory(0, index));
ArrayPool<byte>.Shared.Return(bytes);
}
}
@@ -112,20 +102,9 @@ namespace cmonitor.plugins.tunnel.server
IPEndPoint ep = new IPEndPoint(IPAddress.Any, IPEndPoint.MinPort);
byte[] _ = socketUdp.EndReceive(result, ref ep);
Memory<byte> memory = MemoryPackSerializer.Serialize(new TunnelExternalIPInfo { ExternalIP = ep });
byte[] bytes = ArrayPool<byte>.Shared.Rent(20);
int index = 0;
bytes[index] = (byte)ep.Address.AddressFamily;
index++;
ep.Address.TryWriteBytes(bytes.AsSpan(index), out int bytesWritten);
index += bytesWritten;
((ushort)ep.Port).ToBytes(bytes.AsMemory(index));
index += 2;
await socketUdp.SendAsync(bytes.AsMemory(0, index), ep);
ArrayPool<byte>.Shared.Return(bytes);
await socketUdp.SendAsync(memory, ep);
result = socketUdp.BeginReceive(ReceiveCallbackUdp, null);
}
@@ -147,6 +126,7 @@ namespace cmonitor.plugins.tunnel.server
public void Stop()
{
CloseClientSocket(acceptEventArg);
socketUdp?.Close();
}
}
@@ -162,4 +142,11 @@ namespace cmonitor.plugins.tunnel.server
GC.Collect();
}
}
[MemoryPackable]
public sealed partial class TunnelExternalIPInfo
{
[MemoryPackAllowSerialize]
public IPEndPoint ExternalIP { get; set; }
}
}

View File

@@ -1,10 +1,43 @@
using System.Net;
using MemoryPack;
using System.Net;
using System.Net.Sockets;
namespace cmonitor.plugins.tunnel.transport
{
public interface ITransport
{
public Task<Socket> ConnectAsync(IPEndPoint local, IPEndPoint remote);
public string Name { get; }
public ProtocolType TypeFlag { get; }
public Func<TunnelTransportInfo, Task<TunnelTransportInfo>> SendBegin { get; set; }
public Action<TransportState> OnConnected { get; set; }
public Task<Socket> ConnectAsync(string fromMachineName, string toMachineName);
public Task<TunnelTransportInfo> OnBegin(TunnelTransportInfo tunnelTransportNoticeInfo);
public Task OnReverse(TunnelTransportInfo tunnelTransportNoticeInfo);
}
[MemoryPackable]
public sealed partial class TunnelTransportInfo
{
[MemoryPackAllowSerialize]
public IPEndPoint FromLocal { get; set; }
[MemoryPackAllowSerialize]
public IPEndPoint FromRemote { get; set; }
public string FromMachineName { get; set; }
public string ToMachineName { get; set; }
public ProtocolType TypeFlag { get; set; }
public int RouteLevel { get; set; }
}
public sealed class TransportState
{
public string FromMachineName { get; set; }
public ProtocolType TypeFlag { get; set; }
public object ConnectedObject { get; set; }
}
}

View File

@@ -0,0 +1,160 @@
using cmonitor.plugins.tunnel.compact;
using cmonitor.plugins.tunnel.server;
using common.libs;
using common.libs.extends;
using System.Net;
using System.Net.Sockets;
namespace cmonitor.plugins.tunnel.transport
{
public sealed class TransportTcpNutssb : ITransport
{
private readonly TunnelBindServer tunnelBindServer;
private readonly CompactTransfer compactTransfer;
public Action<TransportState> OnConnected { get; set; } = (state) => { };
public Func<TunnelTransportInfo, Task<TunnelTransportInfo>> SendBegin { get; set; }
public string Name => "TcpNutssb";
public ProtocolType TypeFlag => ProtocolType.Tcp;
public TransportTcpNutssb(TunnelBindServer tunnelBindServer, CompactTransfer compactTransfer)
{
this.tunnelBindServer = tunnelBindServer;
tunnelBindServer.OnTcpConnected += OnTcpConnected;
this.compactTransfer = compactTransfer;
}
public async Task<Socket> ConnectAsync(string fromMachineName, string toMachineName)
{
//获取自己的外网IP
TunnelCompactIPEndPoint[] ips = await compactTransfer.GetExternalIPAsync(TypeFlag);
if (ips.Length == 0)
{
return null;
}
//告诉对方,我要连你,你需要给我发送一下 低TTL并且对方要返回它的外网地址过来给我去连接
TunnelTransportInfo tunnelTransportInfo = new TunnelTransportInfo
{
FromMachineName = fromMachineName,
ToMachineName = toMachineName,
FromLocal = ips[0].Local,
FromRemote = ips[0].Remote,
};
TunnelTransportInfo remoteInfo = await SendBegin(tunnelTransportInfo);
//要连接哪些IP
IPEndPoint[] eps = new IPEndPoint[] {
new IPEndPoint(remoteInfo.FromLocal.Address,remoteInfo.FromLocal.Port),
new IPEndPoint(remoteInfo.FromLocal.Address,remoteInfo.FromRemote.Port),
new IPEndPoint(remoteInfo.FromLocal.Address,remoteInfo.FromRemote.Port+1),
new IPEndPoint(remoteInfo.FromRemote.Address,remoteInfo.FromRemote.Port),
new IPEndPoint(remoteInfo.FromRemote.Address,remoteInfo.FromRemote.Port+1),
};
//过滤掉不支持IPV6的情况去尝试连接
IEnumerable<IAsyncResult> results = eps.Where(c => NotIPv6Support(c.Address) == false).Select(ip =>
{
using Socket targetSocket = new(ip.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
try
{
targetSocket.IPv6Only(ip.Address.AddressFamily, false);
targetSocket.ReuseBind(new IPEndPoint(ip.AddressFamily == AddressFamily.InterNetwork ? IPAddress.Any : IPAddress.IPv6Any, tunnelTransportInfo.FromLocal.Port));
IAsyncResult result = targetSocket.BeginConnect(ip, null, targetSocket);
return result;
}
catch (Exception)
{
}
return null;
});
//检查一下是否连接成功
for (int i = 0; i < 10; i++)
{
IAsyncResult result = results.FirstOrDefault(c => c.IsCompleted);
if (result != null)
{
return result.AsyncState as Socket;
}
await Task.Delay(10);
}
return null;
}
public async Task<TunnelTransportInfo> OnBegin(TunnelTransportInfo tunnelTransportInfo)
{
//获取自己的外网IP
TunnelCompactIPEndPoint[] ips = await compactTransfer.GetExternalIPAsync(ProtocolType.Tcp);
if (ips.Length == 0)
{
return null;
}
//监听,等对方来连
TunnelTransportInfo info = new TunnelTransportInfo
{
ToMachineName = tunnelTransportInfo.FromMachineName,
FromMachineName = tunnelTransportInfo.ToMachineName,
FromLocal = ips[0].Local,
FromRemote = ips[0].Remote,
RouteLevel = tunnelTransportInfo.RouteLevel
};
TransportTcpNutssbState state = new TransportTcpNutssbState { FromMachineName = tunnelTransportInfo.FromMachineName };
tunnelBindServer.Bind(info.FromLocal, state);
//给对方发送TTL消息
IPEndPoint[] eps = new IPEndPoint[] {
new IPEndPoint(tunnelTransportInfo.FromLocal.Address,tunnelTransportInfo.FromLocal.Port),
new IPEndPoint(tunnelTransportInfo.FromLocal.Address,tunnelTransportInfo.FromRemote.Port),
new IPEndPoint(tunnelTransportInfo.FromLocal.Address,tunnelTransportInfo.FromRemote.Port+1),
new IPEndPoint(tunnelTransportInfo.FromRemote.Address,tunnelTransportInfo.FromRemote.Port),
new IPEndPoint(tunnelTransportInfo.FromRemote.Address,tunnelTransportInfo.FromRemote.Port+1),
};
//过滤掉不支持IPV6的情况
IEnumerable<Socket> sockets = eps.Where(c => NotIPv6Support(c.Address) == false).Select(ip =>
{
using Socket targetSocket = new(ip.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
try
{
targetSocket.IPv6Only(ip.Address.AddressFamily, false);
targetSocket.Ttl = (short)(info.RouteLevel);
targetSocket.ReuseBind(new IPEndPoint(ip.AddressFamily == AddressFamily.InterNetwork ? IPAddress.Any : IPAddress.IPv6Any, info.FromLocal.Port));
_ = targetSocket.ConnectAsync(ip);
return targetSocket;
}
catch (Exception)
{
}
return null;
});
foreach (Socket item in sockets.Where(c => c != null && c.Connected == false))
{
item.SafeClose();
}
return info;
}
public async Task OnReverse(TunnelTransportInfo tunnelTransportInfo)
{
}
private void OnTcpConnected(object state, Socket socket)
{
if (state is TransportTcpNutssbState _state)
{
OnConnected(new TransportState { FromMachineName = _state.FromMachineName, TypeFlag = ProtocolType.Tcp, ConnectedObject = socket });
}
}
private bool NotIPv6Support(IPAddress ip)
{
return ip.AddressFamily == AddressFamily.InterNetworkV6 && (NetworkHelper.IPv6Support == false);
}
public sealed class TransportTcpNutssbState
{
public string FromMachineName { get; set; }
}
}
}

View File

@@ -53,7 +53,7 @@ namespace cmonitor.plugins.viewer.messenger
public async Task ProxyFromServer(IConnection connection)
{
ViewerProxyInfo proxy = MemoryPackSerializer.Deserialize<ViewerProxyInfo>(connection.ReceiveRequestWrap.Payload.Span);
proxy.ProxyEP = $"{clientSignInState.Connection.Address.Address}:{config.Data.Client.Viewer.ProxyPort}";
proxy.ProxyEP = new System.Net.IPEndPoint(clientSignInState.Connection.Address.Address,config.Data.Client.Viewer.ProxyPort);
proxy.TargetEP = runningConfig.Data.Viewer.ConnectEP;
await viewerProxyClient.Connect(proxy);
}

View File

@@ -248,22 +248,13 @@ namespace cmonitor.plugins.viewer.proxy
Socket targetSocket = null;
try
{
if (IPEndPoint.TryParse(viewerProxyInfo.ProxyEP, out IPEndPoint proxyEP) == false)
{
return;
}
if (IPEndPoint.TryParse(viewerProxyInfo.TargetEP, out IPEndPoint targetEP) == false)
{
return;
}
proxySocket = new Socket(proxyEP.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
proxySocket = new Socket(viewerProxyInfo.ProxyEP.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
proxySocket.KeepAlive();
await proxySocket.ConnectAsync(proxyEP);
await proxySocket.ConnectAsync(viewerProxyInfo.ProxyEP);
targetSocket = new Socket(targetEP.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
targetSocket = new Socket(viewerProxyInfo.TargetEP.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
targetSocket.KeepAlive();
await targetSocket.ConnectAsync(targetEP);
await targetSocket.ConnectAsync(viewerProxyInfo.TargetEP);
int length = responseBytes.Length + 4;
byte[] data = ArrayPool<byte>.Shared.Rent(length);
@@ -428,9 +419,11 @@ namespace cmonitor.plugins.viewer.proxy
public string ViewerMachine { get; set; }
public string ProxyEP { get; set; }
[MemoryPackAllowSerialize]
public IPEndPoint ProxyEP { get; set; }
public string TargetEP { get; set; }
[MemoryPackAllowSerialize]
public IPEndPoint TargetEP { get; set; }
}
public sealed class ConnectServerCache

View File

@@ -35,7 +35,7 @@ namespace cmonitor.plugins.viewer.proxy
Payload = MemoryPackSerializer.Serialize(new ViewerProxyInfo
{
ConnectId = connectId,
ProxyEP = $"{clientSignInState.Connection.LocalAddress.Address}:{LocalEndpoint.Port}",
ProxyEP = new System.Net.IPEndPoint(clientSignInState.Connection.LocalAddress.Address, LocalEndpoint.Port),
ViewerMachine = runningConfig.Data.Viewer.ServerMachine
})
});

View File

@@ -31,7 +31,7 @@ namespace cmonitor.plugins.viewer.proxy
Payload = MemoryPackSerializer.Serialize(new ViewerProxyInfo
{
ConnectId = connectId,
ProxyEP = string.Empty,
ProxyEP = null,
ViewerMachine = string.Empty
})
});

View File

@@ -10,9 +10,9 @@ namespace cmonitor.plugins.viewer.report
public void Open(bool value, ParamInfo info);
public string GetConnectString();
public void SetConnectString(string connectStr);
public string GetConnectEP(string connectStr)
public IPEndPoint GetConnectEP(string connectStr)
{
return string.Empty;
return null;
}
}
@@ -50,7 +50,8 @@ namespace cmonitor.plugins.viewer.report
/// 比如 B 是共享服务端A是共享客户端
/// 当连不上时会需要代理由B去连接A或者B去连接服务器形成通道那B这边还需要手动连接共享服务就用这个去连
/// </summary>
public string ConnectEP { get; set; } = string.Empty;
[MemoryPackAllowSerialize]
public IPEndPoint ConnectEP { get; set; }
}
public enum ViewerMode : byte

View File

@@ -16,9 +16,9 @@ namespace cmonitor.plugins.viewer.report
}
public string GetConnectEP(string connectStr)
public IPEndPoint GetConnectEP(string connectStr)
{
return string.Empty;
return null;
}
}
}

View File

@@ -16,9 +16,9 @@ namespace cmonitor.plugins.viewer.report
}
public string GetConnectEP(string connectStr)
public IPEndPoint GetConnectEP(string connectStr)
{
return string.Empty;
return null;
}
}
}

View File

@@ -179,7 +179,7 @@ namespace cmonitor.plugins.viewer.report
}
private void UpdateConnectEP()
{
string connectEP = viewer.GetConnectEP(runningConfig.Data.Viewer.ConnectStr);
IPEndPoint connectEP = viewer.GetConnectEP(runningConfig.Data.Viewer.ConnectStr);
runningConfig.Data.Viewer.ConnectEP = connectEP;
runningConfig.Data.Update();
}

View File

@@ -35,7 +35,7 @@ namespace cmonitor.plugins.viewer.report
Registry.SetValue("HKEY_CURRENT_USER\\SOFTWARE\\Cmonitor", "viewerConnectStr", connectStr);
}
public string GetConnectEP(string connectStr)
public IPEndPoint GetConnectEP(string connectStr)
{
try
{
@@ -48,13 +48,13 @@ namespace cmonitor.plugins.viewer.report
var p = node.Attributes["P"].Value;
var n = node.Attributes["N"].Value;
return $"{n}:{p}";
return new IPEndPoint(IPAddress.Parse(n),int.Parse(p));
}
catch (Exception ex)
{
Logger.Instance.Error(ex);
}
return string.Empty;
return null;
}
}
}

View File

@@ -0,0 +1,50 @@
using common.libs.extends;
using MemoryPack;
using System.Net;
namespace cmonitor.serializes
{
public sealed class IPEndPointFormatter : MemoryPackFormatter<IPEndPoint>
{
public override void Serialize<TBufferWriter>(ref MemoryPackWriter<TBufferWriter> writer, scoped ref IPEndPoint value)
{
if (value == null)
{
writer.WriteNullCollectionHeader();
return;
}
Memory<byte> memory = new byte[20];
Span<byte> span = memory.Span;
int index = 1;
value.Address.TryWriteBytes(span.Slice(index), out int bytesWritten);
index += bytesWritten;
span[0] = (byte)bytesWritten;
ushort port = (ushort)value.Port;
port.ToBytes(memory.Slice(index));
index += 2;
writer.WriteCollectionHeader(index + 4);
writer.WriteSpan(span.Slice(0, index));
}
public override void Deserialize(ref MemoryPackReader reader, scoped ref IPEndPoint value)
{
if (!reader.TryReadCollectionHeader(out int len))
{
value = null;
return;
}
Span<byte> span = Array.Empty<byte>();
reader.ReadSpan(ref span);
int length = span[4];
value = new IPEndPoint(new IPAddress(span.Slice(4 + 1, length)), span.Slice(4 + 1 + length).ToUInt16());
}
}
}

View File

@@ -0,0 +1,30 @@
using cmonitor.config;
using cmonitor.startup;
using MemoryPack;
using Microsoft.Extensions.DependencyInjection;
using System.Reflection;
namespace cmonitor.serializes
{
public sealed class SerializeStartup : IStartup
{
public void AddClient(ServiceCollection serviceCollection, Config config, Assembly[] assemblies)
{
MemoryPackFormatterProvider.Register(new IPEndPointFormatter());
}
public void AddServer(ServiceCollection serviceCollection, Config config, Assembly[] assemblies)
{
MemoryPackFormatterProvider.Register(new IPEndPointFormatter());
}
public void UseClient(ServiceProvider serviceProvider, Config config, Assembly[] assemblies)
{
}
public void UseServer(ServiceProvider serviceProvider, Config config, Assembly[] assemblies)
{
}
}
}

View File

@@ -16,6 +16,8 @@ namespace cmonitor.startup
types = types.Where(c => config.Data.Common.PluginNames.Any(d => c.FullName.Contains(d)));
}
startups = types.Select(c => Activator.CreateInstance(c) as IStartup).ToList();
Logger.Instance.Warning($"load startup : {string.Join(",", types.Select(c=>c.Name))}");
}
public static void Add(ServiceCollection serviceCollection, Config config, Assembly[] assemblies)

View File

@@ -1,7 +1,10 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Text;
namespace common.libs
{
@@ -46,6 +49,75 @@ namespace common.libs
return new IPEndPoint(ip, port);
}
public static ushort GetRouteLevel(out List<IPAddress> ips)
{
ips = new List<IPAddress>();
try
{
List<string> starts = new() { "10.", "100.", "192.168.", "172." };
var list = GetTraceRoute("www.baidu.com").ToList();
for (ushort i = 0; i < list.Count(); i++)
{
string ip = list.ElementAt(i).ToString();
if (ip.StartsWith(starts[0], StringComparison.Ordinal) || ip.StartsWith(starts[1], StringComparison.Ordinal) || ip.StartsWith(starts[2], StringComparison.Ordinal) || ip.StartsWith(starts[3], StringComparison.Ordinal))
{
if (ip.StartsWith(starts[2], StringComparison.Ordinal) == false)
ips.Add(list.ElementAt(i));
}
else
{
return i;
}
}
}
catch (Exception)
{
}
return 0;
}
public static IEnumerable<IPAddress> GetTraceRoute(string hostNameOrAddress)
{
return GetTraceRoute(hostNameOrAddress, 1);
}
private static IEnumerable<IPAddress> GetTraceRoute(string hostNameOrAddress, int ttl)
{
Ping pinger = new();
// 创建PingOptions对象
PingOptions pingerOptions = new(ttl, true);
int timeout = 100;
byte[] buffer = Encoding.ASCII.GetBytes("11");
// 创建PingReply对象
// 发送ping命令
PingReply reply = pinger.Send(hostNameOrAddress, timeout, buffer, pingerOptions);
// 处理返回结果
List<IPAddress> result = new();
if (reply.Status == IPStatus.Success)
{
result.Add(reply.Address);
}
else if (reply.Status == IPStatus.TtlExpired || reply.Status == IPStatus.TimedOut)
{
//增加当前这个访问地址
if (reply.Status == IPStatus.TtlExpired)
{
result.Add(reply.Address);
}
if (ttl <= 10)
{
//递归访问下一个地址
IEnumerable<IPAddress> tempResult = GetTraceRoute(hostNameOrAddress, ttl + 1);
result.AddRange(tempResult);
}
}
else
{
//失败
}
return result;
}
#if DISABLE_IPV6 || (!UNITY_EDITOR && ENABLE_IL2CPP && !UNITY_2018_3_OR_NEWER)
public static bool IPv6Support = false;