From 244ebe99c36925b01c19b962dfd98f1da885faec Mon Sep 17 00:00:00 2001 From: snltty <1069410172@qq.com> Date: Tue, 11 Mar 2025 21:12:45 +0800 Subject: [PATCH] cdkey --- .github/workflows/dotnet.yml | 42 +---- gen/index.js | 3 +- publish.bat | 2 +- src/linker.app/MainPage.xaml.cs | 7 +- .../Platforms/Android/MainActivity.cs | 10 ++ .../docs/2、首次运行/2.5、初始化配置.md | 80 ++++++++- .../docs/8、集成和二次开发/8.9、中继CDKEY.md | 149 ++++++++++++++++ .../docs/{10、公益赞助.md => 9、公益赞助.md} | 4 +- src/linker.doc.web/docs/9、收费项目.md | 74 -------- src/linker.libs/Logger.cs | 4 + src/linker.libs/NetworkHelper.cs | 13 +- .../LinkerMessengerEntry.cs | 12 +- .../transport/RelayClientTransportSelfHost.cs | 4 +- .../messenger/RelayMessenger.cs | 11 +- .../server/IRelayServerNodeStore.cs | 2 - .../server/RelayServerMasterTransfer.cs | 21 ++- .../server/RelayServerNodeTransfer.cs | 164 ++++++++---------- .../server/RelayServerResolver.cs | 2 +- src/linker.messenger.store.file/Entry.cs | 3 +- src/linker.messenger.store.file/FileConfig.cs | 21 ++- .../TunnelNetworkTransfer.cs | 59 +++++-- src/linker.messenger/IConnection.cs | 13 +- .../connection/TunnelConnectionUdp.cs | 2 +- .../transport/TransportMsQuic.cs | 4 +- .../transport/TransportTcpNutssb.cs | 4 +- .../transport/TransportTcpP2PNAT.cs | 4 +- .../transport/TransportTcpPortMap.cs | 4 +- src/linker.tunnel/transport/TransportUdp.cs | 6 +- .../transport/TransportUdpPortMap.cs | 6 +- src/linker.web/public/armbian.svg | 1 + .../src/views/full/devices/tuntap.js | 1 + src/linker/Program.cs | 32 +++- src/linker/linker.csproj | 8 +- version.txt | 10 +- 34 files changed, 484 insertions(+), 298 deletions(-) create mode 100644 src/linker.doc.web/docs/8、集成和二次开发/8.9、中继CDKEY.md rename src/linker.doc.web/docs/{10、公益赞助.md => 9、公益赞助.md} (52%) delete mode 100644 src/linker.doc.web/docs/9、收费项目.md create mode 100644 src/linker.web/public/armbian.svg diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index 34689f00..b22bcefd 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -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 diff --git a/gen/index.js b/gen/index.js index 3e873a49..5125cfb1 100644 --- a/gen/index.js +++ b/gen/index.js @@ -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]; diff --git a/publish.bat b/publish.bat index d837bbf8..1408bca4 100644 --- a/publish.bat +++ b/publish.bat @@ -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 diff --git a/src/linker.app/MainPage.xaml.cs b/src/linker.app/MainPage.xaml.cs index 72644159..d391f33a 100644 --- a/src/linker.app/MainPage.xaml.cs +++ b/src/linker.app/MainPage.xaml.cs @@ -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); + } } diff --git a/src/linker.app/Platforms/Android/MainActivity.cs b/src/linker.app/Platforms/Android/MainActivity.cs index 37cbd2d4..cab597bd 100644 --- a/src/linker.app/Platforms/Android/MainActivity.cs +++ b/src/linker.app/Platforms/Android/MainActivity.cs @@ -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 () => { diff --git a/src/linker.doc.web/docs/2、首次运行/2.5、初始化配置.md b/src/linker.doc.web/docs/2、首次运行/2.5、初始化配置.md index ff9de479..2c340fe0 100644 --- a/src/linker.doc.web/docs/2、首次运行/2.5、初始化配置.md +++ b/src/linker.doc.web/docs/2、首次运行/2.5、初始化配置.md @@ -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\"} +``` +::: + diff --git a/src/linker.doc.web/docs/8、集成和二次开发/8.9、中继CDKEY.md b/src/linker.doc.web/docs/8、集成和二次开发/8.9、中继CDKEY.md new file mode 100644 index 00000000..e36c71cc --- /dev/null +++ b/src/linker.doc.web/docs/8、集成和二次开发/8.9、中继CDKEY.md @@ -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 Decode(byte[] buffer) + { + return Decode(buffer, 0, buffer.Length); + } + public Memory 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]; + } +} +``` +::: diff --git a/src/linker.doc.web/docs/10、公益赞助.md b/src/linker.doc.web/docs/9、公益赞助.md similarity index 52% rename from src/linker.doc.web/docs/10、公益赞助.md rename to src/linker.doc.web/docs/9、公益赞助.md index 9f497e87..63f948a9 100644 --- a/src/linker.doc.web/docs/10、公益赞助.md +++ b/src/linker.doc.web/docs/9、公益赞助.md @@ -1,7 +1,7 @@ --- -sidebar_position: 10 +sidebar_position: 9 --- -# 10、公益赞助 +# 9、公益赞助 ![Docusaurus Plushie](./img/qr.jpg) diff --git a/src/linker.doc.web/docs/9、收费项目.md b/src/linker.doc.web/docs/9、收费项目.md deleted file mode 100644 index 985a47fb..00000000 --- a/src/linker.doc.web/docs/9、收费项目.md +++ /dev/null @@ -1,74 +0,0 @@ ---- -sidebar_position: 9 ---- - -# 9、收费项目 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Linker2设备内2-5设备5-10设备10设备以上权益
使用免费免费免费免费/
开源集成免费免费免费免费/
安装配置维护/次20/次50/次100/次10/台/次私有化部署、配置、BUG修复
安装配置维护/年99/年239/年399/年29/台/年私有化部署、配置、BUG修复、技术解答
商业集成详谈,技术解答,原理讲解,二开指导
功能定制详谈,技术解答,原理讲解,二开指导
- - - - - - - - - - - - - -
证书
3个月泛域名证书9.9/个
\ No newline at end of file diff --git a/src/linker.libs/Logger.cs b/src/linker.libs/Logger.cs index 070fb19f..855a38a2 100644 --- a/src/linker.libs/Logger.cs +++ b/src/linker.libs/Logger.cs @@ -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) diff --git a/src/linker.libs/NetworkHelper.cs b/src/linker.libs/NetworkHelper.cs index ba9fa374..5b86102e 100644 --- a/src/linker.libs/NetworkHelper.cs +++ b/src/linker.libs/NetworkHelper.cs @@ -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; + } + /// /// 域名解析 @@ -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() { diff --git a/src/linker.messenger.entry/LinkerMessengerEntry.cs b/src/linker.messenger.entry/LinkerMessengerEntry.cs index 61437832..68607232 100644 --- a/src/linker.messenger.entry/LinkerMessengerEntry.cs +++ b/src/linker.messenger.entry/LinkerMessengerEntry.cs @@ -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().ToJsonFormat()); + } /// /// 开始初始化 /// @@ -76,7 +82,7 @@ namespace linker.messenger.entry .AddTuntapClient().AddTuntapServer() //更新 .AddUpdaterClient().AddUpdaterServer() - + //信标 .AddMessenger() //流量统计 @@ -131,7 +137,7 @@ namespace linker.messenger.entry /// 开始运行 /// /// 排除哪些模块,默认无 - public static void Setup(ExcludeModule modules = ExcludeModule.None) + public static void Setup(ExcludeModule modules = ExcludeModule.None, Dictionary 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(); diff --git a/src/linker.messenger.relay/client/transport/RelayClientTransportSelfHost.cs b/src/linker.messenger.relay/client/transport/RelayClientTransportSelfHost.cs index 6de9b519..06368f28 100644 --- a/src/linker.messenger.relay/client/transport/RelayClientTransportSelfHost.cs +++ b/src/linker.messenger.relay/client/transport/RelayClientTransportSelfHost.cs @@ -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, diff --git a/src/linker.messenger.relay/messenger/RelayMessenger.cs b/src/linker.messenger.relay/messenger/RelayMessenger.cs index a56bc729..70dd3abe 100644 --- a/src/linker.messenger.relay/messenger/RelayMessenger.cs +++ b/src/linker.messenger.relay/messenger/RelayMessenger.cs @@ -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 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(connection.ReceiveRequestWrap.Payload.Span); - if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG) - { - LoggerHelper.Instance.Debug($"relay node report : {info.ToJson()}"); - } relayServerTransfer.SetNodeReport(connection, info); } /// @@ -279,10 +277,7 @@ namespace linker.messenger.relay.messenger public void UpdateNode(IConnection connection) { RelayServerNodeUpdateInfo info = serializer.Deserialize(connection.ReceiveRequestWrap.Payload.Span); - if (relayServerNodeTransfer.Id == info.Id) - { - relayServerNodeTransfer.UpdateNode(info); - } + relayServerNodeTransfer.UpdateNode(info); } /// /// 更新节点转发 diff --git a/src/linker.messenger.relay/server/IRelayServerNodeStore.cs b/src/linker.messenger.relay/server/IRelayServerNodeStore.cs index 02c8bf46..e7265ffe 100644 --- a/src/linker.messenger.relay/server/IRelayServerNodeStore.cs +++ b/src/linker.messenger.relay/server/IRelayServerNodeStore.cs @@ -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 { diff --git a/src/linker.messenger.relay/server/RelayServerMasterTransfer.cs b/src/linker.messenger.relay/server/RelayServerMasterTransfer.cs index 77b4093b..fd7a1251 100644 --- a/src/linker.messenger.relay/server/RelayServerMasterTransfer.cs +++ b/src/linker.messenger.relay/server/RelayServerMasterTransfer.cs @@ -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 /// 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 /// /// /// - public void AddTraffic(Dictionary dic) + public void AddTraffic(Dictionary dic) { if (dic.Count > 0) trafficQueue.Enqueue(dic); diff --git a/src/linker.messenger.relay/server/RelayServerNodeTransfer.cs b/src/linker.messenger.relay/server/RelayServerNodeTransfer.cs index 6050a391..d225c804 100644 --- a/src/linker.messenger.relay/server/RelayServerNodeTransfer.cs +++ b/src/linker.messenger.relay/server/RelayServerNodeTransfer.cs @@ -13,11 +13,13 @@ namespace linker.messenger.relay.server /// public class RelayServerNodeTransfer { - public string Id => relayServerNodeStore.Node.Id; + /// + /// 配置了就用配置的,每配置就用一个默认的 + /// + 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 TryGetRelayCache(string key, string nodeid) + public async ValueTask 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); } /// @@ -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 /// 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 /// 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; } /// @@ -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)); } /// @@ -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 nodes = new List - { - //默认报告给自己,作为本服务器的一个默认中继节点 - 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(); diff --git a/src/linker.messenger.relay/server/RelayServerResolver.cs b/src/linker.messenger.relay/server/RelayServerResolver.cs index c49d5c48..6caa99d1 100644 --- a/src/linker.messenger.relay/server/RelayServerResolver.cs +++ b/src/linker.messenger.relay/server/RelayServerResolver.cs @@ -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) diff --git a/src/linker.messenger.store.file/Entry.cs b/src/linker.messenger.store.file/Entry.cs index 6d49cb05..7a924829 100644 --- a/src/linker.messenger.store.file/Entry.cs +++ b/src/linker.messenger.store.file/Entry.cs @@ -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 configDic) { LoggerHelper.Instance.Info("use store file"); FileConfig fileConfig = serviceProvider.GetService(); + fileConfig.Initialize(configDic); RunningConfig runningConfig = serviceProvider.GetService(); IApiServer apiServer = serviceProvider.GetService(); diff --git a/src/linker.messenger.store.file/FileConfig.cs b/src/linker.messenger.store.file/FileConfig.cs index 98a2a77b..f76096a0 100644 --- a/src/linker.messenger.store.file/FileConfig.cs +++ b/src/linker.messenger.store.file/FileConfig.cs @@ -18,9 +18,12 @@ namespace linker.messenger.store.file public ConfigInfo Data { get; private set; } = new ConfigInfo(); public FileConfig() + { + } + public void Initialize(Dictionary dic) { Init(); - Load(); + Load(dic); Save(); SaveTask(); } @@ -47,7 +50,7 @@ namespace linker.messenger.store.file }); } } - private void Load() + private void Load(Dictionary 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 } } - + } diff --git a/src/linker.messenger.tunnel/TunnelNetworkTransfer.cs b/src/linker.messenger.tunnel/TunnelNetworkTransfer.cs index df6d957f..77ff2534 100644 --- a/src/linker.messenger.tunnel/TunnelNetworkTransfer.cs +++ b/src/linker.messenger.tunnel/TunnelNetworkTransfer.cs @@ -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(); + 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(); - } - } - catch (Exception) - { - } + await Task.WhenAll(GetIsp(), GetPosition()); } } diff --git a/src/linker.messenger/IConnection.cs b/src/linker.messenger/IConnection.cs index 3a7ed2bc..4bd5cd4d 100644 --- a/src/linker.messenger/IConnection.cs +++ b/src/linker.messenger/IConnection.cs @@ -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); } diff --git a/src/linker.tunnel/connection/TunnelConnectionUdp.cs b/src/linker.tunnel/connection/TunnelConnectionUdp.cs index 41208370..f9610883 100644 --- a/src/linker.tunnel/connection/TunnelConnectionUdp.cs +++ b/src/linker.tunnel/connection/TunnelConnectionUdp.cs @@ -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) diff --git a/src/linker.tunnel/transport/TransportMsQuic.cs b/src/linker.tunnel/transport/TransportMsQuic.cs index eb810c17..6b9f4928 100644 --- a/src/linker.tunnel/transport/TransportMsQuic.cs +++ b/src/linker.tunnel/transport/TransportMsQuic.cs @@ -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, }; diff --git a/src/linker.tunnel/transport/TransportTcpNutssb.cs b/src/linker.tunnel/transport/TransportTcpNutssb.cs index 3e60ad37..ba6a2e87 100644 --- a/src/linker.tunnel/transport/TransportTcpNutssb.cs +++ b/src/linker.tunnel/transport/TransportTcpNutssb.cs @@ -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, diff --git a/src/linker.tunnel/transport/TransportTcpP2PNAT.cs b/src/linker.tunnel/transport/TransportTcpP2PNAT.cs index 38dc154c..8d4156b0 100644 --- a/src/linker.tunnel/transport/TransportTcpP2PNAT.cs +++ b/src/linker.tunnel/transport/TransportTcpP2PNAT.cs @@ -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, diff --git a/src/linker.tunnel/transport/TransportTcpPortMap.cs b/src/linker.tunnel/transport/TransportTcpPortMap.cs index 9fe51e84..48953b87 100644 --- a/src/linker.tunnel/transport/TransportTcpPortMap.cs +++ b/src/linker.tunnel/transport/TransportTcpPortMap.cs @@ -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, diff --git a/src/linker.tunnel/transport/TransportUdp.cs b/src/linker.tunnel/transport/TransportUdp.cs index 135dec01..04a8d322 100644 --- a/src/linker.tunnel/transport/TransportUdp.cs +++ b/src/linker.tunnel/transport/TransportUdp.cs @@ -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, diff --git a/src/linker.tunnel/transport/TransportUdpPortMap.cs b/src/linker.tunnel/transport/TransportUdpPortMap.cs index 46b119a9..752fe4a3 100644 --- a/src/linker.tunnel/transport/TransportUdpPortMap.cs +++ b/src/linker.tunnel/transport/TransportUdpPortMap.cs @@ -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, diff --git a/src/linker.web/public/armbian.svg b/src/linker.web/public/armbian.svg new file mode 100644 index 00000000..46d2081f --- /dev/null +++ b/src/linker.web/public/armbian.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/linker.web/src/views/full/devices/tuntap.js b/src/linker.web/src/views/full/devices/tuntap.js index 1561bf75..215e5476 100644 --- a/src/linker.web/src/views/full/devices/tuntap.js +++ b/src/linker.web/src/views/full/devices/tuntap.js @@ -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'], diff --git a/src/linker/Program.cs b/src/linker/Program.cs index 0f8d17be..7edbffc5 100644 --- a/src/linker/Program.cs +++ b/src/linker/Program.cs @@ -54,9 +54,11 @@ namespace linker public static void Run(string[] args) { + Dictionary 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 ParseArgs(string[] args) + { + Dictionary configDic = new Dictionary(); + 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; + } } } \ No newline at end of file diff --git a/src/linker/linker.csproj b/src/linker/linker.csproj index eee3cc36..ae9dd56b 100644 --- a/src/linker/linker.csproj +++ b/src/linker/linker.csproj @@ -20,15 +20,17 @@ linker snltty snltty - 1. 优化linux下路由跟踪问题 -2. 优化linux下获取本机IP问题 + 1. 优化linux下路由跟踪问题,提高启动速度 +2. 优化linux下获取本机IP问题,提升虚拟网卡稳定性 3. 增加ICS,让win7+、win server2008+支持NAT 4. 增加中继cdkey,使用cdkey解锁公开中继节点的带宽、流量、连接数限制 5. 增加内外穿透定时开关功能 6. 优化管理页面连接接口的体验 7. 优化一些UI体验,去除同步页面,将同步功能放至各个实际的位置 8. 优化端口转发,让不同分组间可以使用相同端口 -9. 其它一些修复优化 +9. 从命令行参数初始化配置 +10. 优化打洞,IPV6支持的更多了 +11. 其它一些修复优化 snltty https://github.com/snltty/linker https://github.com/snltty/linker diff --git a/version.txt b/version.txt index f7da8f5b..1f4c06b1 100644 --- a/version.txt +++ b/version.txt @@ -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. 其它一些修复优化 \ No newline at end of file +9. 从命令行参数初始化配置 +10. 优化打洞,IPV6支持的更多了 +11. 其它一些修复优化 \ No newline at end of file