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:
|
env:
|
||||||
GITHUB_TOKEN: '${{ secrets.ACTIONS_TOKEN }}'
|
GITHUB_TOKEN: '${{ secrets.ACTIONS_TOKEN }}'
|
||||||
with:
|
with:
|
||||||
tag_name: v1.2.0.5
|
tag_name: v1.2.0.6
|
||||||
release_name: v1.2.0.5.${{ steps.date.outputs.today }}
|
release_name: v1.2.0.6.${{ steps.date.outputs.today }}
|
||||||
draft: false
|
draft: false
|
||||||
prerelease: false
|
prerelease: false
|
||||||
body: |
|
body: |
|
||||||
1. UDP端口映射连接(无ssl加密)
|
1. 显示虚拟网卡ping值
|
||||||
2. UDP打洞,纯净版(无ssl加密)
|
2. 更新服务器,更新服务器,更新服务器
|
||||||
3. 如果当前版本小于v1.2.0.4,则windows下需要重新卸载安装服务
|
|
||||||
4. 先更新所有客户端,再更新服务端(先更新服务端会获取不到客户端列表)
|
#- name: upload win x86 oss
|
||||||
5. 用不上无加密UDP打洞的可以不更新
|
# 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
|
- name: upload win x86
|
||||||
id: upload-win-x86
|
id: upload-win-x86
|
||||||
|
@@ -38,8 +38,21 @@ sudo pfctl -f /etc/pf.conf -e
|
|||||||
|
|
||||||
:::tip[2、情况2,你的设备无法使用NAT转发时]
|
:::tip[2、情况2,你的设备无法使用NAT转发时]
|
||||||
|
|
||||||
1. 你的设备无法使用NAT转发(一般出现在低版本windows下,win10以下),那你只能使用windows的端口转发功能来访问你当前设备局域网下的其它设备
|
1. 你的设备无法使用NAT转发(一般出现在低版本windows下,win10以下),那你只能使用端口转发功能来访问你当前设备局域网下的其它设备
|
||||||
2. 按如下配置。当其它设备通过`192.168.54.2:12345` 访问时,将访问到你的局域网的`192.168.1.35:3389`
|
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;
|
||||||
using linker.libs.extends;
|
using linker.libs.extends;
|
||||||
using Microsoft.Win32.SafeHandles;
|
using Microsoft.Win32.SafeHandles;
|
||||||
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
@@ -131,7 +132,7 @@ namespace linker.tun
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
IPAddress network = NetworkHelper.ToNetworkIp(address, NetworkHelper.MaskValue(prefixLength));
|
IPAddress network = NetworkHelper.ToNetworkIp(address, NetworkHelper.MaskValue(prefixLength));
|
||||||
CommandHelper.Linux(string.Empty, new string[] {
|
CommandHelper.Linux(string.Empty, new string[] {
|
||||||
$"sysctl -w net.ipv4.ip_forward=1",
|
$"sysctl -w net.ipv4.ip_forward=1",
|
||||||
$"iptables -t nat -A POSTROUTING ! -o {Name} -s {network}/{prefixLength} -j MASQUERADE",
|
$"iptables -t nat -A POSTROUTING ! -o {Name} -s {network}/{prefixLength} -j MASQUERADE",
|
||||||
});
|
});
|
||||||
@@ -165,9 +166,33 @@ namespace linker.tun
|
|||||||
|
|
||||||
public void AddForward(List<LinkerTunDeviceForwardItem> forwards)
|
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)
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -287,7 +312,7 @@ namespace linker.tun
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -13,7 +13,7 @@ namespace linker.tunnel.transport
|
|||||||
{
|
{
|
||||||
public string Name => "udp";
|
public string Name => "udp";
|
||||||
|
|
||||||
public string Label => "UDP、非常纯";
|
public string Label => "UDP、非常纯,无ssl";
|
||||||
|
|
||||||
public TunnelProtocolType ProtocolType => TunnelProtocolType.Udp;
|
public TunnelProtocolType ProtocolType => TunnelProtocolType.Udp;
|
||||||
public TunnelWanPortProtocolType AllowWanPortProtocolType => TunnelWanPortProtocolType.Udp;
|
public TunnelWanPortProtocolType AllowWanPortProtocolType => TunnelWanPortProtocolType.Udp;
|
||||||
|
@@ -17,7 +17,7 @@ namespace linker.tunnel.transport
|
|||||||
{
|
{
|
||||||
public string Name => "UdpPortMap";
|
public string Name => "UdpPortMap";
|
||||||
|
|
||||||
public string Label => "UDP、端口映射";
|
public string Label => "UDP、端口映射,无ssl";
|
||||||
|
|
||||||
public TunnelProtocolType ProtocolType => TunnelProtocolType.Udp;
|
public TunnelProtocolType ProtocolType => TunnelProtocolType.Udp;
|
||||||
|
|
||||||
|
@@ -55,6 +55,14 @@
|
|||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</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>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -65,12 +73,17 @@ import { stopTuntap, runTuntap } from '@/apis/tuntap';
|
|||||||
import { ElMessage } from 'element-plus';
|
import { ElMessage } from 'element-plus';
|
||||||
import { useTuntap } from './tuntap';
|
import { useTuntap } from './tuntap';
|
||||||
import {Loading} from '@element-plus/icons-vue'
|
import {Loading} from '@element-plus/icons-vue'
|
||||||
|
import { injectGlobalData } from '@/provide';
|
||||||
|
import { computed } from 'vue';
|
||||||
export default {
|
export default {
|
||||||
emits: ['edit','refresh'],
|
emits: ['edit','refresh'],
|
||||||
components:{Loading},
|
components:{Loading},
|
||||||
setup(props, { emit }) {
|
setup(props, { emit }) {
|
||||||
|
|
||||||
const tuntap = useTuntap();
|
const tuntap = useTuntap();
|
||||||
|
const globalData = injectGlobalData();
|
||||||
|
|
||||||
|
const showDelay = computed(()=>globalData.value.config.Running.Tuntap.ShowDelay);
|
||||||
const handleTuntap = (tuntap) => {
|
const handleTuntap = (tuntap) => {
|
||||||
const fn = tuntap.running ? stopTuntap (tuntap.MachineId) : runTuntap(tuntap.MachineId);
|
const fn = tuntap.running ? stopTuntap (tuntap.MachineId) : runTuntap(tuntap.MachineId);
|
||||||
tuntap.loading = true;
|
tuntap.loading = true;
|
||||||
@@ -88,7 +101,7 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return {
|
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);
|
-webkit-text-fill-color:hsla(0,0%,100%,0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.delay{position: absolute;right:0;bottom:0;line-height:normal}
|
||||||
|
|
||||||
|
|
||||||
</style>
|
</style>
|
@@ -3,26 +3,41 @@
|
|||||||
<div>
|
<div>
|
||||||
<el-form ref="ruleFormRef" :model="state.ruleForm" :rules="state.rules" label-width="140">
|
<el-form ref="ruleFormRef" :model="state.ruleForm" :rules="state.rules" label-width="140">
|
||||||
<el-form-item prop="gateway" style="margin-bottom:0">
|
<el-form-item prop="gateway" style="margin-bottom:0">
|
||||||
赐予此设备IP,其它可以通过这个IP访问
|
赐予此设备IP,其它设备可通过此IP访问
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="此设备的虚拟网卡IP" prop="IP">
|
<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>
|
||||||
<el-form-item prop="upgrade" style="margin-bottom:0">
|
<el-form-item prop="upgrade" style="margin-bottom:0">
|
||||||
<el-checkbox v-model="state.ruleForm.Upgrade" label="我很懂,我要使用高级功能(点对网和网对网)" size="large" />
|
<el-checkbox v-model="state.ruleForm.Upgrade" label="我很懂,我要使用高级功能(点对网和网对网)" size="large" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<div class="upgrade-wrap" v-if="state.ruleForm.Upgrade">
|
<div class="upgrade-wrap" v-if="state.ruleForm.Upgrade">
|
||||||
<el-form-item prop="gateway" style="margin-bottom:0">
|
<el-form-item prop="gateway" style="border-bottom: 1px solid #ddd;margin-bottom:0">
|
||||||
<el-checkbox v-model="state.ruleForm.Gateway" label="此设备在路由器(网对网,将对方的 局域网IP 转发到对方)" size="large" />
|
<el-checkbox v-model="state.ruleForm.Gateway" label="此设备在路由器(网对网)" size="large" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item prop="gateway" style="margin-bottom:0">
|
<el-form-item prop="nat" style="margin-bottom:0">
|
||||||
<span class="yellow">此设备可以用NAT转发,那填写局域网IP,其它交给NAT(linux、macos、win10+)</span>
|
<span class="yellow">此设备能使用NAT转发,只需局域网IP,剩下的交给NAT(linux、macos、win10+)</span>
|
||||||
</el-form-item>
|
</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">
|
<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]" 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>
|
||||||
<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>
|
||||||
@@ -31,15 +46,15 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item prop="gateway" style="margin-bottom:0">
|
<el-form-item prop="forward" style="margin-bottom:0">
|
||||||
<span class="yellow">此设备不能用NAT转发,那可以使用系统端口转发实现类似的效果(仅windows)</span>
|
<span class="yellow">此设备无法使用NAT转发,或只想使用端口转发</span>
|
||||||
</el-form-item>
|
</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">
|
<template v-for="(item, index) in state.ruleForm.Forwards" :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="item.ListenAddr" style="width:7rem" readonly /> : <el-input @change="handleForwardChange(index)" v-model="item.ListenPort" style="width:6rem" />
|
<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>
|
||||||
<div class="pdl-10">
|
<div class="pdl-10">
|
||||||
|
|
||||||
@@ -85,6 +100,8 @@ export default {
|
|||||||
Masks: tuntap.value.current.Masks.slice(0),
|
Masks: tuntap.value.current.Masks.slice(0),
|
||||||
PrefixLength:tuntap.value.current.PrefixLength || 24,
|
PrefixLength:tuntap.value.current.PrefixLength || 24,
|
||||||
Gateway: tuntap.value.current.Gateway,
|
Gateway: tuntap.value.current.Gateway,
|
||||||
|
ShowDelay: tuntap.value.current.ShowDelay,
|
||||||
|
AutoConnect: tuntap.value.current.AutoConnect,
|
||||||
Upgrade: tuntap.value.current.Upgrade,
|
Upgrade: tuntap.value.current.Upgrade,
|
||||||
|
|
||||||
Forwards:tuntap.value.current.Forwards.length == 0 ? [
|
Forwards:tuntap.value.current.Forwards.length == 0 ? [
|
||||||
@@ -144,6 +161,8 @@ export default {
|
|||||||
json.Masks = masks;
|
json.Masks = masks;
|
||||||
json.PrefixLength = +state.ruleForm.PrefixLength;
|
json.PrefixLength = +state.ruleForm.PrefixLength;
|
||||||
json.Gateway = state.ruleForm.Gateway;
|
json.Gateway = state.ruleForm.Gateway;
|
||||||
|
json.ShowDelay = state.ruleForm.ShowDelay;
|
||||||
|
json.AutoConnect = state.ruleForm.AutoConnect;
|
||||||
json.Upgrade = state.ruleForm.Upgrade;
|
json.Upgrade = state.ruleForm.Upgrade;
|
||||||
json.Forwards = state.ruleForm.Forwards;
|
json.Forwards = state.ruleForm.Forwards;
|
||||||
json.Forwards.forEach(c=>{
|
json.Forwards.forEach(c=>{
|
||||||
@@ -185,6 +204,6 @@ export default {
|
|||||||
.upgrade-wrap{
|
.upgrade-wrap{
|
||||||
border:1px solid #ddd;
|
border:1px solid #ddd;
|
||||||
margin-bottom:2rem
|
margin-bottom:2rem
|
||||||
padding:1rem 0;
|
padding:0 0 1rem 0;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
@@ -55,7 +55,6 @@ export default {
|
|||||||
bufferSize:globalData.value.bufferSize
|
bufferSize:globalData.value.bufferSize
|
||||||
});
|
});
|
||||||
watch(()=>globalData.value.config.Running.Tunnel.Transports,()=>{
|
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);
|
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
|
var servers = running.Data.Relay.Servers
|
||||||
.Where(c => c.Disabled == false)
|
.Where(c => c.Disabled == false)
|
||||||
.Where(c => string.IsNullOrWhiteSpace(c.Host) == 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)
|
foreach (RelayServerInfo item in servers)
|
||||||
{
|
{
|
||||||
ITransport transport = transports.FirstOrDefault(c => c.Type == item.RelayType);
|
ITransport transport = transports.FirstOrDefault(c => c.Type == item.RelayType);
|
||||||
@@ -278,43 +283,20 @@ namespace linker.plugins.relay
|
|||||||
{
|
{
|
||||||
try
|
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 == server.RelayType);
|
||||||
{
|
if (transport == null) continue;
|
||||||
ITransport transport = transports.FirstOrDefault(d => d.Type == c.RelayType);
|
|
||||||
if (transport == null) return null;
|
|
||||||
|
|
||||||
IPEndPoint server = NetworkHelper.GetEndPoint(c.Host, 3478);
|
IPEndPoint serverEP = NetworkHelper.GetEndPoint(server.Host, 3478);
|
||||||
|
RelayTestResultInfo result = await transport.RelayTestAsync(new RelayTestInfo
|
||||||
return new TestInfo
|
|
||||||
{
|
|
||||||
Server = c,
|
|
||||||
Task = transport.RelayTestAsync(new RelayTestInfo
|
|
||||||
{
|
|
||||||
MachineId = fileConfig.Data.Client.Id,
|
|
||||||
SecretKey = c.SecretKey,
|
|
||||||
Server = server,
|
|
||||||
})
|
|
||||||
};
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
{
|
||||||
}
|
MachineId = fileConfig.Data.Client.Id,
|
||||||
return null;
|
SecretKey = server.SecretKey,
|
||||||
});
|
Server = serverEP,
|
||||||
|
});
|
||||||
try
|
server.Delay = result.Delay;
|
||||||
{
|
server.Available = result.Available;
|
||||||
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)
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception)
|
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 socket = new Socket(relayTestInfo.Server.AddressFamily, SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp);
|
||||||
socket.KeepAlive();
|
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);
|
connection = await messengerResolver.BeginReceiveClient(socket);
|
||||||
|
|
||||||
@@ -249,7 +249,6 @@ namespace linker.plugins.relay.transport
|
|||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
@@ -46,17 +46,16 @@ namespace linker.plugins.tunnel
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public TunnelListInfo Get(ApiControllerParamsInfo param)
|
public TunnelListInfo Get(ApiControllerParamsInfo param)
|
||||||
{
|
{
|
||||||
uint hashCode = uint.Parse(param.Content);
|
ulong hashCode = ulong.Parse(param.Content);
|
||||||
uint _hashCode = tunnelConfigTransfer.ConfigVersion;
|
if (tunnelConfigTransfer.Version.Eq(hashCode,out ulong version))
|
||||||
if (_hashCode != hashCode)
|
|
||||||
{
|
{
|
||||||
return new TunnelListInfo
|
return new TunnelListInfo
|
||||||
{
|
{
|
||||||
List = tunnelConfigTransfer.Config,
|
List = tunnelConfigTransfer.Config,
|
||||||
HashCode = _hashCode
|
HashCode = version
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return new TunnelListInfo { HashCode = _hashCode };
|
return new TunnelListInfo { HashCode = version };
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 刷新隧道信息
|
/// 刷新隧道信息
|
||||||
@@ -145,7 +144,7 @@ namespace linker.plugins.tunnel
|
|||||||
public sealed class TunnelListInfo
|
public sealed class TunnelListInfo
|
||||||
{
|
{
|
||||||
public ConcurrentDictionary<string, TunnelTransportRouteLevelInfo> List { get; set; }
|
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 TransportTcpPortMap transportTcpPortMap;
|
||||||
private readonly TransportUdpPortMap transportUdpPortMap;
|
private readonly TransportUdpPortMap transportUdpPortMap;
|
||||||
|
|
||||||
|
public VersionManager Version { get; } = new VersionManager();
|
||||||
private uint version = 0;
|
public ConcurrentDictionary<string, TunnelTransportRouteLevelInfo> Config { get; } = new ConcurrentDictionary<string, TunnelTransportRouteLevelInfo>();
|
||||||
public uint ConfigVersion => version;
|
|
||||||
private ConcurrentDictionary<string, TunnelTransportRouteLevelInfo> configs = new ConcurrentDictionary<string, TunnelTransportRouteLevelInfo>();
|
|
||||||
public ConcurrentDictionary<string, TunnelTransportRouteLevelInfo> Config => configs;
|
|
||||||
|
|
||||||
public TunnelConfigTransfer(FileConfig config, RunningConfig running, ClientSignInState clientSignInState, MessengerSender messengerSender, RunningConfigTransfer runningConfigTransfer, ITunnelAdapter tunnelAdapter, TransportTcpPortMap transportTcpPortMap, TransportUdpPortMap transportUdpPortMap)
|
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>
|
/// <returns></returns>
|
||||||
public TunnelTransportRouteLevelInfo OnRemoteRouteLevel(TunnelTransportRouteLevelInfo tunnelTransportFileConfigInfo)
|
public TunnelTransportRouteLevelInfo OnRemoteRouteLevel(TunnelTransportRouteLevelInfo tunnelTransportFileConfigInfo)
|
||||||
{
|
{
|
||||||
configs.AddOrUpdate(tunnelTransportFileConfigInfo.MachineId, tunnelTransportFileConfigInfo, (a, b) => tunnelTransportFileConfigInfo);
|
Config.AddOrUpdate(tunnelTransportFileConfigInfo.MachineId, tunnelTransportFileConfigInfo, (a, b) => tunnelTransportFileConfigInfo);
|
||||||
Interlocked.Increment(ref version);
|
Version.Add();
|
||||||
return GetLocalRouteLevel();
|
return GetLocalRouteLevel();
|
||||||
}
|
}
|
||||||
private void GetRemoteRouteLevel()
|
private void GetRemoteRouteLevel()
|
||||||
@@ -128,11 +125,11 @@ namespace linker.plugins.tunnel
|
|||||||
List<TunnelTransportRouteLevelInfo> list = MemoryPackSerializer.Deserialize<List<TunnelTransportRouteLevelInfo>>(result.Result.Data.Span);
|
List<TunnelTransportRouteLevelInfo> list = MemoryPackSerializer.Deserialize<List<TunnelTransportRouteLevelInfo>>(result.Result.Data.Span);
|
||||||
foreach (var item in list)
|
foreach (var item in list)
|
||||||
{
|
{
|
||||||
configs.AddOrUpdate(item.MachineId, item, (a, b) => item);
|
Config.AddOrUpdate(item.MachineId, item, (a, b) => item);
|
||||||
}
|
}
|
||||||
TunnelTransportRouteLevelInfo config = GetLocalRouteLevel();
|
TunnelTransportRouteLevelInfo config = GetLocalRouteLevel();
|
||||||
configs.AddOrUpdate(config.MachineId, config, (a, b) => config);
|
Config.AddOrUpdate(config.MachineId, config, (a, b) => config);
|
||||||
Interlocked.Increment(ref version);
|
Version.Add();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -145,7 +142,7 @@ namespace linker.plugins.tunnel
|
|||||||
RouteLevelPlus = running.Data.Tunnel.RouteLevelPlus,
|
RouteLevelPlus = running.Data.Tunnel.RouteLevelPlus,
|
||||||
PortMapWan = running.Data.Tunnel.PortMapWan,
|
PortMapWan = running.Data.Tunnel.PortMapWan,
|
||||||
PortMapLan = running.Data.Tunnel.PortMapLan,
|
PortMapLan = running.Data.Tunnel.PortMapLan,
|
||||||
NeedReboot = reboot
|
NeedReboot = false
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
private void InitRouteLevel()
|
private void InitRouteLevel()
|
||||||
@@ -157,7 +154,6 @@ namespace linker.plugins.tunnel
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool reboot = false;
|
|
||||||
private void TestQuic()
|
private void TestQuic()
|
||||||
{
|
{
|
||||||
if (OperatingSystem.IsWindows())
|
if (OperatingSystem.IsWindows())
|
||||||
@@ -172,7 +168,6 @@ namespace linker.plugins.tunnel
|
|||||||
File.Move("msquic.dll", "msquic.dll.temp", true);
|
File.Move("msquic.dll", "msquic.dll.temp", true);
|
||||||
File.Move("msquic-openssl.dll", "msquic.dll", true);
|
File.Move("msquic-openssl.dll", "msquic.dll", true);
|
||||||
|
|
||||||
reboot = true;
|
|
||||||
Environment.Exit(1);
|
Environment.Exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -46,17 +46,16 @@ namespace linker.plugins.tuntap
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public TuntabListInfo Get(ApiControllerParamsInfo param)
|
public TuntabListInfo Get(ApiControllerParamsInfo param)
|
||||||
{
|
{
|
||||||
uint hashCode = uint.Parse(param.Content);
|
ulong hashCode = ulong.Parse(param.Content);
|
||||||
uint _hashCode = tuntapTransfer.InfosVersion;
|
if (tuntapTransfer.Version.Eq(hashCode, out ulong version))
|
||||||
if (_hashCode != hashCode)
|
|
||||||
{
|
{
|
||||||
return new TuntabListInfo
|
return new TuntabListInfo
|
||||||
{
|
{
|
||||||
List = tuntapTransfer.Infos,
|
List = tuntapTransfer.Infos,
|
||||||
HashCode = _hashCode
|
HashCode = version
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return new TuntabListInfo { HashCode = _hashCode };
|
return new TuntabListInfo { HashCode = version };
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 刷新网卡信息
|
/// 刷新网卡信息
|
||||||
@@ -147,7 +146,7 @@ namespace linker.plugins.tuntap
|
|||||||
public sealed class TuntabListInfo
|
public sealed class TuntabListInfo
|
||||||
{
|
{
|
||||||
public ConcurrentDictionary<string, TuntapInfo> List { get; set; }
|
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.messenger;
|
||||||
using linker.plugins.tuntap.config;
|
using linker.plugins.tuntap.config;
|
||||||
using linker.tun;
|
using linker.tun;
|
||||||
|
using linker.tunnel.connection;
|
||||||
|
|
||||||
namespace linker.plugins.tuntap
|
namespace linker.plugins.tuntap
|
||||||
{
|
{
|
||||||
@@ -25,16 +26,15 @@ namespace linker.plugins.tuntap
|
|||||||
private readonly LinkerTunDeviceAdapter linkerTunDeviceAdapter;
|
private readonly LinkerTunDeviceAdapter linkerTunDeviceAdapter;
|
||||||
|
|
||||||
private string deviceName = "linker";
|
private string deviceName = "linker";
|
||||||
private uint operating = 0;
|
|
||||||
private List<IPAddress> routeIps = new List<IPAddress>();
|
private List<IPAddress> routeIps = new List<IPAddress>();
|
||||||
|
|
||||||
private uint infosVersion = 0;
|
public VersionManager Version { get; } = new VersionManager();
|
||||||
public uint InfosVersion => infosVersion;
|
|
||||||
|
|
||||||
private readonly ConcurrentDictionary<string, TuntapInfo> tuntapInfos = new ConcurrentDictionary<string, TuntapInfo>();
|
private readonly ConcurrentDictionary<string, TuntapInfo> tuntapInfos = new ConcurrentDictionary<string, TuntapInfo>();
|
||||||
public ConcurrentDictionary<string, TuntapInfo> Infos => tuntapInfos;
|
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)
|
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);
|
NetworkHelper.GetRouteLevel(config.Data.Client.Server, out routeIps);
|
||||||
NotifyConfig();
|
NotifyConfig();
|
||||||
CheckTuntapStatusTask();
|
CheckTuntapStatusTask();
|
||||||
|
PingTask();
|
||||||
if (runningConfig.Data.Tuntap.Running)
|
if (runningConfig.Data.Tuntap.Running)
|
||||||
{
|
{
|
||||||
Setup();
|
Setup();
|
||||||
@@ -71,7 +72,7 @@ namespace linker.plugins.tuntap
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void Setup()
|
public void Setup()
|
||||||
{
|
{
|
||||||
if (Interlocked.CompareExchange(ref operating, 1, 0) == 1)
|
if (operatingManager.StartOperation() == false)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -111,7 +112,7 @@ namespace linker.plugins.tuntap
|
|||||||
}
|
}
|
||||||
private void SetupAfter()
|
private void SetupAfter()
|
||||||
{
|
{
|
||||||
Interlocked.Exchange(ref operating, 0);
|
operatingManager.StopOperation();
|
||||||
NotifyConfig();
|
NotifyConfig();
|
||||||
}
|
}
|
||||||
private void SetupSuccess()
|
private void SetupSuccess()
|
||||||
@@ -127,7 +128,7 @@ namespace linker.plugins.tuntap
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void Shutdown()
|
public void Shutdown()
|
||||||
{
|
{
|
||||||
if (Interlocked.CompareExchange(ref operating, 1, 0) == 1)
|
if (operatingManager.StartOperation() == false)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -155,7 +156,7 @@ namespace linker.plugins.tuntap
|
|||||||
}
|
}
|
||||||
private void ShutdownAfter()
|
private void ShutdownAfter()
|
||||||
{
|
{
|
||||||
Interlocked.Exchange(ref operating, 0);
|
operatingManager.StopOperation();
|
||||||
NotifyConfig();
|
NotifyConfig();
|
||||||
}
|
}
|
||||||
private void ShutdownSuccess()
|
private void ShutdownSuccess()
|
||||||
@@ -188,6 +189,8 @@ namespace linker.plugins.tuntap
|
|||||||
runningConfig.Data.Tuntap.Masks = info.Masks;
|
runningConfig.Data.Tuntap.Masks = info.Masks;
|
||||||
runningConfig.Data.Tuntap.PrefixLength = info.PrefixLength;
|
runningConfig.Data.Tuntap.PrefixLength = info.PrefixLength;
|
||||||
runningConfig.Data.Tuntap.Gateway = info.Gateway;
|
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.Upgrade = info.Upgrade;
|
||||||
runningConfig.Data.Tuntap.Forwards = info.Forwards;
|
runningConfig.Data.Tuntap.Forwards = info.Forwards;
|
||||||
runningConfig.Data.Update();
|
runningConfig.Data.Update();
|
||||||
@@ -214,7 +217,7 @@ namespace linker.plugins.tuntap
|
|||||||
{
|
{
|
||||||
DelRoute();
|
DelRoute();
|
||||||
tuntapInfos.AddOrUpdate(info.MachineId, info, (a, b) => info);
|
tuntapInfos.AddOrUpdate(info.MachineId, info, (a, b) => info);
|
||||||
Interlocked.Increment(ref infosVersion);
|
Version.Add();
|
||||||
AddRoute();
|
AddRoute();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -240,7 +243,7 @@ namespace linker.plugins.tuntap
|
|||||||
}
|
}
|
||||||
AddRoute();
|
AddRoute();
|
||||||
}
|
}
|
||||||
Interlocked.Increment(ref infosVersion);
|
Version.Add();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -260,9 +263,12 @@ namespace linker.plugins.tuntap
|
|||||||
Error = linkerTunDeviceAdapter.Error,
|
Error = linkerTunDeviceAdapter.Error,
|
||||||
Error1 = linkerTunDeviceAdapter.Error1,
|
Error1 = linkerTunDeviceAdapter.Error1,
|
||||||
SystemInfo = $"{System.Runtime.InteropServices.RuntimeInformation.OSDescription} {(string.IsNullOrWhiteSpace(Environment.GetEnvironmentVariable("SNLTTY_LINKER_IS_DOCKER")) == false ? "Docker" : "")}",
|
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,
|
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)
|
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);
|
await Task.Delay(15000).ConfigureAwait(false);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (runningConfig.Data.Tuntap.Running && OperatingSystem.IsWindows() && operating == 0)
|
if (runningConfig.Data.Tuntap.Running && OperatingSystem.IsWindows() && operatingManager.Operating == false)
|
||||||
{
|
{
|
||||||
await CheckInterface().ConfigureAwait(false);
|
await CheckInterface().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
@@ -419,18 +425,64 @@ namespace linker.plugins.tuntap
|
|||||||
{
|
{
|
||||||
NetworkInterface networkInterface = NetworkInterface.GetAllNetworkInterfaces().FirstOrDefault(c => c.Name == deviceName);
|
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");
|
LoggerHelper.Instance.Error($"tuntap inerface {deviceName} is {networkInterface?.OperationalStatus ?? OperationalStatus.Unknown}, restarting");
|
||||||
Shutdown();
|
Shutdown();
|
||||||
await Task.Delay(5000).ConfigureAwait(false);
|
await Task.Delay(5000).ConfigureAwait(false);
|
||||||
|
|
||||||
networkInterface = NetworkInterface.GetAllNetworkInterfaces().FirstOrDefault(c => c.Name == deviceName);
|
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();
|
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
|
namespace linker.plugins.tuntap.config
|
||||||
{
|
{
|
||||||
public sealed class TuntapConfigInfo
|
[MemoryPackable]
|
||||||
|
public sealed partial class TuntapConfigInfo
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 网卡IP
|
/// 网卡IP
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[MemoryPackAllowSerialize]
|
||||||
public IPAddress IP { get; set; } = IPAddress.Any;
|
public IPAddress IP { get; set; } = IPAddress.Any;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 局域网IP列表
|
/// 局域网IP列表
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[MemoryPackAllowSerialize]
|
||||||
public IPAddress[] LanIPs { get; set; } = Array.Empty<IPAddress>();
|
public IPAddress[] LanIPs { get; set; } = Array.Empty<IPAddress>();
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 局域网掩码列表,与IP列表一一对应
|
/// 局域网掩码列表,与IP列表一一对应
|
||||||
@@ -33,9 +36,19 @@ namespace linker.plugins.tuntap.config
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public bool Gateway { get; set; }
|
public bool Gateway { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// 显示延迟
|
||||||
|
/// </summary>
|
||||||
|
public bool ShowDelay { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 自动连接
|
||||||
|
/// </summary>
|
||||||
|
public bool AutoConnect { get; set; }
|
||||||
|
/// <summary>
|
||||||
/// 使用高级功能
|
/// 使用高级功能
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool Upgrade { get; set; }
|
public bool Upgrade { get; set; }
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 端口转发列表
|
/// 端口转发列表
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -103,6 +116,12 @@ namespace linker.plugins.tuntap.config
|
|||||||
|
|
||||||
[MemoryPackAllowSerialize]
|
[MemoryPackAllowSerialize]
|
||||||
public IPAddress IP { get; set; }
|
public IPAddress IP { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 前缀长度
|
||||||
|
/// </summary>
|
||||||
|
public byte PrefixLength { get; set; } = 24;
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 局域网IP
|
/// 局域网IP
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -115,11 +134,6 @@ namespace linker.plugins.tuntap.config
|
|||||||
public int[] Masks { get; set; } = Array.Empty<int>();
|
public int[] Masks { get; set; } = Array.Empty<int>();
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 前缀长度
|
|
||||||
/// </summary>
|
|
||||||
public byte PrefixLength { get; set; } = 24;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 网卡安装错误
|
/// 网卡安装错误
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -132,18 +146,120 @@ namespace linker.plugins.tuntap.config
|
|||||||
/// 系统信息
|
/// 系统信息
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string SystemInfo { get; set; }
|
public string SystemInfo { get; set; }
|
||||||
/// <summary>
|
|
||||||
/// 是否网关
|
|
||||||
/// </summary>
|
|
||||||
public bool Gateway { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
/// 使用高级功能
|
|
||||||
/// </summary>
|
|
||||||
public bool Upgrade { get; set; }
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 端口转发列表
|
/// 端口转发列表
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public List<TuntapForwardInfo> Forwards { get; set; } = new List<TuntapForwardInfo>();
|
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.plugins.tuntap.config;
|
||||||
using linker.tun;
|
using linker.tun;
|
||||||
using System.Buffers.Binary;
|
using System.Buffers.Binary;
|
||||||
using System.Net.Sockets;
|
|
||||||
using System.Net;
|
|
||||||
|
|
||||||
namespace linker.plugins.tuntap.proxy
|
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<string, ITunnelConnection> connections = new ConcurrentDictionary<string, ITunnelConnection>();
|
||||||
private readonly ConcurrentDictionary<uint, ITunnelConnection> ipConnections = new ConcurrentDictionary<uint, ITunnelConnection>();
|
private readonly ConcurrentDictionary<uint, ITunnelConnection> ipConnections = new ConcurrentDictionary<uint, ITunnelConnection>();
|
||||||
|
|
||||||
SemaphoreSlim slimGlobal = new SemaphoreSlim(1);
|
private readonly OperatingMultipleManager operatingMultipleManager = new OperatingMultipleManager();
|
||||||
private readonly ConcurrentDictionary<string, SemaphoreSlim> dicLocks = new ConcurrentDictionary<string, SemaphoreSlim>();
|
|
||||||
|
|
||||||
public TuntapProxy(TunnelTransfer tunnelTransfer, RelayTransfer relayTransfer, RunningConfig runningConfig, FileConfig config, LinkerTunDeviceAdapter linkerTunDeviceAdapter)
|
public TuntapProxy(TunnelTransfer tunnelTransfer, RelayTransfer relayTransfer, RunningConfig runningConfig, FileConfig config, LinkerTunDeviceAdapter linkerTunDeviceAdapter)
|
||||||
{
|
{
|
||||||
@@ -112,7 +109,6 @@ namespace linker.plugins.tuntap.proxy
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 设置IP,等下有连接进来,用IP匹配,才能知道这个连接是要连谁
|
/// 设置IP,等下有连接进来,用IP匹配,才能知道这个连接是要连谁
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -179,23 +175,13 @@ namespace linker.plugins.tuntap.proxy
|
|||||||
return connection;
|
return connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
await slimGlobal.WaitAsync().ConfigureAwait(false);
|
if(operatingMultipleManager.StartOperation(machineId) ==false)
|
||||||
if (dicLocks.TryGetValue(machineId, out SemaphoreSlim slim) == false)
|
|
||||||
{
|
{
|
||||||
slim = new SemaphoreSlim(1);
|
return null;
|
||||||
dicLocks.TryAdd(machineId, slim);
|
|
||||||
}
|
}
|
||||||
slimGlobal.Release();
|
|
||||||
|
|
||||||
await slim.WaitAsync().ConfigureAwait(false);
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (connections.TryGetValue(machineId, out connection) && connection.Connected)
|
|
||||||
{
|
|
||||||
return connection;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG) LoggerHelper.Instance.Debug($"tuntap tunnel to {machineId}");
|
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG) LoggerHelper.Instance.Debug($"tuntap tunnel to {machineId}");
|
||||||
|
|
||||||
connection = await tunnelTransfer.ConnectAsync(machineId, "tuntap", TunnelProtocolType.None).ConfigureAwait(false);
|
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);
|
connection = await relayTransfer.ConnectAsync(config.Data.Client.Id, machineId, "tuntap").ConfigureAwait(false);
|
||||||
if (connection != null)
|
if (connection != null)
|
||||||
{
|
{
|
||||||
//tunnelTransfer.StartBackground(machineId, "tuntap");
|
|
||||||
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG) LoggerHelper.Instance.Debug($"tuntap relay success,{connection.ToString()}");
|
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG) LoggerHelper.Instance.Debug($"tuntap relay success,{connection.ToString()}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -224,7 +209,7 @@ namespace linker.plugins.tuntap.proxy
|
|||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
slim.Release();
|
operatingMultipleManager.StopOperation(machineId);
|
||||||
}
|
}
|
||||||
return connection;
|
return connection;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user