mirror of
				https://github.com/snltty/linker.git
				synced 2025-10-31 12:36:48 +08:00 
			
		
		
		
	sync
This commit is contained in:
		
							
								
								
									
										14
									
								
								.github/workflows/dotnet.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										14
									
								
								.github/workflows/dotnet.yml
									
									
									
									
										vendored
									
									
								
							| @@ -48,19 +48,13 @@ jobs: | |||||||
|       env: |       env: | ||||||
|           GITHUB_TOKEN: '${{ secrets.ACTIONS_TOKEN }}' |           GITHUB_TOKEN: '${{ secrets.ACTIONS_TOKEN }}' | ||||||
|       with: |       with: | ||||||
|         tag_name: v1.2.0.2 |         tag_name: v1.2.0.3 | ||||||
|         release_name: v1.2.0.2.${{ steps.date.outputs.today }} |         release_name: v1.2.0.3.${{ steps.date.outputs.today }} | ||||||
|         draft: false |         draft: false | ||||||
|         prerelease: false |         prerelease: false | ||||||
|         body: | |         body: | | ||||||
|           1. 网关层级计算修复(在linux下计算错误导致打洞失败) |           1. 这是一个测试版本,请使用v1.2.0.2版本 | ||||||
|           2. 修复在IPV6环境下域名解析缓慢问题 |           2. 请勿更新 | ||||||
|           3. 新增基于端口映射的打洞协议 |  | ||||||
|           4. 修复端口转发潜在BUG |  | ||||||
|           5. 虚拟网卡支持广播组播了 |  | ||||||
|           6. 修复了socks5的一些问题 |  | ||||||
|           7. 增加了docker宿主机访问策略,docker也可以用虚拟网卡通信了 |  | ||||||
|           8. 请更新服务端 |  | ||||||
|  |  | ||||||
|     - name: upload win x64 |     - name: upload win x64 | ||||||
|       id: upload-win-x64 |       id: upload-win-x64 | ||||||
|   | |||||||
							
								
								
									
										3
									
								
								.github/workflows/nuget.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.github/workflows/nuget.yml
									
									
									
									
										vendored
									
									
								
							| @@ -23,11 +23,13 @@ jobs: | |||||||
|       run: | |       run: | | ||||||
|         dotnet build ./linker.libs -c release |         dotnet build ./linker.libs -c release | ||||||
|         dotnet build ./linker.tunnel -c release |         dotnet build ./linker.tunnel -c release | ||||||
|  |         dotnet build ./linker.tun -c release | ||||||
|  |  | ||||||
|     - name: Pack |     - name: Pack | ||||||
|       run: | |       run: | | ||||||
|         dotnet pack ./linker.libs -c release |         dotnet pack ./linker.libs -c release | ||||||
|         dotnet pack ./linker.tunnel -c release |         dotnet pack ./linker.tunnel -c release | ||||||
|  |         dotnet pack ./linker.tun -c release | ||||||
|          |          | ||||||
|     - name: Install Nuget |     - name: Install Nuget | ||||||
|       uses: nuget/setup-nuget@v1 |       uses: nuget/setup-nuget@v1 | ||||||
| @@ -38,3 +40,4 @@ jobs: | |||||||
|       run: | |       run: | | ||||||
|         nuget push ./linker.tunnel/bin/release/linker.tunnel.1.2.0.nupkg -Source https://api.nuget.org/v3/index.json -SkipDuplicate -ApiKey ${{ secrets.NUGET_KEY }} -NoSymbol |         nuget push ./linker.tunnel/bin/release/linker.tunnel.1.2.0.nupkg -Source https://api.nuget.org/v3/index.json -SkipDuplicate -ApiKey ${{ secrets.NUGET_KEY }} -NoSymbol | ||||||
|         nuget push ./linker.libs/bin/release/linker.libs.1.2.0.nupkg -Source https://api.nuget.org/v3/index.json -SkipDuplicate -ApiKey ${{ secrets.NUGET_KEY }} -NoSymbol |         nuget push ./linker.libs/bin/release/linker.libs.1.2.0.nupkg -Source https://api.nuget.org/v3/index.json -SkipDuplicate -ApiKey ${{ secrets.NUGET_KEY }} -NoSymbol | ||||||
|  |         nuget push ./linker.tun/bin/release/linker.tun.1.2.0.nupkg -Source https://api.nuget.org/v3/index.json -SkipDuplicate -ApiKey ${{ secrets.NUGET_KEY }} -NoSymbol | ||||||
|   | |||||||
							
								
								
									
										90
									
								
								linker.doc.web/docs/8、集成tun网卡到你的项目.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								linker.doc.web/docs/8、集成tun网卡到你的项目.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,90 @@ | |||||||
|  | --- | ||||||
|  | sidebar_position: 8 | ||||||
|  | --- | ||||||
|  |  | ||||||
|  | # 8、集成tun网卡到你的项目 | ||||||
|  |  | ||||||
|  | 在你的.NET8.0+项目中,集成tun网卡,适用于`windows`、`linux` | ||||||
|  |  | ||||||
|  | ## 1、windows | ||||||
|  |  | ||||||
|  | [下载wintun](https://www.wintun.net/),选择适合你系统的 `wintun.dll`放到项目根目录,然后nuget 安装 `linker.tun` | ||||||
|  |  | ||||||
|  | ## 2、linux | ||||||
|  |  | ||||||
|  | 请确保你的系统拥有`tuntap`模块,`ifconfig`、`ip`命令 | ||||||
|  |  | ||||||
|  | ## 3、编写一个简单的代码 | ||||||
|  | ```c# | ||||||
|  |  | ||||||
|  | internal class Program | ||||||
|  | { | ||||||
|  |     public static LinkerTunDeviceAdapter linkerTunDeviceAdapter; | ||||||
|  |     static void Main(string[] args) | ||||||
|  |     { | ||||||
|  |         linkerTunDeviceAdapter = new LinkerTunDeviceAdapter(); | ||||||
|  |         //设置网卡IP包回调 | ||||||
|  |         linkerTunDeviceAdapter.SetReadCallback(new LinkerTunDeviceCallback()); | ||||||
|  |         //启动网卡 | ||||||
|  |         linkerTunDeviceAdapter.SetUp( | ||||||
|  |             "linker" //网卡名称 | ||||||
|  |              //windows下,使用一个固定guid,否则网卡编号会不断递增,注册表不断产生新纪录 | ||||||
|  |             , Guid.Parse("dc6d4efa-2b53-41bd-a403-f416c9bf7129") | ||||||
|  |             , IPAddress.Parse("192.168.54.2"), 24); //网卡IP和掩码 | ||||||
|  |         //设置MTU | ||||||
|  |         linkerTunDeviceAdapter.SetMtu(1420); | ||||||
|  |  | ||||||
|  |         //如果存在错误 | ||||||
|  |         if (string.IsNullOrWhiteSpace(linkerTunDeviceAdapter.Error)) | ||||||
|  |         { | ||||||
|  |             Console.WriteLine(linkerTunDeviceAdapter.Error); | ||||||
|  |             //关闭网卡 | ||||||
|  |             linkerTunDeviceAdapter.Shutdown(); | ||||||
|  |         } | ||||||
|  |         Console.ReadLine(); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | public sealed class LinkerTunDeviceCallback : ILinkerTunDeviceCallback | ||||||
|  | { | ||||||
|  |     //收到IP数据包 | ||||||
|  |     public async Task Callback(LinkerTunDevicPacket packet) | ||||||
|  |     { | ||||||
|  |         ICMPAnswer(packet); | ||||||
|  |         await Task.CompletedTask; | ||||||
|  |     } | ||||||
|  |     private unsafe void ICMPAnswer(LinkerTunDevicPacket packet) | ||||||
|  |     { | ||||||
|  |         //去掉首部表示包长度的4字节, | ||||||
|  |         Memory<byte> writableMemory = MemoryMarshal.AsMemory(packet.Packet.Slice(4)); | ||||||
|  |         fixed (byte* ptr = writableMemory.Span) | ||||||
|  |         { | ||||||
|  |             //ICMP包,且是 Request | ||||||
|  |             if (ptr[9] == 1 && ptr[20] == 8) | ||||||
|  |             { | ||||||
|  |                 Console.WriteLine($"ICMP to {new IPAddress(writableMemory.Span.Slice(16, 4))}"); | ||||||
|  |  | ||||||
|  |                 uint dist = BinaryPrimitives.ReadUInt32LittleEndian(writableMemory.Span.Slice(16, 4)); | ||||||
|  |                 //目的地址变源地址, | ||||||
|  |                 *(uint*)(ptr + 16) = *(uint*)(ptr + 12); | ||||||
|  |                 //假装是网关回复的 | ||||||
|  |                 *(uint*)(ptr + 12) = dist; | ||||||
|  |  | ||||||
|  |                 //计算一次IP头校验和 | ||||||
|  |                 *(ushort*)(ptr + 10) = 0; | ||||||
|  |                 *(ushort*)(ptr + 10) = Program.linkerTunDeviceAdapter.Checksum((ushort*)ptr, 20); | ||||||
|  |  | ||||||
|  |                 //改为ICMP Reply | ||||||
|  |                 *(ushort*)(ptr + 20) = 0; | ||||||
|  |  | ||||||
|  |                 //计算ICMP校验和 | ||||||
|  |                 *(ushort*)(ptr + 22) = 0; | ||||||
|  |                 *(ushort*)(ptr + 22) = Program.linkerTunDeviceAdapter.Checksum((ushort*)(ptr + 20), (uint)(writableMemory.Length - 20)); | ||||||
|  |  | ||||||
|  |                 //写入网卡,回应这个ICMP请求 | ||||||
|  |                 Program.linkerTunDeviceAdapter.Write(writableMemory); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | ``` | ||||||
| @@ -1,9 +0,0 @@ | |||||||
| --- |  | ||||||
| sidebar_position: 8 |  | ||||||
| --- |  | ||||||
|  |  | ||||||
| # 8、集成虚拟网卡到你的项目 |  | ||||||
|  |  | ||||||
| :::tip[说明] |  | ||||||
| 还没写完,敬请期待 |  | ||||||
| ::: |  | ||||||
| @@ -15,8 +15,8 @@ | |||||||
| 		<PackageProjectUrl>https://github.com/snltty/linker</PackageProjectUrl> | 		<PackageProjectUrl>https://github.com/snltty/linker</PackageProjectUrl> | ||||||
| 		<RepositoryUrl>https://github.com/snltty/linker</RepositoryUrl> | 		<RepositoryUrl>https://github.com/snltty/linker</RepositoryUrl> | ||||||
| 		<Version>1.2.0</Version> | 		<Version>1.2.0</Version> | ||||||
| 		<AssemblyVersion>1.2.0.2</AssemblyVersion> | 		<AssemblyVersion>1.2.0.3</AssemblyVersion> | ||||||
| 		<FileVersion>1.2.0.2</FileVersion> | 		<FileVersion>1.2.0.3</FileVersion> | ||||||
| 	</PropertyGroup> | 	</PropertyGroup> | ||||||
| 	<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> | 	<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> | ||||||
| 		<DebugType>full</DebugType> | 		<DebugType>full</DebugType> | ||||||
|   | |||||||
| @@ -22,8 +22,8 @@ | |||||||
| 		<PackageProjectUrl>https://github.com/snltty/linker</PackageProjectUrl> | 		<PackageProjectUrl>https://github.com/snltty/linker</PackageProjectUrl> | ||||||
| 		<RepositoryUrl>https://github.com/snltty/linker</RepositoryUrl> | 		<RepositoryUrl>https://github.com/snltty/linker</RepositoryUrl> | ||||||
| 		<PackageReleaseNotes>snltty service</PackageReleaseNotes> | 		<PackageReleaseNotes>snltty service</PackageReleaseNotes> | ||||||
| 		<AssemblyVersion>1.2.0.2</AssemblyVersion> | 		<AssemblyVersion>1.2.0.3</AssemblyVersion> | ||||||
| 		<FileVersion>1.2.0.2</FileVersion> | 		<FileVersion>1.2.0.3</FileVersion> | ||||||
| 	</PropertyGroup> | 	</PropertyGroup> | ||||||
|  |  | ||||||
| 	<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> | 	<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> | ||||||
|   | |||||||
| @@ -10,7 +10,7 @@ namespace linker.tun.test | |||||||
|         static void Main(string[] args) |         static void Main(string[] args) | ||||||
|         { |         { | ||||||
|             linkerTunDeviceAdapter = new LinkerTunDeviceAdapter(); |             linkerTunDeviceAdapter = new LinkerTunDeviceAdapter(); | ||||||
|             linkerTunDeviceAdapter.SetCallback(new LinkerTunDeviceCallback()); |             linkerTunDeviceAdapter.SetReadCallback(new LinkerTunDeviceCallback()); | ||||||
|             linkerTunDeviceAdapter.SetUp("linker111" |             linkerTunDeviceAdapter.SetUp("linker111" | ||||||
|                 , Guid.Parse("dc6d4efa-2b53-41bd-a403-f416c9bf7129") |                 , Guid.Parse("dc6d4efa-2b53-41bd-a403-f416c9bf7129") | ||||||
|                 , IPAddress.Parse("192.168.55.2"), 24); |                 , IPAddress.Parse("192.168.55.2"), 24); | ||||||
|   | |||||||
| @@ -3,6 +3,9 @@ using System.Net; | |||||||
|  |  | ||||||
| namespace linker.tun | namespace linker.tun | ||||||
| { | { | ||||||
|  |     /// <summary> | ||||||
|  |     /// linker tun网卡适配器,自动选择不同平台的实现 | ||||||
|  |     /// </summary> | ||||||
|     public sealed class LinkerTunDeviceAdapter |     public sealed class LinkerTunDeviceAdapter | ||||||
|     { |     { | ||||||
|         private ILinkerTunDevice linkerTunDevice; |         private ILinkerTunDevice linkerTunDevice; | ||||||
| @@ -27,20 +30,19 @@ namespace linker.tun | |||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         /// <summary> |  | ||||||
|         /// 构造 |  | ||||||
|         /// </summary> |  | ||||||
|         /// <param name="linkerTunDeviceCallback">数据包回调</param> |  | ||||||
|         public LinkerTunDeviceAdapter() |         public LinkerTunDeviceAdapter() | ||||||
|         { |         { | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         public void SetCallback(ILinkerTunDeviceCallback linkerTunDeviceCallback) |         /// <summary> | ||||||
|  |         /// 设置网卡读取回调 | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="linkerTunDeviceCallback"></param> | ||||||
|  |         public void SetReadCallback(ILinkerTunDeviceCallback linkerTunDeviceCallback) | ||||||
|         { |         { | ||||||
|             this.linkerTunDeviceCallback = linkerTunDeviceCallback; |             this.linkerTunDeviceCallback = linkerTunDeviceCallback; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// 开启网卡 |         /// 开启网卡 | ||||||
|         /// </summary> |         /// </summary> | ||||||
| @@ -48,11 +50,12 @@ namespace linker.tun | |||||||
|         /// <param name="guid">windows的时候,需要一个固定guid,不然网卡编号一直递增,注册表一直新增记录</param> |         /// <param name="guid">windows的时候,需要一个固定guid,不然网卡编号一直递增,注册表一直新增记录</param> | ||||||
|         /// <param name="address">网卡IP</param> |         /// <param name="address">网卡IP</param> | ||||||
|         /// <param name="prefixLength">掩码。一般24即可</param> |         /// <param name="prefixLength">掩码。一般24即可</param> | ||||||
|         public void SetUp(string name, Guid guid, IPAddress address, byte prefixLength) |         public bool SetUp(string name, Guid guid, IPAddress address, byte prefixLength) | ||||||
|         { |         { | ||||||
|             if (Interlocked.CompareExchange(ref starting, 1, 0) == 1) |             if (Interlocked.CompareExchange(ref starting, 1, 0) == 1) | ||||||
|             { |             { | ||||||
|                 return; |                 error = $"setup are operating"; | ||||||
|  |                 return false; | ||||||
|             } |             } | ||||||
|             Shutdown(); |             Shutdown(); | ||||||
|             try |             try | ||||||
| @@ -75,14 +78,14 @@ namespace linker.tun | |||||||
|                 if (linkerTunDevice == null) |                 if (linkerTunDevice == null) | ||||||
|                 { |                 { | ||||||
|                     error = $"{System.Runtime.InteropServices.RuntimeInformation.OSDescription} not support"; |                     error = $"{System.Runtime.InteropServices.RuntimeInformation.OSDescription} not support"; | ||||||
|                     return; |                     return false; | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|                 linkerTunDevice.Shutdown(); |                 linkerTunDevice.Shutdown(); | ||||||
|                 linkerTunDevice.SetUp(address, NetworkHelper.ToGatewayIP(address, prefixLength), prefixLength, out error); |                 linkerTunDevice.SetUp(address, NetworkHelper.ToGatewayIP(address, prefixLength), prefixLength, out error); | ||||||
|                 if (string.IsNullOrWhiteSpace(error) == false) |                 if (string.IsNullOrWhiteSpace(error) == false) | ||||||
|                 { |                 { | ||||||
|                     return; |                     return false; | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|                 cancellationTokenSource = new CancellationTokenSource(); |                 cancellationTokenSource = new CancellationTokenSource(); | ||||||
| @@ -127,6 +130,7 @@ namespace linker.tun | |||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|                 }); |                 }); | ||||||
|  |                 return true; | ||||||
|             } |             } | ||||||
|             catch (Exception ex) |             catch (Exception ex) | ||||||
|             { |             { | ||||||
| @@ -136,6 +140,7 @@ namespace linker.tun | |||||||
|             { |             { | ||||||
|                 Interlocked.Exchange(ref starting, 0); |                 Interlocked.Exchange(ref starting, 0); | ||||||
|             } |             } | ||||||
|  |             return false; | ||||||
|         } |         } | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// 关闭网卡 |         /// 关闭网卡 | ||||||
| @@ -152,15 +157,24 @@ namespace linker.tun | |||||||
|             error = string.Empty; |             error = string.Empty; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// 设置MTU | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="value"></param> | ||||||
|         public void SetMtu(int value) |         public void SetMtu(int value) | ||||||
|         { |         { | ||||||
|             linkerTunDevice?.SetMtu(value); |             linkerTunDevice?.SetMtu(value); | ||||||
|         } |         } | ||||||
|  |         /// <summary> | ||||||
|  |         /// 添加NAT转发 | ||||||
|  |         /// </summary> | ||||||
|         public void SetNat() |         public void SetNat() | ||||||
|         { |         { | ||||||
|             linkerTunDevice?.SetNat(); |             linkerTunDevice?.SetNat(); | ||||||
|         } |         } | ||||||
|  |         /// <summary> | ||||||
|  |         /// 移除NAT转发 | ||||||
|  |         /// </summary> | ||||||
|         public void RemoveNat() |         public void RemoveNat() | ||||||
|         { |         { | ||||||
|             linkerTunDevice?.RemoveNat(); |             linkerTunDevice?.RemoveNat(); | ||||||
|   | |||||||
| @@ -120,7 +120,6 @@ namespace linker.tun | |||||||
|             CommandHelper.PowerShell(string.Empty, new string[] { $"Remove-NetNat -Name {Name}" }); |             CommandHelper.PowerShell(string.Empty, new string[] { $"Remove-NetNat -Name {Name}" }); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |  | ||||||
|         public void AddRoute(LinkerTunDeviceRouteItem[] ips, IPAddress ip) |         public void AddRoute(LinkerTunDeviceRouteItem[] ips, IPAddress ip) | ||||||
|         { |         { | ||||||
|             if (interfaceNumber > 0) |             if (interfaceNumber > 0) | ||||||
|   | |||||||
| @@ -17,8 +17,8 @@ | |||||||
| 		<PackageProjectUrl>https://github.com/snltty/linker</PackageProjectUrl> | 		<PackageProjectUrl>https://github.com/snltty/linker</PackageProjectUrl> | ||||||
| 		<RepositoryUrl>https://github.com/snltty/linker</RepositoryUrl> | 		<RepositoryUrl>https://github.com/snltty/linker</RepositoryUrl> | ||||||
| 		<PackageReleaseNotes>linker tun</PackageReleaseNotes> | 		<PackageReleaseNotes>linker tun</PackageReleaseNotes> | ||||||
| 		<AssemblyVersion>1.2.0.2</AssemblyVersion> | 		<AssemblyVersion>1.2.0.3</AssemblyVersion> | ||||||
| 		<FileVersion>1.2.0.2</FileVersion> | 		<FileVersion>1.2.0.3</FileVersion> | ||||||
| 	</PropertyGroup> | 	</PropertyGroup> | ||||||
|  |  | ||||||
| 	<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> | 	<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> | ||||||
|   | |||||||
| @@ -17,8 +17,8 @@ | |||||||
| 		<PackageProjectUrl>https://github.com/snltty/linker</PackageProjectUrl> | 		<PackageProjectUrl>https://github.com/snltty/linker</PackageProjectUrl> | ||||||
| 		<RepositoryUrl>https://github.com/snltty/linker</RepositoryUrl> | 		<RepositoryUrl>https://github.com/snltty/linker</RepositoryUrl> | ||||||
| 		<PackageReleaseNotes>linker tunnel</PackageReleaseNotes> | 		<PackageReleaseNotes>linker tunnel</PackageReleaseNotes> | ||||||
| 		<AssemblyVersion>1.2.0.2</AssemblyVersion> | 		<AssemblyVersion>1.2.0.3</AssemblyVersion> | ||||||
| 		<FileVersion>1.2.0.2</FileVersion> | 		<FileVersion>1.2.0.3</FileVersion> | ||||||
| 	</PropertyGroup> | 	</PropertyGroup> | ||||||
|  |  | ||||||
| 	<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> | 	<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> | ||||||
|   | |||||||
| @@ -3,8 +3,7 @@ | |||||||
|         <el-form ref="formDom" :model="state.form" :rules="state.rules" label-width="8rem"> |         <el-form ref="formDom" :model="state.form" :rules="state.rules" label-width="8rem"> | ||||||
|             <el-form-item label="" label-width="0"> |             <el-form-item label="" label-width="0"> | ||||||
|                 <div class="t-c w-100"> |                 <div class="t-c w-100"> | ||||||
|                     <p>端口为0则不监听</p> |                     <p>端口为0则不监听,相同分组名之间的客户端相互可见</p> | ||||||
|                     <p>相同分组名之间的客户端相互可见</p> |  | ||||||
|                 </div> |                 </div> | ||||||
|             </el-form-item> |             </el-form-item> | ||||||
|             <el-form-item label="" label-width="0"> |             <el-form-item label="" label-width="0"> | ||||||
| @@ -36,10 +35,47 @@ | |||||||
|                 </el-row> |                 </el-row> | ||||||
|             </el-form-item> |             </el-form-item> | ||||||
|             <el-form-item label="" label-width="0"> |             <el-form-item label="" label-width="0"> | ||||||
|  |                 <el-row> | ||||||
|  |                     <el-col :span="12"> | ||||||
|                         <el-form-item label="接口密码" prop="password"> |                         <el-form-item label="接口密码" prop="password"> | ||||||
|                     <el-input type="password" v-model="state.form.password" show-password maxlength="36" |                             <el-input  style="width:42rem"  type="password" v-model="state.form.password" show-password maxlength="36" show-word-limit/> | ||||||
|                         show-word-limit /> |  | ||||||
|                         </el-form-item> |                         </el-form-item> | ||||||
|  |                     </el-col> | ||||||
|  |                     <el-col :span="12"> | ||||||
|  |                         <el-form-item label-width="8rem" prop="hasServer"> | ||||||
|  |                             <el-checkbox v-model="state.form.hasServer" label="我有服务器" size="large" /> | ||||||
|  |                         </el-form-item> | ||||||
|  |                     </el-col> | ||||||
|  |                 </el-row> | ||||||
|  |             </el-form-item> | ||||||
|  |  | ||||||
|  |             <el-form-item label="" label-width="0" v-if="state.form.hasServer"> | ||||||
|  |                 <el-row> | ||||||
|  |                     <el-col :span="12"> | ||||||
|  |                         <el-form-item label="服务器" prop="server"> | ||||||
|  |                             <el-input v-model="state.form.server"/> | ||||||
|  |                         </el-form-item> | ||||||
|  |                     </el-col> | ||||||
|  |                     <el-col :span="12"> | ||||||
|  |                         <el-form-item label="更新密钥" prop="updaterSecretKey"> | ||||||
|  |                             <el-input v-model="state.form.updaterSecretKey" maxlength="36" show-word-limit /> | ||||||
|  |                         </el-form-item> | ||||||
|  |                     </el-col> | ||||||
|  |                 </el-row> | ||||||
|  |             </el-form-item> | ||||||
|  |             <el-form-item label="" label-width="0" v-if="state.form.hasServer"> | ||||||
|  |                 <el-row> | ||||||
|  |                     <el-col :span="12"> | ||||||
|  |                         <el-form-item label="穿透密钥" prop="sForwardSecretKey"> | ||||||
|  |                             <el-input v-model="state.form.sForwardSecretKey" maxlength="36" show-word-limit /> | ||||||
|  |                         </el-form-item> | ||||||
|  |                     </el-col> | ||||||
|  |                     <el-col :span="12"> | ||||||
|  |                         <el-form-item label="中继密钥" prop="relaySecretKey"> | ||||||
|  |                             <el-input v-model="state.form.relaySecretKey" maxlength="36" show-word-limit /> | ||||||
|  |                         </el-form-item> | ||||||
|  |                     </el-col> | ||||||
|  |                 </el-row> | ||||||
|             </el-form-item> |             </el-form-item> | ||||||
|         </el-form> |         </el-form> | ||||||
|     </div> |     </div> | ||||||
| @@ -55,11 +91,17 @@ export default { | |||||||
|  |  | ||||||
|         const state = reactive({ |         const state = reactive({ | ||||||
|             form: { |             form: { | ||||||
|                 name: globalData.value.config.Client.Name, |                 name:step.value.form.client.name || globalData.value.config.Client.Name, | ||||||
|                 groupid: globalData.value.config.Client.GroupId, |                 groupid: step.value.form.client.groupid ||globalData.value.config.Client.GroupId, | ||||||
|                 api: globalData.value.config.Client.CApi.ApiPort, |                 api: step.value.form.client.api ||globalData.value.config.Client.CApi.ApiPort, | ||||||
|                 web: globalData.value.config.Client.CApi.WebPort, |                 web: step.value.form.client.web ||globalData.value.config.Client.CApi.WebPort, | ||||||
|                 password: globalData.value.config.Client.CApi.ApiPassword |                 password:step.value.form.client.password || globalData.value.config.Client.CApi.ApiPassword, | ||||||
|  |  | ||||||
|  |                 hasServer:step.value.form.client.hasServer ||false, | ||||||
|  |                 server:step.value.form.client.server ||globalData.value.config.Client.Server, | ||||||
|  |                 sForwardSecretKey:step.value.form.client.sForwardSecretKey ||globalData.value.config.Running.SForwardSecretKey, | ||||||
|  |                 relaySecretKey:step.value.form.client.relaySecretKey ||(globalData.value.config.Running.Relay.Servers[0] || {SecretKey:'snltty'}).SecretKey, | ||||||
|  |                 updaterSecretKey:step.value.form.client.updaterSecretKey ||globalData.value.config.Running.UpdaterSecretKey, | ||||||
|             }, |             }, | ||||||
|             rules: { |             rules: { | ||||||
|                 name: [{ required: true, message: "必填", trigger: "blur" }], |                 name: [{ required: true, message: "必填", trigger: "blur" }], | ||||||
| @@ -99,12 +141,23 @@ export default { | |||||||
|                 formDom.value.validate((valid) => { |                 formDom.value.validate((valid) => { | ||||||
|                     if (valid) { |                     if (valid) { | ||||||
|                         resolve({ |                         resolve({ | ||||||
|  |                             json:{ | ||||||
|                                 Client:{ |                                 Client:{ | ||||||
|                                     name: state.form.name, |                                     name: state.form.name, | ||||||
|                                     groupid: state.form.groupid, |                                     groupid: state.form.groupid, | ||||||
|                                     api: +state.form.api, |                                     api: +state.form.api, | ||||||
|                                     web: +state.form.web, |                                     web: +state.form.web, | ||||||
|                                 password: state.form.password |                                     password: state.form.password, | ||||||
|  |  | ||||||
|  |                                     hasServer: state.form.hasServer, | ||||||
|  |                                     server: state.form.server, | ||||||
|  |                                     sForwardSecretKey: state.form.sForwardSecretKey, | ||||||
|  |                                     relaySecretKey: state.form.relaySecretKey, | ||||||
|  |                                     updaterSecretKey: state.form.updaterSecretKey, | ||||||
|  |                                 } | ||||||
|  |                             }, | ||||||
|  |                             form:{ | ||||||
|  |                                 client:JSON.parse(JSON.stringify(state.form)) | ||||||
|                             } |                             } | ||||||
|                         }); |                         }); | ||||||
|                     } else { |                     } else { | ||||||
|   | |||||||
| @@ -15,8 +15,8 @@ export default { | |||||||
|         const step = inject('step'); |         const step = inject('step'); | ||||||
|         const state =  reactive({ |         const state =  reactive({ | ||||||
|             form: { |             form: { | ||||||
|                 client: (step.value.json.Common && step.value.json.Common.client) || false, |                 client:step.value.form.common.client ||  (step.value.json.Common && step.value.json.Common.client) || false, | ||||||
|                 server: (step.value.json.Common && step.value.json.Common.server) || false, |                 server:step.value.form.common.server ||  (step.value.json.Common && step.value.json.Common.server) || false, | ||||||
|             } |             } | ||||||
|         }); |         }); | ||||||
|         const handleValidate = (prevJson) => { |         const handleValidate = (prevJson) => { | ||||||
| @@ -26,6 +26,7 @@ export default { | |||||||
|                     reject(); |                     reject(); | ||||||
|                 }else{ |                 }else{ | ||||||
|                     resolve({ |                     resolve({ | ||||||
|  |                         json:{ | ||||||
|                             Common:{ |                             Common:{ | ||||||
|                                 client: state.form.client, |                                 client: state.form.client, | ||||||
|                                 server: state.form.server, |                                 server: state.form.server, | ||||||
| @@ -34,6 +35,8 @@ export default { | |||||||
|                                 state.form.server ? 'server' : '' |                                 state.form.server ? 'server' : '' | ||||||
|                                 ].filter(c=>!!c) |                                 ].filter(c=>!!c) | ||||||
|                             } |                             } | ||||||
|  |                         }, | ||||||
|  |                         form:{common:JSON.parse(JSON.stringify(state.form))} | ||||||
|                     }); |                     }); | ||||||
|                 } |                 } | ||||||
|             }); |             }); | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| <template> | <template> | ||||||
|     <div> |     <div> | ||||||
|         <el-dialog v-model="state.show" title="初始化配置" width="500" top="2vh"> |         <el-dialog v-model="state.show" title="初始化配置" width="600" top="2vh"> | ||||||
|             <div> |             <div> | ||||||
|                 <div class="head"> |                 <div class="head"> | ||||||
|                     <el-steps :active="step.step" finish-status="success"> |                     <el-steps :active="step.step" finish-status="success"> | ||||||
| @@ -60,7 +60,8 @@ export default { | |||||||
|         const step = ref({ |         const step = ref({ | ||||||
|             step:1, |             step:1, | ||||||
|             increment:1, |             increment:1, | ||||||
|             json:{} |             json:{}, | ||||||
|  |             form:{server:{},client:{},common:{}} | ||||||
|         }); |         }); | ||||||
|         provide('step',step); |         provide('step',step); | ||||||
|         const handlePrev = ()=>{ |         const handlePrev = ()=>{ | ||||||
| @@ -70,7 +71,9 @@ export default { | |||||||
|         const handleNext = ()=>{ |         const handleNext = ()=>{ | ||||||
|             step.value.increment = 1; |             step.value.increment = 1; | ||||||
|             currentDom.value.handleValidate().then((json)=>{ |             currentDom.value.handleValidate().then((json)=>{ | ||||||
|                 step.value.json = Object.assign(step.value.json,json); |                 step.value.json = Object.assign(step.value.json,json.json); | ||||||
|  |                 step.value.form = Object.assign(step.value.form,json.form); | ||||||
|  |                 console.log(step.value); | ||||||
|                 step.value.step ++; |                 step.value.step ++; | ||||||
|             }).catch(()=>{ |             }).catch(()=>{ | ||||||
|             }); |             }); | ||||||
|   | |||||||
| @@ -63,14 +63,14 @@ export default { | |||||||
|         const state = reactive({ |         const state = reactive({ | ||||||
|             show: false, |             show: false, | ||||||
|             form: { |             form: { | ||||||
|                 relaySecretKey:globalData.value.config.Server.Relay.SecretKey, |                 relaySecretKey:step.value.form.server.relaySecretKey || globalData.value.config.Server.Relay.SecretKey, | ||||||
|                 sForwardSecretKey:globalData.value.config.Server.SForward.SecretKey, |                 sForwardSecretKey:step.value.form.server.sForwardSecretKey ||globalData.value.config.Server.SForward.SecretKey, | ||||||
|                 servicePort:globalData.value.config.Server.ServicePort, |                 servicePort:step.value.form.server.servicePort ||globalData.value.config.Server.ServicePort, | ||||||
|                 webPort:globalData.value.config.Server.SForward.WebPort, |                 webPort:step.value.form.server.webPort ||globalData.value.config.Server.SForward.WebPort, | ||||||
|                 tunnelPort1:globalData.value.config.Server.SForward.TunnelPortRange[0], |                 tunnelPort1:step.value.form.server.tunnelPort1 ||globalData.value.config.Server.SForward.TunnelPortRange[0], | ||||||
|                 tunnelPort2:globalData.value.config.Server.SForward.TunnelPortRange[1], |                 tunnelPort2:step.value.form.server.tunnelPort2 ||globalData.value.config.Server.SForward.TunnelPortRange[1], | ||||||
|  |  | ||||||
|                 updaterSecretKey:globalData.value.config.Server.Updater.SecretKey, |                 updaterSecretKey:step.value.form.server.updaterSecretKey ||globalData.value.config.Server.Updater.SecretKey, | ||||||
|             }, |             }, | ||||||
|             rules: { |             rules: { | ||||||
|                 relaySecretKey: [{ required: true, message: "必填", trigger: "blur" }], |                 relaySecretKey: [{ required: true, message: "必填", trigger: "blur" }], | ||||||
| @@ -138,6 +138,7 @@ export default { | |||||||
|                         reject(); |                         reject(); | ||||||
|                     }else{ |                     }else{ | ||||||
|                         resolve({ |                         resolve({ | ||||||
|  |                             json:{ | ||||||
|                                 Server:{ |                                 Server:{ | ||||||
|                                     ServicePort: +state.form.servicePort, |                                     ServicePort: +state.form.servicePort, | ||||||
|                                     Relay:{ |                                     Relay:{ | ||||||
| @@ -152,6 +153,8 @@ export default { | |||||||
|                                         SecretKey: state.form.updaterSecretKey |                                         SecretKey: state.form.updaterSecretKey | ||||||
|                                     } |                                     } | ||||||
|                                 }   |                                 }   | ||||||
|  |                             }, | ||||||
|  |                             form:{server:JSON.parse(JSON.stringify(state.form))} | ||||||
|                         }); |                         }); | ||||||
|                     } |                     } | ||||||
|                      |                      | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| <template> | <template> | ||||||
|     <div class="status-wrap flex"> |     <div class="status-wrap flex"> | ||||||
|         <div class="copy"><a href="https://github.com/snltty/linker" target="_blank">snltty©linker v1.2.0.0</a></div> |         <div class="copy"><a href="https://github.com/snltty/linker" target="_blank">snltty©linker v1.2.0.3</a></div> | ||||||
|         <div class="flex-1"></div> |         <div class="flex-1"></div> | ||||||
|         <div class="api"><Api></Api></div> |         <div class="api"><Api></Api></div> | ||||||
|         <div class="server"><Server></Server></div> |         <div class="server"><Server></Server></div> | ||||||
|   | |||||||
| @@ -31,7 +31,7 @@ | |||||||
|                     <el-input v-model="state.form.name" maxlength="12" show-word-limit /> |                     <el-input v-model="state.form.name" maxlength="12" show-word-limit /> | ||||||
|                 </el-form-item> |                 </el-form-item> | ||||||
|                 <el-form-item label="分组名" prop="groupid"> |                 <el-form-item label="分组名" prop="groupid"> | ||||||
|                     <el-input v-model="state.form.groupid" maxlength="36" show-word-limit /> |                     <el-input v-model="state.form.groupid" type="password" show-password maxlength="36" show-word-limit /> | ||||||
|                 </el-form-item> |                 </el-form-item> | ||||||
|             </el-form> |             </el-form> | ||||||
|         </div> |         </div> | ||||||
|   | |||||||
| @@ -30,7 +30,6 @@ | |||||||
|                         {{ item }} / {{ tuntap.list[scope.row.MachineId].Masks[index] }} |                         {{ item }} / {{ tuntap.list[scope.row.MachineId].Masks[index] }} | ||||||
|                     </div> |                     </div> | ||||||
|                 </div> |                 </div> | ||||||
|                 <div class="t-r">{{ 1<<tuntap.list[scope.row.MachineId].BufferSize}}KB</div> |  | ||||||
|             </div>  |             </div>  | ||||||
|         </template> |         </template> | ||||||
|     </el-table-column> |     </el-table-column> | ||||||
|   | |||||||
| @@ -2,12 +2,15 @@ | |||||||
|      <el-dialog v-model="state.show" :close-on-click-modal="false" append-to=".app-wrap" title="设置虚拟网卡IP" width="420"> |      <el-dialog v-model="state.show" :close-on-click-modal="false" append-to=".app-wrap" title="设置虚拟网卡IP" width="420"> | ||||||
|         <div> |         <div> | ||||||
|             <el-form ref="ruleFormRef" :model="state.ruleForm" :rules="state.rules" label-width="80"> |             <el-form ref="ruleFormRef" :model="state.ruleForm" :rules="state.rules" label-width="80"> | ||||||
|                 <el-form-item label="缓冲区" prop="BufferSize"> |                 <!-- <el-form-item label="缓冲区" prop="BufferSize"> | ||||||
|                     <el-select v-model="state.ruleForm.BufferSize" placeholder="Select" style="width:12rem"> |                     <el-select v-model="state.ruleForm.BufferSize" placeholder="Select" style="width:12rem"> | ||||||
|                         <el-option v-for="(item,index) in state.bufferSize" :key="index" :label="item" :value="index"/> |                         <el-option v-for="(item,index) in state.bufferSize" :key="index" :label="item" :value="index"/> | ||||||
|                     </el-select> |                     </el-select> | ||||||
|  |                 </el-form-item> --> | ||||||
|  |                 <el-form-item label=""> | ||||||
|  |                     <div>局域网IP选填,不懂是啥的时候,不要填</div> | ||||||
|                 </el-form-item> |                 </el-form-item> | ||||||
|                 <el-form-item label="网卡IP" prop="IP"> |                 <el-form-item label="虚拟网卡IP" prop="IP"> | ||||||
|                     <el-input v-model="state.ruleForm.IP" style="width:12rem" /> / 24 |                     <el-input v-model="state.ruleForm.IP" style="width:12rem" /> / 24 | ||||||
|                 </el-form-item> |                 </el-form-item> | ||||||
|                 <el-form-item label="局域网IP" prop="LanIP"> |                 <el-form-item label="局域网IP" prop="LanIP"> | ||||||
|   | |||||||
| @@ -25,8 +25,8 @@ | |||||||
| 		<PackageProjectUrl>https://github.com/snltty/linker</PackageProjectUrl> | 		<PackageProjectUrl>https://github.com/snltty/linker</PackageProjectUrl> | ||||||
| 		<RepositoryUrl>https://github.com/snltty/linker</RepositoryUrl> | 		<RepositoryUrl>https://github.com/snltty/linker</RepositoryUrl> | ||||||
| 		<PackageReleaseNotes>linker</PackageReleaseNotes> | 		<PackageReleaseNotes>linker</PackageReleaseNotes> | ||||||
| 		<AssemblyVersion>1.2.0.2</AssemblyVersion> | 		<AssemblyVersion>1.2.0.3</AssemblyVersion> | ||||||
| 		<FileVersion>1.2.0.2</FileVersion> | 		<FileVersion>1.2.0.3</FileVersion> | ||||||
| 	</PropertyGroup> | 	</PropertyGroup> | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -34,6 +34,21 @@ namespace linker.plugins.config | |||||||
|                 config.Data.Client.CApi.WebPort = info.Client.Web; |                 config.Data.Client.CApi.WebPort = info.Client.Web; | ||||||
|                 config.Data.Client.CApi.ApiPort = info.Client.Api; |                 config.Data.Client.CApi.ApiPort = info.Client.Api; | ||||||
|                 config.Data.Client.CApi.ApiPassword = info.Client.Password; |                 config.Data.Client.CApi.ApiPassword = info.Client.Password; | ||||||
|  |  | ||||||
|  |                 if (info.Client.HasServer) | ||||||
|  |                 { | ||||||
|  |                     config.Data.Client.Server = info.Client.Server; | ||||||
|  |                     runningConfig.Data.SForwardSecretKey = info.Client.SForwardSecretKey; | ||||||
|  |                     runningConfig.Data.UpdaterSecretKey = info.Client.UpdaterSecretKey; | ||||||
|  |                     foreach (var item in runningConfig.Data.Relay.Servers) | ||||||
|  |                     { | ||||||
|  |                         item.SecretKey = info.Client.RelaySecretKey; | ||||||
|  |                     } | ||||||
|  |                     foreach (var item in runningConfig.Data.Tunnel.Servers) | ||||||
|  |                     { | ||||||
|  |                         item.Host = info.Client.Server; | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|             } |             } | ||||||
|             if (info.Common.Modes.Contains("server")) |             if (info.Common.Modes.Contains("server")) | ||||||
|             { |             { | ||||||
| @@ -50,6 +65,9 @@ namespace linker.plugins.config | |||||||
|             config.Data.Common.Modes = info.Common.Modes; |             config.Data.Common.Modes = info.Common.Modes; | ||||||
|             config.Data.Common.Install = true; |             config.Data.Common.Install = true; | ||||||
|             config.Data.Update(); |             config.Data.Update(); | ||||||
|  |  | ||||||
|  |             runningConfig.Data.Update(); | ||||||
|  |  | ||||||
|             return true; |             return true; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @@ -67,6 +85,12 @@ namespace linker.plugins.config | |||||||
|         public int Api { get; set; } |         public int Api { get; set; } | ||||||
|         public int Web { get; set; } |         public int Web { get; set; } | ||||||
|         public string Password { get; set; } |         public string Password { get; set; } | ||||||
|  |  | ||||||
|  |         public bool HasServer { get; set; } | ||||||
|  |         public string Server { get; set; } | ||||||
|  |         public string SForwardSecretKey { get; set; } | ||||||
|  |         public string RelaySecretKey { get; set; } | ||||||
|  |         public string UpdaterSecretKey { get; set; } | ||||||
|     } |     } | ||||||
|     public sealed class ConfigInstallServerInfo |     public sealed class ConfigInstallServerInfo | ||||||
|     { |     { | ||||||
|   | |||||||
| @@ -58,7 +58,7 @@ namespace linker.plugins.tuntap | |||||||
|                 } |                 } | ||||||
|             }; |             }; | ||||||
|  |  | ||||||
|             linkerTunDeviceAdapter.SetCallback(tuntapProxy); |             linkerTunDeviceAdapter.SetReadCallback(tuntapProxy); | ||||||
|             linkerTunDeviceAdapter.Shutdown(); |             linkerTunDeviceAdapter.Shutdown(); | ||||||
|             AppDomain.CurrentDomain.ProcessExit += (s, e) => Shutdown(); |             AppDomain.CurrentDomain.ProcessExit += (s, e) => Shutdown(); | ||||||
|             Console.CancelKeyPress += (s, e) => Shutdown(); |             Console.CancelKeyPress += (s, e) => Shutdown(); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 snltty
					snltty