mirror of
https://github.com/snltty/linker.git
synced 2025-10-28 03:13:15 +08:00
测试基于端口映射的P2P连接
This commit is contained in:
@@ -16,14 +16,6 @@ sidebar_position: 1
|
||||
|
||||
<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、感谢支持
|
||||
|
||||
<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>
|
||||
@@ -56,9 +56,13 @@ systemctl enable linker
|
||||
5. debian `snltty/linker-debian-x64`、`snltty/linker-debian-arm64`,压缩约`70MB`、未压缩约`177MB`
|
||||
6. alpine `snltty/linker-musl-x64`、`snltty/linker-musl-arm64`,压缩约`19MB`、未压缩约`43MB`
|
||||
|
||||
#### 特别说明
|
||||
:::tip[特别说明]
|
||||
|
||||
1. 在容器中监听一个端口,宿主机无法访问,所以你需要把端口映射一下,比如 `-p 18000-18010:18000-18010`,预留这些端口,这样就可以使用这些端口做转发
|
||||
2. 在docker容器中创建虚拟网卡,是无法直接通过虚拟网卡访问宿主机的,你需要把端口映射一下,或者直接使用`host`网络模式
|
||||
|
||||
:::
|
||||
|
||||
#### 客户端
|
||||
```
|
||||
docker run -it -d --name linker \
|
||||
|
||||
@@ -18,8 +18,18 @@ sidebar_position: 3
|
||||

|
||||
|
||||
|
||||
1. 为目标设备设置一个IP地址,例如 **192.168.54.2**
|
||||
2. 填写目标设备的局域网IP。比如目标设备局域网IP为**192.168.56.55**,局域网IP是可选的,且各个设备之间,局域网IP段不可重复,比如,不能两个设备的局域网IP 都是 **192.168.56.x/24**
|
||||
1. 为目标设备设置一个IP地址,例如 **192.168.54.2**,每个客户端之间,填写相同网段的**网卡IP**,且掩码是**/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**,会冲突
|
||||
|
||||
:::
|
||||
|
||||
>
|
||||
|
||||

|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using linker.serializes;
|
||||
|
||||
using linker.config;
|
||||
using linker.plugins.serializes;
|
||||
using linker.tunnel.connection;
|
||||
using linker.tunnel.transport;
|
||||
using MemoryPack;
|
||||
@@ -12,9 +14,470 @@ namespace linker.Tests
|
||||
[TestMethod]
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,7 @@ namespace linker.tunnel
|
||||
private ITunnelAdapter tunnelAdapter;
|
||||
|
||||
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>>>();
|
||||
|
||||
public TunnelTransfer()
|
||||
@@ -181,7 +182,8 @@ namespace linker.tunnel
|
||||
TransportType = transport.ProtocolType,
|
||||
Local = localInfo.Result,
|
||||
Remote = remoteInfo.Result,
|
||||
SSL = transportItem.SSL
|
||||
SSL = transportItem.SSL,
|
||||
FlowId = Interlocked.Increment(ref flowid)
|
||||
};
|
||||
OnConnecting(tunnelTransportInfo);
|
||||
ParseRemoteEndPoint(tunnelTransportInfo);
|
||||
@@ -295,6 +297,7 @@ namespace linker.tunnel
|
||||
TunnelWanPortEndPoint ip = await compactTransfer.GetWanPortAsync(tunnelAdapter.LocalIP, info).ConfigureAwait(false);
|
||||
if (ip != null)
|
||||
{
|
||||
PortMapInfo portMapInfo = tunnelAdapter.PortMap ?? new PortMapInfo { LanPort = 0, WanPort = 0 };
|
||||
var config = tunnelAdapter.GetLocalConfig();
|
||||
return new TunnelTransportWanPortInfo
|
||||
{
|
||||
@@ -302,7 +305,9 @@ namespace linker.tunnel
|
||||
Remote = ip.Remote,
|
||||
LocalIps = config.LocalIps,
|
||||
RouteLevel = config.RouteLevel,
|
||||
MachineId = config.MachineId
|
||||
MachineId = config.MachineId,
|
||||
PortMapLan = portMapInfo.LanPort,
|
||||
PortMapWan = portMapInfo.WanPort,
|
||||
};
|
||||
}
|
||||
return null;
|
||||
|
||||
@@ -12,6 +12,8 @@ namespace linker.tunnel.adapter
|
||||
/// </summary>
|
||||
public IPAddress LocalIP { get; }
|
||||
|
||||
public PortMapInfo PortMap { get; }
|
||||
|
||||
/// <summary>
|
||||
/// ssl加密证书
|
||||
/// </summary>
|
||||
@@ -87,6 +89,12 @@ namespace linker.tunnel.adapter
|
||||
public string MachineId { get; set; }
|
||||
}
|
||||
|
||||
public sealed class PortMapInfo
|
||||
{
|
||||
public int WanPort { get; set; }
|
||||
public int LanPort { get; set; }
|
||||
}
|
||||
|
||||
public sealed class TunnelWanPortProtocolInfo
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -5,7 +5,6 @@ using System.Buffers;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace linker.tunnel.proxy
|
||||
{
|
||||
@@ -91,13 +90,6 @@ namespace linker.tunnel.proxy
|
||||
}
|
||||
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);
|
||||
if (token.Connection != null)
|
||||
{
|
||||
|
||||
@@ -111,6 +111,15 @@ namespace linker.tunnel.transport
|
||||
/// 我的名称
|
||||
/// </summary>
|
||||
public string MachineName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 固定端口,外网
|
||||
/// </summary>
|
||||
public int PortMapWan { get; set; }
|
||||
/// <summary>
|
||||
/// 固定端口,内网
|
||||
/// </summary>
|
||||
public int PortMapLan { get; set; }
|
||||
}
|
||||
|
||||
public sealed partial class TunnelTransportItemInfo
|
||||
@@ -200,6 +209,12 @@ namespace linker.tunnel.transport
|
||||
/// 缓冲区
|
||||
/// </summary>
|
||||
public byte BufferSize { get; set; } = 3;
|
||||
|
||||
/// <summary>
|
||||
/// 流id
|
||||
/// </summary>
|
||||
public uint FlowId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 目标ip列表
|
||||
/// </summary>
|
||||
|
||||
@@ -104,7 +104,7 @@ namespace linker.tunnel.transport
|
||||
if (tunnelTransportInfo.SSL && tunnelAdapter.Certificate == null)
|
||||
{
|
||||
LoggerHelper.Instance.Error($"{Name}->ssl Certificate not found");
|
||||
await OnSendConnectSuccess(tunnelTransportInfo).ConfigureAwait(false);
|
||||
await OnSendConnectFail(tunnelTransportInfo).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
//正向连接,也就是它要连接我,那我就监听
|
||||
|
||||
@@ -88,7 +88,7 @@ namespace linker.tunnel.transport
|
||||
if (tunnelTransportInfo.SSL && tunnelAdapter.Certificate == null)
|
||||
{
|
||||
LoggerHelper.Instance.Error($"{Name}->ssl Certificate not found");
|
||||
await OnSendConnectSuccess(tunnelTransportInfo).ConfigureAwait(false);
|
||||
await OnSendConnectFail(tunnelTransportInfo).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
ITunnelConnection connection = await ConnectForward(tunnelTransportInfo, TunnelMode.Server).ConfigureAwait(false);
|
||||
|
||||
346
linker.tunnel/transport/TransportTcpPortMap.cs
Normal file
346
linker.tunnel/transport/TransportTcpPortMap.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,4 @@
|
||||
using linker.libs;
|
||||
using linker.libs.extends;
|
||||
using System.Diagnostics;
|
||||
using System.Net;
|
||||
|
||||
namespace linker.tunnel.wanport
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<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="api"><Api></Api></div>
|
||||
<div class="server"><Server></Server></div>
|
||||
|
||||
@@ -3,11 +3,7 @@
|
||||
<div>
|
||||
<el-form ref="ruleFormRef" :model="state.ruleForm" :rules="state.rules" label-width="auto">
|
||||
<el-form-item label="" prop="alert">
|
||||
<div>
|
||||
<p>网关层级自动计算,可能并不符合实际情况</p>
|
||||
<p>你可以调整层级加减,得到最终层级数以符合你的实际环境</p>
|
||||
<p>这有助于提高TCP打洞成功率</p>
|
||||
</div>
|
||||
<div>网关层级为你的设备与外网的距离,你可以手动调整数值</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="">
|
||||
<el-row>
|
||||
@@ -23,6 +19,23 @@
|
||||
</el-col>
|
||||
</el-row>
|
||||
</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">
|
||||
<div class="t-c w-100">
|
||||
<el-button @click="state.show = false">取消</el-button>
|
||||
@@ -51,6 +64,8 @@ export default {
|
||||
ruleForm: {
|
||||
RouteLevel: tunnel.value.current.RouteLevel,
|
||||
RouteLevelPlus: tunnel.value.current.RouteLevelPlus,
|
||||
PortMapWan: tunnel.value.current.PortMapWan,
|
||||
PortMapLan: tunnel.value.current.PortMapLan,
|
||||
},
|
||||
rules: {}
|
||||
});
|
||||
@@ -66,6 +81,8 @@ export default {
|
||||
const json = JSON.parse(JSON.stringify(tunnel.value.current));
|
||||
json.RouteLevel = +state.ruleForm.RouteLevel;
|
||||
json.RouteLevelPlus = +state.ruleForm.RouteLevelPlus;
|
||||
json.PortMapWan = +state.ruleForm.PortMapWan;
|
||||
json.PortMapLan = +state.ruleForm.PortMapLan;
|
||||
setTunnelRouteLevel(json).then(() => {
|
||||
state.show = false;
|
||||
ElMessage.success('已操作!');
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace linker.plugins.tunnel
|
||||
{
|
||||
public IPAddress LocalIP => clientSignInState.Connection?.LocalAddress.Address ?? IPAddress.Any;
|
||||
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 MessengerSender messengerSender;
|
||||
@@ -104,7 +104,6 @@ namespace linker.plugins.tunnel
|
||||
}
|
||||
|
||||
|
||||
|
||||
public NetworkInfo GetLocalConfig()
|
||||
{
|
||||
var excludeips = excludeIPTransfer.Get();
|
||||
@@ -180,6 +179,5 @@ namespace linker.plugins.tunnel
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ using System.Collections.Concurrent;
|
||||
using linker.tunnel.wanport;
|
||||
using linker.client.config;
|
||||
using linker.plugins.client;
|
||||
using linker.plugins.server;
|
||||
using linker.plugins.capi;
|
||||
using linker.plugins.messenger;
|
||||
using linker.plugins.tunnel.excludeip;
|
||||
@@ -87,7 +86,6 @@ namespace linker.plugins.tunnel
|
||||
List<TunnelWanPortInfo> info = param.Content.DeJson<List<TunnelWanPortInfo>>();
|
||||
tunnelMessengerAdapter.SetTunnelWanPortProtocols(info,true);
|
||||
return true;
|
||||
|
||||
}
|
||||
/// <summary>
|
||||
/// 设置网关层级
|
||||
@@ -144,7 +142,6 @@ namespace linker.plugins.tunnel
|
||||
ExcludeIPItem[] info = param.Content.DeJson<ExcludeIPItem[]>();
|
||||
excludeIPTransfer.SettExcludeIPs(info);
|
||||
}
|
||||
|
||||
public sealed class TunnelListInfo
|
||||
{
|
||||
public ConcurrentDictionary<string, TunnelTransportRouteLevelInfo> List { get; set; }
|
||||
|
||||
@@ -5,6 +5,7 @@ using linker.plugins.client;
|
||||
using linker.plugins.messenger;
|
||||
using linker.plugins.tunnel.messenger;
|
||||
using linker.tunnel.adapter;
|
||||
using linker.tunnel.transport;
|
||||
using linker.tunnel.wanport;
|
||||
using MemoryPack;
|
||||
using System.Collections.Concurrent;
|
||||
@@ -20,7 +21,7 @@ namespace linker.plugins.tunnel
|
||||
private readonly MessengerSender messengerSender;
|
||||
private readonly RunningConfigTransfer runningConfigTransfer;
|
||||
private readonly ITunnelAdapter tunnelAdapter;
|
||||
|
||||
private readonly TransportTcpPortMap transportTcpPortMap;
|
||||
|
||||
|
||||
private uint version = 0;
|
||||
@@ -28,7 +29,7 @@ namespace linker.plugins.tunnel
|
||||
private ConcurrentDictionary<string, TunnelTransportRouteLevelInfo> configs = new ConcurrentDictionary<string, TunnelTransportRouteLevelInfo>();
|
||||
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.running = running;
|
||||
@@ -36,12 +37,15 @@ namespace linker.plugins.tunnel
|
||||
this.messengerSender = messengerSender;
|
||||
this.runningConfigTransfer = runningConfigTransfer;
|
||||
this.tunnelAdapter = tunnelAdapter;
|
||||
this.transportTcpPortMap = transportTcpPortMap;
|
||||
|
||||
InitRouteLevel();
|
||||
|
||||
InitConfig();
|
||||
|
||||
TestQuic();
|
||||
|
||||
RefreshPortMap();
|
||||
}
|
||||
|
||||
private void InitConfig()
|
||||
@@ -89,8 +93,11 @@ namespace linker.plugins.tunnel
|
||||
public void OnLocalRouteLevel(TunnelTransportRouteLevelInfo tunnelTransportFileConfigInfo)
|
||||
{
|
||||
running.Data.Tunnel.RouteLevelPlus = tunnelTransportFileConfigInfo.RouteLevelPlus;
|
||||
running.Data.Tunnel.PortMapWan = tunnelTransportFileConfigInfo.PortMapWan;
|
||||
running.Data.Tunnel.PortMapLan = tunnelTransportFileConfigInfo.PortMapLan;
|
||||
running.Data.Update();
|
||||
GetRemoteRouteLevel();
|
||||
RefreshPortMap();
|
||||
}
|
||||
/// <summary>
|
||||
/// 收到别人发给我的修改我的信息
|
||||
@@ -134,6 +141,8 @@ namespace linker.plugins.tunnel
|
||||
MachineId = config.Data.Client.Id,
|
||||
RouteLevel = config.Data.Client.Tunnel.RouteLevel,
|
||||
RouteLevelPlus = running.Data.Tunnel.RouteLevelPlus,
|
||||
PortMapWan = running.Data.Tunnel.PortMapWan,
|
||||
PortMapLan = running.Data.Tunnel.PortMapLan,
|
||||
NeedReboot = reboot
|
||||
};
|
||||
}
|
||||
@@ -175,5 +184,11 @@ namespace linker.plugins.tunnel
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void RefreshPortMap()
|
||||
{
|
||||
_ = transportTcpPortMap.Listen(running.Data.Tunnel.PortMapLan);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,11 +49,13 @@ namespace linker.plugins.tunnel
|
||||
serviceCollection.AddSingleton<TunnelWanPortProtocolLinkerTcp>();
|
||||
serviceCollection.AddSingleton<TunnelWanPortProtocolStun>();
|
||||
|
||||
|
||||
//打洞协议
|
||||
serviceCollection.AddSingleton<TunnelTransfer>();
|
||||
serviceCollection.AddSingleton<TunnelTransportTcpNutssb>();
|
||||
serviceCollection.AddSingleton<TransportMsQuic>();
|
||||
serviceCollection.AddSingleton<TransportTcpP2PNAT>();
|
||||
serviceCollection.AddSingleton<TransportTcpPortMap>();
|
||||
|
||||
|
||||
serviceCollection.AddSingleton<TunnelExcludeIPTransfer>();
|
||||
@@ -101,6 +103,7 @@ namespace linker.plugins.tunnel
|
||||
|
||||
TunnelExcludeIPTransfer excludeIPTransfer = serviceProvider.GetService<TunnelExcludeIPTransfer>();
|
||||
excludeIPTransfer.Load(assemblies);
|
||||
|
||||
}
|
||||
|
||||
public void UseServer(ServiceProvider serviceProvider, FileConfig config, Assembly[] assemblies)
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace linker.client.config
|
||||
/// <summary>
|
||||
/// 附加的网关层级
|
||||
/// </summary>
|
||||
public int RouteLevelPlus { get; set; } = 0;
|
||||
public int RouteLevelPlus { get; set; }
|
||||
/// <summary>
|
||||
/// 打洞排除IP列表
|
||||
/// </summary>
|
||||
@@ -38,6 +38,9 @@ namespace linker.client.config
|
||||
/// 打洞协议列表
|
||||
/// </summary>
|
||||
public List<TunnelTransportItemInfo> Transports { get; set; } = new List<TunnelTransportItemInfo>();
|
||||
|
||||
public int PortMapWan { get; set; }
|
||||
public int PortMapLan { get; set; }
|
||||
}
|
||||
|
||||
[MemoryPackable]
|
||||
@@ -73,10 +76,13 @@ namespace linker.config
|
||||
public sealed partial class TunnelTransportRouteLevelInfo
|
||||
{
|
||||
public string MachineId { get; set; }
|
||||
public int RouteLevel { get; set; } = 0;
|
||||
public int RouteLevelPlus { get; set; } = 0;
|
||||
public int RouteLevel { get; set; }
|
||||
public int RouteLevelPlus { 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]
|
||||
string MachineName => tunnelTransportWanPortInfo.MachineName;
|
||||
|
||||
[MemoryPackInclude]
|
||||
int PortMapWan => tunnelTransportWanPortInfo.PortMapWan;
|
||||
|
||||
[MemoryPackInclude]
|
||||
int PortMapLan => tunnelTransportWanPortInfo.PortMapLan;
|
||||
|
||||
[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;
|
||||
}
|
||||
|
||||
@@ -259,7 +281,6 @@ namespace linker.config
|
||||
}
|
||||
|
||||
|
||||
|
||||
[MemoryPackable]
|
||||
public readonly partial struct SerializableTunnelTransportItemInfo
|
||||
{
|
||||
@@ -357,9 +378,12 @@ namespace linker.config
|
||||
[MemoryPackInclude]
|
||||
byte BufferSize => tunnelTransportInfo.BufferSize;
|
||||
|
||||
[MemoryPackInclude]
|
||||
uint FlowId => tunnelTransportInfo.FlowId;
|
||||
|
||||
|
||||
[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
|
||||
{
|
||||
@@ -371,6 +395,7 @@ namespace linker.config
|
||||
Direction = direction,
|
||||
SSL = ssl,
|
||||
BufferSize = bufferSize,
|
||||
FlowId = flowid
|
||||
};
|
||||
this.tunnelTransportInfo = tunnelTransportInfo;
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
tunnelTransportInfo.Local.MachineName = cache1.MachineName;
|
||||
tunnelTransportInfo.Remote.MachineName = cache.MachineName;
|
||||
|
||||
await messengerSender.SendOnly(new MessageRequestWrap
|
||||
{
|
||||
Connection = cache.Connection,
|
||||
MessengerId = (ushort)TunnelMessengerIds.Begin,
|
||||
Payload = connection.ReceiveRequestWrap.Payload
|
||||
Payload = MemoryPackSerializer.Serialize(tunnelTransportInfo)
|
||||
}).ConfigureAwait(false);
|
||||
connection.Write(Helper.TrueArray);
|
||||
}
|
||||
@@ -167,11 +170,13 @@ namespace linker.plugins.tunnel.messenger
|
||||
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)
|
||||
{
|
||||
tunnelTransportInfo.Local.MachineName = cache1.MachineName;
|
||||
tunnelTransportInfo.Remote.MachineName = cache.MachineName;
|
||||
await messengerSender.SendOnly(new MessageRequestWrap
|
||||
{
|
||||
Connection = cache.Connection,
|
||||
MessengerId = (ushort)TunnelMessengerIds.Fail,
|
||||
Payload = connection.ReceiveRequestWrap.Payload
|
||||
Payload = MemoryPackSerializer.Serialize(tunnelTransportInfo)
|
||||
}).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
@@ -183,11 +188,13 @@ namespace linker.plugins.tunnel.messenger
|
||||
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)
|
||||
{
|
||||
tunnelTransportInfo.Local.MachineName = cache1.MachineName;
|
||||
tunnelTransportInfo.Remote.MachineName = cache.MachineName;
|
||||
await messengerSender.SendOnly(new MessageRequestWrap
|
||||
{
|
||||
Connection = cache.Connection,
|
||||
MessengerId = (ushort)TunnelMessengerIds.Success,
|
||||
Payload = connection.ReceiveRequestWrap.Payload
|
||||
Payload = MemoryPackSerializer.Serialize(tunnelTransportInfo)
|
||||
}).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user