组网的一些更新
12
.github/workflows/dotnet.yml
vendored
@@ -48,18 +48,12 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: '${{ secrets.ACTIONS_TOKEN }}'
|
GITHUB_TOKEN: '${{ secrets.ACTIONS_TOKEN }}'
|
||||||
with:
|
with:
|
||||||
tag_name: v1.2.0.3
|
tag_name: v1.2.0.4
|
||||||
release_name: v1.2.0.3.${{ steps.date.outputs.today }}
|
release_name: v1.2.0.4.${{ steps.date.outputs.today }}
|
||||||
draft: false
|
draft: false
|
||||||
prerelease: false
|
prerelease: false
|
||||||
body: |
|
body: |
|
||||||
1. 重要更新
|
1. 测试中,不要更新
|
||||||
2. 重写的虚拟网卡,不再依赖tun2socks,(仅windows、linux,暂时的)
|
|
||||||
3. 虚拟网卡支持广播、点对网、网对网了
|
|
||||||
4. 公开`linker.tun`库,可以nuget安装,将网卡集成到你的项目中
|
|
||||||
5. webui显示设备区域,设备系统,及是否docker
|
|
||||||
6. 服务器穿透支持端口范围
|
|
||||||
7. 要更新服务器,要更新服务器,要更新服务器
|
|
||||||
|
|
||||||
- name: upload win x64
|
- name: upload win x64
|
||||||
id: upload-win-x64
|
id: upload-win-x64
|
||||||
|
@@ -14,6 +14,16 @@ sidebar_position: 1
|
|||||||
6. 打洞失败回退、这需要你中继部署服务器进行中继通信
|
6. 打洞失败回退、这需要你中继部署服务器进行中继通信
|
||||||
7. 易用的web管理页面
|
7. 易用的web管理页面
|
||||||
|
|
||||||
|
|
||||||
|
:::danger[win10以下]
|
||||||
|
|
||||||
|
1. win7 或 win8 可能需要安装一些环境,才能运行
|
||||||
|
2. <a href="https://aka.ms/vs/16/release/vc_redist.x64.exe" target="_blank">Microsoft Visual C++ 2015-2019 Redistributable </a>
|
||||||
|
2. <a href="https://www.microsoft.com/download/details.aspx?id=47442" target="_blank">KB3063858 </a>
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
|
||||||
:::tip[加入组织]
|
:::tip[加入组织]
|
||||||
|
|
||||||
<a href="https://jq.qq.com/?_wv=1027&k=ucoIVfz4" target="_blank">你可以加入QQ群:1121552990,可以申请一些免费的中继服务器 </a>
|
<a href="https://jq.qq.com/?_wv=1027&k=ucoIVfz4" target="_blank">你可以加入QQ群:1121552990,可以申请一些免费的中继服务器 </a>
|
||||||
|
@@ -8,8 +8,7 @@ sidebar_position: 1
|
|||||||
|
|
||||||
1. 各个设备的`网卡IP`,不要一样,要同一网段,且不应该使用`1`、`255`
|
1. 各个设备的`网卡IP`,不要一样,要同一网段,且不应该使用`1`、`255`
|
||||||
2. 请使用 `10.0.0.0 - 10.255.255.255`、`172.16.0.0 - 172.31.255.255`、`192.168.0.0 - 192.168.255.255` 范围内的IP
|
2. 请使用 `10.0.0.0 - 10.255.255.255`、`172.16.0.0 - 172.31.255.255`、`192.168.0.0 - 192.168.255.255` 范围内的IP
|
||||||
3. `局域网IP`,是选填的,可以不填,不懂是啥时,不要填、不要填、不要填
|
3. 虽然支持UDP广播,但是UDP广播不会去主动连接所有设备,所以,你可以先 ping 以下对方,让两端相互连接
|
||||||
4. 虽然支持UDP广播,但是UDP广播不会去主动连接所有设备,所以,你可以先 ping 以下对方,让两端相互连接
|
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
|
||||||
@@ -17,20 +16,24 @@ sidebar_position: 1
|
|||||||
|
|
||||||
在设备,虚拟网卡一栏,点击IP配置
|
在设备,虚拟网卡一栏,点击IP配置
|
||||||
|
|
||||||

|

|
||||||

|

|
||||||
|
|
||||||
开启网卡成功后,即可通过`虚拟IP`访问目标设备(当然,前提是能够打洞成功,或者中继成功)
|
开启网卡成功后,即可通过`虚拟IP`访问目标设备(当然,前提是能够打洞成功,或者中继成功)
|
||||||
|
|
||||||

|

|
||||||

|

|
||||||
|
|
||||||
试一下能不能连接,第一次连接时,会尝试去打洞或中继,时间可能会比较久,耐心等待
|
试一下能不能连接,第一次连接时,会尝试去打洞或中继,时间可能会比较久,耐心等待
|
||||||

|

|
||||||
|
|
||||||
## 2、点对网(局域网IP)
|
## 2、点对网
|
||||||
|
|
||||||
:::tip[说明]
|
:::danger[重要]
|
||||||
|
你要确定你知道你在搞什么,如果只是简单的P2P通信,上面的内容已经够了,以下的东西不要看,不要看,不要看
|
||||||
|
:::
|
||||||
|
|
||||||
|
:::tip[1、情况1,你的设备支持NAT转发时]
|
||||||
|
|
||||||
1. linux,已经自动添加NAT转发
|
1. linux,已经自动添加NAT转发
|
||||||
2. windows,你可以尝试在`powershell`运行 `Get-NetNat` 如果没有报错则可以正常使用,如果报错,那你可能需要打开`Hyper-V`才能使用点对网功能, `控制面板\程序\启用或关闭 Windows 功能`
|
2. windows,你可以尝试在`powershell`运行 `Get-NetNat` 如果没有报错则可以正常使用,如果报错,那你可能需要打开`Hyper-V`才能使用点对网功能, `控制面板\程序\启用或关闭 Windows 功能`
|
||||||
@@ -44,25 +47,36 @@ nat on en0 from 192.168.54.0/24 to any -> (en0)
|
|||||||
# 加载规则
|
# 加载规则
|
||||||
sudo pfctl -f /etc/pf.conf -e
|
sudo pfctl -f /etc/pf.conf -e
|
||||||
```
|
```
|
||||||
3. 局域网IP,是你设备所在局域网的IP,不是虚拟网卡IP、不是虚拟网卡IP、不是虚拟网卡IP
|
|
||||||
|
|
||||||
:::
|
:::
|
||||||
|
|
||||||
我这里,B端的局域网IP是 `192.168.1.35`
|
我这里,B端的局域网IP是 `192.168.1.35`
|
||||||
|
|
||||||

|

|
||||||
|

|
||||||
|
|
||||||
尝试连接 对方的局域网IP,或者局域网内其它设备(记得关闭防火墙,或者防火墙添加一条规则,允许ICMP通过)
|
尝试连接 对方的局域网IP,或者局域网内其它设备(记得关闭防火墙,或者防火墙添加一条规则,允许ICMP通过)
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
|
||||||
|
:::tip[2、情况2,你的设备无法使用NAT转发时]
|
||||||
|
|
||||||
|
1. 你的设备无法使用NAT转发(一般出现在低版本windows下,win10以下),那你只能使用windows的端口转发功能来访问你当前设备局域网下的其它设备
|
||||||
|
2. 按如下配置。当其它设备通过`192.168.54.2:12345` 访问时,将访问到你的局域网的`192.168.1.35:3389`
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
|
||||||
## 3、网对网
|
## 3、网对网
|
||||||
|
|
||||||
:::tip[说明]
|
:::tip[说明]
|
||||||
|
|
||||||
1. 如果你把linker安装在路由器上,勾选我是网关即可
|
1. 如果你把linker安装在路由器上,可以勾选
|
||||||
|
2. 假设B端设置的`局域网IP`为`192.168.1.35/24`,那么在A端勾选此项,则A端下局域网内的所有设备都能通过`192.168.1.x`去访问B端局域网内的设备
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
Before Width: | Height: | Size: 150 KiB After Width: | Height: | Size: 150 KiB |
BIN
linker.doc.web/docs/4、通信功能/img/tun-add1.png
Normal file
After Width: | Height: | Size: 52 KiB |
BIN
linker.doc.web/docs/4、通信功能/img/tun-forward.png
Normal file
After Width: | Height: | Size: 127 KiB |
BIN
linker.doc.web/docs/4、通信功能/img/tun-gateway.png
Normal file
After Width: | Height: | Size: 120 KiB |
Before Width: | Height: | Size: 110 KiB After Width: | Height: | Size: 110 KiB |
BIN
linker.doc.web/docs/4、通信功能/img/tun-local.png
Normal file
After Width: | Height: | Size: 125 KiB |
Before Width: | Height: | Size: 157 KiB After Width: | Height: | Size: 157 KiB |
Before Width: | Height: | Size: 154 KiB After Width: | Height: | Size: 154 KiB |
Before Width: | Height: | Size: 155 KiB After Width: | Height: | Size: 155 KiB |
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 69 KiB |
Before Width: | Height: | Size: 149 KiB |
Before Width: | Height: | Size: 49 KiB |
@@ -8,24 +8,26 @@ namespace linker.libs
|
|||||||
{
|
{
|
||||||
public static string Windows(string arg, string[] commands)
|
public static string Windows(string arg, string[] commands)
|
||||||
{
|
{
|
||||||
return Execute("cmd.exe", arg, commands);
|
return Execute("cmd.exe", arg, commands,out string error);
|
||||||
}
|
}
|
||||||
public static string PowerShell(string arg, string[] commands)
|
public static string PowerShell(string arg, string[] commands, out string error)
|
||||||
{
|
{
|
||||||
|
error = string.Empty;
|
||||||
if (IsPowerShellInstalled() == false)
|
if (IsPowerShellInstalled() == false)
|
||||||
{
|
{
|
||||||
|
error = "PowerShell is not installed";
|
||||||
return string.Empty;
|
return string.Empty;
|
||||||
}
|
}
|
||||||
return Execute("powershell.exe", arg, commands);
|
return Execute("powershell.exe", arg, commands,out error);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string Linux(string arg, string[] commands)
|
public static string Linux(string arg, string[] commands)
|
||||||
{
|
{
|
||||||
return Execute("/bin/bash", arg, commands);
|
return Execute("/bin/bash", arg, commands, out string error);
|
||||||
}
|
}
|
||||||
public static string Osx(string arg, string[] commands)
|
public static string Osx(string arg, string[] commands)
|
||||||
{
|
{
|
||||||
return Execute("/bin/bash", arg, commands);
|
return Execute("/bin/bash", arg, commands, out string error);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Process Execute(string fileName, string arg)
|
public static Process Execute(string fileName, string arg)
|
||||||
@@ -45,7 +47,7 @@ namespace linker.libs
|
|||||||
return proc;
|
return proc;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string Execute(string fileName, string arg, string[] commands)
|
public static string Execute(string fileName, string arg, string[] commands,out string error)
|
||||||
{
|
{
|
||||||
using Process proc = new Process();
|
using Process proc = new Process();
|
||||||
proc.StartInfo.WorkingDirectory = Path.GetFullPath(Path.Join("./"));
|
proc.StartInfo.WorkingDirectory = Path.GetFullPath(Path.Join("./"));
|
||||||
@@ -68,7 +70,7 @@ namespace linker.libs
|
|||||||
proc.StandardInput.AutoFlush = true;
|
proc.StandardInput.AutoFlush = true;
|
||||||
proc.StandardInput.WriteLine("exit");
|
proc.StandardInput.WriteLine("exit");
|
||||||
proc.StandardInput.Close();
|
proc.StandardInput.Close();
|
||||||
string error = proc.StandardError.ReadToEnd();
|
error = proc.StandardError.ReadToEnd();
|
||||||
string output = string.Empty;
|
string output = string.Empty;
|
||||||
if (string.IsNullOrWhiteSpace(error))
|
if (string.IsNullOrWhiteSpace(error))
|
||||||
{
|
{
|
||||||
|
@@ -57,7 +57,7 @@ cmd /c netsh advfirewall firewall add rule name=""{fileName}"" dir=in action=all
|
|||||||
string firewall = Path.Join(distPath, "firewall.bat");
|
string firewall = Path.Join(distPath, "firewall.bat");
|
||||||
|
|
||||||
File.WriteAllText(firewall, content);
|
File.WriteAllText(firewall, content);
|
||||||
CommandHelper.Execute(firewall, string.Empty, new string[0]);
|
CommandHelper.Execute(firewall, string.Empty, new string[0],out string error);
|
||||||
File.Delete(firewall);
|
File.Delete(firewall);
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
|
@@ -61,20 +61,24 @@ namespace linker.libs
|
|||||||
|
|
||||||
|
|
||||||
static List<string> starts = new() { "10.", "100.", "192.168.", "172." };
|
static List<string> starts = new() { "10.", "100.", "192.168.", "172." };
|
||||||
static string domain = "linker.snltty.com";
|
public static ushort GetRouteLevel(string server, out List<IPAddress> result)
|
||||||
public static ushort GetRouteLevel(out List<IPAddress> result)
|
|
||||||
{
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(server) == false)
|
||||||
|
{
|
||||||
|
server = server.Split(':')[0];
|
||||||
|
}
|
||||||
|
|
||||||
if (OperatingSystem.IsWindows())
|
if (OperatingSystem.IsWindows())
|
||||||
{
|
{
|
||||||
return GetRouteLevelWindows(out result);
|
return GetRouteLevelWindows(server, out result);
|
||||||
}
|
}
|
||||||
return GetRouteLevelLinux(out result);
|
return GetRouteLevelLinux(server, out result);
|
||||||
}
|
}
|
||||||
private static ushort GetRouteLevelLinux(out List<IPAddress> result)
|
private static ushort GetRouteLevelLinux(string server, out List<IPAddress> result)
|
||||||
{
|
{
|
||||||
result = new List<IPAddress>();
|
result = new List<IPAddress>();
|
||||||
|
|
||||||
string str = CommandHelper.Linux(string.Empty, new string[] { $"traceroute {domain} -4 -m 5" });
|
string str = CommandHelper.Linux(string.Empty, new string[] { $"traceroute {server} -4 -m 5" });
|
||||||
string[] lines = str.Split(Environment.NewLine);
|
string[] lines = str.Split(Environment.NewLine);
|
||||||
|
|
||||||
Regex regex = new Regex(@"(\d+\.\d+\.\d+\.\d+)");
|
Regex regex = new Regex(@"(\d+\.\d+\.\d+\.\d+)");
|
||||||
@@ -93,12 +97,12 @@ namespace linker.libs
|
|||||||
|
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
private static ushort GetRouteLevelWindows(out List<IPAddress> result)
|
private static ushort GetRouteLevelWindows(string server, out List<IPAddress> result)
|
||||||
{
|
{
|
||||||
result = new List<IPAddress>();
|
result = new List<IPAddress>();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
IPAddress target = Dns.GetHostEntry(domain).AddressList.FirstOrDefault(c => c.AddressFamily == AddressFamily.InterNetwork);
|
IPAddress target = Dns.GetHostEntry(server).AddressList.FirstOrDefault(c => c.AddressFamily == AddressFamily.InterNetwork);
|
||||||
|
|
||||||
for (ushort i = 1; i <= 5; i++)
|
for (ushort i = 1; i <= 5; i++)
|
||||||
{
|
{
|
||||||
|
@@ -15,8 +15,8 @@
|
|||||||
<PackageProjectUrl>https://github.com/snltty/linker</PackageProjectUrl>
|
<PackageProjectUrl>https://github.com/snltty/linker</PackageProjectUrl>
|
||||||
<RepositoryUrl>https://github.com/snltty/linker</RepositoryUrl>
|
<RepositoryUrl>https://github.com/snltty/linker</RepositoryUrl>
|
||||||
<Version>1.2.0</Version>
|
<Version>1.2.0</Version>
|
||||||
<AssemblyVersion>1.2.0.3</AssemblyVersion>
|
<AssemblyVersion>1.2.0.4</AssemblyVersion>
|
||||||
<FileVersion>1.2.0.3</FileVersion>
|
<FileVersion>1.2.0.4</FileVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||||
<DebugType>full</DebugType>
|
<DebugType>full</DebugType>
|
||||||
|
@@ -1,139 +0,0 @@
|
|||||||
using System.Diagnostics;
|
|
||||||
using System.ServiceProcess;
|
|
||||||
|
|
||||||
namespace linker.service
|
|
||||||
{
|
|
||||||
partial class LinkerService : ServiceBase
|
|
||||||
{
|
|
||||||
private readonly string[] args;
|
|
||||||
public LinkerService(string[] args)
|
|
||||||
{
|
|
||||||
this.args = args;
|
|
||||||
InitializeComponent();
|
|
||||||
}
|
|
||||||
|
|
||||||
private string mainExeName = "linker";
|
|
||||||
private CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
|
|
||||||
|
|
||||||
protected override void OnStart(string[] _args)
|
|
||||||
{
|
|
||||||
OpenExe();
|
|
||||||
CheckMainProcess();
|
|
||||||
}
|
|
||||||
protected override void OnStop()
|
|
||||||
{
|
|
||||||
cancellationTokenSource?.Cancel();
|
|
||||||
KillExe();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private Process proc;
|
|
||||||
private void CheckMainProcess()
|
|
||||||
{
|
|
||||||
|
|
||||||
Task.Run(async () =>
|
|
||||||
{
|
|
||||||
while (cancellationTokenSource.IsCancellationRequested == false)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (Process.GetProcessesByName(mainExeName).Any() == false)
|
|
||||||
{
|
|
||||||
string filename = Process.GetCurrentProcess().MainModule.FileName;
|
|
||||||
string dir = Path.GetDirectoryName(filename);
|
|
||||||
if (File.Exists(Path.Combine(dir, $"{mainExeName}.exe.temp")))
|
|
||||||
{
|
|
||||||
RestartService();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
KillExe();
|
|
||||||
OpenExe();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
await Task.Delay(3000).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
private bool OpenExe()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
string filename = Process.GetCurrentProcess().MainModule.FileName;
|
|
||||||
string dir = Path.GetDirectoryName(filename);
|
|
||||||
proc = Process.Start(new ProcessStartInfo()
|
|
||||||
{
|
|
||||||
WorkingDirectory = dir,
|
|
||||||
FileName = Path.Combine(dir, $"{mainExeName}.exe"),
|
|
||||||
CreateNoWindow = false,
|
|
||||||
ErrorDialog = false,
|
|
||||||
UseShellExecute = true,
|
|
||||||
WindowStyle = ProcessWindowStyle.Hidden,
|
|
||||||
//Arguments = string.Join(" ", this.args),
|
|
||||||
Verb = "runas",
|
|
||||||
});
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
proc.Kill();
|
|
||||||
proc.Dispose();
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
proc = null;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
private void KillExe()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
proc?.Close();
|
|
||||||
proc?.Dispose();
|
|
||||||
|
|
||||||
foreach (var item in Process.GetProcessesByName(mainExeName))
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
item.Kill();
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var item in Process.GetProcessesByName("tun2socks"))
|
|
||||||
{
|
|
||||||
item.Kill();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
proc = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void RestartService()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
KillExe();
|
|
||||||
Environment.Exit(1);
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,24 +0,0 @@
|
|||||||
using System.ServiceProcess;
|
|
||||||
|
|
||||||
namespace linker.service
|
|
||||||
{
|
|
||||||
internal class Program
|
|
||||||
{
|
|
||||||
static void Main(string[] args)
|
|
||||||
{
|
|
||||||
AppDomain.CurrentDomain.UnhandledException += (a, b) =>
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
if (OperatingSystem.IsWindows())
|
|
||||||
{
|
|
||||||
ServiceBase[] ServicesToRun;
|
|
||||||
ServicesToRun = new ServiceBase[]
|
|
||||||
{
|
|
||||||
new LinkerService(args)
|
|
||||||
};
|
|
||||||
ServiceBase.Run(ServicesToRun);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,79 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
|
|
||||||
<assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
|
|
||||||
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
|
|
||||||
<security>
|
|
||||||
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
|
|
||||||
<!-- UAC 清单选项
|
|
||||||
如果想要更改 Windows 用户帐户控制级别,请使用
|
|
||||||
以下节点之一替换 requestedExecutionLevel 节点。
|
|
||||||
|
|
||||||
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
|
|
||||||
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
|
|
||||||
<requestedExecutionLevel level="highestAvailable" uiAccess="false" />
|
|
||||||
|
|
||||||
指定 requestedExecutionLevel 元素将禁用文件和注册表虚拟化。
|
|
||||||
如果你的应用程序需要此虚拟化来实现向后兼容性,则移除此
|
|
||||||
元素。
|
|
||||||
-->
|
|
||||||
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
|
|
||||||
</requestedPrivileges>
|
|
||||||
</security>
|
|
||||||
</trustInfo>
|
|
||||||
|
|
||||||
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
|
||||||
<application>
|
|
||||||
<!-- 设计此应用程序与其一起工作且已针对此应用程序进行测试的
|
|
||||||
Windows 版本的列表。取消评论适当的元素,
|
|
||||||
Windows 将自动选择最兼容的环境。 -->
|
|
||||||
|
|
||||||
<!-- Windows Vista -->
|
|
||||||
<!--<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}" />-->
|
|
||||||
|
|
||||||
<!-- Windows 7 -->
|
|
||||||
<!--<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />-->
|
|
||||||
|
|
||||||
<!-- Windows 8 -->
|
|
||||||
<!--<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" />-->
|
|
||||||
|
|
||||||
<!-- Windows 8.1 -->
|
|
||||||
<!--<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" />-->
|
|
||||||
|
|
||||||
<!-- Windows 10 -->
|
|
||||||
<!--<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />-->
|
|
||||||
|
|
||||||
</application>
|
|
||||||
</compatibility>
|
|
||||||
|
|
||||||
<!-- 指示该应用程序可感知 DPI 且 Windows 在 DPI 较高时将不会对其进行
|
|
||||||
自动缩放。Windows Presentation Foundation (WPF)应用程序自动感知 DPI,无需
|
|
||||||
选择加入。选择加入此设置的 Windows 窗体应用程序(面向 .NET Framework 4.6)还应
|
|
||||||
在其 app.config 中将 "EnableWindowsFormsHighDpiAutoResizing" 设置设置为 "true"。
|
|
||||||
|
|
||||||
将应用程序设为感知长路径。请参阅 https://docs.microsoft.com/windows/win32/fileio/maximum-file-path-limitation -->
|
|
||||||
<!--
|
|
||||||
<application xmlns="urn:schemas-microsoft-com:asm.v3">
|
|
||||||
<windowsSettings>
|
|
||||||
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
|
|
||||||
<longPathAware xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">true</longPathAware>
|
|
||||||
</windowsSettings>
|
|
||||||
</application>
|
|
||||||
-->
|
|
||||||
|
|
||||||
<!-- 启用 Windows 公共控件和对话框的主题(Windows XP 和更高版本) -->
|
|
||||||
<!--
|
|
||||||
<dependency>
|
|
||||||
<dependentAssembly>
|
|
||||||
<assemblyIdentity
|
|
||||||
type="win32"
|
|
||||||
name="Microsoft.Windows.Common-Controls"
|
|
||||||
version="6.0.0.0"
|
|
||||||
processorArchitecture="*"
|
|
||||||
publicKeyToken="6595b64144ccf1df"
|
|
||||||
language="*"
|
|
||||||
/>
|
|
||||||
</dependentAssembly>
|
|
||||||
</dependency>
|
|
||||||
-->
|
|
||||||
|
|
||||||
</assembly>
|
|
Before Width: | Height: | Size: 28 KiB |
@@ -1,43 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<OutputType>Exe</OutputType>
|
|
||||||
<TargetFrameworks>net8.0</TargetFrameworks>
|
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
|
||||||
<Nullable>disable</Nullable>
|
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
|
||||||
<ApplicationManifest>app.manifest</ApplicationManifest>
|
|
||||||
<ApplicationIcon>favicon.ico</ApplicationIcon>
|
|
||||||
<BuiltInComInteropSupport>true</BuiltInComInteropSupport>
|
|
||||||
<Configurations>Debug;Release</Configurations>
|
|
||||||
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
|
|
||||||
<PublishAot>false</PublishAot>
|
|
||||||
<JsonSerializerIsReflectionEnabledByDefault>true</JsonSerializerIsReflectionEnabledByDefault>
|
|
||||||
<EnablePreviewFeatures>true</EnablePreviewFeatures>
|
|
||||||
<Version>1.2.0</Version>
|
|
||||||
<Authors>snltty</Authors>
|
|
||||||
<Company>snltty</Company>
|
|
||||||
<Description>snltty</Description>
|
|
||||||
<Copyright>snltty</Copyright>
|
|
||||||
<PackageProjectUrl>https://github.com/snltty/linker</PackageProjectUrl>
|
|
||||||
<RepositoryUrl>https://github.com/snltty/linker</RepositoryUrl>
|
|
||||||
<PackageReleaseNotes>snltty service</PackageReleaseNotes>
|
|
||||||
<AssemblyVersion>1.2.0.3</AssemblyVersion>
|
|
||||||
<FileVersion>1.2.0.3</FileVersion>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
|
||||||
<DebugType>full</DebugType>
|
|
||||||
<DebugSymbols>true</DebugSymbols>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
|
||||||
<DebugType>none</DebugType>
|
|
||||||
<DebugSymbols>false</DebugSymbols>
|
|
||||||
<Optimize>True</Optimize>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="System.ServiceProcess.ServiceController" Version="8.0.0" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
|
@@ -1,11 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
||||||
<PropertyGroup>
|
|
||||||
<_LastSelectedProfileId>D:\desktop\cmonitor\cmonitor.sas.service\Properties\PublishProfiles\FolderProfile.pubxml</_LastSelectedProfileId>
|
|
||||||
</PropertyGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<Compile Update="LinkerService.cs">
|
|
||||||
<SubType>Component</SubType>
|
|
||||||
</Compile>
|
|
||||||
</ItemGroup>
|
|
||||||
</Project>
|
|
16
linker.sln
@@ -9,13 +9,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "linker.libs", "linker.libs\
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "linker.tests", "linker.tests\linker.tests.csproj", "{04AA3054-5350-4D8B-97F6-31495AE0609D}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "linker.tests", "linker.tests\linker.tests.csproj", "{04AA3054-5350-4D8B-97F6-31495AE0609D}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "linker.service", "linker.service\linker.service.csproj", "{E8AB5039-3A42-424F-AAEC-A102C8CAA305}"
|
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "linker.tunnel", "linker.tunnel\linker.tunnel.csproj", "{AFADE8D6-AB00-456B-9F43-53BC95B7B608}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "linker.tunnel", "linker.tunnel\linker.tunnel.csproj", "{AFADE8D6-AB00-456B-9F43-53BC95B7B608}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "linker.tun", "linker.tun\linker.tun.csproj", "{0DE134E0-7CD8-4DCF-8D2A-325CEBE5895F}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "linker.tun", "linker.tun\linker.tun.csproj", "{0DE134E0-7CD8-4DCF-8D2A-325CEBE5895F}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "linker.tun.test", "linker.tun.test\linker.tun.test.csproj", "{4A660D3B-76DE-4E6F-9E90-90BA0DBE906A}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "linker.tun.test", "linker.tun.test\linker.tun.test.csproj", "{4A660D3B-76DE-4E6F-9E90-90BA0DBE906A}"
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
@@ -63,18 +61,6 @@ Global
|
|||||||
{04AA3054-5350-4D8B-97F6-31495AE0609D}.Release|x64.Build.0 = Release|Any CPU
|
{04AA3054-5350-4D8B-97F6-31495AE0609D}.Release|x64.Build.0 = Release|Any CPU
|
||||||
{04AA3054-5350-4D8B-97F6-31495AE0609D}.Release|x86.ActiveCfg = Release|Any CPU
|
{04AA3054-5350-4D8B-97F6-31495AE0609D}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
{04AA3054-5350-4D8B-97F6-31495AE0609D}.Release|x86.Build.0 = Release|Any CPU
|
{04AA3054-5350-4D8B-97F6-31495AE0609D}.Release|x86.Build.0 = Release|Any CPU
|
||||||
{E8AB5039-3A42-424F-AAEC-A102C8CAA305}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{E8AB5039-3A42-424F-AAEC-A102C8CAA305}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{E8AB5039-3A42-424F-AAEC-A102C8CAA305}.Debug|x64.ActiveCfg = Debug|Any CPU
|
|
||||||
{E8AB5039-3A42-424F-AAEC-A102C8CAA305}.Debug|x64.Build.0 = Debug|Any CPU
|
|
||||||
{E8AB5039-3A42-424F-AAEC-A102C8CAA305}.Debug|x86.ActiveCfg = Debug|Any CPU
|
|
||||||
{E8AB5039-3A42-424F-AAEC-A102C8CAA305}.Debug|x86.Build.0 = Debug|Any CPU
|
|
||||||
{E8AB5039-3A42-424F-AAEC-A102C8CAA305}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{E8AB5039-3A42-424F-AAEC-A102C8CAA305}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{E8AB5039-3A42-424F-AAEC-A102C8CAA305}.Release|x64.ActiveCfg = Release|Any CPU
|
|
||||||
{E8AB5039-3A42-424F-AAEC-A102C8CAA305}.Release|x64.Build.0 = Release|Any CPU
|
|
||||||
{E8AB5039-3A42-424F-AAEC-A102C8CAA305}.Release|x86.ActiveCfg = Release|Any CPU
|
|
||||||
{E8AB5039-3A42-424F-AAEC-A102C8CAA305}.Release|x86.Build.0 = Release|Any CPU
|
|
||||||
{AFADE8D6-AB00-456B-9F43-53BC95B7B608}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{AFADE8D6-AB00-456B-9F43-53BC95B7B608}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{AFADE8D6-AB00-456B-9F43-53BC95B7B608}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{AFADE8D6-AB00-456B-9F43-53BC95B7B608}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{AFADE8D6-AB00-456B-9F43-53BC95B7B608}.Debug|x64.ActiveCfg = Debug|Any CPU
|
{AFADE8D6-AB00-456B-9F43-53BC95B7B608}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
|
|
||||||
using linker.config;
|
using linker.config;
|
||||||
using linker.plugins.serializes;
|
using linker.plugins.serializes;
|
||||||
|
using linker.plugins.signin.messenger;
|
||||||
using linker.plugins.tuntap.config;
|
using linker.plugins.tuntap.config;
|
||||||
using linker.tunnel.connection;
|
using linker.tunnel.connection;
|
||||||
using linker.tunnel.transport;
|
using linker.tunnel.transport;
|
||||||
@@ -19,30 +20,47 @@ namespace linker.Tests
|
|||||||
MemoryPackFormatterProvider.Register(new IPAddressFormatter());
|
MemoryPackFormatterProvider.Register(new IPAddressFormatter());
|
||||||
|
|
||||||
|
|
||||||
TuntapInfo tuntapInfo = new TuntapInfo
|
|
||||||
|
|
||||||
|
byte[] bytes = MemoryPackSerializer.Serialize(new SignInListRequestInfo1
|
||||||
{
|
{
|
||||||
Error = "dfgdgdfgdfgddfgdfhdhdhdhdfhdfdfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
|
GroupId = string.Empty,
|
||||||
Gateway = false,
|
Ids =[],
|
||||||
IP = IPAddress.Any,
|
Name = "11",
|
||||||
LanIPs = new IPAddress[] { IPAddress.Any, IPAddress.Loopback, IPAddress.Broadcast },
|
Page = 1,
|
||||||
Masks = [24, 24, 24],
|
Size = 1,
|
||||||
MachineId = "dfgdgdfgdfgddfgdfhdhdhdhdfhdfdfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
|
});
|
||||||
Status = TuntapStatus.Normal,
|
|
||||||
System = "dfgdgdfgdfgddfgdfhdhdhdhdfhdfdfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
|
|
||||||
};
|
|
||||||
List<TuntapInfo> tuntapInfos = new List<TuntapInfo>();
|
|
||||||
for (int i = 0; i < 100; i++)
|
|
||||||
{
|
|
||||||
tuntapInfos.Add(tuntapInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
byte[] bytes = MemoryPackSerializer.Serialize(tuntapInfos);
|
SignInListRequestInfo tuntapInfos1 = MemoryPackSerializer.Deserialize<SignInListRequestInfo>(bytes);
|
||||||
|
|
||||||
List<TuntapInfo> tuntapInfos1 = MemoryPackSerializer.Deserialize<List<TuntapInfo>>(bytes);
|
Assert.AreEqual(tuntapInfos1.Name, "11");
|
||||||
|
|
||||||
Assert.AreEqual(tuntapInfos1.Count, tuntapInfos.Count);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MemoryPackable]
|
||||||
|
public sealed partial class SignInListRequestInfo1
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// <20><>ǰҳ
|
||||||
|
/// </summary>
|
||||||
|
public int Page { get; set; } = 1;
|
||||||
|
/// <summary>
|
||||||
|
/// ÿҳ<C3BF><D2B3>С
|
||||||
|
/// </summary>
|
||||||
|
public int Size { get; set; } = 10;
|
||||||
|
/// <summary>
|
||||||
|
/// <20><><EFBFBD>ڷ<EFBFBD><DAB7><EFBFBD>
|
||||||
|
/// </summary>
|
||||||
|
public string GroupId { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||||
|
/// </summary>
|
||||||
|
public string Name { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// <20><>id<69><64>ȡ
|
||||||
|
/// </summary>
|
||||||
|
public string[] Ids { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
@@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<project ver="10" name="linker.tray.win" libEmbed="true" icon="..\linker\favicon.ico" ui="win" output="linker.tray.win.exe" CompanyName="snltty" FileDescription="linker.tray.win" LegalCopyright="Copyright (C) snltty 2024" ProductName="linker.tray.win" InternalName="linker.install.win" FileVersion="0.0.0.59" ProductVersion="0.0.0.59" publishDir="/dist/" dstrip="false" local="false" ignored="false">
|
<project ver="10" name="linker.tray.win" libEmbed="true" icon="..\linker\favicon.ico" ui="win" output="linker.tray.win.exe" CompanyName="snltty" FileDescription="linker.tray.win" LegalCopyright="Copyright (C) snltty 2024" ProductName="linker.tray.win" InternalName="linker.install.win" FileVersion="0.0.0.63" ProductVersion="0.0.0.63" publishDir="/dist/" dstrip="false" local="false" ignored="false">
|
||||||
<file name="main.aardio" path="main.aardio" comment="main.aardio"/>
|
<file name="main.aardio" path="main.aardio" comment="main.aardio"/>
|
||||||
<folder name="资源文件" path="res" embed="true" local="false" ignored="false">
|
<folder name="资源文件" path="res" embed="true" local="false" ignored="false">
|
||||||
<file name="favicon.ico" path="res\favicon.ico" comment="res\favicon.ico"/>
|
<file name="favicon.ico" path="res\favicon.ico" comment="res\favicon.ico"/>
|
||||||
|
BIN
linker.tray.win/dist/linker.tray.win.exe
vendored
@@ -30,7 +30,7 @@ catch(e){
|
|||||||
|
|
||||||
|
|
||||||
mainForm.serviceName = "linker.service";
|
mainForm.serviceName = "linker.service";
|
||||||
mainForm.exeName = "linker.service.exe";
|
mainForm.exeName = "linker.exe";
|
||||||
|
|
||||||
import win.image;
|
import win.image;
|
||||||
hIcon = win.image.loadIconFromFile("/res/favicon.ico",true);
|
hIcon = win.image.loadIconFromFile("/res/favicon.ico",true);
|
||||||
@@ -51,6 +51,8 @@ mainForm.wndproc = function(hwnd,message,wParam,lParam){
|
|||||||
//左键
|
//左键
|
||||||
if(lParam === 0x0202){
|
if(lParam === 0x0202){
|
||||||
mainForm.show();
|
mainForm.show();
|
||||||
|
win.setTopmost(mainForm.hwnd);
|
||||||
|
win.setTopmost(mainForm.hwnd,false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//关闭
|
//关闭
|
||||||
@@ -248,6 +250,8 @@ mainForm.showPopmenu();
|
|||||||
if(!_ARGV["task"])
|
if(!_ARGV["task"])
|
||||||
{
|
{
|
||||||
mainForm.show();
|
mainForm.show();
|
||||||
|
win.setTopmost(mainForm.hwnd);
|
||||||
|
win.setTopmost(mainForm.hwnd,false);
|
||||||
}
|
}
|
||||||
|
|
||||||
mainForm.setInterval(
|
mainForm.setInterval(
|
||||||
@@ -257,12 +261,15 @@ mainForm.setInterval(
|
|||||||
try{
|
try{
|
||||||
if(io.exist(io._exefile+".temp"))
|
if(io.exist(io._exefile+".temp"))
|
||||||
{
|
{
|
||||||
|
mainForm.reStart();
|
||||||
|
/*
|
||||||
var prcs = process.popen.cmd("tasklist | findstr "+mainForm.serviceName);
|
var prcs = process.popen.cmd("tasklist | findstr "+mainForm.serviceName);
|
||||||
var str = prcs.readAll();
|
var str = prcs.readAll();
|
||||||
if(!!!string.indexOf(str,mainForm.serviceName))
|
if(!!!string.indexOf(str,mainForm.serviceName))
|
||||||
{
|
{
|
||||||
mainForm.reStart();
|
mainForm.reStart();
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
}catch(e)
|
}catch(e)
|
||||||
{
|
{
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace linker.tun
|
namespace linker.tun
|
||||||
{
|
{
|
||||||
@@ -50,6 +51,18 @@ namespace linker.tun
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void RemoveNat(out string error);
|
public void RemoveNat(out string error);
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 添加端口转发
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="forwards"></param>
|
||||||
|
public void AddForward(List<LinkerTunDeviceForwardItem> forwards);
|
||||||
|
/// <summary>
|
||||||
|
/// 删除端口转发
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="forwards"></param>
|
||||||
|
public void RemoveForward(List<LinkerTunDeviceForwardItem> forwards);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 添加路由
|
/// 添加路由
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -90,6 +103,17 @@ namespace linker.tun
|
|||||||
public Task Callback(LinkerTunDevicPacket packet);
|
public Task Callback(LinkerTunDevicPacket packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public sealed class LinkerTunDeviceForwardItem
|
||||||
|
{
|
||||||
|
public IPAddress ListenAddr { get; set; } = IPAddress.Any;
|
||||||
|
public int ListenPort { get; set; }
|
||||||
|
public IPAddress ConnectAddr { get; set; } = IPAddress.Any;
|
||||||
|
public int ConnectPort { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore]
|
||||||
|
public bool Enable => ListenPort > 0 && ConnectAddr.Equals(IPAddress.Any) == false && ConnectPort > 0;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 数据包
|
/// 数据包
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@@ -162,6 +162,15 @@ namespace linker.tun
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void AddForward(List<LinkerTunDeviceForwardItem> forwards)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
public void RemoveForward(List<LinkerTunDeviceForwardItem> forwards)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public void AddRoute(LinkerTunDeviceRouteItem[] ips, IPAddress ip, bool gateway)
|
public void AddRoute(LinkerTunDeviceRouteItem[] ips, IPAddress ip, bool gateway)
|
||||||
{
|
{
|
||||||
if (gateway)
|
if (gateway)
|
||||||
@@ -276,8 +285,9 @@ namespace linker.tun
|
|||||||
|
|
||||||
public void Clear()
|
public void Clear()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -112,6 +112,14 @@ namespace linker.tun
|
|||||||
error = string.Empty;
|
error = string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void AddForward(List<LinkerTunDeviceForwardItem> forwards)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
public void RemoveForward(List<LinkerTunDeviceForwardItem> forwards)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private byte[] buffer = new byte[2 * 1024];
|
private byte[] buffer = new byte[2 * 1024];
|
||||||
public ReadOnlyMemory<byte> Read()
|
public ReadOnlyMemory<byte> Read()
|
||||||
{
|
{
|
||||||
|
@@ -16,6 +16,10 @@ namespace linker.tun
|
|||||||
private string error = string.Empty;
|
private string error = string.Empty;
|
||||||
public string Error => error;
|
public string Error => error;
|
||||||
|
|
||||||
|
private string error1 = string.Empty;
|
||||||
|
public string Error1 => error1;
|
||||||
|
|
||||||
|
|
||||||
private uint operating = 0;
|
private uint operating = 0;
|
||||||
public LinkerTunDeviceStatus Status
|
public LinkerTunDeviceStatus Status
|
||||||
{
|
{
|
||||||
@@ -125,7 +129,6 @@ namespace linker.tun
|
|||||||
{
|
{
|
||||||
cancellationTokenSource?.Cancel();
|
cancellationTokenSource?.Cancel();
|
||||||
linkerTunDevice?.Shutdown();
|
linkerTunDevice?.Shutdown();
|
||||||
linkerTunDevice?.RemoveNat(out error);
|
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
@@ -142,14 +145,31 @@ namespace linker.tun
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void SetNat()
|
public void SetNat()
|
||||||
{
|
{
|
||||||
linkerTunDevice?.SetNat(out error);
|
linkerTunDevice?.SetNat(out error1);
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 移除NAT转发
|
/// 移除NAT转发
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void RemoveNat()
|
public void RemoveNat()
|
||||||
{
|
{
|
||||||
linkerTunDevice?.RemoveNat(out error);
|
linkerTunDevice?.RemoveNat(out error1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 添加端口转发
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="forwards"></param>
|
||||||
|
public void AddForward(List<LinkerTunDeviceForwardItem> forwards)
|
||||||
|
{
|
||||||
|
linkerTunDevice?.AddForward(forwards);
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 移除端口转发
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="forwards"></param>
|
||||||
|
public void RemoveForward(List<LinkerTunDeviceForwardItem> forwards)
|
||||||
|
{
|
||||||
|
linkerTunDevice?.RemoveForward(forwards);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@@ -118,9 +118,9 @@ namespace linker.tun
|
|||||||
error = string.Empty;
|
error = string.Empty;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
CommandHelper.PowerShell($"start-service WinNat", []);
|
CommandHelper.PowerShell($"start-service WinNat", [], out error);
|
||||||
IPAddress network = NetworkHelper.ToNetworkIp(this.address, NetworkHelper.MaskValue(prefixLength));
|
IPAddress network = NetworkHelper.ToNetworkIp(this.address, NetworkHelper.MaskValue(prefixLength));
|
||||||
CommandHelper.PowerShell($"New-NetNat -Name {Name} -InternalIPInterfaceAddressPrefix {network}/{prefixLength}", []);
|
CommandHelper.PowerShell($"New-NetNat -Name {Name} -InternalIPInterfaceAddressPrefix {network}/{prefixLength}", [], out error);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -148,9 +148,9 @@ namespace linker.tun
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
CommandHelper.PowerShell($"start-service WinNat", []);
|
CommandHelper.PowerShell($"start-service WinNat", [], out error);
|
||||||
CommandHelper.PowerShell($"Remove-NetNat -Name {Name} -Confirm:$false", []);
|
CommandHelper.PowerShell($"Remove-NetNat -Name {Name} -Confirm:$false", [], out error);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var scope = new ManagementScope(@"root\StandardCimv2");
|
var scope = new ManagementScope(@"root\StandardCimv2");
|
||||||
@@ -176,6 +176,25 @@ namespace linker.tun
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void AddForward(List<LinkerTunDeviceForwardItem> forwards)
|
||||||
|
{
|
||||||
|
string[] commands = forwards.Where(c => c != null && c.Enable).Select(c =>
|
||||||
|
{
|
||||||
|
return $"netsh interface portproxy add v4tov4 listenaddress={c.ListenAddr} listenport={c.ListenPort} connectaddress={c.ConnectAddr} connectport={c.ConnectPort}";
|
||||||
|
}).ToArray();
|
||||||
|
CommandHelper.Windows(string.Empty, commands);
|
||||||
|
}
|
||||||
|
public void RemoveForward(List<LinkerTunDeviceForwardItem> forwards)
|
||||||
|
{
|
||||||
|
string[] commands = forwards.Where(c => c != null && c.Enable).Select(c =>
|
||||||
|
{
|
||||||
|
return $"netsh interface portproxy delete v4tov4 listenport={c.ListenPort} listenaddress={c.ListenAddr}";
|
||||||
|
}).ToArray();
|
||||||
|
CommandHelper.Windows(string.Empty, commands);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public void AddRoute(LinkerTunDeviceRouteItem[] ips, IPAddress ip, bool gateway)
|
public void AddRoute(LinkerTunDeviceRouteItem[] ips, IPAddress ip, bool gateway)
|
||||||
{
|
{
|
||||||
if (interfaceNumber > 0)
|
if (interfaceNumber > 0)
|
||||||
|
@@ -17,8 +17,8 @@
|
|||||||
<PackageProjectUrl>https://github.com/snltty/linker</PackageProjectUrl>
|
<PackageProjectUrl>https://github.com/snltty/linker</PackageProjectUrl>
|
||||||
<RepositoryUrl>https://github.com/snltty/linker</RepositoryUrl>
|
<RepositoryUrl>https://github.com/snltty/linker</RepositoryUrl>
|
||||||
<PackageReleaseNotes>linker tun</PackageReleaseNotes>
|
<PackageReleaseNotes>linker tun</PackageReleaseNotes>
|
||||||
<AssemblyVersion>1.2.0.3</AssemblyVersion>
|
<AssemblyVersion>1.2.0.4</AssemblyVersion>
|
||||||
<FileVersion>1.2.0.3</FileVersion>
|
<FileVersion>1.2.0.4</FileVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||||
|
@@ -17,8 +17,8 @@
|
|||||||
<PackageProjectUrl>https://github.com/snltty/linker</PackageProjectUrl>
|
<PackageProjectUrl>https://github.com/snltty/linker</PackageProjectUrl>
|
||||||
<RepositoryUrl>https://github.com/snltty/linker</RepositoryUrl>
|
<RepositoryUrl>https://github.com/snltty/linker</RepositoryUrl>
|
||||||
<PackageReleaseNotes>linker tunnel</PackageReleaseNotes>
|
<PackageReleaseNotes>linker tunnel</PackageReleaseNotes>
|
||||||
<AssemblyVersion>1.2.0.3</AssemblyVersion>
|
<AssemblyVersion>1.2.0.4</AssemblyVersion>
|
||||||
<FileVersion>1.2.0.3</FileVersion>
|
<FileVersion>1.2.0.4</FileVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||||
|
@@ -230,7 +230,7 @@ namespace linker.tunnel.transport
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}).AsTask().WaitAsync(TimeSpan.FromMilliseconds(5000)).ConfigureAwait(false);
|
}).AsTask().WaitAsync(TimeSpan.FromMilliseconds(1000)).ConfigureAwait(false);
|
||||||
QuicStream quicStream = await connection.OpenOutboundStreamAsync(QuicStreamType.Bidirectional).ConfigureAwait(false);
|
QuicStream quicStream = await connection.OpenOutboundStreamAsync(QuicStreamType.Bidirectional).ConfigureAwait(false);
|
||||||
return new TunnelConnectionMsQuic
|
return new TunnelConnectionMsQuic
|
||||||
{
|
{
|
||||||
|
@@ -11,6 +11,9 @@ export const setSignInServers = (servers) => {
|
|||||||
export const getSignInfo = () => {
|
export const getSignInfo = () => {
|
||||||
return sendWebsocketMsg('signInclient/info');
|
return sendWebsocketMsg('signInclient/info');
|
||||||
}
|
}
|
||||||
|
export const setSignInIndex = (ids) => {
|
||||||
|
return sendWebsocketMsg('signInclient/setindex', ids);
|
||||||
|
}
|
||||||
export const getSignInList = (data) => {
|
export const getSignInList = (data) => {
|
||||||
return sendWebsocketMsg('signInclient/List', data);
|
return sendWebsocketMsg('signInclient/List', data);
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-table-column prop="MachineId" label="设备">
|
<el-table-column prop="MachineId" label="设备" width="240">
|
||||||
<template #header>
|
<template #header>
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
<span class="flex-1">设备</span>
|
<span class="flex-1">设备</span>
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
<div>
|
<div>
|
||||||
<p>
|
<p>
|
||||||
<template v-if="tuntap.list[scope.row.MachineId] && tuntap.list[scope.row.MachineId].system">
|
<template v-if="tuntap.list[scope.row.MachineId] && tuntap.list[scope.row.MachineId].system">
|
||||||
<span :title="tuntap.list[scope.row.MachineId].System">
|
<span :title="tuntap.list[scope.row.MachineId].SystemInfo">
|
||||||
<img v-if="scope.row.countryFlag" class="system" :src="scope.row.countryFlag" />
|
<img v-if="scope.row.countryFlag" class="system" :src="scope.row.countryFlag" />
|
||||||
<img class="system":src="`/${tuntap.list[scope.row.MachineId].system}.svg`" />
|
<img class="system":src="`/${tuntap.list[scope.row.MachineId].system}.svg`" />
|
||||||
<img v-if="tuntap.list[scope.row.MachineId].systemDocker" class="system" src="/docker.svg" />
|
<img v-if="tuntap.list[scope.row.MachineId].systemDocker" class="system" src="/docker.svg" />
|
||||||
|
@@ -1,5 +1,13 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="home-list-wrap absolute" >
|
<div class="home-list-wrap absolute" >
|
||||||
|
<el-table border style="width: 100%" height="32px" size="small" @sort-change="handleSortChange" class="table-sort">
|
||||||
|
<el-table-column prop="MachineId" label="设备名" width="120" sortable ></el-table-column>
|
||||||
|
<el-table-column prop="Version" label="版本" width="120" sortable></el-table-column>
|
||||||
|
<el-table-column prop="tunnel" label="网关" width="90" sortable></el-table-column>
|
||||||
|
<el-table-column prop="tuntap" label="网卡IP" width="150" sortable></el-table-column>
|
||||||
|
<el-table-column prop="forward" label=""></el-table-column>
|
||||||
|
<el-table-column label="" width="74" fixed="right"></el-table-column>
|
||||||
|
</el-table>
|
||||||
<el-table :data="devices.page.List" stripe border style="width: 100%" :height="`${state.height}px`" size="small">
|
<el-table :data="devices.page.List" stripe border style="width: 100%" :height="`${state.height}px`" size="small">
|
||||||
<Device @edit="handleDeviceEdit" @refresh="handlePageRefresh"></Device>
|
<Device @edit="handleDeviceEdit" @refresh="handlePageRefresh"></Device>
|
||||||
<Tunnel @edit="handleTunnelEdit" @refresh="handleTunnelRefresh" @connections="handleTunnelConnections"></Tunnel>
|
<Tunnel @edit="handleTunnelEdit" @refresh="handleTunnelRefresh" @connections="handleTunnelConnections"></Tunnel>
|
||||||
@@ -55,14 +63,14 @@ export default {
|
|||||||
|
|
||||||
const globalData = injectGlobalData();
|
const globalData = injectGlobalData();
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
height: computed(()=>globalData.value.height-60),
|
height: computed(()=>globalData.value.height-90),
|
||||||
});
|
});
|
||||||
|
|
||||||
const {devices, machineId, _getSignList, _getSignList1,
|
const {devices, machineId, _getSignList, _getSignList1,
|
||||||
handleDeviceEdit, handlePageChange, handlePageSizeChange, handleDel,clearDevicesTimeout} = provideDevices();
|
handleDeviceEdit, handlePageChange, handlePageSizeChange, handleDel,clearDevicesTimeout,setSort} = provideDevices();
|
||||||
|
|
||||||
const {tuntap,_getTuntapInfo,handleTuntapEdit,handleTuntapRefresh,clearTuntapTimeout,getTuntapMachines} = provideTuntap();
|
const {tuntap,_getTuntapInfo,handleTuntapEdit,handleTuntapRefresh,clearTuntapTimeout,getTuntapMachines,sortTuntapIP} = provideTuntap();
|
||||||
const {tunnel,_getTunnelInfo,handleTunnelEdit,handleTunnelRefresh,clearTunnelTimeout} = provideTunnel();
|
const {tunnel,_getTunnelInfo,handleTunnelEdit,handleTunnelRefresh,clearTunnelTimeout,sortTunnel} = provideTunnel();
|
||||||
const {forward,_getForwardInfo,handleForwardEdit,_testTargetForwardInfo,clearForwardTimeout,getForwardMachines} = provideForward();
|
const {forward,_getForwardInfo,handleForwardEdit,_testTargetForwardInfo,clearForwardTimeout,getForwardMachines} = provideForward();
|
||||||
const {sforward,_getSForwardInfo,handleSForwardEdit,_testLocalSForwardInfo,clearSForwardTimeout,getSForwardMachines} = provideSforward();
|
const {sforward,_getSForwardInfo,handleSForwardEdit,_testLocalSForwardInfo,clearSForwardTimeout,getSForwardMachines} = provideSforward();
|
||||||
const {connections,
|
const {connections,
|
||||||
@@ -73,6 +81,30 @@ export default {
|
|||||||
|
|
||||||
const {_getUpdater,clearUpdaterTimeout} = provideUpdater();
|
const {_getUpdater,clearUpdaterTimeout} = provideUpdater();
|
||||||
|
|
||||||
|
const handleSortChange = (row)=>{
|
||||||
|
|
||||||
|
devices.page.Request.Prop = row.prop;
|
||||||
|
devices.page.Request.Asc = row.order == 'ascending';
|
||||||
|
|
||||||
|
let fn = new Promise((resolve,reject)=>{
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
if(row.prop == 'tunnel'){
|
||||||
|
const ids = sortTunnel(devices.page.Request.Asc);
|
||||||
|
if(ids .length > 0){
|
||||||
|
fn = setSort(ids);
|
||||||
|
}
|
||||||
|
}else if(row.prop == 'tuntap'){
|
||||||
|
const ids = sortTuntapIP(devices.page.Request.Asc);
|
||||||
|
if(ids .length > 0){
|
||||||
|
fn = setSort(ids);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn.then(()=>{
|
||||||
|
handlePageChange();
|
||||||
|
}).catch(()=>{});
|
||||||
|
}
|
||||||
|
|
||||||
const _handleForwardEdit = (machineId) => {
|
const _handleForwardEdit = (machineId) => {
|
||||||
handleForwardEdit(machineId,devices.page.List.filter(c => c.MachineId == machineId)[0].MachineName);
|
handleForwardEdit(machineId,devices.page.List.filter(c => c.MachineId == machineId)[0].MachineName);
|
||||||
}
|
}
|
||||||
@@ -142,7 +174,7 @@ export default {
|
|||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
state,devices, machineId,
|
state,devices, machineId,handleSortChange,
|
||||||
handleDeviceEdit,handlePageRefresh,handlePageSearch, handlePageChange,handlePageSizeChange, handleDel,
|
handleDeviceEdit,handlePageRefresh,handlePageSearch, handlePageChange,handlePageSizeChange, handleDel,
|
||||||
tuntap, handleTuntapEdit, handleTuntapRefresh,
|
tuntap, handleTuntapEdit, handleTuntapRefresh,
|
||||||
tunnel,connections, handleTunnelEdit, handleTunnelRefresh,handleTunnelConnections,
|
tunnel,connections, handleTunnelEdit, handleTunnelRefresh,handleTunnelConnections,
|
||||||
@@ -152,7 +184,18 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
<style lang="stylus">
|
||||||
|
.table-sort.el-table
|
||||||
|
{
|
||||||
|
th.el-table__cell.is-leaf{border-bottom:0}
|
||||||
|
.el-table__inner-wrapper:before{height:0}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
<style lang="stylus" scoped>
|
<style lang="stylus" scoped>
|
||||||
|
.table-sort
|
||||||
|
{
|
||||||
|
th{border-bottom:0}
|
||||||
|
}
|
||||||
.home-list-wrap{
|
.home-list-wrap{
|
||||||
padding:1rem;
|
padding:1rem;
|
||||||
|
|
||||||
|
@@ -10,8 +10,8 @@
|
|||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<a href="javascript:;" class="a-line" @click="handleConnections(scope.row.MachineId)">
|
<a href="javascript:;" class="a-line" :class="{green:connectionCount(scope.row.MachineId)>0}" @click="handleConnections(scope.row.MachineId)">
|
||||||
<span>连接数 : {{connectionCount(scope.row.MachineId)}}</span>
|
连接数 : <span>{{connectionCount(scope.row.MachineId)}}</span>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -57,4 +57,6 @@ export default {
|
|||||||
<style lang="stylus" scoped>
|
<style lang="stylus" scoped>
|
||||||
|
|
||||||
.el-switch.is-disabled{opacity :1;}
|
.el-switch.is-disabled{opacity :1;}
|
||||||
|
|
||||||
|
.green{font-weight:bold;}
|
||||||
</style>
|
</style>
|
@@ -33,9 +33,28 @@
|
|||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div v-for="(item,index) in tuntap.list[scope.row.MachineId].LanIPs" :key="index">
|
<template v-if="tuntap.list[scope.row.MachineId].Error1">
|
||||||
{{ item }} / {{ tuntap.list[scope.row.MachineId].Masks[index] }}
|
<el-popover placement="top" title="msg" width="20rem" trigger="hover" :content="tuntap.list[scope.row.MachineId].Error1">
|
||||||
</div>
|
<template #reference>
|
||||||
|
<div class="yellow">
|
||||||
|
<template v-for="(item,index) in tuntap.list[scope.row.MachineId].LanIPs" :key="index">
|
||||||
|
<div>
|
||||||
|
{{ item }} / {{ tuntap.list[scope.row.MachineId].Masks[index] }}
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-popover>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<div>
|
||||||
|
<template v-for="(item,index) in tuntap.list[scope.row.MachineId].LanIPs" :key="index">
|
||||||
|
<div>
|
||||||
|
{{ item }} / {{ tuntap.list[scope.row.MachineId].Masks[index] }}
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@@ -1,29 +1,55 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-dialog v-model="state.show" :close-on-click-modal="false" append-to=".app-wrap" title="设置虚拟网卡IP" width="420">
|
<el-dialog v-model="state.show" :close-on-click-modal="false" append-to=".app-wrap" title="组网设置" top="1vh" width="700">
|
||||||
<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="140">
|
||||||
<el-form-item prop="gateway" style="margin-bottom:0">
|
<el-form-item prop="gateway" style="margin-bottom:0">
|
||||||
<el-checkbox v-model="state.ruleForm.Gateway" label="我在路由器,我是网关" size="large" />
|
赐予此设备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" /> / 24
|
<el-input v-model="state.ruleForm.IP" style="width:12rem" /> / <el-input @change="handlePrefixLengthChange" v-model="state.ruleForm.PrefixLength" style="width:4rem" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item style="margin-bottom:0">
|
<el-form-item prop="upgrade" style="margin-bottom:0">
|
||||||
<div>局域网IP选填,不懂是啥的时候,不要填</div>
|
<el-checkbox v-model="state.ruleForm.Upgrade" label="我很懂,我要使用高级功能(点对网和网对网)" size="large" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="局域网IP" prop="LanIP">
|
<div class="upgrade-wrap" v-if="state.ruleForm.Upgrade">
|
||||||
<template v-for="(item, index) in state.ruleForm.LanIPs" :key="index">
|
<el-form-item prop="gateway" style="margin-bottom:0">
|
||||||
<div class="flex" style="margin-bottom:.6rem">
|
<el-checkbox v-model="state.ruleForm.Gateway" label="此设备在路由器(网对网,将对方的 局域网IP 转发到对方)" size="large" />
|
||||||
<div class="flex-1">
|
</el-form-item>
|
||||||
<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-form-item prop="gateway" style="margin-bottom:0">
|
||||||
|
<span class="yellow">此设备可以用NAT转发,那填写局域网IP,其它交给NAT(linux、macos、win10+)</span>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="此设备局域网IP" prop="LanIP">
|
||||||
|
<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" />
|
||||||
|
</div>
|
||||||
|
<div class="pdl-10">
|
||||||
|
<el-button type="danger" @click="handleDel(index)"><el-icon><Delete /></el-icon></el-button>
|
||||||
|
<el-button type="primary" @click="handleAdd(index)"><el-icon><Plus /></el-icon></el-button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="pdl-10">
|
</template>
|
||||||
<el-button type="danger" @click="handleDel(index)"><el-icon><Delete /></el-icon></el-button>
|
</el-form-item>
|
||||||
<el-button type="primary" @click="handleAdd(index)"><el-icon><Plus /></el-icon></el-button>
|
<el-form-item prop="gateway" style="margin-bottom:0">
|
||||||
|
<span class="yellow">此设备不能用NAT转发,那可以使用系统端口转发实现类似的效果(仅windows)</span>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="端口转发" prop="foreards">
|
||||||
|
<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" />
|
||||||
|
</div>
|
||||||
|
<div class="pdl-10">
|
||||||
|
|
||||||
|
<el-button type="danger" @click="handleDelForward(index)"><el-icon><Delete /></el-icon></el-button>
|
||||||
|
<el-button type="primary" @click="handleAddForward(index)"><el-icon><Plus /></el-icon></el-button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</template>
|
||||||
</template>
|
</el-form-item>
|
||||||
</el-form-item>
|
</div>
|
||||||
<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>
|
||||||
@@ -57,7 +83,13 @@ export default {
|
|||||||
IP: tuntap.value.current.IP,
|
IP: tuntap.value.current.IP,
|
||||||
LanIPs: tuntap.value.current.LanIPs.slice(0),
|
LanIPs: tuntap.value.current.LanIPs.slice(0),
|
||||||
Masks: tuntap.value.current.Masks.slice(0),
|
Masks: tuntap.value.current.Masks.slice(0),
|
||||||
|
PrefixLength:tuntap.value.current.PrefixLength || 24,
|
||||||
Gateway: tuntap.value.current.Gateway,
|
Gateway: tuntap.value.current.Gateway,
|
||||||
|
Upgrade: tuntap.value.current.Upgrade,
|
||||||
|
|
||||||
|
Forwards:tuntap.value.current.Forwards.slice(0) || [
|
||||||
|
{ListenAddr:'0.0.0.0',ListenPort:0,ConnectAddr:'0.0.0.0',ConnectPort:0}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
rules: {}
|
rules: {}
|
||||||
});
|
});
|
||||||
@@ -73,6 +105,13 @@ export default {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const handlePrefixLengthChange = ()=>{
|
||||||
|
var value = +state.ruleForm.PrefixLength;
|
||||||
|
if(value>32 || value<16 || isNaN(value)){
|
||||||
|
value = 24;
|
||||||
|
}
|
||||||
|
state.ruleForm.PrefixLength = value;
|
||||||
|
}
|
||||||
const handleMaskChange = (index)=>{
|
const handleMaskChange = (index)=>{
|
||||||
var value = +state.ruleForm.Masks[index];
|
var value = +state.ruleForm.Masks[index];
|
||||||
if(value>32 || value<16 || isNaN(value)){
|
if(value>32 || value<16 || isNaN(value)){
|
||||||
@@ -81,9 +120,11 @@ export default {
|
|||||||
state.ruleForm.Masks[index] = value;
|
state.ruleForm.Masks[index] = value;
|
||||||
}
|
}
|
||||||
const handleDel = (index) => {
|
const handleDel = (index) => {
|
||||||
if (state.ruleForm.LanIPs.length == 1) return;
|
|
||||||
state.ruleForm.LanIPs.splice(index, 1);
|
state.ruleForm.LanIPs.splice(index, 1);
|
||||||
state.ruleForm.Masks.splice(index, 1);
|
state.ruleForm.Masks.splice(index, 1);
|
||||||
|
if (state.ruleForm.LanIPs.length == 0){
|
||||||
|
handleAdd(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
const handleAdd = (index) => {
|
const handleAdd = (index) => {
|
||||||
state.ruleForm.LanIPs.splice(index + 1, 0, '');
|
state.ruleForm.LanIPs.splice(index + 1, 0, '');
|
||||||
@@ -101,7 +142,14 @@ export default {
|
|||||||
},{lanips:[],masks:[]});
|
},{lanips:[],masks:[]});
|
||||||
json.LanIPs = lanips;
|
json.LanIPs = lanips;
|
||||||
json.Masks = masks;
|
json.Masks = masks;
|
||||||
|
json.PrefixLength = +state.ruleForm.PrefixLength;
|
||||||
json.Gateway = state.ruleForm.Gateway;
|
json.Gateway = state.ruleForm.Gateway;
|
||||||
|
json.Upgrade = state.ruleForm.Upgrade;
|
||||||
|
json.Forwards = state.ruleForm.Forwards;
|
||||||
|
json.Forwards.forEach(c=>{
|
||||||
|
c.ListenPort=+c.ListenPort;
|
||||||
|
c.ConnectPort=+c.ConnectPort;
|
||||||
|
});
|
||||||
updateTuntap(json).then(() => {
|
updateTuntap(json).then(() => {
|
||||||
state.show = false;
|
state.show = false;
|
||||||
ElMessage.success('已操作!');
|
ElMessage.success('已操作!');
|
||||||
@@ -111,12 +159,32 @@ export default {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleDelForward = (index) => {
|
||||||
|
state.ruleForm.Forwards.splice(index, 1);
|
||||||
|
if (state.ruleForm.Forwards.length == 0) {
|
||||||
|
handleAddForward(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const handleAddForward = (index) => {
|
||||||
|
state.ruleForm.Forwards.splice(index + 1, 0, {ListenAddr:'0.0.0.0',ListenPort:0,ConnectAddr:'0.0.0.0',ConnectPort:0});
|
||||||
|
}
|
||||||
|
const handleForwardChange = ()=>{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
state, ruleFormRef,handleMaskChange, handleDel, handleAdd, handleSave
|
state, ruleFormRef,handlePrefixLengthChange,handleMaskChange, handleDel, handleAdd, handleSave,
|
||||||
|
handleForwardChange,handleDelForward,handleAddForward
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="stylus" scoped>
|
<style lang="stylus" scoped>
|
||||||
.el-switch.is-disabled{opacity :1;}
|
.el-switch.is-disabled{opacity :1;}
|
||||||
|
|
||||||
|
.upgrade-wrap{
|
||||||
|
border:1px solid #ddd;
|
||||||
|
margin-bottom:2rem
|
||||||
|
padding:1rem 0;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
@@ -1,4 +1,4 @@
|
|||||||
import { getSignInList, signInDel } from "@/apis/signin";
|
import { getSignInList, signInDel, setSignInIndex } from "@/apis/signin";
|
||||||
import { injectGlobalData } from "@/provide";
|
import { injectGlobalData } from "@/provide";
|
||||||
import { computed, reactive } from "vue";
|
import { computed, reactive } from "vue";
|
||||||
|
|
||||||
@@ -12,7 +12,7 @@ export const provideDevices = () => {
|
|||||||
timer: 0,
|
timer: 0,
|
||||||
page: {
|
page: {
|
||||||
Request: {
|
Request: {
|
||||||
Page: 1, Size: +(localStorage.getItem('ps') || '10'), Name: '', Ids: []
|
Page: 1, Size: +(localStorage.getItem('ps') || '10'), Name: '', Ids: [], Prop: '', Asc: true
|
||||||
},
|
},
|
||||||
Count: 0,
|
Count: 0,
|
||||||
List: []
|
List: []
|
||||||
@@ -23,7 +23,6 @@ export const provideDevices = () => {
|
|||||||
});
|
});
|
||||||
const _getSignList = () => {
|
const _getSignList = () => {
|
||||||
getSignInList(devices.page.Request).then((res) => {
|
getSignInList(devices.page.Request).then((res) => {
|
||||||
console.log(res);
|
|
||||||
devices.page.Request = res.Request;
|
devices.page.Request = res.Request;
|
||||||
devices.page.Count = res.Count;
|
devices.page.Count = res.Count;
|
||||||
for (let j in res.List) {
|
for (let j in res.List) {
|
||||||
@@ -33,7 +32,7 @@ export const provideDevices = () => {
|
|||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
devices.page.List = res.List.sort((a, b) => b.Connected - a.Connected);
|
devices.page.List = res.List;
|
||||||
for (let i = 0; i < devices.page.List.length; i++) {
|
for (let i = 0; i < devices.page.List.length; i++) {
|
||||||
queue.push(devices.page.List[i]);
|
queue.push(devices.page.List[i]);
|
||||||
}
|
}
|
||||||
@@ -112,7 +111,12 @@ export const provideDevices = () => {
|
|||||||
devices.timer = 0;
|
devices.timer = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const setSort = (ids) => {
|
||||||
|
return setSignInIndex(ids);
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
devices, machineId, _getSignList, _getSignList1, handleDeviceEdit, handlePageChange, handlePageSizeChange, handleDel, clearDevicesTimeout
|
devices, machineId, _getSignList, _getSignList1, handleDeviceEdit, handlePageChange, handlePageSizeChange, handleDel, clearDevicesTimeout,
|
||||||
|
setSort
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -40,8 +40,13 @@ export const provideTunnel = () => {
|
|||||||
const clearTunnelTimeout = () => {
|
const clearTunnelTimeout = () => {
|
||||||
clearTimeout(tunnel.value.timer);
|
clearTimeout(tunnel.value.timer);
|
||||||
}
|
}
|
||||||
|
const sortTunnel = (asc) => {
|
||||||
|
return Object.values(tunnel.value.list).sort((a, b) => {
|
||||||
|
return asc ? a.RouteLevel - b.RouteLevel : b.RouteLevel - a.RouteLevel;
|
||||||
|
}).map(c => c.MachineId);
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
tunnel, _getTunnelInfo, handleTunnelEdit, handleTunnelRefresh, clearTunnelTimeout
|
tunnel, _getTunnelInfo, handleTunnelEdit, handleTunnelRefresh, clearTunnelTimeout, sortTunnel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export const useTunnel = () => {
|
export const useTunnel = () => {
|
||||||
|
@@ -27,13 +27,14 @@ export const provideTuntap = () => {
|
|||||||
if (globalData.value.api.connected) {
|
if (globalData.value.api.connected) {
|
||||||
getTuntapInfo(tuntap.value.hashcode.toString()).then((res) => {
|
getTuntapInfo(tuntap.value.hashcode.toString()).then((res) => {
|
||||||
tuntap.value.hashcode = res.HashCode;
|
tuntap.value.hashcode = res.HashCode;
|
||||||
|
console.log(res);
|
||||||
if (res.List) {
|
if (res.List) {
|
||||||
for (let j in res.List) {
|
for (let j in res.List) {
|
||||||
res.List[j].running = res.List[j].Status == 2;
|
res.List[j].running = res.List[j].Status == 2;
|
||||||
res.List[j].loading = res.List[j].Status == 1;
|
res.List[j].loading = res.List[j].Status == 1;
|
||||||
res.List[j].system = 'system';
|
res.List[j].system = 'system';
|
||||||
|
|
||||||
const systemStr = res.List[j].System.toLowerCase();
|
const systemStr = res.List[j].SystemInfo.toLowerCase();
|
||||||
res.List[j].systemDocker = systemStr.indexOf('docker') >= 0;
|
res.List[j].systemDocker = systemStr.indexOf('docker') >= 0;
|
||||||
|
|
||||||
for (let jj in systems) {
|
for (let jj in systems) {
|
||||||
@@ -81,8 +82,22 @@ export const provideTuntap = () => {
|
|||||||
.filter(c => c.IP.indexOf(name) >= 0 || (c.LanIPs.filter(d => d.indexOf(name) >= 0).length > 0))
|
.filter(c => c.IP.indexOf(name) >= 0 || (c.LanIPs.filter(d => d.indexOf(name) >= 0).length > 0))
|
||||||
.map(c => c.MachineId);
|
.map(c => c.MachineId);
|
||||||
}
|
}
|
||||||
|
const sortTuntapIP = (asc) => {
|
||||||
|
return Object.values(tuntap.value.list).sort((a, b) => {
|
||||||
|
const arrA = a.IP.split('.').map(c => Number(c));
|
||||||
|
const arrB = b.IP.split('.').map(c => Number(c));
|
||||||
|
for (let i = 0; i < arrA.length; i++) {
|
||||||
|
if (arrA[i] != arrB[i]) {
|
||||||
|
return asc ? arrA[i] - arrB[i] : arrB[i] - arrA[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}).map(c => c.MachineId);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
tuntap, _getTuntapInfo, handleTuntapEdit, handleTuntapRefresh, clearTuntapTimeout, getTuntapMachines
|
tuntap, _getTuntapInfo, handleTuntapEdit, handleTuntapRefresh, clearTuntapTimeout, getTuntapMachines, sortTuntapIP
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -3,6 +3,8 @@ using Microsoft.Extensions.DependencyInjection;
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using linker.startup;
|
using linker.startup;
|
||||||
using linker.config;
|
using linker.config;
|
||||||
|
using System.ServiceProcess;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
namespace linker
|
namespace linker
|
||||||
{
|
{
|
||||||
@@ -10,8 +12,28 @@ namespace linker
|
|||||||
{
|
{
|
||||||
static async Task Main(string[] args)
|
static async Task Main(string[] args)
|
||||||
{
|
{
|
||||||
Run(args);
|
if (Environment.UserInteractive == false && OperatingSystem.IsWindows())
|
||||||
await Helper.Await().ConfigureAwait(false);
|
{
|
||||||
|
AppDomain.CurrentDomain.UnhandledException += (a, b) =>
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
string serviceDirectory = Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName);
|
||||||
|
Directory.SetCurrentDirectory(serviceDirectory);
|
||||||
|
|
||||||
|
ServiceBase[] ServicesToRun;
|
||||||
|
ServicesToRun = new ServiceBase[]
|
||||||
|
{
|
||||||
|
new Service()
|
||||||
|
};
|
||||||
|
ServiceBase.Run(ServicesToRun);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Run(args);
|
||||||
|
await Helper.Await().ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Run(string[] args)
|
public static void Run(string[] args)
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
namespace linker.service
|
namespace linker
|
||||||
{
|
{
|
||||||
partial class LinkerService
|
partial class Service
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 必需的设计器变量。
|
/// 必需的设计器变量。
|
24
linker/Service.cs
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
|
||||||
|
using System.ServiceProcess;
|
||||||
|
|
||||||
|
namespace linker
|
||||||
|
{
|
||||||
|
partial class Service : ServiceBase
|
||||||
|
{
|
||||||
|
public Service()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnStart(string[] args)
|
||||||
|
{
|
||||||
|
Program.Run(args);
|
||||||
|
// TODO: 在此处添加代码以启动服务。
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnStop()
|
||||||
|
{
|
||||||
|
// TODO: 在此处添加代码以执行停止服务所需的关闭操作。
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -25,8 +25,8 @@
|
|||||||
<PackageProjectUrl>https://github.com/snltty/linker</PackageProjectUrl>
|
<PackageProjectUrl>https://github.com/snltty/linker</PackageProjectUrl>
|
||||||
<RepositoryUrl>https://github.com/snltty/linker</RepositoryUrl>
|
<RepositoryUrl>https://github.com/snltty/linker</RepositoryUrl>
|
||||||
<PackageReleaseNotes>linker</PackageReleaseNotes>
|
<PackageReleaseNotes>linker</PackageReleaseNotes>
|
||||||
<AssemblyVersion>1.2.0.3</AssemblyVersion>
|
<AssemblyVersion>1.2.0.4</AssemblyVersion>
|
||||||
<FileVersion>1.2.0.3</FileVersion>
|
<FileVersion>1.2.0.4</FileVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
|
||||||
@@ -65,5 +65,6 @@
|
|||||||
<PackageReference Include="LiteDB" Version="5.0.17" />
|
<PackageReference Include="LiteDB" Version="5.0.17" />
|
||||||
<PackageReference Include="MemoryPack" Version="1.10.0" />
|
<PackageReference Include="MemoryPack" Version="1.10.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
|
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
|
||||||
|
<PackageReference Include="System.ServiceProcess.ServiceController" Version="8.0.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
@@ -7,4 +7,9 @@
|
|||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||||
<DebuggerFlavor>ProjectDebugger</DebuggerFlavor>
|
<DebuggerFlavor>ProjectDebugger</DebuggerFlavor>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Update="Service.cs">
|
||||||
|
<SubType>Component</SubType>
|
||||||
|
</Compile>
|
||||||
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
@@ -70,6 +70,15 @@ namespace linker.plugins.signin
|
|||||||
Payload = MemoryPackSerializer.Serialize(param.Content)
|
Payload = MemoryPackSerializer.Serialize(param.Content)
|
||||||
}).ConfigureAwait(false);
|
}).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
public async Task SetIndex(ApiControllerParamsInfo param)
|
||||||
|
{
|
||||||
|
await messengerSender.SendOnly(new MessageRequestWrap
|
||||||
|
{
|
||||||
|
Connection = clientSignInState.Connection,
|
||||||
|
MessengerId = (ushort)SignInMessengerIds.SetIndex,
|
||||||
|
Payload = MemoryPackSerializer.Serialize(param.Content.DeJson<string[]>())
|
||||||
|
}).ConfigureAwait(false);
|
||||||
|
}
|
||||||
public async Task<SignInListResponseInfo> List(ApiControllerParamsInfo param)
|
public async Task<SignInListResponseInfo> List(ApiControllerParamsInfo param)
|
||||||
{
|
{
|
||||||
SignInListRequestInfo request = param.Content.DeJson<SignInListRequestInfo>();
|
SignInListRequestInfo request = param.Content.DeJson<SignInListRequestInfo>();
|
||||||
|
@@ -94,7 +94,6 @@ namespace linker.plugins.signin.messenger
|
|||||||
public DateTime LastSignIn { get; set; } = DateTime.Now;
|
public DateTime LastSignIn { get; set; } = DateTime.Now;
|
||||||
public Dictionary<string, string> Args { get; set; } = new Dictionary<string, string>();
|
public Dictionary<string, string> Args { get; set; } = new Dictionary<string, string>();
|
||||||
|
|
||||||
|
|
||||||
private IPEndPoint ip = new IPEndPoint(IPAddress.Any, 0);
|
private IPEndPoint ip = new IPEndPoint(IPAddress.Any, 0);
|
||||||
[MemoryPackAllowSerialize]
|
[MemoryPackAllowSerialize]
|
||||||
public IPEndPoint IP
|
public IPEndPoint IP
|
||||||
@@ -132,6 +131,9 @@ namespace linker.plugins.signin.messenger
|
|||||||
|
|
||||||
[MemoryPackIgnore, JsonIgnore, BsonIgnore]
|
[MemoryPackIgnore, JsonIgnore, BsonIgnore]
|
||||||
public IConnection Connection { get; set; }
|
public IConnection Connection { get; set; }
|
||||||
|
|
||||||
|
[MemoryPackIgnore, JsonIgnore, BsonIgnore]
|
||||||
|
public uint Index { get; set; } = 65535;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -44,6 +44,27 @@ namespace linker.plugins.signin.messenger
|
|||||||
connection.Write(MemoryPackSerializer.Serialize(info.MachineId));
|
connection.Write(MemoryPackSerializer.Serialize(info.MachineId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MessengerId((ushort)SignInMessengerIds.SetIndex)]
|
||||||
|
public void SetIndex(IConnection connection)
|
||||||
|
{
|
||||||
|
string[] ids = MemoryPackSerializer.Deserialize<string[]>(connection.ReceiveRequestWrap.Payload.Span);
|
||||||
|
if (signCaching.TryGet(connection.Id, out SignCacheInfo cache))
|
||||||
|
{
|
||||||
|
IEnumerable<SignCacheInfo> list = signCaching.Get(cache.GroupId);
|
||||||
|
foreach (var item in list)
|
||||||
|
{
|
||||||
|
item.Index = uint.MaxValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint i = 0; i < ids.Length; i++)
|
||||||
|
{
|
||||||
|
SignCacheInfo item = list.FirstOrDefault(c => c.MachineId == ids[i]);
|
||||||
|
if (item != null)
|
||||||
|
item.Index = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
[MessengerId((ushort)SignInMessengerIds.List)]
|
[MessengerId((ushort)SignInMessengerIds.List)]
|
||||||
public void List(IConnection connection)
|
public void List(IConnection connection)
|
||||||
@@ -51,15 +72,51 @@ namespace linker.plugins.signin.messenger
|
|||||||
SignInListRequestInfo request = MemoryPackSerializer.Deserialize<SignInListRequestInfo>(connection.ReceiveRequestWrap.Payload.Span);
|
SignInListRequestInfo request = MemoryPackSerializer.Deserialize<SignInListRequestInfo>(connection.ReceiveRequestWrap.Payload.Span);
|
||||||
if (signCaching.TryGet(connection.Id, out SignCacheInfo cache))
|
if (signCaching.TryGet(connection.Id, out SignCacheInfo cache))
|
||||||
{
|
{
|
||||||
IEnumerable<SignCacheInfo> list = signCaching.Get(cache.GroupId).OrderByDescending(c => c.MachineName).OrderByDescending(c => c.LastSignIn).OrderByDescending(c => c.Version).ToList();
|
IEnumerable<SignCacheInfo> list = signCaching.Get(cache.GroupId).Where(c => c.MachineId != cache.MachineId);
|
||||||
if (string.IsNullOrWhiteSpace(request.Name) == false)
|
if (string.IsNullOrWhiteSpace(request.Name) == false)
|
||||||
{
|
{
|
||||||
list = list.Where(c => c.Version.Contains(request.Name) || c.IP.ToString().Contains(request.Name) || c.MachineName.Contains(request.Name) || request.Ids.Contains(c.MachineId));
|
list = list.Where(c => c.Version.Contains(request.Name) || c.IP.ToString().Contains(request.Name) || c.MachineName.Contains(request.Name) || request.Ids.Contains(c.MachineId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(request.Prop) == false)
|
||||||
|
{
|
||||||
|
if (request.Asc)
|
||||||
|
{
|
||||||
|
switch (request.Prop)
|
||||||
|
{
|
||||||
|
case "MachineId":
|
||||||
|
list = list.OrderBy(c => c.MachineName);
|
||||||
|
break;
|
||||||
|
case "Version":
|
||||||
|
list = list.OrderBy(c => c.Version);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
list = list.OrderBy(c => c.Index);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch (request.Prop)
|
||||||
|
{
|
||||||
|
case "MachineId":
|
||||||
|
list = list.OrderByDescending(c => c.MachineName);
|
||||||
|
break;
|
||||||
|
case "Version":
|
||||||
|
list = list.OrderByDescending(c => c.Version);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
list = list.OrderByDescending(c => c.Index);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int count = list.Count();
|
int count = list.Count();
|
||||||
list = list.Skip((request.Page - 1) * request.Size).Take(request.Size);
|
list = list.Skip((request.Page - 1) * request.Size).Take(request.Size);
|
||||||
|
|
||||||
SignInListResponseInfo response = new SignInListResponseInfo { Request = request, Count = count, List = list.ToList() };
|
List<SignCacheInfo> result = [cache, .. list];
|
||||||
|
SignInListResponseInfo response = new SignInListResponseInfo { Request = request, Count = count, List = result };
|
||||||
|
|
||||||
connection.Write(MemoryPackSerializer.Serialize(response));
|
connection.Write(MemoryPackSerializer.Serialize(response));
|
||||||
}
|
}
|
||||||
@@ -148,10 +205,6 @@ namespace linker.plugins.signin.messenger
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public int Size { get; set; } = 10;
|
public int Size { get; set; } = 10;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 所在分组
|
|
||||||
/// </summary>
|
|
||||||
public string GroupId { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
/// 按名称搜索
|
/// 按名称搜索
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
@@ -159,6 +212,15 @@ namespace linker.plugins.signin.messenger
|
|||||||
/// 按id获取
|
/// 按id获取
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string[] Ids { get; set; }
|
public string[] Ids { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 排序
|
||||||
|
/// </summary>
|
||||||
|
public bool Asc { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 排序字段
|
||||||
|
/// </summary>
|
||||||
|
public string Prop { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[MemoryPackable]
|
[MemoryPackable]
|
||||||
|
@@ -14,6 +14,8 @@
|
|||||||
Ids = 8,
|
Ids = 8,
|
||||||
Exists = 9,
|
Exists = 9,
|
||||||
|
|
||||||
|
SetIndex = 10,
|
||||||
|
|
||||||
None = 99
|
None = 99
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -177,10 +177,19 @@ namespace linker.plugins.tunnel
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
try
|
||||||
if (File.Exists("msquic.dll.temp"))
|
{
|
||||||
|
if (File.Exists("msquic.dll.temp"))
|
||||||
|
{
|
||||||
|
File.Delete("msquic.dll.temp");
|
||||||
|
}
|
||||||
|
if (File.Exists("msquic-openssl.dll"))
|
||||||
|
{
|
||||||
|
File.Delete("msquic-openssl.dll");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
{
|
{
|
||||||
File.Delete("msquic.dll.temp");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -63,7 +63,7 @@ namespace linker.plugins.tunnel
|
|||||||
serviceCollection.AddSingleton<ITunnelAdapter, TunnelAdapter>();
|
serviceCollection.AddSingleton<ITunnelAdapter, TunnelAdapter>();
|
||||||
|
|
||||||
LoggerHelper.Instance.Info($"tunnel route level getting.");
|
LoggerHelper.Instance.Info($"tunnel route level getting.");
|
||||||
config.Data.Client.Tunnel.RouteLevel = NetworkHelper.GetRouteLevel(out List<IPAddress> ips);
|
config.Data.Client.Tunnel.RouteLevel = NetworkHelper.GetRouteLevel(config.Data.Client.Server, out List<IPAddress> ips);
|
||||||
config.Data.Client.Tunnel.RouteIPs = ips.ToArray();
|
config.Data.Client.Tunnel.RouteIPs = ips.ToArray();
|
||||||
LoggerHelper.Instance.Warning($"route ips:{string.Join(",", ips.Select(c => c.ToString()))}");
|
LoggerHelper.Instance.Warning($"route ips:{string.Join(",", ips.Select(c => c.ToString()))}");
|
||||||
config.Data.Client.Tunnel.LocalIPs = NetworkHelper.GetIPV6().Concat(NetworkHelper.GetIPV4()).ToArray();
|
config.Data.Client.Tunnel.LocalIPs = NetworkHelper.GetIPV6().Concat(NetworkHelper.GetIPV4()).ToArray();
|
||||||
|
@@ -15,6 +15,7 @@ namespace linker.plugins.tuntap
|
|||||||
//网卡IP,和局域网IP。不参与打洞
|
//网卡IP,和局域网IP。不参与打洞
|
||||||
return new ExcludeIPItem[] { new ExcludeIPItem { IPAddress = runningConfig.Data.Tuntap.IP, Mask = 32 } }
|
return new ExcludeIPItem[] { new ExcludeIPItem { IPAddress = runningConfig.Data.Tuntap.IP, Mask = 32 } }
|
||||||
.Concat(runningConfig.Data.Tuntap.LanIPs.Select((c, index) => new ExcludeIPItem { IPAddress = c, Mask = (byte)runningConfig.Data.Tuntap.Masks[index] }))
|
.Concat(runningConfig.Data.Tuntap.LanIPs.Select((c, index) => new ExcludeIPItem { IPAddress = c, Mask = (byte)runningConfig.Data.Tuntap.Masks[index] }))
|
||||||
|
.Where(c=>c.IPAddress != null)
|
||||||
.ToArray();
|
.ToArray();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -117,7 +117,11 @@ namespace linker.plugins.tuntap
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//更新网卡信息
|
/// <summary>
|
||||||
|
/// 更新网卡信息
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="param"></param>
|
||||||
|
/// <returns></returns>
|
||||||
public async Task<bool> Update(ApiControllerParamsInfo param)
|
public async Task<bool> Update(ApiControllerParamsInfo param)
|
||||||
{
|
{
|
||||||
TuntapInfo info = param.Content.DeJson<TuntapInfo>();
|
TuntapInfo info = param.Content.DeJson<TuntapInfo>();
|
||||||
|
@@ -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.libs.extends;
|
||||||
|
|
||||||
namespace linker.plugins.tuntap
|
namespace linker.plugins.tuntap
|
||||||
{
|
{
|
||||||
@@ -56,7 +57,7 @@ namespace linker.plugins.tuntap
|
|||||||
{
|
{
|
||||||
Task.Run(() =>
|
Task.Run(() =>
|
||||||
{
|
{
|
||||||
NetworkHelper.GetRouteLevel(out routeIps);
|
NetworkHelper.GetRouteLevel(config.Data.Client.Server, out routeIps);
|
||||||
NotifyConfig();
|
NotifyConfig();
|
||||||
CheckTuntapStatusTask();
|
CheckTuntapStatusTask();
|
||||||
if (runningConfig.Data.Tuntap.Running)
|
if (runningConfig.Data.Tuntap.Running)
|
||||||
@@ -77,19 +78,17 @@ namespace linker.plugins.tuntap
|
|||||||
}
|
}
|
||||||
Task.Run(() =>
|
Task.Run(() =>
|
||||||
{
|
{
|
||||||
NotifyConfig();
|
SetupBefore();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (runningConfig.Data.Tuntap.IP.Equals(IPAddress.Any))
|
if (runningConfig.Data.Tuntap.IP.Equals(IPAddress.Any))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
linkerTunDeviceAdapter.Setup(runningConfig.Data.Tuntap.IP, 24, 1416);
|
linkerTunDeviceAdapter.Setup(runningConfig.Data.Tuntap.IP, runningConfig.Data.Tuntap.PrefixLength, 1416);
|
||||||
if (string.IsNullOrWhiteSpace(linkerTunDeviceAdapter.Error))
|
if (string.IsNullOrWhiteSpace(linkerTunDeviceAdapter.Error))
|
||||||
{
|
{
|
||||||
linkerTunDeviceAdapter.SetNat();
|
SetupSuccess();
|
||||||
runningConfig.Data.Tuntap.Running = true;
|
|
||||||
runningConfig.Data.Update();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -102,11 +101,28 @@ namespace linker.plugins.tuntap
|
|||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
Interlocked.Exchange(ref operating, 0);
|
SetupAfter();
|
||||||
NotifyConfig();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void SetupBefore()
|
||||||
|
{
|
||||||
|
NotifyConfig();
|
||||||
|
}
|
||||||
|
private void SetupAfter()
|
||||||
|
{
|
||||||
|
Interlocked.Exchange(ref operating, 0);
|
||||||
|
NotifyConfig();
|
||||||
|
}
|
||||||
|
private void SetupSuccess()
|
||||||
|
{
|
||||||
|
linkerTunDeviceAdapter.SetNat();
|
||||||
|
AddForward();
|
||||||
|
runningConfig.Data.Tuntap.Running = true;
|
||||||
|
runningConfig.Data.Update();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 停止网卡
|
/// 停止网卡
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -118,11 +134,9 @@ namespace linker.plugins.tuntap
|
|||||||
}
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
NotifyConfig();
|
ShutdownBefore();
|
||||||
linkerTunDeviceAdapter.Shutdown();
|
linkerTunDeviceAdapter.Shutdown();
|
||||||
|
ShutdownSuccess();
|
||||||
runningConfig.Data.Tuntap.Running = false;
|
|
||||||
runningConfig.Data.Update();
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -133,10 +147,27 @@ namespace linker.plugins.tuntap
|
|||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
Interlocked.Exchange(ref operating, 0);
|
ShutdownAfter();
|
||||||
NotifyConfig();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
private void ShutdownBefore()
|
||||||
|
{
|
||||||
|
NotifyConfig();
|
||||||
|
}
|
||||||
|
private void ShutdownAfter()
|
||||||
|
{
|
||||||
|
Interlocked.Exchange(ref operating, 0);
|
||||||
|
NotifyConfig();
|
||||||
|
}
|
||||||
|
private void ShutdownSuccess()
|
||||||
|
{
|
||||||
|
linkerTunDeviceAdapter.RemoveNat();
|
||||||
|
DeleteForward();
|
||||||
|
runningConfig.Data.Tuntap.Running = false;
|
||||||
|
runningConfig.Data.Update();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 刷新信息,把自己的网卡配置发给别人,顺便把别人的网卡信息带回来
|
/// 刷新信息,把自己的网卡配置发给别人,顺便把别人的网卡信息带回来
|
||||||
@@ -153,10 +184,14 @@ namespace linker.plugins.tuntap
|
|||||||
{
|
{
|
||||||
Task.Run(() =>
|
Task.Run(() =>
|
||||||
{
|
{
|
||||||
|
DeleteForward();
|
||||||
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.Masks = info.Masks;
|
runningConfig.Data.Tuntap.Masks = info.Masks;
|
||||||
|
runningConfig.Data.Tuntap.PrefixLength = info.PrefixLength;
|
||||||
runningConfig.Data.Tuntap.Gateway = info.Gateway;
|
runningConfig.Data.Tuntap.Gateway = info.Gateway;
|
||||||
|
runningConfig.Data.Tuntap.Upgrade = info.Upgrade;
|
||||||
|
runningConfig.Data.Tuntap.Forwards = info.Forwards;
|
||||||
runningConfig.Data.Update();
|
runningConfig.Data.Update();
|
||||||
if (Status == TuntapStatus.Running)
|
if (Status == TuntapStatus.Running)
|
||||||
{
|
{
|
||||||
@@ -165,6 +200,7 @@ namespace linker.plugins.tuntap
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
AddForward();
|
||||||
NotifyConfig();
|
NotifyConfig();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -204,9 +240,9 @@ namespace linker.plugins.tuntap
|
|||||||
{
|
{
|
||||||
tuntapInfos.AddOrUpdate(item.MachineId, item, (a, b) => item);
|
tuntapInfos.AddOrUpdate(item.MachineId, item, (a, b) => item);
|
||||||
}
|
}
|
||||||
Interlocked.Increment(ref infosVersion);
|
|
||||||
AddRoute();
|
AddRoute();
|
||||||
}
|
}
|
||||||
|
Interlocked.Increment(ref infosVersion);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -220,11 +256,15 @@ namespace linker.plugins.tuntap
|
|||||||
IP = runningConfig.Data.Tuntap.IP,
|
IP = runningConfig.Data.Tuntap.IP,
|
||||||
LanIPs = runningConfig.Data.Tuntap.LanIPs,
|
LanIPs = runningConfig.Data.Tuntap.LanIPs,
|
||||||
Masks = runningConfig.Data.Tuntap.Masks,
|
Masks = runningConfig.Data.Tuntap.Masks,
|
||||||
|
PrefixLength = runningConfig.Data.Tuntap.PrefixLength,
|
||||||
MachineId = config.Data.Client.Id,
|
MachineId = config.Data.Client.Id,
|
||||||
Status = Status,
|
Status = Status,
|
||||||
Error = linkerTunDeviceAdapter.Error,
|
Error = linkerTunDeviceAdapter.Error,
|
||||||
System = $"{System.Runtime.InteropServices.RuntimeInformation.OSDescription} {(string.IsNullOrWhiteSpace(Environment.GetEnvironmentVariable("SNLTTY_LINKER_IS_DOCKER")) == false ? "Docker" : "")}",
|
Error1 = linkerTunDeviceAdapter.Error1,
|
||||||
|
SystemInfo = $"{System.Runtime.InteropServices.RuntimeInformation.OSDescription} {(string.IsNullOrWhiteSpace(Environment.GetEnvironmentVariable("SNLTTY_LINKER_IS_DOCKER")) == false ? "Docker" : "")}",
|
||||||
Gateway = runningConfig.Data.Tuntap.Gateway,
|
Gateway = runningConfig.Data.Tuntap.Gateway,
|
||||||
|
Upgrade = runningConfig.Data.Tuntap.Upgrade,
|
||||||
|
Forwards = runningConfig.Data.Tuntap.Forwards,
|
||||||
};
|
};
|
||||||
if (runningConfig.Data.Tuntap.Masks.Length != runningConfig.Data.Tuntap.LanIPs.Length)
|
if (runningConfig.Data.Tuntap.Masks.Length != runningConfig.Data.Tuntap.LanIPs.Length)
|
||||||
{
|
{
|
||||||
@@ -258,16 +298,38 @@ namespace linker.plugins.tuntap
|
|||||||
return infos;
|
return infos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// <summary>
|
||||||
|
/// 添加端口转发
|
||||||
|
/// </summary>
|
||||||
|
private void AddForward()
|
||||||
|
{
|
||||||
|
linkerTunDeviceAdapter.AddForward(runningConfig.Data.Tuntap.Forwards.Select(c => new LinkerTunDeviceForwardItem { ListenAddr = c.ListenAddr, ListenPort = c.ListenPort, ConnectAddr = c.ConnectAddr, ConnectPort = c.ConnectPort }).ToList());
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 删除端口转发
|
||||||
|
/// </summary>
|
||||||
|
private void DeleteForward()
|
||||||
|
{
|
||||||
|
linkerTunDeviceAdapter.RemoveForward(runningConfig.Data.Tuntap.Forwards.Select(c => new LinkerTunDeviceForwardItem { ListenAddr = c.ListenAddr, ListenPort = c.ListenPort, ConnectAddr = c.ConnectAddr, ConnectPort = c.ConnectPort }).ToList());
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 删除路由
|
/// 删除路由
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void DelRoute()
|
private void DelRoute()
|
||||||
{
|
{
|
||||||
List<TuntapVeaLanIPAddressList> ipsList = ParseIPs(tuntapInfos.Values.ToList());
|
try
|
||||||
TuntapVeaLanIPAddress[] ips = ipsList.SelectMany(c => c.IPS).ToArray();
|
{
|
||||||
|
List<TuntapVeaLanIPAddressList> ipsList = ParseIPs(tuntapInfos.Values.ToList());
|
||||||
var items = ipsList.SelectMany(c => c.IPS).Select(c => new LinkerTunDeviceRouteItem { Address = c.OriginIPAddress, PrefixLength = c.MaskLength }).ToArray();
|
TuntapVeaLanIPAddress[] ips = ipsList.SelectMany(c => c.IPS).ToArray();
|
||||||
linkerTunDeviceAdapter.DelRoute(items, runningConfig.Data.Tuntap.Gateway);
|
var items = ipsList.SelectMany(c => c.IPS).Select(c => new LinkerTunDeviceRouteItem { Address = c.OriginIPAddress, PrefixLength = c.MaskLength }).ToArray();
|
||||||
|
linkerTunDeviceAdapter.DelRoute(items, runningConfig.Data.Tuntap.Gateway);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine(ex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 添加路由
|
/// 添加路由
|
||||||
@@ -291,7 +353,7 @@ namespace linker.plugins.tuntap
|
|||||||
{
|
{
|
||||||
uint[] localIps = NetworkHelper.GetIPV4()
|
uint[] localIps = NetworkHelper.GetIPV4()
|
||||||
.Concat(new IPAddress[] { runningConfig.Data.Tuntap.IP })
|
.Concat(new IPAddress[] { runningConfig.Data.Tuntap.IP })
|
||||||
.Concat(runningConfig.Data.Tuntap.LanIPs)
|
.Concat(runningConfig.Data.Tuntap.LanIPs.Where(c => c != null))
|
||||||
.Concat(routeIps)
|
.Concat(routeIps)
|
||||||
.Select(c => BinaryPrimitives.ReadUInt32BigEndian(c.GetAddressBytes()))
|
.Select(c => BinaryPrimitives.ReadUInt32BigEndian(c.GetAddressBytes()))
|
||||||
.ToArray();
|
.ToArray();
|
||||||
@@ -313,7 +375,7 @@ namespace linker.plugins.tuntap
|
|||||||
private List<TuntapVeaLanIPAddress> ParseIPs(IPAddress[] lanIPs, int[] masks)
|
private List<TuntapVeaLanIPAddress> ParseIPs(IPAddress[] lanIPs, int[] masks)
|
||||||
{
|
{
|
||||||
if (masks.Length != lanIPs.Length) masks = lanIPs.Select(c => 24).ToArray();
|
if (masks.Length != lanIPs.Length) masks = lanIPs.Select(c => 24).ToArray();
|
||||||
return lanIPs.Where(c => c.Equals(IPAddress.Any) == false).Select((c, index) =>
|
return lanIPs.Where(c => c.Equals(IPAddress.Any) == false && c != null).Select((c, index) =>
|
||||||
{
|
{
|
||||||
return ParseIPAddress(c, (byte)masks[index]);
|
return ParseIPAddress(c, (byte)masks[index]);
|
||||||
|
|
||||||
|
@@ -1,25 +1,15 @@
|
|||||||
using linker.plugins.tuntap.config;
|
using linker.plugins.tuntap.config;
|
||||||
using MemoryPack;
|
using MemoryPack;
|
||||||
using System.Buffers.Binary;
|
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
|
||||||
namespace linker.plugins.tuntap.config
|
namespace linker.plugins.tuntap.config
|
||||||
{
|
{
|
||||||
public sealed class TuntapConfigInfo
|
public sealed class TuntapConfigInfo
|
||||||
{
|
{
|
||||||
private IPAddress ip = IPAddress.Any;
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 网卡IP
|
/// 网卡IP
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IPAddress IP
|
public IPAddress IP { get; set; } = IPAddress.Any;
|
||||||
{
|
|
||||||
get => ip; set
|
|
||||||
{
|
|
||||||
ip = value;
|
|
||||||
IpInt = BinaryPrimitives.ReadUInt32BigEndian(ip.GetAddressBytes());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public uint IpInt { get; private set; }
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 局域网IP列表
|
/// 局域网IP列表
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -28,12 +18,28 @@ namespace linker.plugins.tuntap.config
|
|||||||
/// 局域网掩码列表,与IP列表一一对应
|
/// 局域网掩码列表,与IP列表一一对应
|
||||||
/// </summary>
|
/// </summary>
|
||||||
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>
|
||||||
public bool Running { get; set; }
|
public bool Running { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 是否网关
|
||||||
|
/// </summary>
|
||||||
public bool Gateway { get; set; }
|
public bool Gateway { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 使用高级功能
|
||||||
|
/// </summary>
|
||||||
|
public bool Upgrade { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 端口转发列表
|
||||||
|
/// </summary>
|
||||||
|
public List<TuntapForwardInfo> Forwards { get; set; } = new List<TuntapForwardInfo>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -65,31 +71,93 @@ namespace linker.plugins.tuntap.config
|
|||||||
|
|
||||||
public enum TuntapStatus : byte
|
public enum TuntapStatus : byte
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 无
|
||||||
|
/// </summary>
|
||||||
Normal = 0,
|
Normal = 0,
|
||||||
|
/// <summary>
|
||||||
|
/// 操作中
|
||||||
|
/// </summary>
|
||||||
Operating = 1,
|
Operating = 1,
|
||||||
|
/// <summary>
|
||||||
|
/// 运行中
|
||||||
|
/// </summary>
|
||||||
Running = 2
|
Running = 2
|
||||||
}
|
}
|
||||||
|
|
||||||
[MemoryPackable]
|
[MemoryPackable]
|
||||||
public sealed partial class TuntapInfo
|
public sealed partial class TuntapInfo
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 设备id
|
||||||
|
/// </summary>
|
||||||
public string MachineId { get; set; }
|
public string MachineId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 虚拟网卡状态
|
||||||
|
/// </summary>
|
||||||
public TuntapStatus Status { get; set; }
|
public TuntapStatus Status { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 虚拟网卡IP
|
||||||
|
/// </summary>
|
||||||
|
|
||||||
[MemoryPackAllowSerialize]
|
[MemoryPackAllowSerialize]
|
||||||
public IPAddress IP { get; set; }
|
public IPAddress IP { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 局域网IP
|
||||||
|
/// </summary>
|
||||||
|
|
||||||
[MemoryPackAllowSerialize]
|
[MemoryPackAllowSerialize]
|
||||||
public IPAddress[] LanIPs { get; set; } = Array.Empty<IPAddress>();
|
public IPAddress[] LanIPs { get; set; } = Array.Empty<IPAddress>();
|
||||||
|
/// <summary>
|
||||||
|
/// 局域网IP掩码
|
||||||
|
/// </summary>
|
||||||
public int[] Masks { get; set; } = Array.Empty<int>();
|
public int[] Masks { get; set; } = Array.Empty<int>();
|
||||||
|
|
||||||
public string Error { get; set; }
|
|
||||||
public string System { get; set; }
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 前缀长度
|
||||||
|
/// </summary>
|
||||||
|
public byte PrefixLength { get; set; } = 24;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 网卡安装错误
|
||||||
|
/// </summary>
|
||||||
|
public string Error { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// NAT设置错误
|
||||||
|
/// </summary>
|
||||||
|
public string Error1 { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 系统信息
|
||||||
|
/// </summary>
|
||||||
|
public string SystemInfo { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 是否网关
|
||||||
|
/// </summary>
|
||||||
public bool Gateway { get; set; }
|
public bool Gateway { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 使用高级功能
|
||||||
|
/// </summary>
|
||||||
|
public bool Upgrade { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 端口转发列表
|
||||||
|
/// </summary>
|
||||||
|
public List<TuntapForwardInfo> Forwards { get; set; } = new List<TuntapForwardInfo>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[MemoryPackable]
|
||||||
|
public sealed partial class TuntapForwardInfo
|
||||||
|
{
|
||||||
|
[MemoryPackAllowSerialize]
|
||||||
|
public IPAddress ListenAddr { get; set; } = IPAddress.Any;
|
||||||
|
public int ListenPort { get; set; }
|
||||||
|
|
||||||
|
[MemoryPackAllowSerialize]
|
||||||
|
public IPAddress ConnectAddr { get; set; } = IPAddress.Any;
|
||||||
|
public int ConnectPort { get; set; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -156,6 +156,8 @@ namespace linker.plugins.tuntap.messenger
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Task.WhenAll(tasks).ContinueWith(async (result) =>
|
Task.WhenAll(tasks).ContinueWith(async (result) =>
|
||||||
{
|
{
|
||||||
List<TuntapInfo> results = tasks.Where(c => c.Result.Code == MessageResponeCodes.OK)
|
List<TuntapInfo> results = tasks.Where(c => c.Result.Code == MessageResponeCodes.OK)
|
||||||
|
@@ -12,12 +12,11 @@ call npm run build
|
|||||||
cd ../
|
cd ../
|
||||||
|
|
||||||
for %%r in (win-x64,win-arm64) do (
|
for %%r in (win-x64,win-arm64) do (
|
||||||
dotnet publish ./linker.service -c release -f net8.0 -o public/extends/%%r/linker-%%r/ -r %%r -p:PublishAot=true -p:PublishTrimmed=true --self-contained true -p:TieredPGO=true -p:DebugType=none -p:DebugSymbols=false -p:EnableCompressionInSingleFile=true -p:DebuggerSupport=false -p:EnableUnsafeBinaryFormatterSerialization=false -p:EnableUnsafeUTF7Encoding=false -p:HttpActivityPropagationSupport=false -p:InvariantGlobalization=true -p:MetadataUpdaterSupport=false -p:UseSystemResourceKeys=true
|
|
||||||
echo F|xcopy "linker.tray.win\\dist\\*" "public\\extends\\%%r\\linker-%%r\\*" /s /f /h /y
|
echo F|xcopy "linker.tray.win\\dist\\*" "public\\extends\\%%r\\linker-%%r\\*" /s /f /h /y
|
||||||
echo F|xcopy "linker\\msquic.dll" "public\\extends\\%%r\\linker-%%r\\msquic.dll" /s /f /h /y
|
echo F|xcopy "linker\\msquic.dll" "public\\extends\\%%r\\linker-%%r\\msquic.dll" /s /f /h /y
|
||||||
echo F|xcopy "linker\\msquic-%%r.dll" "public\\extends\\%%r\\linker-%%r\\msquic.dll" /s /f /h /y
|
echo F|xcopy "linker\\msquic-%%r.dll" "public\\extends\\%%r\\linker-%%r\\msquic.dll" /s /f /h /y
|
||||||
echo F|xcopy "linker\\msquic-openssl3-%%r.dll" "public\\extends\\%%r\\linker-%%r\\msquic-openssl.dll" /s /f /h /y
|
echo F|xcopy "linker\\msquic-openssl3-%%r.dll" "public\\extends\\%%r\\linker-%%r\\msquic-openssl.dll" /s /f /h /y
|
||||||
echo F|xcopy "linker\\wintun-%%r.dll" "public\\extends\\%%r\\linker-%%r\\wintun.dll" /s /f /h /y
|
echo F|xcopy "linker\\wintun-%%r.dll" "public\\extends\\%%r\\linker-%%r\\wintun.dll" /s /f /h /y
|
||||||
)
|
)
|
||||||
|
|
||||||
for %%r in (win-x64,win-arm64,linux-x64,linux-arm64,linux-musl-x64,linux-musl-arm64,osx-x64,osx-arm64) do (
|
for %%r in (win-x64,win-arm64,linux-x64,linux-arm64,linux-musl-x64,linux-musl-arm64,osx-x64,osx-arm64) do (
|
||||||
|