From 8b47c5533c1d829dfa83303009894e6ef75b3021 Mon Sep 17 00:00:00 2001 From: snltty <1069410172@qq.com> Date: Tue, 2 Jul 2024 16:50:59 +0800 Subject: [PATCH] sync --- linker.tunnel/TunnelTransfer.cs | 161 ++++++++++++------ linker.tunnel/adapter/ITunnelAdapter.cs | 22 ++- linker.tunnel/transport/ITunnelTransport.cs | 32 ++++ linker.tunnel/transport/TransportMsQuic.cs | 12 +- linker.tunnel/transport/TransportTcpNutssb.cs | 10 ++ linker.tunnel/transport/TransportTcpP2PNAT.cs | 27 ++- linker.tunnel/transport/TransportUdp.cs | 11 ++ ...elWanPort.cs => ITunnelWanPortProtocol.cs} | 11 +- linker.tunnel/wanport/TunnelWanPortLinker.cs | 54 ------ .../wanport/TunnelWanPortProtocolLinker.cs | 109 ++++++++++++ ...rtStun.cs => TunnelWanPortProtocolStun.cs} | 8 +- .../wanport/TunnelWanPortTransfer.cs | 52 +++--- linker.web/src/views/devices/ForwardEdit.vue | 16 +- linker.web/src/views/devices/SForwardEdit.vue | 14 +- .../src/views/settings/RelayServers.vue | 8 +- linker.web/src/views/settings/Transports.vue | 4 +- .../src/views/settings/TunnelServers.vue | 18 +- .../PublishProfiles/FolderProfile.pubxml | 6 +- .../PublishProfiles/FolderProfile.pubxml.user | 2 +- linker/linker.csproj.user | 2 +- linker/plugins/relay/RelayApiController.cs | 4 +- linker/plugins/relay/RelayTransfer.cs | 16 +- linker/plugins/relay/config/Config.cs | 20 +-- .../plugins/relay/messenger/RelayMessenger.cs | 4 +- linker/plugins/relay/transport/ITransport.cs | 2 +- .../relay/transport/TransportSelfHost.cs | 2 +- linker/plugins/tunnel/TunnelAdapter.cs | 16 +- linker/plugins/tunnel/TunnelApiController.cs | 2 +- linker/plugins/tunnel/TunnelConfigTransfer.cs | 4 +- linker/plugins/tunnel/TunnelStartup.cs | 12 +- linker/plugins/tunnel/config/Config.cs | 58 ++++++- .../tunnel/messenger/TunnelMessenger.cs | 9 +- linker/server/TcpServer.cs | 65 +++++-- publish.bat | 4 +- 34 files changed, 560 insertions(+), 237 deletions(-) rename linker.tunnel/wanport/{ITunnelWanPort.cs => ITunnelWanPortProtocol.cs} (85%) delete mode 100644 linker.tunnel/wanport/TunnelWanPortLinker.cs create mode 100644 linker.tunnel/wanport/TunnelWanPortProtocolLinker.cs rename linker.tunnel/wanport/{TunnelWanPortStun.cs => TunnelWanPortProtocolStun.cs} (90%) diff --git a/linker.tunnel/TunnelTransfer.cs b/linker.tunnel/TunnelTransfer.cs index d4f82d16..631f8895 100644 --- a/linker.tunnel/TunnelTransfer.cs +++ b/linker.tunnel/TunnelTransfer.cs @@ -14,7 +14,7 @@ namespace linker.tunnel { private List transports; private TunnelWanPortTransfer compactTransfer; - private ITunnelAdapter tunnelAdapter ; + private ITunnelAdapter tunnelAdapter; private ConcurrentDictionary connectingDic = new ConcurrentDictionary(); private Dictionary>> OnConnected { get; } = new Dictionary>>(); @@ -42,11 +42,38 @@ namespace linker.tunnel } var transportItems = tunnelAdapter.GetTunnelTransports(); - transportItems = transportItems.Concat(transports.Select(c => new TunnelTransportItemInfo { Label = c.Label, Name = c.Name, ProtocolType = c.ProtocolType.ToString() })) + transportItems = transportItems.Concat(transports.Select(c => new TunnelTransportItemInfo + { + Label = c.Label, + Name = c.Name, + ProtocolType = c.ProtocolType.ToString(), + Reverse = c.Reverse, + DisableReverse = c.DisableReverse, + SSL = c.SSL, + DisableSSL = c.DisableSSL + })) .Distinct(new TunnelTransportItemInfoEqualityComparer()) - .Where(c=> transports.Select(c=>c.Name).Contains(c.Name)) + .Where(c => transports.Select(c => c.Name).Contains(c.Name)) .ToList(); + foreach (var item in transportItems) + { + var transport = transports.FirstOrDefault(c => c.Name == item.Name); + if (transport != null) + { + item.DisableReverse = transport.DisableReverse; + item.DisableSSL = transport.DisableSSL; + if (transport.DisableReverse) + { + item.Reverse = transport.Reverse; + } + if (transport.DisableSSL) + { + item.SSL = transport.SSL; + } + } + } + tunnelAdapter.SetTunnelTransports(transportItems); @@ -98,66 +125,87 @@ namespace linker.tunnel try { - foreach (TunnelTransportItemInfo transportItem in tunnelAdapter.GetTunnelTransports().Where(c => c.Disabled == false)) + foreach (var wanPortProtocol in tunnelAdapter.GetTunnelWanPortProtocols().Where(c => c.Disabled == false && string.IsNullOrWhiteSpace(c.Host) == false)) { - ITunnelTransport transport = transports.FirstOrDefault(c => c.Name == transportItem.Name); - if (transport == null) continue; - - TunnelTransportInfo tunnelTransportInfo = null; - //是否在失败后尝试反向连接 - int times = transportItem.Reverse ? 1 : 0; - for (int i = 0; i <= times; i++) + foreach (TunnelTransportItemInfo transportItem in tunnelAdapter.GetTunnelTransports().Where(c => c.Disabled == false)) { - try + ITunnelTransport transport = transports.FirstOrDefault(c => c.Name == transportItem.Name); + //找不到这个打洞协议 + if (transport == null) { - //获取自己的外网ip - TunnelTransportWanPortInfo localInfo = await GetLocalInfo(); - if (localInfo == null) - { - LoggerHelper.Instance.Error($"tunnel {transport.Name} get local external ip fail "); - break; - } - LoggerHelper.Instance.Info($"tunnel {transport.Name} got local external ip {localInfo.ToJson()}"); - //获取对方的外网ip - TunnelTransportWanPortInfo remoteInfo = await tunnelAdapter.GetRemoteWanPort(remoteMachineId); - if (remoteInfo == null) - { - LoggerHelper.Instance.Error($"tunnel {transport.Name} get remote {remoteMachineId} external ip fail "); - break; - } - LoggerHelper.Instance.Info($"tunnel {transport.Name} got remote external ip {remoteInfo.ToJson()}"); + continue; + } + //这个打洞协议不支持这个外网端口协议 + if((transport.AllowWanPortProtocolType & wanPortProtocol.ProtocolType) != wanPortProtocol.ProtocolType) + { + continue; + } - tunnelTransportInfo = new TunnelTransportInfo + TunnelTransportInfo tunnelTransportInfo = null; + //是否在失败后尝试反向连接 + int times = transportItem.Reverse ? 1 : 0; + for (int i = 0; i <= times; i++) + { + try { - Direction = (TunnelDirection)i, - TransactionId = transactionId, - TransportName = transport.Name, - TransportType = transport.ProtocolType, - Local = localInfo, - Remote = remoteInfo, - SSL = transportItem.SSL - }; - OnConnecting(tunnelTransportInfo); - ParseRemoteEndPoint(tunnelTransportInfo); - ITunnelConnection connection = await transport.ConnectAsync(tunnelTransportInfo); - if (connection != null) + //获取自己的外网ip + Task localInfo = GetLocalInfo(wanPortProtocol); + //获取对方的外网ip + Task remoteInfo = tunnelAdapter.GetRemoteWanPort(new TunnelWanPortProtocolInfo + { + MachineId = remoteMachineId, + ProtocolType = wanPortProtocol.ProtocolType, + Type = wanPortProtocol.Type, + }); + await Task.WhenAll(localInfo, remoteInfo); + + if (localInfo.Result == null) + { + LoggerHelper.Instance.Error($"tunnel {transport.Name} get local external ip fail "); + break; + } + + if (remoteInfo.Result == null) + { + LoggerHelper.Instance.Error($"tunnel {transport.Name} get remote {remoteMachineId} external ip fail "); + break; + } + LoggerHelper.Instance.Info($"tunnel {transport.Name} got local external ip {localInfo.ToJson()}"); + LoggerHelper.Instance.Info($"tunnel {transport.Name} got remote external ip {remoteInfo.ToJson()}"); + + + tunnelTransportInfo = new TunnelTransportInfo + { + Direction = (TunnelDirection)i, + TransactionId = transactionId, + TransportName = transport.Name, + TransportType = transport.ProtocolType, + Local = localInfo.Result, + Remote = remoteInfo.Result, + SSL = transportItem.SSL + }; + OnConnecting(tunnelTransportInfo); + ParseRemoteEndPoint(tunnelTransportInfo); + ITunnelConnection connection = await transport.ConnectAsync(tunnelTransportInfo); + if (connection != null) + { + _OnConnected(connection); + return connection; + } + } + catch (Exception ex) { - _OnConnected(connection); - return connection; + if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG) + { + LoggerHelper.Instance.Error(ex); + } } } - catch (Exception ex) + if (tunnelTransportInfo != null) { - if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG) - { - LoggerHelper.Instance.Error(ex); - } + OnConnectFail(tunnelTransportInfo); } } - if (tunnelTransportInfo != null) - { - OnConnectFail(tunnelTransportInfo); - } } } catch (Exception ex) @@ -239,18 +287,19 @@ namespace linker.tunnel /// 获取自己的外网IP,给别人调用 /// /// - public async Task GetWanPort() + public async Task GetWanPort(TunnelWanPortProtocolInfo _info) { - return await GetLocalInfo(); + TunnelWanPortInfo info = tunnelAdapter.GetTunnelWanPortProtocols().FirstOrDefault(c => c.Type == _info.Type && c.ProtocolType == _info.ProtocolType); + return await GetLocalInfo(info); } /// /// 获取自己的外网IP /// /// - private async Task GetLocalInfo() + private async Task GetLocalInfo(TunnelWanPortInfo info) { - TunnelWanPortEndPoint ip = await compactTransfer.GetWanPortAsync(tunnelAdapter.LocalIP); + TunnelWanPortEndPoint ip = await compactTransfer.GetWanPortAsync(tunnelAdapter.LocalIP, info); if (ip != null) { var config = tunnelAdapter.GetLocalConfig(); diff --git a/linker.tunnel/adapter/ITunnelAdapter.cs b/linker.tunnel/adapter/ITunnelAdapter.cs index 770a74a3..5f48fe6c 100644 --- a/linker.tunnel/adapter/ITunnelAdapter.cs +++ b/linker.tunnel/adapter/ITunnelAdapter.cs @@ -21,12 +21,12 @@ namespace linker.tunnel.adapter /// 获取外网端口协议列表 /// /// - public List GetTunnelWanPortCompacts(); + public List GetTunnelWanPortProtocols(); /// /// 保存外网端口协议列表 /// /// - public void SetTunnelWanPortCompacts(List compacts); + public void SetTunnelWanPortProtocols(List protocols); /// /// 获取打洞协议列表 @@ -49,7 +49,7 @@ namespace linker.tunnel.adapter /// /// /// - public Task GetRemoteWanPort(string remoteMachineId); + public Task GetRemoteWanPort(TunnelWanPortProtocolInfo info); /// /// 发送开始打洞 @@ -86,4 +86,20 @@ namespace linker.tunnel.adapter /// public string MachineId { get; set; } } + + public sealed class TunnelWanPortProtocolInfo + { + /// + /// 类别 + /// + public TunnelWanPortType Type { get; set; } + /// + /// 协议 + /// + public TunnelWanPortProtocolType ProtocolType { get; set; } = TunnelWanPortProtocolType.Udp; + /// + /// 本机名 + /// + public string MachineId { get; set; } + } } diff --git a/linker.tunnel/transport/ITunnelTransport.cs b/linker.tunnel/transport/ITunnelTransport.cs index 59bbdbdd..4edde1fc 100644 --- a/linker.tunnel/transport/ITunnelTransport.cs +++ b/linker.tunnel/transport/ITunnelTransport.cs @@ -1,13 +1,43 @@ using linker.tunnel.connection; +using linker.tunnel.wanport; using System.Net; namespace linker.tunnel.transport { public interface ITunnelTransport { + /// + /// 打洞协议名 + /// public string Name { get; } + /// + /// 打洞协议说明 + /// public string Label { get; } + /// + /// 隧道协议 + /// public TunnelProtocolType ProtocolType { get; } + /// + /// 允许哪些端口协议 + /// + public TunnelWanPortProtocolType AllowWanPortProtocolType { get; } + /// + /// 是否反向打洞 + /// + public bool Reverse { get; } + /// + /// 是否允许修改反向打洞配置 + /// + public bool DisableReverse { get; } + /// + /// 是否ssl + /// + public bool SSL { get; } + /// + /// 是否允许修改ssl配置 + /// + public bool DisableSSL { get; } /// /// 发送连接开始信息 @@ -91,7 +121,9 @@ namespace linker.tunnel.transport public bool Disabled { get; set; } = false; public bool Reverse { get; set; } = true; + public bool DisableReverse { get; set; } = false; public bool SSL { get; set; } = true; + public bool DisableSSL { get; set; } = false; public byte BufferSize { get; set; } = 4; } diff --git a/linker.tunnel/transport/TransportMsQuic.cs b/linker.tunnel/transport/TransportMsQuic.cs index f4d04ccd..32b2aed7 100644 --- a/linker.tunnel/transport/TransportMsQuic.cs +++ b/linker.tunnel/transport/TransportMsQuic.cs @@ -2,7 +2,6 @@ using linker.tunnel.connection; using linker.libs; using linker.libs.extends; -using System.Buffers; using System.Collections.Concurrent; using System.Net; using System.Net.Quic; @@ -10,6 +9,7 @@ using System.Net.Security; using System.Net.Sockets; using System.Security.Authentication; using System.Text; +using linker.tunnel.wanport; namespace linker.tunnel.transport { @@ -20,12 +20,22 @@ namespace linker.tunnel.transport public string Label => "MsQuic,win10+、linux"; public TunnelProtocolType ProtocolType => TunnelProtocolType.Quic; + public TunnelWanPortProtocolType AllowWanPortProtocolType => TunnelWanPortProtocolType.Udp; + public bool Reverse => true; + + public bool DisableReverse => false; + + public bool SSL => true; + + public bool DisableSSL => true; + public Func> OnSendConnectBegin { get; set; } = async (info) => { return await Task.FromResult(false); }; public Func OnSendConnectFail { get; set; } = async (info) => { await Task.CompletedTask; }; public Func OnSendConnectSuccess { get; set; } = async (info) => { await Task.CompletedTask; }; public Action OnConnected { get; set; } = (state) => { }; + private ConcurrentDictionary stateDic = new ConcurrentDictionary(); private byte[] authBytes = Encoding.UTF8.GetBytes($"{Helper.GlobalString}.ttl"); diff --git a/linker.tunnel/transport/TransportTcpNutssb.cs b/linker.tunnel/transport/TransportTcpNutssb.cs index 0edcda2e..7536b2fe 100644 --- a/linker.tunnel/transport/TransportTcpNutssb.cs +++ b/linker.tunnel/transport/TransportTcpNutssb.cs @@ -8,6 +8,7 @@ using System.Net.Security; using System.Net.Sockets; using System.Security.Authentication; using System.Security.Cryptography.X509Certificates; +using linker.tunnel.wanport; namespace linker.tunnel.transport { @@ -16,6 +17,15 @@ namespace linker.tunnel.transport public string Name => "TcpNutssb"; public string Label => "TCP、低TTL"; public TunnelProtocolType ProtocolType => TunnelProtocolType.Tcp; + public TunnelWanPortProtocolType AllowWanPortProtocolType => TunnelWanPortProtocolType.Udp; + public bool Reverse => true; + + public bool DisableReverse => false; + + public bool SSL => true; + + public bool DisableSSL => false; + /// /// 发送开始连接消息 diff --git a/linker.tunnel/transport/TransportTcpP2PNAT.cs b/linker.tunnel/transport/TransportTcpP2PNAT.cs index 99daee6d..fe530572 100644 --- a/linker.tunnel/transport/TransportTcpP2PNAT.cs +++ b/linker.tunnel/transport/TransportTcpP2PNAT.cs @@ -8,6 +8,7 @@ using System.Net.Sockets; using System.Security.Authentication; using System.Security.Cryptography.X509Certificates; using System.Text; +using linker.tunnel.wanport; namespace linker.tunnel.transport { @@ -16,6 +17,14 @@ namespace linker.tunnel.transport public string Name => "TcpP2PNAT"; public string Label => "TCP、同时打开"; public TunnelProtocolType ProtocolType => TunnelProtocolType.Tcp; + public TunnelWanPortProtocolType AllowWanPortProtocolType => TunnelWanPortProtocolType.Tcp; + public bool Reverse => false; + + public bool DisableReverse => true; + + public bool SSL => true; + + public bool DisableSSL => false; /// /// 发送开始连接消息 @@ -56,6 +65,7 @@ namespace linker.tunnel.transport { return null; } + await Task.Delay(50); ITunnelConnection connection = await ConnectForward(tunnelTransportInfo, TunnelMode.Client); if (connection != null) { @@ -110,7 +120,7 @@ namespace linker.tunnel.transport try { targetSocket.KeepAlive(); - targetSocket.ReuseBind(new IPEndPoint(IPAddress.Any, tunnelTransportInfo.Local.Local.Port)); + targetSocket.ReuseBind(new IPEndPoint(tunnelTransportInfo.Local.Local.Address, tunnelTransportInfo.Local.Local.Port)); if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG) { @@ -137,6 +147,12 @@ namespace linker.tunnel.transport private async Task TcpClient(TunnelTransportInfo state, Socket socket) { + //随便发个消息看对方有没有收到 + await socket.SendAsync(authBytes); + //如果对方收到,会回个消息,不管是啥,回了就行 + int length = await socket.ReceiveAsync(new byte[1024]); + if (length == 0) return null; + //需要ssl SslStream sslStream = null; if (state.SSL) @@ -167,6 +183,15 @@ namespace linker.tunnel.transport { try { + //对方会随便发个消息,不管是啥 + int length = await socket.ReceiveAsync(new byte[1024]); + if (length == 0) + { + return null; + } + //回个消息给它就完了 + await socket.SendAsync(endBytes); + socket.KeepAlive(); SslStream sslStream = null; if (state.SSL) diff --git a/linker.tunnel/transport/TransportUdp.cs b/linker.tunnel/transport/TransportUdp.cs index aac1ccb2..b7aa9038 100644 --- a/linker.tunnel/transport/TransportUdp.cs +++ b/linker.tunnel/transport/TransportUdp.cs @@ -5,6 +5,7 @@ using System.Collections.Concurrent; using System.Net; using System.Net.Sockets; using System.Text; +using linker.tunnel.wanport; namespace linker.tunnel.transport { @@ -15,12 +16,22 @@ namespace linker.tunnel.transport public string Label => "udp"; public TunnelProtocolType ProtocolType => TunnelProtocolType.Udp; + public TunnelWanPortProtocolType AllowWanPortProtocolType => TunnelWanPortProtocolType.Udp; + public bool Reverse => true; + + public bool DisableReverse => false; + + public bool SSL => true; + + public bool DisableSSL => false; + public Func> OnSendConnectBegin { get; set; } = async (info) => { return await Task.FromResult(false); }; public Func OnSendConnectFail { get; set; } = async (info) => { await Task.CompletedTask; }; public Func OnSendConnectSuccess { get; set; } = async (info) => { await Task.CompletedTask; }; public Action OnConnected { get; set; } = (state) => { }; + private byte[] authBytes = Encoding.UTF8.GetBytes($"{Helper.GlobalString}.ttl"); private byte[] endBytes = Encoding.UTF8.GetBytes($"{Helper.GlobalString}.end"); diff --git a/linker.tunnel/wanport/ITunnelWanPort.cs b/linker.tunnel/wanport/ITunnelWanPortProtocol.cs similarity index 85% rename from linker.tunnel/wanport/ITunnelWanPort.cs rename to linker.tunnel/wanport/ITunnelWanPortProtocol.cs index 61ea70e3..072ec031 100644 --- a/linker.tunnel/wanport/ITunnelWanPort.cs +++ b/linker.tunnel/wanport/ITunnelWanPortProtocol.cs @@ -5,10 +5,11 @@ namespace linker.tunnel.wanport /// /// 外网端口协议 /// - public interface ITunnelWanPort + public interface ITunnelWanPortProtocol { public string Name { get; } public TunnelWanPortType Type { get; } + public TunnelWanPortProtocolType ProtocolType { get; } /// /// 获取外网端口 /// @@ -39,6 +40,7 @@ namespace linker.tunnel.wanport /// 协议类别 /// public TunnelWanPortType Type { get; set; } + public TunnelWanPortProtocolType ProtocolType { get; set; } = TunnelWanPortProtocolType.Udp; /// /// 地址 /// @@ -55,6 +57,13 @@ namespace linker.tunnel.wanport Stun = 1 } + [Flags] + public enum TunnelWanPortProtocolType : byte + { + Tcp = 1, + Udp = 2, + } + public sealed class TunnelWanPortTypeInfo { public TunnelWanPortType Value { get; set; } diff --git a/linker.tunnel/wanport/TunnelWanPortLinker.cs b/linker.tunnel/wanport/TunnelWanPortLinker.cs deleted file mode 100644 index cb451190..00000000 --- a/linker.tunnel/wanport/TunnelWanPortLinker.cs +++ /dev/null @@ -1,54 +0,0 @@ -using linker.libs.extends; -using System.Net; -using System.Net.Sockets; - -namespace linker.tunnel.wanport -{ - public sealed class TunnelWanPortLinker : ITunnelWanPort - { - public string Name => "默认"; - public TunnelWanPortType Type => TunnelWanPortType.Linker; - - public TunnelWanPortLinker() - { - } - - public async Task GetAsync(IPEndPoint server) - { - UdpClient udpClient = new UdpClient(AddressFamily.InterNetwork); - udpClient.Client.Reuse(); - udpClient.Client.WindowsUdpBug(); - - for (int i = 0; i < 5; i++) - { - try - { - await udpClient.SendAsync(new byte[1] { 0 }, server); - UdpReceiveResult result = await udpClient.ReceiveAsync().WaitAsync(TimeSpan.FromMilliseconds(500)); - if (result.Buffer.Length == 0) - { - return null; - } - - for (int j = 0; j < result.Buffer.Length; j++) - { - result.Buffer[j] = (byte)(result.Buffer[j] ^ byte.MaxValue); - } - AddressFamily addressFamily = (AddressFamily)result.Buffer[0]; - int length = addressFamily == AddressFamily.InterNetwork ? 4 : 16; - IPAddress ip = new IPAddress(result.Buffer.AsSpan(1, length)); - ushort port = result.Buffer.AsMemory(1 + length).ToUInt16(); - - IPEndPoint remoteEP = new IPEndPoint(ip, port); - - return new TunnelWanPortEndPoint { Local = udpClient.Client.LocalEndPoint as IPEndPoint, Remote = remoteEP }; - } - catch (Exception) - { - } - } - - return null; - } - } -} diff --git a/linker.tunnel/wanport/TunnelWanPortProtocolLinker.cs b/linker.tunnel/wanport/TunnelWanPortProtocolLinker.cs new file mode 100644 index 00000000..9c19e790 --- /dev/null +++ b/linker.tunnel/wanport/TunnelWanPortProtocolLinker.cs @@ -0,0 +1,109 @@ +using linker.libs.extends; +using System.Buffers; +using System.Net; +using System.Net.Sockets; + +namespace linker.tunnel.wanport +{ + public sealed class TunnelWanPortProtocolLinkerUdp : ITunnelWanPortProtocol + { + public string Name => "Linker Udp"; + public TunnelWanPortType Type => TunnelWanPortType.Linker; + + public TunnelWanPortProtocolType ProtocolType => TunnelWanPortProtocolType.Udp; + + public TunnelWanPortProtocolLinkerUdp() + { + + } + + public async Task GetAsync(IPEndPoint server) + { + UdpClient udpClient = new UdpClient(AddressFamily.InterNetwork); + udpClient.Client.Reuse(); + udpClient.Client.WindowsUdpBug(); + + for (int i = 0; i < 5; i++) + { + try + { + await udpClient.SendAsync(new byte[1] { 0 }, server); + UdpReceiveResult result = await udpClient.ReceiveAsync().WaitAsync(TimeSpan.FromMilliseconds(500)); + if (result.Buffer.Length == 0) + { + return null; + } + + for (int j = 0; j < result.Buffer.Length; j++) + { + result.Buffer[j] = (byte)(result.Buffer[j] ^ byte.MaxValue); + } + AddressFamily addressFamily = (AddressFamily)result.Buffer[0]; + int length = addressFamily == AddressFamily.InterNetwork ? 4 : 16; + IPAddress ip = new IPAddress(result.Buffer.AsSpan(1, length)); + ushort port = result.Buffer.AsMemory(1 + length).ToUInt16(); + + IPEndPoint remoteEP = new IPEndPoint(ip, port); + + return new TunnelWanPortEndPoint { Local = udpClient.Client.LocalEndPoint as IPEndPoint, Remote = remoteEP }; + } + catch (Exception) + { + } + } + + return null; + } + } + + + public sealed class TunnelWanPortProtocolLinkerTcp : ITunnelWanPortProtocol + { + public string Name => "Linker Tcp"; + public TunnelWanPortType Type => TunnelWanPortType.Linker; + + public TunnelWanPortProtocolType ProtocolType => TunnelWanPortProtocolType.Tcp; + + public TunnelWanPortProtocolLinkerTcp() + { + + } + + public async Task GetAsync(IPEndPoint server) + { + byte[] buffer = ArrayPool.Shared.Rent(20); + try + { + Socket socket = new Socket(server.AddressFamily, SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp); + await socket.ConnectAsync(server); + + await socket.SendAsync(new byte[] { 0 }); + int length = await socket.ReceiveAsync(buffer.AsMemory(), SocketFlags.None); + + for (int j = 0; j < length; j++) + { + buffer[j] = (byte)(buffer[j] ^ byte.MaxValue); + } + AddressFamily addressFamily = (AddressFamily)buffer[0]; + int iplength = addressFamily == AddressFamily.InterNetwork ? 4 : 16; + IPAddress ip = new IPAddress(buffer.AsSpan(1, iplength)); + ushort port = buffer.AsMemory(1 + iplength).ToUInt16(); + + IPEndPoint remoteEP = new IPEndPoint(ip, port); + IPEndPoint localEP = socket.LocalEndPoint as IPEndPoint; + socket.Close(); + + return new TunnelWanPortEndPoint { Local = localEP, Remote = remoteEP }; + } + catch (Exception) + { + } + finally + { + ArrayPool.Shared.Return(buffer); + } + + return null; + } + } +} diff --git a/linker.tunnel/wanport/TunnelWanPortStun.cs b/linker.tunnel/wanport/TunnelWanPortProtocolStun.cs similarity index 90% rename from linker.tunnel/wanport/TunnelWanPortStun.cs rename to linker.tunnel/wanport/TunnelWanPortProtocolStun.cs index 94392127..4cd95542 100644 --- a/linker.tunnel/wanport/TunnelWanPortStun.cs +++ b/linker.tunnel/wanport/TunnelWanPortProtocolStun.cs @@ -5,12 +5,14 @@ using System.Net.Sockets; namespace linker.tunnel.wanport { - public sealed class TunnelWanPortStun : ITunnelWanPort + public sealed class TunnelWanPortProtocolStun : ITunnelWanPortProtocol { - public string Name => "Stun"; + public string Name => "Stun Udp"; public TunnelWanPortType Type => TunnelWanPortType.Stun; - public TunnelWanPortStun() + public TunnelWanPortProtocolType ProtocolType => TunnelWanPortProtocolType.Udp; + + public TunnelWanPortProtocolStun() { } diff --git a/linker.tunnel/wanport/TunnelWanPortTransfer.cs b/linker.tunnel/wanport/TunnelWanPortTransfer.cs index bac4de03..cf31f17c 100644 --- a/linker.tunnel/wanport/TunnelWanPortTransfer.cs +++ b/linker.tunnel/wanport/TunnelWanPortTransfer.cs @@ -1,5 +1,4 @@ -using linker.tunnel.adapter; -using linker.libs; +using linker.libs; using System.Diagnostics; using System.Net; @@ -10,8 +9,7 @@ namespace linker.tunnel.wanport /// public sealed class TunnelWanPortTransfer { - private List tunnelWanPorts; - private ITunnelAdapter tunnelAdapter; + private List tunnelWanPorts; public TunnelWanPortTransfer() { @@ -21,10 +19,8 @@ namespace linker.tunnel.wanport /// 加载所有外网端口协议 /// /// - public void Init(ITunnelAdapter tunnelAdapter, List tunnelWanPorts) + public void Init(List tunnelWanPorts) { - - this.tunnelAdapter = tunnelAdapter; this.tunnelWanPorts = tunnelWanPorts; LoggerHelper.Instance.Warning($"load tunnel wanport compacts:{string.Join(",", tunnelWanPorts.Select(c => c.Name))}"); } @@ -39,37 +35,31 @@ namespace linker.tunnel.wanport /// /// 你的局域网IP /// - public async Task GetWanPortAsync(IPAddress localIP) + public async Task GetWanPortAsync(IPAddress localIP, TunnelWanPortInfo info) { - var tunnelWanPortItems = tunnelAdapter.GetTunnelWanPortCompacts(); - foreach (TunnelWanPortInfo item in tunnelWanPortItems) + if (info == null) return null; + var tunnelWanPort = tunnelWanPorts.FirstOrDefault(c => c.Type == info.Type && c.ProtocolType == info.ProtocolType); + try { - if (item.Disabled || string.IsNullOrWhiteSpace(item.Host)) continue; - ITunnelWanPort tunnelWanPort = tunnelWanPorts.FirstOrDefault(c => c.Type == item.Type); - if (tunnelWanPort == null) continue; - - try + Stopwatch sw = new Stopwatch(); + sw.Start(); + IPEndPoint server = NetworkHelper.GetEndPoint(info.Host, 3478); + sw.Stop(); + if (sw.ElapsedMilliseconds > 1000) { - Stopwatch sw = new Stopwatch(); - sw.Start(); - IPEndPoint server = NetworkHelper.GetEndPoint(item.Host, 3478); - sw.Stop(); - if (sw.ElapsedMilliseconds > 1000) - { - LoggerHelper.Instance.Warning($"get domain ip time:{sw.ElapsedMilliseconds}ms"); - } - TunnelWanPortEndPoint WanPort = await tunnelWanPort.GetAsync(server); - if (WanPort != null) - { - WanPort.Local.Address = localIP; - return WanPort; - } + LoggerHelper.Instance.Warning($"get domain ip time:{sw.ElapsedMilliseconds}ms"); } - catch (Exception ex) + TunnelWanPortEndPoint WanPort = await tunnelWanPort.GetAsync(server); + if (WanPort != null) { - LoggerHelper.Instance.Error(ex); + WanPort.Local.Address = localIP; + return WanPort; } } + catch (Exception ex) + { + LoggerHelper.Instance.Error(ex); + } return null; } } diff --git a/linker.web/src/views/devices/ForwardEdit.vue b/linker.web/src/views/devices/ForwardEdit.vue index 69510365..0133f13e 100644 --- a/linker.web/src/views/devices/ForwardEdit.vue +++ b/linker.web/src/views/devices/ForwardEdit.vue @@ -8,7 +8,7 @@