diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index d6838c73..aa031036 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -48,19 +48,13 @@ jobs: env: GITHUB_TOKEN: '${{ secrets.ACTIONS_TOKEN }}' with: - tag_name: v1.2.0.2 - release_name: v1.2.0.2.${{ steps.date.outputs.today }} + tag_name: v1.2.0.3 + release_name: v1.2.0.3.${{ steps.date.outputs.today }} draft: false prerelease: false body: | - 1. 网关层级计算修复(在linux下计算错误导致打洞失败) - 2. 修复在IPV6环境下域名解析缓慢问题 - 3. 新增基于端口映射的打洞协议 - 4. 修复端口转发潜在BUG - 5. 虚拟网卡支持广播组播了 - 6. 修复了socks5的一些问题 - 7. 增加了docker宿主机访问策略,docker也可以用虚拟网卡通信了 - 8. 请更新服务端 + 1. 这是一个测试版本,请使用v1.2.0.2版本 + 2. 请勿更新 - name: upload win x64 id: upload-win-x64 diff --git a/.github/workflows/nuget.yml b/.github/workflows/nuget.yml index ab2082f7..bd430559 100644 --- a/.github/workflows/nuget.yml +++ b/.github/workflows/nuget.yml @@ -23,11 +23,13 @@ jobs: run: | dotnet build ./linker.libs -c release dotnet build ./linker.tunnel -c release + dotnet build ./linker.tun -c release - name: Pack run: | dotnet pack ./linker.libs -c release dotnet pack ./linker.tunnel -c release + dotnet pack ./linker.tun -c release - name: Install Nuget uses: nuget/setup-nuget@v1 @@ -38,3 +40,4 @@ jobs: 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.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 diff --git a/linker.doc.web/docs/8、集成tun网卡到你的项目.md b/linker.doc.web/docs/8、集成tun网卡到你的项目.md new file mode 100644 index 00000000..89379081 --- /dev/null +++ b/linker.doc.web/docs/8、集成tun网卡到你的项目.md @@ -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 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); + } + } + } +} +``` \ No newline at end of file diff --git a/linker.doc.web/docs/8、集成虚拟网卡到你的项目.md b/linker.doc.web/docs/8、集成虚拟网卡到你的项目.md deleted file mode 100644 index dac2d1e5..00000000 --- a/linker.doc.web/docs/8、集成虚拟网卡到你的项目.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -sidebar_position: 8 ---- - -# 8、集成虚拟网卡到你的项目 - -:::tip[说明] -还没写完,敬请期待 -::: \ No newline at end of file diff --git a/linker.libs/linker.libs.csproj b/linker.libs/linker.libs.csproj index 0aecaea4..d1b6a32d 100644 --- a/linker.libs/linker.libs.csproj +++ b/linker.libs/linker.libs.csproj @@ -15,8 +15,8 @@ https://github.com/snltty/linker https://github.com/snltty/linker 1.2.0 - 1.2.0.2 - 1.2.0.2 + 1.2.0.3 + 1.2.0.3 full diff --git a/linker.service/linker.service.csproj b/linker.service/linker.service.csproj index e278d693..176ec8ee 100644 --- a/linker.service/linker.service.csproj +++ b/linker.service/linker.service.csproj @@ -22,8 +22,8 @@ https://github.com/snltty/linker https://github.com/snltty/linker snltty service - 1.2.0.2 - 1.2.0.2 + 1.2.0.3 + 1.2.0.3 diff --git a/linker.tun.test/Program.cs b/linker.tun.test/Program.cs index f606e452..0125ada3 100644 --- a/linker.tun.test/Program.cs +++ b/linker.tun.test/Program.cs @@ -10,7 +10,7 @@ namespace linker.tun.test static void Main(string[] args) { linkerTunDeviceAdapter = new LinkerTunDeviceAdapter(); - linkerTunDeviceAdapter.SetCallback(new LinkerTunDeviceCallback()); + linkerTunDeviceAdapter.SetReadCallback(new LinkerTunDeviceCallback()); linkerTunDeviceAdapter.SetUp("linker111" , Guid.Parse("dc6d4efa-2b53-41bd-a403-f416c9bf7129") , IPAddress.Parse("192.168.55.2"), 24); diff --git a/linker.tun/LinkerTunDeviceAdapter.cs b/linker.tun/LinkerTunDeviceAdapter.cs index 3d824ae0..6cb636b0 100644 --- a/linker.tun/LinkerTunDeviceAdapter.cs +++ b/linker.tun/LinkerTunDeviceAdapter.cs @@ -3,6 +3,9 @@ using System.Net; namespace linker.tun { + /// + /// linker tun网卡适配器,自动选择不同平台的实现 + /// public sealed class LinkerTunDeviceAdapter { private ILinkerTunDevice linkerTunDevice; @@ -27,20 +30,19 @@ namespace linker.tun } } - /// - /// 构造 - /// - /// 数据包回调 public LinkerTunDeviceAdapter() { } - public void SetCallback(ILinkerTunDeviceCallback linkerTunDeviceCallback) + /// + /// 设置网卡读取回调 + /// + /// + public void SetReadCallback(ILinkerTunDeviceCallback linkerTunDeviceCallback) { this.linkerTunDeviceCallback = linkerTunDeviceCallback; } - /// /// 开启网卡 /// @@ -48,11 +50,12 @@ namespace linker.tun /// windows的时候,需要一个固定guid,不然网卡编号一直递增,注册表一直新增记录 /// 网卡IP /// 掩码。一般24即可 - 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) { - return; + error = $"setup are operating"; + return false; } Shutdown(); try @@ -75,14 +78,14 @@ namespace linker.tun if (linkerTunDevice == null) { error = $"{System.Runtime.InteropServices.RuntimeInformation.OSDescription} not support"; - return; + return false; } linkerTunDevice.Shutdown(); linkerTunDevice.SetUp(address, NetworkHelper.ToGatewayIP(address, prefixLength), prefixLength, out error); if (string.IsNullOrWhiteSpace(error) == false) { - return; + return false; } cancellationTokenSource = new CancellationTokenSource(); @@ -127,6 +130,7 @@ namespace linker.tun } } }); + return true; } catch (Exception ex) { @@ -136,6 +140,7 @@ namespace linker.tun { Interlocked.Exchange(ref starting, 0); } + return false; } /// /// 关闭网卡 @@ -152,15 +157,24 @@ namespace linker.tun error = string.Empty; } - + /// + /// 设置MTU + /// + /// public void SetMtu(int value) { linkerTunDevice?.SetMtu(value); } + /// + /// 添加NAT转发 + /// public void SetNat() { linkerTunDevice?.SetNat(); } + /// + /// 移除NAT转发 + /// public void RemoveNat() { linkerTunDevice?.RemoveNat(); diff --git a/linker.tun/LinkerWinTunDevice.cs b/linker.tun/LinkerWinTunDevice.cs index e1ce7a0e..f83adb35 100644 --- a/linker.tun/LinkerWinTunDevice.cs +++ b/linker.tun/LinkerWinTunDevice.cs @@ -120,7 +120,6 @@ namespace linker.tun CommandHelper.PowerShell(string.Empty, new string[] { $"Remove-NetNat -Name {Name}" }); } - public void AddRoute(LinkerTunDeviceRouteItem[] ips, IPAddress ip) { if (interfaceNumber > 0) diff --git a/linker.tun/linker.tun.csproj b/linker.tun/linker.tun.csproj index 6137061d..3222eb77 100644 --- a/linker.tun/linker.tun.csproj +++ b/linker.tun/linker.tun.csproj @@ -17,8 +17,8 @@ https://github.com/snltty/linker https://github.com/snltty/linker linker tun - 1.2.0.2 - 1.2.0.2 + 1.2.0.3 + 1.2.0.3 diff --git a/linker.tunnel/linker.tunnel.csproj b/linker.tunnel/linker.tunnel.csproj index 5b77e360..a8a6506e 100644 --- a/linker.tunnel/linker.tunnel.csproj +++ b/linker.tunnel/linker.tunnel.csproj @@ -17,8 +17,8 @@ https://github.com/snltty/linker https://github.com/snltty/linker linker tunnel - 1.2.0.2 - 1.2.0.2 + 1.2.0.3 + 1.2.0.3 diff --git a/linker.web/src/components/install/Client.vue b/linker.web/src/components/install/Client.vue index 7f048cfd..e801a4e5 100644 --- a/linker.web/src/components/install/Client.vue +++ b/linker.web/src/components/install/Client.vue @@ -3,8 +3,7 @@
-

端口为0则不监听

-

相同分组名之间的客户端相互可见

+

端口为0则不监听,相同分组名之间的客户端相互可见

@@ -36,10 +35,47 @@ - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
@@ -55,11 +91,17 @@ export default { const state = reactive({ form: { - name: globalData.value.config.Client.Name, - groupid: globalData.value.config.Client.GroupId, - api: globalData.value.config.Client.CApi.ApiPort, - web: globalData.value.config.Client.CApi.WebPort, - password: globalData.value.config.Client.CApi.ApiPassword + name:step.value.form.client.name || globalData.value.config.Client.Name, + groupid: step.value.form.client.groupid ||globalData.value.config.Client.GroupId, + api: step.value.form.client.api ||globalData.value.config.Client.CApi.ApiPort, + web: step.value.form.client.web ||globalData.value.config.Client.CApi.WebPort, + 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: { name: [{ required: true, message: "必填", trigger: "blur" }], @@ -99,12 +141,23 @@ export default { formDom.value.validate((valid) => { if (valid) { resolve({ - Client:{ - name: state.form.name, - groupid: state.form.groupid, - api: +state.form.api, - web: +state.form.web, - password: state.form.password + json:{ + Client:{ + name: state.form.name, + groupid: state.form.groupid, + api: +state.form.api, + web: +state.form.web, + 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 { diff --git a/linker.web/src/components/install/Common.vue b/linker.web/src/components/install/Common.vue index 9d676050..a08a2206 100644 --- a/linker.web/src/components/install/Common.vue +++ b/linker.web/src/components/install/Common.vue @@ -15,8 +15,8 @@ export default { const step = inject('step'); const state = reactive({ form: { - client: (step.value.json.Common && step.value.json.Common.client) || false, - server: (step.value.json.Common && step.value.json.Common.server) || false, + client:step.value.form.common.client || (step.value.json.Common && step.value.json.Common.client) || false, + server:step.value.form.common.server || (step.value.json.Common && step.value.json.Common.server) || false, } }); const handleValidate = (prevJson) => { @@ -26,14 +26,17 @@ export default { reject(); }else{ resolve({ - Common:{ - client: state.form.client, - server: state.form.server, - modes:[ - state.form.client ? 'client' : '', - state.form.server ? 'server' : '' - ].filter(c=>!!c) - } + json:{ + Common:{ + client: state.form.client, + server: state.form.server, + modes:[ + state.form.client ? 'client' : '', + state.form.server ? 'server' : '' + ].filter(c=>!!c) + } + }, + form:{common:JSON.parse(JSON.stringify(state.form))} }); } }); diff --git a/linker.web/src/components/install/Index.vue b/linker.web/src/components/install/Index.vue index 3ef7e4d2..cf8e0f20 100644 --- a/linker.web/src/components/install/Index.vue +++ b/linker.web/src/components/install/Index.vue @@ -1,6 +1,6 @@