mirror of
https://github.com/snltty/linker.git
synced 2025-10-09 02:50:12 +08:00
虚拟网卡ping值
This commit is contained in:
22
.github/workflows/dotnet.yml
vendored
22
.github/workflows/dotnet.yml
vendored
@@ -48,16 +48,24 @@ jobs:
|
||||
env:
|
||||
GITHUB_TOKEN: '${{ secrets.ACTIONS_TOKEN }}'
|
||||
with:
|
||||
tag_name: v1.2.0.5
|
||||
release_name: v1.2.0.5.${{ steps.date.outputs.today }}
|
||||
tag_name: v1.2.0.6
|
||||
release_name: v1.2.0.6.${{ steps.date.outputs.today }}
|
||||
draft: false
|
||||
prerelease: false
|
||||
body: |
|
||||
1. UDP端口映射连接(无ssl加密)
|
||||
2. UDP打洞,纯净版(无ssl加密)
|
||||
3. 如果当前版本小于v1.2.0.4,则windows下需要重新卸载安装服务
|
||||
4. 先更新所有客户端,再更新服务端(先更新服务端会获取不到客户端列表)
|
||||
5. 用不上无加密UDP打洞的可以不更新
|
||||
1. 显示虚拟网卡ping值
|
||||
2. 更新服务器,更新服务器,更新服务器
|
||||
|
||||
#- name: upload win x86 oss
|
||||
# id: upload-win-x86-oss
|
||||
# uses: tvrcgo/oss-action@v0.1.1
|
||||
# with:
|
||||
# region: oss-cn-guangzhou
|
||||
# key-id: '${{ secrets.ALIYUN_OSS_ID }}'
|
||||
# key-secret: '${{ secrets.ALIYUN_OSS_SECRET }}'
|
||||
# bucket: snltty
|
||||
# asset-path: ./public/publish-zip/linker-win-x86.zip
|
||||
# target-path: /linker/v1.2.0.6/linker-win-x86.zip
|
||||
|
||||
- name: upload win x86
|
||||
id: upload-win-x86
|
||||
|
@@ -38,8 +38,21 @@ sudo pfctl -f /etc/pf.conf -e
|
||||
|
||||
:::tip[2、情况2,你的设备无法使用NAT转发时]
|
||||
|
||||
1. 你的设备无法使用NAT转发(一般出现在低版本windows下,win10以下),那你只能使用windows的端口转发功能来访问你当前设备局域网下的其它设备
|
||||
1. 你的设备无法使用NAT转发(一般出现在低版本windows下,win10以下),那你只能使用端口转发功能来访问你当前设备局域网下的其它设备
|
||||
2. 按如下配置。当其它设备通过`192.168.54.2:12345` 访问时,将访问到你的局域网的`192.168.1.35:3389`
|
||||
3. macos下需要你自己在**被访问端**添加端口转发
|
||||
```
|
||||
//编辑 pf 配置文件
|
||||
sudo nano /etc/pf.conf
|
||||
|
||||
//添加转发规则
|
||||
rdr pass on en0 inet proto tcp from any to any port 33890 -> 127.0.0.1 port 3389
|
||||
rdr pass on en0 inet proto udp from any to any port 33890 -> 127.0.0.1 port 3389
|
||||
|
||||
//启用并重新加载 pf
|
||||
sudo pfctl -f /etc/pf.conf
|
||||
sudo pfctl -e
|
||||
```
|
||||
|
||||

|
||||
|
||||
|
35
linker.libs/OperatingManager.cs
Normal file
35
linker.libs/OperatingManager.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
using System.Collections.Concurrent;
|
||||
using System.Reflection.PortableExecutable;
|
||||
using System.Threading;
|
||||
|
||||
namespace linker.libs
|
||||
{
|
||||
public sealed class OperatingManager
|
||||
{
|
||||
private uint operating = 0;
|
||||
public bool Operating => operating == 1;
|
||||
|
||||
public bool StartOperation()
|
||||
{
|
||||
return Interlocked.CompareExchange(ref operating, 1, 0) == 0;
|
||||
}
|
||||
public void StopOperation()
|
||||
{
|
||||
Interlocked.Exchange(ref operating, 0);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class OperatingMultipleManager
|
||||
{
|
||||
private readonly ConcurrentDictionary<string, bool> dicOperating = new ConcurrentDictionary<string, bool>();
|
||||
|
||||
public bool StartOperation(string key)
|
||||
{
|
||||
return dicOperating.TryAdd(key, true);
|
||||
}
|
||||
public void StopOperation(string key)
|
||||
{
|
||||
dicOperating.TryRemove(key, out _);
|
||||
}
|
||||
}
|
||||
}
|
21
linker.libs/VersionManager.cs
Normal file
21
linker.libs/VersionManager.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
|
||||
using System.Threading;
|
||||
|
||||
namespace linker.libs
|
||||
{
|
||||
public sealed class VersionManager
|
||||
{
|
||||
private ulong version = 0;
|
||||
|
||||
public bool Eq(ulong outsideVersion, out ulong insideVersion)
|
||||
{
|
||||
insideVersion = version;
|
||||
return outsideVersion == version;
|
||||
}
|
||||
|
||||
public void Add()
|
||||
{
|
||||
Interlocked.Increment(ref version);
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,6 +1,7 @@
|
||||
using linker.libs;
|
||||
using linker.libs.extends;
|
||||
using Microsoft.Win32.SafeHandles;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
@@ -165,9 +166,33 @@ namespace linker.tun
|
||||
|
||||
public void AddForward(List<LinkerTunDeviceForwardItem> forwards)
|
||||
{
|
||||
string[] commands = forwards.Where(c => c != null && c.Enable).SelectMany(c =>
|
||||
{
|
||||
return new string[] {
|
||||
$"sysctl -w net.ipv4.ip_forward=1",
|
||||
$"iptables -t nat -A PREROUTING -p tcp --dport {c.ListenPort} -j DNAT --to-destination {c.ConnectAddr}:{c.ConnectPort}",
|
||||
$"iptables -t nat -A POSTROUTING -p tcp --dport {c.ConnectPort} -j MASQUERADE",
|
||||
$"iptables -t nat -A PREROUTING -p udp --dport {c.ListenPort} -j DNAT --to-destination {c.ConnectAddr}:{c.ConnectPort}",
|
||||
$"iptables -t nat -A POSTROUTING -p udp --dport {c.ConnectPort} -j MASQUERADE",
|
||||
};
|
||||
|
||||
}).ToArray();
|
||||
CommandHelper.Windows(string.Empty, commands);
|
||||
}
|
||||
public void RemoveForward(List<LinkerTunDeviceForwardItem> forwards)
|
||||
{
|
||||
string[] commands = forwards.Where(c => c != null && c.Enable).SelectMany(c =>
|
||||
{
|
||||
return new string[] {
|
||||
$"sysctl -w net.ipv4.ip_forward=1",
|
||||
$"iptables -t nat -D PREROUTING -p tcp --dport {c.ListenPort} -j DNAT --to-destination {c.ConnectAddr}:{c.ConnectPort}",
|
||||
$"iptables -t nat -D POSTROUTING -p tcp --dport {c.ConnectPort} -j MASQUERADE",
|
||||
$"iptables -t nat -D PREROUTING -p udp --dport {c.ListenPort} -j DNAT --to-destination {c.ConnectAddr}:{c.ConnectPort}",
|
||||
$"iptables -t nat -D POSTROUTING -p udp --dport {c.ConnectPort} -j MASQUERADE"
|
||||
};
|
||||
|
||||
}).ToArray();
|
||||
CommandHelper.Windows(string.Empty, commands);
|
||||
}
|
||||
|
||||
|
||||
|
@@ -13,7 +13,7 @@ namespace linker.tunnel.transport
|
||||
{
|
||||
public string Name => "udp";
|
||||
|
||||
public string Label => "UDP、非常纯";
|
||||
public string Label => "UDP、非常纯,无ssl";
|
||||
|
||||
public TunnelProtocolType ProtocolType => TunnelProtocolType.Udp;
|
||||
public TunnelWanPortProtocolType AllowWanPortProtocolType => TunnelWanPortProtocolType.Udp;
|
||||
|
@@ -17,7 +17,7 @@ namespace linker.tunnel.transport
|
||||
{
|
||||
public string Name => "UdpPortMap";
|
||||
|
||||
public string Label => "UDP、端口映射";
|
||||
public string Label => "UDP、端口映射,无ssl";
|
||||
|
||||
public TunnelProtocolType ProtocolType => TunnelProtocolType.Udp;
|
||||
|
||||
|
@@ -55,6 +55,14 @@
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
<template v-if="showDelay">
|
||||
<template v-if="tuntap.list[scope.row.MachineId].Delay>=0 && tuntap.list[scope.row.MachineId].Delay<=100">
|
||||
<div class="delay green">{{ tuntap.list[scope.row.MachineId].Delay }}ms</div>
|
||||
</template>
|
||||
<template>
|
||||
<div class="delay yellow">{{ tuntap.list[scope.row.MachineId].Delay }}ms</div>
|
||||
</template>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -65,12 +73,17 @@ import { stopTuntap, runTuntap } from '@/apis/tuntap';
|
||||
import { ElMessage } from 'element-plus';
|
||||
import { useTuntap } from './tuntap';
|
||||
import {Loading} from '@element-plus/icons-vue'
|
||||
import { injectGlobalData } from '@/provide';
|
||||
import { computed } from 'vue';
|
||||
export default {
|
||||
emits: ['edit','refresh'],
|
||||
components:{Loading},
|
||||
setup(props, { emit }) {
|
||||
|
||||
const tuntap = useTuntap();
|
||||
const globalData = injectGlobalData();
|
||||
|
||||
const showDelay = computed(()=>globalData.value.config.Running.Tuntap.ShowDelay);
|
||||
const handleTuntap = (tuntap) => {
|
||||
const fn = tuntap.running ? stopTuntap (tuntap.MachineId) : runTuntap(tuntap.MachineId);
|
||||
tuntap.loading = true;
|
||||
@@ -88,7 +101,7 @@ export default {
|
||||
}
|
||||
|
||||
return {
|
||||
tuntap, handleTuntap, handleTuntapIP,handleTuntapRefresh
|
||||
tuntap,showDelay, handleTuntap, handleTuntapIP,handleTuntapRefresh
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -119,5 +132,7 @@ export default {
|
||||
-webkit-text-fill-color:hsla(0,0%,100%,0);
|
||||
}
|
||||
}
|
||||
.delay{position: absolute;right:0;bottom:0;line-height:normal}
|
||||
|
||||
|
||||
</style>
|
@@ -3,26 +3,41 @@
|
||||
<div>
|
||||
<el-form ref="ruleFormRef" :model="state.ruleForm" :rules="state.rules" label-width="140">
|
||||
<el-form-item prop="gateway" style="margin-bottom:0">
|
||||
赐予此设备IP,其它可以通过这个IP访问
|
||||
赐予此设备IP,其它设备可通过此IP访问
|
||||
</el-form-item>
|
||||
<el-form-item label="此设备的虚拟网卡IP" prop="IP">
|
||||
<el-input v-model="state.ruleForm.IP" style="width:12rem" /> / <el-input @change="handlePrefixLengthChange" v-model="state.ruleForm.PrefixLength" style="width:4rem" />
|
||||
<el-input v-model="state.ruleForm.IP" style="width:14rem" />
|
||||
<span>/</span>
|
||||
<el-input @change="handlePrefixLengthChange" v-model="state.ruleForm.PrefixLength" style="width:4rem" />
|
||||
<span style="width: 3rem;"></span>
|
||||
<el-checkbox v-model="state.ruleForm.ShowDelay" label="显示延迟" size="large" />
|
||||
<el-popover
|
||||
placement="top" title="提示" :width="400" trigger="hover"
|
||||
content="在测试延迟时,如果未连接,将自动去打洞连接,当你有一百个设备时,每个设备都同时去与其它99台设备连接,这数据量不小,所以尽量不要个设备都勾选"
|
||||
>
|
||||
<template #reference>
|
||||
<el-checkbox v-model="state.ruleForm.AutoConnect" label="自动连接?" size="large" />
|
||||
</template>
|
||||
</el-popover>
|
||||
|
||||
</el-form-item>
|
||||
<el-form-item prop="upgrade" style="margin-bottom:0">
|
||||
<el-checkbox v-model="state.ruleForm.Upgrade" label="我很懂,我要使用高级功能(点对网和网对网)" size="large" />
|
||||
</el-form-item>
|
||||
<div class="upgrade-wrap" v-if="state.ruleForm.Upgrade">
|
||||
<el-form-item prop="gateway" style="margin-bottom:0">
|
||||
<el-checkbox v-model="state.ruleForm.Gateway" label="此设备在路由器(网对网,将对方的 局域网IP 转发到对方)" size="large" />
|
||||
<el-form-item prop="gateway" style="border-bottom: 1px solid #ddd;margin-bottom:0">
|
||||
<el-checkbox v-model="state.ruleForm.Gateway" label="此设备在路由器(网对网)" size="large" />
|
||||
</el-form-item>
|
||||
<el-form-item prop="gateway" style="margin-bottom:0">
|
||||
<span class="yellow">此设备可以用NAT转发,那填写局域网IP,其它交给NAT(linux、macos、win10+)</span>
|
||||
<el-form-item prop="nat" style="margin-bottom:0">
|
||||
<span class="yellow">此设备能使用NAT转发,只需局域网IP,剩下的交给NAT(linux、macos、win10+)</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="此设备局域网IP" prop="LanIP">
|
||||
<el-form-item label="此设备局域网IP" prop="LanIP" style="border-bottom: 1px solid #ddd;margin-bottom:0">
|
||||
<template v-for="(item, index) in state.ruleForm.LanIPs" :key="index">
|
||||
<div class="flex" style="margin-bottom:.6rem">
|
||||
<div class="flex-1">
|
||||
<el-input v-model="state.ruleForm.LanIPs[index]" style="width:12rem" /> / <el-input @change="handleMaskChange(index)" v-model="state.ruleForm.Masks[index]" style="width:4rem" />
|
||||
<el-input v-model="state.ruleForm.LanIPs[index]" style="width:14rem" />
|
||||
<span>/</span>
|
||||
<el-input @change="handleMaskChange(index)" v-model="state.ruleForm.Masks[index]" style="width:4rem" />
|
||||
</div>
|
||||
<div class="pdl-10">
|
||||
<el-button type="danger" @click="handleDel(index)"><el-icon><Delete /></el-icon></el-button>
|
||||
@@ -31,15 +46,15 @@
|
||||
</div>
|
||||
</template>
|
||||
</el-form-item>
|
||||
<el-form-item prop="gateway" style="margin-bottom:0">
|
||||
<span class="yellow">此设备不能用NAT转发,那可以使用系统端口转发实现类似的效果(仅windows)</span>
|
||||
<el-form-item prop="forward" style="margin-bottom:0">
|
||||
<span class="yellow">此设备无法使用NAT转发,或只想使用端口转发</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="端口转发" prop="foreards">
|
||||
<el-form-item label="端口转发" prop="forwards">
|
||||
<template v-for="(item, index) in state.ruleForm.Forwards" :key="index">
|
||||
<div class="flex" style="margin-bottom:.6rem">
|
||||
<div class="flex-1">
|
||||
<el-input v-model="item.ListenAddr" style="width:7rem" readonly /> : <el-input @change="handleForwardChange(index)" v-model="item.ListenPort" style="width:6rem" />
|
||||
-> <el-input v-model="item.ConnectAddr" style="width:12rem" /> : <el-input @change="handleForwardChange(index)" v-model="item.ConnectPort" style="width:6rem" />
|
||||
-> <el-input v-model="item.ConnectAddr" style="width:14rem" /> : <el-input @change="handleForwardChange(index)" v-model="item.ConnectPort" style="width:6rem" />
|
||||
</div>
|
||||
<div class="pdl-10">
|
||||
|
||||
@@ -85,6 +100,8 @@ export default {
|
||||
Masks: tuntap.value.current.Masks.slice(0),
|
||||
PrefixLength:tuntap.value.current.PrefixLength || 24,
|
||||
Gateway: tuntap.value.current.Gateway,
|
||||
ShowDelay: tuntap.value.current.ShowDelay,
|
||||
AutoConnect: tuntap.value.current.AutoConnect,
|
||||
Upgrade: tuntap.value.current.Upgrade,
|
||||
|
||||
Forwards:tuntap.value.current.Forwards.length == 0 ? [
|
||||
@@ -144,6 +161,8 @@ export default {
|
||||
json.Masks = masks;
|
||||
json.PrefixLength = +state.ruleForm.PrefixLength;
|
||||
json.Gateway = state.ruleForm.Gateway;
|
||||
json.ShowDelay = state.ruleForm.ShowDelay;
|
||||
json.AutoConnect = state.ruleForm.AutoConnect;
|
||||
json.Upgrade = state.ruleForm.Upgrade;
|
||||
json.Forwards = state.ruleForm.Forwards;
|
||||
json.Forwards.forEach(c=>{
|
||||
@@ -185,6 +204,6 @@ export default {
|
||||
.upgrade-wrap{
|
||||
border:1px solid #ddd;
|
||||
margin-bottom:2rem
|
||||
padding:1rem 0;
|
||||
padding:0 0 1rem 0;
|
||||
}
|
||||
</style>
|
@@ -55,7 +55,6 @@ export default {
|
||||
bufferSize:globalData.value.bufferSize
|
||||
});
|
||||
watch(()=>globalData.value.config.Running.Tunnel.Transports,()=>{
|
||||
console.log(globalData.value.config.Running.Tunnel.Transports);
|
||||
state.list = globalData.value.config.Running.Tunnel.Transports.sort((a,b)=>a.Order - b.Order);
|
||||
});
|
||||
|
||||
|
@@ -155,7 +155,12 @@ namespace linker.plugins.relay
|
||||
var servers = running.Data.Relay.Servers
|
||||
.Where(c => c.Disabled == false)
|
||||
.Where(c => string.IsNullOrWhiteSpace(c.Host) == false)
|
||||
.Where(c => c.Delay >= 0).OrderBy(c => c.Delay);
|
||||
.Where(c => c.Delay >= 0);
|
||||
if (running.Data.Relay.ByRelay)
|
||||
{
|
||||
servers = servers.OrderBy(c => c.Delay);
|
||||
}
|
||||
|
||||
foreach (RelayServerInfo item in servers)
|
||||
{
|
||||
ITransport transport = transports.FirstOrDefault(c => c.Type == item.RelayType);
|
||||
@@ -278,43 +283,20 @@ namespace linker.plugins.relay
|
||||
{
|
||||
try
|
||||
{
|
||||
var tasks = running.Data.Relay.Servers.Select(c =>
|
||||
foreach (var server in running.Data.Relay.Servers)
|
||||
{
|
||||
try
|
||||
{
|
||||
ITransport transport = transports.FirstOrDefault(d => d.Type == c.RelayType);
|
||||
if (transport == null) return null;
|
||||
ITransport transport = transports.FirstOrDefault(d => d.Type == server.RelayType);
|
||||
if (transport == null) continue;
|
||||
|
||||
IPEndPoint server = NetworkHelper.GetEndPoint(c.Host, 3478);
|
||||
|
||||
return new TestInfo
|
||||
{
|
||||
Server = c,
|
||||
Task = transport.RelayTestAsync(new RelayTestInfo
|
||||
IPEndPoint serverEP = NetworkHelper.GetEndPoint(server.Host, 3478);
|
||||
RelayTestResultInfo result = await transport.RelayTestAsync(new RelayTestInfo
|
||||
{
|
||||
MachineId = fileConfig.Data.Client.Id,
|
||||
SecretKey = c.SecretKey,
|
||||
Server = server,
|
||||
})
|
||||
};
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
return null;
|
||||
SecretKey = server.SecretKey,
|
||||
Server = serverEP,
|
||||
});
|
||||
|
||||
try
|
||||
{
|
||||
await Task.WhenAll(tasks.Where(c => c != null).Select(c => c.Task)).WaitAsync(TimeSpan.FromMilliseconds(5000)).ConfigureAwait(false);
|
||||
foreach (var item in tasks.Where(c => c != null))
|
||||
{
|
||||
item.Server.Delay = item.Task.Result.Delay;
|
||||
item.Server.Available = item.Task.Result.Available;
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
server.Delay = result.Delay;
|
||||
server.Available = result.Available;
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
|
@@ -228,7 +228,7 @@ namespace linker.plugins.relay.transport
|
||||
{
|
||||
Socket socket = new Socket(relayTestInfo.Server.AddressFamily, SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp);
|
||||
socket.KeepAlive();
|
||||
await socket.ConnectAsync(relayTestInfo.Server).WaitAsync(TimeSpan.FromMilliseconds(500)).ConfigureAwait(false);
|
||||
await socket.ConnectAsync(relayTestInfo.Server).WaitAsync(TimeSpan.FromMilliseconds(1000)).ConfigureAwait(false);
|
||||
|
||||
connection = await messengerResolver.BeginReceiveClient(socket);
|
||||
|
||||
@@ -249,7 +249,6 @@ namespace linker.plugins.relay.transport
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
@@ -46,17 +46,16 @@ namespace linker.plugins.tunnel
|
||||
/// <returns></returns>
|
||||
public TunnelListInfo Get(ApiControllerParamsInfo param)
|
||||
{
|
||||
uint hashCode = uint.Parse(param.Content);
|
||||
uint _hashCode = tunnelConfigTransfer.ConfigVersion;
|
||||
if (_hashCode != hashCode)
|
||||
ulong hashCode = ulong.Parse(param.Content);
|
||||
if (tunnelConfigTransfer.Version.Eq(hashCode,out ulong version))
|
||||
{
|
||||
return new TunnelListInfo
|
||||
{
|
||||
List = tunnelConfigTransfer.Config,
|
||||
HashCode = _hashCode
|
||||
HashCode = version
|
||||
};
|
||||
}
|
||||
return new TunnelListInfo { HashCode = _hashCode };
|
||||
return new TunnelListInfo { HashCode = version };
|
||||
}
|
||||
/// <summary>
|
||||
/// 刷新隧道信息
|
||||
@@ -145,7 +144,7 @@ namespace linker.plugins.tunnel
|
||||
public sealed class TunnelListInfo
|
||||
{
|
||||
public ConcurrentDictionary<string, TunnelTransportRouteLevelInfo> List { get; set; }
|
||||
public uint HashCode { get; set; }
|
||||
public ulong HashCode { get; set; }
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -24,11 +24,8 @@ namespace linker.plugins.tunnel
|
||||
private readonly TransportTcpPortMap transportTcpPortMap;
|
||||
private readonly TransportUdpPortMap transportUdpPortMap;
|
||||
|
||||
|
||||
private uint version = 0;
|
||||
public uint ConfigVersion => version;
|
||||
private ConcurrentDictionary<string, TunnelTransportRouteLevelInfo> configs = new ConcurrentDictionary<string, TunnelTransportRouteLevelInfo>();
|
||||
public ConcurrentDictionary<string, TunnelTransportRouteLevelInfo> Config => configs;
|
||||
public VersionManager Version { get; } = new VersionManager();
|
||||
public ConcurrentDictionary<string, TunnelTransportRouteLevelInfo> Config { get; } = new ConcurrentDictionary<string, TunnelTransportRouteLevelInfo>();
|
||||
|
||||
public TunnelConfigTransfer(FileConfig config, RunningConfig running, ClientSignInState clientSignInState, MessengerSender messengerSender, RunningConfigTransfer runningConfigTransfer, ITunnelAdapter tunnelAdapter, TransportTcpPortMap transportTcpPortMap, TransportUdpPortMap transportUdpPortMap)
|
||||
{
|
||||
@@ -108,8 +105,8 @@ namespace linker.plugins.tunnel
|
||||
/// <returns></returns>
|
||||
public TunnelTransportRouteLevelInfo OnRemoteRouteLevel(TunnelTransportRouteLevelInfo tunnelTransportFileConfigInfo)
|
||||
{
|
||||
configs.AddOrUpdate(tunnelTransportFileConfigInfo.MachineId, tunnelTransportFileConfigInfo, (a, b) => tunnelTransportFileConfigInfo);
|
||||
Interlocked.Increment(ref version);
|
||||
Config.AddOrUpdate(tunnelTransportFileConfigInfo.MachineId, tunnelTransportFileConfigInfo, (a, b) => tunnelTransportFileConfigInfo);
|
||||
Version.Add();
|
||||
return GetLocalRouteLevel();
|
||||
}
|
||||
private void GetRemoteRouteLevel()
|
||||
@@ -128,11 +125,11 @@ namespace linker.plugins.tunnel
|
||||
List<TunnelTransportRouteLevelInfo> list = MemoryPackSerializer.Deserialize<List<TunnelTransportRouteLevelInfo>>(result.Result.Data.Span);
|
||||
foreach (var item in list)
|
||||
{
|
||||
configs.AddOrUpdate(item.MachineId, item, (a, b) => item);
|
||||
Config.AddOrUpdate(item.MachineId, item, (a, b) => item);
|
||||
}
|
||||
TunnelTransportRouteLevelInfo config = GetLocalRouteLevel();
|
||||
configs.AddOrUpdate(config.MachineId, config, (a, b) => config);
|
||||
Interlocked.Increment(ref version);
|
||||
Config.AddOrUpdate(config.MachineId, config, (a, b) => config);
|
||||
Version.Add();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -145,7 +142,7 @@ namespace linker.plugins.tunnel
|
||||
RouteLevelPlus = running.Data.Tunnel.RouteLevelPlus,
|
||||
PortMapWan = running.Data.Tunnel.PortMapWan,
|
||||
PortMapLan = running.Data.Tunnel.PortMapLan,
|
||||
NeedReboot = reboot
|
||||
NeedReboot = false
|
||||
};
|
||||
}
|
||||
private void InitRouteLevel()
|
||||
@@ -157,7 +154,6 @@ namespace linker.plugins.tunnel
|
||||
}
|
||||
|
||||
|
||||
bool reboot = false;
|
||||
private void TestQuic()
|
||||
{
|
||||
if (OperatingSystem.IsWindows())
|
||||
@@ -172,7 +168,6 @@ namespace linker.plugins.tunnel
|
||||
File.Move("msquic.dll", "msquic.dll.temp", true);
|
||||
File.Move("msquic-openssl.dll", "msquic.dll", true);
|
||||
|
||||
reboot = true;
|
||||
Environment.Exit(1);
|
||||
}
|
||||
}
|
||||
|
@@ -46,17 +46,16 @@ namespace linker.plugins.tuntap
|
||||
/// <returns></returns>
|
||||
public TuntabListInfo Get(ApiControllerParamsInfo param)
|
||||
{
|
||||
uint hashCode = uint.Parse(param.Content);
|
||||
uint _hashCode = tuntapTransfer.InfosVersion;
|
||||
if (_hashCode != hashCode)
|
||||
ulong hashCode = ulong.Parse(param.Content);
|
||||
if (tuntapTransfer.Version.Eq(hashCode, out ulong version))
|
||||
{
|
||||
return new TuntabListInfo
|
||||
{
|
||||
List = tuntapTransfer.Infos,
|
||||
HashCode = _hashCode
|
||||
HashCode = version
|
||||
};
|
||||
}
|
||||
return new TuntabListInfo { HashCode = _hashCode };
|
||||
return new TuntabListInfo { HashCode = version };
|
||||
}
|
||||
/// <summary>
|
||||
/// 刷新网卡信息
|
||||
@@ -147,7 +146,7 @@ namespace linker.plugins.tuntap
|
||||
public sealed class TuntabListInfo
|
||||
{
|
||||
public ConcurrentDictionary<string, TuntapInfo> List { get; set; }
|
||||
public uint HashCode { get; set; }
|
||||
public ulong HashCode { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -12,6 +12,7 @@ using linker.plugins.client;
|
||||
using linker.plugins.messenger;
|
||||
using linker.plugins.tuntap.config;
|
||||
using linker.tun;
|
||||
using linker.tunnel.connection;
|
||||
|
||||
namespace linker.plugins.tuntap
|
||||
{
|
||||
@@ -25,16 +26,15 @@ namespace linker.plugins.tuntap
|
||||
private readonly LinkerTunDeviceAdapter linkerTunDeviceAdapter;
|
||||
|
||||
private string deviceName = "linker";
|
||||
private uint operating = 0;
|
||||
private List<IPAddress> routeIps = new List<IPAddress>();
|
||||
|
||||
private uint infosVersion = 0;
|
||||
public uint InfosVersion => infosVersion;
|
||||
|
||||
public VersionManager Version { get; } = new VersionManager();
|
||||
private readonly ConcurrentDictionary<string, TuntapInfo> tuntapInfos = new ConcurrentDictionary<string, TuntapInfo>();
|
||||
public ConcurrentDictionary<string, TuntapInfo> Infos => tuntapInfos;
|
||||
|
||||
public TuntapStatus Status => operating == 1 ? TuntapStatus.Operating : (TuntapStatus)(byte)linkerTunDeviceAdapter.Status;
|
||||
|
||||
private OperatingManager operatingManager = new OperatingManager();
|
||||
public TuntapStatus Status => operatingManager.Operating ? TuntapStatus.Operating : (TuntapStatus)(byte)linkerTunDeviceAdapter.Status;
|
||||
|
||||
public TuntapTransfer(MessengerSender messengerSender, ClientSignInState clientSignInState, LinkerTunDeviceAdapter linkerTunDeviceAdapter, FileConfig config, TuntapProxy tuntapProxy, RunningConfig runningConfig)
|
||||
{
|
||||
@@ -59,6 +59,7 @@ namespace linker.plugins.tuntap
|
||||
NetworkHelper.GetRouteLevel(config.Data.Client.Server, out routeIps);
|
||||
NotifyConfig();
|
||||
CheckTuntapStatusTask();
|
||||
PingTask();
|
||||
if (runningConfig.Data.Tuntap.Running)
|
||||
{
|
||||
Setup();
|
||||
@@ -71,7 +72,7 @@ namespace linker.plugins.tuntap
|
||||
/// </summary>
|
||||
public void Setup()
|
||||
{
|
||||
if (Interlocked.CompareExchange(ref operating, 1, 0) == 1)
|
||||
if (operatingManager.StartOperation() == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -111,7 +112,7 @@ namespace linker.plugins.tuntap
|
||||
}
|
||||
private void SetupAfter()
|
||||
{
|
||||
Interlocked.Exchange(ref operating, 0);
|
||||
operatingManager.StopOperation();
|
||||
NotifyConfig();
|
||||
}
|
||||
private void SetupSuccess()
|
||||
@@ -127,7 +128,7 @@ namespace linker.plugins.tuntap
|
||||
/// </summary>
|
||||
public void Shutdown()
|
||||
{
|
||||
if (Interlocked.CompareExchange(ref operating, 1, 0) == 1)
|
||||
if (operatingManager.StartOperation() == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -155,7 +156,7 @@ namespace linker.plugins.tuntap
|
||||
}
|
||||
private void ShutdownAfter()
|
||||
{
|
||||
Interlocked.Exchange(ref operating, 0);
|
||||
operatingManager.StopOperation();
|
||||
NotifyConfig();
|
||||
}
|
||||
private void ShutdownSuccess()
|
||||
@@ -188,6 +189,8 @@ namespace linker.plugins.tuntap
|
||||
runningConfig.Data.Tuntap.Masks = info.Masks;
|
||||
runningConfig.Data.Tuntap.PrefixLength = info.PrefixLength;
|
||||
runningConfig.Data.Tuntap.Gateway = info.Gateway;
|
||||
runningConfig.Data.Tuntap.ShowDelay = info.ShowDelay;
|
||||
runningConfig.Data.Tuntap.AutoConnect = info.AutoConnect;
|
||||
runningConfig.Data.Tuntap.Upgrade = info.Upgrade;
|
||||
runningConfig.Data.Tuntap.Forwards = info.Forwards;
|
||||
runningConfig.Data.Update();
|
||||
@@ -214,7 +217,7 @@ namespace linker.plugins.tuntap
|
||||
{
|
||||
DelRoute();
|
||||
tuntapInfos.AddOrUpdate(info.MachineId, info, (a, b) => info);
|
||||
Interlocked.Increment(ref infosVersion);
|
||||
Version.Add();
|
||||
AddRoute();
|
||||
});
|
||||
|
||||
@@ -240,7 +243,7 @@ namespace linker.plugins.tuntap
|
||||
}
|
||||
AddRoute();
|
||||
}
|
||||
Interlocked.Increment(ref infosVersion);
|
||||
Version.Add();
|
||||
});
|
||||
}
|
||||
/// <summary>
|
||||
@@ -260,9 +263,12 @@ namespace linker.plugins.tuntap
|
||||
Error = linkerTunDeviceAdapter.Error,
|
||||
Error1 = linkerTunDeviceAdapter.Error1,
|
||||
SystemInfo = $"{System.Runtime.InteropServices.RuntimeInformation.OSDescription} {(string.IsNullOrWhiteSpace(Environment.GetEnvironmentVariable("SNLTTY_LINKER_IS_DOCKER")) == false ? "Docker" : "")}",
|
||||
Gateway = runningConfig.Data.Tuntap.Gateway,
|
||||
Upgrade = runningConfig.Data.Tuntap.Upgrade,
|
||||
|
||||
Forwards = runningConfig.Data.Tuntap.Forwards,
|
||||
Switch = (runningConfig.Data.Tuntap.Gateway ? TuntapSwitch.Gateway : 0)
|
||||
| (runningConfig.Data.Tuntap.Upgrade ? TuntapSwitch.Upgrade : 0)
|
||||
| (runningConfig.Data.Tuntap.ShowDelay ? TuntapSwitch.ShowDelay : 0)
|
||||
| (runningConfig.Data.Tuntap.AutoConnect ? TuntapSwitch.AutoConnect : 0)
|
||||
};
|
||||
if (runningConfig.Data.Tuntap.Masks.Length != runningConfig.Data.Tuntap.LanIPs.Length)
|
||||
{
|
||||
@@ -404,7 +410,7 @@ namespace linker.plugins.tuntap
|
||||
await Task.Delay(15000).ConfigureAwait(false);
|
||||
try
|
||||
{
|
||||
if (runningConfig.Data.Tuntap.Running && OperatingSystem.IsWindows() && operating == 0)
|
||||
if (runningConfig.Data.Tuntap.Running && OperatingSystem.IsWindows() && operatingManager.Operating == false)
|
||||
{
|
||||
await CheckInterface().ConfigureAwait(false);
|
||||
}
|
||||
@@ -419,18 +425,64 @@ namespace linker.plugins.tuntap
|
||||
{
|
||||
NetworkInterface networkInterface = NetworkInterface.GetAllNetworkInterfaces().FirstOrDefault(c => c.Name == deviceName);
|
||||
|
||||
if (networkInterface == null || networkInterface.OperationalStatus != OperationalStatus.Up && operating == 0)
|
||||
if (networkInterface == null || networkInterface.OperationalStatus != OperationalStatus.Up && operatingManager.Operating == false)
|
||||
{
|
||||
LoggerHelper.Instance.Error($"tuntap inerface {deviceName} is {networkInterface?.OperationalStatus ?? OperationalStatus.Unknown}, restarting");
|
||||
Shutdown();
|
||||
await Task.Delay(5000).ConfigureAwait(false);
|
||||
|
||||
networkInterface = NetworkInterface.GetAllNetworkInterfaces().FirstOrDefault(c => c.Name == deviceName);
|
||||
if (networkInterface == null || networkInterface.OperationalStatus != OperationalStatus.Up && operating == 0)
|
||||
if (networkInterface == null || networkInterface.OperationalStatus != OperationalStatus.Up && operatingManager.Operating == false)
|
||||
{
|
||||
Setup();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void PingTask()
|
||||
{
|
||||
Task.Run(async () =>
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
if (Status == TuntapStatus.Running && runningConfig.Data.Tuntap.ShowDelay)
|
||||
{
|
||||
var items = tuntapInfos.Values.Where(c => c.IP != null && c.IP.Equals(IPAddress.Any) == false);
|
||||
if (runningConfig.Data.Tuntap.AutoConnect == false)
|
||||
{
|
||||
var connections = tuntapProxy.GetConnections();
|
||||
items = items.Where(c => (connections.TryGetValue(c.MachineId, out ITunnelConnection connection) && connection.Connected) || c.MachineId == config.Data.Client.Id);
|
||||
}
|
||||
|
||||
|
||||
var tasks = items.Select(c =>
|
||||
{
|
||||
Ping ping = new Ping();
|
||||
return new PingTaskInfo
|
||||
{
|
||||
TuntapInfo = c,
|
||||
Ping = ping,
|
||||
Task = ping.SendPingAsync(c.IP, 1000)
|
||||
};
|
||||
});
|
||||
await Task.WhenAll(tasks.Select(c => c.Task));
|
||||
foreach (var item in tasks.Where(c => c.Task.Result != null))
|
||||
{
|
||||
item.TuntapInfo.Delay = item.Task.Result.Status == IPStatus.Success ? (int)item.Task.Result.RoundtripTime : -1;
|
||||
item.Ping.Dispose();
|
||||
}
|
||||
Version.Add();
|
||||
}
|
||||
await Task.Delay(3000);
|
||||
}
|
||||
});
|
||||
}
|
||||
public sealed class PingTaskInfo
|
||||
{
|
||||
public TuntapInfo TuntapInfo { get; set; }
|
||||
public Ping Ping { get; set; }
|
||||
public Task<PingReply> Task { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -4,15 +4,18 @@ using System.Net;
|
||||
|
||||
namespace linker.plugins.tuntap.config
|
||||
{
|
||||
public sealed class TuntapConfigInfo
|
||||
[MemoryPackable]
|
||||
public sealed partial class TuntapConfigInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// 网卡IP
|
||||
/// </summary>
|
||||
[MemoryPackAllowSerialize]
|
||||
public IPAddress IP { get; set; } = IPAddress.Any;
|
||||
/// <summary>
|
||||
/// 局域网IP列表
|
||||
/// </summary>
|
||||
[MemoryPackAllowSerialize]
|
||||
public IPAddress[] LanIPs { get; set; } = Array.Empty<IPAddress>();
|
||||
/// <summary>
|
||||
/// 局域网掩码列表,与IP列表一一对应
|
||||
@@ -33,9 +36,19 @@ namespace linker.plugins.tuntap.config
|
||||
/// </summary>
|
||||
public bool Gateway { get; set; }
|
||||
/// <summary>
|
||||
/// 显示延迟
|
||||
/// </summary>
|
||||
public bool ShowDelay { get; set; }
|
||||
/// <summary>
|
||||
/// 自动连接
|
||||
/// </summary>
|
||||
public bool AutoConnect { get; set; }
|
||||
/// <summary>
|
||||
/// 使用高级功能
|
||||
/// </summary>
|
||||
public bool Upgrade { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 端口转发列表
|
||||
/// </summary>
|
||||
@@ -103,6 +116,12 @@ namespace linker.plugins.tuntap.config
|
||||
|
||||
[MemoryPackAllowSerialize]
|
||||
public IPAddress IP { get; set; }
|
||||
/// <summary>
|
||||
/// 前缀长度
|
||||
/// </summary>
|
||||
public byte PrefixLength { get; set; } = 24;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 局域网IP
|
||||
/// </summary>
|
||||
@@ -115,11 +134,6 @@ namespace linker.plugins.tuntap.config
|
||||
public int[] Masks { get; set; } = Array.Empty<int>();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 前缀长度
|
||||
/// </summary>
|
||||
public byte PrefixLength { get; set; } = 24;
|
||||
|
||||
/// <summary>
|
||||
/// 网卡安装错误
|
||||
/// </summary>
|
||||
@@ -132,18 +146,120 @@ namespace linker.plugins.tuntap.config
|
||||
/// 系统信息
|
||||
/// </summary>
|
||||
public string SystemInfo { get; set; }
|
||||
/// <summary>
|
||||
/// 是否网关
|
||||
/// </summary>
|
||||
public bool Gateway { get; set; }
|
||||
/// <summary>
|
||||
/// 使用高级功能
|
||||
/// </summary>
|
||||
public bool Upgrade { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 端口转发列表
|
||||
/// </summary>
|
||||
public List<TuntapForwardInfo> Forwards { get; set; } = new List<TuntapForwardInfo>();
|
||||
|
||||
/// <summary>
|
||||
/// 延迟ms
|
||||
/// </summary>
|
||||
public int Delay { get; set; } = -1;
|
||||
|
||||
/// <summary>
|
||||
/// 开关,多个bool集合
|
||||
/// </summary>
|
||||
public TuntapSwitch Switch { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否网关
|
||||
/// </summary>
|
||||
[MemoryPackIgnore]
|
||||
public bool Gateway
|
||||
{
|
||||
get
|
||||
{
|
||||
return (Switch & TuntapSwitch.Gateway) == TuntapSwitch.Gateway;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
Switch |= TuntapSwitch.Gateway;
|
||||
}
|
||||
else
|
||||
{
|
||||
Switch &= ~TuntapSwitch.Gateway;
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 显示延迟
|
||||
/// </summary>
|
||||
[MemoryPackIgnore]
|
||||
public bool ShowDelay
|
||||
{
|
||||
get
|
||||
{
|
||||
return (Switch & TuntapSwitch.ShowDelay) == TuntapSwitch.ShowDelay;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
Switch |= TuntapSwitch.ShowDelay;
|
||||
}
|
||||
else
|
||||
{
|
||||
Switch &= ~TuntapSwitch.ShowDelay;
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 自动连接
|
||||
/// </summary>
|
||||
[MemoryPackIgnore]
|
||||
public bool AutoConnect
|
||||
{
|
||||
get
|
||||
{
|
||||
return (Switch & TuntapSwitch.AutoConnect) == TuntapSwitch.AutoConnect;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
Switch |= TuntapSwitch.AutoConnect;
|
||||
}
|
||||
else
|
||||
{
|
||||
Switch &= ~TuntapSwitch.AutoConnect;
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 使用高级功能
|
||||
/// </summary>
|
||||
[MemoryPackIgnore]
|
||||
public bool Upgrade
|
||||
{
|
||||
get
|
||||
{
|
||||
return (Switch & TuntapSwitch.Upgrade) == TuntapSwitch.Upgrade;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
Switch |= TuntapSwitch.Upgrade;
|
||||
}
|
||||
else
|
||||
{
|
||||
Switch &= ~TuntapSwitch.Upgrade;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum TuntapSwitch
|
||||
{
|
||||
Gateway = 1,
|
||||
ShowDelay = 2,
|
||||
Upgrade = 4,
|
||||
AutoConnect = 8,
|
||||
}
|
||||
|
||||
|
||||
|
@@ -9,8 +9,6 @@ using System.Collections.Concurrent;
|
||||
using linker.plugins.tuntap.config;
|
||||
using linker.tun;
|
||||
using System.Buffers.Binary;
|
||||
using System.Net.Sockets;
|
||||
using System.Net;
|
||||
|
||||
namespace linker.plugins.tuntap.proxy
|
||||
{
|
||||
@@ -27,8 +25,7 @@ namespace linker.plugins.tuntap.proxy
|
||||
private readonly ConcurrentDictionary<string, ITunnelConnection> connections = new ConcurrentDictionary<string, ITunnelConnection>();
|
||||
private readonly ConcurrentDictionary<uint, ITunnelConnection> ipConnections = new ConcurrentDictionary<uint, ITunnelConnection>();
|
||||
|
||||
SemaphoreSlim slimGlobal = new SemaphoreSlim(1);
|
||||
private readonly ConcurrentDictionary<string, SemaphoreSlim> dicLocks = new ConcurrentDictionary<string, SemaphoreSlim>();
|
||||
private readonly OperatingMultipleManager operatingMultipleManager = new OperatingMultipleManager();
|
||||
|
||||
public TuntapProxy(TunnelTransfer tunnelTransfer, RelayTransfer relayTransfer, RunningConfig runningConfig, FileConfig config, LinkerTunDeviceAdapter linkerTunDeviceAdapter)
|
||||
{
|
||||
@@ -112,7 +109,6 @@ namespace linker.plugins.tuntap.proxy
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 设置IP,等下有连接进来,用IP匹配,才能知道这个连接是要连谁
|
||||
/// </summary>
|
||||
@@ -179,23 +175,13 @@ namespace linker.plugins.tuntap.proxy
|
||||
return connection;
|
||||
}
|
||||
|
||||
await slimGlobal.WaitAsync().ConfigureAwait(false);
|
||||
if (dicLocks.TryGetValue(machineId, out SemaphoreSlim slim) == false)
|
||||
if(operatingMultipleManager.StartOperation(machineId) ==false)
|
||||
{
|
||||
slim = new SemaphoreSlim(1);
|
||||
dicLocks.TryAdd(machineId, slim);
|
||||
return null;
|
||||
}
|
||||
slimGlobal.Release();
|
||||
|
||||
await slim.WaitAsync().ConfigureAwait(false);
|
||||
|
||||
try
|
||||
{
|
||||
if (connections.TryGetValue(machineId, out connection) && connection.Connected)
|
||||
{
|
||||
return connection;
|
||||
}
|
||||
|
||||
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG) LoggerHelper.Instance.Debug($"tuntap tunnel to {machineId}");
|
||||
|
||||
connection = await tunnelTransfer.ConnectAsync(machineId, "tuntap", TunnelProtocolType.None).ConfigureAwait(false);
|
||||
@@ -210,7 +196,6 @@ namespace linker.plugins.tuntap.proxy
|
||||
connection = await relayTransfer.ConnectAsync(config.Data.Client.Id, machineId, "tuntap").ConfigureAwait(false);
|
||||
if (connection != null)
|
||||
{
|
||||
//tunnelTransfer.StartBackground(machineId, "tuntap");
|
||||
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG) LoggerHelper.Instance.Debug($"tuntap relay success,{connection.ToString()}");
|
||||
}
|
||||
}
|
||||
@@ -224,7 +209,7 @@ namespace linker.plugins.tuntap.proxy
|
||||
}
|
||||
finally
|
||||
{
|
||||
slim.Release();
|
||||
operatingMultipleManager.StopOperation(machineId);
|
||||
}
|
||||
return connection;
|
||||
}
|
||||
|
Reference in New Issue
Block a user