mirror of
https://github.com/snltty/linker.git
synced 2025-10-27 19:10:27 +08:00
IPV6
This commit is contained in:
@@ -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>
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,10 @@
|
||||
public enum TunnelMessengerIds : ushort
|
||||
{
|
||||
Update = 2000,
|
||||
|
||||
Begin = 2001,
|
||||
BeginForward = 2002,
|
||||
Reverse = 2003,
|
||||
ReverseForward = 2004,
|
||||
None = 2001
|
||||
}
|
||||
}
|
||||
|
||||
117
cmonitor/plugins/tunnel/server/TunnelBindServer.cs
Normal file
117
cmonitor/plugins/tunnel/server/TunnelBindServer.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -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; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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; }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
160
cmonitor/plugins/tunnel/transport/TransportTcpNutssb.cs
Normal file
160
cmonitor/plugins/tunnel/transport/TransportTcpNutssb.cs
Normal 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; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
})
|
||||
});
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace cmonitor.plugins.viewer.proxy
|
||||
Payload = MemoryPackSerializer.Serialize(new ViewerProxyInfo
|
||||
{
|
||||
ConnectId = connectId,
|
||||
ProxyEP = string.Empty,
|
||||
ProxyEP = null,
|
||||
ViewerMachine = string.Empty
|
||||
})
|
||||
});
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -16,9 +16,9 @@ namespace cmonitor.plugins.viewer.report
|
||||
|
||||
}
|
||||
|
||||
public string GetConnectEP(string connectStr)
|
||||
public IPEndPoint GetConnectEP(string connectStr)
|
||||
{
|
||||
return string.Empty;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,9 +16,9 @@ namespace cmonitor.plugins.viewer.report
|
||||
|
||||
}
|
||||
|
||||
public string GetConnectEP(string connectStr)
|
||||
public IPEndPoint GetConnectEP(string connectStr)
|
||||
{
|
||||
return string.Empty;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
50
cmonitor/serializes/IPEndPointFormatter.cs
Normal file
50
cmonitor/serializes/IPEndPointFormatter.cs
Normal 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());
|
||||
}
|
||||
}
|
||||
}
|
||||
30
cmonitor/serializes/SerializeStartup.cs
Normal file
30
cmonitor/serializes/SerializeStartup.cs
Normal 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)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user