mirror of
https://github.com/snltty/linker.git
synced 2025-09-26 21:15:57 +08:00
参数
This commit is contained in:
@@ -255,8 +255,8 @@ namespace linker.app
|
||||
Modes = new string[] { "client" },
|
||||
};
|
||||
return new Dictionary<string, string> {
|
||||
{"Client",Convert.ToBase64String(Encoding.UTF8.GetBytes(JsonSerializer.Serialize(client)))},
|
||||
{"Common", Convert.ToBase64String(Encoding.UTF8.GetBytes(JsonSerializer.Serialize(common)))}
|
||||
{"Client",client.ToJson()},
|
||||
{"Common", common.ToJson()}
|
||||
};
|
||||
}
|
||||
private void TuntapSetup()
|
||||
|
@@ -10,7 +10,8 @@ sidebar_position: 11
|
||||
|
||||
:::tip[2、Android]
|
||||
|
||||
没做保活,没做Activity恢复,请自行设置锁定和允许后台行为,按住下拉,慢一点,拉满100%松开可以刷新整个页面
|
||||
1. 没做保活,没做Activity恢复,请自行设置锁定和允许后台行为,按住下拉,慢一点,拉满100%松开可以刷新整个页面
|
||||
2. Android 使用VpnService服务创建网卡,无法在创建网卡后动态添加路由,在点对网时,如果无法使用,请手动重启一两次网卡
|
||||
|
||||

|
||||
|
||||
|
@@ -1,14 +0,0 @@
|
||||
---
|
||||
sidebar_position: 0
|
||||
---
|
||||
|
||||
# 2.0、重要说明
|
||||
|
||||
:::tip[说明]
|
||||
|
||||
1. linker.exe 一体包含`客户端`,`服务端(信标服务+中继服务)`,区别只在于 `configs/common.json` 里的 Modes 配置,是 client 还是 server
|
||||
2. 服务端模式 监听端口 `1802(TCP+UDP)`
|
||||
3. 客户端模式 监听端口 `1803(TCP)`websocket管理接口,`1804(TCP)`管理UI端口
|
||||
4. 服务端只要运行起来就可以了,没有任何管理,最多手动修改一下`configs/server.json`里的监听端口和密钥
|
||||
|
||||
:::
|
19
src/linker.doc.web/docs/2、首次运行/2.0、重要说明(必看).md
Normal file
19
src/linker.doc.web/docs/2、首次运行/2.0、重要说明(必看).md
Normal file
@@ -0,0 +1,19 @@
|
||||
---
|
||||
sidebar_position: 0
|
||||
---
|
||||
|
||||
# 2.0、重要说明(必看)
|
||||
|
||||
:::tip[公共配置]
|
||||
1. linker.exe 一体包含`客户端`,`服务端(信标服务+中继服务)`,区别只在于 `configs/common.json` 里的 Modes 配置,是 client 还是 server
|
||||
:::
|
||||
|
||||
:::tip[客户端]
|
||||
1. 客户端模式 监听端口 `1803(TCP)`websocket管理接口,`1804(TCP)`管理UI端口
|
||||
2. 运行起来后可以使用`http://127.0.0.1:1804`打开管理页面,如果是windows,也可以在`linker.tray.win.exe`托盘程序里打开管理页面
|
||||
:::
|
||||
|
||||
:::tip[服务端]
|
||||
1. 服务端模式 监听端口 `1802(TCP+UDP)`
|
||||
2. 服务端只要运行起来就可以了,没有任何管理,最多手动修改一下`configs/server.json`里的监听端口和密钥
|
||||
:::
|
@@ -1,8 +1,8 @@
|
||||
---
|
||||
sidebar_position: 9
|
||||
sidebar_position: 10
|
||||
---
|
||||
|
||||
# 2.9、信标密钥
|
||||
# 2.10、信标密钥
|
||||
|
||||
:::tip[说明]
|
||||
|
@@ -54,64 +54,3 @@ systemctl restart linker
|
||||
systemctl enable linker
|
||||
```
|
||||
:::
|
||||
|
||||
## 3、linux 手动 docker
|
||||
|
||||
:::tip[说明]
|
||||
|
||||
1. 服务端端口 `1802` TCP+UDP
|
||||
2. 客户端端口 `1804`、`1803` TCP
|
||||
3. 配置文件夹 `./configs`
|
||||
4. 日志文件夹 `./logs`
|
||||
5. 镜像清单 `snltty/linker-debian`、`snltty/linker-musl`
|
||||
6. 特定平台 `snltty/linker-debian-{arch}`、`snltty/linker-musl-{arch}`,`{arch}`可以是`x64`、`arm64`、`arm`
|
||||
7. `bridge`模式,需要映射一些端口比如`-p 18000-18010:18000-18010`,用于端口转发
|
||||
8. `host`模式,或者直接使用host`--network host`,**建议使用host,点对网,网对网,端口转发都方便**
|
||||
|
||||
#### 客户端-bridge
|
||||
```
|
||||
docker run -it -d --name linker \
|
||||
-p 1804:1804/tcp -p 1803:1803/tcp \
|
||||
-p 18000-18010:18000-18010/tcp \
|
||||
-p 18000-18010:18000-18010/udp \
|
||||
-v /usr/local/linker-docker/configs:/app/configs \
|
||||
-v /usr/local/linker-docker/logs:/app/logs \
|
||||
--device /dev/net/tun \
|
||||
--restart=always \
|
||||
--privileged=true \
|
||||
snltty/linker-musl
|
||||
```
|
||||
#### 客户端-host
|
||||
```
|
||||
docker run -it -d --name linker \
|
||||
-v /usr/local/linker-docker/configs:/app/configs \
|
||||
-v /usr/local/linker-docker/logs:/app/logs \
|
||||
--device /dev/net/tun \
|
||||
--restart=always \
|
||||
--privileged=true \
|
||||
--network host \
|
||||
snltty/linker-musl
|
||||
```
|
||||
|
||||
#### 服务端-bridge
|
||||
```
|
||||
docker run -it -d --name linker \
|
||||
-p 1802:1802/tcp -p 1802:1802/udp \
|
||||
-v /usr/local/linker-docker/configs:/app/configs \
|
||||
-v /usr/local/linker-docker/logs:/app/logs \
|
||||
--restart=always \
|
||||
--privileged=true \
|
||||
snltty/linker-musl
|
||||
```
|
||||
|
||||
#### 服务端-host
|
||||
```
|
||||
docker run -it -d --name linker \
|
||||
-v /usr/local/linker-docker/configs:/app/configs \
|
||||
-v /usr/local/linker-docker/logs:/app/logs \
|
||||
--restart=always \
|
||||
--privileged=true \
|
||||
--network host \
|
||||
snltty/linker-musl
|
||||
```
|
||||
:::
|
||||
|
83
src/linker.doc.web/docs/2、首次运行/2.3、安装方法(docker).md
Normal file
83
src/linker.doc.web/docs/2、首次运行/2.3、安装方法(docker).md
Normal file
@@ -0,0 +1,83 @@
|
||||
---
|
||||
sidebar_position: 3
|
||||
---
|
||||
|
||||
# 2.3、安装方法(docker)
|
||||
|
||||
## 1、linux 一键安装
|
||||
:::tip[说明]
|
||||
下载安装脚本
|
||||
```
|
||||
curl -fsSL https://linker-doc.snltty.com/linker-install.sh -o linker-install.sh
|
||||
chmod +x linker-install.sh
|
||||
```
|
||||
默认安装位置
|
||||
```
|
||||
./linker-install.sh
|
||||
```
|
||||
指定安装位置
|
||||
```
|
||||
./linker-install.sh /usr/local/bin
|
||||
```
|
||||
:::
|
||||
|
||||
## 2、linux 手动 docker
|
||||
|
||||
:::tip[说明]
|
||||
|
||||
1. 服务端端口 `1802` TCP+UDP
|
||||
2. 客户端端口 `1804`、`1803` TCP
|
||||
3. 配置文件夹 `./configs`
|
||||
4. 日志文件夹 `./logs`
|
||||
5. 镜像清单 `snltty/linker-debian`、`snltty/linker-musl`
|
||||
6. 特定平台 `snltty/linker-debian-{arch}`、`snltty/linker-musl-{arch}`,`{arch}`可以是`x64`、`arm64`、`arm`
|
||||
7. `bridge`模式,需要映射一些端口比如`-p 18000-18010:18000-18010`,用于端口转发
|
||||
8. `host`模式,或者直接使用host`--network host`,**建议使用host,点对网,网对网,端口转发都方便**
|
||||
|
||||
#### 客户端-bridge
|
||||
```
|
||||
docker run -it -d --name linker \
|
||||
-p 1804:1804/tcp -p 1803:1803/tcp \
|
||||
-p 18000-18010:18000-18010/tcp \
|
||||
-p 18000-18010:18000-18010/udp \
|
||||
-v /usr/local/linker-docker/configs:/app/configs \
|
||||
-v /usr/local/linker-docker/logs:/app/logs \
|
||||
--device /dev/net/tun \
|
||||
--restart=always \
|
||||
--privileged=true \
|
||||
snltty/linker-musl
|
||||
```
|
||||
#### 客户端-host
|
||||
```
|
||||
docker run -it -d --name linker \
|
||||
-v /usr/local/linker-docker/configs:/app/configs \
|
||||
-v /usr/local/linker-docker/logs:/app/logs \
|
||||
--device /dev/net/tun \
|
||||
--restart=always \
|
||||
--privileged=true \
|
||||
--network host \
|
||||
snltty/linker-musl
|
||||
```
|
||||
|
||||
#### 服务端-bridge
|
||||
```
|
||||
docker run -it -d --name linker \
|
||||
-p 1802:1802/tcp -p 1802:1802/udp \
|
||||
-v /usr/local/linker-docker/configs:/app/configs \
|
||||
-v /usr/local/linker-docker/logs:/app/logs \
|
||||
--restart=always \
|
||||
--privileged=true \
|
||||
snltty/linker-musl
|
||||
```
|
||||
|
||||
#### 服务端-host
|
||||
```
|
||||
docker run -it -d --name linker \
|
||||
-v /usr/local/linker-docker/configs:/app/configs \
|
||||
-v /usr/local/linker-docker/logs:/app/logs \
|
||||
--restart=always \
|
||||
--privileged=true \
|
||||
--network host \
|
||||
snltty/linker-musl
|
||||
```
|
||||
:::
|
@@ -1,5 +1,5 @@
|
||||
---
|
||||
sidebar_position: 3
|
||||
sidebar_position: 4
|
||||
---
|
||||
|
||||
## 1、使用ipk安装
|
@@ -1,8 +1,8 @@
|
||||
---
|
||||
sidebar_position: 4
|
||||
sidebar_position: 5
|
||||
---
|
||||
|
||||
# 2.4、安装方法(NAS)
|
||||
# 2.5、安装方法(NAS)
|
||||
|
||||
:::tip[各个nas都差不多,主要看配置信息]
|
||||
|
@@ -1,8 +1,8 @@
|
||||
---
|
||||
sidebar_position: 5
|
||||
sidebar_position: 6
|
||||
---
|
||||
|
||||
# 2.5、初始化配置1(公共)
|
||||
# 2.6、初始化配置1(公共)
|
||||
|
||||
## 1、公共配置文件,客户端服务端都有的
|
||||
|
@@ -1,12 +1,12 @@
|
||||
---
|
||||
sidebar_position: 6
|
||||
sidebar_position: 7
|
||||
---
|
||||
|
||||
# 2.6、初始化配置2(服务端)
|
||||
# 2.7、初始化配置2(服务端)
|
||||
|
||||
## 1、服务端手动修改配置文件
|
||||
|
||||
这是自建服务器需要配置的,没有服务器则跳过
|
||||
这是自建服务器需要配置的,没有服务器则跳过,**`运行起来就可以了,没有配置,只有一个server.json,只需要把对应的密钥填到客户端即可`**
|
||||
|
||||
:::tip[服务端运行流程]
|
||||
1. 运行程序,在configs目录下会生成 common.json server.json
|
@@ -1,8 +1,8 @@
|
||||
---
|
||||
sidebar_position: 7
|
||||
sidebar_position: 8
|
||||
---
|
||||
|
||||
# 2.7、初始化配置3(客户端)
|
||||
# 2.8、初始化配置3(客户端)
|
||||
|
||||
|
||||
## 1、客户端使用web初始化
|
@@ -1,17 +0,0 @@
|
||||
---
|
||||
sidebar_position: 8
|
||||
---
|
||||
|
||||
# 2.8、初始化配置4(三方入参调用)
|
||||
|
||||
## 1、使用参数初始化
|
||||
|
||||
:::tip[v1.7.0+]
|
||||
1. 服务端,客户端,都可以使用这种方式覆盖配置
|
||||
2. 如果你使用第三方程序启动linker,可以传入参数进行初始化,`client.json`、`server.json`、`action.json`、`common.json`,
|
||||
3. 像这样,不填写的字段将以默认值生成,将json转为base64
|
||||
```
|
||||
linker.exe --config-client base641 --config-server base642 --config-action base643 --config-common base644
|
||||
```
|
||||
:::
|
||||
|
54
src/linker.doc.web/docs/2、首次运行/2.9、初始化配置4(三方入参调用).md
Normal file
54
src/linker.doc.web/docs/2、首次运行/2.9、初始化配置4(三方入参调用).md
Normal file
@@ -0,0 +1,54 @@
|
||||
---
|
||||
sidebar_position: 9
|
||||
---
|
||||
|
||||
# 2.9、初始化配置4(三方入参调用)
|
||||
|
||||
## 1、使用参数初始化
|
||||
|
||||
:::tip[v1.7.0+]
|
||||
1. 如果你使用第三方程序启动linker,可以传入参数进行初始化
|
||||
2. 填写了哪些字段,哪些字段就会强制覆盖原有配置
|
||||
3. 将json转为base64后传入 `linker.exe base64`
|
||||
```
|
||||
{
|
||||
"Client":"{}", //对应client.json
|
||||
"Server":"{}", //对应server.json
|
||||
"Common":"{}", //对应common.json
|
||||
"Action":"{}", //对应action.json
|
||||
"Tuntap":"{
|
||||
"IP":"10.18.18.2", 网卡IP
|
||||
"PrefixLength":24, 网卡掩码
|
||||
局域网IP列表
|
||||
"Lans":[{
|
||||
IP:"10.18.18.1", 局域网IP
|
||||
PrefixLength:24, 掩码
|
||||
Disabled:false, 禁用
|
||||
MapIP:"10.18.18.1", //路由IP
|
||||
MapPrefixLength:24, //路由掩码
|
||||
}],
|
||||
"Name":"linker", 网卡名
|
||||
"Running":true, 是否运行,true则启动后自动运行网卡
|
||||
"Switch":2, 2显示延迟,4使用高级功能,8自动连接,16禁用广播
|
||||
32禁用nat,64开启TCP包合并,128调整网卡顺序
|
||||
端口转发列表
|
||||
"Forwards":[
|
||||
{
|
||||
ListenAddr:"0.0.0.0"
|
||||
ListenPort:33890
|
||||
ConnectAddr:"192.168.1.1"
|
||||
ConnectPort:3389,
|
||||
Remark:"33890 转发到 3389",
|
||||
}
|
||||
],
|
||||
//本组网络配置
|
||||
"Lease":{
|
||||
IP : "10.18.18.0"
|
||||
PrefixLength:24,
|
||||
Name:"linker"
|
||||
}
|
||||
}"
|
||||
}
|
||||
```
|
||||
:::
|
||||
|
@@ -123,8 +123,8 @@ namespace linker.messenger.store.file
|
||||
var (client, clientObject, common, commonObject) = await GetConfig(configExportInfo).ConfigureAwait(false);
|
||||
Dictionary<string, object> dic = new Dictionary<string, object>
|
||||
{
|
||||
{"Client",Convert.ToBase64String(Encoding.UTF8.GetBytes(clientObject.ToJson()))},
|
||||
{"Common",Convert.ToBase64String(Encoding.UTF8.GetBytes(commonObject.ToJson()))},
|
||||
{"Client",clientObject.ToJson()},
|
||||
{"Common",commonObject.ToJson()},
|
||||
};
|
||||
|
||||
return Convert.ToBase64String(Encoding.UTF8.GetBytes(dic.ToJson()));
|
||||
@@ -145,8 +145,8 @@ namespace linker.messenger.store.file
|
||||
var (client, clientObject, common, commonObject) = await GetConfig(configExportInfo).ConfigureAwait(false);
|
||||
Dictionary<string, object> dic = new Dictionary<string, object>
|
||||
{
|
||||
{"Client",Convert.ToBase64String(Encoding.UTF8.GetBytes(clientObject.ToJson()))},
|
||||
{"Common",Convert.ToBase64String(Encoding.UTF8.GetBytes(commonObject.ToJson()))},
|
||||
{"Client",clientObject.ToJson()},
|
||||
{"Common",commonObject.ToJson()},
|
||||
};
|
||||
string value = Convert.ToBase64String(Encoding.UTF8.GetBytes(dic.ToJson()));
|
||||
return await exportResolver.Save(signInClientState.Connection.Address, value);
|
||||
|
@@ -109,10 +109,8 @@ namespace linker.messenger.store.file
|
||||
continue;
|
||||
}
|
||||
string text = item.Value.PropertyMethod.Serialize(item.Value.Property.GetValue(Data));
|
||||
if (dic != null && dic.TryGetValue(item.Value.Property.Name, out string base64))
|
||||
if (dic != null && dic.TryGetValue(item.Value.Property.Name, out string text2))
|
||||
{
|
||||
string text2 = Encoding.UTF8.GetString(Convert.FromBase64String(base64));
|
||||
|
||||
text = item.Value.PropertyMethod.Deserialize(text).ToJson();
|
||||
text = MergeJson(text, text2);
|
||||
|
||||
|
@@ -260,6 +260,7 @@ namespace linker.messenger.tuntap
|
||||
}
|
||||
return tuntapForwardTestWrapInfo;
|
||||
}
|
||||
|
||||
}
|
||||
public sealed class TuntabListInfo
|
||||
{
|
||||
|
@@ -5,7 +5,6 @@ using linker.messenger.signin;
|
||||
using linker.messenger.exroute;
|
||||
using linker.tun;
|
||||
using System.Net;
|
||||
using linker.libs.extends;
|
||||
|
||||
namespace linker.messenger.tuntap
|
||||
{
|
||||
|
@@ -84,6 +84,11 @@ namespace linker.messenger.updater
|
||||
|
||||
|
||||
private readonly LastTicksManager lastTicksManager = new LastTicksManager();
|
||||
|
||||
/// <summary>
|
||||
/// 订阅更新信息
|
||||
/// </summary>
|
||||
/// <param name="machineId"></param>
|
||||
public void Subscribe(string machineId)
|
||||
{
|
||||
if (subscribes.TryGetValue(machineId, out LastTicksManager _lastTicksManager) == false)
|
||||
@@ -146,7 +151,6 @@ namespace linker.messenger.updater
|
||||
}, () => lastTicksManager.DiffLessEqual(5000) ? 3000 : 15000);
|
||||
|
||||
}
|
||||
|
||||
public void Check()
|
||||
{
|
||||
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
||||
|
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<project ver="10" name="linker.route.win" libEmbed="true" icon="res\favicon.ico" ui="win" output="linker.route.win.exe" CompanyName="snltty" FileDescription="linker.route.win" LegalCopyright="Copyright (C) snltty 2024" ProductName="linker.route.win" InternalName="linker.route.win" FileVersion="0.0.0.20" ProductVersion="0.0.0.20" publishDir="/dist/" dstrip="false">
|
||||
<project ver="10" name="linker.route.win" libEmbed="true" icon="res\favicon.ico" ui="win" output="linker.route.win.exe" CompanyName="snltty" FileDescription="linker.route.win" LegalCopyright="Copyright (C) snltty 2024" ProductName="linker.route.win" InternalName="linker.route.win" FileVersion="0.0.0.25" ProductVersion="0.0.0.25" publishDir="/dist/" dstrip="false">
|
||||
<file name="main.aardio" path="main.aardio" comment="main.aardio"/>
|
||||
<folder name="资源文件" path="res" embed="true" local="false" ignored="false">
|
||||
<file name="Program.cs" path="res\Program.cs" comment="res\Program.cs"/>
|
||||
|
BIN
src/linker.route.win/dist/linker.route.win.exe
vendored
BIN
src/linker.route.win/dist/linker.route.win.exe
vendored
Binary file not shown.
@@ -36,7 +36,6 @@ mainForm.compiler = dotNet.createCompiler("C#");
|
||||
mainForm.compiler.Source = string.load("/res/Program.cs");
|
||||
mainForm.compiler.import("LinkerRoute");
|
||||
mainForm.netObj = LinkerRoute.LinkerRoute();
|
||||
mainForm.ipv4 = mainForm.netObj.GetIPV4("linker.snltty.com");
|
||||
|
||||
mainForm.serviceName = "linker.route.service";
|
||||
mainForm.exeName = "linker.route.win.exe";
|
||||
@@ -112,13 +111,21 @@ import win.reg;
|
||||
mainForm.reg = win.reg("HKEY_CURRENT_USER\Software\linker.route.win")
|
||||
|
||||
mainForm.ws = web.socket.client();
|
||||
mainForm.ws.protocol = mainForm.reg.queryValue("password") || mainForm.tbPassword.text;
|
||||
mainForm.wsUrl = mainForm.reg.queryValue("url") || mainForm.tbUrl.text;
|
||||
if(mainForm.reg.queryValue("password"))
|
||||
{
|
||||
mainForm.tbPassword.text = mainForm.reg.queryValue("password");
|
||||
}
|
||||
mainForm.ws.protocol = mainForm.tbPassword.text;
|
||||
if(mainForm.reg.queryValue("url"))
|
||||
{
|
||||
mainForm.tbUrl.text = mainForm.reg.queryValue("url");
|
||||
}
|
||||
mainForm.wsUrl = mainForm.tbUrl.text;
|
||||
mainForm.wsConnected = false;
|
||||
mainForm.running = true;
|
||||
mainForm.hashCode = 0;
|
||||
mainForm.routeContent = {List={}};
|
||||
|
||||
mainForm.routeList = {};
|
||||
mainForm.IP = mainForm.netObj.GetWsIP(mainForm.wsUrl);
|
||||
|
||||
mainForm.ws.onOpen = function(){
|
||||
mainForm.wsConnected = true;
|
||||
@@ -138,42 +145,29 @@ mainForm.ws.onError = function(err){
|
||||
mainForm.textStatus.text = "未连接服务";
|
||||
}
|
||||
|
||||
|
||||
mainForm.alreadyExists = function(ip,prefixLength){
|
||||
for(i=1;table.len(mainForm.ipv4);1){
|
||||
if(mainForm.netObj.GetIsSameNetwork(mainForm.ipv4[i],ip,prefixLength)){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
mainForm.addRoute = function(){
|
||||
for(i=1;table.len(mainForm.routeContent.List) ;1){
|
||||
var item = mainForm.routeContent.List[i];
|
||||
if(mainForm.alreadyExists(item.IP,item.PrefixLength) == false){
|
||||
process.popen.cmd("route add "+item.Network+" mask "+item.PrefixIP+" "+mainForm.routeContent.IP);
|
||||
//console.log("route add "+item.Network+" mask "+item.PrefixIP+" "+mainForm.routeContent.IP);
|
||||
}
|
||||
for(i=1;table.len(mainForm.routeList) ;1){
|
||||
item = mainForm.routeList[i];
|
||||
process.popen.cmd("route add "+item.Network+" mask "+item.PrefixIP+" "+mainForm.IP);
|
||||
}
|
||||
}
|
||||
mainForm.delRoute = function(){
|
||||
for(i=1;table.len(mainForm.routeContent.List) ;1){
|
||||
var item = mainForm.routeContent.List[i];
|
||||
//console.log("route delete "+item.Network+" mask "+item.PrefixIP+" "+mainForm.routeContent.IP);
|
||||
process.popen.cmd("route delete "+item.Network+" mask "+item.PrefixIP+" "+mainForm.routeContent.IP);
|
||||
for(i=1;table.len(mainForm.routeList) ;1){
|
||||
var item = mainForm.routeList[i];
|
||||
process.popen.cmd("route delete "+item.Network+" mask "+item.PrefixIP+" "+mainForm.IP);
|
||||
}
|
||||
}
|
||||
mainForm.sameRoute = function(content){
|
||||
mainForm.sameRoute = function(list){
|
||||
var same = true;
|
||||
if(content.List && table.len(content.List) > 0)
|
||||
if(list && table.len(list) > 0)
|
||||
{
|
||||
same = table.len(content.List) == table.len(mainForm.routeContent.List);
|
||||
same = table.len(list) == table.len(mainForm.routeList);
|
||||
if(same)
|
||||
{
|
||||
for(i=1;table.len(content.List) ;1)
|
||||
for(i=1;table.len(list) ;1)
|
||||
{
|
||||
same = content.List[i].IP == mainForm.routeContent.List[i].IP
|
||||
&& content.List[i].PrefixLength == mainForm.routeContent.List[i].PrefixLength;
|
||||
same = list[i].IP == mainForm.routeList[i].IP
|
||||
&& list[i].PrefixLength == mainForm.routeList[i].PrefixLength;
|
||||
if(!same)
|
||||
{
|
||||
break;
|
||||
@@ -185,12 +179,51 @@ mainForm.sameRoute = function(content){
|
||||
}
|
||||
|
||||
mainForm.ws.onMessage = function(msg){
|
||||
import console;
|
||||
try{
|
||||
var content = web.json.parse(msg.data).Content;
|
||||
var same = mainForm.sameRoute(content);
|
||||
content = web.json.parse(msg.data).Content;
|
||||
result = {};
|
||||
added = false;
|
||||
for(k,v in content.List){
|
||||
if(!added)
|
||||
{
|
||||
added = true;
|
||||
table.push(result,{
|
||||
IP:v.IP,
|
||||
PrefixLength = v.PrefixLength,
|
||||
Network:mainForm.netObj.ToNetwork(v.IP,v.PrefixLength),
|
||||
PrefixIP:mainForm.netObj.ToPrefixIP(v.PrefixLength)
|
||||
});
|
||||
}
|
||||
for(k1,v1 in v.Lans){
|
||||
if(!v1.Disabled && !v1.Exists)
|
||||
{
|
||||
if(v1.MapIP && v1.MapIP != "0.0.0.0")
|
||||
{
|
||||
table.push(result,{
|
||||
IP:v1.MapIP,
|
||||
PrefixLength = v1.MapPrefixLength,
|
||||
Network:mainForm.netObj.ToNetwork(v1.MapIP,v1.MapPrefixLength),
|
||||
PrefixIP:mainForm.netObj.ToPrefixIP(v1.MapPrefixLength)
|
||||
});
|
||||
}else
|
||||
{
|
||||
table.push(result,{
|
||||
IP:v1.IP,
|
||||
PrefixLength = v1.PrefixLength,
|
||||
Network:mainForm.netObj.ToNetwork(v1.IP,v1.PrefixLength),
|
||||
PrefixIP:mainForm.netObj.ToPrefixIP(v1.PrefixLength)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
var same = mainForm.sameRoute(result);
|
||||
if(!same){
|
||||
mainForm.delRoute();
|
||||
mainForm.routeContent = content;
|
||||
mainForm.routeList = result;
|
||||
mainForm.IP = mainForm.netObj.GetWsIP(mainForm.wsUrl);
|
||||
mainForm.addRoute();
|
||||
}
|
||||
}
|
||||
@@ -198,7 +231,6 @@ mainForm.ws.onMessage = function(msg){
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
mainForm.failureService = function()
|
||||
{
|
||||
import process.popen;
|
||||
@@ -277,7 +309,7 @@ mainForm.setInterval(
|
||||
}else
|
||||
{
|
||||
mainForm.ws.send(web.json.stringify({
|
||||
Path: "tuntapclient/routeitems",
|
||||
Path: "tuntap/get",
|
||||
RequestId: 0,
|
||||
Content:mainForm.hashCode+""
|
||||
}));
|
||||
|
@@ -8,102 +8,30 @@ namespace LinkerRoute
|
||||
{
|
||||
public class LinkerRoute
|
||||
{
|
||||
public string[] GetIPV4(string server)
|
||||
public string GetWsIP(string wsServer)
|
||||
{
|
||||
List<string> result = new List<string>();
|
||||
var ips1 = GetRouteLevel(server);
|
||||
var ips2 = GetIPV4();
|
||||
|
||||
foreach (var ip in ips1)
|
||||
{
|
||||
if (result.Contains(ip) == false)
|
||||
{
|
||||
result.Add(ip);
|
||||
}
|
||||
}
|
||||
foreach (var ip in ips2)
|
||||
{
|
||||
if (result.Contains(ip) == false)
|
||||
{
|
||||
result.Add(ip);
|
||||
}
|
||||
}
|
||||
return result.ToArray();
|
||||
return new Uri(wsServer).Host;
|
||||
}
|
||||
|
||||
|
||||
private string[] starts = new string[] { "10.", "100.", "192.168.", "172.", "127." };
|
||||
private string[] GetRouteLevel(string server)
|
||||
public string ToNetwork(string ip, byte prefixLength)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(server) == false)
|
||||
{
|
||||
server = server.Split(':')[0];
|
||||
}
|
||||
var ips = GetRouteLevelWindows(server);
|
||||
|
||||
string[] result = new string[ips.Length];
|
||||
for (int i = 0; i < ips.Length; i++)
|
||||
{
|
||||
result[i] = ips[i].ToString();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
private IPAddress[] GetRouteLevelWindows(string server)
|
||||
{
|
||||
List<IPAddress> result = new List<IPAddress>();
|
||||
try
|
||||
{
|
||||
IPAddress target = Dns.GetHostEntry(server).AddressList[0];
|
||||
|
||||
for (ushort i = 1; i <= 5; i++)
|
||||
{
|
||||
using (Ping pinger = new Ping())
|
||||
{
|
||||
PingReply reply = pinger.Send(target, 100, Encoding.ASCII.GetBytes("snltty"), new PingOptions { Ttl = i, DontFragment = true });
|
||||
|
||||
|
||||
bool any = false;
|
||||
string ip = reply.Address.ToString();
|
||||
for (int k = 0; k < starts.Length; k++)
|
||||
{
|
||||
if (ip.IndexOf(starts[k]) == 0)
|
||||
{
|
||||
any = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (any)
|
||||
{
|
||||
result.Add(reply.Address);
|
||||
}
|
||||
else
|
||||
{
|
||||
return result.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
return result.ToArray();
|
||||
}
|
||||
|
||||
public bool GetIsSameNetwork(string sourceIP, string distIP, byte prefixLength)
|
||||
{
|
||||
byte[] sourceBytes = IPAddress.Parse(sourceIP).GetAddressBytes();
|
||||
byte[] sourceBytes = IPAddress.Parse(ip).GetAddressBytes();
|
||||
Array.Reverse(sourceBytes);
|
||||
|
||||
byte[] distBytes = IPAddress.Parse(distIP).GetAddressBytes();
|
||||
Array.Reverse(distBytes);
|
||||
|
||||
uint sourceIPInt = BitConverter.ToUInt32(sourceBytes, 0);
|
||||
uint distIPInt = BitConverter.ToUInt32(distBytes, 0);
|
||||
|
||||
uint prefixIP = GetPrefixIP(prefixLength);
|
||||
|
||||
return (sourceIPInt & prefixIP) == (distIPInt & prefixIP);
|
||||
sourceBytes = new IPAddress((sourceIPInt & prefixIP)).GetAddressBytes();
|
||||
Array.Reverse(sourceBytes);
|
||||
return string.Join(".",sourceBytes);
|
||||
}
|
||||
public string ToPrefixIP(byte prefixLength)
|
||||
{
|
||||
uint prefixIP = GetPrefixIP(prefixLength);
|
||||
byte[] sourceBytes = new IPAddress(prefixIP).GetAddressBytes();
|
||||
Array.Reverse(sourceBytes);
|
||||
return string.Join(".",sourceBytes);
|
||||
}
|
||||
private uint GetPrefixIP(byte prefixLength)
|
||||
{
|
||||
@@ -111,28 +39,5 @@ namespace LinkerRoute
|
||||
if (prefixLength < 1) return 0;
|
||||
return 0xffffffff << (32 - prefixLength);
|
||||
}
|
||||
|
||||
private string[] GetIPV4()
|
||||
{
|
||||
try
|
||||
{
|
||||
List<string> result = new List<string>();
|
||||
foreach (var item in Dns.GetHostEntry(Dns.GetHostName()).AddressList)
|
||||
{
|
||||
if (item.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork && item.IsIPv4MappedToIPv6 == false && item.Equals(IPAddress.Any) == false)
|
||||
{
|
||||
if (result.Contains(item.ToString()) == false)
|
||||
{
|
||||
result.Add(item.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.ToArray();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
return Array.Empty<string>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -211,7 +211,7 @@ namespace linker.tun
|
||||
{
|
||||
return;
|
||||
}
|
||||
error = $"NetNat and ICS not supported,{error}";
|
||||
error = $"NetNat not supported,{error}";
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
@@ -2,6 +2,7 @@
|
||||
using System.ServiceProcess;
|
||||
using System.Diagnostics;
|
||||
using linker.messenger.entry;
|
||||
using linker.libs.extends;
|
||||
|
||||
namespace linker
|
||||
{
|
||||
@@ -66,33 +67,12 @@ namespace linker
|
||||
private static Dictionary<string, string> ParseArgs(string[] args)
|
||||
{
|
||||
Dictionary<string, string> configDic = new Dictionary<string, string>();
|
||||
for (int i = 0; i < args.Length; i++)
|
||||
try
|
||||
{
|
||||
configDic = args[0].DeJson<Dictionary<string, string>>();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
if (args[i] == "--config-client")
|
||||
{
|
||||
configDic.Add("Client", args[i + 1]);
|
||||
i++;
|
||||
}
|
||||
else if (args[i] == "--config-server")
|
||||
{
|
||||
configDic.Add("Server", args[i + 1]);
|
||||
i++;
|
||||
}
|
||||
else if (args[i] == "--config-action")
|
||||
{
|
||||
configDic.Add("Action", args[i + 1]);
|
||||
i++;
|
||||
}
|
||||
else if (args[i] == "--config-common")
|
||||
{
|
||||
configDic.Add("Common", args[i + 1]);
|
||||
i++;
|
||||
}
|
||||
else if (args[i] == "--config-tuntap")
|
||||
{
|
||||
configDic.Add("Tuntap", args[i + 1]);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return configDic;
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
v1.7.6
|
||||
2025-04-28 16:23:59
|
||||
2025-04-29 16:22:40
|
||||
1. 一些优化
|
||||
2. 安卓APP勉强能用,支持分身,下拉刷新,在线升级
|
||||
5. 如果你设备很多,请尝试升级其中一个成功重启后再升级其它
|
Reference in New Issue
Block a user