This commit is contained in:
snltty
2024-10-31 17:45:21 +08:00
parent b66efa010f
commit 921c34af9e
43 changed files with 581 additions and 185 deletions

View File

@@ -13,9 +13,9 @@ namespace linker.gen
{
private List<GeneratorInfo> generators = new List<GeneratorInfo> {
new GeneratorInfo{ ClassName="FlowTypesLoader", ClassNameSpace="linker.plugins.flow", InterfaceName="linker.plugins.flow.IFlow" },
new GeneratorInfo{ ClassName="RelayValidatorTypeLoader", ClassNameSpace="linker.plugins.relay.validator", InterfaceName="linker.plugins.relay.validator.IRelayValidator" },
new GeneratorInfo{ ClassName="RelayTypesLoader", ClassNameSpace="linker.plugins.relay.client", InterfaceName="linker.plugins.relay.client.transport.ITransport" },
new GeneratorInfo{ ClassName="RelayValidatorTypeLoader", ClassNameSpace="linker.plugins.relay.server.validator", InterfaceName="linker.plugins.relay.server.validator.IRelayValidator" },
new GeneratorInfo{ ClassName="SignInArgsTypesLoader", ClassNameSpace="linker.plugins.signIn.args", InterfaceName="linker.plugins.signIn.args.ISignInArgs" },
new GeneratorInfo{ ClassName="RelayTypesLoader", ClassNameSpace="linker.plugins.relay", InterfaceName="linker.plugins.relay.transport.ITransport" },
new GeneratorInfo{ ClassName="ResolverTypesLoader", ClassNameSpace="linker.plugins.resolver", InterfaceName="linker.plugins.resolver.IResolver" },
new GeneratorInfo{ ClassName="TunnelExcludeIPTypesLoader", ClassNameSpace="linker.plugins.tunnel.excludeip", InterfaceName="linker.plugins.tunnel.excludeip.ITunnelExcludeIP" },
new GeneratorInfo{ ClassName="StartupTransfer", ClassNameSpace="linker.startup", InterfaceName="linker.startup.IStartup", Instance=true },

View File

@@ -8,6 +8,7 @@ using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace linker.libs
{
@@ -38,6 +39,25 @@ namespace linker.libs
}
return null;
}
public static async Task<IPAddress> GetDomainIpAsync(string domain)
{
try
{
if (string.IsNullOrWhiteSpace(domain))
{
return null;
}
if (IPAddress.TryParse(domain, out IPAddress ip))
{
return ip;
}
return (await Dns.GetHostEntryAsync(domain, AddressFamily.InterNetwork)).AddressList.FirstOrDefault();
}
catch (Exception)
{
}
return null;
}
public static IPEndPoint GetEndPoint(string host, int defaultPort)
{
try
@@ -56,6 +76,24 @@ namespace linker.libs
}
return null;
}
public static async Task<IPEndPoint> GetEndPointAsync(string host, int defaultPort)
{
try
{
string[] hostArr = host.Split(':');
int port = defaultPort;
if (hostArr.Length == 2)
{
port = int.Parse(hostArr[1]);
}
IPAddress ip = await GetDomainIpAsync(hostArr[0]);
return new IPEndPoint(ip, port);
}
catch (Exception)
{
}
return null;
}

View File

@@ -81,6 +81,7 @@ export default {
}
const id2text = {
'External':{text:'外网端口',detail:false},
'RelayReport':{text:'中继节点',detail:false},
'Relay':{text:'中继',detail:hasRelayFlow.value},
'Messenger':{text:'信标',detail:hasSigninFlow.value},
'SForward':{text:'内网穿透',detail:hasSForwardFlow.value},

View File

@@ -1,6 +1,6 @@
using linker.config;
using linker.libs.extends;
using linker.plugins.relay.validator;
using linker.plugins.relay.server.validator;
using linker.plugins.sforward.config;
using linker.plugins.sforward.validator;
using linker.plugins.signin.messenger;
@@ -158,7 +158,7 @@ namespace linker.plugins.action
this.fileConfig = fileConfig;
}
public async Task<string> Validate(linker.plugins.relay.transport.RelayInfo relayInfo, SignCacheInfo fromMachine, SignCacheInfo toMachine)
public async Task<string> Validate(linker.plugins.relay.client.transport.RelayInfo relayInfo, SignCacheInfo fromMachine, SignCacheInfo toMachine)
{
if (string.IsNullOrWhiteSpace(fileConfig.Data.Action.RelayActionUrl) == false)
{

View File

@@ -77,7 +77,7 @@ namespace linker.plugins.client
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
LoggerHelper.Instance.Info($"connect to signin server:{config.Data.Client.ServerInfo.Host}");
IPEndPoint ip = NetworkHelper.GetEndPoint(config.Data.Client.ServerInfo.Host, 1802);
IPEndPoint ip = await NetworkHelper.GetEndPointAsync(config.Data.Client.ServerInfo.Host, 1802);
if (ip == null)
{
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)

View File

@@ -48,8 +48,8 @@ namespace linker.plugins.flow
servers.TryAdd(ep.Address, onlineFlowInfo);
}
onlineFlowInfo.Time = time;
onlineFlowInfo.Online = memory.Slice(1, 4).ToInt32();
onlineFlowInfo.Total = memory.Slice(5, 4).ToInt32();
onlineFlowInfo.Online = memory.Slice(0, 4).ToInt32();
onlineFlowInfo.Total = memory.Slice(4, 4).ToInt32();
}
catch (Exception)
{

View File

@@ -2,6 +2,7 @@
using linker.plugins.flow.messenger;
using linker.plugins.messenger;
using linker.plugins.relay;
using linker.plugins.relay.server;
using linker.plugins.sforward.proxy;
using linker.plugins.tunnel;
using linker.startup;
@@ -24,11 +25,15 @@ namespace linker.plugins.flow
serviceCollection.AddSingleton<FlowTypesLoader>();
serviceCollection.AddSingleton<MessengerFlow>();
serviceCollection.AddSingleton<IMessengerResolver,MessengerResolverFlow>();
serviceCollection.AddSingleton<IMessengerSender,MessengerSenderFlow>();
serviceCollection.AddSingleton<IMessengerResolver, MessengerResolverFlow>();
serviceCollection.AddSingleton<IMessengerSender, MessengerSenderFlow>();
serviceCollection.AddSingleton<RelayFlow>();
serviceCollection.AddSingleton<RelayResolver, RelayResolverFlow>();
serviceCollection.AddSingleton<RelayReportFlow>();
serviceCollection.AddSingleton<RelayServerTransfer, RelayServerTransferFlow>();
}
public void AddServer(ServiceCollection serviceCollection, FileConfig config)

View File

@@ -1,14 +1,48 @@
using linker.libs;
using linker.plugins.relay;
using linker.config;
using linker.libs;
using linker.plugins.relay.server;
using linker.plugins.relay.server.caching;
using MemoryPack;
using System.Text.Json.Serialization;
namespace linker.plugins.flow
{
public sealed class RelayReportFlow : IFlow
{
public ulong ReceiveBytes { get; private set; }
public ulong SendtBytes { get; private set; }
public string FlowName => "RelayReport";
public RelayReportFlow()
{
}
public void AddReceive(ulong bytes) { ReceiveBytes += bytes; }
public void AddSendt(ulong bytes) { SendtBytes += bytes; }
}
public sealed class RelayServerTransferFlow : RelayServerTransfer
{
private readonly RelayReportFlow relayReportFlow;
public RelayServerTransferFlow(RelayReportFlow relayReportFlow,IRelayCaching relayCaching,FileConfig fileConfig):base(relayCaching, fileConfig)
{
this.relayReportFlow = relayReportFlow;
}
public override void AddReceive(ulong bytes) { relayReportFlow.AddReceive(bytes); }
public override void AddSendt(ulong bytes) { relayReportFlow.AddSendt(bytes); }
}
public sealed class RelayResolverFlow : RelayResolver
{
private readonly RelayFlow relayFlow;
public RelayResolverFlow(RelayFlow relayFlow)
public RelayResolverFlow(RelayFlow relayFlow, RelayServerTransfer relayServerTransfer) : base(relayServerTransfer)
{
this.relayFlow = relayFlow;
}

View File

@@ -1,5 +1,4 @@
using linker.config;
using linker.plugins.relay;
using linker.tunnel;
using linker.tunnel.connection;
using System.Collections.Concurrent;
@@ -7,6 +6,7 @@ using System.Net;
using linker.plugins.client;
using linker.plugins.tunnel;
using linker.plugins.messenger;
using linker.plugins.relay.client;
namespace linker.plugins.forward.proxy
{

View File

@@ -1,8 +1,10 @@
using linker.config;
using linker.plugins.relay.caching;
using linker.plugins.relay.client;
using linker.plugins.relay.client.transport;
using linker.plugins.relay.messenger;
using linker.plugins.relay.transport;
using linker.plugins.relay.validator;
using linker.plugins.relay.server;
using linker.plugins.relay.server.caching;
using linker.plugins.relay.server.validator;
using linker.startup;
using Microsoft.Extensions.DependencyInjection;
@@ -42,17 +44,19 @@ namespace linker.plugins.relay
serviceCollection.AddSingleton<RelayServerMessenger>();
serviceCollection.AddSingleton<RelayResolver>();
serviceCollection.AddSingleton<RelayReportResolver>();
serviceCollection.AddSingleton<RelayServerTransfer>();
serviceCollection.AddSingleton<RelayValidatorTransfer>();
serviceCollection.AddSingleton<RelayValidatorTypeLoader>();
serviceCollection.AddSingleton<RelayValidatorSecretKey>();
if (config.Data.Server.Relay.Caching.Name == "memory")
if (config.Data.Server.Relay.Distributed.Caching.Type == "memory")
{
serviceCollection.AddSingleton<IRelayCaching, RelayCachingMemory>();
}
else if (config.Data.Server.Relay.Caching.Name == "redis")
else if (config.Data.Server.Relay.Distributed.Caching.Type == "redis")
{
serviceCollection.AddSingleton<IRelayCaching, RelayCachingRedis>();
}
@@ -68,6 +72,8 @@ namespace linker.plugins.relay
{
RelayValidatorTypeLoader relayValidatorTypeLoader = serviceProvider.GetService<RelayValidatorTypeLoader>();
IRelayCaching relayCaching = serviceProvider.GetService<IRelayCaching>();
RelayReportResolver relayReportResolver = serviceProvider.GetService<RelayReportResolver>();
}
}
}

View File

@@ -2,7 +2,7 @@
using linker.plugins.config;
using MemoryPack;
namespace linker.plugins.relay
namespace linker.plugins.relay.client
{
public sealed class ConfigSyncRelaySecretKey : IConfigSync
{

View File

@@ -3,7 +3,7 @@ using linker.libs.api;
using linker.libs.extends;
using linker.plugins.capi;
namespace linker.plugins.relay
namespace linker.plugins.relay.client
{
/// <summary>
/// 中继管理接口
@@ -24,7 +24,7 @@ namespace linker.plugins.relay
/// </summary>
/// <param name="param"></param>
/// <returns></returns>
[ClientApiAccessAttribute(ClientApiAccess.Config)]
[ClientApiAccess(ClientApiAccess.Config)]
public bool SetServers(ApiControllerParamsInfo param)
{
RelayServerInfo info = param.Content.DeJson<RelayServerInfo>();

View File

@@ -1,8 +1,8 @@
using linker.config;
using linker.plugins.relay.transport;
using linker.libs;
using linker.plugins.relay.client.transport;
namespace linker.plugins.relay
namespace linker.plugins.relay.client
{
/// <summary>
/// 中继
@@ -56,6 +56,6 @@ namespace linker.plugins.relay
return true;
}, () => lastTicksManager.DiffLessEqual(3000) ? 3000 : 30000);
}
}
}

View File

@@ -1,11 +1,11 @@
using linker.config;
using linker.plugins.relay.transport;
using linker.plugins.relay.client.transport;
using linker.tunnel.connection;
using linker.libs;
using linker.libs.extends;
using System.Collections.Concurrent;
namespace linker.plugins.relay
namespace linker.plugins.relay.client
{
/// <summary>
/// 中继
@@ -136,7 +136,7 @@ namespace linker.plugins.relay
ITransport _transports = Transports.FirstOrDefault(c => c.Name == relayInfo.TransportName);
if (_transports == null) return false;
await _transports.OnBeginAsync(relayInfo, (ITunnelConnection connection) =>
await _transports.OnBeginAsync(relayInfo, (connection) =>
{
if (connection != null)
{

View File

@@ -1,7 +1,7 @@
using linker.libs;
using linker.plugins.relay.transport;
using linker.plugins.relay.client.transport;
using Microsoft.Extensions.DependencyInjection;
namespace linker.plugins.relay
namespace linker.plugins.relay.client
{
public sealed partial class RelayTypesLoader
{

View File

@@ -2,7 +2,7 @@
using MemoryPack;
using System.Net;
namespace linker.plugins.relay.transport
namespace linker.plugins.relay.client.transport
{
public enum RelayType : byte
{
@@ -98,6 +98,11 @@ namespace linker.plugins.relay.transport
/// </summary>
public ulong FlowingId { get; set; }
/// <summary>
/// 中继节点id
/// </summary>
public string NodeId { get; set; }
/// <summary>
/// 服务器a端选择用什么服务器就带给bb直接用不需要再做复杂的选择
/// </summary>

View File

@@ -12,8 +12,10 @@ using System.Security.Cryptography.X509Certificates;
using linker.plugins.messenger;
using linker.plugins.client;
using System.Diagnostics;
using System.Buffers;
using linker.plugins.relay.server;
namespace linker.plugins.relay.transport
namespace linker.plugins.relay.client.transport
{
public sealed class TransportSelfHost : ITransport
{
@@ -41,53 +43,31 @@ namespace linker.plugins.relay.transport
public async Task<ITunnelConnection> RelayAsync(RelayInfo relayInfo)
{
byte[] buffer = ArrayPool<byte>.Shared.Rent(1024);
try
{
MessageResponeInfo resp = await messengerSender.SendReply(new MessageRequestWrap
{
Connection = clientSignInState.Connection,
MessengerId = (ushort)RelayMessengerIds.RelayAsk,
Payload = MemoryPackSerializer.Serialize(relayInfo),
Timeout = 2000
}).ConfigureAwait(false);
if (resp.Code != MessageResponeCodes.OK)
//问一下能不能中继
RelayAskResultInfo relayAskResultInfo = await RelayAsk(relayInfo);
relayInfo.FlowingId = relayAskResultInfo.FlowingId;
if (relayInfo.FlowingId == 0 || relayAskResultInfo.Nodes.Count == 0)
{
return null;
}
relayInfo.FlowingId = resp.Data.Span.ToUInt64();
//RelayAskResultInfo relayAskResultInfo = MemoryPackSerializer.Deserialize<RelayAskResultInfo>(resp.Data.Span);
// relayInfo.FlowingId = relayAskResultInfo.FlowingId;
// relayInfo.Server = relayAskResultInfo.Server;
if (relayInfo.FlowingId == 0)
//连接中继节点服务器
Socket socket = await ConnectNodeServer(relayInfo, relayAskResultInfo.Nodes);
if (socket == null)
{
return null;
}
// if (relayInfo.Server == null)
{
relayInfo.Server = clientSignInState.Connection.Address;
}
//连接中继服务器
Socket socket = new Socket(relayInfo.Server.AddressFamily, SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp);
socket.KeepAlive();
await socket.ConnectAsync(relayInfo.Server).WaitAsync(TimeSpan.FromMilliseconds(500)).ConfigureAwait(false);
RelayMessage relayMessage = new RelayMessage { FlowId = relayInfo.FlowingId, Type = RelayMessengerType.Ask, FromId = relayInfo.FromMachineId, ToId = relayInfo.RemoteMachineId };
await socket.SendAsync(relayMessage.ToBytes());
//通知对方,确认中继
resp = await messengerSender.SendReply(new MessageRequestWrap
//让对方确认中继
if (await RelayConfirm(relayInfo) == false)
{
Connection = clientSignInState.Connection,
MessengerId = (ushort)RelayMessengerIds.RelayForward,
Payload = MemoryPackSerializer.Serialize(relayInfo),
});
if (resp.Code != MessageResponeCodes.OK || resp.Data.Span.SequenceEqual(Helper.TrueArray) == false)
{
socket.SafeClose();
return null;
}
//成功建立连接,
SslStream sslStream = null;
if (relayInfo.SSL)
{
@@ -122,8 +102,86 @@ namespace linker.plugins.relay.transport
LoggerHelper.Instance.Error(ex);
}
}
finally
{
ArrayPool<byte>.Shared.Return(buffer);
}
return null;
}
private async Task<RelayAskResultInfo> RelayAsk(RelayInfo relayInfo)
{
MessageResponeInfo resp = await messengerSender.SendReply(new MessageRequestWrap
{
Connection = clientSignInState.Connection,
MessengerId = (ushort)RelayMessengerIds.RelayAsk,
Payload = MemoryPackSerializer.Serialize(relayInfo),
Timeout = 2000
}).ConfigureAwait(false);
if (resp.Code != MessageResponeCodes.OK)
{
return new RelayAskResultInfo();
}
return MemoryPackSerializer.Deserialize<RelayAskResultInfo>(resp.Data.Span);
}
private async Task<bool> RelayConfirm(RelayInfo relayInfo)
{
//通知对方去确认中继
var resp = await messengerSender.SendReply(new MessageRequestWrap
{
Connection = clientSignInState.Connection,
MessengerId = (ushort)RelayMessengerIds.RelayForward,
Payload = MemoryPackSerializer.Serialize(relayInfo),
});
return resp.Code == MessageResponeCodes.OK && resp.Data.Span.SequenceEqual(Helper.TrueArray);
}
private async Task<Socket> ConnectNodeServer(RelayInfo relayInfo, List<RelayNodeReportInfo> nodes)
{
byte[] buffer = ArrayPool<byte>.Shared.Rent(1024);
try
{
foreach (var node in nodes)
{
//连接中继服务器
Socket socket = new Socket(node.EndPoint.AddressFamily, SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp);
socket.KeepAlive();
await socket.ConnectAsync(node.EndPoint).WaitAsync(TimeSpan.FromMilliseconds(500)).ConfigureAwait(false);
//是否允许连接
int length = await socket.ReceiveAsync(buffer);
if (buffer[0] != 0)
{
socket.SafeClose();
return null;
}
//建立关联
RelayMessage relayMessage = new RelayMessage { FlowId = relayInfo.FlowingId, Type = RelayMessengerType.Ask, FromId = relayInfo.FromMachineId, ToId = relayInfo.RemoteMachineId };
await socket.SendAsync(relayMessage.ToBytes());
relayInfo.Server = node.EndPoint;
relayInfo.NodeId = node.Id;
return socket;
}
}
catch (Exception ex)
{
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
{
LoggerHelper.Instance.Error(ex);
}
}
finally
{
ArrayPool<byte>.Shared.Return(buffer);
}
return null;
}
private bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
return true;
@@ -132,8 +190,8 @@ namespace linker.plugins.relay.transport
{
try
{
//if (relayInfo.Server == null)
relayInfo.Server = clientSignInState.Connection.Address;
if (relayInfo.Server == null)
relayInfo.Server = clientSignInState.Connection.Address;
Socket socket = new Socket(relayInfo.Server.AddressFamily, SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp);
socket.KeepAlive();
await socket.ConnectAsync(relayInfo.Server).WaitAsync(TimeSpan.FromMilliseconds(500)).ConfigureAwait(false);

View File

@@ -1,6 +1,7 @@
using linker.libs;
using linker.plugins.relay.transport;
using linker.plugins.relay.client.transport;
using MemoryPack;
using System.Net;
namespace linker.config
{
@@ -35,14 +36,61 @@ namespace linker.config
public string SecretKey { get; set; } = Guid.NewGuid().ToString().ToUpper();
#endif
public RelayCacheInfo Caching { get; set; } = new RelayCacheInfo { };
public DistributedInfo Distributed { get; set; } = new DistributedInfo { };
}
public sealed class RelayCacheInfo
public sealed class DistributedInfo
{
public string Name { get; set; } = "memory";
public string Type { get; set; } = "master";
public RelayCachingInfo Caching { get; set; } = new RelayCachingInfo { };
public RelayNodeInfo Node { get; set; } = new RelayNodeInfo { };
public RelayMasterInfo Master { get; set; } = new RelayMasterInfo { };
}
public sealed class RelayMasterInfo
{
#if DEBUG
public string SecretKey { get; set; } = Helper.GlobalString;
#else
public string SecretKey { get; set; } = Guid.NewGuid().ToString().ToUpper();
#endif
}
public sealed class RelayNodeInfo
{
public string Id { get; set; } = Guid.NewGuid().ToString().ToUpper();
public string Name { get; set; } = "default node";
public string Host { get; set; } = string.Empty;
public string MasterHost { get; set; } = string.Empty;
public string MasterSecretKey { get; set; } = Helper.GlobalString;
public int MaxConnection { get; set; } = 100;
public int MaxBandwidth { get; set; } = 500;
public bool Public { get; set; }
}
public sealed class RelayCachingInfo
{
public string Type { get; set; } = "memory";
public string ConnectString { get; set; } = string.Empty;
}
[MemoryPackable]
public sealed partial class RelayNodeReportInfo
{
public string Id { get; set; } = string.Empty;
public string Name { get; set; } = string.Empty;
public double ConnectionRatio { get; set; }
public double BandwidthRatio { get; set; }
public bool Public { get; set; }
[MemoryPackAllowSerialize]
public IPEndPoint EndPoint { get; set; }
}
/// <summary>
/// 中继服务器
/// </summary>

View File

@@ -1,11 +1,13 @@
using linker.config;
using linker.plugins.relay.transport;
using linker.plugins.relay.client.transport;
using linker.plugins.signin.messenger;
using linker.libs;
using MemoryPack;
using linker.plugins.messenger;
using linker.plugins.relay.validator;
using System.Net;
using linker.plugins.relay.client;
using linker.plugins.relay.server.validator;
using linker.plugins.relay.server;
namespace linker.plugins.relay.messenger
{
@@ -28,7 +30,7 @@ namespace linker.plugins.relay.messenger
[MessengerId((ushort)RelayMessengerIds.Relay)]
public async Task Relay(IConnection connection)
{
transport.RelayInfo info = MemoryPackSerializer.Deserialize<transport.RelayInfo>(connection.ReceiveRequestWrap.Payload.Span);
client.transport.RelayInfo info = MemoryPackSerializer.Deserialize<client.transport.RelayInfo>(connection.ReceiveRequestWrap.Payload.Span);
bool res = await relayTransfer.OnBeginAsync(info).ConfigureAwait(false);
connection.Write(res ? Helper.TrueArray : Helper.FalseArray);
}
@@ -43,16 +45,16 @@ namespace linker.plugins.relay.messenger
private readonly FileConfig config;
private readonly IMessengerSender messengerSender;
private readonly SignCaching signCaching;
private readonly RelayResolver relayResolver;
private readonly RelayServerTransfer relayServerTransfer;
private readonly RelayValidatorTransfer relayValidatorTransfer;
public RelayServerMessenger(FileConfig config, IMessengerSender messengerSender, SignCaching signCaching, RelayResolver relayResolver, RelayValidatorTransfer relayValidatorTransfer)
public RelayServerMessenger(FileConfig config, IMessengerSender messengerSender, SignCaching signCaching, RelayServerTransfer relayServerTransfer, RelayValidatorTransfer relayValidatorTransfer)
{
this.config = config;
this.messengerSender = messengerSender;
this.signCaching = signCaching;
this.relayResolver = relayResolver;
this.relayServerTransfer = relayServerTransfer;
this.relayValidatorTransfer = relayValidatorTransfer;
}
@@ -69,7 +71,7 @@ namespace linker.plugins.relay.messenger
connection.Write(Helper.FalseArray);
return;
}
string result = await relayValidatorTransfer.Validate(new transport.RelayInfo
string result = await relayValidatorTransfer.Validate(new client.transport.RelayInfo
{
SecretKey = info.SecretKey,
FromMachineId = info.MachineId,
@@ -79,7 +81,7 @@ namespace linker.plugins.relay.messenger
}, cache, null);
if (string.IsNullOrWhiteSpace(result) == false)
{
connection.Write(ulong.MinValue);
connection.Write(Helper.FalseArray);
return;
}
@@ -94,11 +96,10 @@ namespace linker.plugins.relay.messenger
[MessengerId((ushort)RelayMessengerIds.RelayAsk)]
public async Task RelayAsk(IConnection connection)
{
transport.RelayInfo info = MemoryPackSerializer.Deserialize<transport.RelayInfo>(connection.ReceiveRequestWrap.Payload.Span);
client.transport.RelayInfo info = MemoryPackSerializer.Deserialize<client.transport.RelayInfo>(connection.ReceiveRequestWrap.Payload.Span);
if (signCaching.TryGet(connection.Id, out SignCacheInfo cacheFrom) == false || signCaching.TryGet(info.RemoteMachineId, out SignCacheInfo cacheTo) == false || cacheFrom.GroupId != cacheTo.GroupId)
{
connection.Write(ulong.MinValue);
//connection.Write(MemoryPackSerializer.Serialize(new RelayAskResultInfo { FlowingId = ulong.MinValue, Server = null }));
connection.Write(MemoryPackSerializer.Serialize(new RelayAskResultInfo { }));
return;
}
@@ -107,17 +108,16 @@ namespace linker.plugins.relay.messenger
info.RemoteMachineName = cacheTo.MachineName;
info.FromMachineName = cacheFrom.MachineName;
string result = await relayValidatorTransfer.Validate(info, cacheFrom, cacheTo);
if (string.IsNullOrWhiteSpace(result) == false)
RelayAskResultInfo result = new RelayAskResultInfo();
string error = await relayValidatorTransfer.Validate(info, cacheFrom, cacheTo);
result.Nodes = relayServerTransfer.GetNodes(string.IsNullOrWhiteSpace(error));
if (result.Nodes.Count > 0)
{
connection.Write(ulong.MinValue);
//connection.Write(MemoryPackSerializer.Serialize(new RelayAskResultInfo { FlowingId = ulong.MinValue, Server = null }));
return;
result.FlowingId = await relayServerTransfer.AddRelay(cacheFrom.MachineId, cacheFrom.MachineName, cacheTo.MachineId, cacheTo.MachineName);
}
ulong flowingId = await relayResolver.NewRelay(cacheFrom.MachineId, cacheFrom.MachineName, cacheTo.MachineId, cacheTo.MachineName);
connection.Write(flowingId);
// connection.Write(MemoryPackSerializer.Serialize(new RelayAskResultInfo { FlowingId = flowingId, Server = null }));
connection.Write(MemoryPackSerializer.Serialize(result));
}
/// <summary>
@@ -128,31 +128,37 @@ namespace linker.plugins.relay.messenger
[MessengerId((ushort)RelayMessengerIds.RelayForward)]
public async Task RelayForward(IConnection connection)
{
transport.RelayInfo info = MemoryPackSerializer.Deserialize<transport.RelayInfo>(connection.ReceiveRequestWrap.Payload.Span);
client.transport.RelayInfo info = MemoryPackSerializer.Deserialize<client.transport.RelayInfo>(connection.ReceiveRequestWrap.Payload.Span);
if (signCaching.TryGet(info.FromMachineId, out SignCacheInfo cacheFrom) == false || signCaching.TryGet(info.RemoteMachineId, out SignCacheInfo cacheTo) == false || cacheFrom.GroupId != cacheTo.GroupId)
{
connection.Write(Helper.FalseArray);
return;
}
}
info.RemoteMachineId = cacheTo.MachineId;
info.FromMachineId = cacheFrom.MachineId;
info.RemoteMachineName = cacheTo.MachineName;
info.FromMachineName = cacheFrom.MachineName;
string result = await relayValidatorTransfer.Validate(info, cacheFrom, cacheTo);
if (string.IsNullOrWhiteSpace(result) == false)
//需要验证
if (relayServerTransfer.NodeValidate(info.NodeId))
{
connection.Write(Helper.FalseArray);
return;
info.RemoteMachineId = cacheTo.MachineId;
info.FromMachineId = cacheFrom.MachineId;
info.RemoteMachineName = cacheTo.MachineName;
info.FromMachineName = cacheFrom.MachineName;
string result = await relayValidatorTransfer.Validate(info, cacheFrom, cacheTo);
if (string.IsNullOrWhiteSpace(result) == false)
{
connection.Write(Helper.FalseArray);
return;
}
}
//本服务器,让对方按信标服务器地址连
if (string.IsNullOrWhiteSpace(info.NodeId))
{
info.Server = null;
}
info.RemoteMachineId = cacheFrom.MachineId;
info.FromMachineId = cacheTo.MachineId;
info.RemoteMachineName = cacheFrom.MachineName;
info.FromMachineName = cacheTo.MachineName;
info.Server = null;
try
{
MessageResponeInfo resp = await messengerSender.SendReply(new MessageRequestWrap
@@ -182,7 +188,7 @@ namespace linker.plugins.relay.messenger
public ulong FlowingId { get; set; }
[MemoryPackAllowSerialize]
public IPEndPoint Server { get; set; }
public List<RelayNodeReportInfo> Nodes { get; set; } = new List<RelayNodeReportInfo>();
}
}

View File

@@ -0,0 +1,34 @@
using linker.libs;
using linker.libs.extends;
using linker.plugins.resolver;
using System.Net;
using System.Net.Sockets;
namespace linker.plugins.relay.server
{
public class RelayReportResolver : IResolver
{
public ResolverType Type => ResolverType.RelayReport;
private readonly ICrypto cryptoMaster;
private readonly ICrypto cryptoNode;
private readonly RelayServerTransfer relayServerTransfer;
public RelayReportResolver(RelayServerTransfer relayServerTransfer)
{
this.relayServerTransfer = relayServerTransfer;
}
public async Task Resolve(Socket socket, Memory<byte> memory)
{
socket.SafeClose();
await Task.CompletedTask;
}
public async Task Resolve(Socket socket, IPEndPoint ep, Memory<byte> memory)
{
relayServerTransfer.SetNodeReport(ep, memory);
await Task.CompletedTask;
}
}
}

View File

@@ -4,10 +4,10 @@ using linker.libs.extends;
using System.Collections.Concurrent;
using linker.plugins.resolver;
using System.Net;
using linker.plugins.relay.caching;
using MemoryPack;
using linker.plugins.relay.server.caching;
namespace linker.plugins.relay
namespace linker.plugins.relay.server
{
/// <summary>
/// 中继连接处理
@@ -16,31 +16,13 @@ namespace linker.plugins.relay
{
public ResolverType Type => ResolverType.Relay;
private readonly IRelayCaching relayCaching;
public RelayResolver(IRelayCaching relayCaching)
private readonly RelayServerTransfer relayServerTransfer;
public RelayResolver(RelayServerTransfer relayServerTransfer)
{
this.relayCaching = relayCaching;
this.relayServerTransfer = relayServerTransfer;
}
private readonly ConcurrentDictionary<ulong, RelayWrap> relayDic = new ConcurrentDictionary<ulong, RelayWrap>();
private ulong relayFlowingId = 0;
public async Task<ulong> NewRelay(string fromid, string fromName, string toid, string toName)
{
ulong flowingId = Interlocked.Increment(ref relayFlowingId);
RelayCache cache = new RelayCache
{
FlowId = flowingId,
FromId = fromid,
FromName = fromName,
ToId = toid,
ToName = toName
};
bool added = await relayCaching.TryAdd($"{fromid}->{toid}", cache, 5000);
if (added == false) return 0;
return flowingId;
}
public virtual void AddReceive(string key, string from, string to, ulong bytes)
@@ -66,13 +48,22 @@ namespace linker.plugins.relay
byte[] buffer = ArrayPool<byte>.Shared.Rent(1024);
try
{
if (relayServerTransfer.ValidateConnection() == false)
{
await socket.SendAsync(new byte[] { 1 });
socket.SafeClose();
return;
}
await socket.SendAsync(new byte[] { 0 });
int length = await socket.ReceiveAsync(buffer.AsMemory(), SocketFlags.None).ConfigureAwait(false);
RelayMessage relayMessage = RelayMessage.FromBytes(buffer.AsMemory(0, length));
//ask 是发起端来的那key就是 发起端->目标端, answer的目标和来源会交换所以转换一下
string key = relayMessage.Type == RelayMessengerType.Ask ? $"{relayMessage.FromId}->{relayMessage.ToId}" : $"{relayMessage.ToId}->{relayMessage.FromId}";
RelayCachingValue<RelayCache> relayCacheWrap = new RelayCachingValue<RelayCache>();
if (await relayCaching.TryGetValue(key, relayCacheWrap) == false)
if (await relayServerTransfer.TryGetRelay(key, relayCacheWrap) == false)
{
socket.SafeClose();
return;
@@ -84,35 +75,35 @@ namespace linker.plugins.relay
switch (relayMessage.Type)
{
case RelayMessengerType.Ask:
{
//添加本地缓存
RelayWrap relayWrap = new RelayWrap { Socket = socket, Tcs = new TaskCompletionSource<Socket>() };
relayDic.TryAdd(relayCacheWrap.Value.FlowId, relayWrap);
//等待对方连接
Socket targetSocket = await relayWrap.Tcs.Task.WaitAsync(TimeSpan.FromMilliseconds(3000));
_ = CopyToAsync(relayCacheWrap.Value.FromId, relayCacheWrap.Value.FromName, relayCacheWrap.Value.ToName, 3, socket, targetSocket);
}
break;
case RelayMessengerType.Answer:
{
//看发起端缓存
if (relayDic.TryRemove(relayCacheWrap.Value.FlowId, out RelayWrap relayWrap) == false || relayWrap.Socket == null)
{
socket.SafeClose();
return;
}
//告诉发起端我的socket
relayWrap.Tcs.SetResult(socket);
_ = CopyToAsync(relayCacheWrap.Value.FromId, relayCacheWrap.Value.FromName, relayCacheWrap.Value.ToName, 3, socket, relayWrap.Socket);
}
break;
default:
{
socket.SafeClose();
}
break;
}
//发起端
if (relayMessage.Type == RelayMessengerType.Ask)
{
//添加本地缓存
RelayWrap relayWrap = new RelayWrap { Socket = socket, Tcs = new TaskCompletionSource<Socket>() };
relayDic.TryAdd(relayCacheWrap.Value.FlowId, relayWrap);
//等待对方连接
Socket targetSocket = await relayWrap.Tcs.Task.WaitAsync(TimeSpan.FromMilliseconds(3000));
_ = CopyToAsync(relayCacheWrap.Value.FromId, relayCacheWrap.Value.FromName, relayCacheWrap.Value.ToName, 3, socket, targetSocket);
}
else if (relayMessage.Type == RelayMessengerType.Answer)
{
//看发起端缓存
if (relayDic.TryRemove(relayCacheWrap.Value.FlowId, out RelayWrap relayWrap) == false || relayWrap.Socket == null)
{
socket.SafeClose();
return;
}
//告诉发起端我的socket
relayWrap.Tcs.SetResult(socket);
_ = CopyToAsync(relayCacheWrap.Value.FromId, relayCacheWrap.Value.FromName, relayCacheWrap.Value.ToName, 3, socket, relayWrap.Socket);
}
}
catch (Exception)
{
@@ -136,6 +127,7 @@ namespace linker.plugins.relay
byte[] buffer = new byte[(1 << bufferSize) * 1024];
try
{
relayServerTransfer.IncrementConnectionNum();
int bytesRead;
while ((bytesRead = await source.ReceiveAsync(buffer.AsMemory()).ConfigureAwait(false)) != 0)
{
@@ -147,7 +139,12 @@ namespace linker.plugins.relay
catch (Exception)
{
}
finally
{
relayServerTransfer.DecrementConnectionNum();
}
}
}
@@ -171,7 +168,6 @@ namespace linker.plugins.relay
public TaskCompletionSource<Socket> Tcs { get; set; }
public Socket Socket { get; set; }
}
public sealed class RelayMessage
{
public RelayMessengerType Type { get; set; }

View File

@@ -0,0 +1,167 @@
using linker.config;
using linker.libs;
using linker.libs.extends;
using linker.plugins.relay.server.caching;
using linker.plugins.resolver;
using MemoryPack;
using System.Collections.Concurrent;
using System.Net;
using System.Net.Sockets;
namespace linker.plugins.relay.server
{
public class RelayServerTransfer
{
private uint connectionNum = 0;
private ulong relayFlowingId = 0;
private readonly IRelayCaching relayCaching;
private readonly FileConfig fileConfig;
private readonly ICrypto cryptoMaster;
private readonly ICrypto cryptoNode;
private readonly ConcurrentDictionary<string, RelayNodeReportInfo> reports = new ConcurrentDictionary<string, RelayNodeReportInfo>();
public RelayServerTransfer(IRelayCaching relayCaching, FileConfig fileConfig)
{
this.relayCaching = relayCaching;
this.fileConfig = fileConfig;
if (fileConfig.Data.Server.Relay.Distributed.Type == "master" && string.IsNullOrWhiteSpace(fileConfig.Data.Server.Relay.Distributed.Master.SecretKey) == false)
{
cryptoMaster = CryptoFactory.CreateSymmetric(fileConfig.Data.Server.Relay.Distributed.Master.SecretKey);
}
if (fileConfig.Data.Server.Relay.Distributed.Type == "node" && string.IsNullOrWhiteSpace(fileConfig.Data.Server.Relay.Distributed.Node.MasterSecretKey) == false)
{
cryptoNode = CryptoFactory.CreateSymmetric(fileConfig.Data.Server.Relay.Distributed.Node.MasterSecretKey);
}
if (cryptoNode != null)
{
ReportTask();
}
}
public void IncrementConnectionNum()
{
Interlocked.Increment(ref connectionNum);
}
public void DecrementConnectionNum()
{
Interlocked.Decrement(ref connectionNum);
}
public bool ValidateConnection()
{
return fileConfig.Data.Server.Relay.Distributed.Type == "master"
|| (fileConfig.Data.Server.Relay.Distributed.Type == "node" && fileConfig.Data.Server.Relay.Distributed.Node.MaxConnection * 2 > connectionNum);
}
public async Task<ulong> AddRelay(string fromid, string fromName, string toid, string toName)
{
ulong flowingId = Interlocked.Increment(ref relayFlowingId);
RelayCache cache = new RelayCache
{
FlowId = flowingId,
FromId = fromid,
FromName = fromName,
ToId = toid,
ToName = toName
};
bool added = await relayCaching.TryAdd($"{fromid}->{toid}", cache, 5000);
if (added == false) return 0;
return flowingId;
}
public async ValueTask<bool> TryGetRelay(string key, RelayCachingValue<RelayCache> wrap)
{
return await relayCaching.TryGetValue(key, wrap);
}
public virtual void AddReceive(ulong bytes)
{
}
public virtual void AddSendt(ulong bytes)
{
}
public void SetNodeReport(IPEndPoint ep, Memory<byte> data)
{
AddReceive((ulong)data.Length);
if (cryptoMaster == null) return;
data = cryptoMaster.Decode(data.ToArray());
RelayNodeReportInfo relayNodeReportInfo = MemoryPackSerializer.Deserialize<RelayNodeReportInfo>(data.Span);
if (relayNodeReportInfo.EndPoint.Address.Equals(IPAddress.Any))
{
relayNodeReportInfo.EndPoint.Address = ep.Address;
}
reports.AddOrUpdate(relayNodeReportInfo.Id, relayNodeReportInfo, (a, b) => relayNodeReportInfo);
}
public List<RelayNodeReportInfo> GetNodes(bool validated)
{
List<RelayNodeReportInfo> result = reports.Values.Where(c => c.Public || (c.Public == false && validated)).ToList();
if (validated)
{
result.Add(new RelayNodeReportInfo { Id = string.Empty, Name = "server", BandwidthRatio = 1, ConnectionRatio = 1, Public = false });
}
return result.OrderBy(c => c.ConnectionRatio).ToList();
}
public bool NodeValidate(string nodeId)
{
if (string.IsNullOrWhiteSpace(nodeId)) return true;
return reports.TryGetValue(nodeId, out RelayNodeReportInfo relayNodeReportInfo) && relayNodeReportInfo.Public == false;
}
private void ReportTask()
{
TimerHelper.SetInterval(async () =>
{
try
{
IPEndPoint endPoint = await NetworkHelper.GetEndPointAsync(fileConfig.Data.Server.Relay.Distributed.Node.Host, fileConfig.Data.Server.ServicePort) ?? new IPEndPoint(IPAddress.Any, fileConfig.Data.Server.ServicePort);
double connectionRatio = fileConfig.Data.Server.Relay.Distributed.Node.MaxConnection == 0 ? 0 : connectionNum / fileConfig.Data.Server.Relay.Distributed.Node.MaxConnection;
RelayNodeReportInfo relayNodeReportInfo = new RelayNodeReportInfo
{
Id = fileConfig.Data.Server.Relay.Distributed.Node.Id,
Name = fileConfig.Data.Server.Relay.Distributed.Node.Name,
Public = fileConfig.Data.Server.Relay.Distributed.Node.Public,
BandwidthRatio = 0,
ConnectionRatio = Math.Round(connectionRatio, 2),
EndPoint = endPoint,
};
IPEndPoint ep = await NetworkHelper.GetEndPointAsync(fileConfig.Data.Server.Relay.Distributed.Node.MasterHost, 1802);
byte[] content = cryptoMaster.Encode(MemoryPackSerializer.Serialize(relayNodeReportInfo));
byte[] data = new byte[content.Length + 1];
data[0] = (byte)ResolverType.RelayReport;
content.AsMemory().CopyTo(data.AsMemory(1));
using UdpClient udpClient = new UdpClient(AddressFamily.InterNetwork);
udpClient.Client.WindowsUdpBug();
AddSendt((ulong)data.Length);
await udpClient.SendAsync(data, ep);
}
catch (Exception)
{
}
return true;
}, () => 5000);
}
}
}

View File

@@ -1,4 +1,4 @@
namespace linker.plugins.relay.caching
namespace linker.plugins.relay.server.caching
{
public interface IRelayCaching
{

View File

@@ -1,6 +1,6 @@
using MemoryPack;
using Microsoft.Extensions.Caching.Memory;
namespace linker.plugins.relay.caching
namespace linker.plugins.relay.server.caching
{
public sealed class RelayCachingMemory : IRelayCaching
{

View File

@@ -2,7 +2,7 @@
using MemoryPack;
using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Caching.StackExchangeRedis;
namespace linker.plugins.relay.caching
namespace linker.plugins.relay.server.caching
{
public sealed class RelayCachingRedis : IRelayCaching
{
@@ -13,7 +13,7 @@ namespace linker.plugins.relay.caching
{
cache = new RedisCache(new RedisCacheOptions
{
Configuration = fileConfig.Data.Server.Relay.Caching.ConnectString,
Configuration = fileConfig.Data.Server.Relay.Distributed.Caching.ConnectString,
InstanceName = "Linker"
});
}

View File

@@ -1,8 +1,8 @@
using linker.config;
using linker.plugins.signin.messenger;
using RelayInfo = linker.plugins.relay.transport.RelayInfo;
using RelayInfo = linker.plugins.relay.client.transport.RelayInfo;
namespace linker.plugins.relay.validator
namespace linker.plugins.relay.server.validator
{
public interface IRelayValidator
{
@@ -25,7 +25,7 @@ namespace linker.plugins.relay.validator
this.fileConfig = fileConfig;
}
public async Task<string> Validate(linker.plugins.relay.transport.RelayInfo relayInfo, SignCacheInfo fromMachine, SignCacheInfo toMachine)
public async Task<string> Validate(RelayInfo relayInfo, SignCacheInfo fromMachine, SignCacheInfo toMachine)
{
if (relayInfo.SecretKey != fileConfig.Data.Server.Relay.SecretKey)
{

View File

@@ -1,7 +1,7 @@
using linker.plugins.relay.transport;
using linker.plugins.relay.client.transport;
using linker.plugins.signin.messenger;
namespace linker.plugins.relay.validator
namespace linker.plugins.relay.server.validator
{
public sealed partial class RelayValidatorTransfer
{

View File

@@ -1,7 +1,7 @@
using linker.libs;
using Microsoft.Extensions.DependencyInjection;
namespace linker.plugins.relay.validator
namespace linker.plugins.relay.server.validator
{
public sealed partial class RelayValidatorTypeLoader
{

View File

@@ -10,7 +10,8 @@ namespace linker.plugins.resolver
Relay = 2,
Socks4 = 4,
Socks5 = 5,
Flow = 6
Flow = 6,
RelayReport = 7,
}
public interface IResolver
{

View File

@@ -40,7 +40,7 @@ namespace linker.plugins.resolver
if (resolvers.TryGetValue(type, out IResolver resolver))
{
await resolver.Resolve(socket, buffer.AsMemory(0, length));
await resolver.Resolve(socket, buffer.AsMemory(1, length));
}
}
catch (Exception ex)
@@ -57,7 +57,7 @@ namespace linker.plugins.resolver
{
if (resolvers.TryGetValue((ResolverType)memory.Span[0], out IResolver resolver))
{
await resolver.Resolve(socket, ep, memory);
await resolver.Resolve(socket, ep, memory.Slice(1));
}
}
}

View File

@@ -8,7 +8,6 @@ using linker.plugins.capi;
using linker.plugins.messenger;
using linker.config;
using System.Collections.Concurrent;
using linker.plugins.tuntap.client;
namespace linker.plugins.sforward
{

View File

@@ -1,5 +1,4 @@
using linker.config;
using linker.plugins.relay;
using linker.tunnel;
using linker.tunnel.connection;
using linker.libs;
@@ -13,6 +12,7 @@ using linker.plugins.client;
using linker.plugins.socks5.config;
using System.Text;
using System.Collections.Generic;
using linker.plugins.relay.client;
namespace linker.plugins.socks5
{

View File

@@ -2,7 +2,6 @@
using linker.libs;
using linker.libs.extends;
using linker.plugins.client;
using linker.plugins.relay;
using linker.plugins.resolver;
using linker.tunnel;
using linker.tunnel.connection;
@@ -14,6 +13,7 @@ using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
using linker.plugins.messenger;
using linker.plugins.tuntap.messenger;
using linker.plugins.relay.client;
namespace linker.plugins.tunnel
{

View File

@@ -1,7 +1,7 @@
using linker.client.config;
using linker.plugins.tunnel.excludeip;
namespace linker.plugins.tuntap.client
namespace linker.plugins.tuntap
{
public sealed class ExcludeIP : ITunnelExcludeIP
{

View File

@@ -12,7 +12,7 @@ using linker.plugins.tuntap.config;
using linker.client.config;
using linker.plugins.tuntap.lease;
namespace linker.plugins.tuntap.client
namespace linker.plugins.tuntap
{
public sealed class TuntapClientApiController : IApiClientController
{

View File

@@ -12,7 +12,7 @@ using linker.tun;
using linker.plugins.tuntap.lease;
using linker.plugins.decenter;
namespace linker.plugins.tuntap.client
namespace linker.plugins.tuntap
{
public sealed class TuntapConfigTransfer : IDecenter
{
@@ -92,8 +92,8 @@ namespace linker.plugins.tuntap.client
await LeaseIP();
bool needReboot = ((oldIP.Equals(runningConfig.Data.Tuntap.IP) == false || prefixLength != runningConfig.Data.Tuntap.PrefixLength) && runningConfig.Data.Tuntap.Running)
|| (runningConfig.Data.Tuntap.Running && tuntapTransfer.Status != TuntapStatus.Running);
bool needReboot = (oldIP.Equals(runningConfig.Data.Tuntap.IP) == false || prefixLength != runningConfig.Data.Tuntap.PrefixLength) && runningConfig.Data.Tuntap.Running
|| runningConfig.Data.Tuntap.Running && tuntapTransfer.Status != TuntapStatus.Running;
if (needReboot)
{
@@ -216,8 +216,8 @@ namespace linker.plugins.tuntap.client
await Task.Delay(1000);
}
bool run = ((oldIP.Equals(runningConfig.Data.Tuntap.IP) == false || prefixLength != runningConfig.Data.Tuntap.PrefixLength) && runningConfig.Data.Tuntap.Running)
|| (runningConfig.Data.Tuntap.Running && tuntapTransfer.Status != TuntapStatus.Running);
bool run = (oldIP.Equals(runningConfig.Data.Tuntap.IP) == false || prefixLength != runningConfig.Data.Tuntap.PrefixLength) && runningConfig.Data.Tuntap.Running
|| runningConfig.Data.Tuntap.Running && tuntapTransfer.Status != TuntapStatus.Running;
if (run)
{

View File

@@ -4,7 +4,7 @@ using linker.plugins.tuntap.config;
using linker.tun;
using System.Net.NetworkInformation;
namespace linker.plugins.tuntap.client
namespace linker.plugins.tuntap
{
public sealed class TuntapDeviceStatusTransfer
{

View File

@@ -6,7 +6,7 @@ using System.Net.NetworkInformation;
using System.Net;
using linker.config;
namespace linker.plugins.tuntap.client
namespace linker.plugins.tuntap
{
public sealed class TuntapPingTransfer
{

View File

@@ -1,5 +1,4 @@
using linker.config;
using linker.plugins.relay;
using linker.tunnel;
using linker.tunnel.connection;
using linker.libs;
@@ -11,8 +10,9 @@ using linker.plugins.client;
using linker.plugins.tunnel;
using System.Buffers;
using linker.client.config;
using linker.plugins.relay.client;
namespace linker.plugins.tuntap.client
namespace linker.plugins.tuntap
{
public sealed class TuntapProxy : TunnelBase, ILinkerTunDeviceCallback, ITunnelConnectionReceiveCallback
{

View File

@@ -1,5 +1,4 @@
using linker.config;
using linker.plugins.tuntap.client;
using linker.plugins.tuntap.lease;
using linker.plugins.tuntap.messenger;
using linker.startup;

View File

@@ -5,7 +5,7 @@ using linker.plugins.client;
using linker.plugins.tuntap.config;
using linker.tun;
namespace linker.plugins.tuntap.client
namespace linker.plugins.tuntap
{
public sealed class TuntapTransfer
{
@@ -33,11 +33,11 @@ namespace linker.plugins.tuntap.client
AppDomain.CurrentDomain.ProcessExit += (s, e) => linkerTunDeviceAdapter.Shutdown();
Console.CancelKeyPress += (s, e) => linkerTunDeviceAdapter.Shutdown();
}
/// <summary>
/// 运行网卡
/// </summary>
public void Setup(IPAddress ip,byte prefixLength)
public void Setup(IPAddress ip, byte prefixLength)
{
if (operatingManager.StartOperation() == false)
{

View File

@@ -2,7 +2,6 @@
using linker.libs;
using linker.plugins.messenger;
using linker.plugins.signin.messenger;
using linker.plugins.tuntap.client;
using linker.plugins.tuntap.config;
using linker.plugins.tuntap.lease;
using MemoryPack;

View File

@@ -1,5 +1,5 @@
v1.5.1
2024-10-30 18:01:05
2024-10-31 17:45:20
1. 优化点对网和网对网的局域网IP包括禁用IP和冲突检测
2. 一些UI优化
3. 新增socks5代理