mirror of
https://github.com/snltty/linker.git
synced 2025-12-19 09:56:46 +08:00
UDP打洞
This commit is contained in:
16
.github/workflows/dotnet.yml
vendored
16
.github/workflows/dotnet.yml
vendored
@@ -48,18 +48,16 @@ jobs:
|
||||
env:
|
||||
GITHUB_TOKEN: '${{ secrets.ACTIONS_TOKEN }}'
|
||||
with:
|
||||
tag_name: v1.2.0.4
|
||||
release_name: v1.2.0.4.${{ steps.date.outputs.today }}
|
||||
tag_name: v1.2.0.5
|
||||
release_name: v1.2.0.5.${{ steps.date.outputs.today }}
|
||||
draft: false
|
||||
prerelease: false
|
||||
body: |
|
||||
1. 新增排序
|
||||
2. 新增网卡自定义掩码
|
||||
3. 新增网卡端口转发
|
||||
4. 新增托盘置顶
|
||||
5. 移除linker.service,将windows service内置
|
||||
6. windows下,需要重新卸载安装服务
|
||||
7. 先更新所有客户端,再更新服务端(先更新服务端会获取不到客户端列表)
|
||||
1. UDP端口映射连接(无ssl加密)
|
||||
2. UDP打洞,纯净版(无ssl加密)
|
||||
3. 如果当前版本小于v1.2.0.4,则windows下需要重新卸载安装服务
|
||||
4. 先更新所有客户端,再更新服务端(先更新服务端会获取不到客户端列表)
|
||||
5. 用不上无加密UDP打洞的可以不更新
|
||||
|
||||
- name: upload win x86
|
||||
id: upload-win-x86
|
||||
|
||||
242
linker.libs/Crypto.cs
Normal file
242
linker.libs/Crypto.cs
Normal file
@@ -0,0 +1,242 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
|
||||
namespace linker.libs
|
||||
{
|
||||
public interface ICryptoFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// 对称加密
|
||||
/// </summary>
|
||||
/// <param name="password"></param>
|
||||
/// <returns></returns>
|
||||
public ISymmetricCrypto CreateSymmetric(string password);
|
||||
/// <summary>
|
||||
/// 非对称加密
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <returns></returns>
|
||||
public IAsymmetricCrypto CreateAsymmetric(RsaKey key);
|
||||
}
|
||||
|
||||
public sealed class CryptoFactory : ICryptoFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// 对称加密
|
||||
/// </summary>
|
||||
/// <param name="password"></param>
|
||||
/// <returns></returns>
|
||||
public ISymmetricCrypto CreateSymmetric(string password)
|
||||
{
|
||||
return new AesCrypto(password);
|
||||
}
|
||||
/// <summary>
|
||||
/// 非对称加密
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <returns></returns>
|
||||
public IAsymmetricCrypto CreateAsymmetric(RsaKey key)
|
||||
{
|
||||
return new RsaCrypto(key);
|
||||
}
|
||||
}
|
||||
|
||||
public interface ICrypto : IDisposable
|
||||
{
|
||||
public byte[] Encode(byte[] buffer);
|
||||
public byte[] Encode(in ReadOnlyMemory<byte> buffer);
|
||||
public Memory<byte> Decode(byte[] buffer);
|
||||
public Memory<byte> Decode(in ReadOnlyMemory<byte> buffer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 非对称加密
|
||||
/// </summary>
|
||||
public interface IAsymmetricCrypto : ICrypto
|
||||
{
|
||||
public RsaKey Key { get; }
|
||||
}
|
||||
public sealed class RsaCrypto : IAsymmetricCrypto
|
||||
{
|
||||
RsaKey key = new RsaKey();
|
||||
|
||||
public RsaKey Key => key;
|
||||
public RsaCrypto()
|
||||
{
|
||||
CreateKey();
|
||||
}
|
||||
public RsaCrypto(RsaKey key)
|
||||
{
|
||||
if (key != null)
|
||||
{
|
||||
this.key = key;
|
||||
}
|
||||
else
|
||||
{
|
||||
CreateKey();
|
||||
}
|
||||
}
|
||||
public Memory<byte> Decode(byte[] buffer)
|
||||
{
|
||||
using RSACryptoServiceProvider coder = new RSACryptoServiceProvider();
|
||||
coder.FromXmlString(key.PrivateKey);
|
||||
|
||||
int blockLen = coder.KeySize / 8;
|
||||
if (buffer.Length <= blockLen)
|
||||
{
|
||||
return coder.Decrypt(buffer, false);
|
||||
}
|
||||
|
||||
using MemoryStream dataStream = new MemoryStream(buffer);
|
||||
using MemoryStream enStream = new MemoryStream();
|
||||
|
||||
byte[] data = new byte[blockLen];
|
||||
while (true)
|
||||
{
|
||||
int len = dataStream.Read(data, 0, blockLen);
|
||||
if (len == 0) break;
|
||||
|
||||
if (len == blockLen)
|
||||
{
|
||||
byte[] enBlock = coder.Decrypt(data, false);
|
||||
enStream.Write(enBlock, 0, enBlock.Length);
|
||||
}
|
||||
else
|
||||
{
|
||||
byte[] block = new byte[len];
|
||||
Array.Copy(data, 0, block, 0, len);
|
||||
|
||||
byte[] enBlock = coder.Decrypt(block, false);
|
||||
enStream.Write(enBlock, 0, enBlock.Length);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return enStream.ToArray();
|
||||
}
|
||||
public Memory<byte> Decode(in ReadOnlyMemory<byte> buffer)
|
||||
{
|
||||
return Decode(buffer.ToArray());
|
||||
}
|
||||
public byte[] Encode(byte[] buffer)
|
||||
{
|
||||
using RSACryptoServiceProvider coder = new RSACryptoServiceProvider();
|
||||
coder.FromXmlString(key.PublicKey);
|
||||
|
||||
int blockLen = coder.KeySize / 8 - 11;
|
||||
if (buffer.Length <= blockLen)
|
||||
{
|
||||
return coder.Encrypt(buffer, false);
|
||||
}
|
||||
|
||||
using MemoryStream dataStream = new MemoryStream(buffer);
|
||||
using MemoryStream enStream = new MemoryStream();
|
||||
|
||||
byte[] data = new byte[blockLen];
|
||||
while (true)
|
||||
{
|
||||
int len = dataStream.Read(data, 0, blockLen);
|
||||
if (len == 0) break;
|
||||
|
||||
if (len == blockLen)
|
||||
{
|
||||
byte[] enBlock = coder.Encrypt(data, false);
|
||||
enStream.Write(enBlock, 0, enBlock.Length);
|
||||
}
|
||||
else
|
||||
{
|
||||
byte[] block = new byte[len];
|
||||
Array.Copy(data, 0, block, 0, len);
|
||||
|
||||
byte[] enBlock = coder.Encrypt(block, false);
|
||||
enStream.Write(enBlock, 0, enBlock.Length);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return enStream.ToArray();
|
||||
}
|
||||
|
||||
public byte[] Encode(in ReadOnlyMemory<byte> buffer)
|
||||
{
|
||||
return Encode(buffer.ToArray());
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
key = null;
|
||||
}
|
||||
|
||||
private void CreateKey()
|
||||
{
|
||||
using RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
|
||||
key.PrivateKey = rsa.ToXmlString(true);
|
||||
key.PublicKey = rsa.ToXmlString(false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public sealed class RsaKey
|
||||
{
|
||||
public string PrivateKey { get; set; }
|
||||
public string PublicKey { get; set; }
|
||||
}
|
||||
|
||||
public interface ISymmetricCrypto : ICrypto
|
||||
{
|
||||
public string Password { get; set; }
|
||||
}
|
||||
public sealed class AesCrypto : ISymmetricCrypto
|
||||
{
|
||||
private ICryptoTransform encryptoTransform;
|
||||
private ICryptoTransform decryptoTransform;
|
||||
|
||||
public string Password { get; set; }
|
||||
|
||||
public AesCrypto(in string password)
|
||||
{
|
||||
Password = password;
|
||||
using Aes aes = Aes.Create();
|
||||
aes.Padding = PaddingMode.ANSIX923;
|
||||
(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 encryptoTransform.TransformFinalBlock(buffer, 0, buffer.Length);
|
||||
}
|
||||
public byte[] Encode(in ReadOnlyMemory<byte> buffer)
|
||||
{
|
||||
return Encode(buffer.ToArray());
|
||||
}
|
||||
public Memory<byte> Decode(byte[] buffer)
|
||||
{
|
||||
return decryptoTransform.TransformFinalBlock(buffer, 0, buffer.Length);
|
||||
}
|
||||
public Memory<byte> Decode(in ReadOnlyMemory<byte> buffer)
|
||||
{
|
||||
return Decode(buffer.ToArray());
|
||||
}
|
||||
public void Dispose()
|
||||
{
|
||||
encryptoTransform.Dispose();
|
||||
decryptoTransform.Dispose();
|
||||
}
|
||||
|
||||
private (byte[] Key, byte[] IV) GenerateKeyAndIV(in string password)
|
||||
{
|
||||
byte[] key = new byte[32];
|
||||
byte[] iv = new byte[16];
|
||||
|
||||
using SHA384 sha = SHA384.Create();
|
||||
byte[] hash = sha.ComputeHash(Encoding.UTF8.GetBytes(password));
|
||||
|
||||
Array.Copy(hash, 0, key, 0, 32);
|
||||
Array.Copy(hash, 32, iv, 0, 16);
|
||||
return (Key: key, IV: iv);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user