This commit is contained in:
snltty
2024-06-30 15:39:02 +08:00
parent a80ce92f75
commit e2b7cd31cb
48 changed files with 487 additions and 167 deletions

View File

@@ -98,6 +98,12 @@ namespace linker.tunnel.connection
/// 是否SSL /// 是否SSL
/// </summary> /// </summary>
public bool SSL { get; } public bool SSL { get; }
/// <summary>
/// 缓冲区大小
/// </summary>
public byte BufferSize { get; }
/// <summary> /// <summary>
/// 已连接 /// 已连接
/// </summary> /// </summary>

View File

@@ -30,6 +30,8 @@ namespace linker.tunnel.connection
public IPEndPoint IPEndPoint { get; init; } public IPEndPoint IPEndPoint { get; init; }
public bool SSL => true; public bool SSL => true;
public byte BufferSize { get; init; } = 3;
public bool Connected => Stream != null && Stream.CanWrite; public bool Connected => Stream != null && Stream.CanWrite;
public int Delay { get; private set; } public int Delay { get; private set; }
public long SendBytes { get; private set; } public long SendBytes { get; private set; }
@@ -81,7 +83,7 @@ namespace linker.tunnel.connection
} }
private async Task ProcessWrite() private async Task ProcessWrite()
{ {
byte[] buffer = ArrayPool<byte>.Shared.Rent(16 * 1024); byte[] buffer = ArrayPool<byte>.Shared.Rent((1 << BufferSize) * 1024);
try try
{ {
while (cancellationTokenSource.IsCancellationRequested == false) while (cancellationTokenSource.IsCancellationRequested == false)

View File

@@ -26,7 +26,7 @@ namespace linker.tunnel.connection
public TunnelDirection Direction { get; init; } public TunnelDirection Direction { get; init; }
public IPEndPoint IPEndPoint { get; init; } public IPEndPoint IPEndPoint { get; init; }
public bool SSL { get; init; } public bool SSL { get; init; }
public byte BufferSize { get; init; } = 3;
public bool Connected => Socket != null && Environment.TickCount64 - ticks < 15000; public bool Connected => Socket != null && Environment.TickCount64 - ticks < 15000;
public int Delay { get; private set; } public int Delay { get; private set; }
public long SendBytes { get; private set; } public long SendBytes { get; private set; }
@@ -73,7 +73,7 @@ namespace linker.tunnel.connection
private async Task ProcessWrite() private async Task ProcessWrite()
{ {
byte[] buffer = ArrayPool<byte>.Shared.Rent(16 * 1024); byte[] buffer = ArrayPool<byte>.Shared.Rent((1<<BufferSize) * 1024);
try try
{ {
int length = 0; int length = 0;

View File

@@ -25,6 +25,7 @@ namespace linker.tunnel.connection
public TunnelDirection Direction { get; init; } public TunnelDirection Direction { get; init; }
public IPEndPoint IPEndPoint { get; init; } public IPEndPoint IPEndPoint { get; init; }
public bool SSL => false; public bool SSL => false;
public byte BufferSize { get; init; } = 3;
public bool Connected => UdpClient != null && Environment.TickCount64 - ticks < 15000; public bool Connected => UdpClient != null && Environment.TickCount64 - ticks < 15000;
public int Delay { get; private set; } public int Delay { get; private set; }
@@ -66,7 +67,7 @@ namespace linker.tunnel.connection
} }
private async Task ProcessWrite() private async Task ProcessWrite()
{ {
byte[] buffer = ArrayPool<byte>.Shared.Rent(8 * 1024); byte[] buffer = ArrayPool<byte>.Shared.Rent((1 << BufferSize) * 1024);
try try
{ {
while (cancellationTokenSource.IsCancellationRequested == false) while (cancellationTokenSource.IsCancellationRequested == false)

View File

@@ -13,17 +13,17 @@ namespace linker.tunnel.proxy
private SemaphoreSlim semaphoreSlimForward = new SemaphoreSlim(10); private SemaphoreSlim semaphoreSlimForward = new SemaphoreSlim(10);
private SemaphoreSlim semaphoreSlimReverse = new SemaphoreSlim(10); private SemaphoreSlim semaphoreSlimReverse = new SemaphoreSlim(10);
public virtual IPAddress UdpBindAdress { get; set;} public virtual IPAddress UdpBindAdress { get; set; }
public TunnelProxy() public TunnelProxy()
{ {
TaskUdp(); TaskUdp();
} }
public void Start(IPEndPoint ep) public void Start(IPEndPoint ep, byte bufferSize)
{ {
StartTcp(ep); StartTcp(ep, bufferSize);
StartUdp(new IPEndPoint(ep.Address, LocalEndpoint.Port)); StartUdp(new IPEndPoint(ep.Address, LocalEndpoint.Port), bufferSize);
} }
/// <summary> /// <summary>
@@ -132,9 +132,9 @@ namespace linker.tunnel.proxy
{ {
Request = 1, Request = 1,
Forward = 2, Forward = 2,
Receive = 4, Receive = 3,
Pause = 8, Pause = 4,
Close = 16, Close = 5,
} }
public enum ProxyProtocol : byte public enum ProxyProtocol : byte
{ {
@@ -153,6 +153,7 @@ namespace linker.tunnel.proxy
public ProxyStep Step { get; set; } = ProxyStep.Request; public ProxyStep Step { get; set; } = ProxyStep.Request;
public ProxyProtocol Protocol { get; set; } = ProxyProtocol.Tcp; public ProxyProtocol Protocol { get; set; } = ProxyProtocol.Tcp;
public ProxyDirection Direction { get; set; } = ProxyDirection.Forward; public ProxyDirection Direction { get; set; } = ProxyDirection.Forward;
public byte BufferSize { get; set; } = 3;
public ushort Port { get; set; } public ushort Port { get; set; }
public IPEndPoint SourceEP { get; set; } public IPEndPoint SourceEP { get; set; }
@@ -160,6 +161,7 @@ namespace linker.tunnel.proxy
public byte Rsv { get; set; } public byte Rsv { get; set; }
public ReadOnlyMemory<byte> Data { get; set; } public ReadOnlyMemory<byte> Data { get; set; }
public byte[] ToBytes(out int length) public byte[] ToBytes(out int length)
@@ -167,7 +169,7 @@ namespace linker.tunnel.proxy
int sourceLength = SourceEP == null ? 0 : (SourceEP.AddressFamily == AddressFamily.InterNetwork ? 4 : 16) + 2; int sourceLength = SourceEP == null ? 0 : (SourceEP.AddressFamily == AddressFamily.InterNetwork ? 4 : 16) + 2;
int targetLength = TargetEP == null ? 0 : (TargetEP.AddressFamily == AddressFamily.InterNetwork ? 4 : 16) + 2; int targetLength = TargetEP == null ? 0 : (TargetEP.AddressFamily == AddressFamily.InterNetwork ? 4 : 16) + 2;
length = 4 + 8 + 1 + 1 + 1 length = 4 + 8 + 1 + 1
+ 2 + 2
+ 1 + sourceLength + 1 + sourceLength
+ 1 + targetLength + 1 + targetLength
@@ -185,13 +187,10 @@ namespace linker.tunnel.proxy
ConnectId.ToBytes(memory.Slice(index)); ConnectId.ToBytes(memory.Slice(index));
index += 8; index += 8;
bytes[index] = (byte)Step; bytes[index] = (byte)((byte)Step << 4 | (byte)Protocol << 2 | (byte)Direction);
index += 1; index += 1;
bytes[index] = (byte)Protocol; bytes[index] = BufferSize;
index += 1;
bytes[index] = (byte)Direction;
index += 1; index += 1;
Port.ToBytes(memory.Slice(index)); Port.ToBytes(memory.Slice(index));
@@ -241,14 +240,12 @@ namespace linker.tunnel.proxy
ConnectId = memory.Slice(index).ToUInt64(); ConnectId = memory.Slice(index).ToUInt64();
index += 8; index += 8;
Step = (ProxyStep)span[index]; Step = (ProxyStep)(span[index] >> 4);
index += 1; Protocol = (ProxyProtocol)(span[index] & 0b1100);
Direction = (ProxyDirection)(span[index] & 0b0011);
index++;
Protocol = (ProxyProtocol)span[index]; BufferSize = span[index];
index += 1;
Direction = (ProxyDirection)span[index];
index += 1;
Port = memory.Slice(index).ToUInt16(); Port = memory.Slice(index).ToUInt16();
index += 2; index += 2;

View File

@@ -19,7 +19,7 @@ namespace linker.tunnel.proxy
/// 监听一个端口 /// 监听一个端口
/// </summary> /// </summary>
/// <param name="port"></param> /// <param name="port"></param>
private void StartTcp(IPEndPoint ep) private void StartTcp(IPEndPoint ep, byte bufferSize)
{ {
IPEndPoint _localEndPoint = ep; IPEndPoint _localEndPoint = ep;
socket = new Socket(_localEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); socket = new Socket(_localEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
@@ -33,7 +33,8 @@ namespace linker.tunnel.proxy
AsyncUserToken userToken = new AsyncUserToken AsyncUserToken userToken = new AsyncUserToken
{ {
ListenPort = LocalEndpoint.Port, ListenPort = LocalEndpoint.Port,
Socket = socket Socket = socket,
BufferSize = bufferSize
}; };
_ = StartAccept(userToken); _ = StartAccept(userToken);
tcpListens.AddOrUpdate(LocalEndpoint.Port, userToken, (a, b) => userToken); tcpListens.AddOrUpdate(LocalEndpoint.Port, userToken, (a, b) => userToken);
@@ -75,7 +76,8 @@ namespace linker.tunnel.proxy
{ {
Socket = socket, Socket = socket,
ListenPort = acceptToken.ListenPort, ListenPort = acceptToken.ListenPort,
Buffer = new byte[8 * 1024], BufferSize = acceptToken.BufferSize,
Buffer = new byte[(1 << acceptToken.BufferSize) * 1024],
Proxy = new ProxyInfo { Data = Helper.EmptyArray, Step = ProxyStep.Request, Port = (ushort)acceptToken.ListenPort, ConnectId = ns.Increment() } Proxy = new ProxyInfo { Data = Helper.EmptyArray, Step = ProxyStep.Request, Port = (ushort)acceptToken.ListenPort, ConnectId = ns.Increment() }
}; };
_ = BeginReceive(userToken); _ = BeginReceive(userToken);
@@ -238,7 +240,7 @@ namespace linker.tunnel.proxy
Socket socket = new Socket(token.Proxy.TargetEP.AddressFamily, SocketType.Stream, ProtocolType.Tcp); Socket socket = new Socket(token.Proxy.TargetEP.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
socket.KeepAlive(); socket.KeepAlive();
ConnectState state = new ConnectState { Connection = token.Connection, ConnectId = token.Proxy.ConnectId, Socket = socket, IPEndPoint = token.Proxy.TargetEP }; ConnectState state = new ConnectState { BufferSize = token.Proxy.BufferSize, Connection = token.Connection, ConnectId = token.Proxy.ConnectId, Socket = socket, IPEndPoint = token.Proxy.TargetEP };
state.CopyData(token.Proxy.Data); state.CopyData(token.Proxy.Data);
socket.BeginConnect(token.Proxy.TargetEP, ConnectCallback, state); socket.BeginConnect(token.Proxy.TargetEP, ConnectCallback, state);
@@ -250,7 +252,7 @@ namespace linker.tunnel.proxy
{ {
Connection = state.Connection, Connection = state.Connection,
Socket = state.Socket, Socket = state.Socket,
Buffer = new byte[8 * 1024], Buffer = new byte[(1 << state.BufferSize) * 1024],
Proxy = new ProxyInfo Proxy = new ProxyInfo
{ {
ConnectId = state.ConnectId, ConnectId = state.ConnectId,
@@ -455,6 +457,8 @@ namespace linker.tunnel.proxy
public byte[] Buffer { get; set; } public byte[] Buffer { get; set; }
public byte BufferSize { get; set; } = 3;
public void Clear() public void Clear()
{ {
Socket?.SafeClose(); Socket?.SafeClose();
@@ -474,6 +478,8 @@ namespace linker.tunnel.proxy
public byte[] Data { get; set; } = Helper.EmptyArray; public byte[] Data { get; set; } = Helper.EmptyArray;
public int Length { get; set; } public int Length { get; set; }
public byte BufferSize { get; set; } = 3;
public void CopyData(ReadOnlyMemory<byte> data) public void CopyData(ReadOnlyMemory<byte> data)
{ {
if (data.Length > 0) if (data.Length > 0)

View File

@@ -16,7 +16,7 @@ namespace linker.tunnel.proxy
/// 监听一个端口 /// 监听一个端口
/// </summary> /// </summary>
/// <param name="port"></param> /// <param name="port"></param>
private void StartUdp(IPEndPoint ep) private void StartUdp(IPEndPoint ep, byte buffersize)
{ {
try try
{ {
@@ -32,7 +32,7 @@ namespace linker.tunnel.proxy
}; };
udpListens.AddOrUpdate(ep.Port, asyncUserUdpToken, (a, b) => asyncUserUdpToken); udpListens.AddOrUpdate(ep.Port, asyncUserUdpToken, (a, b) => asyncUserUdpToken);
_ = ReceiveUdp(asyncUserUdpToken); _ = ReceiveUdp(asyncUserUdpToken, buffersize);
} }
catch (Exception ex) catch (Exception ex)
@@ -40,9 +40,9 @@ namespace linker.tunnel.proxy
LoggerHelper.Instance.Error(ex); LoggerHelper.Instance.Error(ex);
} }
} }
private async Task ReceiveUdp(AsyncUserUdpToken token) private async Task ReceiveUdp(AsyncUserUdpToken token, byte buffersize)
{ {
byte[] bytes = new byte[8 * 1024]; byte[] bytes = new byte[(1 << buffersize) * 1024];
IPEndPoint TempRemoteEP = new IPEndPoint(IPAddress.Any, IPEndPoint.MinPort); IPEndPoint TempRemoteEP = new IPEndPoint(IPAddress.Any, IPEndPoint.MinPort);
while (true) while (true)
{ {
@@ -219,11 +219,12 @@ namespace linker.tunnel.proxy
TargetEP = tunnelToken.Proxy.TargetEP, TargetEP = tunnelToken.Proxy.TargetEP,
Step = tunnelToken.Proxy.Step, Step = tunnelToken.Proxy.Step,
Port = tunnelToken.Proxy.Port, Port = tunnelToken.Proxy.Port,
BufferSize = tunnelToken.Proxy.BufferSize,
}, },
TargetSocket = socket, TargetSocket = socket,
ConnectId = connectId, ConnectId = connectId,
Connection = tunnelToken.Connection, Connection = tunnelToken.Connection,
Buffer = new byte[8 * 1027] Buffer = new byte[(1 << tunnelToken.Proxy.BufferSize) * 1024]
}; };
udpToken.Proxy.Direction = ProxyDirection.Reverse; udpToken.Proxy.Direction = ProxyDirection.Reverse;
udpConnections.AddOrUpdate(connectId, udpToken, (a, b) => udpToken); udpConnections.AddOrUpdate(connectId, udpToken, (a, b) => udpToken);

View File

@@ -92,6 +92,8 @@ namespace linker.tunnel.transport
public bool Disabled { get; set; } = false; public bool Disabled { get; set; } = false;
public bool Reverse { get; set; } = true; public bool Reverse { get; set; } = true;
public bool SSL { get; set; } = true; public bool SSL { get; set; } = true;
public byte BufferSize { get; set; } = 3;
} }
public sealed class TunnelTransportItemInfoEqualityComparer : IEqualityComparer<TunnelTransportItemInfo> public sealed class TunnelTransportItemInfoEqualityComparer : IEqualityComparer<TunnelTransportItemInfo>
{ {
@@ -138,6 +140,8 @@ namespace linker.tunnel.transport
/// </summary> /// </summary>
public bool SSL { get; set; } public bool SSL { get; set; }
public byte BufferSize { get; set; } = 3;
public List<IPEndPoint> RemoteEndPoints { get; set; } public List<IPEndPoint> RemoteEndPoints { get; set; }
} }

View File

@@ -97,7 +97,7 @@ namespace linker.tunnel.transport
{ {
//反向连接 //反向连接
TunnelTransportInfo tunnelTransportInfo1 = tunnelTransportInfo.ToJsonFormat().DeJson<TunnelTransportInfo>(); TunnelTransportInfo tunnelTransportInfo1 = tunnelTransportInfo.ToJsonFormat().DeJson<TunnelTransportInfo>();
_ = ListenRemoteConnect(tunnelTransportInfo1.Local.Local, quicListenEP, tunnelTransportInfo1); _ = ListenRemoteConnect(tunnelTransportInfo.BufferSize, tunnelTransportInfo1.Local.Local, quicListenEP, tunnelTransportInfo1);
await Task.Delay(50); await Task.Delay(50);
BindAndTTL(tunnelTransportInfo1); BindAndTTL(tunnelTransportInfo1);
if (await OnSendConnectBegin(tunnelTransportInfo1) == false) if (await OnSendConnectBegin(tunnelTransportInfo1) == false)
@@ -139,7 +139,7 @@ namespace linker.tunnel.transport
} }
if (tunnelTransportInfo.Direction == TunnelDirection.Forward) if (tunnelTransportInfo.Direction == TunnelDirection.Forward)
{ {
_ = ListenRemoteConnect(tunnelTransportInfo.Local.Local, quicListenEP, tunnelTransportInfo); _ = ListenRemoteConnect(tunnelTransportInfo.BufferSize, tunnelTransportInfo.Local.Local, quicListenEP, tunnelTransportInfo);
await Task.Delay(50); await Task.Delay(50);
BindAndTTL(tunnelTransportInfo); BindAndTTL(tunnelTransportInfo);
} }
@@ -173,7 +173,7 @@ namespace linker.tunnel.transport
IPEndPoint local = new IPEndPoint(tunnelTransportInfo.Local.Local.Address, tunnelTransportInfo.Local.Local.Port); IPEndPoint local = new IPEndPoint(tunnelTransportInfo.Local.Local.Address, tunnelTransportInfo.Local.Local.Port);
TaskCompletionSource<IPEndPoint> taskCompletionSource = new TaskCompletionSource<IPEndPoint>(); TaskCompletionSource<IPEndPoint> taskCompletionSource = new TaskCompletionSource<IPEndPoint>();
//接收远端数据,收到了就是成功了 //接收远端数据,收到了就是成功了
Socket remoteUdp = ListenRemoteCallback(local, taskCompletionSource); Socket remoteUdp = ListenRemoteCallback(tunnelTransportInfo.BufferSize, local, taskCompletionSource);
//给远端发送一些消息 //给远端发送一些消息
foreach (IPEndPoint ep in tunnelTransportInfo.RemoteEndPoints) foreach (IPEndPoint ep in tunnelTransportInfo.RemoteEndPoints)
@@ -203,7 +203,7 @@ namespace linker.tunnel.transport
{ {
IPEndPoint remoteEP = await taskCompletionSource.Task.WaitAsync(TimeSpan.FromMilliseconds(500)); IPEndPoint remoteEP = await taskCompletionSource.Task.WaitAsync(TimeSpan.FromMilliseconds(500));
//绑定一个udp用来给QUIC链接 //绑定一个udp用来给QUIC链接
Socket quicUdp = ListenQuicConnect(remoteUdp, remoteEP); Socket quicUdp = ListenQuicConnect(tunnelTransportInfo.BufferSize, remoteUdp, remoteEP);
QuicConnection connection = connection = await QuicConnection.ConnectAsync(new QuicClientConnectionOptions QuicConnection connection = connection = await QuicConnection.ConnectAsync(new QuicClientConnectionOptions
{ {
RemoteEndPoint = new IPEndPoint(IPAddress.Loopback, (quicUdp.LocalEndPoint as IPEndPoint).Port), RemoteEndPoint = new IPEndPoint(IPAddress.Loopback, (quicUdp.LocalEndPoint as IPEndPoint).Port),
@@ -238,6 +238,7 @@ namespace linker.tunnel.transport
Type = TunnelType.P2P, Type = TunnelType.P2P,
Mode = TunnelMode.Client, Mode = TunnelMode.Client,
Label = string.Empty, Label = string.Empty,
BufferSize = tunnelTransportInfo.BufferSize
}; };
} }
catch (Exception ex) catch (Exception ex)
@@ -338,7 +339,7 @@ namespace linker.tunnel.transport
/// <param name="local">绑定的地址</param> /// <param name="local">绑定的地址</param>
/// <param name="tcs">等待对象,等待得到对方的地址</param> /// <param name="tcs">等待对象,等待得到对方的地址</param>
/// <returns></returns> /// <returns></returns>
private Socket ListenRemoteCallback(IPEndPoint local, TaskCompletionSource<IPEndPoint> tcs) private Socket ListenRemoteCallback(byte bufferSize, IPEndPoint local, TaskCompletionSource<IPEndPoint> tcs)
{ {
Socket socketUdp = new Socket(local.AddressFamily, SocketType.Dgram, System.Net.Sockets.ProtocolType.Udp); Socket socketUdp = new Socket(local.AddressFamily, SocketType.Dgram, System.Net.Sockets.ProtocolType.Udp);
socketUdp.ReuseBind(local); socketUdp.ReuseBind(local);
@@ -346,13 +347,13 @@ namespace linker.tunnel.transport
Task.Run(async () => Task.Run(async () =>
{ {
byte[] buffer = ArrayPool<byte>.Shared.Rent(16 * 1024); byte[] buffer = ArrayPool<byte>.Shared.Rent((1 << bufferSize) * 1024);
try try
{ {
IPEndPoint tempEp = new IPEndPoint(IPAddress.Any, IPEndPoint.MinPort); IPEndPoint tempEp = new IPEndPoint(IPAddress.Any, IPEndPoint.MinPort);
//收到远端的消息,表明对方已收到,再给它发个结束消息,表示可以正常通信了 //收到远端的消息,表明对方已收到,再给它发个结束消息,表示可以正常通信了
SocketReceiveFromResult result = await socketUdp.ReceiveFromAsync(buffer, tempEp); SocketReceiveFromResult result = await socketUdp.ReceiveFromAsync(buffer.AsMemory(), tempEp);
IPEndPoint ep = result.RemoteEndPoint as IPEndPoint; IPEndPoint ep = result.RemoteEndPoint as IPEndPoint;
await socketUdp.SendToAsync(endBytes, ep); await socketUdp.SendToAsync(endBytes, ep);
@@ -380,13 +381,13 @@ namespace linker.tunnel.transport
/// <param name="remoteUdp">监听收到消息消息后通过这个udp发送给远端</param> /// <param name="remoteUdp">监听收到消息消息后通过这个udp发送给远端</param>
/// <param name="remoteEP">远端地址</param> /// <param name="remoteEP">远端地址</param>
/// <returns></returns> /// <returns></returns>
private Socket ListenQuicConnect(Socket remoteUdp, IPEndPoint remoteEP) private Socket ListenQuicConnect(byte bufferSize, Socket remoteUdp, IPEndPoint remoteEP)
{ {
Socket localUdp = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, System.Net.Sockets.ProtocolType.Udp); Socket localUdp = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, System.Net.Sockets.ProtocolType.Udp);
localUdp.Bind(new IPEndPoint(IPAddress.Any, 0)); localUdp.Bind(new IPEndPoint(IPAddress.Any, 0));
localUdp.WindowsUdpBug(); localUdp.WindowsUdpBug();
_ = WaitQuicConnect(remoteUdp, remoteEP, localUdp); _ = WaitQuicConnect(bufferSize, remoteUdp, remoteEP, localUdp);
return localUdp; return localUdp;
} }
@@ -395,9 +396,9 @@ namespace linker.tunnel.transport
/// </summary> /// </summary>
/// <param name="token"></param> /// <param name="token"></param>
/// <returns></returns> /// <returns></returns>
private async Task WaitQuicConnect(Socket remoteUdp, IPEndPoint remoteEP, Socket localUdp) private async Task WaitQuicConnect(byte bufferSize, Socket remoteUdp, IPEndPoint remoteEP, Socket localUdp)
{ {
byte[] buffer = ArrayPool<byte>.Shared.Rent(16 * 1024); byte[] buffer = ArrayPool<byte>.Shared.Rent((1 << bufferSize) * 1024);
IPEndPoint tempEp = new IPEndPoint(IPAddress.Any, IPEndPoint.MinPort); IPEndPoint tempEp = new IPEndPoint(IPAddress.Any, IPEndPoint.MinPort);
try try
{ {
@@ -407,7 +408,7 @@ namespace linker.tunnel.transport
//发送给远端 //发送给远端
await remoteUdp.SendToAsync(buffer.AsMemory(0, result.ReceivedBytes), remoteEP).ConfigureAwait(false); await remoteUdp.SendToAsync(buffer.AsMemory(0, result.ReceivedBytes), remoteEP).ConfigureAwait(false);
await Task.WhenAll(CopyToAsync(localUdp, remoteUdp, remoteEP), CopyToAsync(remoteUdp, localUdp, quicEp)).ConfigureAwait(false); await Task.WhenAll(CopyToAsync(bufferSize, localUdp, remoteUdp, remoteEP), CopyToAsync(bufferSize, remoteUdp, localUdp, quicEp)).ConfigureAwait(false);
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -431,7 +432,7 @@ namespace linker.tunnel.transport
/// <param name="quicEP">QUIC监听地址</param> /// <param name="quicEP">QUIC监听地址</param>
/// <param name="state">收到连接后,调用连接成功回调,带上这个信息</param> /// <param name="state">收到连接后,调用连接成功回调,带上这个信息</param>
/// <returns></returns> /// <returns></returns>
private async Task ListenRemoteConnect(IPEndPoint local, IPEndPoint quicEP, TunnelTransportInfo state) private async Task ListenRemoteConnect(byte bufferSize, IPEndPoint local, IPEndPoint quicEP, TunnelTransportInfo state)
{ {
Socket udpClient = new Socket(local.AddressFamily, SocketType.Dgram, System.Net.Sockets.ProtocolType.Udp); Socket udpClient = new Socket(local.AddressFamily, SocketType.Dgram, System.Net.Sockets.ProtocolType.Udp);
ListenAsyncToken token = new ListenAsyncToken ListenAsyncToken token = new ListenAsyncToken
@@ -446,7 +447,7 @@ namespace linker.tunnel.transport
udpClient.ReuseBind(local); udpClient.ReuseBind(local);
udpClient.WindowsUdpBug(); udpClient.WindowsUdpBug();
_ = WaitAuth(token, tcs); _ = WaitAuth(bufferSize, token, tcs);
AddressFamily af = await tcs.Task.WaitAsync(TimeSpan.FromMilliseconds(30000)); AddressFamily af = await tcs.Task.WaitAsync(TimeSpan.FromMilliseconds(30000));
} }
@@ -464,9 +465,9 @@ namespace linker.tunnel.transport
/// </summary> /// </summary>
/// <param name="token"></param> /// <param name="token"></param>
/// <returns></returns> /// <returns></returns>
private async Task WaitAuth(ListenAsyncToken token, TaskCompletionSource<AddressFamily> tcs) private async Task WaitAuth(byte bufferSize, ListenAsyncToken token, TaskCompletionSource<AddressFamily> tcs)
{ {
byte[] buffer = ArrayPool<byte>.Shared.Rent(16 * 1024); byte[] buffer = ArrayPool<byte>.Shared.Rent((1 << bufferSize) * 1024);
IPEndPoint tempEp = new IPEndPoint(IPAddress.Any, IPEndPoint.MinPort); IPEndPoint tempEp = new IPEndPoint(IPAddress.Any, IPEndPoint.MinPort);
try try
{ {
@@ -482,7 +483,7 @@ namespace linker.tunnel.transport
{ {
token.RemoteEP = result.RemoteEndPoint as IPEndPoint; token.RemoteEP = result.RemoteEndPoint as IPEndPoint;
tcs.SetResult(result.RemoteEndPoint.AddressFamily); tcs.SetResult(result.RemoteEndPoint.AddressFamily);
_ = Connect2Quic(token); _ = Connect2Quic(bufferSize, token);
break; break;
} }
else else
@@ -510,9 +511,9 @@ namespace linker.tunnel.transport
/// </summary> /// </summary>
/// <param name="token"></param> /// <param name="token"></param>
/// <returns></returns> /// <returns></returns>
private async Task Connect2Quic(ListenAsyncToken token) private async Task Connect2Quic(byte bufferSize, ListenAsyncToken token)
{ {
byte[] buffer = ArrayPool<byte>.Shared.Rent(16 * 1024); byte[] buffer = ArrayPool<byte>.Shared.Rent((1 << bufferSize) * 1024);
IPEndPoint tempEp = new IPEndPoint(IPAddress.Any, IPEndPoint.MinPort); IPEndPoint tempEp = new IPEndPoint(IPAddress.Any, IPEndPoint.MinPort);
try try
{ {
@@ -526,7 +527,7 @@ namespace linker.tunnel.transport
stateDic.AddOrUpdate((token.QuicUdp.LocalEndPoint as IPEndPoint).Port, token, (a, b) => token); stateDic.AddOrUpdate((token.QuicUdp.LocalEndPoint as IPEndPoint).Port, token, (a, b) => token);
//然后就可以交换数据了 //然后就可以交换数据了
await Task.WhenAll(CopyToAsync(token.RemoteUdp, token.QuicUdp, token.QuicEP), CopyToAsync(token.QuicUdp, token.RemoteUdp, token.RemoteEP)).ConfigureAwait(false); await Task.WhenAll(CopyToAsync(bufferSize, token.RemoteUdp, token.QuicUdp, token.QuicEP), CopyToAsync(bufferSize, token.QuicUdp, token.RemoteUdp, token.RemoteEP)).ConfigureAwait(false);
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -549,9 +550,9 @@ namespace linker.tunnel.transport
/// <param name="remote"></param> /// <param name="remote"></param>
/// <param name="remoteEp"></param> /// <param name="remoteEp"></param>
/// <returns></returns> /// <returns></returns>
private async Task CopyToAsync(Socket local, Socket remote, IPEndPoint remoteEp) private async Task CopyToAsync(byte bufferSize, Socket local, Socket remote, IPEndPoint remoteEp)
{ {
byte[] buffer = ArrayPool<byte>.Shared.Rent(16 * 1024); byte[] buffer = ArrayPool<byte>.Shared.Rent((1 << bufferSize) * 1024);
IPEndPoint tempEp = new IPEndPoint(IPAddress.Any, IPEndPoint.MinPort); IPEndPoint tempEp = new IPEndPoint(IPAddress.Any, IPEndPoint.MinPort);
try try
{ {
@@ -623,6 +624,7 @@ namespace linker.tunnel.transport
TransportName = state.TransportName, TransportName = state.TransportName,
IPEndPoint = remoteEP, IPEndPoint = remoteEP,
Label = string.Empty, Label = string.Empty,
BufferSize = state.BufferSize,
}; };
if (reverseDic.TryRemove(state.Remote.MachineId, out TaskCompletionSource<ITunnelConnection> tcs)) if (reverseDic.TryRemove(state.Remote.MachineId, out TaskCompletionSource<ITunnelConnection> tcs))
{ {

View File

@@ -183,7 +183,8 @@ namespace linker.tunnel.transport
Type = TunnelType.P2P, Type = TunnelType.P2P,
Mode = TunnelMode.Client, Mode = TunnelMode.Client,
Label = string.Empty, Label = string.Empty,
SSL = tunnelTransportInfo.SSL SSL = tunnelTransportInfo.SSL,
BufferSize = tunnelTransportInfo.BufferSize,
}; };
} }
catch (Exception) catch (Exception)
@@ -278,7 +279,8 @@ namespace linker.tunnel.transport
TransportName = _state.TransportName, TransportName = _state.TransportName,
IPEndPoint = socket.RemoteEndPoint as IPEndPoint, IPEndPoint = socket.RemoteEndPoint as IPEndPoint,
Label = string.Empty, Label = string.Empty,
SSL = _state.SSL SSL = _state.SSL,
BufferSize = _state.BufferSize,
}; };
if (reverseDic.TryRemove(_state.Remote.MachineId, out TaskCompletionSource<ITunnelConnection> tcs)) if (reverseDic.TryRemove(_state.Remote.MachineId, out TaskCompletionSource<ITunnelConnection> tcs))
{ {

View File

@@ -24,3 +24,10 @@ export const getTunnelTransports = () => {
export const setTunnelTransports = (data) => { export const setTunnelTransports = (data) => {
return sendWebsocketMsg('tunnel/SetTransports', data); return sendWebsocketMsg('tunnel/SetTransports', data);
} }
export const getTunnelExcludeIPs = () => {
return sendWebsocketMsg('tunnel/GetExcludeIPs');
}
export const setTunnelExcludeIPs = (data) => {
return sendWebsocketMsg('tunnel/SetExcludeIPs', data);
}

View File

@@ -12,7 +12,8 @@ export const provideGlobalData = () => {
config: { Common: {}, Client: {}, Running: {} }, config: { Common: {}, Client: {}, Running: {} },
configed: false, configed: false,
signin: { Connected: false, Connecting: false, Version: 'v1.0.0.0' }, signin: { Connected: false, Connecting: false, Version: 'v1.0.0.0' },
groupid: '' groupid: '',
bufferSize: ['1KB', '2KB', '4KB', '8KB', '16KB', '32KB', '64KB', '128KB', '256KB', '512KB', '1024KB']
}); });
subWebsocketState((state) => { subWebsocketState((state) => {
globalData.value.connected = state; globalData.value.connected = state;

View File

@@ -4,9 +4,9 @@
<el-table :data="state.data" size="small" border height="500"> <el-table :data="state.data" size="small" border height="500">
<el-table-column property="RemoteMachineId" label="目标"> <el-table-column property="RemoteMachineId" label="目标">
<template #default="scope"> <template #default="scope">
<div> <div :class="{green:scope.row.Connected}">
<p>{{scope.row.RemoteMachineName}}</p>
<p>{{scope.row.IPEndPoint}}</p> <p>{{scope.row.IPEndPoint}}</p>
<p>ssl : {{scope.row.SSL}}</p>
</div> </div>
</template> </template>
</el-table-column> </el-table-column>
@@ -19,7 +19,7 @@
<template #default="scope"> <template #default="scope">
<div> <div>
<p>{{scope.row.TransportName}}({{ state.protocolTypes[scope.row.ProtocolType] }})</p> <p>{{scope.row.TransportName}}({{ state.protocolTypes[scope.row.ProtocolType] }})</p>
<p>{{ state.types[scope.row.Type] }}</p> <p>{{ state.types[scope.row.Type] }} - {{1<<scope.row.BufferSize}}KB</p>
</div> </div>
</template> </template>
</el-table-column> </el-table-column>
@@ -31,16 +31,11 @@
<el-table-column property="Bytes" label="通信"> <el-table-column property="Bytes" label="通信">
<template #default="scope"> <template #default="scope">
<div> <div>
<p>sent : {{scope.row.SendBytesText}}</p> <p>up : {{scope.row.SendBytesText}}</p>
<p>receive : {{scope.row.ReceiveBytesText}}</p> <p>down : {{scope.row.ReceiveBytesText}}</p>
</div> </div>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column property="Connected" label="连接中" width="60">
<template #default="scope">
<el-switch disabled v-model="scope.row.Connected" inline-prompt active-text="是" inactive-text="否" />
</template>
</el-table-column>
<el-table-column label="操作" width="54"> <el-table-column label="操作" width="54">
<template #default="scope"> <template #default="scope">
<el-popconfirm confirm-button-text="确认" cancel-button-text="取消" title="确定关闭此连接?" <el-popconfirm confirm-button-text="确认" cancel-button-text="取消" title="确定关闭此连接?"
@@ -101,4 +96,5 @@ export default {
<style lang="stylus" scoped> <style lang="stylus" scoped>
.head{padding-bottom:1rem} .head{padding-bottom:1rem}
.green{color:green}
</style> </style>

View File

@@ -15,6 +15,7 @@
<span :class="{error:!!item.TargetMsg}">{{ item.TargetEP }}</span> <span :class="{error:!!item.TargetMsg}">{{ item.TargetEP }}</span>
</span> </span>
</a> </a>
<span> ({{ 1<<item.BufferSize }}KB)</span>
</li> </li>
</template> </template>
</template> </template>
@@ -37,6 +38,7 @@
<span :class="{error:!!item.LocalMsg}">{{ item.LocalEP }}</span> <span :class="{error:!!item.LocalMsg}">{{ item.LocalEP }}</span>
</span> </span>
</a> </a>
<span> ({{ 1<<item.BufferSize }}KB)</span>
</li> </li>
</template> </template>
</template> </template>

View File

@@ -1,5 +1,5 @@
<template> <template>
<el-dialog v-model="state.show" @open="handleOnShowList" append-to=".app-wrap" :title="`端口转发到【${state.machineName}】`" top="1vh" width="600"> <el-dialog v-model="state.show" @open="handleOnShowList" append-to=".app-wrap" :title="`端口转发到【${state.machineName}】`" top="1vh" width="700">
<div> <div>
<div class="t-c head"> <div class="t-c head">
<el-button type="success" size="small" @click="handleAdd">添加</el-button> <el-button type="success" size="small" @click="handleAdd">添加</el-button>
@@ -17,6 +17,13 @@
</template> </template>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="BufferSize" label="缓冲区" width="100">
<template #default="scope">
<el-select v-model="scope.row.BufferSize" placeholder="Select" size="small" @change="handleEditBlur(scope.row, 'BufferSize')">
<el-option v-for="(item,index) in state.bufferSize" :key="index" :label="item" :value="index"/>
</el-select>
</template>
</el-table-column>
<el-table-column property="BindIPAddress" label="监听IP" width="140"> <el-table-column property="BindIPAddress" label="监听IP" width="140">
<template #default="scope"> <template #default="scope">
<el-select v-model="scope.row.BindIPAddress" size="small"> <el-select v-model="scope.row.BindIPAddress" size="small">
@@ -93,12 +100,14 @@ import { inject, onMounted, onUnmounted, reactive, watch } from 'vue';
import { getForwardInfo, removeForwardInfo, addForwardInfo ,getForwardIpv4,testTargetForwardInfo,testListenForwardInfo } from '@/apis/forward' import { getForwardInfo, removeForwardInfo, addForwardInfo ,getForwardIpv4,testTargetForwardInfo,testListenForwardInfo } from '@/apis/forward'
import { ElMessage } from 'element-plus'; import { ElMessage } from 'element-plus';
import {WarnTriangleFilled} from '@element-plus/icons-vue' import {WarnTriangleFilled} from '@element-plus/icons-vue'
import { injectGlobalData } from '@/provide';
export default { export default {
props: ['data','modelValue'], props: ['data','modelValue'],
emits: ['update:modelValue'], emits: ['update:modelValue'],
components:{WarnTriangleFilled}, components:{WarnTriangleFilled},
setup(props, { emit }) { setup(props, { emit }) {
const globalData = injectGlobalData();
const forward = inject('forward'); const forward = inject('forward');
const state = reactive({ const state = reactive({
show: true, show: true,
@@ -107,7 +116,8 @@ export default {
data: [], data: [],
ips:[], ips:[],
timerTestTarget:0, timerTestTarget:0,
timerTestListen:0 timerTestListen:0,
bufferSize:globalData.value.bufferSize,
}); });
watch(() => state.show, (val) => { watch(() => state.show, (val) => {
if (!val) { if (!val) {

View File

@@ -17,6 +17,11 @@
</template> </template>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="BufferSize" label="缓冲区" width="100">
<template #default="scope">
<span>{{ 1<<scope.row.BufferSize }}KB</span>
</template>
</el-table-column>
<el-table-column property="Temp" label="远程端口/域名" width="160"> <el-table-column property="Temp" label="远程端口/域名" width="160">
<template #default="scope"> <template #default="scope">
<template v-if="scope.row.TempEditing"> <template v-if="scope.row.TempEditing">
@@ -84,14 +89,17 @@ import { inject, onMounted, onUnmounted, reactive, watch } from 'vue';
import { getSForwardInfo, removeSForwardInfo, addSForwardInfo,testLocalSForwardInfo } from '@/apis/sforward' import { getSForwardInfo, removeSForwardInfo, addSForwardInfo,testLocalSForwardInfo } from '@/apis/sforward'
import { ElMessage } from 'element-plus'; import { ElMessage } from 'element-plus';
import {WarnTriangleFilled} from '@element-plus/icons-vue' import {WarnTriangleFilled} from '@element-plus/icons-vue'
import { injectGlobalData } from '@/provide';
export default { export default {
props: ['data','modelValue'], props: ['data','modelValue'],
emits: ['update:modelValue'], emits: ['update:modelValue'],
components:{WarnTriangleFilled}, components:{WarnTriangleFilled},
setup(props, { emit }) { setup(props, { emit }) {
const globalData = injectGlobalData();
const sforward = inject('sforward'); const sforward = inject('sforward');
const state = reactive({ const state = reactive({
bufferSize:globalData.value.bufferSize,
show: true, show: true,
data: [], data: [],
timerTestLocal:0 timerTestLocal:0

View File

@@ -32,6 +32,7 @@
</el-switch> </el-switch>
</div> </div>
<div>{{ tuntap.list[scope.row.MachineId].LanIPs.join('、') }}</div> <div>{{ tuntap.list[scope.row.MachineId].LanIPs.join('、') }}</div>
<div>{{ 1<<tuntap.list[scope.row.MachineId].BufferSize}}KB</div>
</div> </div>
</template> </template>
</el-table-column> </el-table-column>

View File

@@ -1,15 +1,20 @@
<template> <template>
<el-dialog v-model="state.show" :close-on-click-modal="false" append-to=".app-wrap" title="设置虚拟网卡IP" width="400"> <el-dialog v-model="state.show" :close-on-click-modal="false" append-to=".app-wrap" title="设置虚拟网卡IP" width="380">
<div> <div>
<el-form ref="ruleFormRef" :model="state.ruleForm" :rules="state.rules" label-width="80"> <el-form ref="ruleFormRef" :model="state.ruleForm" :rules="state.rules" label-width="80">
<el-form-item label="缓冲区" prop="BufferSize">
<el-select v-model="state.ruleForm.BufferSize" placeholder="Select" style="width:12rem">
<el-option v-for="(item,index) in state.bufferSize" :key="index" :label="item" :value="index"/>
</el-select>
</el-form-item>
<el-form-item label="网卡IP" prop="IP"> <el-form-item label="网卡IP" prop="IP">
<el-input v-model="state.ruleForm.IP" /> <el-input v-model="state.ruleForm.IP" style="width:12rem" /> / 24
</el-form-item> </el-form-item>
<el-form-item label="局域网IP" prop="LanIP"> <el-form-item label="局域网IP" prop="LanIP">
<template v-for="(item, index) in state.ruleForm.LanIPs" :key="index"> <template v-for="(item, index) in state.ruleForm.LanIPs" :key="index">
<div class="flex" style="margin-bottom:.6rem"> <div class="flex" style="margin-bottom:.6rem">
<div class="flex-1"> <div class="flex-1">
<el-input v-model="state.ruleForm.LanIPs[index]" /> <el-input v-model="state.ruleForm.LanIPs[index]" style="width:12rem" /> / 24
</div> </div>
<div class="pdl-10"> <div class="pdl-10">
<el-button type="danger" @click="handleDel(index)"><el-icon><Delete /></el-icon></el-button> <el-button type="danger" @click="handleDel(index)"><el-icon><Delete /></el-icon></el-button>
@@ -18,9 +23,6 @@
</div> </div>
</template> </template>
</el-form-item> </el-form-item>
<el-form-item label="" prop="alert">
<div>网卡IP和局域网IP都是 /24 掩码</div>
</el-form-item>
<el-form-item label="" prop="Btns"> <el-form-item label="" prop="Btns">
<div> <div>
<el-button @click="state.show = false">取消</el-button> <el-button @click="state.show = false">取消</el-button>
@@ -33,6 +35,7 @@
</template> </template>
<script> <script>
import {updateTuntap } from '@/apis/tuntap'; import {updateTuntap } from '@/apis/tuntap';
import { injectGlobalData } from '@/provide';
import { ElMessage } from 'element-plus'; import { ElMessage } from 'element-plus';
import { inject, reactive, ref, watch } from 'vue'; import { inject, reactive, ref, watch } from 'vue';
@@ -40,13 +43,18 @@ export default {
props: ['modelValue'], props: ['modelValue'],
emits: ['change','update:modelValue'], emits: ['change','update:modelValue'],
setup(props, { emit }) { setup(props, { emit }) {
const globalData = injectGlobalData();
const tuntap = inject('tuntap'); const tuntap = inject('tuntap');
const ruleFormRef = ref(null); const ruleFormRef = ref(null);
const state = reactive({ const state = reactive({
show: true, show: true,
bufferSize:globalData.value.bufferSize,
ruleForm: { ruleForm: {
IP: tuntap.value.current.IP, IP: tuntap.value.current.IP,
LanIPs: tuntap.value.current.LanIPs.slice(0) LanIPs: tuntap.value.current.LanIPs.slice(0),
BufferSize: tuntap.value.current.BufferSize
}, },
rules: {} rules: {}
}); });
@@ -72,6 +80,7 @@ export default {
const json = JSON.parse(JSON.stringify(tuntap.value.current)); const json = JSON.parse(JSON.stringify(tuntap.value.current));
json.IP = state.ruleForm.IP || '0.0.0.0'; json.IP = state.ruleForm.IP || '0.0.0.0';
json.LanIPs = state.ruleForm.LanIPs.filter(c => c); json.LanIPs = state.ruleForm.LanIPs.filter(c => c);
json.BufferSize = state.ruleForm.BufferSize;
updateTuntap(json).then(() => { updateTuntap(json).then(() => {
state.show = false; state.show = false;
ElMessage.success('已操作!'); ElMessage.success('已操作!');

View File

@@ -0,0 +1,113 @@
<template>
<div class="flex">
<div class="pdr-10 pdb-6 flex-1">
<el-checkbox v-model="state.sync" label="将更改同步到所有客户端" />
</div>
<div>打洞时排除这些IP(比如VPN虚拟网卡IP)</div>
</div>
<el-table :data="state.list" border size="small" width="100%" :height="`${state.height}px`" @cell-dblclick="handleCellClick">
<el-table-column prop="IPAddress" label="IP">
<template #default="scope">
<template v-if="scope.row.IPAddressEditing">
<el-input autofocus size="small" v-model="scope.row.IPAddress" @blur="handleEditBlur(scope.row, 'IPAddress')"></el-input>
</template>
<template v-else>
{{ scope.row.IPAddress }}
</template>
</template>
</el-table-column>
<el-table-column prop="Mask" label="掩码">
<template #default="scope">
<template v-if="scope.row.MaskEditing">
<el-input autofocus size="small" v-model="scope.row.Mask" @blur="handleEditBlur(scope.row, 'Mask')"></el-input>
</template>
<template v-else>
{{ scope.row.Mask }}
</template>
</template>
</el-table-column>
<el-table-column prop="Oper" label="操作" width="104" fixed="right">
<template #default="scope">
<div>
<el-popconfirm title="删除不可逆,是否确认?" @confirm="handleDel(scope.$index)">
<template #reference>
<el-button type="danger" size="small">
<el-icon><Delete /></el-icon>
</el-button>
</template>
</el-popconfirm>
<el-button type="primary" size="small" @click="handleAdd(scope.$index)">
<el-icon><Plus /></el-icon>
</el-button>
</div>
</template>
</el-table-column>
</el-table>
</template>
<script>
import { setTunnelExcludeIPs } from '@/apis/tunnel';
import { injectGlobalData } from '@/provide';
import { ElMessage } from 'element-plus';
import { computed, onMounted, reactive } from 'vue'
export default {
setup(props) {
const globalData = injectGlobalData();
const state = reactive({
list:((globalData.value.config.Running.Tunnel || {ExcludeIPs:[]}).ExcludeIPs || [{IPAddress:'0.0.0.0',Mask:32}]),
types:[],
height: computed(()=>globalData.value.height-130),
sync:true
});
const handleCellClick = (row, column) => {
handleEdit(row, column.property);
}
const handleEdit = (row, p) => {
state.list.forEach(c => {
c[`IPAddressEditing`] = false;
c[`MaskEditing`] = false;
})
row[`${p}Editing`] = true;
}
const handleEditBlur = (row, p) => {
row[`${p}Editing`] = false;
handleSave();
}
const handleDel = (index)=>{
state.list.splice(index,1);
handleSave();
}
const handleAdd = (index)=>{
state.list.splice(index+1,0,{IPAddress:'0.0.0.0',Mask:32});
handleSave();
}
const handleSave = ()=>{
state.list.forEach(c=>{
c.Mask = parseInt(c.Mask);
})
setTunnelExcludeIPs({
sync:state.sync,
list:state.list
}).then(()=>{
ElMessage.success('已操作');
}).catch(()=>{
ElMessage.success('操作失败');
});;
}
onMounted(() => {
if(state.list.length == 0){
state.list = [{IPAddress:'0.0.0.0',Mask:32}];
}
});
return {state,handleCellClick,handleEditBlur,handleDel,handleAdd}
}
}
</script>
<style lang="stylus" scoped>
</style>

View File

@@ -10,6 +10,9 @@
<el-tab-pane label="打洞协议" name="hole"> <el-tab-pane label="打洞协议" name="hole">
<Transports v-if="state.connected"></Transports> <Transports v-if="state.connected"></Transports>
</el-tab-pane> </el-tab-pane>
<el-tab-pane label="打洞排除IP" name="ips">
<ExcludeIP v-if="state.connected"></ExcludeIP>
</el-tab-pane>
<el-tab-pane label="中继服务器" name="relay"> <el-tab-pane label="中继服务器" name="relay">
<RelayServers v-if="state.connected"></RelayServers> <RelayServers v-if="state.connected"></RelayServers>
</el-tab-pane> </el-tab-pane>
@@ -25,10 +28,11 @@ import SignInServers from './SignInServers.vue'
import RelayServers from './RelayServers.vue' import RelayServers from './RelayServers.vue'
import TunnelServers from './TunnelServers.vue' import TunnelServers from './TunnelServers.vue'
import Transports from './Transports.vue' import Transports from './Transports.vue'
import ExcludeIP from './ExcludeIP.vue'
import SForward from './SForward.vue' import SForward from './SForward.vue'
import { injectGlobalData } from '@/provide'; import { injectGlobalData } from '@/provide';
export default { export default {
components:{SignInServers,RelayServers,TunnelServers,Transports,SForward}, components:{SignInServers,RelayServers,TunnelServers,Transports,ExcludeIP,SForward},
setup(props) { setup(props) {
const globalData = injectGlobalData(); const globalData = injectGlobalData();

View File

@@ -85,6 +85,7 @@
<script> <script>
import { setRelayServers,getRelayTypes } from '@/apis/relay'; import { setRelayServers,getRelayTypes } from '@/apis/relay';
import { injectGlobalData } from '@/provide'; import { injectGlobalData } from '@/provide';
import { ElMessage } from 'element-plus';
import { computed, onMounted, reactive } from 'vue' import { computed, onMounted, reactive } from 'vue'
export default { export default {
setup(props) { setup(props) {
@@ -147,7 +148,11 @@ export default {
setRelayServers({ setRelayServers({
sync:state.sync, sync:state.sync,
list:state.list list:state.list
}); }).then(()=>{
ElMessage.success('已操作');
}).catch(()=>{
ElMessage.success('操作失败');
});;
} }
onMounted(()=>{ onMounted(()=>{

View File

@@ -103,7 +103,11 @@ export default {
setSignInServers({ setSignInServers({
sync:state.sync, sync:state.sync,
list:state.list list:state.list
}); }).then(()=>{
ElMessage.success('已操作');
}).catch(()=>{
ElMessage.success('操作失败');
});;
} }
return {state,handleCellClick,handleEditBlur,handleDel,handleAdd,handleUse} return {state,handleCellClick,handleEditBlur,handleDel,handleAdd,handleUse}

View File

@@ -9,6 +9,13 @@
<el-table-column prop="Name" label="名称" width="120"></el-table-column> <el-table-column prop="Name" label="名称" width="120"></el-table-column>
<el-table-column prop="Label" label="说明"></el-table-column> <el-table-column prop="Label" label="说明"></el-table-column>
<el-table-column prop="ProtocolType" label="协议" width="60"></el-table-column> <el-table-column prop="ProtocolType" label="协议" width="60"></el-table-column>
<el-table-column prop="BufferSize" label="缓冲区" width="100">
<template #default="scope">
<el-select v-model="scope.row.BufferSize" placeholder="Select" size="small" @change="handleSave">
<el-option v-for="(item,index) in state.bufferSize" :key="index" :label="item" :value="index"/>
</el-select>
</template>
</el-table-column>
<el-table-column property="Reverse" label="反向" width="60"> <el-table-column property="Reverse" label="反向" width="60">
<template #default="scope"> <template #default="scope">
<el-switch v-model="scope.row.Reverse" @change="handleSave" inline-prompt active-text="是" inactive-text="否" /> <el-switch v-model="scope.row.Reverse" @change="handleSave" inline-prompt active-text="是" inactive-text="否" />
@@ -41,6 +48,7 @@
<script> <script>
import { getTunnelTransports,setTunnelTransports } from '@/apis/tunnel'; import { getTunnelTransports,setTunnelTransports } from '@/apis/tunnel';
import { injectGlobalData } from '@/provide'; import { injectGlobalData } from '@/provide';
import { ElMessage } from 'element-plus';
import { computed, onMounted, reactive } from 'vue' import { computed, onMounted, reactive } from 'vue'
export default { export default {
setup(props) { setup(props) {
@@ -48,7 +56,8 @@ export default {
const state = reactive({ const state = reactive({
list:[], list:[],
height: computed(()=>globalData.value.height-130), height: computed(()=>globalData.value.height-130),
sync:true bufferSize:globalData.value.bufferSize,
sync:true,
}); });
const _getTunnelTransports = ()=>{ const _getTunnelTransports = ()=>{
@@ -56,7 +65,6 @@ export default {
state.list = res; state.list = res;
}); });
} }
const handleSort = (index,oper)=>{ const handleSort = (index,oper)=>{
const current = state.list[index]; const current = state.list[index];
const outher = state.list[index+oper]; const outher = state.list[index+oper];
@@ -67,15 +75,19 @@ export default {
} }
handleSave(state.list); handleSave(state.list);
} }
const handleSave = ()=>{ const handleSave = ()=>{
state.list = state.list.slice().sort((a,b)=>a.Disabled - b.Disabled); state.list = state.list.slice().sort((a,b)=>a.Disabled - b.Disabled);
setTunnelTransports({ setTunnelTransports({
sync:state.sync, sync:state.sync,
List:state.list List:state.list
}).then(()=>{
ElMessage.success('已操作');
}).catch(()=>{
ElMessage.success('操作失败');
}); });
} }
onMounted(()=>{ onMounted(()=>{
_getTunnelTransports(); _getTunnelTransports();
}); });

View File

@@ -72,6 +72,7 @@
<script> <script>
import { setTunnelServers,getTunnelTypes } from '@/apis/tunnel'; import { setTunnelServers,getTunnelTypes } from '@/apis/tunnel';
import { injectGlobalData } from '@/provide'; import { injectGlobalData } from '@/provide';
import { ElMessage } from 'element-plus';
import { computed, onMounted, reactive } from 'vue' import { computed, onMounted, reactive } from 'vue'
export default { export default {
setup(props) { setup(props) {
@@ -85,7 +86,6 @@ export default {
const _getTunnelTypes = ()=>{ const _getTunnelTypes = ()=>{
getTunnelTypes().then((res)=>{ getTunnelTypes().then((res)=>{
console.log(res);
state.types = res; state.types = res;
}); });
} }
@@ -134,7 +134,11 @@ export default {
setTunnelServers({ setTunnelServers({
sync:state.sync, sync:state.sync,
list:state.list list:state.list
}); }).then(()=>{
ElMessage.success('已操作');
}).catch(()=>{
ElMessage.success('操作失败');
});;
} }
onMounted(()=>{ onMounted(()=>{

View File

@@ -64,7 +64,7 @@ namespace linker.plugins.forward
{ {
try try
{ {
forwardProxy.Start(new System.Net.IPEndPoint(forwardInfo.BindIPAddress, forwardInfo.Port), forwardInfo.TargetEP, forwardInfo.MachineId); forwardProxy.Start(new System.Net.IPEndPoint(forwardInfo.BindIPAddress, forwardInfo.Port), forwardInfo.TargetEP, forwardInfo.MachineId, forwardInfo.BufferSize);
forwardInfo.Port = forwardProxy.LocalEndpoint.Port; forwardInfo.Port = forwardProxy.LocalEndpoint.Port;
if (forwardInfo.Port > 0) if (forwardInfo.Port > 0)
@@ -211,7 +211,7 @@ namespace linker.plugins.forward
try try
{ {
forwardProxy.Stop(item.Port); forwardProxy.Stop(item.Port);
forwardProxy.Start(new IPEndPoint(item.BindIPAddress, item.Port), item.TargetEP, item.MachineId); forwardProxy.Start(new IPEndPoint(item.BindIPAddress, item.Port), item.TargetEP, item.MachineId, item.BufferSize);
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -268,6 +268,7 @@ namespace linker.plugins.forward
old.TargetEP = forwardInfo.TargetEP; old.TargetEP = forwardInfo.TargetEP;
old.MachineId = forwardInfo.MachineId; old.MachineId = forwardInfo.MachineId;
old.Started = forwardInfo.Started; old.Started = forwardInfo.Started;
old.BufferSize = forwardInfo.BufferSize;
} }
else else
{ {

View File

@@ -21,6 +21,8 @@ namespace linker.client.config
public IPEndPoint TargetEP { get; set; } public IPEndPoint TargetEP { get; set; }
public bool Started { get; set; } public bool Started { get; set; }
public byte BufferSize { get; set; } = 3;
public string Msg { get; set; } public string Msg { get; set; }
public string TargetMsg { get; set; } public string TargetMsg { get; set; }

View File

@@ -138,10 +138,10 @@ namespace linker.plugins.forward.proxy
} }
public void Start(IPEndPoint ep, IPEndPoint targetEP, string machineId) public void Start(IPEndPoint ep, IPEndPoint targetEP, string machineId,byte bufferSize)
{ {
Stop(ep.Port); Stop(ep.Port);
base.Start(ep); base.Start(ep, bufferSize);
caches.TryAdd(LocalEndpoint.Port, new ForwardProxyCacheInfo { Port = LocalEndpoint.Port, TargetEP = targetEP, MachineId = machineId }); caches.TryAdd(LocalEndpoint.Port, new ForwardProxyCacheInfo { Port = LocalEndpoint.Port, TargetEP = targetEP, MachineId = machineId });
} }
public override void Stop(int port) public override void Stop(int port)

View File

@@ -29,7 +29,7 @@ namespace linker.config
public sealed class RelayConfigServerInfo public sealed class RelayConfigServerInfo
{ {
public string SecretKey { get; set; } = Guid.NewGuid().ToString().ToUpper(); public string SecretKey { get; set; } = Guid.NewGuid().ToString().ToUpper();
public byte BufferSize { get; set; } = 3;
} }
[MemoryPackable] [MemoryPackable]

View File

@@ -172,27 +172,22 @@ namespace linker.plugins.relay.messenger
private async Task Relay(IConnection source, IConnection target, string secretKey) private async Task Relay(IConnection source, IConnection target, string secretKey)
{ {
await Task.Delay(100); await Task.Delay(100);
int limit = 0;
source.TargetStream = target.SourceStream; source.TargetStream = target.SourceStream;
source.TargetSocket = target.SourceSocket; source.TargetSocket = target.SourceSocket;
source.TargetNetworkStream = target.SourceNetworkStream; source.TargetNetworkStream = target.SourceNetworkStream;
source.RelayLimit = (uint)limit; source.RelayLimit = 0;
target.TargetStream = source.SourceStream; target.TargetStream = source.SourceStream;
target.TargetSocket = source.SourceSocket; target.TargetSocket = source.SourceSocket;
target.TargetNetworkStream = source.SourceNetworkStream; target.TargetNetworkStream = source.SourceNetworkStream;
target.RelayLimit = (uint)limit; target.RelayLimit = 0;
source.Cancel(); source.Cancel();
target.Cancel(); target.Cancel();
await Task.Delay(200); await Task.Delay(200);
await Task.WhenAll(source.RelayAsync(), target.RelayAsync()); await Task.WhenAll(source.RelayAsync(config.Data.Server.Relay.BufferSize), target.RelayAsync(config.Data.Server.Relay.BufferSize));
} }
public sealed class TcsWrap public sealed class TcsWrap

View File

@@ -87,7 +87,8 @@ namespace linker.plugins.relay.transport
TransactionId = relayInfo.TransactionId, TransactionId = relayInfo.TransactionId,
TransportName = Name, TransportName = Name,
Type = TunnelType.Relay, Type = TunnelType.Relay,
SSL = relayInfo.SSL SSL = relayInfo.SSL,
BufferSize = 3
}; };
} }
catch (Exception ex) catch (Exception ex)
@@ -148,7 +149,8 @@ namespace linker.plugins.relay.transport
TransactionId = relayInfo.TransactionId, TransactionId = relayInfo.TransactionId,
TransportName = Name, TransportName = Name,
Type = TunnelType.Relay, Type = TunnelType.Relay,
SSL = relayInfo.SSL SSL = relayInfo.SSL,
BufferSize = 3,
}; };
} }
catch (Exception ex) catch (Exception ex)

View File

@@ -59,7 +59,7 @@ namespace linker.plugins.sforward
SForwardProxy sForwardProxy = serviceProvider.GetService<SForwardProxy>(); SForwardProxy sForwardProxy = serviceProvider.GetService<SForwardProxy>();
if (config.Data.Server.SForward.WebPort > 0) if (config.Data.Server.SForward.WebPort > 0)
{ {
sForwardProxy.Start(config.Data.Server.SForward.WebPort, true); sForwardProxy.Start(config.Data.Server.SForward.WebPort, true, config.Data.Server.SForward.BufferSize);
LoggerHelper.Instance.Info($"listen server forward web in {config.Data.Server.SForward.WebPort}"); LoggerHelper.Instance.Info($"listen server forward web in {config.Data.Server.SForward.WebPort}");
} }
LoggerHelper.Instance.Info($"listen server forward tunnel in {string.Join("-", config.Data.Server.SForward.TunnelPortRange)}"); LoggerHelper.Instance.Info($"listen server forward tunnel in {string.Join("-", config.Data.Server.SForward.TunnelPortRange)}");

View File

@@ -64,6 +64,7 @@ namespace linker.plugins.sforward
if (result.Result.Code == MessageResponeCodes.OK) if (result.Result.Code == MessageResponeCodes.OK)
{ {
SForwardAddResultInfo sForwardAddResultInfo = MemoryPackSerializer.Deserialize<SForwardAddResultInfo>(result.Result.Data.Span); SForwardAddResultInfo sForwardAddResultInfo = MemoryPackSerializer.Deserialize<SForwardAddResultInfo>(result.Result.Data.Span);
forwardInfo.BufferSize = sForwardAddResultInfo.BufferSize;
if (sForwardAddResultInfo.Success) if (sForwardAddResultInfo.Success)
{ {
forwardInfo.Proxy = true; forwardInfo.Proxy = true;

View File

@@ -20,6 +20,8 @@ namespace linker.client.config
public string Domain { get; set; } public string Domain { get; set; }
public int RemotePort { get; set; } public int RemotePort { get; set; }
public byte BufferSize { get; set; } = 3;
public IPEndPoint LocalEP { get; set; } public IPEndPoint LocalEP { get; set; }
public bool Started { get; set; } public bool Started { get; set; }
@@ -42,7 +44,7 @@ namespace linker.config
public sealed class SForwardConfigServerInfo public sealed class SForwardConfigServerInfo
{ {
public string SecretKey { get; set; } = Guid.NewGuid().ToString().ToUpper(); public string SecretKey { get; set; } = Guid.NewGuid().ToString().ToUpper();
public byte BufferSize { get; set; } = 3;
public int WebPort { get; set; } public int WebPort { get; set; }
public int[] TunnelPortRange { get; set; } = new int[] { 10000, 60000 }; public int[] TunnelPortRange { get; set; } = new int[] { 10000, 60000 };
@@ -65,6 +67,8 @@ namespace linker.plugins.sforward.config
{ {
public bool Success { get; set; } public bool Success { get; set; }
public string Message { get; set; } public string Message { get; set; }
public byte BufferSize { get; set; }
} }
@@ -74,5 +78,7 @@ namespace linker.plugins.sforward.config
public ulong Id { get; set; } public ulong Id { get; set; }
public string Domain { get; set; } public string Domain { get; set; }
public int RemotePort { get; set; } public int RemotePort { get; set; }
public byte BufferSize { get; set; } = 3;
} }
} }

View File

@@ -5,6 +5,7 @@ using linker.plugins.signin.messenger;
using linker.server; using linker.server;
using MemoryPack; using MemoryPack;
using linker.plugins.sforward.proxy; using linker.plugins.sforward.proxy;
using linker.config;
namespace linker.plugins.sforward.messenger namespace linker.plugins.sforward.messenger
{ {
@@ -15,10 +16,10 @@ namespace linker.plugins.sforward.messenger
private readonly ISForwardServerCahing sForwardServerCahing; private readonly ISForwardServerCahing sForwardServerCahing;
private readonly MessengerSender sender; private readonly MessengerSender sender;
private readonly SignCaching signCaching; private readonly SignCaching signCaching;
private readonly ConfigWrap configWrap;
private readonly IValidator validator; private readonly IValidator validator;
public SForwardServerMessenger(SForwardProxy proxy, ISForwardServerCahing sForwardServerCahing, MessengerSender sender, SignCaching signCaching, IValidator validator) public SForwardServerMessenger(SForwardProxy proxy, ISForwardServerCahing sForwardServerCahing, MessengerSender sender, SignCaching signCaching, ConfigWrap configWrap, IValidator validator)
{ {
this.proxy = proxy; this.proxy = proxy;
proxy.WebConnect = WebConnect; proxy.WebConnect = WebConnect;
@@ -27,6 +28,7 @@ namespace linker.plugins.sforward.messenger
this.sForwardServerCahing = sForwardServerCahing; this.sForwardServerCahing = sForwardServerCahing;
this.sender = sender; this.sender = sender;
this.signCaching = signCaching; this.signCaching = signCaching;
this.configWrap = configWrap;
this.validator = validator; this.validator = validator;
} }
@@ -34,7 +36,7 @@ namespace linker.plugins.sforward.messenger
public void Add(IConnection connection) public void Add(IConnection connection)
{ {
SForwardAddInfo sForwardAddInfo = MemoryPackSerializer.Deserialize<SForwardAddInfo>(connection.ReceiveRequestWrap.Payload.Span); SForwardAddInfo sForwardAddInfo = MemoryPackSerializer.Deserialize<SForwardAddInfo>(connection.ReceiveRequestWrap.Payload.Span);
SForwardAddResultInfo result = new SForwardAddResultInfo { Success = true }; SForwardAddResultInfo result = new SForwardAddResultInfo { Success = true, BufferSize = configWrap.Data.Server.SForward.BufferSize };
try try
{ {
if (validator.Valid(connection, sForwardAddInfo, out string error) == false) if (validator.Valid(connection, sForwardAddInfo, out string error) == false)
@@ -67,7 +69,7 @@ namespace linker.plugins.sforward.messenger
} }
else else
{ {
string msg = proxy.Start(sForwardAddInfo.RemotePort, false); string msg = proxy.Start(sForwardAddInfo.RemotePort, false, configWrap.Data.Server.SForward.BufferSize);
if (string.IsNullOrWhiteSpace(msg) == false) if (string.IsNullOrWhiteSpace(msg) == false)
{ {
result.Success = false; result.Success = false;
@@ -177,7 +179,7 @@ namespace linker.plugins.sforward.messenger
{ {
Connection = sign.Connection, Connection = sign.Connection,
MessengerId = (ushort)SForwardMessengerIds.Proxy, MessengerId = (ushort)SForwardMessengerIds.Proxy,
Payload = MemoryPackSerializer.Serialize(new SForwardProxyInfo { Domain = host, RemotePort = port, Id = id }) Payload = MemoryPackSerializer.Serialize(new SForwardProxyInfo { Domain = host, RemotePort = port, Id = id, BufferSize= configWrap.Data.Server.SForward.BufferSize })
}); });
} }
return false; return false;
@@ -190,7 +192,7 @@ namespace linker.plugins.sforward.messenger
{ {
Connection = sign.Connection, Connection = sign.Connection,
MessengerId = (ushort)SForwardMessengerIds.Proxy, MessengerId = (ushort)SForwardMessengerIds.Proxy,
Payload = MemoryPackSerializer.Serialize(new SForwardProxyInfo { RemotePort = port, Id = id }) Payload = MemoryPackSerializer.Serialize(new SForwardProxyInfo { RemotePort = port, Id = id, BufferSize = configWrap.Data.Server.SForward.BufferSize })
}); });
} }
return false; return false;
@@ -203,7 +205,7 @@ namespace linker.plugins.sforward.messenger
{ {
Connection = sign.Connection, Connection = sign.Connection,
MessengerId = (ushort)SForwardMessengerIds.ProxyUdp, MessengerId = (ushort)SForwardMessengerIds.ProxyUdp,
Payload = MemoryPackSerializer.Serialize(new SForwardProxyInfo { RemotePort = port, Id = id }) Payload = MemoryPackSerializer.Serialize(new SForwardProxyInfo { RemotePort = port, Id = id, BufferSize = configWrap.Data.Server.SForward.BufferSize })
}); });
} }
return false; return false;
@@ -231,7 +233,7 @@ namespace linker.plugins.sforward.messenger
SForwardInfo sForwardInfo = runningConfig.Data.SForwards.FirstOrDefault(c => c.Domain == sForwardProxyInfo.Domain); SForwardInfo sForwardInfo = runningConfig.Data.SForwards.FirstOrDefault(c => c.Domain == sForwardProxyInfo.Domain);
if (sForwardInfo != null) if (sForwardInfo != null)
{ {
_ = proxy.OnConnectTcp(sForwardProxyInfo.Id, new System.Net.IPEndPoint(connection.Address.Address, sForwardProxyInfo.RemotePort), sForwardInfo.LocalEP); _ = proxy.OnConnectTcp(sForwardProxyInfo.BufferSize,sForwardProxyInfo.Id, new System.Net.IPEndPoint(connection.Address.Address, sForwardProxyInfo.RemotePort), sForwardInfo.LocalEP);
} }
} }
else if (sForwardProxyInfo.RemotePort > 0) else if (sForwardProxyInfo.RemotePort > 0)
@@ -239,7 +241,7 @@ namespace linker.plugins.sforward.messenger
SForwardInfo sForwardInfo = runningConfig.Data.SForwards.FirstOrDefault(c => c.RemotePort == sForwardProxyInfo.RemotePort); SForwardInfo sForwardInfo = runningConfig.Data.SForwards.FirstOrDefault(c => c.RemotePort == sForwardProxyInfo.RemotePort);
if (sForwardInfo != null) if (sForwardInfo != null)
{ {
_ = proxy.OnConnectTcp(sForwardProxyInfo.Id, new System.Net.IPEndPoint(connection.Address.Address, sForwardProxyInfo.RemotePort), sForwardInfo.LocalEP); _ = proxy.OnConnectTcp(sForwardProxyInfo.BufferSize, sForwardProxyInfo.Id, new System.Net.IPEndPoint(connection.Address.Address, sForwardProxyInfo.RemotePort), sForwardInfo.LocalEP);
} }
} }
} }
@@ -252,7 +254,7 @@ namespace linker.plugins.sforward.messenger
SForwardInfo sForwardInfo = runningConfig.Data.SForwards.FirstOrDefault(c => c.RemotePort == sForwardProxyInfo.RemotePort); SForwardInfo sForwardInfo = runningConfig.Data.SForwards.FirstOrDefault(c => c.RemotePort == sForwardProxyInfo.RemotePort);
if (sForwardInfo != null) if (sForwardInfo != null)
{ {
_ = proxy.OnConnectUdp(sForwardProxyInfo.Id, new System.Net.IPEndPoint(connection.Address.Address, sForwardProxyInfo.RemotePort), sForwardInfo.LocalEP); _ = proxy.OnConnectUdp(sForwardProxyInfo.BufferSize, sForwardProxyInfo.Id, new System.Net.IPEndPoint(connection.Address.Address, sForwardProxyInfo.RemotePort), sForwardInfo.LocalEP);
} }
} }
} }

View File

@@ -13,12 +13,12 @@ namespace linker.plugins.sforward.proxy
UdpTask(); UdpTask();
} }
public string Start(int port, bool isweb) public string Start(int port, bool isweb,byte bufferSize)
{ {
try try
{ {
StartTcp(port, isweb); StartTcp(port, isweb, bufferSize);
StartUdp(port); StartUdp(port, bufferSize);
return string.Empty; return string.Empty;
} }
catch (Exception ex) catch (Exception ex)

View File

@@ -15,10 +15,10 @@ namespace linker.plugins.sforward.proxy
public Func<int, ulong, Task<bool>> TunnelConnect { get; set; } = async (port, id) => { return await Task.FromResult(false); }; public Func<int, ulong, Task<bool>> TunnelConnect { get; set; } = async (port, id) => { return await Task.FromResult(false); };
public Func<string,int, ulong, Task<bool>> WebConnect { get; set; } = async (host,port, id) => { return await Task.FromResult(false); }; public Func<string, int, ulong, Task<bool>> WebConnect { get; set; } = async (host, port, id) => { return await Task.FromResult(false); };
private void StartTcp(int port, bool isweb) private void StartTcp(int port, bool isweb, byte bufferSize)
{ {
IPEndPoint localEndPoint = new IPEndPoint(NetworkHelper.IPv6Support ? IPAddress.IPv6Any : IPAddress.Any, port); IPEndPoint localEndPoint = new IPEndPoint(NetworkHelper.IPv6Support ? IPAddress.IPv6Any : IPAddress.Any, port);
Socket socket = new Socket(localEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); Socket socket = new Socket(localEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
@@ -30,6 +30,7 @@ namespace linker.plugins.sforward.proxy
ListenPort = port, ListenPort = port,
SourceSocket = socket, SourceSocket = socket,
IsWeb = isweb, IsWeb = isweb,
BufferSize = bufferSize,
}; };
SocketAsyncEventArgs acceptEventArg = new SocketAsyncEventArgs SocketAsyncEventArgs acceptEventArg = new SocketAsyncEventArgs
{ {
@@ -86,6 +87,7 @@ namespace linker.plugins.sforward.proxy
SourceSocket = socket, SourceSocket = socket,
ListenPort = acceptToken.ListenPort, ListenPort = acceptToken.ListenPort,
IsWeb = acceptToken.IsWeb, IsWeb = acceptToken.IsWeb,
BufferSize = acceptToken.BufferSize,
}; };
_ = BindReceive(userToken); _ = BindReceive(userToken);
} }
@@ -100,8 +102,8 @@ namespace linker.plugins.sforward.proxy
private async Task BindReceive(AsyncUserToken token) private async Task BindReceive(AsyncUserToken token)
{ {
ulong id = ns.Increment(); ulong id = ns.Increment();
byte[] buffer1 = ArrayPool<byte>.Shared.Rent(8 * 1024); byte[] buffer1 = ArrayPool<byte>.Shared.Rent((1 << token.BufferSize) * 1024);
byte[] buffer2 = ArrayPool<byte>.Shared.Rent(8 * 1024); byte[] buffer2 = ArrayPool<byte>.Shared.Rent((1 << token.BufferSize) * 1024);
try try
{ {
int length = await token.SourceSocket.ReceiveAsync(buffer1.AsMemory(), SocketFlags.None); int length = await token.SourceSocket.ReceiveAsync(buffer1.AsMemory(), SocketFlags.None);
@@ -132,7 +134,7 @@ namespace linker.plugins.sforward.proxy
} }
else else
{ {
if(await TunnelConnect(token.ListenPort, id) == false) if (await TunnelConnect(token.ListenPort, id) == false)
{ {
CloseClientSocket(token); CloseClientSocket(token);
return; return;
@@ -144,7 +146,7 @@ namespace linker.plugins.sforward.proxy
token.TargetSocket = await tcs.Task.WaitAsync(TimeSpan.FromMilliseconds(2000)).ConfigureAwait(false); token.TargetSocket = await tcs.Task.WaitAsync(TimeSpan.FromMilliseconds(2000)).ConfigureAwait(false);
await token.TargetSocket.SendAsync(buffer1.AsMemory(0, length)); await token.TargetSocket.SendAsync(buffer1.AsMemory(0, length));
await Task.WhenAll(SwarpData(token, buffer1, token.SourceSocket, token.TargetSocket), SwarpData(token,buffer2, token.TargetSocket, token.SourceSocket)); await Task.WhenAll(CopyToAsync(buffer1, token.SourceSocket, token.TargetSocket), CopyToAsync(buffer2, token.TargetSocket, token.SourceSocket));
CloseClientSocket(token); CloseClientSocket(token);
} }
@@ -157,14 +159,15 @@ namespace linker.plugins.sforward.proxy
tcpConnections.TryRemove(id, out _); tcpConnections.TryRemove(id, out _);
ArrayPool<byte>.Shared.Return(buffer1); ArrayPool<byte>.Shared.Return(buffer1);
ArrayPool<byte>.Shared.Return(buffer2); ArrayPool<byte>.Shared.Return(buffer2);
} }
} }
public async Task OnConnectTcp(ulong id, IPEndPoint server, IPEndPoint service) public async Task OnConnectTcp(byte bufferSize, ulong id, IPEndPoint server, IPEndPoint service)
{ {
Socket sourceSocket = null; Socket sourceSocket = null;
Socket targetSocket = null; Socket targetSocket = null;
byte[] buffer1 = ArrayPool<byte>.Shared.Rent(8 * 1024); byte[] buffer1 = ArrayPool<byte>.Shared.Rent((1 << bufferSize) * 1024);
byte[] buffer2 = ArrayPool<byte>.Shared.Rent(8 * 1024); byte[] buffer2 = ArrayPool<byte>.Shared.Rent((1 << bufferSize) * 1024);
try try
{ {
sourceSocket = new Socket(server.AddressFamily, SocketType.Stream, ProtocolType.Tcp); sourceSocket = new Socket(server.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
@@ -179,7 +182,7 @@ namespace linker.plugins.sforward.proxy
id.ToBytes(buffer1.AsMemory(flagBytes.Length)); id.ToBytes(buffer1.AsMemory(flagBytes.Length));
await sourceSocket.SendAsync(buffer1.AsMemory(0, flagBytes.Length + 8)); await sourceSocket.SendAsync(buffer1.AsMemory(0, flagBytes.Length + 8));
await Task.WhenAll(SwarpData(null,buffer1, sourceSocket, targetSocket), SwarpData(null,buffer2, targetSocket, sourceSocket)); await Task.WhenAll(CopyToAsync(buffer1, sourceSocket, targetSocket), CopyToAsync(buffer2, targetSocket, sourceSocket));
} }
catch (Exception) catch (Exception)
@@ -194,6 +197,7 @@ namespace linker.plugins.sforward.proxy
} }
} }
private byte[] hostBytes = Encoding.UTF8.GetBytes("Host: "); private byte[] hostBytes = Encoding.UTF8.GetBytes("Host: ");
private byte[] wrapBytes = Encoding.UTF8.GetBytes("\r\n"); private byte[] wrapBytes = Encoding.UTF8.GetBytes("\r\n");
private byte[] colonBytes = Encoding.UTF8.GetBytes(":"); private byte[] colonBytes = Encoding.UTF8.GetBytes(":");
@@ -210,14 +214,15 @@ namespace linker.plugins.sforward.proxy
return Encoding.UTF8.GetString(buffer.Slice(start, length).Span); return Encoding.UTF8.GetString(buffer.Slice(start, length).Span);
} }
private async Task SwarpData(AsyncUserToken token,Memory<byte> buffer, Socket source, Socket target)
private async Task CopyToAsync(Memory<byte> buffer, Socket source, Socket target)
{ {
try try
{ {
int bytesRead; int bytesRead;
while ((bytesRead = await source.ReceiveAsync(buffer).ConfigureAwait(false)) != 0) while ((bytesRead = await source.ReceiveAsync(buffer, SocketFlags.None).ConfigureAwait(false)) != 0)
{ {
await target.SendAsync(buffer.Slice(0, bytesRead)).ConfigureAwait(false); await target.SendAsync(buffer.Slice(0, bytesRead), SocketFlags.None).ConfigureAwait(false);
} }
} }
catch (Exception ex) catch (Exception ex)
@@ -227,6 +232,11 @@ namespace linker.plugins.sforward.proxy
LoggerHelper.Instance.Error(ex); LoggerHelper.Instance.Error(ex);
} }
} }
finally
{
source.SafeClose();
target.SafeClose();
}
} }
private void CloseClientSocket(AsyncUserToken token) private void CloseClientSocket(AsyncUserToken token)
@@ -260,6 +270,8 @@ namespace linker.plugins.sforward.proxy
public Socket SourceSocket { get; set; } public Socket SourceSocket { get; set; }
public Socket TargetSocket { get; set; } public Socket TargetSocket { get; set; }
public byte BufferSize { get; set; }
public void Clear() public void Clear()
{ {
SourceSocket?.SafeClose(); SourceSocket?.SafeClose();

View File

@@ -16,7 +16,7 @@ namespace linker.plugins.sforward.proxy
public Func<int, ulong, Task<bool>> UdpConnect { get; set; } = async (port, id) => { return await Task.FromResult(false); }; public Func<int, ulong, Task<bool>> UdpConnect { get; set; } = async (port, id) => { return await Task.FromResult(false); };
private void StartUdp(int port) private void StartUdp(int port, byte bufferSize)
{ {
Socket socketUdp = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); Socket socketUdp = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
socketUdp.Bind(new IPEndPoint(IPAddress.Any, port)); socketUdp.Bind(new IPEndPoint(IPAddress.Any, port));
@@ -28,16 +28,16 @@ namespace linker.plugins.sforward.proxy
socketUdp.EnableBroadcast = true; socketUdp.EnableBroadcast = true;
socketUdp.WindowsUdpBug(); socketUdp.WindowsUdpBug();
_ = BindReceive(asyncUserUdpToken); _ = BindReceive(asyncUserUdpToken, bufferSize);
udpListens.AddOrUpdate(port, asyncUserUdpToken, (a, b) => asyncUserUdpToken); udpListens.AddOrUpdate(port, asyncUserUdpToken, (a, b) => asyncUserUdpToken);
} }
private async Task BindReceive(AsyncUserUdpToken token) private async Task BindReceive(AsyncUserUdpToken token, byte bufferSize)
{ {
try try
{ {
byte[] buffer = new byte[8 * 1024]; byte[] buffer = new byte[(1 << bufferSize) * 1024];
IPEndPoint tempRemoteEP = new IPEndPoint(IPAddress.Any, IPEndPoint.MinPort); IPEndPoint tempRemoteEP = new IPEndPoint(IPAddress.Any, IPEndPoint.MinPort);
while (true) while (true)
{ {
@@ -125,7 +125,7 @@ namespace linker.plugins.sforward.proxy
} }
} }
} }
public async Task OnConnectUdp(ulong id, IPEndPoint server, IPEndPoint service) public async Task OnConnectUdp(byte bufferSize, ulong id, IPEndPoint server, IPEndPoint service)
{ {
Socket socketUdp = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); Socket socketUdp = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
socketUdp.WindowsUdpBug(); socketUdp.WindowsUdpBug();
@@ -137,7 +137,7 @@ namespace linker.plugins.sforward.proxy
await socketUdp.SendToAsync(buffer, server); await socketUdp.SendToAsync(buffer, server);
Socket serviceUdp = null; Socket serviceUdp = null;
buffer = new byte[8 * 1024]; buffer = new byte[(1 << bufferSize) * 1024];
IPEndPoint tempEp = new IPEndPoint(IPAddress.Any, IPEndPoint.MinPort); IPEndPoint tempEp = new IPEndPoint(IPAddress.Any, IPEndPoint.MinPort);
while (true) while (true)
{ {
@@ -160,7 +160,7 @@ namespace linker.plugins.sforward.proxy
_ = Task.Run(async () => _ = Task.Run(async () =>
{ {
buffer = new byte[8 * 1024]; buffer = new byte[(1 << bufferSize) * 1024];
IPEndPoint tempEp = new IPEndPoint(IPAddress.Any, IPEndPoint.MinPort); IPEndPoint tempEp = new IPEndPoint(IPAddress.Any, IPEndPoint.MinPort);
while (true) while (true)
{ {

View File

@@ -10,6 +10,9 @@ using MemoryPack;
using System.Net; using System.Net;
using System.Security.Cryptography.X509Certificates; using System.Security.Cryptography.X509Certificates;
using linker.tunnel.wanport; using linker.tunnel.wanport;
using System.Linq;
using linker.libs.extends;
using System.Buffers.Binary;
namespace linker.plugins.tunnel namespace linker.plugins.tunnel
{ {
@@ -63,7 +66,26 @@ namespace linker.plugins.tunnel
{ {
return new NetworkInfo return new NetworkInfo
{ {
LocalIps = config.Data.Client.Tunnel.LocalIPs.Where(c => c.Equals(running.Data.Tuntap.IP) == false).ToArray(), LocalIps = config.Data.Client.Tunnel.LocalIPs
.Where(c => c.Equals(running.Data.Tuntap.IP) == false)
.Where(c=>
{
if(c.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
{
uint ip = BinaryPrimitives.ReadUInt32BigEndian(c.GetAddressBytes());
foreach (var item in running.Data.Tunnel.ExcludeIPs)
{
uint maskValue = NetworkHelper.MaskValue(item.Mask);
uint ip1 = BinaryPrimitives.ReadUInt32BigEndian(item.IPAddress.GetAddressBytes());
if((ip & maskValue) == (ip1 & maskValue))
{
return false;
}
}
}
return true;
})
.ToArray(),
RouteLevel = config.Data.Client.Tunnel.RouteLevel + running.Data.Tunnel.RouteLevelPlus, RouteLevel = config.Data.Client.Tunnel.RouteLevel + running.Data.Tunnel.RouteLevelPlus,
MachineId = config.Data.Client.Id MachineId = config.Data.Client.Id
}; };

View File

@@ -10,6 +10,7 @@ using linker.libs.extends;
using MemoryPack; using MemoryPack;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using linker.tunnel.wanport; using linker.tunnel.wanport;
using linker.client.config;
namespace linker.plugins.tunnel namespace linker.plugins.tunnel
{ {
@@ -149,6 +150,25 @@ namespace linker.plugins.tunnel
} }
} }
public ExcludeIPItem[] GetExcludeIPs(ApiControllerParamsInfo param)
{
return tunnelConfigTransfer.GetExcludeIPs();
}
public async Task SetExcludeIPs(ApiControllerParamsInfo param)
{
SetExcludeIPsParamInfo info = param.Content.DeJson<SetExcludeIPsParamInfo>();
tunnelConfigTransfer.SettExcludeIPs(info.List);
if (info.Sync)
{
await messengerSender.SendOnly(new MessageRequestWrap
{
Connection = clientSignInState.Connection,
MessengerId = (ushort)TunnelMessengerIds.ExcludeIPsForward,
Payload = MemoryPackSerializer.Serialize(info.List)
});
}
}
public sealed class TunnelListInfo public sealed class TunnelListInfo
{ {
@@ -167,6 +187,11 @@ namespace linker.plugins.tunnel
public bool Sync { get; set; } public bool Sync { get; set; }
public List<TunnelTransportItemInfo> List { get; set; } = new List<TunnelTransportItemInfo>(); public List<TunnelTransportItemInfo> List { get; set; } = new List<TunnelTransportItemInfo>();
} }
public sealed class SetExcludeIPsParamInfo
{
public bool Sync { get; set; }
public ExcludeIPItem[] List { get; set; } = Array.Empty<ExcludeIPItem>();
}
} }
} }

View File

@@ -99,7 +99,6 @@ namespace linker.plugins.tunnel
} }
}); });
} }
private TunnelTransportRouteLevelInfo GetLocalRouteLevel() private TunnelTransportRouteLevelInfo GetLocalRouteLevel()
{ {
return new TunnelTransportRouteLevelInfo return new TunnelTransportRouteLevelInfo
@@ -110,5 +109,15 @@ namespace linker.plugins.tunnel
}; };
} }
public ExcludeIPItem[] GetExcludeIPs()
{
return running.Data.Tunnel.ExcludeIPs;
}
public void SettExcludeIPs(ExcludeIPItem[] ips)
{
running.Data.Tunnel.ExcludeIPs = ips;
}
} }
} }

View File

@@ -20,8 +20,18 @@ namespace linker.client.config
public TunnelWanPortInfo[] Servers { get; set; } = Array.Empty<TunnelWanPortInfo>(); public TunnelWanPortInfo[] Servers { get; set; } = Array.Empty<TunnelWanPortInfo>();
public int RouteLevelPlus { get; set; } = 0; public int RouteLevelPlus { get; set; } = 0;
public ExcludeIPItem[] ExcludeIPs { get; set; } = Array.Empty<ExcludeIPItem>();
public List<TunnelTransportItemInfo> Transports { get; set; } = new List<TunnelTransportItemInfo>(); public List<TunnelTransportItemInfo> Transports { get; set; } = new List<TunnelTransportItemInfo>();
} }
[MemoryPackable]
public sealed partial class ExcludeIPItem
{
[MemoryPackAllowSerialize]
public IPAddress IPAddress { get; set;}
public byte Mask { get; set; } = 32;
}
} }
namespace linker.config namespace linker.config
@@ -133,9 +143,9 @@ namespace linker.config
string MachineName => tunnelTransportWanPortInfo.MachineName; string MachineName => tunnelTransportWanPortInfo.MachineName;
[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)
{ {
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 };
this.tunnelTransportWanPortInfo = tunnelTransportWanPortInfo; this.tunnelTransportWanPortInfo = tunnelTransportWanPortInfo;
} }
@@ -195,11 +205,14 @@ namespace linker.config
[MemoryPackInclude] [MemoryPackInclude]
bool Reverse => tunnelTransportItemInfo.Reverse; bool Reverse => tunnelTransportItemInfo.Reverse;
[MemoryPackInclude]
byte BufferSize => tunnelTransportItemInfo.BufferSize;
[MemoryPackConstructor] [MemoryPackConstructor]
SerializableTunnelTransportItemInfo(string name, string label, string protocolType, bool disabled, bool reverse) SerializableTunnelTransportItemInfo(string name, string label, string protocolType, bool disabled, bool reverse, byte buffersize)
{ {
var tunnelTransportItemInfo = new TunnelTransportItemInfo { Name = name, Label = label, ProtocolType = protocolType, Disabled = disabled, Reverse = reverse }; var tunnelTransportItemInfo = new TunnelTransportItemInfo { Name = name, Label = label, ProtocolType = protocolType, Disabled = disabled, Reverse = reverse, BufferSize = buffersize };
this.tunnelTransportItemInfo = tunnelTransportItemInfo; this.tunnelTransportItemInfo = tunnelTransportItemInfo;
} }
@@ -264,9 +277,12 @@ namespace linker.config
[MemoryPackInclude] [MemoryPackInclude]
bool SSL => tunnelTransportInfo.SSL; bool SSL => tunnelTransportInfo.SSL;
[MemoryPackInclude]
byte BufferSize => tunnelTransportInfo.BufferSize;
[MemoryPackConstructor] [MemoryPackConstructor]
SerializableTunnelTransportInfo(TunnelTransportWanPortInfo local, TunnelTransportWanPortInfo remote, string transactionId, TunnelProtocolType transportType, string transportName, TunnelDirection direction, bool ssl) SerializableTunnelTransportInfo(TunnelTransportWanPortInfo local, TunnelTransportWanPortInfo remote, string transactionId, TunnelProtocolType transportType, string transportName, TunnelDirection direction, bool ssl, byte bufferSize)
{ {
var tunnelTransportInfo = new TunnelTransportInfo var tunnelTransportInfo = new TunnelTransportInfo
{ {
@@ -276,7 +292,8 @@ namespace linker.config
TransportName = transportName, TransportName = transportName,
TransportType = transportType, TransportType = transportType,
Direction = direction, Direction = direction,
SSL = ssl SSL = ssl,
BufferSize = bufferSize,
}; };
this.tunnelTransportInfo = tunnelTransportInfo; this.tunnelTransportInfo = tunnelTransportInfo;
} }

View File

@@ -7,6 +7,7 @@ using linker.tunnel.transport;
using linker.libs; using linker.libs;
using MemoryPack; using MemoryPack;
using linker.tunnel.wanport; using linker.tunnel.wanport;
using linker.client.config;
namespace linker.plugins.tunnel.messenger namespace linker.plugins.tunnel.messenger
{ {
@@ -96,6 +97,13 @@ namespace linker.plugins.tunnel.messenger
TunnelWanPortInfo[] servers = MemoryPackSerializer.Deserialize<TunnelWanPortInfo[]>(connection.ReceiveRequestWrap.Payload.Span); TunnelWanPortInfo[] servers = MemoryPackSerializer.Deserialize<TunnelWanPortInfo[]>(connection.ReceiveRequestWrap.Payload.Span);
tunnelMessengerAdapter.SetTunnelWanPortCompacts(servers.ToList()); tunnelMessengerAdapter.SetTunnelWanPortCompacts(servers.ToList());
} }
[MessengerId((ushort)TunnelMessengerIds.ExcludeIPs)]
public void ExcludeIPs(IConnection connection)
{
ExcludeIPItem[] ips = MemoryPackSerializer.Deserialize<ExcludeIPItem[]>(connection.ReceiveRequestWrap.Payload.Span);
tunnelConfigTransfer.SettExcludeIPs(ips);
}
} }
public sealed class TunnelServerMessenger : IMessenger public sealed class TunnelServerMessenger : IMessenger
@@ -274,6 +282,25 @@ namespace linker.plugins.tunnel.messenger
} }
} }
} }
[MessengerId((ushort)TunnelMessengerIds.ExcludeIPsForward)]
public async Task ExcludeIPsForward(IConnection connection)
{
if (signCaching.TryGet(connection.Id, out SignCacheInfo cache))
{
List<SignCacheInfo> caches = signCaching.Get(cache.GroupId);
foreach (SignCacheInfo item in caches.Where(c => c.MachineId != connection.Id && c.Connected))
{
await messengerSender.SendOnly(new MessageRequestWrap
{
Connection = item.Connection,
MessengerId = (ushort)TunnelMessengerIds.ExcludeIPs,
Payload = connection.ReceiveRequestWrap.Payload
});
}
}
}
} }

View File

@@ -28,6 +28,9 @@
Servers = 2015, Servers = 2015,
ServersForward = 2016, ServersForward = 2016,
ExcludeIPs = 2017,
ExcludeIPsForward = 2018,
None = 2099 None = 2099
} }
} }

View File

@@ -90,6 +90,7 @@ namespace linker.plugins.tuntap
return; return;
} }
tuntapProxy.Start();
while (tuntapProxy.LocalEndpoint == null) while (tuntapProxy.LocalEndpoint == null)
{ {
await Task.Delay(1000); await Task.Delay(1000);
@@ -125,6 +126,7 @@ namespace linker.plugins.tuntap
} }
try try
{ {
tuntapProxy.Stop();
OnChange(); OnChange();
tuntapVea.Kill(); tuntapVea.Kill();
runningConfig.Data.Tuntap.Running = Status == TuntapStatus.Running; runningConfig.Data.Tuntap.Running = Status == TuntapStatus.Running;
@@ -162,6 +164,7 @@ namespace linker.plugins.tuntap
{ {
runningConfig.Data.Tuntap.IP = info.IP; runningConfig.Data.Tuntap.IP = info.IP;
runningConfig.Data.Tuntap.LanIPs = info.LanIPs; runningConfig.Data.Tuntap.LanIPs = info.LanIPs;
runningConfig.Data.Tuntap.BufferSize = info.BufferSize;
runningConfig.Data.Update(); runningConfig.Data.Update();
if (Status == TuntapStatus.Running) if (Status == TuntapStatus.Running)
{ {
@@ -227,7 +230,8 @@ namespace linker.plugins.tuntap
LanIPs = runningConfig.Data.Tuntap.LanIPs, LanIPs = runningConfig.Data.Tuntap.LanIPs,
MachineId = config.Data.Client.Id, MachineId = config.Data.Client.Id,
Status = Status, Status = Status,
Error = tuntapVea.Error Error = tuntapVea.Error,
BufferSize = runningConfig.Data.Tuntap.BufferSize
}; };
} }
/// <summary> /// <summary>
@@ -377,12 +381,8 @@ namespace linker.plugins.tuntap
await socket.ConnectAsync(new IPEndPoint(IPAddress.Loopback, tuntapProxy.LocalEndpoint.Port)).WaitAsync(TimeSpan.FromMilliseconds(100)); await socket.ConnectAsync(new IPEndPoint(IPAddress.Loopback, tuntapProxy.LocalEndpoint.Port)).WaitAsync(TimeSpan.FromMilliseconds(100));
socket.SafeClose(); socket.SafeClose();
} }
catch (Exception ex) catch (Exception)
{ {
LoggerHelper.Instance.Error($"tuntap proxy {new IPEndPoint(IPAddress.Loopback, tuntapProxy.LocalEndpoint.Port)} {ex}");
tuntapProxy.Start();
LoggerHelper.Instance.Debug($"tuntap proxy restart in {new IPEndPoint(IPAddress.Loopback, tuntapProxy.LocalEndpoint.Port)}");
Stop(); Stop();
await Task.Delay(5000); await Task.Delay(5000);
Run(); Run();

View File

@@ -20,6 +20,7 @@ namespace linker.plugins.tuntap.config
} }
public uint IpInt { get; private set; } public uint IpInt { get; private set; }
public byte BufferSize { get; set; } = 3;
/// <summary> /// <summary>
/// 局域网IP列表 /// 局域网IP列表

View File

@@ -37,9 +37,6 @@ namespace linker.plugins.tuntap.proxy
this.runningConfig = runningConfig; this.runningConfig = runningConfig;
this.config = config; this.config = config;
Start();
LoggerHelper.Instance.Info($"start tuntap proxy, listen port : {LocalEndpoint}");
//监听打洞连接成功 //监听打洞连接成功
tunnelTransfer.SetConnectedCallback("tuntap", OnConnected); tunnelTransfer.SetConnectedCallback("tuntap", OnConnected);
//监听中继连接成功 //监听中继连接成功
@@ -51,7 +48,7 @@ namespace linker.plugins.tuntap.proxy
{ {
Stop(proxyEP.Port); Stop(proxyEP.Port);
} }
Start(new IPEndPoint(IPAddress.Any, 0)); Start(new IPEndPoint(IPAddress.Any, 0), runningConfig.Data.Tuntap.BufferSize);
proxyEP = new IPEndPoint(IPAddress.Any, LocalEndpoint.Port); proxyEP = new IPEndPoint(IPAddress.Any, LocalEndpoint.Port);
} }

View File

@@ -65,6 +65,7 @@ namespace linker.plugins.tuntap.vea
public string Error { get; set; } public string Error { get; set; }
public byte BufferSize { get; set; } = 3;
} }
[MemoryPackable] [MemoryPackable]

View File

@@ -108,7 +108,7 @@ namespace linker.server
/// 开始中继不再处理包在此之前应该先调用Cancel取消处理包在等待一段时间后再开始中继 /// 开始中继不再处理包在此之前应该先调用Cancel取消处理包在等待一段时间后再开始中继
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
public Task RelayAsync(); public Task RelayAsync(byte bufferSize);
/// <summary> /// <summary>
/// 取消处理包 /// 取消处理包
@@ -234,7 +234,7 @@ namespace linker.server
public abstract Task<bool> SendAsync(ReadOnlyMemory<byte> data); public abstract Task<bool> SendAsync(ReadOnlyMemory<byte> data);
public abstract Task<bool> SendAsync(byte[] data, int length); public abstract Task<bool> SendAsync(byte[] data, int length);
public abstract Task RelayAsync(); public abstract Task RelayAsync(byte bufferSize);
public virtual void Cancel() public virtual void Cancel()
@@ -508,16 +508,16 @@ namespace linker.server
return await SendAsync(data.AsMemory(0, length)); return await SendAsync(data.AsMemory(0, length));
} }
public override async Task RelayAsync() public override async Task RelayAsync(byte bufferSize)
{ {
if (TargetNetworkStream != null) if (TargetNetworkStream != null)
{ {
await CopyToAsync(SourceNetworkStream, TargetNetworkStream); await CopyToAsync(bufferSize,SourceNetworkStream, TargetNetworkStream);
} }
} }
private async Task CopyToAsync(NetworkStream source, NetworkStream destination) private async Task CopyToAsync(byte bufferSize,NetworkStream source, NetworkStream destination)
{ {
byte[] buffer = ArrayPool<byte>.Shared.Rent(8 * 1024); byte[] buffer = ArrayPool<byte>.Shared.Rent((1<< bufferSize) * 1024);
try try
{ {
int bytesRead; int bytesRead;