测试基于端口映射的P2P连接

This commit is contained in:
snltty
2024-07-27 00:35:24 +08:00
parent 540954b9c5
commit 0e741e46d3
20 changed files with 953 additions and 58 deletions

View File

@@ -16,14 +16,6 @@ sidebar_position: 1
<a href="https://jq.qq.com/?_wv=1027&k=ucoIVfz4" target="_blank">你可以加入QQ群1121552990 </a> <a href="https://jq.qq.com/?_wv=1027&k=ucoIVfz4" target="_blank">你可以加入QQ群1121552990 </a>
## 2、一些免费中继服务器
请各位善待
1. free、linker-hw-222200.snltty.com:1802、snltty
2. free、linker-hw-223400.snltty.com:1802、snltty
3. free、linker-hw-2451000.snltty.com:1802、snltty
## 2、感谢支持 ## 2、感谢支持
<a href="https://mi-d.cn" target="_blank"><img src="https://mi-d.cn/wp-content/uploads/2021/12/cropped-1639494965-网站LOGO无字.png" width="40" style={{verticalAlign: 'middle'}} /> 米多贝克</a> <a href="https://mi-d.cn" target="_blank"><img src="https://mi-d.cn/wp-content/uploads/2021/12/cropped-1639494965-网站LOGO无字.png" width="40" style={{verticalAlign: 'middle'}} /> 米多贝克</a>

View File

@@ -56,9 +56,13 @@ systemctl enable linker
5. debian `snltty/linker-debian-x64``snltty/linker-debian-arm64`,压缩约`70MB`、未压缩约`177MB` 5. debian `snltty/linker-debian-x64``snltty/linker-debian-arm64`,压缩约`70MB`、未压缩约`177MB`
6. alpine `snltty/linker-musl-x64``snltty/linker-musl-arm64`,压缩约`19MB`、未压缩约`43MB` 6. alpine `snltty/linker-musl-x64``snltty/linker-musl-arm64`,压缩约`19MB`、未压缩约`43MB`
#### 特别说明 :::tip[特别说明]
1. 在容器中监听一个端口,宿主机无法访问,所以你需要把端口映射一下,比如 `-p 18000-18010:18000-18010`,预留这些端口,这样就可以使用这些端口做转发 1. 在容器中监听一个端口,宿主机无法访问,所以你需要把端口映射一下,比如 `-p 18000-18010:18000-18010`,预留这些端口,这样就可以使用这些端口做转发
2. 在docker容器中创建虚拟网卡是无法直接通过虚拟网卡访问宿主机的你需要把端口映射一下或者直接使用`host`网络模式 2. 在docker容器中创建虚拟网卡是无法直接通过虚拟网卡访问宿主机的你需要把端口映射一下或者直接使用`host`网络模式
:::
#### 客户端 #### 客户端
``` ```
docker run -it -d --name linker \ docker run -it -d --name linker \

View File

@@ -18,8 +18,18 @@ sidebar_position: 3
![Docusaurus Plushie](./img/tuntap.png) ![Docusaurus Plushie](./img/tuntap.png)
1. 为目标设备设置一个IP地址例如 **192.168.54.2** 1. 为目标设备设置一个IP地址例如 **192.168.54.2**,每个客户端之间,填写相同网段的**网卡IP**,且掩码是**/24**的
2. 填写目标设备的局域网IP。比如目标设备局域网IP为**192.168.56.55**局域网IP是可选的且各个设备之间局域网IP段不可重复比如不能两个设备的局域网IP 都是 **192.168.56.x/24** 2. `局域网IP` 是选填的,可以不填
:::tip[局域网IP特别说明]
1. 假设你 A 的内网IP是 **192.168.1.2**B 的内网IP是 **192.168.2.3**这样AB之间是无法相互连接的
2. 这时 A 可以在 **局域网IP**填写 **192.168.1.2/24**B 填写 **192.168.2.3/24**这样AB之间就可以使用对方的内网IP相互访问
3. 值得一提的是,如果你选择填写**局域网IP**,那么每个客户端之间,是不能填写相同网段的**局域网IP**,会冲突
:::
>
![Docusaurus Plushie](./img/tuntap1.png) ![Docusaurus Plushie](./img/tuntap1.png)

View File

@@ -1,4 +1,6 @@
using linker.serializes;
using linker.config;
using linker.plugins.serializes;
using linker.tunnel.connection; using linker.tunnel.connection;
using linker.tunnel.transport; using linker.tunnel.transport;
using MemoryPack; using MemoryPack;
@@ -12,9 +14,470 @@ namespace linker.Tests
[TestMethod] [TestMethod]
public void Serialize() public void Serialize()
{ {
MemoryPackFormatterProvider.Register(new TunnelTransportWanPortInfoFormatter1());
MemoryPackFormatterProvider.Register(new TunnelTransportWanPortInfoFormatter2());
MemoryPackFormatterProvider.Register(new TunnelTransportInfoFormatter1());
MemoryPackFormatterProvider.Register(new TunnelTransportInfoFormatter2());
MemoryPackFormatterProvider.Register(new IPEndPointFormatter());
MemoryPackFormatterProvider.Register(new IPAddressFormatter());
TunnelTransportInfo2 tunnelTransportInfo2 = new TunnelTransportInfo2 { Local = new TunnelTransportWanPortInfo2 { MachineName = "local2" }, Remote = new TunnelTransportWanPortInfo2 { MachineName = "remote2" } };
byte[] bytes = MemoryPackSerializer.Serialize(tunnelTransportInfo2);
TunnelTransportInfo1 tunnelTransportInfo1 = MemoryPackSerializer.Deserialize<TunnelTransportInfo1>(bytes);
Assert.AreEqual(tunnelTransportInfo2.Local.MachineName, tunnelTransportInfo1.Local.MachineName);
} }
} }
public sealed partial class TunnelTransportWanPortInfo1
{
/// <summary>
/// <20>ҵı<D2B5><C4B1><EFBFBD>
/// </summary>
public IPEndPoint Local { get; set; }
/// <summary>
/// <20>ҵ<EFBFBD><D2B5><EFBFBD><EFBFBD><EFBFBD>
/// </summary>
public IPEndPoint Remote { get; set; }
/// <summary>
/// <20>ҵľ<D2B5><C4BE><EFBFBD><EFBFBD><EFBFBD>IP
/// </summary>
public IPAddress[] LocalIps { get; set; }
/// <summary>
/// <20>ҵ<EFBFBD><D2B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/// </summary>
public int RouteLevel { get; set; }
/// <summary>
/// <20>ҵ<EFBFBD>id
/// </summary>
public string MachineId { get; set; }
/// <summary>
/// <20>ҵ<EFBFBD><D2B5><EFBFBD><EFBFBD><EFBFBD>
/// </summary>
public string MachineName { get; set; }
}
public sealed partial class TunnelTransportWanPortInfo2
{
/// <summary>
/// <20>ҵı<D2B5><C4B1><EFBFBD>
/// </summary>
public IPEndPoint Local { get; set; }
/// <summary>
/// <20>ҵ<EFBFBD><D2B5><EFBFBD><EFBFBD><EFBFBD>
/// </summary>
public IPEndPoint Remote { get; set; }
/// <summary>
/// <20>ҵľ<D2B5><C4BE><EFBFBD><EFBFBD><EFBFBD>IP
/// </summary>
public IPAddress[] LocalIps { get; set; }
/// <summary>
/// <20>ҵ<EFBFBD><D2B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/// </summary>
public int RouteLevel { get; set; }
/// <summary>
/// <20>ҵ<EFBFBD>id
/// </summary>
public string MachineId { get; set; }
/// <summary>
/// <20>ҵ<EFBFBD><D2B5><EFBFBD><EFBFBD><EFBFBD>
/// </summary>
public string MachineName { get; set; }
public int PortMapLan { get; set; }
public int PortMapWan { get; set; }
}
[MemoryPackable]
public readonly partial struct SerializableTunnelTransportWanPortInfo1
{
[MemoryPackIgnore]
public readonly TunnelTransportWanPortInfo1 tunnelTransportWanPortInfo;
[MemoryPackInclude, MemoryPackAllowSerialize]
IPEndPoint Local => tunnelTransportWanPortInfo.Local;
[MemoryPackInclude, MemoryPackAllowSerialize]
IPEndPoint Remote => tunnelTransportWanPortInfo.Remote;
[MemoryPackInclude, MemoryPackAllowSerialize]
IPAddress[] LocalIps => tunnelTransportWanPortInfo.LocalIps;
[MemoryPackInclude]
int RouteLevel => tunnelTransportWanPortInfo.RouteLevel;
[MemoryPackInclude]
string MachineId => tunnelTransportWanPortInfo.MachineId;
[MemoryPackInclude]
string MachineName => tunnelTransportWanPortInfo.MachineName;
[MemoryPackConstructor]
SerializableTunnelTransportWanPortInfo1(IPEndPoint local, IPEndPoint remote, IPAddress[] localIps, int routeLevel, string machineId, string machineName)
{
var tunnelTransportWanPortInfo = new TunnelTransportWanPortInfo1 { Local = local, Remote = remote, LocalIps = localIps, RouteLevel = routeLevel, MachineId = machineId, MachineName = machineName };
this.tunnelTransportWanPortInfo = tunnelTransportWanPortInfo;
}
public SerializableTunnelTransportWanPortInfo1(TunnelTransportWanPortInfo1 tunnelTransportWanPortInfo)
{
this.tunnelTransportWanPortInfo = tunnelTransportWanPortInfo;
}
}
public class TunnelTransportWanPortInfoFormatter1 : MemoryPackFormatter<TunnelTransportWanPortInfo1>
{
public override void Serialize<TBufferWriter>(ref MemoryPackWriter<TBufferWriter> writer, scoped ref TunnelTransportWanPortInfo1 value)
{
if (value == null)
{
writer.WriteNullObjectHeader();
return;
}
writer.WritePackable(new SerializableTunnelTransportWanPortInfo1(value));
}
public override void Deserialize(ref MemoryPackReader reader, scoped ref TunnelTransportWanPortInfo1 value)
{
if (reader.PeekIsNull())
{
reader.Advance(1); // skip null block
value = null;
return;
}
var wrapped = reader.ReadPackable<SerializableTunnelTransportWanPortInfo1>();
value = wrapped.tunnelTransportWanPortInfo;
}
}
[MemoryPackable]
public readonly partial struct SerializableTunnelTransportWanPortInfo2
{
[MemoryPackIgnore]
public readonly TunnelTransportWanPortInfo2 tunnelTransportWanPortInfo;
[MemoryPackInclude, MemoryPackAllowSerialize]
IPEndPoint Local => tunnelTransportWanPortInfo.Local;
[MemoryPackInclude, MemoryPackAllowSerialize]
IPEndPoint Remote => tunnelTransportWanPortInfo.Remote;
[MemoryPackInclude, MemoryPackAllowSerialize]
IPAddress[] LocalIps => tunnelTransportWanPortInfo.LocalIps;
[MemoryPackInclude]
int RouteLevel => tunnelTransportWanPortInfo.RouteLevel;
[MemoryPackInclude]
string MachineId => tunnelTransportWanPortInfo.MachineId;
[MemoryPackInclude]
string MachineName => tunnelTransportWanPortInfo.MachineName;
[MemoryPackInclude]
int PortMapLan => tunnelTransportWanPortInfo.PortMapLan;
[MemoryPackInclude]
int PortMapWan => tunnelTransportWanPortInfo.PortMapWan;
[MemoryPackConstructor]
SerializableTunnelTransportWanPortInfo2(IPEndPoint local, IPEndPoint remote, IPAddress[] localIps, int routeLevel, string machineId, string machineName, int portMapLan, int portMapWan)
{
var tunnelTransportWanPortInfo = new TunnelTransportWanPortInfo2
{
Local = local,
Remote = remote,
LocalIps = localIps,
RouteLevel = routeLevel,
MachineId = machineId,
MachineName = machineName,
PortMapLan = portMapLan,
PortMapWan = portMapWan
};
this.tunnelTransportWanPortInfo = tunnelTransportWanPortInfo;
}
public SerializableTunnelTransportWanPortInfo2(TunnelTransportWanPortInfo2 tunnelTransportWanPortInfo)
{
this.tunnelTransportWanPortInfo = tunnelTransportWanPortInfo;
}
}
public class TunnelTransportWanPortInfoFormatter2 : MemoryPackFormatter<TunnelTransportWanPortInfo2>
{
public override void Serialize<TBufferWriter>(ref MemoryPackWriter<TBufferWriter> writer, scoped ref TunnelTransportWanPortInfo2 value)
{
if (value == null)
{
writer.WriteNullObjectHeader();
return;
}
writer.WritePackable(new SerializableTunnelTransportWanPortInfo2(value));
}
public override void Deserialize(ref MemoryPackReader reader, scoped ref TunnelTransportWanPortInfo2 value)
{
if (reader.PeekIsNull())
{
reader.Advance(1); // skip null block
value = null;
return;
}
var wrapped = reader.ReadPackable<SerializableTunnelTransportWanPortInfo2>();
value = wrapped.tunnelTransportWanPortInfo;
}
}
public sealed partial class TunnelTransportInfo1
{
/// <summary>
/// <20>ҵ<EFBFBD>
/// </summary>
public TunnelTransportWanPortInfo1 Local { get; set; }
/// <summary>
/// <20>Է<EFBFBD><D4B7><EFBFBD>
/// </summary>
public TunnelTransportWanPortInfo1 Remote { get; set; }
/// <summary>
/// <20><><EFBFBD><EFBFBD>
/// </summary>
public string TransactionId { get; set; }
/// <summary>
/// Э<><D0AD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/// </summary>
public TunnelProtocolType TransportType { get; set; }
/// <summary>
/// Э<><D0AD><EFBFBD><EFBFBD>
/// </summary>
public string TransportName { get; set; }
/// <summary>
/// <20><><EFBFBD><EFBFBD>
/// </summary>
public TunnelDirection Direction { get; set; }
/// <summary>
/// <20><>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD>
/// </summary>
public bool SSL { get; set; }
/// <summary>
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/// </summary>
public byte BufferSize { get; set; } = 3;
/// <summary>
/// Ŀ<><C4BF>ip<69>б<EFBFBD>
/// </summary>
public List<IPEndPoint> RemoteEndPoints { get; set; }
}
public sealed partial class TunnelTransportInfo2
{
/// <summary>
/// <20>ҵ<EFBFBD>
/// </summary>
public TunnelTransportWanPortInfo2 Local { get; set; }
/// <summary>
/// <20>Է<EFBFBD><D4B7><EFBFBD>
/// </summary>
public TunnelTransportWanPortInfo2 Remote { get; set; }
/// <summary>
/// <20><><EFBFBD><EFBFBD>
/// </summary>
public string TransactionId { get; set; }
/// <summary>
/// Э<><D0AD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/// </summary>
public TunnelProtocolType TransportType { get; set; }
/// <summary>
/// Э<><D0AD><EFBFBD><EFBFBD>
/// </summary>
public string TransportName { get; set; }
/// <summary>
/// <20><><EFBFBD><EFBFBD>
/// </summary>
public TunnelDirection Direction { get; set; }
/// <summary>
/// <20><>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD>
/// </summary>
public bool SSL { get; set; }
/// <summary>
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/// </summary>
public byte BufferSize { get; set; } = 3;
/// <summary>
/// Ŀ<><C4BF>ip<69>б<EFBFBD>
/// </summary>
public List<IPEndPoint> RemoteEndPoints { get; set; }
}
[MemoryPackable]
public readonly partial struct SerializableTunnelTransportInfo1
{
[MemoryPackIgnore]
public readonly TunnelTransportInfo1 tunnelTransportInfo;
[MemoryPackInclude, MemoryPackAllowSerialize]
TunnelTransportWanPortInfo1 Local => tunnelTransportInfo.Local;
[MemoryPackInclude, MemoryPackAllowSerialize]
TunnelTransportWanPortInfo1 Remote => tunnelTransportInfo.Remote;
[MemoryPackInclude]
string TransactionId => tunnelTransportInfo.TransactionId;
[MemoryPackInclude]
TunnelProtocolType TransportType => tunnelTransportInfo.TransportType;
[MemoryPackInclude]
string TransportName => tunnelTransportInfo.TransportName;
[MemoryPackInclude]
TunnelDirection Direction => tunnelTransportInfo.Direction;
[MemoryPackInclude]
bool SSL => tunnelTransportInfo.SSL;
[MemoryPackInclude]
byte BufferSize => tunnelTransportInfo.BufferSize;
[MemoryPackConstructor]
SerializableTunnelTransportInfo1(TunnelTransportWanPortInfo1 local, TunnelTransportWanPortInfo1 remote, string transactionId, TunnelProtocolType transportType, string transportName, TunnelDirection direction, bool ssl, byte bufferSize)
{
var tunnelTransportInfo = new TunnelTransportInfo1
{
Local = local,
Remote = remote,
TransactionId = transactionId,
TransportName = transportName,
TransportType = transportType,
Direction = direction,
SSL = ssl,
BufferSize = bufferSize,
};
this.tunnelTransportInfo = tunnelTransportInfo;
}
public SerializableTunnelTransportInfo1(TunnelTransportInfo1 tunnelTransportInfo)
{
this.tunnelTransportInfo = tunnelTransportInfo;
}
}
public class TunnelTransportInfoFormatter1 : MemoryPackFormatter<TunnelTransportInfo1>
{
public override void Serialize<TBufferWriter>(ref MemoryPackWriter<TBufferWriter> writer, scoped ref TunnelTransportInfo1 value)
{
if (value == null)
{
writer.WriteNullObjectHeader();
return;
}
writer.WritePackable(new SerializableTunnelTransportInfo1(value));
}
public override void Deserialize(ref MemoryPackReader reader, scoped ref TunnelTransportInfo1 value)
{
if (reader.PeekIsNull())
{
reader.Advance(1); // skip null block
value = null;
return;
}
var wrapped = reader.ReadPackable<SerializableTunnelTransportInfo1>();
value = wrapped.tunnelTransportInfo;
}
}
[MemoryPackable]
public readonly partial struct SerializableTunnelTransportInfo2
{
[MemoryPackIgnore]
public readonly TunnelTransportInfo2 tunnelTransportInfo;
[MemoryPackInclude, MemoryPackAllowSerialize]
TunnelTransportWanPortInfo2 Local => tunnelTransportInfo.Local;
[MemoryPackInclude, MemoryPackAllowSerialize]
TunnelTransportWanPortInfo2 Remote => tunnelTransportInfo.Remote;
[MemoryPackInclude]
string TransactionId => tunnelTransportInfo.TransactionId;
[MemoryPackInclude]
TunnelProtocolType TransportType => tunnelTransportInfo.TransportType;
[MemoryPackInclude]
string TransportName => tunnelTransportInfo.TransportName;
[MemoryPackInclude]
TunnelDirection Direction => tunnelTransportInfo.Direction;
[MemoryPackInclude]
bool SSL => tunnelTransportInfo.SSL;
[MemoryPackInclude]
byte BufferSize => tunnelTransportInfo.BufferSize;
[MemoryPackConstructor]
SerializableTunnelTransportInfo2(TunnelTransportWanPortInfo2 local, TunnelTransportWanPortInfo2 remote, string transactionId, TunnelProtocolType transportType, string transportName, TunnelDirection direction, bool ssl, byte bufferSize)
{
var tunnelTransportInfo = new TunnelTransportInfo2
{
Local = local,
Remote = remote,
TransactionId = transactionId,
TransportName = transportName,
TransportType = transportType,
Direction = direction,
SSL = ssl,
BufferSize = bufferSize,
};
this.tunnelTransportInfo = tunnelTransportInfo;
}
public SerializableTunnelTransportInfo2(TunnelTransportInfo2 tunnelTransportInfo)
{
this.tunnelTransportInfo = tunnelTransportInfo;
}
}
public class TunnelTransportInfoFormatter2 : MemoryPackFormatter<TunnelTransportInfo2>
{
public override void Serialize<TBufferWriter>(ref MemoryPackWriter<TBufferWriter> writer, scoped ref TunnelTransportInfo2 value)
{
if (value == null)
{
writer.WriteNullObjectHeader();
return;
}
writer.WritePackable(new SerializableTunnelTransportInfo2(value));
}
public override void Deserialize(ref MemoryPackReader reader, scoped ref TunnelTransportInfo2 value)
{
if (reader.PeekIsNull())
{
reader.Advance(1); // skip null block
value = null;
return;
}
var wrapped = reader.ReadPackable<SerializableTunnelTransportInfo2>();
value = wrapped.tunnelTransportInfo;
}
}
} }

View File

@@ -17,6 +17,7 @@ namespace linker.tunnel
private ITunnelAdapter tunnelAdapter; private ITunnelAdapter tunnelAdapter;
private ConcurrentDictionary<string, bool> connectingDic = new ConcurrentDictionary<string, bool>(); private ConcurrentDictionary<string, bool> connectingDic = new ConcurrentDictionary<string, bool>();
private uint flowid = 1;
private Dictionary<string, List<Action<ITunnelConnection>>> OnConnected { get; } = new Dictionary<string, List<Action<ITunnelConnection>>>(); private Dictionary<string, List<Action<ITunnelConnection>>> OnConnected { get; } = new Dictionary<string, List<Action<ITunnelConnection>>>();
public TunnelTransfer() public TunnelTransfer()
@@ -181,7 +182,8 @@ namespace linker.tunnel
TransportType = transport.ProtocolType, TransportType = transport.ProtocolType,
Local = localInfo.Result, Local = localInfo.Result,
Remote = remoteInfo.Result, Remote = remoteInfo.Result,
SSL = transportItem.SSL SSL = transportItem.SSL,
FlowId = Interlocked.Increment(ref flowid)
}; };
OnConnecting(tunnelTransportInfo); OnConnecting(tunnelTransportInfo);
ParseRemoteEndPoint(tunnelTransportInfo); ParseRemoteEndPoint(tunnelTransportInfo);
@@ -295,6 +297,7 @@ namespace linker.tunnel
TunnelWanPortEndPoint ip = await compactTransfer.GetWanPortAsync(tunnelAdapter.LocalIP, info).ConfigureAwait(false); TunnelWanPortEndPoint ip = await compactTransfer.GetWanPortAsync(tunnelAdapter.LocalIP, info).ConfigureAwait(false);
if (ip != null) if (ip != null)
{ {
PortMapInfo portMapInfo = tunnelAdapter.PortMap ?? new PortMapInfo { LanPort = 0, WanPort = 0 };
var config = tunnelAdapter.GetLocalConfig(); var config = tunnelAdapter.GetLocalConfig();
return new TunnelTransportWanPortInfo return new TunnelTransportWanPortInfo
{ {
@@ -302,7 +305,9 @@ namespace linker.tunnel
Remote = ip.Remote, Remote = ip.Remote,
LocalIps = config.LocalIps, LocalIps = config.LocalIps,
RouteLevel = config.RouteLevel, RouteLevel = config.RouteLevel,
MachineId = config.MachineId MachineId = config.MachineId,
PortMapLan = portMapInfo.LanPort,
PortMapWan = portMapInfo.WanPort,
}; };
} }
return null; return null;

View File

@@ -12,6 +12,8 @@ namespace linker.tunnel.adapter
/// </summary> /// </summary>
public IPAddress LocalIP { get; } public IPAddress LocalIP { get; }
public PortMapInfo PortMap { get; }
/// <summary> /// <summary>
/// ssl加密证书 /// ssl加密证书
/// </summary> /// </summary>
@@ -26,7 +28,7 @@ namespace linker.tunnel.adapter
/// 保存外网端口协议列表 /// 保存外网端口协议列表
/// </summary> /// </summary>
/// <param name="compacts"></param> /// <param name="compacts"></param>
public void SetTunnelWanPortProtocols(List<TunnelWanPortInfo> protocols,bool updateVersion); public void SetTunnelWanPortProtocols(List<TunnelWanPortInfo> protocols, bool updateVersion);
/// <summary> /// <summary>
/// 获取打洞协议列表 /// 获取打洞协议列表
@@ -87,6 +89,12 @@ namespace linker.tunnel.adapter
public string MachineId { get; set; } public string MachineId { get; set; }
} }
public sealed class PortMapInfo
{
public int WanPort { get; set; }
public int LanPort { get; set; }
}
public sealed class TunnelWanPortProtocolInfo public sealed class TunnelWanPortProtocolInfo
{ {
/// <summary> /// <summary>

View File

@@ -5,7 +5,6 @@ using System.Buffers;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Net; using System.Net;
using System.Net.Sockets; using System.Net.Sockets;
using System.Collections.Generic;
namespace linker.tunnel.proxy namespace linker.tunnel.proxy
{ {
@@ -91,13 +90,6 @@ namespace linker.tunnel.proxy
} }
private async Task BeginReceive(AsyncUserToken token) private async Task BeginReceive(AsyncUserToken token)
{ {
int length = await token.Socket.ReceiveAsync(token.Buffer.AsMemory(), SocketFlags.None).ConfigureAwait(false);
if (length == 0)
{
CloseClientSocket(token);
return;
}
token.Proxy.Data = token.Buffer.AsMemory(0, length);
bool closeConnect = await ConnectTunnelConnection(token).ConfigureAwait(false); bool closeConnect = await ConnectTunnelConnection(token).ConfigureAwait(false);
if (token.Connection != null) if (token.Connection != null)
{ {

View File

@@ -25,7 +25,7 @@ namespace linker.tunnel.transport
/// <summary> /// <summary>
/// 是否反向打洞 /// 是否反向打洞
/// </summary> /// </summary>
public bool Reverse { get; } public bool Reverse { get; }
/// <summary> /// <summary>
/// 是否允许修改反向打洞配置 /// 是否允许修改反向打洞配置
/// </summary> /// </summary>
@@ -37,7 +37,7 @@ namespace linker.tunnel.transport
/// <summary> /// <summary>
/// 是否允许修改ssl配置 /// 是否允许修改ssl配置
/// </summary> /// </summary>
public bool DisableSSL { get; } public bool DisableSSL { get; }
/// <summary> /// <summary>
/// 发送连接开始信息 /// 发送连接开始信息
@@ -111,6 +111,15 @@ namespace linker.tunnel.transport
/// 我的名称 /// 我的名称
/// </summary> /// </summary>
public string MachineName { get; set; } public string MachineName { get; set; }
/// <summary>
/// 固定端口,外网
/// </summary>
public int PortMapWan { get; set; }
/// <summary>
/// 固定端口,内网
/// </summary>
public int PortMapLan { get; set; }
} }
public sealed partial class TunnelTransportItemInfo public sealed partial class TunnelTransportItemInfo
@@ -200,6 +209,12 @@ namespace linker.tunnel.transport
/// 缓冲区 /// 缓冲区
/// </summary> /// </summary>
public byte BufferSize { get; set; } = 3; public byte BufferSize { get; set; } = 3;
/// <summary>
/// 流id
/// </summary>
public uint FlowId { get; set; }
/// <summary> /// <summary>
/// 目标ip列表 /// 目标ip列表
/// </summary> /// </summary>

View File

@@ -104,7 +104,7 @@ namespace linker.tunnel.transport
if (tunnelTransportInfo.SSL && tunnelAdapter.Certificate == null) if (tunnelTransportInfo.SSL && tunnelAdapter.Certificate == null)
{ {
LoggerHelper.Instance.Error($"{Name}->ssl Certificate not found"); LoggerHelper.Instance.Error($"{Name}->ssl Certificate not found");
await OnSendConnectSuccess(tunnelTransportInfo).ConfigureAwait(false); await OnSendConnectFail(tunnelTransportInfo).ConfigureAwait(false);
return; return;
} }
//正向连接,也就是它要连接我,那我就监听 //正向连接,也就是它要连接我,那我就监听

View File

@@ -65,7 +65,7 @@ namespace linker.tunnel.transport
{ {
return null; return null;
} }
if(tunnelTransportInfo.Direction == TunnelDirection.Reverse) if (tunnelTransportInfo.Direction == TunnelDirection.Reverse)
{ {
await Task.Delay(50).ConfigureAwait(false); await Task.Delay(50).ConfigureAwait(false);
} }
@@ -88,7 +88,7 @@ namespace linker.tunnel.transport
if (tunnelTransportInfo.SSL && tunnelAdapter.Certificate == null) if (tunnelTransportInfo.SSL && tunnelAdapter.Certificate == null)
{ {
LoggerHelper.Instance.Error($"{Name}->ssl Certificate not found"); LoggerHelper.Instance.Error($"{Name}->ssl Certificate not found");
await OnSendConnectSuccess(tunnelTransportInfo).ConfigureAwait(false); await OnSendConnectFail(tunnelTransportInfo).ConfigureAwait(false);
return; return;
} }
ITunnelConnection connection = await ConnectForward(tunnelTransportInfo, TunnelMode.Server).ConfigureAwait(false); ITunnelConnection connection = await ConnectForward(tunnelTransportInfo, TunnelMode.Server).ConfigureAwait(false);

View File

@@ -0,0 +1,346 @@
using linker.tunnel.connection;
using linker.tunnel.wanport;
using System.Net.Sockets;
using System.Net;
using System.Text;
using linker.libs.extends;
using System.Collections.Concurrent;
using linker.libs;
using linker.tunnel.adapter;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Security.Authentication;
namespace linker.tunnel.transport
{
/// <summary>
/// 基于端口映射
/// </summary>
public sealed class TransportTcpPortMap : ITunnelTransport
{
public string Name => "TcpPortMap";
public string Label => "Tcp端口映射";
public TunnelProtocolType ProtocolType => TunnelProtocolType.Tcp;
public TunnelWanPortProtocolType AllowWanPortProtocolType => TunnelWanPortProtocolType.Tcp | 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; };
public Func<TunnelTransportInfo, Task> OnSendConnectSuccess { get; set; } = async (info) => { await Task.CompletedTask; };
public Action<ITunnelConnection> OnConnected { get; set; } = (state) => { };
private readonly ConcurrentDictionary<string, TaskCompletionSource<Socket>> distDic = new ConcurrentDictionary<string, TaskCompletionSource<Socket>>();
private readonly ITunnelAdapter tunnelAdapter;
public TransportTcpPortMap(ITunnelAdapter tunnelAdapter)
{
this.tunnelAdapter = tunnelAdapter;
}
Socket socket;
public async Task Listen(int localPort)
{
if (socket != null && (socket.LocalEndPoint as IPEndPoint).Port == localPort)
{
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
{
LoggerHelper.Instance.Warning($"{Name} {socket.LocalEndPoint} already exists");
}
return;
}
try
{
socket?.SafeClose();
if (localPort == 0) return;
IPAddress localIP = IPAddress.Any;
socket = new Socket(localIP.AddressFamily, SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp);
socket.IPv6Only(localIP.AddressFamily, false);
socket.ReuseBind(new IPEndPoint(localIP, localPort));
socket.Listen(int.MaxValue);
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
{
LoggerHelper.Instance.Debug($"{Name} listen {localPort}");
}
while (true)
{
try
{
Socket client = await socket.AcceptAsync();
_ = Task.Run(async () =>
{
try
{
byte[] bytes = new byte[1024];
int length = await client.ReceiveAsync(bytes.AsMemory()).AsTask().WaitAsync(TimeSpan.FromMilliseconds(3000));
if (length > 0)
{
string key = bytes.AsMemory(0, length).GetString();
LoggerHelper.Instance.Debug(key);
if (distDic.TryRemove(key, out TaskCompletionSource<Socket> tcs))
{
await client.SendAsync(bytes.AsMemory(0, length));
tcs.SetResult(client);
return;
}
}
client.SafeClose();
}
catch (Exception)
{
client.SafeClose();
}
});
}
catch (Exception)
{
break;
}
}
}
catch (Exception ex)
{
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
{
LoggerHelper.Instance.Error(ex);
}
}
}
public async Task<ITunnelConnection> ConnectAsync(TunnelTransportInfo tunnelTransportInfo)
{
if (tunnelTransportInfo.Direction == TunnelDirection.Forward)
{
if (tunnelTransportInfo.Remote.PortMapWan == 0)
{
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
LoggerHelper.Instance.Error($"ConnectAsync Forward【{Name}】{tunnelTransportInfo.Remote.MachineName} port mapping not configured");
return null;
}
//正向连接
if (await OnSendConnectBegin(tunnelTransportInfo).ConfigureAwait(false) == false)
{
return null;
}
await Task.Delay(100).ConfigureAwait(false);
ITunnelConnection connection = await ConnectForward(tunnelTransportInfo).ConfigureAwait(false);
if (connection != null)
{
await OnSendConnectSuccess(tunnelTransportInfo).ConfigureAwait(false);
return connection;
}
}
else if (tunnelTransportInfo.Direction == TunnelDirection.Reverse)
{
if (tunnelTransportInfo.Local.PortMapWan == 0)
{
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
LoggerHelper.Instance.Error($"ConnectAsync Reverse【{Name}】{tunnelTransportInfo.Local.MachineName} port mapping not configured");
return null;
}
//反向连接
TunnelTransportInfo tunnelTransportInfo1 = tunnelTransportInfo.ToJsonFormat().DeJson<TunnelTransportInfo>();
//等待对方连接如果连接成功我会收到一个socket并且创建一个连接对象失败的话会超时那就是null
var task = WaitConnect(tunnelTransportInfo1);
if (await OnSendConnectBegin(tunnelTransportInfo1).ConfigureAwait(false) == false)
{
return null;
}
ITunnelConnection connection = await task.ConfigureAwait(false);
if (connection != null)
{
await OnSendConnectSuccess(tunnelTransportInfo).ConfigureAwait(false);
return connection;
}
}
await OnSendConnectFail(tunnelTransportInfo).ConfigureAwait(false);
return null;
}
public async Task OnBegin(TunnelTransportInfo tunnelTransportInfo)
{
if (tunnelTransportInfo.SSL && tunnelAdapter.Certificate == null)
{
LoggerHelper.Instance.Error($"{Name}->ssl Certificate not found");
await OnSendConnectFail(tunnelTransportInfo).ConfigureAwait(false);
return;
}
//正向连接,等他来连
if (tunnelTransportInfo.Direction == TunnelDirection.Forward)
{
if (tunnelTransportInfo.Local.PortMapWan == 0)
{
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
LoggerHelper.Instance.Error($"OnBegin WaitConnect 【{Name}】{tunnelTransportInfo.Local.MachineName} port mapping not configured");
await OnSendConnectFail(tunnelTransportInfo).ConfigureAwait(false);
return;
}
_ = WaitConnect(tunnelTransportInfo).ContinueWith((result) =>
{
OnConnected(result.Result);
});
}
//我要连它,那就连接
else
{
if (tunnelTransportInfo.Remote.PortMapWan == 0)
{
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
LoggerHelper.Instance.Error($"OnBegin ConnectForward 【{Name}】{tunnelTransportInfo.Remote.MachineName} port mapping not configured");
await OnSendConnectFail(tunnelTransportInfo).ConfigureAwait(false);
return;
}
ITunnelConnection connection = await ConnectForward(tunnelTransportInfo).ConfigureAwait(false);
if (connection != null)
{
OnConnected(connection);
await OnSendConnectSuccess(tunnelTransportInfo).ConfigureAwait(false);
}
else
{
await OnSendConnectFail(tunnelTransportInfo).ConfigureAwait(false);
}
}
}
public void OnFail(TunnelTransportInfo tunnelTransportInfo)
{
}
public void OnSuccess(TunnelTransportInfo tunnelTransportInfo)
{
}
private async Task<ITunnelConnection> WaitConnect(TunnelTransportInfo tunnelTransportInfo)
{
TaskCompletionSource<Socket> tcs = new TaskCompletionSource<Socket>();
string key = $"{tunnelTransportInfo.Remote.MachineId}-{tunnelTransportInfo.FlowId}";
distDic.TryAdd(key, tcs);
try
{
Socket socket = await tcs.Task.WaitAsync(TimeSpan.FromMilliseconds(5000));
socket.KeepAlive();
SslStream sslStream = null;
if (tunnelTransportInfo.SSL)
{
if (tunnelAdapter.Certificate == null)
{
LoggerHelper.Instance.Error($"{Name}-> ssl Certificate not found");
socket.SafeClose();
return null;
}
sslStream = new SslStream(new NetworkStream(socket, false), false);
await sslStream.AuthenticateAsServerAsync(tunnelAdapter.Certificate, false, SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12 | SslProtocols.Tls13, false).ConfigureAwait(false);
}
TunnelConnectionTcp result = new TunnelConnectionTcp
{
RemoteMachineId = tunnelTransportInfo.Remote.MachineId,
RemoteMachineName = tunnelTransportInfo.Remote.MachineName,
Direction = tunnelTransportInfo.Direction,
ProtocolType = TunnelProtocolType.Tcp,
Stream = sslStream,
Socket = socket,
Type = TunnelType.P2P,
Mode = TunnelMode.Server,
TransactionId = tunnelTransportInfo.TransactionId,
TransportName = tunnelTransportInfo.TransportName,
IPEndPoint = socket.RemoteEndPoint as IPEndPoint,
Label = string.Empty,
SSL = tunnelTransportInfo.SSL,
BufferSize = tunnelTransportInfo.BufferSize,
};
return result;
}
catch (Exception)
{
}
finally
{
distDic.TryRemove(key, out _);
}
return null;
}
private async Task<ITunnelConnection> ConnectForward(TunnelTransportInfo tunnelTransportInfo)
{
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
{
LoggerHelper.Instance.Warning($"{Name} connect to {tunnelTransportInfo.Remote.MachineId}->{tunnelTransportInfo.Remote.MachineName} {string.Join("\r\n", tunnelTransportInfo.RemoteEndPoints.Select(c => c.ToString()))}");
}
IPEndPoint ep = new IPEndPoint(tunnelTransportInfo.Remote.Remote.Address, tunnelTransportInfo.Remote.PortMapWan);
Socket targetSocket = new(ep.AddressFamily, SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp);
try
{
targetSocket.KeepAlive();
targetSocket.ReuseBind(new IPEndPoint(tunnelTransportInfo.Local.Local.Address, tunnelTransportInfo.Local.Local.Port));
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
{
LoggerHelper.Instance.Warning($"{Name} connect to {tunnelTransportInfo.Remote.MachineId}->{tunnelTransportInfo.Remote.MachineName} {ep}");
}
await targetSocket.ConnectAsync(ep).WaitAsync(TimeSpan.FromMilliseconds(500)).ConfigureAwait(false);
await targetSocket.SendAsync($"{tunnelTransportInfo.Local.MachineId}-{tunnelTransportInfo.FlowId}".ToBytes());
await targetSocket.ReceiveAsync(new byte[1024]).WaitAsync(TimeSpan.FromMilliseconds(500)).ConfigureAwait(false); ;
//需要ssl
SslStream sslStream = null;
if (tunnelTransportInfo.SSL)
{
sslStream = new SslStream(new NetworkStream(targetSocket, false), false, new RemoteCertificateValidationCallback(ValidateServerCertificate), null);
await sslStream.AuthenticateAsClientAsync(new SslClientAuthenticationOptions { EnabledSslProtocols = SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12 | SslProtocols.Tls13 }).ConfigureAwait(false);
}
return new TunnelConnectionTcp
{
Stream = sslStream,
Socket = targetSocket,
IPEndPoint = targetSocket.RemoteEndPoint as IPEndPoint,
TransactionId = tunnelTransportInfo.TransactionId,
RemoteMachineId = tunnelTransportInfo.Remote.MachineId,
RemoteMachineName = tunnelTransportInfo.Remote.MachineName,
TransportName = Name,
Direction = tunnelTransportInfo.Direction,
ProtocolType = ProtocolType,
Type = TunnelType.P2P,
Mode = TunnelMode.Client,
Label = string.Empty,
SSL = tunnelTransportInfo.SSL,
BufferSize = tunnelTransportInfo.BufferSize,
};
}
catch (Exception ex)
{
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
{
LoggerHelper.Instance.Error($"{Name} connect {ep} fail {ex}");
}
targetSocket.SafeClose();
}
return null;
}
private bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
return true;
}
}
}

View File

@@ -1,6 +1,4 @@
using linker.libs; using linker.libs;
using linker.libs.extends;
using System.Diagnostics;
using System.Net; using System.Net;
namespace linker.tunnel.wanport namespace linker.tunnel.wanport
@@ -54,7 +52,7 @@ namespace linker.tunnel.wanport
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG) if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
LoggerHelper.Instance.Debug($"get domain ip {info.Host}"); LoggerHelper.Instance.Debug($"get domain ip {info.Host}");
IPEndPoint server = NetworkHelper.GetEndPoint(info.Host, 3478); IPEndPoint server = NetworkHelper.GetEndPoint(info.Host, 3478);
if(server == null) return null; if (server == null) return null;
TunnelWanPortEndPoint wanPort = await tunnelWanPort.GetAsync(server).ConfigureAwait(false); TunnelWanPortEndPoint wanPort = await tunnelWanPort.GetAsync(server).ConfigureAwait(false);
if (wanPort != null) if (wanPort != null)
{ {

View File

@@ -1,6 +1,6 @@
<template> <template>
<div class="status-wrap flex"> <div class="status-wrap flex">
<div class="copy"><a href="https://github.com/snltty/linker" target="_blank">snltty©linker v1.1.2.2</a></div> <div class="copy"><a href="https://github.com/snltty/linker" target="_blank">snltty©linker v1.2.0.0</a></div>
<div class="flex-1"></div> <div class="flex-1"></div>
<div class="api"><Api></Api></div> <div class="api"><Api></Api></div>
<div class="server"><Server></Server></div> <div class="server"><Server></Server></div>

View File

@@ -3,11 +3,7 @@
<div> <div>
<el-form ref="ruleFormRef" :model="state.ruleForm" :rules="state.rules" label-width="auto"> <el-form ref="ruleFormRef" :model="state.ruleForm" :rules="state.rules" label-width="auto">
<el-form-item label="" prop="alert"> <el-form-item label="" prop="alert">
<div> <div>网关层级为你的设备与外网的距离你可以手动调整数值</div>
<p>网关层级自动计算可能并不符合实际情况</p>
<p>你可以调整层级加减得到最终层级数以符合你的实际环境</p>
<p>这有助于提高TCP打洞成功率</p>
</div>
</el-form-item> </el-form-item>
<el-form-item label=""> <el-form-item label="">
<el-row> <el-row>
@@ -23,6 +19,23 @@
</el-col> </el-col>
</el-row> </el-row>
</el-form-item> </el-form-item>
<el-form-item label="" prop="alert">
<div>光猫映射了端口后可以直接连接需要把TcpPortMap调到第一</div>
</el-form-item>
<el-form-item label="">
<el-row>
<el-col :span="12">
<el-form-item label="外网端口" prop="PortMapWan">
<el-input-number v-model="state.ruleForm.PortMapWan" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="内网端口" prop="PortMapLan">
<el-input-number v-model="state.ruleForm.PortMapLan" />
</el-form-item>
</el-col>
</el-row>
</el-form-item>
<el-form-item label="" prop="Btns"> <el-form-item label="" prop="Btns">
<div class="t-c w-100"> <div class="t-c w-100">
<el-button @click="state.show = false">取消</el-button> <el-button @click="state.show = false">取消</el-button>
@@ -51,6 +64,8 @@ export default {
ruleForm: { ruleForm: {
RouteLevel: tunnel.value.current.RouteLevel, RouteLevel: tunnel.value.current.RouteLevel,
RouteLevelPlus: tunnel.value.current.RouteLevelPlus, RouteLevelPlus: tunnel.value.current.RouteLevelPlus,
PortMapWan: tunnel.value.current.PortMapWan,
PortMapLan: tunnel.value.current.PortMapLan,
}, },
rules: {} rules: {}
}); });
@@ -66,6 +81,8 @@ export default {
const json = JSON.parse(JSON.stringify(tunnel.value.current)); const json = JSON.parse(JSON.stringify(tunnel.value.current));
json.RouteLevel = +state.ruleForm.RouteLevel; json.RouteLevel = +state.ruleForm.RouteLevel;
json.RouteLevelPlus = +state.ruleForm.RouteLevelPlus; json.RouteLevelPlus = +state.ruleForm.RouteLevelPlus;
json.PortMapWan = +state.ruleForm.PortMapWan;
json.PortMapLan = +state.ruleForm.PortMapLan;
setTunnelRouteLevel(json).then(() => { setTunnelRouteLevel(json).then(() => {
state.show = false; state.show = false;
ElMessage.success('已操作!'); ElMessage.success('已操作!');

View File

@@ -19,7 +19,7 @@ namespace linker.plugins.tunnel
{ {
public IPAddress LocalIP => clientSignInState.Connection?.LocalAddress.Address ?? IPAddress.Any; public IPAddress LocalIP => clientSignInState.Connection?.LocalAddress.Address ?? IPAddress.Any;
public X509Certificate2 Certificate { get; private set; } public X509Certificate2 Certificate { get; private set; }
public PortMapInfo PortMap => new PortMapInfo { WanPort = running.Data.Tunnel.PortMapWan, LanPort = running.Data.Tunnel.PortMapLan };
private readonly ClientSignInState clientSignInState; private readonly ClientSignInState clientSignInState;
private readonly MessengerSender messengerSender; private readonly MessengerSender messengerSender;
@@ -104,7 +104,6 @@ namespace linker.plugins.tunnel
} }
public NetworkInfo GetLocalConfig() public NetworkInfo GetLocalConfig()
{ {
var excludeips = excludeIPTransfer.Get(); var excludeips = excludeIPTransfer.Get();
@@ -180,6 +179,5 @@ namespace linker.plugins.tunnel
return true; return true;
} }
} }
} }

View File

@@ -9,7 +9,6 @@ using System.Collections.Concurrent;
using linker.tunnel.wanport; using linker.tunnel.wanport;
using linker.client.config; using linker.client.config;
using linker.plugins.client; using linker.plugins.client;
using linker.plugins.server;
using linker.plugins.capi; using linker.plugins.capi;
using linker.plugins.messenger; using linker.plugins.messenger;
using linker.plugins.tunnel.excludeip; using linker.plugins.tunnel.excludeip;
@@ -87,7 +86,6 @@ namespace linker.plugins.tunnel
List<TunnelWanPortInfo> info = param.Content.DeJson<List<TunnelWanPortInfo>>(); List<TunnelWanPortInfo> info = param.Content.DeJson<List<TunnelWanPortInfo>>();
tunnelMessengerAdapter.SetTunnelWanPortProtocols(info,true); tunnelMessengerAdapter.SetTunnelWanPortProtocols(info,true);
return true; return true;
} }
/// <summary> /// <summary>
/// 设置网关层级 /// 设置网关层级
@@ -144,7 +142,6 @@ namespace linker.plugins.tunnel
ExcludeIPItem[] info = param.Content.DeJson<ExcludeIPItem[]>(); ExcludeIPItem[] info = param.Content.DeJson<ExcludeIPItem[]>();
excludeIPTransfer.SettExcludeIPs(info); excludeIPTransfer.SettExcludeIPs(info);
} }
public sealed class TunnelListInfo public sealed class TunnelListInfo
{ {
public ConcurrentDictionary<string, TunnelTransportRouteLevelInfo> List { get; set; } public ConcurrentDictionary<string, TunnelTransportRouteLevelInfo> List { get; set; }

View File

@@ -5,6 +5,7 @@ using linker.plugins.client;
using linker.plugins.messenger; using linker.plugins.messenger;
using linker.plugins.tunnel.messenger; using linker.plugins.tunnel.messenger;
using linker.tunnel.adapter; using linker.tunnel.adapter;
using linker.tunnel.transport;
using linker.tunnel.wanport; using linker.tunnel.wanport;
using MemoryPack; using MemoryPack;
using System.Collections.Concurrent; using System.Collections.Concurrent;
@@ -20,15 +21,15 @@ namespace linker.plugins.tunnel
private readonly MessengerSender messengerSender; private readonly MessengerSender messengerSender;
private readonly RunningConfigTransfer runningConfigTransfer; private readonly RunningConfigTransfer runningConfigTransfer;
private readonly ITunnelAdapter tunnelAdapter; private readonly ITunnelAdapter tunnelAdapter;
private readonly TransportTcpPortMap transportTcpPortMap;
private uint version = 0; private uint version = 0;
public uint ConfigVersion => version; public uint ConfigVersion => version;
private ConcurrentDictionary<string, TunnelTransportRouteLevelInfo> configs = new ConcurrentDictionary<string, TunnelTransportRouteLevelInfo>(); private ConcurrentDictionary<string, TunnelTransportRouteLevelInfo> configs = new ConcurrentDictionary<string, TunnelTransportRouteLevelInfo>();
public ConcurrentDictionary<string, TunnelTransportRouteLevelInfo> Config => configs; public ConcurrentDictionary<string, TunnelTransportRouteLevelInfo> Config => configs;
public TunnelConfigTransfer(FileConfig config, RunningConfig running, ClientSignInState clientSignInState, MessengerSender messengerSender, RunningConfigTransfer runningConfigTransfer, ITunnelAdapter tunnelAdapter) public TunnelConfigTransfer(FileConfig config, RunningConfig running, ClientSignInState clientSignInState, MessengerSender messengerSender, RunningConfigTransfer runningConfigTransfer, ITunnelAdapter tunnelAdapter, TransportTcpPortMap transportTcpPortMap)
{ {
this.config = config; this.config = config;
this.running = running; this.running = running;
@@ -36,12 +37,15 @@ namespace linker.plugins.tunnel
this.messengerSender = messengerSender; this.messengerSender = messengerSender;
this.runningConfigTransfer = runningConfigTransfer; this.runningConfigTransfer = runningConfigTransfer;
this.tunnelAdapter = tunnelAdapter; this.tunnelAdapter = tunnelAdapter;
this.transportTcpPortMap = transportTcpPortMap;
InitRouteLevel(); InitRouteLevel();
InitConfig(); InitConfig();
TestQuic(); TestQuic();
RefreshPortMap();
} }
private void InitConfig() private void InitConfig()
@@ -89,8 +93,11 @@ namespace linker.plugins.tunnel
public void OnLocalRouteLevel(TunnelTransportRouteLevelInfo tunnelTransportFileConfigInfo) public void OnLocalRouteLevel(TunnelTransportRouteLevelInfo tunnelTransportFileConfigInfo)
{ {
running.Data.Tunnel.RouteLevelPlus = tunnelTransportFileConfigInfo.RouteLevelPlus; running.Data.Tunnel.RouteLevelPlus = tunnelTransportFileConfigInfo.RouteLevelPlus;
running.Data.Tunnel.PortMapWan = tunnelTransportFileConfigInfo.PortMapWan;
running.Data.Tunnel.PortMapLan = tunnelTransportFileConfigInfo.PortMapLan;
running.Data.Update(); running.Data.Update();
GetRemoteRouteLevel(); GetRemoteRouteLevel();
RefreshPortMap();
} }
/// <summary> /// <summary>
/// 收到别人发给我的修改我的信息 /// 收到别人发给我的修改我的信息
@@ -134,6 +141,8 @@ namespace linker.plugins.tunnel
MachineId = config.Data.Client.Id, MachineId = config.Data.Client.Id,
RouteLevel = config.Data.Client.Tunnel.RouteLevel, RouteLevel = config.Data.Client.Tunnel.RouteLevel,
RouteLevelPlus = running.Data.Tunnel.RouteLevelPlus, RouteLevelPlus = running.Data.Tunnel.RouteLevelPlus,
PortMapWan = running.Data.Tunnel.PortMapWan,
PortMapLan = running.Data.Tunnel.PortMapLan,
NeedReboot = reboot NeedReboot = reboot
}; };
} }
@@ -175,5 +184,11 @@ namespace linker.plugins.tunnel
} }
} }
} }
private void RefreshPortMap()
{
_ = transportTcpPortMap.Listen(running.Data.Tunnel.PortMapLan);
}
} }
} }

View File

@@ -48,13 +48,15 @@ namespace linker.plugins.tunnel
serviceCollection.AddSingleton<TunnelWanPortProtocolLinkerUdp>(); serviceCollection.AddSingleton<TunnelWanPortProtocolLinkerUdp>();
serviceCollection.AddSingleton<TunnelWanPortProtocolLinkerTcp>(); serviceCollection.AddSingleton<TunnelWanPortProtocolLinkerTcp>();
serviceCollection.AddSingleton<TunnelWanPortProtocolStun>(); serviceCollection.AddSingleton<TunnelWanPortProtocolStun>();
//打洞协议 //打洞协议
serviceCollection.AddSingleton<TunnelTransfer>(); serviceCollection.AddSingleton<TunnelTransfer>();
serviceCollection.AddSingleton<TunnelTransportTcpNutssb>(); serviceCollection.AddSingleton<TunnelTransportTcpNutssb>();
serviceCollection.AddSingleton<TransportMsQuic>(); serviceCollection.AddSingleton<TransportMsQuic>();
serviceCollection.AddSingleton<TransportTcpP2PNAT>(); serviceCollection.AddSingleton<TransportTcpP2PNAT>();
serviceCollection.AddSingleton<TransportTcpPortMap>();
serviceCollection.AddSingleton<TunnelExcludeIPTransfer>(); serviceCollection.AddSingleton<TunnelExcludeIPTransfer>();
serviceCollection.AddSingleton<TunnelConfigTransfer>(); serviceCollection.AddSingleton<TunnelConfigTransfer>();
@@ -101,6 +103,7 @@ namespace linker.plugins.tunnel
TunnelExcludeIPTransfer excludeIPTransfer = serviceProvider.GetService<TunnelExcludeIPTransfer>(); TunnelExcludeIPTransfer excludeIPTransfer = serviceProvider.GetService<TunnelExcludeIPTransfer>();
excludeIPTransfer.Load(assemblies); excludeIPTransfer.Load(assemblies);
} }
public void UseServer(ServiceProvider serviceProvider, FileConfig config, Assembly[] assemblies) public void UseServer(ServiceProvider serviceProvider, FileConfig config, Assembly[] assemblies)

View File

@@ -28,7 +28,7 @@ namespace linker.client.config
/// <summary> /// <summary>
/// 附加的网关层级 /// 附加的网关层级
/// </summary> /// </summary>
public int RouteLevelPlus { get; set; } = 0; public int RouteLevelPlus { get; set; }
/// <summary> /// <summary>
/// 打洞排除IP列表 /// 打洞排除IP列表
/// </summary> /// </summary>
@@ -38,6 +38,9 @@ namespace linker.client.config
/// 打洞协议列表 /// 打洞协议列表
/// </summary> /// </summary>
public List<TunnelTransportItemInfo> Transports { get; set; } = new List<TunnelTransportItemInfo>(); public List<TunnelTransportItemInfo> Transports { get; set; } = new List<TunnelTransportItemInfo>();
public int PortMapWan { get; set; }
public int PortMapLan { get; set; }
} }
[MemoryPackable] [MemoryPackable]
@@ -73,10 +76,13 @@ namespace linker.config
public sealed partial class TunnelTransportRouteLevelInfo public sealed partial class TunnelTransportRouteLevelInfo
{ {
public string MachineId { get; set; } public string MachineId { get; set; }
public int RouteLevel { get; set; } = 0; public int RouteLevel { get; set; }
public int RouteLevelPlus { get; set; } = 0; public int RouteLevelPlus { get; set; }
public bool NeedReboot { get; set; } public bool NeedReboot { get; set; }
public int PortMapWan { get; set; }
public int PortMapLan { get; set; }
} }
@@ -219,10 +225,26 @@ namespace linker.config
[MemoryPackInclude] [MemoryPackInclude]
string MachineName => tunnelTransportWanPortInfo.MachineName; string MachineName => tunnelTransportWanPortInfo.MachineName;
[MemoryPackInclude]
int PortMapWan => tunnelTransportWanPortInfo.PortMapWan;
[MemoryPackInclude]
int PortMapLan => tunnelTransportWanPortInfo.PortMapLan;
[MemoryPackConstructor] [MemoryPackConstructor]
SerializableTunnelTransportWanPortInfo(IPEndPoint local, IPEndPoint remote, IPAddress[] localIps, int routeLevel, string machineId, string machineName) SerializableTunnelTransportWanPortInfo(IPEndPoint local, IPEndPoint remote, IPAddress[] localIps, int routeLevel, string machineId, string machineName, int portMapWan, int portMapLan)
{ {
var tunnelTransportWanPortInfo = new TunnelTransportWanPortInfo { Local = local, Remote = remote, LocalIps = localIps, RouteLevel = routeLevel, MachineId = machineId, MachineName = machineName }; var tunnelTransportWanPortInfo = new TunnelTransportWanPortInfo
{
Local = local,
Remote = remote,
LocalIps = localIps,
RouteLevel = routeLevel,
MachineId = machineId,
MachineName = machineName,
PortMapWan = portMapWan,
PortMapLan = portMapLan
};
this.tunnelTransportWanPortInfo = tunnelTransportWanPortInfo; this.tunnelTransportWanPortInfo = tunnelTransportWanPortInfo;
} }
@@ -259,7 +281,6 @@ namespace linker.config
} }
[MemoryPackable] [MemoryPackable]
public readonly partial struct SerializableTunnelTransportItemInfo public readonly partial struct SerializableTunnelTransportItemInfo
{ {
@@ -357,9 +378,12 @@ namespace linker.config
[MemoryPackInclude] [MemoryPackInclude]
byte BufferSize => tunnelTransportInfo.BufferSize; byte BufferSize => tunnelTransportInfo.BufferSize;
[MemoryPackInclude]
uint FlowId => tunnelTransportInfo.FlowId;
[MemoryPackConstructor] [MemoryPackConstructor]
SerializableTunnelTransportInfo(TunnelTransportWanPortInfo local, TunnelTransportWanPortInfo remote, string transactionId, TunnelProtocolType transportType, string transportName, TunnelDirection direction, bool ssl, byte bufferSize) SerializableTunnelTransportInfo(TunnelTransportWanPortInfo local, TunnelTransportWanPortInfo remote, string transactionId, TunnelProtocolType transportType, string transportName, TunnelDirection direction, bool ssl, byte bufferSize, uint flowid)
{ {
var tunnelTransportInfo = new TunnelTransportInfo var tunnelTransportInfo = new TunnelTransportInfo
{ {
@@ -371,6 +395,7 @@ namespace linker.config
Direction = direction, Direction = direction,
SSL = ssl, SSL = ssl,
BufferSize = bufferSize, BufferSize = bufferSize,
FlowId = flowid
}; };
this.tunnelTransportInfo = tunnelTransportInfo; this.tunnelTransportInfo = tunnelTransportInfo;
} }

View File

@@ -150,11 +150,14 @@ namespace linker.plugins.tunnel.messenger
if (signCaching.TryGet(tunnelTransportInfo.Remote.MachineId, out SignCacheInfo cache) && signCaching.TryGet(connection.Id, out SignCacheInfo cache1) && cache.GroupId == cache1.GroupId) if (signCaching.TryGet(tunnelTransportInfo.Remote.MachineId, out SignCacheInfo cache) && signCaching.TryGet(connection.Id, out SignCacheInfo cache1) && cache.GroupId == cache1.GroupId)
{ {
tunnelTransportInfo.Local.MachineName = cache1.MachineName;
tunnelTransportInfo.Remote.MachineName = cache.MachineName;
await messengerSender.SendOnly(new MessageRequestWrap await messengerSender.SendOnly(new MessageRequestWrap
{ {
Connection = cache.Connection, Connection = cache.Connection,
MessengerId = (ushort)TunnelMessengerIds.Begin, MessengerId = (ushort)TunnelMessengerIds.Begin,
Payload = connection.ReceiveRequestWrap.Payload Payload = MemoryPackSerializer.Serialize(tunnelTransportInfo)
}).ConfigureAwait(false); }).ConfigureAwait(false);
connection.Write(Helper.TrueArray); connection.Write(Helper.TrueArray);
} }
@@ -167,11 +170,13 @@ namespace linker.plugins.tunnel.messenger
TunnelTransportInfo tunnelTransportInfo = MemoryPackSerializer.Deserialize<TunnelTransportInfo>(connection.ReceiveRequestWrap.Payload.Span); TunnelTransportInfo tunnelTransportInfo = MemoryPackSerializer.Deserialize<TunnelTransportInfo>(connection.ReceiveRequestWrap.Payload.Span);
if (signCaching.TryGet(tunnelTransportInfo.Remote.MachineId, out SignCacheInfo cache) && signCaching.TryGet(connection.Id, out SignCacheInfo cache1) && cache.GroupId == cache1.GroupId) if (signCaching.TryGet(tunnelTransportInfo.Remote.MachineId, out SignCacheInfo cache) && signCaching.TryGet(connection.Id, out SignCacheInfo cache1) && cache.GroupId == cache1.GroupId)
{ {
tunnelTransportInfo.Local.MachineName = cache1.MachineName;
tunnelTransportInfo.Remote.MachineName = cache.MachineName;
await messengerSender.SendOnly(new MessageRequestWrap await messengerSender.SendOnly(new MessageRequestWrap
{ {
Connection = cache.Connection, Connection = cache.Connection,
MessengerId = (ushort)TunnelMessengerIds.Fail, MessengerId = (ushort)TunnelMessengerIds.Fail,
Payload = connection.ReceiveRequestWrap.Payload Payload = MemoryPackSerializer.Serialize(tunnelTransportInfo)
}).ConfigureAwait(false); }).ConfigureAwait(false);
} }
} }
@@ -183,11 +188,13 @@ namespace linker.plugins.tunnel.messenger
TunnelTransportInfo tunnelTransportInfo = MemoryPackSerializer.Deserialize<TunnelTransportInfo>(connection.ReceiveRequestWrap.Payload.Span); TunnelTransportInfo tunnelTransportInfo = MemoryPackSerializer.Deserialize<TunnelTransportInfo>(connection.ReceiveRequestWrap.Payload.Span);
if (signCaching.TryGet(tunnelTransportInfo.Remote.MachineId, out SignCacheInfo cache) && signCaching.TryGet(connection.Id, out SignCacheInfo cache1) && cache.GroupId == cache1.GroupId) if (signCaching.TryGet(tunnelTransportInfo.Remote.MachineId, out SignCacheInfo cache) && signCaching.TryGet(connection.Id, out SignCacheInfo cache1) && cache.GroupId == cache1.GroupId)
{ {
tunnelTransportInfo.Local.MachineName = cache1.MachineName;
tunnelTransportInfo.Remote.MachineName = cache.MachineName;
await messengerSender.SendOnly(new MessageRequestWrap await messengerSender.SendOnly(new MessageRequestWrap
{ {
Connection = cache.Connection, Connection = cache.Connection,
MessengerId = (ushort)TunnelMessengerIds.Success, MessengerId = (ushort)TunnelMessengerIds.Success,
Payload = connection.ReceiveRequestWrap.Payload Payload = MemoryPackSerializer.Serialize(tunnelTransportInfo)
}).ConfigureAwait(false); }).ConfigureAwait(false);
} }
} }