mirror of
https://github.com/snltty/linker.git
synced 2025-09-27 13:32:14 +08:00
183
This commit is contained in:
2
.github/workflows/dotnet.yml
vendored
2
.github/workflows/dotnet.yml
vendored
@@ -37,7 +37,7 @@ jobs:
|
||||
release_name: v1.8.3.${{ steps.date.outputs.today }}
|
||||
draft: false
|
||||
prerelease: false
|
||||
body: "1. 一些累计更新\r\n2. 修复socks5,解决CPU爆满问题,增加域名解析和HTTP代理\r\n3. 优化唤醒模块\r\n5. 管理端口改为1804,一个端口托管Web+Websocket"
|
||||
body: "1. 一些累计更新\r\n2. 修复socks5,解决CPU爆满问题,增加本地域名解析,支持HTTP代理\r\n3. 优化唤醒模块\r\n4. 优化应用NAT,根据目标IP自动选择网卡\r\n5. 分离cdkey,使其可作用于任意模块"
|
||||
- name: publish projects
|
||||
run: ./publish.bat "C:\\Android\\android-sdk"
|
||||
- name: upload-win-x86-oss
|
||||
|
1
src/linker.app/public/web/css/118.be8a94f0.css
Normal file
1
src/linker.app/public/web/css/118.be8a94f0.css
Normal file
@@ -0,0 +1 @@
|
||||
.el-radio-group[data-v-3927a588]{margin-right:.6rem}.wrap[data-v-3927a588]{padding-bottom:1rem}.el-form-item[data-v-8eed28d4]{margin-bottom:1rem}.el-input-number--small[data-v-8eed28d4]{width:10rem!important}.el-form-item[data-v-3afdc5d4]{margin-bottom:1rem}.el-input-number--small[data-v-3afdc5d4]{width:10rem!important}.head .search>div[data-v-33dd67e0]{margin-right:1rem}.page[data-v-33dd67e0]{padding:2rem 0;display:inline-block}.el-form-item[data-v-33dd67e0]{margin-bottom:1rem}.el-input-number--small[data-v-33dd67e0]{width:10rem!important}.head .search>div[data-v-d3ca7ebe]{margin-right:1rem}.page[data-v-d3ca7ebe]{padding:2rem 0;display:inline-block}.el-form-item[data-v-d3ca7ebe]{margin-bottom:1rem}.el-input-number--small[data-v-d3ca7ebe]{width:10rem!important}.el-form-item[data-v-c2557c92]{margin-bottom:1rem}.el-input-number--small[data-v-c2557c92]{width:10rem!important}.blue[data-v-62bbb114]{color:#409eff}a.a-edit[data-v-62bbb114]{margin-left:1rem}a.a-edit .el-icon[data-v-62bbb114]{vertical-align:middle}.servers-wrap[data-v-60d7955e]{padding:1rem;font-size:1.3rem;color:#555}.servers-wrap a[data-v-60d7955e]{color:#333}
|
@@ -1 +1 @@
|
||||
<!doctype html><html lang=""><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" href="favicon.ico"><title>linker.web</title><link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY=" crossorigin=""/><script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js" integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo=" crossorigin=""></script><script defer="defer" src="js/chunk-vendors.81af7d4e.js"></script><script defer="defer" src="js/app.360c2592.js"></script><link href="css/chunk-vendors.d8267b33.css" rel="stylesheet"><link href="css/app.f83ea0ab.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but linker.web doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div></body></html>
|
||||
<!doctype html><html lang=""><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" href="favicon.ico"><title>linker.web</title><link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY=" crossorigin=""/><script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js" integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo=" crossorigin=""></script><script defer="defer" src="js/chunk-vendors.81af7d4e.js"></script><script defer="defer" src="js/app.665d3555.js"></script><link href="css/chunk-vendors.d8267b33.css" rel="stylesheet"><link href="css/app.f83ea0ab.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but linker.web doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div></body></html>
|
File diff suppressed because one or more lines are too long
1
src/linker.app/public/web/js/159.d85691cc.js
Normal file
1
src/linker.app/public/web/js/159.d85691cc.js
Normal file
File diff suppressed because one or more lines are too long
1
src/linker.app/public/web/js/app.665d3555.js
Normal file
1
src/linker.app/public/web/js/app.665d3555.js
Normal file
File diff suppressed because one or more lines are too long
@@ -75,10 +75,10 @@ namespace linker.libs
|
||||
byte[] key = new byte[16];
|
||||
byte[] iv = new byte[16];
|
||||
byte[] hash = SHA384.HashData(Encoding.UTF8.GetBytes(password));
|
||||
|
||||
Array.Copy(hash, 0, key, 0, key.Length);
|
||||
Array.Copy(hash, key.Length, iv, 0, iv.Length);
|
||||
return (Key: key, IV: iv);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -20,8 +20,15 @@ namespace linker.messenger.store.file.relay
|
||||
{
|
||||
this.dBfactory = dBfactory;
|
||||
liteCollection = dBfactory.GetCollection<CdkeyStoreInfo>("relayCdkey");
|
||||
this.crypto = CryptoFactory.CreateSymmetric(fileConfig.Data.Server.Relay.Cdkey.SecretKey, System.Security.Cryptography.PaddingMode.PKCS7);
|
||||
this.fileConfig = fileConfig;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(fileConfig.Data.Server.Relay.Cdkey.SecretKey) == false)
|
||||
{
|
||||
fileConfig.Data.Server.Cdkey.SecretKey = fileConfig.Data.Server.Relay.Cdkey.SecretKey;
|
||||
fileConfig.Data.Server.Relay.Cdkey.SecretKey = string.Empty;
|
||||
fileConfig.Data.Update();
|
||||
}
|
||||
this.crypto = CryptoFactory.CreateSymmetric(fileConfig.Data.Server.Cdkey.SecretKey, System.Security.Cryptography.PaddingMode.PKCS7);
|
||||
}
|
||||
|
||||
public bool ValidateSecretKey(string secretKey)
|
||||
|
@@ -10,7 +10,7 @@ namespace linker.messenger.store.file
|
||||
public sealed partial class RunningConfigInfo
|
||||
{
|
||||
public RelayInfo Relay { get; set; } = new RelayInfo();
|
||||
|
||||
|
||||
}
|
||||
|
||||
public sealed class RelayInfo
|
||||
@@ -49,7 +49,8 @@ namespace linker.messenger.store.file
|
||||
#else
|
||||
public string SecretKey { get; set; } = Guid.NewGuid().ToString().ToUpper();
|
||||
#endif
|
||||
public CdkeyConfigInfo Cdkey { get; set; } = new CdkeyConfigInfo();
|
||||
[SaveJsonIgnore]
|
||||
public CdkeyConfigTempInfo Cdkey { get; set; } = new CdkeyConfigTempInfo();
|
||||
|
||||
public DistributedInfo Distributed { get; set; } = new DistributedInfo { };
|
||||
}
|
||||
@@ -59,4 +60,9 @@ namespace linker.messenger.store.file
|
||||
public RelayServerNodeInfo Node { get; set; } = new RelayServerNodeInfo { };
|
||||
public RelayServerMasterInfo Master { get; set; } = new RelayServerMasterInfo { };
|
||||
}
|
||||
|
||||
public sealed class CdkeyConfigTempInfo
|
||||
{
|
||||
public string SecretKey { get; set; }
|
||||
}
|
||||
}
|
||||
|
@@ -7,7 +7,6 @@ using System.Net;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Net.Sockets;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace linker.snat
|
||||
{
|
||||
@@ -21,7 +20,7 @@ namespace linker.snat
|
||||
/// 4,改为 192.168.56.6(局域网IP)->10.18.18.23(客户端A的虚拟网卡IP)
|
||||
/// 5,回到客户端A,就完成了NAT
|
||||
/// </summary>
|
||||
public sealed class LinkerSrcNat
|
||||
public sealed partial class LinkerSrcNat
|
||||
{
|
||||
public bool Running => winDivert != null;
|
||||
|
||||
@@ -30,13 +29,6 @@ namespace linker.snat
|
||||
/// </summary>
|
||||
private WinDivert winDivert;
|
||||
|
||||
/// <summary>
|
||||
/// 网卡IP,用来作为源地址
|
||||
/// </summary>
|
||||
private NetworkIPv4Addr interfaceAddr;
|
||||
private HashSet<uint> interfaceAddrs;
|
||||
|
||||
|
||||
private uint srcIp;
|
||||
private NetworkIPv4Addr srcAddr;
|
||||
|
||||
@@ -54,11 +46,17 @@ namespace linker.snat
|
||||
/// <summary>
|
||||
/// 五元组NAT映射表
|
||||
/// </summary>
|
||||
private ConcurrentDictionary<(uint src, ushort srcPort, uint dst, ushort dstPort, ProtocolType pro), NatMapInfo> natMap = new ConcurrentDictionary<(uint src, ushort srcPort, uint dst, ushort dstPort, ProtocolType pro), NatMapInfo>();
|
||||
private readonly ConcurrentDictionary<(uint src, ushort srcPort, uint dst, ushort dstPort, ProtocolType pro), NatMapInfo> natMap = new();
|
||||
/// <summary>
|
||||
/// 分配端口表
|
||||
/// </summary>
|
||||
private ConcurrentDictionary<(uint src, ushort port), ushort> source2portMap = new ConcurrentDictionary<(uint src, ushort port), ushort>();
|
||||
private readonly ConcurrentDictionary<(uint src, ushort port), ushort> source2portMap = new();
|
||||
|
||||
/// <summary>
|
||||
/// 网络接口
|
||||
/// </summary>
|
||||
private readonly LinkerSrcNatInterfaceHelper interfaceHelper = new();
|
||||
|
||||
|
||||
public LinkerSrcNat()
|
||||
{
|
||||
@@ -70,10 +68,8 @@ namespace linker.snat
|
||||
/// <param name="info">启动参数</param>
|
||||
/// <param name="error">false启动失败的时候会有报错信息</param>
|
||||
/// <returns></returns>
|
||||
public bool Setup(SetupInfo info, out string error)
|
||||
public bool Setup(SetupInfo info, ref string error)
|
||||
{
|
||||
error = string.Empty;
|
||||
|
||||
if (OperatingSystem.IsWindows() == false || (RuntimeInformation.ProcessArchitecture != Architecture.X86 && RuntimeInformation.ProcessArchitecture != Architecture.X64))
|
||||
{
|
||||
error = "only win x64 and win x86";
|
||||
@@ -88,15 +84,6 @@ namespace linker.snat
|
||||
{
|
||||
return false;
|
||||
}
|
||||
IPAddress defaultInterfaceIP = GetDefaultInterface();
|
||||
if (defaultInterfaceIP == null)
|
||||
{
|
||||
error = "SNAT get default interface id fail";
|
||||
string routes = CommandHelper.Windows(string.Empty, new string[] { $"route print" });
|
||||
LoggerHelper.Instance.Error(routes);
|
||||
return false;
|
||||
}
|
||||
interfaceAddrs = GetInterfaces();
|
||||
|
||||
try
|
||||
{
|
||||
@@ -105,12 +92,11 @@ namespace linker.snat
|
||||
srcIp = NetworkHelper.ToValue(info.Src);
|
||||
srcAddr = IPv4Addr.Parse(info.Src.ToString());
|
||||
|
||||
interfaceAddr = IPv4Addr.Parse(defaultInterfaceIP.ToString());
|
||||
interfaceHelper.Setup();
|
||||
string filters = BuildFilter(info.Dsts);
|
||||
winDivert = new WinDivert(filters, WinDivert.Layer.Network, 0, 0);
|
||||
|
||||
cts = new CancellationTokenSource();
|
||||
|
||||
Recv(cts);
|
||||
ClearTask(cts);
|
||||
|
||||
@@ -122,34 +108,6 @@ namespace linker.snat
|
||||
}
|
||||
return false;
|
||||
}
|
||||
private static IPAddress GetDefaultInterface()
|
||||
{
|
||||
string[] lines = CommandHelper.Windows(string.Empty, new string[] { $"route print" }).Split(Environment.NewLine);
|
||||
foreach (var item in lines)
|
||||
{
|
||||
if (item.Trim().StartsWith("0.0.0.0"))
|
||||
{
|
||||
string[] arr = Regex.Replace(item.Trim(), @"\s+", " ").Split(' ');
|
||||
return IPAddress.Parse(arr[arr.Length - 2]);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
private static HashSet<uint> GetInterfaces()
|
||||
{
|
||||
return NetworkInterface.GetAllNetworkInterfaces().Select(c =>
|
||||
{
|
||||
try
|
||||
{
|
||||
return c.GetIPProperties().UnicastAddresses.FirstOrDefault(c => c.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork).Address;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
return null;
|
||||
}).Where(c => c != null).Select(NetworkHelper.ToValue).ToHashSet();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 过滤条件,只过滤一定的数据包
|
||||
@@ -159,7 +117,6 @@ namespace linker.snat
|
||||
{
|
||||
IEnumerable<string> ipRanges = dsts.Select(c => $"(ip.SrcAddr >= {c.NetworkIP} and ip.SrcAddr <= {c.BroadcastIP})");
|
||||
return $"inbound and ({string.Join(" or ", ipRanges)})";
|
||||
//return $"({string.Join(" or ", ipRanges)})";
|
||||
}
|
||||
/// <summary>
|
||||
/// 开始接收数据包
|
||||
@@ -241,14 +198,14 @@ namespace linker.snat
|
||||
{
|
||||
foreach (var (i, p) in new WinDivertIndexedPacketParser(packet))
|
||||
{
|
||||
//本机网卡IP不需要改,直接注入就可以
|
||||
if (interfaceAddrs.Contains(ipv4.DstAddr) == false)
|
||||
NetworkIPv4Addr interfaceAddr = interfaceHelper.GetInterfaceAddr(ipv4.DstAddr);
|
||||
if (interfaceAddr.Raw != 0)
|
||||
{
|
||||
bool result = (ProtocolType)p.IPv4Hdr->Protocol switch
|
||||
{
|
||||
ProtocolType.Icmp => InjectIcmp(p, ptr),
|
||||
ProtocolType.Tcp => InjectTcp(p, ptr),
|
||||
ProtocolType.Udp => InjectUdp(p, ptr),
|
||||
ProtocolType.Icmp => InjectIcmp(p, ptr, interfaceAddr),
|
||||
ProtocolType.Tcp => InjectTcp(p, ptr, interfaceAddr),
|
||||
ProtocolType.Udp => InjectUdp(p, ptr, interfaceAddr),
|
||||
_ => false,
|
||||
};
|
||||
if (result == false) return false;
|
||||
@@ -263,13 +220,14 @@ namespace linker.snat
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 注入ICMP
|
||||
/// </summary>
|
||||
/// <param name="p"></param>
|
||||
/// <param name="ptr"></param>
|
||||
/// <returns></returns>
|
||||
private unsafe bool InjectIcmp(WinDivertParseResult p, byte* ptr)
|
||||
private unsafe bool InjectIcmp(WinDivertParseResult p, byte* ptr, NetworkIPv4Addr interfaceAddr)
|
||||
{
|
||||
//只操作response 和 request
|
||||
if (p.ICMPv4Hdr->Type != 0 && p.ICMPv4Hdr->Type != 8) return false;
|
||||
@@ -342,7 +300,7 @@ namespace linker.snat
|
||||
/// <param name="p"></param>
|
||||
/// <param name="ptr"></param>
|
||||
/// <returns></returns>
|
||||
private unsafe bool InjectTcp(WinDivertParseResult p, byte* ptr)
|
||||
private unsafe bool InjectTcp(WinDivertParseResult p, byte* ptr, NetworkIPv4Addr interfaceAddr)
|
||||
{
|
||||
IPV4Packet ipv4 = new IPV4Packet(ptr);
|
||||
|
||||
@@ -410,7 +368,7 @@ namespace linker.snat
|
||||
/// <param name="p"></param>
|
||||
/// <param name="ptr"></param>
|
||||
/// <returns></returns>
|
||||
private unsafe bool InjectUdp(WinDivertParseResult p, byte* ptr)
|
||||
private unsafe bool InjectUdp(WinDivertParseResult p, byte* ptr, NetworkIPv4Addr interfaceAddr)
|
||||
{
|
||||
//新端口
|
||||
ValueTuple<uint, ushort> portKey = (p.IPv4Hdr->SrcAddr.Raw, p.UDPHdr->SrcPort);
|
||||
@@ -481,6 +439,8 @@ namespace linker.snat
|
||||
|
||||
natMap.Clear();
|
||||
source2portMap.Clear();
|
||||
|
||||
interfaceHelper.Shutdown();
|
||||
}
|
||||
|
||||
private void ClearTask(CancellationTokenSource cts)
|
||||
@@ -663,16 +623,61 @@ namespace linker.snat
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// SNAT回调
|
||||
/// </summary>
|
||||
public interface ILinkerSNatRecvCallback
|
||||
}
|
||||
|
||||
public sealed class LinkerSrcNatInterfaceHelper
|
||||
{
|
||||
private uint[] interfaceMasks = [];
|
||||
private readonly ConcurrentDictionary<uint, (uint, NetworkIPv4Addr)> network2ipMap = new();
|
||||
private readonly ConcurrentDictionary<uint, NetworkIPv4Addr> ip2ipMap = new();
|
||||
|
||||
public void Setup()
|
||||
{
|
||||
/// <summary>
|
||||
/// 接收到的TCP/IP数据包
|
||||
/// </summary>
|
||||
/// <param name="packet"></param>
|
||||
public void Recv(ReadOnlyMemory<byte> packet);
|
||||
Shutdown();
|
||||
List<(IPAddress Address, IPAddress IPv4Mask)> interfaces = NetworkInterface.GetAllNetworkInterfaces()
|
||||
.Where(c => c.OperationalStatus == OperationalStatus.Up && c.NetworkInterfaceType != NetworkInterfaceType.Loopback && c.NetworkInterfaceType != NetworkInterfaceType.Tunnel)
|
||||
.Select(c => c.GetIPProperties()).SelectMany(c => c.UnicastAddresses.Where(c => c.Address.AddressFamily == AddressFamily.InterNetwork).Select(c => (c.Address, c.IPv4Mask))).ToList();
|
||||
|
||||
interfaceMasks = interfaces.Select(c => NetworkHelper.ToValue(c.IPv4Mask)).Distinct().ToArray();
|
||||
foreach ((IPAddress Address, IPAddress IPv4Mask) in interfaces)
|
||||
{
|
||||
uint value = NetworkHelper.ToValue(Address);
|
||||
uint network = NetworkHelper.ToNetworkValue(value, NetworkHelper.ToValue(IPv4Mask));
|
||||
network2ipMap.TryAdd(network, (value, IPv4Addr.Parse(Address.ToString())));
|
||||
}
|
||||
}
|
||||
|
||||
public NetworkIPv4Addr GetInterfaceAddr(uint dstAddr)
|
||||
{
|
||||
if (ip2ipMap.TryGetValue(dstAddr, out NetworkIPv4Addr interfaceAddr))
|
||||
{
|
||||
return interfaceAddr;
|
||||
}
|
||||
for (int i = 0; i < interfaceMasks.Length; i++)
|
||||
{
|
||||
//找到匹配的网卡
|
||||
if (network2ipMap.TryGetValue(interfaceMasks[i] & dstAddr, out (uint, NetworkIPv4Addr) info))
|
||||
{
|
||||
//目标ip与网卡ip相同,无需注入
|
||||
if (info.Item1 == dstAddr)
|
||||
{
|
||||
ip2ipMap.TryAdd(dstAddr, default);
|
||||
return default;
|
||||
}
|
||||
|
||||
ip2ipMap.TryAdd(dstAddr, info.Item2);
|
||||
return info.Item2;
|
||||
}
|
||||
}
|
||||
|
||||
return default;
|
||||
}
|
||||
|
||||
public void Shutdown()
|
||||
{
|
||||
ip2ipMap.Clear();
|
||||
network2ipMap.Clear();
|
||||
interfaceMasks = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
<?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.301" ProductVersion="0.0.0.301" 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.302" ProductVersion="0.0.0.302" publishDir="/dist/" dstrip="false" local="false" ignored="false">
|
||||
<file name="main.aardio" path="main.aardio" comment="main.aardio"/>
|
||||
<folder name="资源文件" path="res" embed="true" local="false" ignored="false">
|
||||
<file name="favicon.ico" path="res\favicon.ico" comment="res\favicon.ico"/>
|
||||
|
BIN
src/linker.tray.win/dist/linker.tray.win.exe
vendored
BIN
src/linker.tray.win/dist/linker.tray.win.exe
vendored
Binary file not shown.
1
src/linker.tray.win/web/css/118.be8a94f0.css
Normal file
1
src/linker.tray.win/web/css/118.be8a94f0.css
Normal file
@@ -0,0 +1 @@
|
||||
.el-radio-group[data-v-3927a588]{margin-right:.6rem}.wrap[data-v-3927a588]{padding-bottom:1rem}.el-form-item[data-v-8eed28d4]{margin-bottom:1rem}.el-input-number--small[data-v-8eed28d4]{width:10rem!important}.el-form-item[data-v-3afdc5d4]{margin-bottom:1rem}.el-input-number--small[data-v-3afdc5d4]{width:10rem!important}.head .search>div[data-v-33dd67e0]{margin-right:1rem}.page[data-v-33dd67e0]{padding:2rem 0;display:inline-block}.el-form-item[data-v-33dd67e0]{margin-bottom:1rem}.el-input-number--small[data-v-33dd67e0]{width:10rem!important}.head .search>div[data-v-d3ca7ebe]{margin-right:1rem}.page[data-v-d3ca7ebe]{padding:2rem 0;display:inline-block}.el-form-item[data-v-d3ca7ebe]{margin-bottom:1rem}.el-input-number--small[data-v-d3ca7ebe]{width:10rem!important}.el-form-item[data-v-c2557c92]{margin-bottom:1rem}.el-input-number--small[data-v-c2557c92]{width:10rem!important}.blue[data-v-62bbb114]{color:#409eff}a.a-edit[data-v-62bbb114]{margin-left:1rem}a.a-edit .el-icon[data-v-62bbb114]{vertical-align:middle}.servers-wrap[data-v-60d7955e]{padding:1rem;font-size:1.3rem;color:#555}.servers-wrap a[data-v-60d7955e]{color:#333}
|
@@ -1 +0,0 @@
|
||||
.el-radio-group[data-v-7061404c]{margin-right:.6rem}.wrap[data-v-7061404c]{padding-bottom:1rem}.el-form-item[data-v-2bef0d8e]{margin-bottom:1rem}.el-input-number--small[data-v-2bef0d8e]{width:10rem!important}.el-form-item[data-v-3d96703d]{margin-bottom:1rem}.el-input-number--small[data-v-3d96703d]{width:10rem!important}.head .search>div[data-v-5d11d068]{margin-right:1rem}.page[data-v-5d11d068]{padding:2rem 0;display:inline-block}.el-form-item[data-v-5d11d068]{margin-bottom:1rem}.el-input-number--small[data-v-5d11d068]{width:10rem!important}.head .search>div[data-v-22d5523e]{margin-right:1rem}.page[data-v-22d5523e]{padding:2rem 0;display:inline-block}.el-form-item[data-v-22d5523e]{margin-bottom:1rem}.el-input-number--small[data-v-22d5523e]{width:10rem!important}.el-form-item[data-v-c2557c92]{margin-bottom:1rem}.el-input-number--small[data-v-c2557c92]{width:10rem!important}.blue[data-v-1c91b9a3]{color:#409eff}a.a-edit[data-v-1c91b9a3]{margin-left:1rem}a.a-edit .el-icon[data-v-1c91b9a3]{vertical-align:middle}.servers-wrap[data-v-60d7955e]{padding:1rem;font-size:1.3rem;color:#555}.servers-wrap a[data-v-60d7955e]{color:#333}
|
@@ -1 +1 @@
|
||||
<!doctype html><html lang=""><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" href="favicon.ico"><title>linker.web</title><link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY=" crossorigin=""/><script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js" integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo=" crossorigin=""></script><script defer="defer" src="js/chunk-vendors.81af7d4e.js"></script><script defer="defer" src="js/app.360c2592.js"></script><link href="css/chunk-vendors.d8267b33.css" rel="stylesheet"><link href="css/app.f83ea0ab.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but linker.web doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div></body></html>
|
||||
<!doctype html><html lang=""><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" href="favicon.ico"><title>linker.web</title><link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY=" crossorigin=""/><script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js" integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo=" crossorigin=""></script><script defer="defer" src="js/chunk-vendors.81af7d4e.js"></script><script defer="defer" src="js/app.665d3555.js"></script><link href="css/chunk-vendors.d8267b33.css" rel="stylesheet"><link href="css/app.f83ea0ab.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but linker.web doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div></body></html>
|
277
src/linker.tray.win/web/js/118.16573c08.js
Normal file
277
src/linker.tray.win/web/js/118.16573c08.js
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1
src/linker.tray.win/web/js/159.d85691cc.js
Normal file
1
src/linker.tray.win/web/js/159.d85691cc.js
Normal file
File diff suppressed because one or more lines are too long
1
src/linker.tray.win/web/js/212.2cb1147b.js
Normal file
1
src/linker.tray.win/web/js/212.2cb1147b.js
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1
src/linker.tray.win/web/js/app.665d3555.js
Normal file
1
src/linker.tray.win/web/js/app.665d3555.js
Normal file
File diff suppressed because one or more lines are too long
@@ -10,7 +10,7 @@ namespace linker.tun
|
||||
public bool Running => linkerSrcNat.Running;
|
||||
|
||||
private LinkerSrcNat linkerSrcNat = new LinkerSrcNat();
|
||||
|
||||
|
||||
|
||||
public LanSnat()
|
||||
{
|
||||
@@ -40,8 +40,9 @@ namespace linker.tun
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.Instance.Error(ex);
|
||||
}
|
||||
|
||||
Shutdown();
|
||||
@@ -49,7 +50,7 @@ namespace linker.tun
|
||||
{
|
||||
Src = address,
|
||||
Dsts = items.Select(c => new LinkerSrcNat.AddrInfo(c.IP, c.PrefixLength)).ToArray()
|
||||
}, out error);
|
||||
}, ref error);
|
||||
}
|
||||
public void Shutdown()
|
||||
{
|
||||
|
@@ -206,7 +206,9 @@ namespace linker.tun
|
||||
return;
|
||||
}
|
||||
if (linkerTunDevice.Running)
|
||||
{
|
||||
lanSnat.Setup(address, prefixLength, items, ref natError);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 移除NAT
|
||||
|
@@ -21,9 +21,10 @@
|
||||
<Authors>snltty</Authors>
|
||||
<Company>snltty</Company>
|
||||
<Description>1. 一些累计更新
|
||||
2. 修复socks5,解决CPU爆满问题,增加域名解析和HTTP代理
|
||||
2. 修复socks5,解决CPU爆满问题,增加本地域名解析,支持HTTP代理
|
||||
3. 优化唤醒模块
|
||||
5. 管理端口改为1804,一个端口托管Web+Websocket</Description>
|
||||
4. 优化应用NAT,根据目标IP自动选择网卡
|
||||
5. 分离cdkey,使其可作用于任意模块</Description>
|
||||
<Copyright>snltty</Copyright>
|
||||
<PackageProjectUrl>https://github.com/snltty/linker</PackageProjectUrl>
|
||||
<RepositoryUrl>https://github.com/snltty/linker</RepositoryUrl>
|
||||
|
@@ -1,6 +1,7 @@
|
||||
v1.8.3
|
||||
2025-06-10 17:28:53
|
||||
2025-06-13 10:47:48
|
||||
1. 一些累计更新
|
||||
2. 修复socks5,解决CPU爆满问题,增加域名解析和HTTP代理
|
||||
2. 修复socks5,解决CPU爆满问题,增加本地域名解析,支持HTTP代理
|
||||
3. 优化唤醒模块
|
||||
5. 管理端口改为1804,一个端口托管Web+Websocket
|
||||
4. 优化应用NAT,根据目标IP自动选择网卡
|
||||
5. 分离cdkey,使其可作用于任意模块
|
Reference in New Issue
Block a user