This commit is contained in:
snltty
2024-07-02 16:50:59 +08:00
parent db49b61f37
commit 8b47c5533c
34 changed files with 560 additions and 237 deletions

View File

@@ -14,7 +14,7 @@ namespace linker.tunnel
{
private List<ITunnelTransport> transports;
private TunnelWanPortTransfer compactTransfer;
private ITunnelAdapter tunnelAdapter ;
private ITunnelAdapter tunnelAdapter;
private ConcurrentDictionary<string, bool> connectingDic = new ConcurrentDictionary<string, bool>();
private Dictionary<string, List<Action<ITunnelConnection>>> OnConnected { get; } = new Dictionary<string, List<Action<ITunnelConnection>>>();
@@ -42,11 +42,38 @@ namespace linker.tunnel
}
var transportItems = tunnelAdapter.GetTunnelTransports();
transportItems = transportItems.Concat(transports.Select(c => new TunnelTransportItemInfo { Label = c.Label, Name = c.Name, ProtocolType = c.ProtocolType.ToString() }))
transportItems = transportItems.Concat(transports.Select(c => new TunnelTransportItemInfo
{
Label = c.Label,
Name = c.Name,
ProtocolType = c.ProtocolType.ToString(),
Reverse = c.Reverse,
DisableReverse = c.DisableReverse,
SSL = c.SSL,
DisableSSL = c.DisableSSL
}))
.Distinct(new TunnelTransportItemInfoEqualityComparer())
.Where(c=> transports.Select(c=>c.Name).Contains(c.Name))
.Where(c => transports.Select(c => c.Name).Contains(c.Name))
.ToList();
foreach (var item in transportItems)
{
var transport = transports.FirstOrDefault(c => c.Name == item.Name);
if (transport != null)
{
item.DisableReverse = transport.DisableReverse;
item.DisableSSL = transport.DisableSSL;
if (transport.DisableReverse)
{
item.Reverse = transport.Reverse;
}
if (transport.DisableSSL)
{
item.SSL = transport.SSL;
}
}
}
tunnelAdapter.SetTunnelTransports(transportItems);
@@ -97,11 +124,22 @@ namespace linker.tunnel
}
try
{
foreach (var wanPortProtocol in tunnelAdapter.GetTunnelWanPortProtocols().Where(c => c.Disabled == false && string.IsNullOrWhiteSpace(c.Host) == false))
{
foreach (TunnelTransportItemInfo transportItem in tunnelAdapter.GetTunnelTransports().Where(c => c.Disabled == false))
{
ITunnelTransport transport = transports.FirstOrDefault(c => c.Name == transportItem.Name);
if (transport == null) continue;
//找不到这个打洞协议
if (transport == null)
{
continue;
}
//这个打洞协议不支持这个外网端口协议
if((transport.AllowWanPortProtocolType & wanPortProtocol.ProtocolType) != wanPortProtocol.ProtocolType)
{
continue;
}
TunnelTransportInfo tunnelTransportInfo = null;
//是否在失败后尝试反向连接
@@ -111,30 +149,39 @@ namespace linker.tunnel
try
{
//获取自己的外网ip
TunnelTransportWanPortInfo localInfo = await GetLocalInfo();
if (localInfo == null)
Task<TunnelTransportWanPortInfo> localInfo = GetLocalInfo(wanPortProtocol);
//获取对方的外网ip
Task<TunnelTransportWanPortInfo> remoteInfo = tunnelAdapter.GetRemoteWanPort(new TunnelWanPortProtocolInfo
{
MachineId = remoteMachineId,
ProtocolType = wanPortProtocol.ProtocolType,
Type = wanPortProtocol.Type,
});
await Task.WhenAll(localInfo, remoteInfo);
if (localInfo.Result == null)
{
LoggerHelper.Instance.Error($"tunnel {transport.Name} get local external ip fail ");
break;
}
LoggerHelper.Instance.Info($"tunnel {transport.Name} got local external ip {localInfo.ToJson()}");
//获取对方的外网ip
TunnelTransportWanPortInfo remoteInfo = await tunnelAdapter.GetRemoteWanPort(remoteMachineId);
if (remoteInfo == null)
if (remoteInfo.Result == null)
{
LoggerHelper.Instance.Error($"tunnel {transport.Name} get remote {remoteMachineId} external ip fail ");
break;
}
LoggerHelper.Instance.Info($"tunnel {transport.Name} got local external ip {localInfo.ToJson()}");
LoggerHelper.Instance.Info($"tunnel {transport.Name} got remote external ip {remoteInfo.ToJson()}");
tunnelTransportInfo = new TunnelTransportInfo
{
Direction = (TunnelDirection)i,
TransactionId = transactionId,
TransportName = transport.Name,
TransportType = transport.ProtocolType,
Local = localInfo,
Remote = remoteInfo,
Local = localInfo.Result,
Remote = remoteInfo.Result,
SSL = transportItem.SSL
};
OnConnecting(tunnelTransportInfo);
@@ -160,6 +207,7 @@ namespace linker.tunnel
}
}
}
}
catch (Exception ex)
{
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
@@ -239,18 +287,19 @@ namespace linker.tunnel
/// 获取自己的外网IP给别人调用
/// </summary>
/// <returns></returns>
public async Task<TunnelTransportWanPortInfo> GetWanPort()
public async Task<TunnelTransportWanPortInfo> GetWanPort(TunnelWanPortProtocolInfo _info)
{
return await GetLocalInfo();
TunnelWanPortInfo info = tunnelAdapter.GetTunnelWanPortProtocols().FirstOrDefault(c => c.Type == _info.Type && c.ProtocolType == _info.ProtocolType);
return await GetLocalInfo(info);
}
/// <summary>
/// 获取自己的外网IP
/// </summary>
/// <returns></returns>
private async Task<TunnelTransportWanPortInfo> GetLocalInfo()
private async Task<TunnelTransportWanPortInfo> GetLocalInfo(TunnelWanPortInfo info)
{
TunnelWanPortEndPoint ip = await compactTransfer.GetWanPortAsync(tunnelAdapter.LocalIP);
TunnelWanPortEndPoint ip = await compactTransfer.GetWanPortAsync(tunnelAdapter.LocalIP, info);
if (ip != null)
{
var config = tunnelAdapter.GetLocalConfig();

View File

@@ -21,12 +21,12 @@ namespace linker.tunnel.adapter
/// 获取外网端口协议列表
/// </summary>
/// <returns></returns>
public List<TunnelWanPortInfo> GetTunnelWanPortCompacts();
public List<TunnelWanPortInfo> GetTunnelWanPortProtocols();
/// <summary>
/// 保存外网端口协议列表
/// </summary>
/// <param name="compacts"></param>
public void SetTunnelWanPortCompacts(List<TunnelWanPortInfo> compacts);
public void SetTunnelWanPortProtocols(List<TunnelWanPortInfo> protocols);
/// <summary>
/// 获取打洞协议列表
@@ -49,7 +49,7 @@ namespace linker.tunnel.adapter
/// </summary>
/// <param name="remoteMachineId"></param>
/// <returns></returns>
public Task<TunnelTransportWanPortInfo> GetRemoteWanPort(string remoteMachineId);
public Task<TunnelTransportWanPortInfo> GetRemoteWanPort(TunnelWanPortProtocolInfo info);
/// <summary>
/// 发送开始打洞
@@ -86,4 +86,20 @@ namespace linker.tunnel.adapter
/// </summary>
public string MachineId { get; set; }
}
public sealed class TunnelWanPortProtocolInfo
{
/// <summary>
/// 类别
/// </summary>
public TunnelWanPortType Type { get; set; }
/// <summary>
/// 协议
/// </summary>
public TunnelWanPortProtocolType ProtocolType { get; set; } = TunnelWanPortProtocolType.Udp;
/// <summary>
/// 本机名
/// </summary>
public string MachineId { get; set; }
}
}

View File

@@ -1,13 +1,43 @@
using linker.tunnel.connection;
using linker.tunnel.wanport;
using System.Net;
namespace linker.tunnel.transport
{
public interface ITunnelTransport
{
/// <summary>
/// 打洞协议名
/// </summary>
public string Name { get; }
/// <summary>
/// 打洞协议说明
/// </summary>
public string Label { get; }
/// <summary>
/// 隧道协议
/// </summary>
public TunnelProtocolType ProtocolType { get; }
/// <summary>
/// 允许哪些端口协议
/// </summary>
public TunnelWanPortProtocolType AllowWanPortProtocolType { get; }
/// <summary>
/// 是否反向打洞
/// </summary>
public bool Reverse { get; }
/// <summary>
/// 是否允许修改反向打洞配置
/// </summary>
public bool DisableReverse { get; }
/// <summary>
/// 是否ssl
/// </summary>
public bool SSL { get; }
/// <summary>
/// 是否允许修改ssl配置
/// </summary>
public bool DisableSSL { get; }
/// <summary>
/// 发送连接开始信息
@@ -91,7 +121,9 @@ namespace linker.tunnel.transport
public bool Disabled { get; set; } = false;
public bool Reverse { get; set; } = true;
public bool DisableReverse { get; set; } = false;
public bool SSL { get; set; } = true;
public bool DisableSSL { get; set; } = false;
public byte BufferSize { get; set; } = 4;
}

View File

@@ -2,7 +2,6 @@
using linker.tunnel.connection;
using linker.libs;
using linker.libs.extends;
using System.Buffers;
using System.Collections.Concurrent;
using System.Net;
using System.Net.Quic;
@@ -10,6 +9,7 @@ using System.Net.Security;
using System.Net.Sockets;
using System.Security.Authentication;
using System.Text;
using linker.tunnel.wanport;
namespace linker.tunnel.transport
{
@@ -20,6 +20,15 @@ namespace linker.tunnel.transport
public string Label => "MsQuicwin10+、linux";
public TunnelProtocolType ProtocolType => TunnelProtocolType.Quic;
public TunnelWanPortProtocolType AllowWanPortProtocolType => TunnelWanPortProtocolType.Udp;
public bool Reverse => true;
public bool DisableReverse => false;
public bool SSL => true;
public bool DisableSSL => true;
public Func<TunnelTransportInfo, Task<bool>> OnSendConnectBegin { get; set; } = async (info) => { return await Task.FromResult<bool>(false); };
public Func<TunnelTransportInfo, Task> OnSendConnectFail { get; set; } = async (info) => { await Task.CompletedTask; };
@@ -27,6 +36,7 @@ namespace linker.tunnel.transport
public Action<ITunnelConnection> OnConnected { get; set; } = (state) => { };
private ConcurrentDictionary<int, ListenAsyncToken> stateDic = new ConcurrentDictionary<int, ListenAsyncToken>();
private byte[] authBytes = Encoding.UTF8.GetBytes($"{Helper.GlobalString}.ttl");
private byte[] endBytes = Encoding.UTF8.GetBytes($"{Helper.GlobalString}.end");

View File

@@ -8,6 +8,7 @@ using System.Net.Security;
using System.Net.Sockets;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
using linker.tunnel.wanport;
namespace linker.tunnel.transport
{
@@ -16,6 +17,15 @@ namespace linker.tunnel.transport
public string Name => "TcpNutssb";
public string Label => "TCP、低TTL";
public TunnelProtocolType ProtocolType => TunnelProtocolType.Tcp;
public TunnelWanPortProtocolType AllowWanPortProtocolType => TunnelWanPortProtocolType.Udp;
public bool Reverse => true;
public bool DisableReverse => false;
public bool SSL => true;
public bool DisableSSL => false;
/// <summary>
/// 发送开始连接消息

View File

@@ -8,6 +8,7 @@ using System.Net.Sockets;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using linker.tunnel.wanport;
namespace linker.tunnel.transport
{
@@ -16,6 +17,14 @@ namespace linker.tunnel.transport
public string Name => "TcpP2PNAT";
public string Label => "TCP、同时打开";
public TunnelProtocolType ProtocolType => TunnelProtocolType.Tcp;
public TunnelWanPortProtocolType AllowWanPortProtocolType => TunnelWanPortProtocolType.Tcp;
public bool Reverse => false;
public bool DisableReverse => true;
public bool SSL => true;
public bool DisableSSL => false;
/// <summary>
/// 发送开始连接消息
@@ -56,6 +65,7 @@ namespace linker.tunnel.transport
{
return null;
}
await Task.Delay(50);
ITunnelConnection connection = await ConnectForward(tunnelTransportInfo, TunnelMode.Client);
if (connection != null)
{
@@ -110,7 +120,7 @@ namespace linker.tunnel.transport
try
{
targetSocket.KeepAlive();
targetSocket.ReuseBind(new IPEndPoint(IPAddress.Any, tunnelTransportInfo.Local.Local.Port));
targetSocket.ReuseBind(new IPEndPoint(tunnelTransportInfo.Local.Local.Address, tunnelTransportInfo.Local.Local.Port));
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
{
@@ -137,6 +147,12 @@ namespace linker.tunnel.transport
private async Task<ITunnelConnection> TcpClient(TunnelTransportInfo state, Socket socket)
{
//随便发个消息看对方有没有收到
await socket.SendAsync(authBytes);
//如果对方收到,会回个消息,不管是啥,回了就行
int length = await socket.ReceiveAsync(new byte[1024]);
if (length == 0) return null;
//需要ssl
SslStream sslStream = null;
if (state.SSL)
@@ -167,6 +183,15 @@ namespace linker.tunnel.transport
{
try
{
//对方会随便发个消息,不管是啥
int length = await socket.ReceiveAsync(new byte[1024]);
if (length == 0)
{
return null;
}
//回个消息给它就完了
await socket.SendAsync(endBytes);
socket.KeepAlive();
SslStream sslStream = null;
if (state.SSL)

View File

@@ -5,6 +5,7 @@ using System.Collections.Concurrent;
using System.Net;
using System.Net.Sockets;
using System.Text;
using linker.tunnel.wanport;
namespace linker.tunnel.transport
{
@@ -15,6 +16,15 @@ namespace linker.tunnel.transport
public string Label => "udp";
public TunnelProtocolType ProtocolType => TunnelProtocolType.Udp;
public TunnelWanPortProtocolType AllowWanPortProtocolType => TunnelWanPortProtocolType.Udp;
public bool Reverse => true;
public bool DisableReverse => false;
public bool SSL => true;
public bool DisableSSL => false;
public Func<TunnelTransportInfo, Task<bool>> OnSendConnectBegin { get; set; } = async (info) => { return await Task.FromResult<bool>(false); };
public Func<TunnelTransportInfo, Task> OnSendConnectFail { get; set; } = async (info) => { await Task.CompletedTask; };
@@ -22,6 +32,7 @@ namespace linker.tunnel.transport
public Action<ITunnelConnection> OnConnected { get; set; } = (state) => { };
private byte[] authBytes = Encoding.UTF8.GetBytes($"{Helper.GlobalString}.ttl");
private byte[] endBytes = Encoding.UTF8.GetBytes($"{Helper.GlobalString}.end");

View File

@@ -5,10 +5,11 @@ namespace linker.tunnel.wanport
/// <summary>
/// 外网端口协议
/// </summary>
public interface ITunnelWanPort
public interface ITunnelWanPortProtocol
{
public string Name { get; }
public TunnelWanPortType Type { get; }
public TunnelWanPortProtocolType ProtocolType { get; }
/// <summary>
/// 获取外网端口
/// </summary>
@@ -39,6 +40,7 @@ namespace linker.tunnel.wanport
/// 协议类别
/// </summary>
public TunnelWanPortType Type { get; set; }
public TunnelWanPortProtocolType ProtocolType { get; set; } = TunnelWanPortProtocolType.Udp;
/// <summary>
/// 地址
/// </summary>
@@ -55,6 +57,13 @@ namespace linker.tunnel.wanport
Stun = 1
}
[Flags]
public enum TunnelWanPortProtocolType : byte
{
Tcp = 1,
Udp = 2,
}
public sealed class TunnelWanPortTypeInfo
{
public TunnelWanPortType Value { get; set; }

View File

@@ -1,54 +0,0 @@
using linker.libs.extends;
using System.Net;
using System.Net.Sockets;
namespace linker.tunnel.wanport
{
public sealed class TunnelWanPortLinker : ITunnelWanPort
{
public string Name => "默认";
public TunnelWanPortType Type => TunnelWanPortType.Linker;
public TunnelWanPortLinker()
{
}
public async Task<TunnelWanPortEndPoint> GetAsync(IPEndPoint server)
{
UdpClient udpClient = new UdpClient(AddressFamily.InterNetwork);
udpClient.Client.Reuse();
udpClient.Client.WindowsUdpBug();
for (int i = 0; i < 5; i++)
{
try
{
await udpClient.SendAsync(new byte[1] { 0 }, server);
UdpReceiveResult result = await udpClient.ReceiveAsync().WaitAsync(TimeSpan.FromMilliseconds(500));
if (result.Buffer.Length == 0)
{
return null;
}
for (int j = 0; j < result.Buffer.Length; j++)
{
result.Buffer[j] = (byte)(result.Buffer[j] ^ byte.MaxValue);
}
AddressFamily addressFamily = (AddressFamily)result.Buffer[0];
int length = addressFamily == AddressFamily.InterNetwork ? 4 : 16;
IPAddress ip = new IPAddress(result.Buffer.AsSpan(1, length));
ushort port = result.Buffer.AsMemory(1 + length).ToUInt16();
IPEndPoint remoteEP = new IPEndPoint(ip, port);
return new TunnelWanPortEndPoint { Local = udpClient.Client.LocalEndPoint as IPEndPoint, Remote = remoteEP };
}
catch (Exception)
{
}
}
return null;
}
}
}

View File

@@ -0,0 +1,109 @@
using linker.libs.extends;
using System.Buffers;
using System.Net;
using System.Net.Sockets;
namespace linker.tunnel.wanport
{
public sealed class TunnelWanPortProtocolLinkerUdp : ITunnelWanPortProtocol
{
public string Name => "Linker Udp";
public TunnelWanPortType Type => TunnelWanPortType.Linker;
public TunnelWanPortProtocolType ProtocolType => TunnelWanPortProtocolType.Udp;
public TunnelWanPortProtocolLinkerUdp()
{
}
public async Task<TunnelWanPortEndPoint> GetAsync(IPEndPoint server)
{
UdpClient udpClient = new UdpClient(AddressFamily.InterNetwork);
udpClient.Client.Reuse();
udpClient.Client.WindowsUdpBug();
for (int i = 0; i < 5; i++)
{
try
{
await udpClient.SendAsync(new byte[1] { 0 }, server);
UdpReceiveResult result = await udpClient.ReceiveAsync().WaitAsync(TimeSpan.FromMilliseconds(500));
if (result.Buffer.Length == 0)
{
return null;
}
for (int j = 0; j < result.Buffer.Length; j++)
{
result.Buffer[j] = (byte)(result.Buffer[j] ^ byte.MaxValue);
}
AddressFamily addressFamily = (AddressFamily)result.Buffer[0];
int length = addressFamily == AddressFamily.InterNetwork ? 4 : 16;
IPAddress ip = new IPAddress(result.Buffer.AsSpan(1, length));
ushort port = result.Buffer.AsMemory(1 + length).ToUInt16();
IPEndPoint remoteEP = new IPEndPoint(ip, port);
return new TunnelWanPortEndPoint { Local = udpClient.Client.LocalEndPoint as IPEndPoint, Remote = remoteEP };
}
catch (Exception)
{
}
}
return null;
}
}
public sealed class TunnelWanPortProtocolLinkerTcp : ITunnelWanPortProtocol
{
public string Name => "Linker Tcp";
public TunnelWanPortType Type => TunnelWanPortType.Linker;
public TunnelWanPortProtocolType ProtocolType => TunnelWanPortProtocolType.Tcp;
public TunnelWanPortProtocolLinkerTcp()
{
}
public async Task<TunnelWanPortEndPoint> GetAsync(IPEndPoint server)
{
byte[] buffer = ArrayPool<byte>.Shared.Rent(20);
try
{
Socket socket = new Socket(server.AddressFamily, SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp);
await socket.ConnectAsync(server);
await socket.SendAsync(new byte[] { 0 });
int length = await socket.ReceiveAsync(buffer.AsMemory(), SocketFlags.None);
for (int j = 0; j < length; j++)
{
buffer[j] = (byte)(buffer[j] ^ byte.MaxValue);
}
AddressFamily addressFamily = (AddressFamily)buffer[0];
int iplength = addressFamily == AddressFamily.InterNetwork ? 4 : 16;
IPAddress ip = new IPAddress(buffer.AsSpan(1, iplength));
ushort port = buffer.AsMemory(1 + iplength).ToUInt16();
IPEndPoint remoteEP = new IPEndPoint(ip, port);
IPEndPoint localEP = socket.LocalEndPoint as IPEndPoint;
socket.Close();
return new TunnelWanPortEndPoint { Local = localEP, Remote = remoteEP };
}
catch (Exception)
{
}
finally
{
ArrayPool<byte>.Shared.Return(buffer);
}
return null;
}
}
}

View File

@@ -5,12 +5,14 @@ using System.Net.Sockets;
namespace linker.tunnel.wanport
{
public sealed class TunnelWanPortStun : ITunnelWanPort
public sealed class TunnelWanPortProtocolStun : ITunnelWanPortProtocol
{
public string Name => "Stun";
public string Name => "Stun Udp";
public TunnelWanPortType Type => TunnelWanPortType.Stun;
public TunnelWanPortStun()
public TunnelWanPortProtocolType ProtocolType => TunnelWanPortProtocolType.Udp;
public TunnelWanPortProtocolStun()
{
}

View File

@@ -1,5 +1,4 @@
using linker.tunnel.adapter;
using linker.libs;
using linker.libs;
using System.Diagnostics;
using System.Net;
@@ -10,8 +9,7 @@ namespace linker.tunnel.wanport
/// </summary>
public sealed class TunnelWanPortTransfer
{
private List<ITunnelWanPort> tunnelWanPorts;
private ITunnelAdapter tunnelAdapter;
private List<ITunnelWanPortProtocol> tunnelWanPorts;
public TunnelWanPortTransfer()
{
@@ -21,10 +19,8 @@ namespace linker.tunnel.wanport
/// 加载所有外网端口协议
/// </summary>
/// <param name="assembs"></param>
public void Init(ITunnelAdapter tunnelAdapter, List<ITunnelWanPort> tunnelWanPorts)
public void Init(List<ITunnelWanPortProtocol> tunnelWanPorts)
{
this.tunnelAdapter = tunnelAdapter;
this.tunnelWanPorts = tunnelWanPorts;
LoggerHelper.Instance.Warning($"load tunnel wanport compacts:{string.Join(",", tunnelWanPorts.Select(c => c.Name))}");
}
@@ -39,20 +35,15 @@ namespace linker.tunnel.wanport
/// </summary>
/// <param name="localIP">你的局域网IP</param>
/// <returns></returns>
public async Task<TunnelWanPortEndPoint> GetWanPortAsync(IPAddress localIP)
public async Task<TunnelWanPortEndPoint> GetWanPortAsync(IPAddress localIP, TunnelWanPortInfo info)
{
var tunnelWanPortItems = tunnelAdapter.GetTunnelWanPortCompacts();
foreach (TunnelWanPortInfo item in tunnelWanPortItems)
{
if (item.Disabled || string.IsNullOrWhiteSpace(item.Host)) continue;
ITunnelWanPort tunnelWanPort = tunnelWanPorts.FirstOrDefault(c => c.Type == item.Type);
if (tunnelWanPort == null) continue;
if (info == null) return null;
var tunnelWanPort = tunnelWanPorts.FirstOrDefault(c => c.Type == info.Type && c.ProtocolType == info.ProtocolType);
try
{
Stopwatch sw = new Stopwatch();
sw.Start();
IPEndPoint server = NetworkHelper.GetEndPoint(item.Host, 3478);
IPEndPoint server = NetworkHelper.GetEndPoint(info.Host, 3478);
sw.Stop();
if (sw.ElapsedMilliseconds > 1000)
{
@@ -69,7 +60,6 @@ namespace linker.tunnel.wanport
{
LoggerHelper.Instance.Error(ex);
}
}
return null;
}
}

View File

@@ -8,7 +8,7 @@
<el-table :data="state.data" size="small" border height="500" @cell-dblclick="handleCellClick">
<el-table-column property="Name" label="名称">
<template #default="scope">
<template v-if="scope.row.NameEditing">
<template v-if="scope.row.NameEditing && scope.row.Started==false">
<el-input autofocus size="small" v-model="scope.row.Name"
@blur="handleEditBlur(scope.row, 'Name')"></el-input>
</template>
@@ -26,14 +26,14 @@
</el-table-column>
<el-table-column property="BindIPAddress" label="监听IP" width="140">
<template #default="scope">
<el-select v-model="scope.row.BindIPAddress" size="small">
<el-select v-model="scope.row.BindIPAddress" size="small" :disabled="scope.row.Started">
<el-option v-for="item in state.ips" :key="item" :label="item" :value="item"/>
</el-select>
</template>
</el-table-column>
<el-table-column property="Port" label="监听端口" width="80">
<template #default="scope">
<template v-if="scope.row.PortEditing">
<template v-if="scope.row.PortEditing && scope.row.Started==false">
<el-input type="number" autofocus size="small" v-model="scope.row.Port"
@blur="handleEditBlur(scope.row, 'Port')"></el-input>
</template>
@@ -56,7 +56,7 @@
</el-table-column>
<el-table-column property="TargetEP" label="目标服务" width="140">
<template #default="scope">
<template v-if="scope.row.TargetEPEditing">
<template v-if="scope.row.TargetEPEditing && scope.row.Started==false">
<el-input autofocus size="small" v-model="scope.row.TargetEP"
@blur="handleEditBlur(scope.row, 'TargetEP')"></el-input>
</template>
@@ -173,6 +173,10 @@ export default {
saveRow({ ID: 0, Name: '', Port: 0, TargetEP: '127.0.0.1:80', machineId: state.machineId });
}
const handleEdit = (row, p) => {
if(row.Started){
ElMessage.error('请先停止');
return;
}
state.data.forEach(c => {
c[`NameEditing`] = false;
c[`PortEditing`] = false;
@@ -182,6 +186,10 @@ export default {
row[`${p}Editing`] = true;
}
const handleEditBlur = (row, p) => {
if(row.Started){
ElMessage.error('请先停止');
return;
}
row[`${p}Editing`] = false;
saveRow(row);
}

View File

@@ -8,7 +8,7 @@
<el-table :data="state.data" size="small" border height="500" @cell-dblclick="handleCellClick">
<el-table-column property="Name" label="名称">
<template #default="scope">
<template v-if="scope.row.NameEditing">
<template v-if="scope.row.NameEditing && scope.row.Started==false ">
<el-input autofocus size="small" v-model="scope.row.Name"
@blur="handleEditBlur(scope.row, 'Name')"></el-input>
</template>
@@ -24,7 +24,7 @@
</el-table-column>
<el-table-column property="Temp" label="远程端口/域名" width="160">
<template #default="scope">
<template v-if="scope.row.TempEditing">
<template v-if="scope.row.TempEditing && scope.row.Started==false">
<el-input autofocus size="small" v-model="scope.row.Temp"
@blur="handleEditBlur(scope.row, 'Temp')"></el-input>
</template>
@@ -45,7 +45,7 @@
</el-table-column>
<el-table-column property="LocalEP" label="本机服务" width="140">
<template #default="scope">
<template v-if="scope.row.LocalEPEditing">
<template v-if="scope.row.LocalEPEditing && scope.row.Started==false">
<el-input autofocus size="small" v-model="scope.row.LocalEP"
@blur="handleEditBlur(scope.row, 'LocalEP')"></el-input>
</template>
@@ -152,6 +152,10 @@ export default {
});
}
const handleEdit = (row, p) => {
if(row.Started){
ElMessage.error('请先停止运行');
return;
}
state.data.forEach(c => {
c[`NameEditing`] = false;
c[`RemotePortEditing`] = false;
@@ -162,6 +166,10 @@ export default {
row[`${p}Editing`] = true;
}
const handleEditBlur = (row, p) => {
if(row.Started){
ElMessage.error('请先停止运行');
return;
}
row[`${p}Editing`] = false;
saveRow(row);
}

View File

@@ -17,9 +17,9 @@
</template>
</template>
</el-table-column>
<el-table-column prop="Type" label="类别" width="80">
<el-table-column prop="RelayType" label="类别" width="80">
<template #default="scope">
<el-select v-model="scope.row.Type" placeholder="Select" size="small" @change="handleEditBlur(scope.row, 'Type')">
<el-select v-model="scope.row.RelayType" placeholder="Select" size="small" @change="handleEditBlur(scope.row, 'RelayType')">
<el-option v-for="item in state.types" :key="item.Value" :label="item.Name" :value="item.Value"/>
</el-select>
</template>
@@ -109,7 +109,7 @@ export default {
const handleEdit = (row, p) => {
state.list.forEach(c => {
c[`NameEditing`] = false;
c[`TypeEditing`] = false;
c[`RelayTypeEditing`] = false;
c[`HostEditing`] = false;
c[`SecretKeyEditing`] = false;
})
@@ -128,7 +128,7 @@ export default {
if(state.list.filter(c=>c.Host == '' || c.Name == '').length > 0){
return;
}
state.list.splice(index+1,0,{Name:'',Host:'',Type:0,SecretKey:'snltty',Disabled:false});
state.list.splice(index+1,0,{Name:'',Host:'',RelayType:0,SecretKey:'snltty',Disabled:false});
handleSave();
}

View File

@@ -18,12 +18,12 @@
</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="否" />
<el-switch :disabled="scope.row.DisableReverse" v-model="scope.row.Reverse" @change="handleSave" inline-prompt active-text="是" inactive-text="否" />
</template>
</el-table-column>
<el-table-column property="SSL" label="SSL" width="60">
<template #default="scope">
<el-switch v-model="scope.row.SSL" @change="handleSave" inline-prompt active-text="是" inactive-text="否" />
<el-switch :disabled="scope.row.DisableSSL" v-model="scope.row.SSL" @change="handleSave" inline-prompt active-text="是" inactive-text="否" />
</template>
</el-table-column>
<el-table-column property="Disabled" label="禁用" width="60">

View File

@@ -3,7 +3,7 @@
<div class="pdr-10 pdb-6 flex-1">
<el-checkbox v-model="state.sync" label="将更改同步到所有客户端" />
</div>
<div>将按顺序获取IP直到其中一个成功获取连接不同地域的服务器可能会走不同线路</div>
<div>将按顺序获取IP进行尝试打洞</div>
</div>
<el-table :data="state.list" border size="small" width="100%" :height="`${state.height}px`" @cell-dblclick="handleCellClick">
<el-table-column prop="Name" label="名称">
@@ -17,6 +17,16 @@
</template>
</template>
</el-table-column>
<el-table-column prop="ProtocolType" label="协议" width="100">
<template #default="scope">
<div>
<el-select v-model="scope.row.ProtocolType" placeholder="Select" size="small" @change="handleEditBlur(scope.row, 'ProtocolType')">
<el-option v-for="(item,index) in state.protocolTypes" :key="+index" :label="item" :value="+index"/>
</el-select>
</div>
</template>
</el-table-column>
<el-table-column prop="Type" label="类别" width="100">
<template #default="scope">
<el-select v-model="scope.row.Type" placeholder="Select" size="small" @change="handleEditBlur(scope.row, 'Type')">
@@ -81,7 +91,8 @@ export default {
list:((globalData.value.config.Running.Tunnel || {Servers:[]}).Servers || []).sort((a,b)=>a.Disabled - b.Disabled),
types:[],
height: computed(()=>globalData.value.height-130),
sync:true
sync:true,
protocolTypes:{1:'tcp',2:'udp'},
});
const _getTunnelTypes = ()=>{
@@ -98,6 +109,7 @@ export default {
c[`NameEditing`] = false;
c[`TypeEditing`] = false;
c[`HostEditing`] = false;
c[`ProtocolTypeEditing`] = false;
})
row[`${p}Editing`] = true;
}
@@ -114,7 +126,7 @@ export default {
if(state.list.filter(c=>c.Host == '' || c.Name == '').length > 0){
return;
}
state.list.splice(index+1,0,{Name:'',Host:'',Type:0,Disabled:false});
state.list.splice(index+1,0,{Name:'',Host:'',Type:0,Disabled:false,ProtocolType:2});
handleSave();
}

View File

@@ -10,10 +10,6 @@ https://go.microsoft.com/fwlink/?LinkID=208121.
<PublishProtocol>FileSystem</PublishProtocol>
<_TargetId>Folder</_TargetId>
<TargetFramework>net8.0</TargetFramework>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<SelfContained>true</SelfContained>
<PublishSingleFile>true</PublishSingleFile>
<PublishTrimmed>true</PublishTrimmed>
<PublishReadyToRun>false</PublishReadyToRun>
<SelfContained>false</SelfContained>
</PropertyGroup>
</Project>

View File

@@ -4,7 +4,7 @@ https://go.microsoft.com/fwlink/?LinkID=208121.
-->
<Project>
<PropertyGroup>
<History>True|2024-06-02T07:39:16.1880914Z;True|2024-06-02T15:38:26.4314913+08:00;True|2024-06-02T15:27:20.2651650+08:00;True|2024-06-02T15:26:34.3414728+08:00;True|2024-06-02T15:22:33.1407820+08:00;True|2024-06-02T15:22:01.4381533+08:00;True|2024-06-02T15:20:29.6692030+08:00;True|2024-06-02T15:19:55.9152032+08:00;True|2024-06-02T15:16:15.2278365+08:00;True|2024-04-23T09:09:03.5136215+08:00;True|2024-04-22T12:57:38.4988098+08:00;True|2023-12-23T09:50:45.7841097+08:00;True|2023-11-17T09:24:26.3650754+08:00;True|2023-11-17T09:11:28.0867966+08:00;True|2023-11-17T09:09:49.7366925+08:00;False|2023-11-17T09:08:56.6254247+08:00;False|2023-11-17T09:08:45.4560896+08:00;True|2023-11-16T11:49:56.3722044+08:00;True|2023-11-16T11:48:06.3192199+08:00;True|2023-11-16T11:47:35.3708397+08:00;True|2023-11-16T11:45:11.0208634+08:00;False|2023-11-16T11:44:01.7611210+08:00;True|2023-10-01T17:27:31.0065885+08:00;True|2023-09-04T18:19:54.7492652+08:00;True|2023-09-04T18:19:32.2969345+08:00;False|2023-09-04T18:18:51.7827366+08:00;True|2023-09-04T18:15:31.6783417+08:00;True|2023-09-04T18:14:40.9964104+08:00;</History>
<History>True|2024-07-01T09:25:46.1203574Z;True|2024-06-02T15:39:16.1880914+08:00;True|2024-06-02T15:38:26.4314913+08:00;True|2024-06-02T15:27:20.2651650+08:00;True|2024-06-02T15:26:34.3414728+08:00;True|2024-06-02T15:22:33.1407820+08:00;True|2024-06-02T15:22:01.4381533+08:00;True|2024-06-02T15:20:29.6692030+08:00;True|2024-06-02T15:19:55.9152032+08:00;True|2024-06-02T15:16:15.2278365+08:00;True|2024-04-23T09:09:03.5136215+08:00;True|2024-04-22T12:57:38.4988098+08:00;True|2023-12-23T09:50:45.7841097+08:00;True|2023-11-17T09:24:26.3650754+08:00;True|2023-11-17T09:11:28.0867966+08:00;True|2023-11-17T09:09:49.7366925+08:00;False|2023-11-17T09:08:56.6254247+08:00;False|2023-11-17T09:08:45.4560896+08:00;True|2023-11-16T11:49:56.3722044+08:00;True|2023-11-16T11:48:06.3192199+08:00;True|2023-11-16T11:47:35.3708397+08:00;True|2023-11-16T11:45:11.0208634+08:00;False|2023-11-16T11:44:01.7611210+08:00;True|2023-10-01T17:27:31.0065885+08:00;True|2023-09-04T18:19:54.7492652+08:00;True|2023-09-04T18:19:32.2969345+08:00;False|2023-09-04T18:18:51.7827366+08:00;True|2023-09-04T18:15:31.6783417+08:00;True|2023-09-04T18:14:40.9964104+08:00;</History>
<LastFailureDetails />
</PropertyGroup>
</Project>

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<_LastSelectedProfileId>C:\Users\snltty\Desktop\cmonitor\cmonitor\Properties\PublishProfiles\FolderProfile.pubxml</_LastSelectedProfileId>
<_LastSelectedProfileId>C:\Users\snltty\Desktop\linker\linker\Properties\PublishProfiles\FolderProfile.pubxml</_LastSelectedProfileId>
<ActiveDebugProfile>cmonitor</ActiveDebugProfile>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">

View File

@@ -31,7 +31,7 @@ namespace linker.plugins.relay
/// </summary>
/// <param name="param"></param>
/// <returns></returns>
public List<RelayCompactTypeInfo> GetTypes(ApiControllerParamsInfo param)
public List<RelayTypeInfo> GetTypes(ApiControllerParamsInfo param)
{
return relayTransfer.GetTypes();
}
@@ -64,7 +64,7 @@ namespace linker.plugins.relay
public sealed class RelayCompactParamInfo
{
public bool Sync { get; set; }
public RelayCompactInfo[] List { get; set; } = Array.Empty<RelayCompactInfo>();
public RelayServerInfo[] List { get; set; } = Array.Empty<RelayServerInfo>();
}
}

View File

@@ -31,11 +31,11 @@ namespace linker.plugins.relay
if (running.Data.Relay.Servers.Length == 0)
{
running.Data.Relay.Servers = new RelayCompactInfo[]
running.Data.Relay.Servers = new RelayServerInfo[]
{
new RelayCompactInfo{
new RelayServerInfo{
Name="默认",
Type= RelayCompactType.linker,
RelayType= RelayType.Linker,
Disabled = false,
Host = running.Data.Client.Servers.FirstOrDefault().Host
}
@@ -58,15 +58,15 @@ namespace linker.plugins.relay
/// 获取所有中继协议
/// </summary>
/// <returns></returns>
public List<RelayCompactTypeInfo> GetTypes()
public List<RelayTypeInfo> GetTypes()
{
return transports.Select(c => new RelayCompactTypeInfo { Value = c.Type, Name = c.Type.ToString() }).Distinct(new RelayCompactTypeInfoEqualityComparer()).ToList();
return transports.Select(c => new RelayTypeInfo { Value = c.Type, Name = c.Type.ToString() }).Distinct(new RelayCompactTypeInfoEqualityComparer()).ToList();
}
/// <summary>
/// 收到中继协议列表
/// </summary>
/// <param name="servers"></param>
public void OnServers(RelayCompactInfo[] servers)
public void OnServers(RelayServerInfo[] servers)
{
running.Data.Relay.Servers = servers;
running.Data.Update();
@@ -113,9 +113,9 @@ namespace linker.plugins.relay
try
{
IEnumerable<ITransport> _transports = transports.OrderBy(c => c.Type);
foreach (RelayCompactInfo item in running.Data.Relay.Servers.Where(c => c.Disabled == false && string.IsNullOrWhiteSpace(c.Host) == false))
foreach (RelayServerInfo item in running.Data.Relay.Servers.Where(c => c.Disabled == false && string.IsNullOrWhiteSpace(c.Host) == false))
{
ITransport transport = _transports.FirstOrDefault(c => c.Type == item.Type);
ITransport transport = _transports.FirstOrDefault(c => c.Type == item.RelayType);
if (transport == null)
{
continue;

View File

@@ -14,7 +14,7 @@ namespace linker.client.config
public sealed class RelayRunningInfo
{
public ObjectId Id { get; set; }
public RelayCompactInfo[] Servers { get; set; } = Array.Empty<RelayCompactInfo>();
public RelayServerInfo[] Servers { get; set; } = Array.Empty<RelayServerInfo>();
}
}
@@ -33,35 +33,35 @@ namespace linker.config
}
[MemoryPackable]
public sealed partial class RelayCompactInfo
public sealed partial class RelayServerInfo
{
public string Name { get; set; } = string.Empty;
public RelayCompactType Type { get; set; } = RelayCompactType.linker;
public RelayType RelayType { get; set; } = RelayType.Linker;
public string SecretKey { get; set; } = "snltty";
public string Host { get; set; } = string.Empty;
public bool Disabled { get; set; }
public bool SSL { get; set; } = true;
}
public enum RelayCompactType : byte
public enum RelayType : byte
{
linker = 0,
Linker = 0,
}
public sealed class RelayCompactTypeInfo
public sealed class RelayTypeInfo
{
public RelayCompactType Value { get; set; }
public RelayType Value { get; set; }
public string Name { get; set; }
}
public sealed class RelayCompactTypeInfoEqualityComparer : IEqualityComparer<RelayCompactTypeInfo>
public sealed class RelayCompactTypeInfoEqualityComparer : IEqualityComparer<RelayTypeInfo>
{
public bool Equals(RelayCompactTypeInfo x, RelayCompactTypeInfo y)
public bool Equals(RelayTypeInfo x, RelayTypeInfo y)
{
return x.Value == y.Value;
}
public int GetHashCode([DisallowNull] RelayCompactTypeInfo obj)
public int GetHashCode([DisallowNull] RelayTypeInfo obj)
{
return obj.Value.GetHashCode();
}

View File

@@ -39,7 +39,7 @@ namespace linker.plugins.relay.messenger
[MessengerId((ushort)RelayMessengerIds.Servers)]
public void Servers(IConnection connection)
{
RelayCompactInfo[] servers = MemoryPackSerializer.Deserialize<RelayCompactInfo[]>(connection.ReceiveRequestWrap.Payload.Span);
RelayServerInfo[] servers = MemoryPackSerializer.Deserialize<RelayServerInfo[]>(connection.ReceiveRequestWrap.Payload.Span);
relayTransfer.OnServers(servers);
}
}
@@ -71,7 +71,7 @@ namespace linker.plugins.relay.messenger
[MessengerId((ushort)RelayMessengerIds.ServersForward)]
public async Task ServersForward(IConnection connection)
{
RelayCompactInfo[] servers = MemoryPackSerializer.Deserialize<RelayCompactInfo[]>(connection.ReceiveRequestWrap.Payload.Span);
RelayServerInfo[] servers = MemoryPackSerializer.Deserialize<RelayServerInfo[]>(connection.ReceiveRequestWrap.Payload.Span);
if (signCaching.TryGet(connection.Id, out SignCacheInfo cache))
{

View File

@@ -17,7 +17,7 @@ namespace linker.plugins.relay.transport
/// <summary>
/// 中继类型
/// </summary>
public RelayCompactType Type { get; }
public RelayType Type { get; }
/// <summary>
/// 协议
/// </summary>

View File

@@ -17,7 +17,7 @@ namespace linker.plugins.relay.transport
public sealed class TransportSelfHost : ITransport
{
public string Name => "默认";
public RelayCompactType Type => RelayCompactType.linker;
public RelayType Type => RelayType.Linker;
public TunnelProtocolType ProtocolType => TunnelProtocolType.Tcp;
private readonly TcpServer tcpServer;

View File

@@ -10,8 +10,6 @@ using MemoryPack;
using System.Net;
using System.Security.Cryptography.X509Certificates;
using linker.tunnel.wanport;
using System.Linq;
using linker.libs.extends;
using System.Buffers.Binary;
namespace linker.plugins.tunnel
@@ -42,11 +40,11 @@ namespace linker.plugins.tunnel
}
}
public List<TunnelWanPortInfo> GetTunnelWanPortCompacts()
public List<TunnelWanPortInfo> GetTunnelWanPortProtocols()
{
return running.Data.Tunnel.Servers.ToList();
}
public void SetTunnelWanPortCompacts(List<TunnelWanPortInfo> compacts)
public void SetTunnelWanPortProtocols(List<TunnelWanPortInfo> compacts)
{
running.Data.Tunnel.Servers = compacts.ToArray();
running.Data.Update();
@@ -68,16 +66,16 @@ namespace linker.plugins.tunnel
{
LocalIps = config.Data.Client.Tunnel.LocalIPs
.Where(c => c.Equals(running.Data.Tuntap.IP) == false)
.Where(c=>
.Where(c =>
{
if(c.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
if (c.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
{
uint ip = BinaryPrimitives.ReadUInt32BigEndian(c.GetAddressBytes());
foreach (var item in running.Data.Tunnel.ExcludeIPs)
{
uint maskValue = NetworkHelper.MaskValue(item.Mask);
uint ip1 = BinaryPrimitives.ReadUInt32BigEndian(item.IPAddress.GetAddressBytes());
if((ip & maskValue) == (ip1 & maskValue))
if ((ip & maskValue) == (ip1 & maskValue))
{
return false;
}
@@ -90,13 +88,13 @@ namespace linker.plugins.tunnel
MachineId = config.Data.Client.Id
};
}
public async Task<TunnelTransportWanPortInfo> GetRemoteWanPort(string remoteMachineId)
public async Task<TunnelTransportWanPortInfo> GetRemoteWanPort(TunnelWanPortProtocolInfo info)
{
MessageResponeInfo resp = await messengerSender.SendReply(new MessageRequestWrap
{
Connection = clientSignInState.Connection,
MessengerId = (ushort)TunnelMessengerIds.InfoForward,
Payload = MemoryPackSerializer.Serialize(remoteMachineId)
Payload = MemoryPackSerializer.Serialize(info)
});
if (resp.Code == MessageResponeCodes.OK && resp.Data.Length > 0)
{

View File

@@ -82,7 +82,7 @@ namespace linker.plugins.tunnel
{
SetServersParamInfo info = param.Content.DeJson<SetServersParamInfo>();
tunnelMessengerAdapter.SetTunnelWanPortCompacts(info.List.ToList());
tunnelMessengerAdapter.SetTunnelWanPortProtocols(info.List.ToList());
if (info.Sync)
{
await messengerSender.SendOnly(new MessageRequestWrap

View File

@@ -38,10 +38,10 @@ namespace linker.plugins.tunnel
running.Data.Tunnel.Servers = new TunnelWanPortInfo[]
{
new TunnelWanPortInfo{
Name="默认",
Name="Linker Udp",
Type= TunnelWanPortType.Linker,
Disabled = false,
Host = running.Data.Client.Servers.FirstOrDefault().Host
Host = running.Data.Client.Servers.FirstOrDefault().Host,
}
};
}

View File

@@ -42,14 +42,14 @@ namespace linker.plugins.tunnel
//外网端口协议
serviceCollection.AddSingleton<TunnelWanPortTransfer>();
serviceCollection.AddSingleton<TunnelWanPortLinker>();
serviceCollection.AddSingleton<TunnelWanPortStun>();
serviceCollection.AddSingleton<TunnelWanPortProtocolLinkerUdp>();
serviceCollection.AddSingleton<TunnelWanPortProtocolStun>();
//打洞协议
serviceCollection.AddSingleton<TunnelTransfer>();
serviceCollection.AddSingleton<TunnelTransportTcpNutssb>();
serviceCollection.AddSingleton<TransportMsQuic>();
serviceCollection.AddSingleton<TransportMsQuic>();
serviceCollection.AddSingleton<TransportTcpP2PNAT>();
serviceCollection.AddSingleton<TunnelConfigTransfer>();
serviceCollection.AddSingleton<ITunnelAdapter, TunnelAdapter>();
@@ -77,10 +77,10 @@ namespace linker.plugins.tunnel
{
ITunnelAdapter tunnelAdapter = serviceProvider.GetService<ITunnelAdapter>();
IEnumerable<Type> types = ReflectionHelper.GetInterfaceSchieves(assemblies.Concat(new Assembly[] { typeof(TunnelWanPortTransfer).Assembly }).ToArray(), typeof(ITunnelWanPort));
List<ITunnelWanPort> compacts = types.Select(c => (ITunnelWanPort)serviceProvider.GetService(c)).Where(c => c != null).Where(c => string.IsNullOrWhiteSpace(c.Name) == false).ToList();
IEnumerable<Type> types = ReflectionHelper.GetInterfaceSchieves(assemblies.Concat(new Assembly[] { typeof(TunnelWanPortTransfer).Assembly }).ToArray(), typeof(ITunnelWanPortProtocol));
List<ITunnelWanPortProtocol> compacts = types.Select(c => (ITunnelWanPortProtocol)serviceProvider.GetService(c)).Where(c => c != null).Where(c => string.IsNullOrWhiteSpace(c.Name) == false).ToList();
TunnelWanPortTransfer compack = serviceProvider.GetService<TunnelWanPortTransfer>();
compack.Init(tunnelAdapter,compacts);
compack.Init(compacts);
types = ReflectionHelper.GetInterfaceSchieves(assemblies.Concat(new Assembly[] { typeof(TunnelTransfer).Assembly }).ToArray(), typeof(ITunnelTransport));

View File

@@ -5,6 +5,8 @@ using LiteDB;
using MemoryPack;
using System.Net;
using System.Text.Json.Serialization;
using linker.tunnel.adapter;
using System.Net.Sockets;
namespace linker.client.config
@@ -29,7 +31,7 @@ namespace linker.client.config
public sealed partial class ExcludeIPItem
{
[MemoryPackAllowSerialize]
public IPAddress IPAddress { get; set;}
public IPAddress IPAddress { get; set; }
public byte Mask { get; set; } = 32;
}
}
@@ -60,6 +62,60 @@ namespace linker.config
}
[MemoryPackable]
public readonly partial struct SerializableTunnelWanPortProtocolInfo
{
[MemoryPackIgnore]
public readonly TunnelWanPortProtocolInfo info;
[MemoryPackInclude]
string MachineId => info.MachineId;
[MemoryPackInclude]
TunnelWanPortType Type => info.Type;
[MemoryPackInclude]
TunnelWanPortProtocolType ProtocolType => info.ProtocolType;
[MemoryPackConstructor]
SerializableTunnelWanPortProtocolInfo(string machineId, TunnelWanPortType type, TunnelWanPortProtocolType protocolType)
{
var info = new TunnelWanPortProtocolInfo { MachineId = machineId, Type = type, ProtocolType = protocolType };
this.info = info;
}
public SerializableTunnelWanPortProtocolInfo(TunnelWanPortProtocolInfo tunnelCompactInfo)
{
this.info = tunnelCompactInfo;
}
}
public class TunnelWanPortProtocolInfoFormatter : MemoryPackFormatter<TunnelWanPortProtocolInfo>
{
public override void Serialize<TBufferWriter>(ref MemoryPackWriter<TBufferWriter> writer, scoped ref TunnelWanPortProtocolInfo value)
{
if (value == null)
{
writer.WriteNullObjectHeader();
return;
}
writer.WritePackable(new SerializableTunnelWanPortProtocolInfo(value));
}
public override void Deserialize(ref MemoryPackReader reader, scoped ref TunnelWanPortProtocolInfo value)
{
if (reader.PeekIsNull())
{
reader.Advance(1); // skip null block
value = null;
return;
}
var wrapped = reader.ReadPackable<SerializableTunnelWanPortProtocolInfo>();
value = wrapped.info;
}
}
[MemoryPackable]
public readonly partial struct SerializableTunnelWanPortInfo
{

View File

@@ -39,7 +39,8 @@ namespace linker.plugins.tunnel.messenger
[MessengerId((ushort)TunnelMessengerIds.Info)]
public async Task Info(IConnection connection)
{
TunnelTransportWanPortInfo tunnelTransportPortInfo = await tunnel.GetWanPort();
TunnelWanPortProtocolInfo info = MemoryPackSerializer.Deserialize<TunnelWanPortProtocolInfo>(connection.ReceiveRequestWrap.Payload.Span);
TunnelTransportWanPortInfo tunnelTransportPortInfo = await tunnel.GetWanPort(info);
if (tunnelTransportPortInfo != null)
{
connection.Write(MemoryPackSerializer.Serialize(tunnelTransportPortInfo));
@@ -95,7 +96,7 @@ namespace linker.plugins.tunnel.messenger
public void Servers(IConnection connection)
{
TunnelWanPortInfo[] servers = MemoryPackSerializer.Deserialize<TunnelWanPortInfo[]>(connection.ReceiveRequestWrap.Payload.Span);
tunnelMessengerAdapter.SetTunnelWanPortCompacts(servers.ToList());
tunnelMessengerAdapter.SetTunnelWanPortProtocols(servers.ToList());
}
[MessengerId((ushort)TunnelMessengerIds.ExcludeIPs)]
@@ -119,8 +120,8 @@ namespace linker.plugins.tunnel.messenger
[MessengerId((ushort)TunnelMessengerIds.InfoForward)]
public void InfoForward(IConnection connection)
{
string remoteMachineId = MemoryPackSerializer.Deserialize<string>(connection.ReceiveRequestWrap.Payload.Span);
if (signCaching.TryGet(remoteMachineId, out SignCacheInfo cache) && signCaching.TryGet(connection.Id, out SignCacheInfo cache1) && cache.GroupId == cache1.GroupId)
TunnelWanPortProtocolInfo info = MemoryPackSerializer.Deserialize<TunnelWanPortProtocolInfo>(connection.ReceiveRequestWrap.Payload.Span);
if (signCaching.TryGet(info.MachineId, out SignCacheInfo cache) && signCaching.TryGet(connection.Id, out SignCacheInfo cache1) && cache.GroupId == cache1.GroupId)
{
uint requestid = connection.ReceiveRequestWrap.RequestId;
_ = messengerSender.SendReply(new MessageRequestWrap

View File

@@ -1,5 +1,6 @@
using linker.libs;
using linker.libs.extends;
using System.Buffers;
using System.Net;
using System.Net.Security;
using System.Net.Sockets;
@@ -64,6 +65,20 @@ namespace linker.server
}
private Memory<byte> BuildSendData(byte[] data, IPEndPoint ep)
{
//给客户端返回他的IP+端口
data[0] = (byte)ep.AddressFamily;
ep.Address.TryWriteBytes(data.AsSpan(1), out int length);
((ushort)ep.Port).ToBytes(data.AsMemory(1 + length));
//防止一些网关修改掉它的外网IP
for (int i = 0; i < 1 + length + 2; i++)
{
data[i] = (byte)(data[i] ^ byte.MaxValue);
}
return data.AsMemory(0, 1 + length + 2);
}
private async Task BindUdp(int port)
{
@@ -81,18 +96,9 @@ namespace linker.server
IPEndPoint ep = result.RemoteEndPoint as IPEndPoint;
try
{
//给客户端返回他的IP+端口
sendData[0] = (byte)ep.AddressFamily;
ep.Address.TryWriteBytes(sendData.AsSpan(1), out int length);
((ushort)ep.Port).ToBytes(sendData.AsMemory(1 + length));
Memory<byte> memory = BuildSendData(sendData, ep);
//防止一些网关修改掉它的外网IP
for (int i = 0; i < 1 + length + 2; i++)
{
sendData[i] = (byte)(sendData[i] ^ byte.MaxValue);
}
await socketUdp.SendToAsync(sendData.AsMemory(0, 1 + length + 2), ep);
await socketUdp.SendToAsync(memory, ep);
}
catch (Exception)
{
@@ -140,15 +146,45 @@ namespace linker.server
StartAccept(e);
}
}
private async Task<IConnection> BeginReceiveServer(Socket socket)
private async Task<byte> ReceiveType(Socket socket)
{
byte[] sendData = ArrayPool<byte>.Shared.Rent(20);
try
{
await socket.ReceiveAsync(sendData.AsMemory(0, 1), SocketFlags.None);
byte type = sendData[0];
if (type == 0)
{
Memory<byte> memory = BuildSendData(sendData, socket.RemoteEndPoint as IPEndPoint);
await socket.SendAsync(memory, SocketFlags.None);
}
return type;
}
catch (Exception)
{
}
finally
{
ArrayPool<byte>.Shared.Return(sendData);
}
return 1;
}
private async Task BeginReceiveServer(Socket socket)
{
try
{
if (socket == null || socket.RemoteEndPoint == null)
{
return null;
return;
}
socket.KeepAlive();
if (await ReceiveType(socket) == 0)
{
return;
}
NetworkStream networkStream = new NetworkStream(socket, false);
SslStream sslStream = new SslStream(networkStream, true);
await sslStream.AuthenticateAsServerAsync(serverCertificate, false, SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12 | SslProtocols.Tls13, false);
@@ -156,14 +192,12 @@ namespace linker.server
connection.BeginReceive(connectionReceiveCallback, null, true);
return connection;
}
catch (Exception ex)
{
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
LoggerHelper.Instance.Error(ex);
}
return null;
}
private bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
@@ -179,6 +213,7 @@ namespace linker.server
return null;
}
socket.KeepAlive();
await socket.SendAsync(new byte[] { 1 });
NetworkStream networkStream = new NetworkStream(socket, false);
SslStream sslStream = new SslStream(networkStream, true, new RemoteCertificateValidationCallback(ValidateServerCertificate), null);
await sslStream.AuthenticateAsClientAsync(new SslClientAuthenticationOptions

View File

@@ -17,6 +17,7 @@ for %%r in (win-x64,win-arm64) do (
echo F|xcopy "linker\\msquic.dll" "public\\extends\\%%r\\linker-%%r\\msquic.dll" /s /f /h /y
echo F|xcopy "linker\\msquic-openssl.dll" "public\\extends\\%%r\\linker-%%r\\msquic-openssl.dll" /s /f /h /y
)
for %%r in (linux-x64,linux-arm64,osx-x64,osx-arm64) do (
echo F|xcopy "linker\\plugins\\tuntap\\tun2socks-%%r" "public\\extends\\%%r\\linker-%%r\\plugins\\tuntap\\tun2socks" /s /f /h /y
)
@@ -24,7 +25,6 @@ for %%r in (win-x64,win-arm64) do (
echo F|xcopy "linker\\plugins\\tuntap\\tun2socks-%%r" "public\\extends\\%%r\\linker-%%r\\plugins\\tuntap\\tun2socks.exe" /s /f /h /y
)
for %%r in (win-x64,win-arm64,linux-x64,linux-arm64,osx-x64,osx-arm64) do (
dotnet publish ./linker -c release -f net8.0 -o ./public/publish/%%r/linker-%%r -r %%r -p:PublishTrimmed=true -p:TrimMode=partial --self-contained true -p:TieredPGO=true -p:DebugType=none -p:DebugSymbols=false -p:PublishSingleFile=true -p:EnableCompressionInSingleFile=true -p:DebuggerSupport=false -p:EnableUnsafeBinaryFormatterSerialization=false -p:EnableUnsafeUTF7Encoding=false -p:HttpActivityPropagationSupport=false -p:InvariantGlobalization=true -p:MetadataUpdaterSupport=false -p:UseSystemResourceKeys=true