This commit is contained in:
snltty
2025-03-11 21:12:45 +08:00
parent 56e5957fcf
commit 244ebe99c3
34 changed files with 484 additions and 298 deletions

View File

@@ -35,7 +35,7 @@ jobs:
release_name: v1.6.9.${{ steps.date.outputs.today }}
draft: false
prerelease: false
body: "1. 优化linux下路由跟踪问题\r\n2. 优化linux下获取本机IP问题\r\n3. 增加ICS让win7+、win server2008+支持NAT\r\n4. 增加中继cdkey使用cdkey解锁公开中继节点的带宽、流量、连接数限制\r\n5. 增加内外穿透定时开关功能\r\n6. 优化管理页面连接接口的体验\r\n7. 优化一些UI体验去除同步页面将同步功能放至各个实际的位置\r\n8. 优化端口转发,让不同分组间可以使用相同端口\r\n9. 其它一些修复优化"
body: "1. 优化linux下路由跟踪问题,提高启动速度\r\n2. 优化linux下获取本机IP问题,提升虚拟网卡稳定性\r\n3. 增加ICS让win7+、win server2008+支持NAT\r\n4. 增加中继cdkey使用cdkey解锁公开中继节点的带宽、流量、连接数限制\r\n5. 增加内外穿透定时开关功能\r\n6. 优化管理页面连接接口的体验\r\n7. 优化一些UI体验去除同步页面将同步功能放至各个实际的位置\r\n8. 优化端口转发,让不同分组间可以使用相同端口\r\n9. 从命令行参数初始化配置\r\n10. 优化打洞IPV6支持的更多了\r\n11. 其它一些修复优化"
- name: publish projects
run: ./publish.bat
- name: upload-win-x86-oss
@@ -218,46 +218,6 @@ jobs:
asset_path: ./public/publish-zip/linker-linux-musl-arm64.zip
asset_name: linker-linux-musl-arm64.zip
asset_content_type: application/zip
- name: upload-osx-x64-oss
id: upload-osx-x64-oss
uses: tvrcgo/oss-action@v0.1.1
with:
region: oss-cn-shenzhen
key-id: ${{ secrets.ALIYUN_OSS_ID }}
key-secret: ${{ secrets.ALIYUN_OSS_SECRET }}
bucket: ide-qbcode
asset-path: ./public/publish-zip/linker-osx-x64.zip
target-path: /downloads/linker/v1.6.9/linker-osx-x64.zip
- name: upload-osx-x64
id: upload-osx-x64
uses: actions/upload-release-asset@master
env:
GITHUB_TOKEN: ${{ secrets.ACTIONS_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./public/publish-zip/linker-osx-x64.zip
asset_name: linker-osx-x64.zip
asset_content_type: application/zip
- name: upload-osx-arm64-oss
id: upload-osx-arm64-oss
uses: tvrcgo/oss-action@v0.1.1
with:
region: oss-cn-shenzhen
key-id: ${{ secrets.ALIYUN_OSS_ID }}
key-secret: ${{ secrets.ALIYUN_OSS_SECRET }}
bucket: ide-qbcode
asset-path: ./public/publish-zip/linker-osx-arm64.zip
target-path: /downloads/linker/v1.6.9/linker-osx-arm64.zip
- name: upload-osx-arm64
id: upload-osx-arm64
uses: actions/upload-release-asset@master
env:
GITHUB_TOKEN: ${{ secrets.ACTIONS_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./public/publish-zip/linker-osx-arm64.zip
asset_name: linker-osx-arm64.zip
asset_content_type: application/zip
- name: upload-version-oss
id: upload-version-oss
uses: tvrcgo/oss-action@v0.1.1

View File

@@ -50,8 +50,7 @@ function writeUpload(data, tagName) {
const platforms = {
'win': ['x86', 'x64', 'arm64'],
'linux': ['x64', 'arm', 'arm64'],
'linux-musl': ['x64', 'arm', 'arm64'],
'osx': ['x64', 'arm64'],
'linux-musl': ['x64', 'arm', 'arm64']
};
for (let plat in platforms) {
let archs = platforms[plat];

View File

@@ -30,7 +30,7 @@ del /f .\public\extends\win-arm64\linker-win-arm64\linker.ics.pdb
msbuild "src\\linker.ics\\linker.ics.csproj" -p:Configuration=Release -p:OutputPath=../../public/extends/win-x86/linker-win-x86
del /f .\public\extends\win-x86\linker-win-x86\linker.ics.pdb
for %%r in (win-x86,win-x64,win-arm64,linux-x64,linux-arm,linux-arm64,linux-musl-x64,linux-musl-arm,linux-musl-arm64,osx-x64,osx-arm64) do (
for %%r in (win-x86,win-x64,win-arm64,linux-x64,linux-arm,linux-arm64,linux-musl-x64,linux-musl-arm,linux-musl-arm64) do (
dotnet publish ./src/linker -c release -f net8.0 -o ./public/publish/%%r/linker-%%r -r %%r -p:PublishSingleFile=true --self-contained true -p:TrimMode=partial -p:TieredPGO=true -p:DebugType=full -p:EventSourceSupport=false -p:DebugSymbols=true -p:EnableCompressionInSingleFile=true -p:DebuggerSupport=false -p:EnableUnsafeBinaryFormatterSerialization=false -p:EnableUnsafeUTF7Encoding=false -p:HttpActivityPropagationSupport=false -p:InvariantGlobalization=true -p:MetadataUpdaterSupport=false -p:UseSystemResourceKeys=true -p:MetricsSupport=false -p:StackTraceSupport=false -p:XmlResolverIsNetworkingEnabledByDefault=false
echo F|xcopy "public\\extends\\%%r\\linker-%%r\\*" "public\\publish\\%%r\\linker-%%r\\*" /s /f /h /y

View File

@@ -1,4 +1,8 @@
namespace linker.app
using Microsoft.Maui.Controls.PlatformConfiguration;
using System.Diagnostics;
using System.Net.NetworkInformation;
namespace linker.app
{
public partial class MainPage : ContentPage
{
@@ -19,6 +23,7 @@
CounterBtn.Text = $"Clicked {count} times";
SemanticScreenReader.Announce(CounterBtn.Text);
}
}

View File

@@ -4,6 +4,7 @@ using Android.Content;
using Android.Content.PM;
using Android.Health.Connect.DataTypes.Units;
using Android.Net;
using Android.Nfc;
using Android.OS;
using Android.Views;
using AndroidX.Core.App;
@@ -35,6 +36,8 @@ namespace linker.app
StartActivityForResult(intent, 0);
}
StartForegroundService(new Intent(this, typeof(VpnServiceLinker)));
}
protected override void OnStart()
@@ -77,6 +80,13 @@ namespace linker.app
if (vpnInterface != null)
{
Android.Util.Log.Error(TAG, "==============================================VPN is connected");
/*
Task.Run(async () =>
{
});
*/
/*
Task.Run(async () =>
{

View File

@@ -7,6 +7,7 @@ sidebar_position: 3
## 1、公共配置文件客户端服务端都有的
:::tip[服务端运行流程]
common.json
```
{
//运行在哪个模式下,多个模式可同时存在
@@ -41,24 +42,20 @@ sidebar_position: 3
4. 修改server.json可以去在线生成一些GUID作为各个功能的密钥
5. 再次运行程序
common.json
```
{
"Modes": ["server"]
}
```
server.json
```
{
//中继
"Relay": {
//中继密钥,客户端密钥不准确时无法使用本中继
"SecretKey": ""
"SecretKey": "",
"Cdkey": {
//cdkey 加密密钥
"SecretKey": "snltty"
},
},
//信标服务器端口
"ServicePort": 1802,
//内网穿透配置
"SForward": {
//内网穿透密钥
@@ -82,6 +79,14 @@ server.json
}
}
```
action.json
```
{
"SignInActionUrl": "", //登入信标的验证接口
"RelayActionUrl": "", //中继验证接口
"SForwardActionUrl": ""//服务器穿透的验证接口
}
```
:::
## 3、客户端使用web初始化
@@ -93,6 +98,63 @@ server.json
![](./img/mode.png)
![](./img/client.png)
![](./img/save.png)
对应配置文件 client.json
```
{
"Name": "A", //客户端名
"Access": 4503599627370495, //权限值,可以看`src/linker.messenger.api/Config.cs`里的`AccessValue`枚举
"CApi": {
"ApiPort": 1803, //api接口
"ApiPassword": "snltty", //api密码
"WebPort": 1804, //web端口
"WebRoot": "./web/" //web根目录
},
"Servers": [
{
"Name": "Linker", //信标服务器名称
"Host": "127.0.0.1:1802", //信标服务器地址
"SecretKey": null, //信标密钥
"UserId": "8225e9d4-0ac7-4d76-9946-c4fe04ad4696" //用户标识,多个客户端可相同
}
],
"Groups": [
{
"Name": "snltty", //分组名
"Id": "snltty", //分组id
"Password": "snltty" //分组密码
}
],
"Relay": {
"Servers": [
{
"SecretKey": "snltty", //中继密钥
"Disabled": false, //是否禁用
"SSL": true //启用ssl
}
]
},
"SForward": {
"SecretKey": "snltty" //服务器穿透密钥
},
"Updater": {
"SecretKey": "snltty" //更新密钥
},
"Action": {
"Args": {} //自定义验证的参数
}
}
```
:::
## 4、使用参数初始化
:::tip[v1.7.0+]
1. 如果你使用第三方程序启动linker`仅配置文件不存在时初始化,后续不会覆盖`,可以传入参数进行初始化,`client.json``server.json``action.json``common.json`
2. 像这样不填写的字段将以默认值生成json的双引号需要转义json里不能有空格
```
linker.exe --config-client {\"a\":\"1\"} --config-server {\"a\":\"1\"} --config-action {\"a\":\"1\"} --config-common {\"a\":\"1\"}
```
:::

View File

@@ -0,0 +1,149 @@
---
sidebar_position: 9
---
# 8.9、中继CDKEY
:::tip[v1.7.0+]
在哪里发卡都可以可以自己开发卡密商城只要最后按一定的字段和加密方式生成cdkey就可以导入使用
:::
### 1、CDKEY参数字段
:::tip[说明]
```
{
"GB":100, //流量GB
"Speed":100, //带宽 Mbps
"Time":"1-0-0 0:0:0", //持续时间 年-月-日 时:分:秒
"WidgetUserId":"2b9c9fef-c342-c968-9dc0-c15e3bc23646",//用户标识
"OrderId":"ACG1234567890", //订单号
"Contact":"111@qq.com", //联系方式
"CostPrice":1, //成本元 double
"Price":1, //原价元 double
"UserPrice":1, //会员价元 double
"PayPrice":1, //支付金额元 double
"Count":1, //数量,导入后,会 GB*Count
"Type":"Relay", //类型 固定 Relay
}
```
:::
### 2、加密方式AES-128-ECB
:::tip[说明]
1. C#样例
```
AesCrypto crypto = new AesCrypto("加密密钥", System.Security.Cryptography.PaddingMode.PKCS7);
//加密
byte[] bytes = crypto.Encode(jsonString);
string cdkey = Convert.ToBase64String(bytes);
public sealed class AesCrypto : ISymmetricCrypto
{
private ICryptoTransform encryptoTransform;
private ICryptoTransform decryptoTransform;
public string Password { get; set; }
public AesCrypto(string password, PaddingMode mode = PaddingMode.ANSIX923)
{
Password = password;
using Aes aes = Aes.Create();
aes.Padding = mode;
(aes.Key, aes.IV) = GenerateKeyAndIV(password);
encryptoTransform = aes.CreateEncryptor(aes.Key, aes.IV);
decryptoTransform = aes.CreateDecryptor(aes.Key, aes.IV);
}
public byte[] Encode(byte[] buffer)
{
return Encode(buffer, 0, buffer.Length);
}
public byte[] Encode(byte[] buffer, int offset, int length)
{
return encryptoTransform.TransformFinalBlock(buffer, offset, length);
}
public Memory<byte> Decode(byte[] buffer)
{
return Decode(buffer, 0, buffer.Length);
}
public Memory<byte> Decode(byte[] buffer, int offset, int length)
{
return decryptoTransform.TransformFinalBlock(buffer, offset, length);
}
public void Dispose()
{
encryptoTransform.Dispose();
decryptoTransform.Dispose();
}
private (byte[] Key, byte[] IV) GenerateKeyAndIV(string password)
{
byte[] key = new byte[16];
byte[] iv = new byte[16];
using SHA384 sha = SHA384.Create();
byte[] hash = sha.ComputeHash(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);
}
}
```
2. PHP样例
```
//加密
$aesCrypto = new AesCrypto("加密密钥");
$cdkey = base64_encode($aesCrypto->encode($jsonString));
class AesCrypto
{
private $key;
private $iv;
private $password;
public function __construct($password)
{
$this->password = $password;
$this->initAes();
}
private function initAes()
{
$keyAndIV = $this->generateKeyAndIV($this->password);
$this->key = $keyAndIV['key'];
$this->iv = $keyAndIV['iv'];
}
public function encode($data)
{
return $this->encodeWithOffset($data, 0, strlen($data));
}
public function encodeWithOffset($data, $offset, $length)
{
$data = substr($data, $offset, $length);
return openssl_encrypt($data, 'AES-128-CBC', $this->key, OPENSSL_RAW_DATA, $this->iv);
}
public function decode($data)
{
return $this->decodeWithOffset($data, 0, strlen($data));
}
public function decodeWithOffset($data, $offset, $length)
{
$data = substr($data, $offset, $length);
return openssl_decrypt($data, 'AES-128-CBC', $this->key, OPENSSL_RAW_DATA, $this->iv);
}
private function generateKeyAndIV($password)
{
$hash = hash('sha384', $password, true);
$key = substr($hash, 0, 16);
$iv = substr($hash, 16, 16);
return ['key' => $key, 'iv' => $iv];
}
}
```
:::

View File

@@ -1,7 +1,7 @@
---
sidebar_position: 10
sidebar_position: 9
---
# 10、公益赞助
# 9、公益赞助
![Docusaurus Plushie](./img/qr.jpg)

View File

@@ -1,74 +0,0 @@
---
sidebar_position: 9
---
# 9、收费项目
<table width="100%">
<thead>
<tr>
<th>Linker</th>
<th>2设备内</th>
<th>2-5设备</th>
<th>5-10设备</th>
<th>10设备以上</th>
<th>权益</th>
</tr>
</thead>
<tbody>
<tr>
<td>使用</td>
<td>免费</td>
<td>免费</td>
<td>免费</td>
<td>免费</td>
<td>/</td>
</tr>
<tr>
<td>开源集成</td>
<td>免费</td>
<td>免费</td>
<td>免费</td>
<td>免费</td>
<td>/</td>
</tr>
<tr>
<td>安装配置维护/次</td>
<td>20/次</td>
<td>50/次</td>
<td>100/次</td>
<td>10/台/次</td>
<td>私有化部署、配置、BUG修复</td>
</tr>
<tr>
<td>安装配置维护/年</td>
<td>99/年</td>
<td>239/年</td>
<td>399/年</td>
<td>29/台/年</td>
<td>私有化部署、配置、BUG修复、技术解答</td>
</tr>
<tr>
<td>商业集成</td>
<td colspan="5" align="center">详谈,技术解答,原理讲解,二开指导</td>
</tr>
<tr>
<td>功能定制</td>
<td colspan="5" align="center">详谈,技术解答,原理讲解,二开指导</td>
</tr>
</tbody>
</table>
<table width="100%">
<thead>
<tr>
<th>证书</th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td>3个月泛域名证书</td>
<td align="center">9.9/个</td>
</tr>
</tbody>
</table>

View File

@@ -73,6 +73,10 @@ namespace linker.libs
}
Enqueue(new LoggerModel { Type = LoggerTypes.WARNING, Content = content });
}
public void Warning(Exception ex)
{
Enqueue(new LoggerModel { Type = LoggerTypes.WARNING, Content = ex + "" });
}
public void Error(string content, params object[] args)
{
if (args != null && args.Length > 0)

View File

@@ -42,6 +42,15 @@ namespace linker.libs
public static class NetworkHelper
{
public static IPEndPoint TransEndpointFamily(IPEndPoint ep)
{
if (ep.Address.AddressFamily == AddressFamily.InterNetworkV6 && ep.Address.IsIPv4MappedToIPv6)
{
return new IPEndPoint(new IPAddress(ep.Address.GetAddressBytes()[^4..]), ep.Port);
}
return ep;
}
/// <summary>
/// 域名解析
@@ -217,7 +226,9 @@ namespace linker.libs
{
return GetIP()
.Where(c => c.AddressFamily == AddressFamily.InterNetworkV6)
.Where(c => c.GetAddressBytes().AsSpan(0, 8).SequenceEqual(ipv6LocalBytes) == false).Distinct().ToArray(); ;
.Where(c => c.GetAddressBytes().AsSpan(0, 8).SequenceEqual(ipv6LocalBytes) == false)
.Where(c=>c.Equals(IPAddress.IPv6Loopback) == false)
.Distinct().ToArray();
}
public static IPAddress[] GetIPV4()
{

View File

@@ -18,6 +18,7 @@ using linker.messenger.updater;
using linker.messenger.store.file;
using linker.messenger.serializer.memorypack;
using linker.libs;
using linker.libs.extends;
namespace linker.messenger.entry
{
@@ -29,6 +30,11 @@ namespace linker.messenger.entry
private static OperatingManager builded = new OperatingManager();
private static OperatingManager setuped = new OperatingManager();
public static void InputJsonConfig(string str)
{
Console.WriteLine(str.DeJson<ConfigClientInfo>().ToJsonFormat());
}
/// <summary>
/// 开始初始化
/// </summary>
@@ -76,7 +82,7 @@ namespace linker.messenger.entry
.AddTuntapClient().AddTuntapServer()
//更新
.AddUpdaterClient().AddUpdaterServer()
//信标
.AddMessenger()
//流量统计
@@ -131,7 +137,7 @@ namespace linker.messenger.entry
/// 开始运行
/// </summary>
/// <param name="modules">排除哪些模块,默认无</param>
public static void Setup(ExcludeModule modules = ExcludeModule.None)
public static void Setup(ExcludeModule modules = ExcludeModule.None, Dictionary<string, string> configDic = null)
{
if (setuped.StartOperation() == false) return;
@@ -139,7 +145,7 @@ namespace linker.messenger.entry
serviceProvider.UseMessenger();
if ((modules & ExcludeModule.StoreFile) != ExcludeModule.StoreFile)
serviceProvider.UseStoreFile();
serviceProvider.UseStoreFile(configDic);
if ((modules & ExcludeModule.SerializerMemoryPack) != ExcludeModule.SerializerMemoryPack)
serviceProvider.UseSerializerMemoryPack();

View File

@@ -96,7 +96,7 @@ namespace linker.messenger.relay.client.transport
Stream = sslStream,
Socket = socket,
Mode = TunnelMode.Client,
IPEndPoint = socket.RemoteEndPoint as IPEndPoint,
IPEndPoint = NetworkHelper.TransEndpointFamily(socket.RemoteEndPoint as IPEndPoint),
TransactionId = relayInfo.TransactionId,
TransportName = Name,
Type = TunnelType.Relay,
@@ -286,7 +286,7 @@ namespace linker.messenger.relay.client.transport
Stream = sslStream,
Socket = socket,
Mode = TunnelMode.Server,
IPEndPoint = socket.RemoteEndPoint as IPEndPoint,
IPEndPoint = NetworkHelper.TransEndpointFamily(socket.RemoteEndPoint as IPEndPoint),
TransactionId = relayInfo.TransactionId,
TransportName = Name,
Type = TunnelType.Relay,

View File

@@ -6,6 +6,7 @@ using linker.messenger.relay.server;
using linker.messenger.signin;
using linker.messenger.relay.server.validator;
using linker.libs.extends;
using System.Collections.Generic;
namespace linker.messenger.relay.messenger
{
@@ -73,6 +74,7 @@ namespace linker.messenger.relay.messenger
await RelayTest(connection, info, (validated) =>
{
List<RelayServerNodeReportInfo> list = relayServerTransfer.GetNodes(validated).Select(c => (RelayServerNodeReportInfo)c).ToList();
return serializer.Serialize(list);
});
}
@@ -264,10 +266,6 @@ namespace linker.messenger.relay.messenger
public void NodeReport(IConnection connection)
{
RelayServerNodeReportInfo170 info = serializer.Deserialize<RelayServerNodeReportInfo170>(connection.ReceiveRequestWrap.Payload.Span);
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
{
LoggerHelper.Instance.Debug($"relay node report : {info.ToJson()}");
}
relayServerTransfer.SetNodeReport(connection, info);
}
/// <summary>
@@ -279,10 +277,7 @@ namespace linker.messenger.relay.messenger
public void UpdateNode(IConnection connection)
{
RelayServerNodeUpdateInfo info = serializer.Deserialize<RelayServerNodeUpdateInfo>(connection.ReceiveRequestWrap.Payload.Span);
if (relayServerNodeTransfer.Id == info.Id)
{
relayServerNodeTransfer.UpdateNode(info);
}
relayServerNodeTransfer.UpdateNode(info);
}
/// <summary>
/// 更新节点转发

View File

@@ -45,8 +45,6 @@ namespace linker.messenger.relay.server
public sealed class RelayServerNodeInfo
{
public const string MASTER_NODE_ID = "824777CF-2804-83FE-DE71-69B7B7D3BBA7";
private string id = Guid.NewGuid().ToString().ToUpper();
public string Id
{

View File

@@ -1,4 +1,5 @@
using linker.libs;
using linker.libs.extends;
using linker.messenger.relay.messenger;
using linker.messenger.relay.server.caching;
using System.Collections.Concurrent;
@@ -66,17 +67,23 @@ namespace linker.messenger.relay.server
{
try
{
if (info.Id == RelayServerNodeInfo.MASTER_NODE_ID)
{
info.EndPoint = new IPEndPoint(IPAddress.Any, 0);
}
else if (info.EndPoint.Address.Equals(IPAddress.Any))
if (info.EndPoint.Address.Equals(IPAddress.Any))
{
info.EndPoint.Address = connection.Address.Address;
}
if (info.EndPoint.Address.Equals(IPAddress.Loopback))
{
info.EndPoint = new IPEndPoint(IPAddress.Any, 0);
}
info.LastTicks = Environment.TickCount64;
info.Connection = connection;
reports.AddOrUpdate(info.Id, info, (a, b) => info);
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
{
LoggerHelper.Instance.Debug($"relay node report : {info.ToJson()}");
}
}
catch (Exception ex)
{
@@ -92,8 +99,6 @@ namespace linker.messenger.relay.server
/// <param name="info"></param>
public async Task UpdateNodeReport(RelayServerNodeUpdateInfo info)
{
if (RelayServerNodeInfo.MASTER_NODE_ID == info.Id) return;
if (reports.TryGetValue(info.Id, out RelayServerNodeReportInfo170 cache))
{
await messengerSender.SendOnly(new MessageRequestWrap
@@ -143,7 +148,7 @@ namespace linker.messenger.relay.server
/// </summary>
/// <param name="relayTrafficUpdateInfo"></param>
/// <returns></returns>
public void AddTraffic(Dictionary<long,long> dic)
public void AddTraffic(Dictionary<long, long> dic)
{
if (dic.Count > 0)
trafficQueue.Enqueue(dic);

View File

@@ -13,11 +13,13 @@ namespace linker.messenger.relay.server
/// </summary>
public class RelayServerNodeTransfer
{
public string Id => relayServerNodeStore.Node.Id;
/// <summary>
/// 配置了就用配置的,每配置就用一个默认的
/// </summary>
public RelayServerNodeInfo node = null;
private uint connectionNum = 0;
private IConnection localConnection;
private IConnection remoteConnection;
private IConnection connection;
private long bytes = 0;
private long lastBytes = 0;
@@ -38,7 +40,23 @@ namespace linker.messenger.relay.server
this.messengerResolver = messengerResolver;
this.messengerSender = messengerSender;
limitTotal.SetLimit((uint)Math.Ceiling((relayServerNodeStore.Node.MaxBandwidthTotal * 1024 * 1024) / 8.0));
node = string.IsNullOrWhiteSpace(relayServerNodeStore.Node.MasterHost) ? new RelayServerNodeInfo
{
Id = "824777CF-2804-83FE-DE71-69B7B7D3BBA7",
Host = new IPEndPoint(IPAddress.Any, relayServerNodeStore.ServicePort).ToString(),
MasterHost = new IPEndPoint(IPAddress.Loopback, relayServerNodeStore.ServicePort).ToString(),
MasterSecretKey = relayServerMasterStore.Master.SecretKey,
MaxBandwidth = 0,
MaxConnection = 0,
MaxBandwidthTotal = 0,
MaxGbTotal = 0,
MaxGbTotalLastBytes = 0,
MaxGbTotalMonth = 0,
Name = "default",
Public = false,
} : relayServerNodeStore.Node;
limitTotal.SetLimit((uint)Math.Ceiling((node.MaxBandwidthTotal * 1024 * 1024) / 8.0));
TrafficTask();
ReportTask();
@@ -46,12 +64,10 @@ namespace linker.messenger.relay.server
}
public async ValueTask<RelayCacheInfo> TryGetRelayCache(string key, string nodeid)
public async ValueTask<RelayCacheInfo> TryGetRelayCache(string key)
{
try
{
IConnection connection = relayServerNodeStore.Node.Id == RelayServerNodeInfo.MASTER_NODE_ID ? localConnection : remoteConnection;
MessageResponeInfo resp = await messengerSender.SendReply(new MessageRequestWrap
{
Connection = connection,
@@ -73,7 +89,8 @@ namespace linker.messenger.relay.server
public void UpdateNode(RelayServerNodeUpdateInfo info)
{
relayServerNodeStore.UpdateInfo(info);
if (info.Id == node.Id)
relayServerNodeStore.UpdateInfo(info);
}
/// <summary>
@@ -84,6 +101,7 @@ namespace linker.messenger.relay.server
{
//已认证的没有流量限制
if (relayCache.Validated) return true;
if (node.Public == false) return false;
//流量卡有的,就能继续用
if (relayCache.Cdkey.Any(c => c.LastBytes > 0)) return true;
@@ -95,9 +113,9 @@ namespace linker.messenger.relay.server
/// <returns></returns>
private bool ValidateConnection(RelayCacheInfo relayCache)
{
bool res = relayServerNodeStore.Node.MaxConnection == 0 || relayServerNodeStore.Node.MaxConnection * 2 > connectionNum;
bool res = node.MaxConnection == 0 || node.MaxConnection * 2 > connectionNum;
if (res == false && LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
LoggerHelper.Instance.Debug($"relay ValidateConnection false,{connectionNum}/{relayServerNodeStore.Node.MaxConnection * 2}");
LoggerHelper.Instance.Debug($"relay ValidateConnection false,{connectionNum}/{node.MaxConnection * 2}");
return res;
}
@@ -107,11 +125,11 @@ namespace linker.messenger.relay.server
/// <returns></returns>
private bool ValidateBytes(RelayCacheInfo relayCache)
{
bool res = relayServerNodeStore.Node.MaxGbTotal == 0
|| (relayServerNodeStore.Node.MaxGbTotal > 0 && relayServerNodeStore.Node.MaxGbTotalLastBytes > 0);
bool res = node.MaxGbTotal == 0
|| (node.MaxGbTotal > 0 && node.MaxGbTotalLastBytes > 0);
if (res == false && LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
LoggerHelper.Instance.Debug($"relay ValidateBytes false,{relayServerNodeStore.Node.MaxGbTotalLastBytes}bytes/{relayServerNodeStore.Node.MaxGbTotal}gb");
LoggerHelper.Instance.Debug($"relay ValidateBytes false,{node.MaxGbTotalLastBytes}bytes/{node.MaxGbTotal}gb");
return res;
}
@@ -181,14 +199,14 @@ namespace linker.messenger.relay.server
//验证过的,不消耗流量
if (cache.Cache.Validated) return true;
//节点无流量限制的,不消耗流量
if (relayServerNodeStore.Node.MaxGbTotal == 0) return true;
if (node.MaxGbTotal == 0) return true;
Interlocked.Add(ref cache.Sendt, length);
var current = cache.CurrentCdkey;
if (current != null) return current.LastBytes > 0;
return relayServerNodeStore.Node.MaxGbTotalLastBytes > 0;
return node.MaxGbTotalLastBytes > 0;
}
/// <summary>
@@ -198,7 +216,7 @@ namespace linker.messenger.relay.server
private void SetLimit(RelayTrafficCacheInfo relayCache)
{
//无限制
if (relayCache.Cache.Validated || relayServerNodeStore.Node.MaxBandwidth == 0)
if (relayCache.Cache.Validated || node.MaxBandwidth == 0)
{
relayCache.Limit.SetLimit(0);
return;
@@ -206,14 +224,14 @@ namespace linker.messenger.relay.server
RelayServerCdkeyInfo currentCdkey = relayCache.Cache.Cdkey.Where(c => c.LastBytes > 0).OrderByDescending(c => c.Bandwidth).FirstOrDefault();
//有cdkey且带宽大于节点带宽就用cdkey的带宽
if (currentCdkey != null && (currentCdkey.Bandwidth == 0 || currentCdkey.Bandwidth >= relayServerNodeStore.Node.MaxBandwidth || relayServerNodeStore.Node.MaxGbTotalLastBytes == 0))
if (currentCdkey != null && (currentCdkey.Bandwidth == 0 || currentCdkey.Bandwidth >= node.MaxBandwidth || node.MaxGbTotalLastBytes == 0))
{
relayCache.CurrentCdkey = currentCdkey;
relayCache.Limit.SetLimit((uint)Math.Ceiling((relayCache.CurrentCdkey.Bandwidth * 1024 * 1024) / 8.0));
return;
}
relayCache.CurrentCdkey = null;
relayCache.Limit.SetLimit((uint)Math.Ceiling((relayServerNodeStore.Node.MaxBandwidth * 1024 * 1024) / 8.0));
relayCache.Limit.SetLimit((uint)Math.Ceiling((node.MaxBandwidth * 1024 * 1024) / 8.0));
}
/// <summary>
@@ -236,18 +254,20 @@ namespace linker.messenger.relay.server
}
private void ResetNodeBytes()
{
if (node.MaxGbTotal == 0) return;
foreach (var cache in trafficDict.Values.Where(c => c.CurrentCdkey == null))
{
long length = Interlocked.Exchange(ref cache.Sendt, 0);
if (relayServerNodeStore.Node.MaxGbTotalLastBytes >= length)
relayServerNodeStore.SetMaxGbTotalLastBytes(relayServerNodeStore.Node.MaxGbTotalLastBytes - length);
if (node.MaxGbTotalLastBytes >= length)
relayServerNodeStore.SetMaxGbTotalLastBytes(node.MaxGbTotalLastBytes - length);
else relayServerNodeStore.SetMaxGbTotalLastBytes(0);
}
if (relayServerNodeStore.Node.MaxGbTotalMonth != DateTime.Now.Month)
if (node.MaxGbTotalMonth != DateTime.Now.Month)
{
relayServerNodeStore.SetMaxGbTotalMonth(DateTime.Now.Month);
relayServerNodeStore.SetMaxGbTotalLastBytes((long)(relayServerNodeStore.Node.MaxGbTotal * 1024 * 1024 * 1024));
relayServerNodeStore.SetMaxGbTotalLastBytes((long)(node.MaxGbTotal * 1024 * 1024 * 1024));
}
relayServerNodeStore.Confirm();
}
@@ -259,14 +279,12 @@ namespace linker.messenger.relay.server
bool result = await messengerSender.SendOnly(new MessageRequestWrap
{
Connection = relayServerNodeStore.Node.Id == RelayServerNodeInfo.MASTER_NODE_ID ? localConnection : remoteConnection,
Connection = connection,
MessengerId = (ushort)RelayMessengerIds.TrafficReport,
Payload = serializer.Serialize(new RelayTrafficUpdateInfo
{
Dic = id2sent,
SecretKey = relayServerNodeStore.Node.Id == RelayServerNodeInfo.MASTER_NODE_ID
? relayServerMasterStore.Master.SecretKey
: relayServerNodeStore.Node.MasterSecretKey
SecretKey = relayServerMasterStore.Master.SecretKey
}),
Timeout = 4000
});
@@ -307,67 +325,39 @@ namespace linker.messenger.relay.server
{
TimerHelper.SetIntervalLong(async () =>
{
IEnumerable<RelayServerNodeInfo> nodes = new List<RelayServerNodeInfo>
{
//默认报告给自己,作为本服务器的一个默认中继节点
new RelayServerNodeInfo{
Id = RelayServerNodeInfo.MASTER_NODE_ID,
Host = new IPEndPoint(IPAddress.Any, relayServerNodeStore.ServicePort).ToString(),
MasterHost = new IPEndPoint(IPAddress.Loopback, relayServerNodeStore.ServicePort).ToString(),
MasterSecretKey = relayServerMasterStore.Master.SecretKey,
MaxBandwidth = 0,
MaxConnection = 0,
MaxBandwidthTotal=0,
MaxGbTotal=0,
MaxGbTotalLastBytes=0,
MaxGbTotalMonth=0,
Name = "default",
Public = false
},
//配置的中继节点
relayServerNodeStore.Node
}.Where(c => string.IsNullOrWhiteSpace(c.MasterHost) == false && string.IsNullOrWhiteSpace(c.MasterSecretKey) == false)
.Where(c => string.IsNullOrWhiteSpace(c.Name) == false && string.IsNullOrWhiteSpace(c.Id) == false);
double diff = (bytes - lastBytes) * 8 / 1024.0 / 1024.0;
lastBytes = bytes;
foreach (var node in nodes)
try
{
try
IPEndPoint endPoint = await NetworkHelper.GetEndPointAsync(node.Host, relayServerNodeStore.ServicePort) ?? new IPEndPoint(IPAddress.Any, relayServerNodeStore.ServicePort);
RelayServerNodeReportInfo170 relayNodeReportInfo = new RelayServerNodeReportInfo170
{
IConnection connection = node.Id == RelayServerNodeInfo.MASTER_NODE_ID ? localConnection : remoteConnection;
IPEndPoint endPoint = await NetworkHelper.GetEndPointAsync(node.Host, relayServerNodeStore.ServicePort) ?? new IPEndPoint(IPAddress.Any, relayServerNodeStore.ServicePort);
RelayServerNodeReportInfo170 relayNodeReportInfo = new RelayServerNodeReportInfo170
{
Id = node.Id,
Name = node.Name,
Public = node.Public,
MaxBandwidth = node.MaxBandwidth,
BandwidthRatio = Math.Round(diff / 5, 2),
MaxBandwidthTotal = node.MaxBandwidthTotal,
MaxGbTotal = node.MaxGbTotal,
MaxGbTotalLastBytes = node.MaxGbTotalLastBytes,
MaxConnection = node.MaxConnection,
ConnectionRatio = Math.Round(connectionNum / 2.0),
EndPoint = endPoint,
Url = node.Url
};
await messengerSender.SendOnly(new MessageRequestWrap
{
Connection = connection,
MessengerId = (ushort)RelayMessengerIds.NodeReport,
Payload = serializer.Serialize(relayNodeReportInfo)
});
}
catch (Exception ex)
Id = node.Id,
Name = node.Name,
Public = node.Public,
MaxBandwidth = node.MaxBandwidth,
BandwidthRatio = Math.Round(diff / 5, 2),
MaxBandwidthTotal = node.MaxBandwidthTotal,
MaxGbTotal = node.MaxGbTotal,
MaxGbTotalLastBytes = node.MaxGbTotalLastBytes,
MaxConnection = node.MaxConnection,
ConnectionRatio = Math.Round(connectionNum / 2.0),
EndPoint = endPoint,
Url = node.Url
};
await messengerSender.SendOnly(new MessageRequestWrap
{
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
{
LoggerHelper.Instance.Error($"relay report : {ex}");
}
Connection = connection,
MessengerId = (ushort)RelayMessengerIds.NodeReport,
Payload = serializer.Serialize(relayNodeReportInfo)
});
}
catch (Exception ex)
{
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
{
LoggerHelper.Instance.Error($"relay report : {ex}");
}
}
return true;
@@ -378,13 +368,9 @@ namespace linker.messenger.relay.server
{
TimerHelper.SetIntervalLong(async () =>
{
if ((remoteConnection == null || remoteConnection.Connected == false) && string.IsNullOrWhiteSpace(relayServerNodeStore.Node.MasterHost) == false)
if (connection == null || connection.Connected == false)
{
remoteConnection = await SignIn(relayServerNodeStore.Node.MasterHost, relayServerNodeStore.Node.MasterSecretKey).ConfigureAwait(false);
}
if (localConnection == null || localConnection.Connected == false)
{
localConnection = await SignIn(new IPEndPoint(IPAddress.Loopback, relayServerNodeStore.ServicePort).ToString(), relayServerMasterStore.Master.SecretKey).ConfigureAwait(false);
connection = await SignIn(node.MasterHost, node.MasterSecretKey).ConfigureAwait(false);
}
return true;
}, 3000);
@@ -401,6 +387,10 @@ namespace linker.messenger.relay.server
IPEndPoint remote = await NetworkHelper.GetEndPointAsync(host, 1802);
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
{
LoggerHelper.Instance.Warning($"relay node sign in to {remote}");
}
Socket socket = new Socket(remote.Address.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
socket.KeepAlive();

View File

@@ -53,7 +53,7 @@ namespace linker.messenger.relay.server
//ask 是发起端来的那key就是 发起端->目标端, answer的目标和来源会交换所以转换一下
string key = relayMessage.Type == RelayMessengerType.Ask ? $"{relayMessage.FromId}->{relayMessage.ToId}->{relayMessage.FlowId}" : $"{relayMessage.ToId}->{relayMessage.FromId}->{relayMessage.FlowId}";
//获取缓存
RelayCacheInfo relayCache = await relayServerNodeTransfer.TryGetRelayCache(key, relayMessage.NodeId);
RelayCacheInfo relayCache = await relayServerNodeTransfer.TryGetRelayCache(key);
if (relayCache == null)
{
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)

View File

@@ -100,11 +100,12 @@ namespace linker.messenger.store.file
return serviceCollection;
}
public static ServiceProvider UseStoreFile(this ServiceProvider serviceProvider)
public static ServiceProvider UseStoreFile(this ServiceProvider serviceProvider,Dictionary<string,string> configDic)
{
LoggerHelper.Instance.Info("use store file");
FileConfig fileConfig = serviceProvider.GetService<FileConfig>();
fileConfig.Initialize(configDic);
RunningConfig runningConfig = serviceProvider.GetService<RunningConfig>();
IApiServer apiServer = serviceProvider.GetService<IApiServer>();

View File

@@ -18,9 +18,12 @@ namespace linker.messenger.store.file
public ConfigInfo Data { get; private set; } = new ConfigInfo();
public FileConfig()
{
}
public void Initialize(Dictionary<string, string> dic)
{
Init();
Load();
Load(dic);
Save();
SaveTask();
}
@@ -47,7 +50,7 @@ namespace linker.messenger.store.file
});
}
}
private void Load()
private void Load(Dictionary<string, string> dic)
{
slim.Wait();
try
@@ -61,13 +64,15 @@ namespace linker.messenger.store.file
LoggerHelper.Instance.Error($"{item.Value.Property.Name} not found");
continue;
}
if (File.Exists(item.Value.Path) == false)
string text = string.Empty;
if (File.Exists(item.Value.Path))
{
LoggerHelper.Instance.Error($"{item.Value.Path} not exists");
continue;
text = File.ReadAllText(item.Value.Path, encoding: System.Text.Encoding.UTF8);
}
else if (dic != null && dic.ContainsKey(item.Value.Property.Name))
{
text = dic[item.Value.Property.Name];
}
string text = File.ReadAllText(item.Value.Path, encoding: System.Text.Encoding.UTF8);
if (string.IsNullOrWhiteSpace(text))
{
LoggerHelper.Instance.Error($"{item.Value.Path} empty");
@@ -232,5 +237,5 @@ namespace linker.messenger.store.file
}
}
}

View File

@@ -4,6 +4,7 @@ using linker.messenger.signin;
using linker.tunnel;
using System.Net;
using System.Net.Quic;
using System.Text.Json.Nodes;
namespace linker.messenger.tunnel
{
@@ -45,23 +46,55 @@ namespace linker.messenger.tunnel
LoggerHelper.Instance.Warning($"tunnel route level:{Info.RouteLevel}");
}
private async Task GetIsp()
{
try
{
using HttpClient httpClient = new HttpClient();
string str = await httpClient.GetStringAsync($"http://ip-api.com/json").WaitAsync(TimeSpan.FromMilliseconds(3000));
if (string.IsNullOrWhiteSpace(str) == false)
{
TunnelNetInfo net = str.DeJson<TunnelNetInfo>();
Info.Net.Isp = net.Isp;
Info.Net.As = net.As;
Info.Net.Org = net.Org;
Info.Net.Region = net.Region;
Info.Net.RegionName = net.RegionName;
Info.Net.Country = net.Country;
Info.Net.CountryCode = net.CountryCode;
}
}
catch (Exception ex)
{
LoggerHelper.Instance.Warning(ex);
}
}
private async Task GetPosition()
{
try
{
using HttpClient httpClient = new HttpClient();
string str = await httpClient.GetStringAsync($"https://api.myip.la/en?json").WaitAsync(TimeSpan.FromMilliseconds(5000));
if (string.IsNullOrWhiteSpace(str) == false)
{
JsonNode json = JsonObject.Parse(str);
Info.Net.City = json["location"]["city"].ToString();
Info.Net.Lat = double.Parse(json["location"]["latitude"].ToString());
Info.Net.Lon = double.Parse(json["location"]["longitude"].ToString());
}
}
catch (Exception ex)
{
LoggerHelper.Instance.Warning(ex);
}
}
private async Task GetNet()
{
if (string.IsNullOrWhiteSpace(Info.Net.City))
{
try
{
using HttpClient httpClient = new HttpClient();
string str = await httpClient.GetStringAsync($"http://ip-api.com/json").WaitAsync(TimeSpan.FromMilliseconds(3000));
if (string.IsNullOrWhiteSpace(str) == false)
{
Info.Net = str.DeJson<TunnelNetInfo>();
}
}
catch (Exception)
{
}
await Task.WhenAll(GetIsp(), GetPosition());
}
}

View File

@@ -252,17 +252,8 @@ namespace linker.messenger
SourceStream = stream;
SourceNetworkStream = networkStream;
SourceSocket = socket;
if (remote.Address.AddressFamily == AddressFamily.InterNetworkV6 && remote.Address.IsIPv4MappedToIPv6)
{
remote = new IPEndPoint(new IPAddress(remote.Address.GetAddressBytes()[^4..]), remote.Port);
}
Address = remote;
if (local.Address.AddressFamily == AddressFamily.InterNetworkV6 && local.Address.IsIPv4MappedToIPv6)
{
local = new IPEndPoint(new IPAddress(local.Address.GetAddressBytes()[^4..]), local.Port);
}
LocalAddress = local;
Address = NetworkHelper.TransEndpointFamily(remote) ;
LocalAddress = NetworkHelper.TransEndpointFamily(local);
}

View File

@@ -93,7 +93,7 @@ namespace linker.tunnel.connection
private async Task ProcessWrite()
{
byte[] buffer = new byte[65 * 1024];
IPEndPoint ep = new IPEndPoint(IPAddress.Any, 0);
IPEndPoint ep = new IPEndPoint(IPEndPoint.AddressFamily == AddressFamily.InterNetwork ? IPAddress.Any : IPAddress.IPv6Any, 0);
try
{
while (cancellationTokenSource.IsCancellationRequested == false)

View File

@@ -230,7 +230,7 @@ namespace linker.tunnel.transport
RemoteUdp = remoteUdp,
Stream = quicStream,
Connection = connection,
IPEndPoint = remoteEP,
IPEndPoint = NetworkHelper.TransEndpointFamily(remoteEP),
TransactionId = tunnelTransportInfo.TransactionId,
TransactionTag = tunnelTransportInfo.TransactionTag,
RemoteMachineId = tunnelTransportInfo.Remote.MachineId,
@@ -626,7 +626,7 @@ namespace linker.tunnel.transport
TransactionId = state.TransactionId,
TransactionTag = state.TransactionTag,
TransportName = state.TransportName,
IPEndPoint = remoteEP,
IPEndPoint = NetworkHelper.TransEndpointFamily(remoteEP),
Label = string.Empty,
BufferSize = state.BufferSize,
};

View File

@@ -185,7 +185,7 @@ namespace linker.tunnel.transport
{
Stream = sslStream,
Socket = targetSocket,
IPEndPoint = targetSocket.RemoteEndPoint as IPEndPoint,
IPEndPoint = NetworkHelper.TransEndpointFamily(targetSocket.RemoteEndPoint as IPEndPoint),
TransactionId = tunnelTransportInfo.TransactionId,
TransactionTag = tunnelTransportInfo.TransactionTag,
RemoteMachineId = tunnelTransportInfo.Remote.MachineId,
@@ -291,7 +291,7 @@ namespace linker.tunnel.transport
TransactionId = _state.TransactionId,
TransactionTag = _state.TransactionTag,
TransportName = _state.TransportName,
IPEndPoint = socket.RemoteEndPoint as IPEndPoint,
IPEndPoint = NetworkHelper.TransEndpointFamily(socket.RemoteEndPoint as IPEndPoint),
Label = string.Empty,
SSL = _state.SSL,
BufferSize = _state.BufferSize,

View File

@@ -178,7 +178,7 @@ namespace linker.tunnel.transport
{
Stream = sslStream,
Socket = socket,
IPEndPoint = socket.RemoteEndPoint as IPEndPoint,
IPEndPoint = NetworkHelper.TransEndpointFamily(socket.RemoteEndPoint as IPEndPoint),
TransactionId = state.TransactionId,
TransactionTag = state.TransactionTag,
RemoteMachineId = state.Remote.MachineId,
@@ -238,7 +238,7 @@ namespace linker.tunnel.transport
TransactionId = state.TransactionId,
TransactionTag = state.TransactionTag,
TransportName = state.TransportName,
IPEndPoint = socket.RemoteEndPoint as IPEndPoint,
IPEndPoint = NetworkHelper.TransEndpointFamily(socket.RemoteEndPoint as IPEndPoint),
Label = string.Empty,
SSL = state.SSL,
BufferSize = state.BufferSize,

View File

@@ -277,7 +277,7 @@ namespace linker.tunnel.transport
TransactionId = tunnelTransportInfo.TransactionId,
TransactionTag = tunnelTransportInfo.TransactionTag,
TransportName = tunnelTransportInfo.TransportName,
IPEndPoint = socket.RemoteEndPoint as IPEndPoint,
IPEndPoint = NetworkHelper.TransEndpointFamily(socket.RemoteEndPoint as IPEndPoint),
Label = string.Empty,
SSL = tunnelTransportInfo.SSL,
BufferSize = tunnelTransportInfo.BufferSize,
@@ -338,7 +338,7 @@ namespace linker.tunnel.transport
{
Stream = sslStream,
Socket = targetSocket,
IPEndPoint = targetSocket.RemoteEndPoint as IPEndPoint,
IPEndPoint = NetworkHelper.TransEndpointFamily(targetSocket.RemoteEndPoint as IPEndPoint),
TransactionId = tunnelTransportInfo.TransactionId,
TransactionTag = tunnelTransportInfo.TransactionTag,
RemoteMachineId = tunnelTransportInfo.Remote.MachineId,

View File

@@ -179,7 +179,7 @@ namespace linker.tunnel.transport
return new TunnelConnectionUdp
{
UdpClient = remoteUdp,
IPEndPoint = remoteEP,
IPEndPoint = NetworkHelper.TransEndpointFamily( remoteEP),
TransactionId = tunnelTransportInfo.TransactionId,
TransactionTag = tunnelTransportInfo.TransactionTag,
RemoteMachineId = tunnelTransportInfo.Remote.MachineId,
@@ -224,7 +224,7 @@ namespace linker.tunnel.transport
TimerHelper.Async(async () =>
{
byte[] buffer = new byte[1024];
SocketReceiveFromResult result = await socket.ReceiveFromAsync(buffer, new IPEndPoint(IPAddress.Any, 0)).ConfigureAwait(false);
SocketReceiveFromResult result = await socket.ReceiveFromAsync(buffer, new IPEndPoint(IPAddress.IPv6Any, 0)).ConfigureAwait(false);
await socket.SendToAsync(endBytes, result.RemoteEndPoint);
tcs.SetResult(result.RemoteEndPoint as IPEndPoint);
});
@@ -408,7 +408,7 @@ namespace linker.tunnel.transport
TransactionId = state.TransactionId,
TransactionTag = state.TransactionTag,
TransportName = state.TransportName,
IPEndPoint = remoteEP,
IPEndPoint = NetworkHelper.TransEndpointFamily(remoteEP),
Label = string.Empty,
Receive = true,
SSL = state.SSL,

View File

@@ -270,7 +270,7 @@ namespace linker.tunnel.transport
TransactionId = tunnelTransportInfo.TransactionId,
TransactionTag = tunnelTransportInfo.TransactionTag,
TransportName = tunnelTransportInfo.TransportName,
IPEndPoint = state.RemoteEndPoint,
IPEndPoint = NetworkHelper.TransEndpointFamily(state.RemoteEndPoint),
Label = string.Empty,
BufferSize = tunnelTransportInfo.BufferSize,
Receive = false,
@@ -323,14 +323,14 @@ namespace linker.tunnel.transport
}
await targetSocket.SendToAsync($"{flagTexts}-{tunnelTransportInfo.Local.MachineId}-{tunnelTransportInfo.FlowId}".ToBytes(), ep).ConfigureAwait(false);
await targetSocket.ReceiveFromAsync(new byte[1024], new IPEndPoint(IPAddress.IPv6Any, 0)).WaitAsync(TimeSpan.FromMilliseconds(500)).ConfigureAwait(false);
await targetSocket.ReceiveFromAsync(new byte[1024], new IPEndPoint(ep.AddressFamily == AddressFamily.InterNetwork ? IPAddress.Any : IPAddress.IPv6Any, 0)).WaitAsync(TimeSpan.FromMilliseconds(500)).ConfigureAwait(false);
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
LoggerHelper.Instance.Debug($"{Name} connect to {tunnelTransportInfo.Remote.MachineId}->{tunnelTransportInfo.Remote.MachineName} {ep} success");
TunnelConnectionUdp result = new TunnelConnectionUdp
{
IPEndPoint = ep,
IPEndPoint = NetworkHelper.TransEndpointFamily(ep),
TransactionId = tunnelTransportInfo.TransactionId,
TransactionTag = tunnelTransportInfo.TransactionTag,
RemoteMachineId = tunnelTransportInfo.Remote.MachineId,

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 24 KiB

View File

@@ -17,6 +17,7 @@ export const provideTuntap = () => {
const systems = {
linux: ['debian', 'ubuntu', 'alpine', 'rocky', 'centos', 'fedora', 'archlinux'],
armbian: ['armbian'],
openwrt: ['openwrt'],
ubuntu: ['ubuntu'],
windows: ['windows'],

View File

@@ -54,9 +54,11 @@ namespace linker
public static void Run(string[] args)
{
Dictionary<string, string> configDic = ParseArgs(args);
LinkerMessengerEntry.Initialize();
LinkerMessengerEntry.Build();
LinkerMessengerEntry.Setup(ExcludeModule.None);
LinkerMessengerEntry.Setup(ExcludeModule.None, configDic);
LoggerHelper.Instance.Warning($"current version : {VersionHelper.version}");
@@ -66,6 +68,34 @@ namespace linker
GCHelper.FlushMemory();
}
private static Dictionary<string, string> ParseArgs(string[] args)
{
Dictionary<string, string> configDic = new Dictionary<string, string>();
for (int i = 0; i < args.Length; i++)
{
if (args[i] == "--config-cient")
{
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++;
}
}
return configDic;
}
}
}

View File

@@ -20,15 +20,17 @@
<Title>linker</Title>
<Authors>snltty</Authors>
<Company>snltty</Company>
<Description>1. 优化linux下路由跟踪问题
2. 优化linux下获取本机IP问题
<Description>1. 优化linux下路由跟踪问题,提高启动速度
2. 优化linux下获取本机IP问题,提升虚拟网卡稳定性
3. 增加ICS让win7+、win server2008+支持NAT
4. 增加中继cdkey使用cdkey解锁公开中继节点的带宽、流量、连接数限制
5. 增加内外穿透定时开关功能
6. 优化管理页面连接接口的体验
7. 优化一些UI体验去除同步页面将同步功能放至各个实际的位置
8. 优化端口转发,让不同分组间可以使用相同端口
9. 其它一些修复优化</Description>
9. 从命令行参数初始化配置
10. 优化打洞IPV6支持的更多了
11. 其它一些修复优化</Description>
<Copyright>snltty</Copyright>
<PackageProjectUrl>https://github.com/snltty/linker</PackageProjectUrl>
<RepositoryUrl>https://github.com/snltty/linker</RepositoryUrl>

View File

@@ -1,11 +1,13 @@
v1.6.9
2025-03-10 17:55:39
1. 优化linux下路由跟踪问题
2. 优化linux下获取本机IP问题
2025-03-11 21:12:44
1. 优化linux下路由跟踪问题,提高启动速度
2. 优化linux下获取本机IP问题,提升虚拟网卡稳定性
3. 增加ICS让win7+、win server2008+支持NAT
4. 增加中继cdkey使用cdkey解锁公开中继节点的带宽、流量、连接数限制
5. 增加内外穿透定时开关功能
6. 优化管理页面连接接口的体验
7. 优化一些UI体验去除同步页面将同步功能放至各个实际的位置
8. 优化端口转发,让不同分组间可以使用相同端口
9. 其它一些修复优化
9. 从命令行参数初始化配置
10. 优化打洞IPV6支持的更多了
11. 其它一些修复优化