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>
|
<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>
|
||||||
@@ -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 \
|
||||||
|
|||||||
@@ -18,8 +18,18 @@ sidebar_position: 3
|
|||||||

|

|
||||||
|
|
||||||
|
|
||||||
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**,会冲突
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
>
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -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;
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
//正向连接,也就是它要连接我,那我就监听
|
//正向连接,也就是它要连接我,那我就监听
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
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;
|
||||||
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)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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('已操作!');
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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; }
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user