This commit is contained in:
snltty
2024-06-02 00:37:58 +08:00
parent ddd36a09d6
commit 7eda8044e5
14 changed files with 440 additions and 146 deletions

View File

@@ -9,6 +9,11 @@
<el-table-column prop="Name" label="名称"></el-table-column>
<el-table-column prop="Label" label="说明"></el-table-column>
<el-table-column prop="ProtocolType" label="协议" ></el-table-column>
<el-table-column property="Reverse" label="反向" width="60">
<template #default="scope">
<el-switch v-model="scope.row.Reverse" @change="handleSave" inline-prompt active-text="是" inactive-text="否" style="--el-switch-on-color: red; --el-switch-off-color: #ddd" />
</template>
</el-table-column>
<el-table-column property="Disabled" label="禁用" width="60">
<template #default="scope">
<el-switch v-model="scope.row.Disabled" @change="handleSave" inline-prompt active-text="是" inactive-text="否" style="--el-switch-on-color: red; --el-switch-off-color: #ddd" />

View File

@@ -28,16 +28,15 @@ namespace cmonitor.client
this.messengerSender = messengerSender;
this.signInArgsTransfer = signInArgsTransfer;
SignInTask();
//SignInTask();
}
private void SignInTask()
public void SignInTask()
{
Task.Run(async () =>
{
while (true)
{
if (clientSignInState.Connected == false)
{
try

View File

@@ -49,7 +49,7 @@ namespace cmonitor.client
if (string.IsNullOrWhiteSpace(config.Data.Client.Server) && config.Data.Client.Servers.Length > 0)
config.Data.Client.Server = config.Data.Client.Servers.FirstOrDefault().Host;
ClientSignInTransfer clientTransfer = serviceProvider.GetService<ClientSignInTransfer>();
clientTransfer.SignInTask();
}

View File

@@ -6,6 +6,7 @@ using System.Net.Quic;
using System.Net;
using System.Text;
using System.Text.Json.Serialization;
using System.Net.Sockets;
namespace cmonitor.client.tunnel
{
@@ -32,6 +33,11 @@ namespace cmonitor.client.tunnel
[JsonIgnore]
public QuicConnection Connection { get; init; }
[JsonIgnore]
public UdpClient LocalUdp { get; init; }
[JsonIgnore]
public UdpClient remoteUdp { get; init; }
private ITunnelConnectionReceiveCallback callback;
private CancellationTokenSource cancellationTokenSource;
@@ -256,6 +262,9 @@ namespace cmonitor.client.tunnel
Connection?.CloseAsync(0x0a);
Connection?.DisposeAsync();
LocalUdp?.Close();
remoteUdp?.Close();
}
public override string ToString()

View File

@@ -10,6 +10,7 @@ using common.libs.extends;
using MemoryPack;
using Microsoft.Extensions.DependencyInjection;
using System.Collections.Concurrent;
using System.Net;
using System.Reflection;
namespace cmonitor.plugins.tunnel
@@ -59,7 +60,7 @@ namespace cmonitor.plugins.tunnel
//拼接,再去重,因为有可能有新的
config.Data.Client.Tunnel.TunnelTransports = config.Data.Client.Tunnel.TunnelTransports
.Concat(transports.Select(c => new TunnelTransportItemInfo { Disabled = c.Disabled, Label = c.Label, Name = c.Name, ProtocolType = c.ProtocolType.ToString() }))
.Concat(transports.Select(c => new TunnelTransportItemInfo { Reverse = true, Disabled = false, Label = c.Label, Name = c.Name, ProtocolType = c.ProtocolType.ToString() }))
.Distinct(new TunnelTransportItemInfoEqualityComparer())
.ToList();
@@ -91,6 +92,7 @@ namespace cmonitor.plugins.tunnel
{
Connection = clientSignInState.Connection,
MessengerId = (ushort)TunnelMessengerIds.ConfigForward,
Timeout = 3000,
Payload = MemoryPackSerializer.Serialize(config)
}).ContinueWith((result) =>
{
@@ -157,7 +159,8 @@ namespace cmonitor.plugins.tunnel
* 所以,我们需要在第一次正向连接失败后再尝试反向连接,因为间隔了一定时间,最大程度避免了连续端口污染
*/
TunnelTransportInfo tunnelTransportInfo = null;
for (int i = 0; i <= 0; i++)
int times = transportItem.Reverse ? 1 : 0;
for (int i = 0; i <= times; i++)
{
try
{
@@ -197,7 +200,7 @@ namespace cmonitor.plugins.tunnel
}
catch (Exception ex)
{
if(Logger.Instance.LoggerLevel <= LoggerTypes.DEBUG)
if (Logger.Instance.LoggerLevel <= LoggerTypes.DEBUG)
{
Logger.Instance.Error(ex);
}
@@ -243,7 +246,7 @@ namespace cmonitor.plugins.tunnel
private async Task<TunnelTransportExternalIPInfo> GetLocalInfo()
{
TunnelCompactIPEndPoint ip = await compactTransfer.GetExternalIPAsync();
TunnelCompactIPEndPoint ip = await compactTransfer.GetExternalIPAsync(clientSignInState.Connection?.LocalAddress.Address ?? IPAddress.Any);
if (ip != null)
{
return new TunnelTransportExternalIPInfo

View File

@@ -11,21 +11,17 @@ namespace cmonitor.plugins.tunnel.compact
public string Name => "默认";
public TunnelCompactType Type => TunnelCompactType.Self;
public static UdpClient udpClient;
public TunnelCompactSelfHost()
{
}
public async Task<TunnelCompactIPEndPoint> GetExternalIPAsync(IPEndPoint server)
{
udpClient = new UdpClient(AddressFamily.InterNetwork);
//udpClient.Client.IPv6Only(AddressFamily.InterNetworkV6, false);
udpClient.Client.Reuse(true);
udpClient.Client.Bind(new IPEndPoint(IPAddress.Any, new Random().Next(10000, 50000)));
UdpClient udpClient = new UdpClient(AddressFamily.InterNetwork);
udpClient.Client.Reuse();
udpClient.Client.WindowsUdpBug();
for (int i = 0; i < 10; i++)
for (int i = 0; i < 5; i++)
{
try
{
@@ -54,22 +50,6 @@ namespace cmonitor.plugins.tunnel.compact
}
}
Task.Run(async () =>
{
while (true)
{
try
{
UdpReceiveResult result = await udpClient.ReceiveAsync();
Logger.Instance.Error(Encoding.UTF8.GetString(result.Buffer));
}
catch (Exception ex)
{
Logger.Instance.Error(ex);
}
}
});
return null;
}
}

View File

@@ -41,7 +41,7 @@ namespace cmonitor.plugins.tunnel.compact
config.Save();
}
public async Task<TunnelCompactIPEndPoint> GetExternalIPAsync()
public async Task<TunnelCompactIPEndPoint> GetExternalIPAsync(IPAddress localIP)
{
for (int i = 0; i < config.Data.Client.Tunnel.Servers.Length; i++)
{
@@ -61,7 +61,11 @@ namespace cmonitor.plugins.tunnel.compact
Logger.Instance.Warning($"get domain ip time:{sw.ElapsedMilliseconds}ms");
}
TunnelCompactIPEndPoint externalIP = await compact.GetExternalIPAsync(server);
if (externalIP != null) return externalIP;
if (externalIP != null)
{
externalIP.Local.Address = localIP;
return externalIP;
}
}
catch (Exception ex)
{

View File

@@ -114,7 +114,8 @@ namespace cmonitor.plugins.tunnel.messenger
{
Connection = cache.Connection,
MessengerId = (ushort)TunnelMessengerIds.Info,
Payload = connection.ReceiveRequestWrap.Payload
Payload = connection.ReceiveRequestWrap.Payload,
Timeout = 3000,
});
if (resp.Code == MessageResponeCodes.OK && resp.Data.Span.Length > 0)
{
@@ -131,7 +132,7 @@ namespace cmonitor.plugins.tunnel.messenger
if (signCaching.Get(tunnelTransportInfo.Remote.MachineName, out SignCacheInfo cache) && signCaching.Get(connection.Name, out SignCacheInfo cache1) && cache.GroupId == cache1.GroupId)
{
await messengerSender.SendReply(new MessageRequestWrap
await messengerSender.SendOnly(new MessageRequestWrap
{
Connection = cache.Connection,
MessengerId = (ushort)TunnelMessengerIds.Begin,
@@ -204,6 +205,7 @@ namespace cmonitor.plugins.tunnel.messenger
{
Connection = item.Connection,
MessengerId = (ushort)TunnelMessengerIds.Config,
Timeout = 3000,
Payload = connection.ReceiveRequestWrap.Payload
}));
}

View File

@@ -8,7 +8,6 @@ namespace cmonitor.plugins.tunnel.transport
{
public string Name { get; }
public string Label { get; }
public bool Disabled { get; }
public TunnelProtocolType ProtocolType { get; }
/// <summary>
@@ -93,6 +92,7 @@ namespace cmonitor.plugins.tunnel.transport
public string ProtocolType { get; set; }
public bool Disabled { get; set; }
public bool Reverse { get; set; }
}
public sealed class TunnelTransportItemInfoEqualityComparer : IEqualityComparer<TunnelTransportItemInfo>
{

View File

@@ -18,9 +18,7 @@ namespace cmonitor.plugins.tunnel.transport
{
public string Name => "msquic";
public string Label => "UDP,MsQuic";
public bool Disabled => false;
public string Label => "UDP over MsQuicwin11+、linux";
public TunnelProtocolType ProtocolType => TunnelProtocolType.Quic;
@@ -30,6 +28,10 @@ namespace cmonitor.plugins.tunnel.transport
public Action<ITunnelConnection> OnConnected { get; set; } = (state) => { };
private ConcurrentDictionary<int, ListenAsyncToken> stateDic = new ConcurrentDictionary<int, ListenAsyncToken>();
private byte[] authBytes = Encoding.UTF8.GetBytes("snltty.ttl");
private byte[] endBytes = Encoding.UTF8.GetBytes("snltty.end");
private IPEndPoint quicListenEP = null;
private X509Certificate serverCertificate;
public TransportMsQuic(Config config)
@@ -44,10 +46,9 @@ namespace cmonitor.plugins.tunnel.transport
Logger.Instance.Error($"file {path} not found");
Environment.Exit(0);
}
_ = QuicStart();
}
public async Task<ITunnelConnection> ConnectAsync(TunnelTransportInfo tunnelTransportInfo)
{
if (OperatingSystem.IsWindows() || OperatingSystem.IsLinux() || OperatingSystem.IsMacOS())
@@ -78,8 +79,9 @@ namespace cmonitor.plugins.tunnel.transport
{
//反向连接
TunnelTransportInfo tunnelTransportInfo1 = tunnelTransportInfo.ToJsonFormat().DeJson<TunnelTransportInfo>();
_ = BindListen(tunnelTransportInfo1.Local.Local, quicListenEP, tunnelTransportInfo1);
await Task.Delay(50);
BindAndTTL(tunnelTransportInfo1);
_ = QuicStart(tunnelTransportInfo1.Local.Local, tunnelTransportInfo1);
if (await OnSendConnectBegin(tunnelTransportInfo1) == false)
{
return null;
@@ -101,18 +103,17 @@ namespace cmonitor.plugins.tunnel.transport
{
if (QuicListener.IsSupported == false)
{
//OnSendConnectFail(tunnelTransportInfo);
//return;
OnSendConnectFail(tunnelTransportInfo);
return;
}
}
Task.Run(async () =>
{
if (tunnelTransportInfo.Direction == TunnelDirection.Forward)
{
BindAndTTL(tunnelTransportInfo);
Logger.Instance.Error($"ttl");
_ = BindListen(tunnelTransportInfo.Local.Local, quicListenEP, tunnelTransportInfo);
await Task.Delay(50);
_ = QuicStart(tunnelTransportInfo.Local.Local, tunnelTransportInfo);
BindAndTTL(tunnelTransportInfo);
}
else
{
@@ -131,16 +132,109 @@ namespace cmonitor.plugins.tunnel.transport
});
}
private (UdpClient, UdpClient) BindListen(IPEndPoint local, TaskCompletionSource<IPEndPoint> tcs)
{
UdpClient udpClient = new UdpClient(local.AddressFamily);
udpClient.Client.ReuseBind(local);
udpClient.Client.WindowsUdpBug();
IAsyncResult result = udpClient.BeginReceive((IAsyncResult result) =>
{
try
{
IPEndPoint ep = new IPEndPoint(IPAddress.Any, 0);
byte[] bytes = udpClient.EndReceive(result, ref ep);
udpClient.Send(endBytes, ep);
tcs.SetResult(ep);
}
catch (Exception)
{
}
}, null);
UdpClient udpClient6 = new UdpClient(AddressFamily.InterNetworkV6);
udpClient6.Client.ReuseBind(new IPEndPoint(IPAddress.IPv6Any, local.Port));
udpClient6.Client.WindowsUdpBug();
IAsyncResult result6 = udpClient6.BeginReceive((IAsyncResult result) =>
{
try
{
IPEndPoint ep = new IPEndPoint(IPAddress.Any, 0);
byte[] bytes = udpClient6.EndReceive(result, ref ep);
udpClient6.Send(endBytes, ep);
tcs.SetResult(ep);
}
catch (Exception)
{
}
}, null);
return (udpClient, udpClient6);
}
private UdpClient BindListen(UdpClient remoteUdp, IPEndPoint remoteEP)
{
UdpClient localUdp = new UdpClient(new IPEndPoint(IPAddress.Any, 0));
localUdp.Client.WindowsUdpBug();
ListenAsyncToken token = new ListenAsyncToken
{
LocalUdp = remoteUdp,
Received = false,
RemoteUdp = localUdp,
};
remoteUdp.BeginReceive(ListenConnectCallback, token);
localUdp.BeginReceive(ListenConnectCallback, new ListenAsyncToken
{
LocalUdp = localUdp,
Received = false,
RemoteUdp = remoteUdp,
RemoteEP = remoteEP,
State = token
});
return localUdp;
}
private void ListenConnectCallback(IAsyncResult result)
{
ListenAsyncToken token = result.AsyncState as ListenAsyncToken;
try
{
byte[] bytes = token.LocalUdp.EndReceive(result, ref token.tempEP);
if (token.Received == false)
{
if (token.State is ListenAsyncToken targetToken)
{
targetToken.RemoteEP = token.tempEP;
}
}
token.Received = true;
token.RemoteUdp.Send(bytes, token.RemoteEP);
token.LocalUdp.BeginReceive(ListenConnectCallback, token);
}
catch (Exception)
{
try
{
token.LocalUdp.Close();
token.RemoteUdp.Close();
}
catch (Exception)
{
}
}
}
private async Task<ITunnelConnection> ConnectForward(TunnelTransportInfo tunnelTransportInfo)
{
//要连接哪些IP
IPAddress[] localIps = tunnelTransportInfo.Remote.LocalIps.Where(c => c.Equals(tunnelTransportInfo.Remote.Local.Address) == false).ToArray();
List<IPEndPoint> eps = new List<IPEndPoint>();
eps.AddRange(new List<IPEndPoint>{
new IPEndPoint(tunnelTransportInfo.Remote.Remote.Address,tunnelTransportInfo.Remote.Remote.Port),
new IPEndPoint(tunnelTransportInfo.Remote.Remote.Address,tunnelTransportInfo.Remote.Remote.Port+1),
});
//先尝试内网ipv4
foreach (IPAddress item in localIps.Where(c => c.AddressFamily == AddressFamily.InterNetwork))
{
@@ -149,7 +243,10 @@ namespace cmonitor.plugins.tunnel.transport
eps.Add(new IPEndPoint(item, tunnelTransportInfo.Remote.Remote.Port + 1));
}
//在尝试外网
eps.AddRange(new List<IPEndPoint>{
new IPEndPoint(tunnelTransportInfo.Remote.Remote.Address,tunnelTransportInfo.Remote.Remote.Port),
new IPEndPoint(tunnelTransportInfo.Remote.Remote.Address,tunnelTransportInfo.Remote.Remote.Port+1),
});
//再尝试IPV6
foreach (IPAddress item in localIps.Where(c => c.AddressFamily == AddressFamily.InterNetworkV6))
{
@@ -163,62 +260,28 @@ namespace cmonitor.plugins.tunnel.transport
Logger.Instance.Warning($"{Name} connect to {tunnelTransportInfo.Remote.MachineName} {string.Join("\r\n", eps.Select(c => c.ToString()))}");
}
//IPEndPoint local = new IPEndPoint(IPAddress.Any, tunnelTransportInfo.Local.Local.Port);
//UdpClient udpClient = new UdpClient(local);
//udpClient.Client.ReuseBind(local);
IPEndPoint local = new IPEndPoint(tunnelTransportInfo.Local.Local.Address, tunnelTransportInfo.Local.Local.Port);
TaskCompletionSource<IPEndPoint> taskCompletionSource = new TaskCompletionSource<IPEndPoint>();
//接收远端数据,收到了就是成功了
(UdpClient remoteUdp, UdpClient remoteUdp6) = BindListen(local, taskCompletionSource);
foreach (IPEndPoint ep in eps.Where(c => NetworkHelper.NotIPv6Support(c.Address) == false))
{
//QuicConnection connection = null;
try
{
if (Logger.Instance.LoggerLevel <= LoggerTypes.DEBUG)
{
Logger.Instance.Warning($"{Name} connect to {tunnelTransportInfo.Remote.MachineName} {ep}");
}
TunnelCompactSelfHost.udpClient.Send(Encoding.UTF8.GetBytes("snltty.ttl"), ep);
TunnelCompactSelfHost.udpClient.Send(Encoding.UTF8.GetBytes("snltty.end"), ep);
/*
connection = await QuicConnection.ConnectAsync(new QuicClientConnectionOptions
if (ep.AddressFamily == AddressFamily.InterNetwork)
{
RemoteEndPoint = ep,
LocalEndPoint = new IPEndPoint(ep.AddressFamily == AddressFamily.InterNetwork ? IPAddress.Any : IPAddress.IPv6Any, tunnelTransportInfo.Local.Local.Port),
DefaultCloseErrorCode = 0x0a,
DefaultStreamErrorCode = 0x0b,
IdleTimeout = TimeSpan.FromMilliseconds(15000),
ClientAuthenticationOptions = new SslClientAuthenticationOptions
{
ApplicationProtocols = new List<SslApplicationProtocol> { SslApplicationProtocol.Http3 },
EnabledSslProtocols = SslProtocols.Tls11 | SslProtocols.Tls12 | SslProtocols.Tls13,
RemoteCertificateValidationCallback = (sender, certificate, chain, errors) =>
{
return true;
}
}
}).AsTask().WaitAsync(TimeSpan.FromMilliseconds(ep.Address.Equals(tunnelTransportInfo.Remote.Remote.Address) ? 500 : 100));
QuicStream quicStream = await connection.OpenOutboundStreamAsync(QuicStreamType.Bidirectional);
return new TunnelConnectionMsQuic
remoteUdp.Send(authBytes, ep);
}
else
{
Stream = quicStream,
Connection = connection,
IPEndPoint = ep,
TransactionId = tunnelTransportInfo.TransactionId,
RemoteMachineName = tunnelTransportInfo.Remote.MachineName,
TransportName = Name,
Direction = tunnelTransportInfo.Direction,
ProtocolType = ProtocolType,
Type = TunnelType.P2P,
Mode = TunnelMode.Client,
Label = string.Empty,
};
*/
remoteUdp6.Send(authBytes, ep);
}
await Task.Delay(50);
}
catch (Exception ex)
{
@@ -226,43 +289,233 @@ namespace cmonitor.plugins.tunnel.transport
{
Logger.Instance.Error(ex.Message);
}
//Logger.Instance.Warning($"{Name} wait 1000");
//await Task.Delay(1000);
}
}
try
{
IPEndPoint remoteEP = await taskCompletionSource.Task.WaitAsync(TimeSpan.FromMilliseconds(500));
//绑定一个udp用来给QUIC链接
UdpClient localUdp = BindListen(remoteEP.AddressFamily == AddressFamily.InterNetwork ? remoteUdp : remoteUdp6, remoteEP);
QuicConnection connection = connection = await QuicConnection.ConnectAsync(new QuicClientConnectionOptions
{
RemoteEndPoint = new IPEndPoint(IPAddress.Loopback, (localUdp.Client.LocalEndPoint as IPEndPoint).Port),
LocalEndPoint = new IPEndPoint(IPAddress.Any, 0),
DefaultCloseErrorCode = 0x0a,
DefaultStreamErrorCode = 0x0b,
IdleTimeout = TimeSpan.FromMilliseconds(15000),
ClientAuthenticationOptions = new SslClientAuthenticationOptions
{
ApplicationProtocols = new List<SslApplicationProtocol> { SslApplicationProtocol.Http3 },
EnabledSslProtocols = SslProtocols.Tls11 | SslProtocols.Tls12 | SslProtocols.Tls13,
RemoteCertificateValidationCallback = (sender, certificate, chain, errors) =>
{
return true;
}
}
}).AsTask().WaitAsync(TimeSpan.FromMilliseconds(5000));
QuicStream quicStream = await connection.OpenOutboundStreamAsync(QuicStreamType.Bidirectional);
return new TunnelConnectionMsQuic
{
LocalUdp = localUdp,
remoteUdp = remoteUdp,
Stream = quicStream,
Connection = connection,
IPEndPoint = remoteEP,
TransactionId = tunnelTransportInfo.TransactionId,
RemoteMachineName = tunnelTransportInfo.Remote.MachineName,
TransportName = Name,
Direction = tunnelTransportInfo.Direction,
ProtocolType = ProtocolType,
Type = TunnelType.P2P,
Mode = TunnelMode.Client,
Label = string.Empty,
};
}
catch (Exception ex)
{
if (Logger.Instance.LoggerLevel <= LoggerTypes.DEBUG)
{
Logger.Instance.Error(ex);
}
}
try
{
remoteUdp.Close();
}
catch (Exception)
{
}
return null;
}
private async Task BindListen(IPEndPoint local, IPEndPoint targetEP, TunnelTransportInfo state)
{
UdpClient udpClient = new UdpClient(local.AddressFamily);
UdpClient udpClient6 = new UdpClient(AddressFamily.InterNetworkV6);
try
{
udpClient.Client.ReuseBind(local);
udpClient.Client.WindowsUdpBug();
ListenAsyncToken token = new ListenAsyncToken
{
Step = ListenStep.Auth,
LocalUdp = udpClient,
RemoteEP = targetEP,
Tcs = new TaskCompletionSource<bool>(),
State = state
};
udpClient.BeginReceive(ListenReceiveCallback, token);
udpClient6.Client.ReuseBind(new IPEndPoint(IPAddress.IPv6Any, local.Port));
udpClient6.Client.WindowsUdpBug();
ListenAsyncToken token6 = new ListenAsyncToken
{
Step = ListenStep.Auth,
LocalUdp = udpClient6,
RemoteEP = targetEP,
Tcs = token.Tcs,
State = state
};
udpClient6.BeginReceive(ListenReceiveCallback, token6);
bool result = await token.Tcs.Task.WaitAsync(TimeSpan.FromMilliseconds(30000));
}
catch (Exception ex)
{
udpClient.Close();
udpClient6.Close();
if (Logger.Instance.LoggerLevel <= LoggerTypes.DEBUG)
{
Logger.Instance.Error(ex);
}
}
}
private void ListenReceiveCallback(IAsyncResult result)
{
ListenAsyncToken token = result.AsyncState as ListenAsyncToken;
try
{
byte[] bytes = token.LocalUdp.EndReceive(result, ref token.tempEP);
if (token.Step == ListenStep.Auth)
{
if (bytes.Length == endBytes.Length && bytes.AsSpan().SequenceEqual(endBytes))
{
token.Step = ListenStep.Forward;
}
else
{
token.LocalUdp.Send(bytes, token.tempEP);
}
if (token.Tcs != null && token.Tcs.Task.IsCompleted == false)
{
token.Tcs.SetResult(true);
}
}
else
{
if (token.RemoteUdp == null)
{
token.RemoteUdp = new UdpClient();
token.RemoteUdp.Client.WindowsUdpBug();
}
if (token.Received == false)
{
token.RemoteUdp.Send(bytes, token.RemoteEP);
token.Received = true;
token.RealRemoteEP = token.tempEP;
stateDic.AddOrUpdate((token.RemoteUdp.Client.LocalEndPoint as IPEndPoint).Port, token, (a, b) => token);
token.RemoteUdp.BeginReceive(ListenReceiveCallback, new ListenAsyncToken
{
LocalUdp = token.RemoteUdp,
Step = ListenStep.Forward,
RemoteEP = token.tempEP,
RemoteUdp = token.LocalUdp,
RealRemoteEP = token.tempEP,
Received = true,
}) ;
}
else
{
token.RemoteUdp.Send(bytes, token.RemoteEP);
}
}
token.LocalUdp.BeginReceive(ListenReceiveCallback, token);
}
catch (Exception ex)
{
if (Logger.Instance.LoggerLevel <= LoggerTypes.DEBUG)
{
Logger.Instance.Error(ex);
}
try
{
stateDic.TryRemove((token.RemoteUdp.Client.LocalEndPoint as IPEndPoint).Port, out _);
token.LocalUdp?.Close();
token.RemoteUdp?.Close();
}
catch (Exception)
{
}
}
}
private void BindAndTTL(TunnelTransportInfo tunnelTransportInfo)
{
//给对方发送TTL消息
IPAddress[] localIps = tunnelTransportInfo.Remote.LocalIps.Where(c => c.Equals(tunnelTransportInfo.Remote.Local.Address) == false).ToArray();
List<IPEndPoint> eps = new List<IPEndPoint>();
foreach (IPAddress item in localIps)
{
eps.Add(new IPEndPoint(item, tunnelTransportInfo.Remote.Local.Port));
eps.Add(new IPEndPoint(item, tunnelTransportInfo.Remote.Remote.Port));
eps.Add(new IPEndPoint(item, tunnelTransportInfo.Remote.Remote.Port + 1));
}
eps.AddRange(new List<IPEndPoint>{
new IPEndPoint(tunnelTransportInfo.Remote.Remote.Address,tunnelTransportInfo.Remote.Remote.Port),
new IPEndPoint(tunnelTransportInfo.Remote.Remote.Address,tunnelTransportInfo.Remote.Remote.Port+1),
});
IPEndPoint local = new IPEndPoint(tunnelTransportInfo.Local.Local.Address, tunnelTransportInfo.Local.Local.Port);
foreach (var ip in eps.Where(c => NetworkHelper.NotIPv6Support(c.Address) == false))
{
try
{
if (Logger.Instance.LoggerLevel <= LoggerTypes.DEBUG)
{
Logger.Instance.Warning($"{Name} ttl to {tunnelTransportInfo.Remote.MachineName} {ip}");
}
TunnelCompactSelfHost.udpClient.Send(Encoding.UTF8.GetBytes(tunnelTransportInfo.Remote.MachineName), ip);
if (ip.AddressFamily == AddressFamily.InterNetwork)
{
Socket socket = new Socket(local.AddressFamily, SocketType.Dgram, System.Net.Sockets.ProtocolType.Udp);
socket.WindowsUdpBug();
socket.ReuseBind(local);
socket.Ttl = (short)(tunnelTransportInfo.Local.RouteLevel);
_ = socket.SendToAsync(new byte[0], SocketFlags.None, ip);
socket.SafeClose();
}
else
{
Socket socket = new Socket(ip.AddressFamily, SocketType.Dgram, System.Net.Sockets.ProtocolType.Udp);
socket.WindowsUdpBug();
socket.ReuseBind(new IPEndPoint(IPAddress.IPv6Any, local.Port));
socket.Ttl = 2;
_ = socket.SendToAsync(new byte[0], SocketFlags.None, ip);
socket.SafeClose();
}
}
catch (Exception ex)
{
if (Logger.Instance.LoggerLevel <= LoggerTypes.DEBUG)
{
Logger.Instance.Error(ex);
Logger.Instance.Error(ex.Message);
}
}
finally
@@ -308,14 +561,17 @@ namespace cmonitor.plugins.tunnel.transport
}
private async Task OnUdpConnected(TunnelTransportInfo state, QuicConnection quicConnection, QuicStream stream)
private async Task OnUdpConnected(object _state, UdpClient localUdp, UdpClient remoteUdp,IPEndPoint remoteEP, QuicConnection quicConnection, QuicStream stream)
{
TunnelTransportInfo state = _state as TunnelTransportInfo;
if (state.TransportName == Name)
{
try
{
TunnelConnectionMsQuic result = new TunnelConnectionMsQuic
{
LocalUdp = localUdp,
remoteUdp = remoteUdp,
RemoteMachineName = state.Remote.MachineName,
Direction = state.Direction,
ProtocolType = TunnelProtocolType.Quic,
@@ -325,7 +581,7 @@ namespace cmonitor.plugins.tunnel.transport
Mode = TunnelMode.Server,
TransactionId = state.TransactionId,
TransportName = state.TransportName,
IPEndPoint = quicConnection.RemoteEndPoint,
IPEndPoint = remoteEP,
Label = string.Empty,
};
if (reverseDic.TryRemove(state.Remote.MachineName, out TaskCompletionSource<ITunnelConnection> tcs))
@@ -346,17 +602,8 @@ namespace cmonitor.plugins.tunnel.transport
await Task.CompletedTask;
}
private async Task QuicStart(IPEndPoint local, TunnelTransportInfo info)
private async Task QuicStart()
{
return;
UdpClient udpClient = new UdpClient(local);
while (true)
{
UdpReceiveResult result = await udpClient.ReceiveAsync();
Console.WriteLine(Encoding.UTF8.GetString(result.Buffer));
}
return;
if (OperatingSystem.IsWindows() || OperatingSystem.IsLinux() || OperatingSystem.IsMacOS())
{
if (QuicListener.IsSupported == false) return;
@@ -365,7 +612,7 @@ namespace cmonitor.plugins.tunnel.transport
{
ApplicationProtocols = new List<SslApplicationProtocol> { SslApplicationProtocol.Http3 },
ListenBacklog = int.MaxValue,
ListenEndPoint = local,
ListenEndPoint = new IPEndPoint(IPAddress.Any, 0),
ConnectionOptionsCallback = (connection, hello, token) =>
{
return ValueTask.FromResult(new QuicServerConnectionOptions
@@ -384,22 +631,54 @@ namespace cmonitor.plugins.tunnel.transport
});
}
});
try
quicListenEP = new IPEndPoint(IPAddress.Loopback, listener.LocalEndPoint.Port);
while (true)
{
QuicConnection quicConnection = await listener.AcceptConnectionAsync().AsTask().WaitAsync(TimeSpan.FromMilliseconds(30000));
QuicStream quicStream = await quicConnection.AcceptInboundStreamAsync().AsTask().WaitAsync(TimeSpan.FromMilliseconds(2000));
await OnUdpConnected(info, quicConnection, quicStream);
}
catch (Exception ex)
{
if (Logger.Instance.LoggerLevel <= LoggerTypes.DEBUG)
try
{
Logger.Instance.Error(ex);
QuicConnection quicConnection = await listener.AcceptConnectionAsync();
QuicStream quicStream = await quicConnection.AcceptInboundStreamAsync();
if (stateDic.TryRemove(quicConnection.RemoteEndPoint.Port, out ListenAsyncToken token))
{
await OnUdpConnected(token.State, token.LocalUdp, token.RemoteUdp, token.RealRemoteEP, quicConnection, quicStream);
}
}
catch (Exception ex)
{
if (Logger.Instance.LoggerLevel <= LoggerTypes.DEBUG)
{
Logger.Instance.Error(ex);
}
}
}
await listener.DisposeAsync();
}
}
sealed class ListenAsyncToken
{
public ListenStep Step { get; set; }
public UdpClient LocalUdp { get; set; }
public IPEndPoint tempEP = new IPEndPoint(IPAddress.Any, IPEndPoint.MinPort);
public UdpClient RemoteUdp { get; set; }
public IPEndPoint RemoteEP { get; set; }
public IPEndPoint RealRemoteEP { get; set; }
public TaskCompletionSource<bool> Tcs { get; set; }
public object State { get; set; }
public bool Received { get; set; }
}
enum ListenStep : byte
{
Auth = 0,
Forward = 1
}
}
}

View File

@@ -15,7 +15,6 @@ namespace cmonitor.plugins.tunnel.transport
{
public string Name => "TcpNutssb";
public string Label => "TCP、低TTL";
public bool Disabled => true;
public TunnelProtocolType ProtocolType => TunnelProtocolType.Tcp;
private X509Certificate serverCertificate;

View File

@@ -124,18 +124,21 @@ namespace cmonitor.plugins.tuntap
/// <param name="info"></param>
public void OnUpdate(TuntapInfo info)
{
config.Data.Client.Tuntap.IP = info.IP;
config.Data.Client.Tuntap.LanIPs = info.LanIPs;
config.Save();
if (Status == TuntapStatus.Running)
Task.Run(() =>
{
Stop();
Run();
}
else
{
OnChange();
}
config.Data.Client.Tuntap.IP = info.IP;
config.Data.Client.Tuntap.LanIPs = info.LanIPs;
config.Save();
if (Status == TuntapStatus.Running)
{
Stop();
Run();
}
else
{
OnChange();
}
});
}
/// <summary>
/// 更新远程主机信息
@@ -158,13 +161,20 @@ namespace cmonitor.plugins.tuntap
{
GetRemoteInfo().ContinueWith((result) =>
{
DelRoute();
foreach (var item in result.Result)
if(result.Result == null)
{
tuntapInfos.AddOrUpdate(item.MachineName, item, (a, b) => item);
OnChange();
}
else
{
DelRoute();
foreach (var item in result.Result)
{
tuntapInfos.AddOrUpdate(item.MachineName, item, (a, b) => item);
}
Interlocked.Increment(ref infosVersion);
AddRoute();
}
Interlocked.Increment(ref infosVersion);
AddRoute();
});
}
@@ -179,7 +189,8 @@ namespace cmonitor.plugins.tuntap
{
Connection = clientSignInState.Connection,
MessengerId = (ushort)TuntapMessengerIds.ConfigForward,
Payload = MemoryPackSerializer.Serialize(info)
Payload = MemoryPackSerializer.Serialize(info),
Timeout = 3000
});
if (resp.Code != MessageResponeCodes.OK)
{

View File

@@ -117,7 +117,8 @@ namespace cmonitor.plugins.tuntap.messenger
{
Connection = item.Connection,
MessengerId = (ushort)TuntapMessengerIds.Config,
Payload = connection.ReceiveRequestWrap.Payload
Payload = connection.ReceiveRequestWrap.Payload,
Timeout = 1000,
}));
}

View File

@@ -1,5 +1,6 @@
using common.libs;
using System.Collections.Concurrent;
using System.Diagnostics;
namespace cmonitor.server
{
@@ -69,6 +70,7 @@ namespace cmonitor.server
}
byte[] bytes = msg.ToArray(out int length);
var sw = new Stopwatch();
bool res = await msg.Connection.SendAsync(bytes.AsMemory(0, length)).ConfigureAwait(false);
msg.Return(bytes);
return res;