mirror of
https://github.com/snltty/linker.git
synced 2025-10-06 17:46:59 +08:00
一些常规优化
This commit is contained in:
8
.github/workflows/docker.yml
vendored
8
.github/workflows/docker.yml
vendored
@@ -57,9 +57,9 @@ jobs:
|
||||
docker tag snltty/linker-musl-x64:latest snltty/linker-musl:amd64 && \
|
||||
docker push snltty/linker-musl:amd64 && \
|
||||
docker manifest create snltty/linker-musl:latest snltty/linker-musl:amd64 snltty/linker-musl:arm64 snltty/linker-musl:arm && \
|
||||
docker manifest create snltty/linker-musl:v1.5.9 snltty/linker-musl:amd64 snltty/linker-musl:arm64 snltty/linker-musl:arm && \
|
||||
docker manifest create snltty/linker-musl:v1.6.0 snltty/linker-musl:amd64 snltty/linker-musl:arm64 snltty/linker-musl:arm && \
|
||||
docker manifest push snltty/linker-musl:latest && \
|
||||
docker manifest push snltty/linker-musl:v1.5.9 && \
|
||||
docker manifest push snltty/linker-musl:v1.6.0 && \
|
||||
docker pull --platform linux/arm/v7 snltty/linker-debian-arm:latest && \
|
||||
docker tag snltty/linker-debian-arm:latest snltty/linker-debian:arm && \
|
||||
docker push snltty/linker-debian:arm && \
|
||||
@@ -70,6 +70,6 @@ jobs:
|
||||
docker tag snltty/linker-debian-x64:latest snltty/linker-debian:amd64 && \
|
||||
docker push snltty/linker-debian:amd64 && \
|
||||
docker manifest create snltty/linker-debian:latest snltty/linker-debian:amd64 snltty/linker-debian:arm64 snltty/linker-debian:arm && \
|
||||
docker manifest create snltty/linker-debian:v1.5.9 snltty/linker-debian:amd64 snltty/linker-debian:arm64 snltty/linker-debian:arm && \
|
||||
docker manifest create snltty/linker-debian:v1.6.0 snltty/linker-debian:amd64 snltty/linker-debian:arm64 snltty/linker-debian:arm && \
|
||||
docker manifest push snltty/linker-debian:latest && \
|
||||
docker manifest push snltty/linker-debian:v1.5.9
|
||||
docker manifest push snltty/linker-debian:v1.6.0
|
30
.github/workflows/dotnet.yml
vendored
30
.github/workflows/dotnet.yml
vendored
@@ -33,11 +33,11 @@ jobs:
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.ACTIONS_TOKEN }}
|
||||
with:
|
||||
tag_name: v1.5.9
|
||||
release_name: v1.5.9.${{ steps.date.outputs.today }}
|
||||
tag_name: v1.6.0
|
||||
release_name: v1.6.0.${{ steps.date.outputs.today }}
|
||||
draft: false
|
||||
prerelease: false
|
||||
body: "1. 优化UI\r\n2. 优化网卡\r\n3. 修复网卡禁用自动重启\r\n4. 增加一键安装脚本"
|
||||
body: "1. 优化websocket(某些代理环境下可能请求头key名称不规范)\r\n2. 尝试解决UDP获取外网IP端口失败的问题\r\n3. 测试中"
|
||||
- name: upload-win-x86-oss
|
||||
id: upload-win-x86-oss
|
||||
uses: tvrcgo/oss-action@v0.1.1
|
||||
@@ -47,7 +47,7 @@ jobs:
|
||||
key-secret: ${{ secrets.ALIYUN_OSS_SECRET }}
|
||||
bucket: ide-qbcode
|
||||
asset-path: ./public/publish-zip/linker-win-x86.zip
|
||||
target-path: /downloads/linker/v1.5.9/linker-win-x86.zip
|
||||
target-path: /downloads/linker/v1.6.0/linker-win-x86.zip
|
||||
- name: upload-win-x86
|
||||
id: upload-win-x86
|
||||
uses: actions/upload-release-asset@master
|
||||
@@ -67,7 +67,7 @@ jobs:
|
||||
key-secret: ${{ secrets.ALIYUN_OSS_SECRET }}
|
||||
bucket: ide-qbcode
|
||||
asset-path: ./public/publish-zip/linker-win-x64.zip
|
||||
target-path: /downloads/linker/v1.5.9/linker-win-x64.zip
|
||||
target-path: /downloads/linker/v1.6.0/linker-win-x64.zip
|
||||
- name: upload-win-x64
|
||||
id: upload-win-x64
|
||||
uses: actions/upload-release-asset@master
|
||||
@@ -87,7 +87,7 @@ jobs:
|
||||
key-secret: ${{ secrets.ALIYUN_OSS_SECRET }}
|
||||
bucket: ide-qbcode
|
||||
asset-path: ./public/publish-zip/linker-win-arm64.zip
|
||||
target-path: /downloads/linker/v1.5.9/linker-win-arm64.zip
|
||||
target-path: /downloads/linker/v1.6.0/linker-win-arm64.zip
|
||||
- name: upload-win-arm64
|
||||
id: upload-win-arm64
|
||||
uses: actions/upload-release-asset@master
|
||||
@@ -107,7 +107,7 @@ jobs:
|
||||
key-secret: ${{ secrets.ALIYUN_OSS_SECRET }}
|
||||
bucket: ide-qbcode
|
||||
asset-path: ./public/publish-zip/linker-linux-x64.zip
|
||||
target-path: /downloads/linker/v1.5.9/linker-linux-x64.zip
|
||||
target-path: /downloads/linker/v1.6.0/linker-linux-x64.zip
|
||||
- name: upload-linux-x64
|
||||
id: upload-linux-x64
|
||||
uses: actions/upload-release-asset@master
|
||||
@@ -127,7 +127,7 @@ jobs:
|
||||
key-secret: ${{ secrets.ALIYUN_OSS_SECRET }}
|
||||
bucket: ide-qbcode
|
||||
asset-path: ./public/publish-zip/linker-linux-arm.zip
|
||||
target-path: /downloads/linker/v1.5.9/linker-linux-arm.zip
|
||||
target-path: /downloads/linker/v1.6.0/linker-linux-arm.zip
|
||||
- name: upload-linux-arm
|
||||
id: upload-linux-arm
|
||||
uses: actions/upload-release-asset@master
|
||||
@@ -147,7 +147,7 @@ jobs:
|
||||
key-secret: ${{ secrets.ALIYUN_OSS_SECRET }}
|
||||
bucket: ide-qbcode
|
||||
asset-path: ./public/publish-zip/linker-linux-arm64.zip
|
||||
target-path: /downloads/linker/v1.5.9/linker-linux-arm64.zip
|
||||
target-path: /downloads/linker/v1.6.0/linker-linux-arm64.zip
|
||||
- name: upload-linux-arm64
|
||||
id: upload-linux-arm64
|
||||
uses: actions/upload-release-asset@master
|
||||
@@ -167,7 +167,7 @@ jobs:
|
||||
key-secret: ${{ secrets.ALIYUN_OSS_SECRET }}
|
||||
bucket: ide-qbcode
|
||||
asset-path: ./public/publish-zip/linker-linux-musl-x64.zip
|
||||
target-path: /downloads/linker/v1.5.9/linker-linux-musl-x64.zip
|
||||
target-path: /downloads/linker/v1.6.0/linker-linux-musl-x64.zip
|
||||
- name: upload-linux-musl-x64
|
||||
id: upload-linux-musl-x64
|
||||
uses: actions/upload-release-asset@master
|
||||
@@ -187,7 +187,7 @@ jobs:
|
||||
key-secret: ${{ secrets.ALIYUN_OSS_SECRET }}
|
||||
bucket: ide-qbcode
|
||||
asset-path: ./public/publish-zip/linker-linux-musl-arm.zip
|
||||
target-path: /downloads/linker/v1.5.9/linker-linux-musl-arm.zip
|
||||
target-path: /downloads/linker/v1.6.0/linker-linux-musl-arm.zip
|
||||
- name: upload-linux-musl-arm
|
||||
id: upload-linux-musl-arm
|
||||
uses: actions/upload-release-asset@master
|
||||
@@ -207,7 +207,7 @@ jobs:
|
||||
key-secret: ${{ secrets.ALIYUN_OSS_SECRET }}
|
||||
bucket: ide-qbcode
|
||||
asset-path: ./public/publish-zip/linker-linux-musl-arm64.zip
|
||||
target-path: /downloads/linker/v1.5.9/linker-linux-musl-arm64.zip
|
||||
target-path: /downloads/linker/v1.6.0/linker-linux-musl-arm64.zip
|
||||
- name: upload-linux-musl-arm64
|
||||
id: upload-linux-musl-arm64
|
||||
uses: actions/upload-release-asset@master
|
||||
@@ -227,7 +227,7 @@ jobs:
|
||||
key-secret: ${{ secrets.ALIYUN_OSS_SECRET }}
|
||||
bucket: ide-qbcode
|
||||
asset-path: ./public/publish-zip/linker-osx-x64.zip
|
||||
target-path: /downloads/linker/v1.5.9/linker-osx-x64.zip
|
||||
target-path: /downloads/linker/v1.6.0/linker-osx-x64.zip
|
||||
- name: upload-osx-x64
|
||||
id: upload-osx-x64
|
||||
uses: actions/upload-release-asset@master
|
||||
@@ -247,7 +247,7 @@ jobs:
|
||||
key-secret: ${{ secrets.ALIYUN_OSS_SECRET }}
|
||||
bucket: ide-qbcode
|
||||
asset-path: ./public/publish-zip/linker-osx-arm64.zip
|
||||
target-path: /downloads/linker/v1.5.9/linker-osx-arm64.zip
|
||||
target-path: /downloads/linker/v1.6.0/linker-osx-arm64.zip
|
||||
- name: upload-osx-arm64
|
||||
id: upload-osx-arm64
|
||||
uses: actions/upload-release-asset@master
|
||||
@@ -277,7 +277,7 @@ jobs:
|
||||
key-secret: ${{ secrets.ALIYUN_OSS_SECRET }}
|
||||
bucket: ide-qbcode
|
||||
asset-path: ./public/publish-zip/linker-windows-route.zip
|
||||
target-path: /downloads/linker/v1.5.9/linker-windows-route.zip
|
||||
target-path: /downloads/linker/v1.6.0/linker-windows-route.zip
|
||||
- name: upload-version-oss
|
||||
id: upload-version-oss
|
||||
uses: tvrcgo/oss-action@v0.1.1
|
||||
|
6
.github/workflows/nuget.yml
vendored
6
.github/workflows/nuget.yml
vendored
@@ -38,6 +38,6 @@ jobs:
|
||||
|
||||
- name: Push
|
||||
run: |
|
||||
nuget push ./linker.tunnel/bin/release/linker.tunnel.1.5.9.nupkg -Source https://api.nuget.org/v3/index.json -SkipDuplicate -ApiKey ${{ secrets.NUGET_KEY }} -NoSymbol
|
||||
nuget push ./linker.libs/bin/release/linker.libs.1.5.9.nupkg -Source https://api.nuget.org/v3/index.json -SkipDuplicate -ApiKey ${{ secrets.NUGET_KEY }} -NoSymbol
|
||||
nuget push ./linker.tun/bin/release/linker.tun.1.5.9.nupkg -Source https://api.nuget.org/v3/index.json -SkipDuplicate -ApiKey ${{ secrets.NUGET_KEY }} -NoSymbol
|
||||
nuget push ./linker.tunnel/bin/release/linker.tunnel.1.6.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.6.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.6.0.nupkg -Source https://api.nuget.org/v3/index.json -SkipDuplicate -ApiKey ${{ secrets.NUGET_KEY }} -NoSymbol
|
||||
|
@@ -3,6 +3,10 @@ sidebar_position: 1
|
||||
---
|
||||
|
||||
# 1、首页
|
||||
:::danger[特别声明]
|
||||
1. 因为没有签名,又需要较高的权限,所以可能存在报毒的情况,请手动在安全软件中添加白名单
|
||||
2. 如有疑问,可右上角移步软件源码,公开透明
|
||||
:::
|
||||
|
||||
:::tip[说明]
|
||||
|
||||
|
@@ -15,14 +15,15 @@ sidebar_position: 1
|
||||
下载安装脚本
|
||||
```
|
||||
curl -fsSL https://linker-doc.snltty.com/linker-install.sh -o linker-install.sh
|
||||
chmod +x linker-install.sh
|
||||
```
|
||||
默认安装位置
|
||||
```
|
||||
sudo sh linker-install.sh
|
||||
./linker-install.sh
|
||||
```
|
||||
指定安装位置
|
||||
```
|
||||
sudo sh linker-install.sh /usr/local/bin
|
||||
./linker-install.sh /usr/local/bin
|
||||
```
|
||||
:::
|
||||
|
||||
|
@@ -17,15 +17,11 @@ plain='\033[0m'
|
||||
export PATH=$PATH:/usr/local/bin
|
||||
|
||||
|
||||
install_base() {
|
||||
(command -v git >/dev/null 2>&1 && command -v curl >/dev/null 2>&1 && command -v wget >/dev/null 2>&1 && command -v unzip >/dev/null 2>&1 && command -v getenforce >/dev/null 2>&1) ||
|
||||
(install_soft curl wget git unzip)
|
||||
}
|
||||
install_soft() {
|
||||
(command -v yum >/dev/null 2>&1 && yum makecache >/dev/null 2>&1 && yum install $* iproute2 dmidecode net-tools curl traceroute iptables ca-certificates -y >/dev/null 2>&1) ||
|
||||
(command -v apt >/dev/null 2>&1 && apt update >/dev/null 2>&1 && apt install $* iproute2 dmidecode net-tools curl traceroute iptables ca-certificates -y >/dev/null 2>&1) ||
|
||||
(command -v pacman >/dev/null 2>&1 && pacman -Syu $* base-devel --noconfirm && install_arch) ||
|
||||
(command -v apt-get >/dev/null 2>&1 && apt-get update >/dev/null 2>&1 && apt-get install $* iproute2 dmidecode net-tools curl traceroute iptables ca-certificates -y >/dev/null 2>&1) ||
|
||||
(command -v yum >/dev/null 2>&1 && yum makecache >/dev/null 2>&1 && yum install curl wget git unzip iproute dmidecode net-tools curl traceroute iptables ca-certificates -y >/dev/null 2>&1) ||
|
||||
(command -v apt >/dev/null 2>&1 && apt update >/dev/null 2>&1 && apt install curl wget git unzip iproute2 dmidecode net-tools curl traceroute iptables ca-certificates -y >/dev/null 2>&1) ||
|
||||
(command -v pacman >/dev/null 2>&1 && pacman -Syu curl wget git unzip base-devel --noconfirm && install_arch) ||
|
||||
(command -v apt-get >/dev/null 2>&1 && apt-get update >/dev/null 2>&1 && apt-get install curl wget git unzip iproute2 dmidecode net-tools curl traceroute iptables ca-certificates -y >/dev/null 2>&1) ||
|
||||
(command -v apk >/dev/null 2>&1 && apk update >/dev/null 2>&1 && apk add --no-cache net-tools iproute2 numactl-dev iputils iptables dmidecode -f >/dev/null 2>&1)
|
||||
}
|
||||
install_systemd() {
|
||||
@@ -131,14 +127,20 @@ install_docker() {
|
||||
os_alpine="0"
|
||||
[ -e /etc/os-release ] && cat /etc/os-release | grep -i "PRETTY_NAME" | grep -qi "alpine" && os_alpine='1'
|
||||
command -v docker >/dev/null 2>&1
|
||||
if [[ $? != 0 ]]; then
|
||||
echo -e "${yellow}===================================================${plain}\n正在安装 Docker"
|
||||
if docker --version >/dev/null 2>&1; then
|
||||
echo -e "${green}已安装docker${plain}"
|
||||
else
|
||||
echo -e "${yellow}===================================================${plain}\n正在安装 docker"
|
||||
if [ "$os_alpine" != 1 ]; then
|
||||
echo -e "下载docker脚本..."
|
||||
bash <(curl -sL https://get.docker.com -o get-docker.sh) >/dev/null 2>&1
|
||||
if [[ $? != 0 ]]; then
|
||||
echo -e "${red}下载脚本失败,请检查本机能否连接 https://get.docker.com${plain}"
|
||||
return 0
|
||||
fi
|
||||
echo -e "执行docker脚本..."
|
||||
chmod +x get-docker.sh
|
||||
./get-docker.sh
|
||||
systemctl enable docker.service >/dev/null 2>&1
|
||||
systemctl start docker.service >/dev/null 2>&1
|
||||
else
|
||||
@@ -146,7 +148,11 @@ install_docker() {
|
||||
rc-update add docker
|
||||
rc-service docker start
|
||||
fi
|
||||
echo -e "${green}Docker 安装成功${plain}"
|
||||
if docker --version >/dev/null 2>&1; then
|
||||
echo -e "${green}docker 安装成功${plain}"
|
||||
else
|
||||
echo -e "${red}docker 安装失败,可以多试几次${plain}" && exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
LINKER_IMAGES=$(docker ps | grep -w "linker")
|
||||
@@ -198,7 +204,7 @@ install_docker() {
|
||||
|
||||
select_version() {
|
||||
if [[ -z $LINKER_IS_DOCKER ]]; then
|
||||
echo -e "${yellow}===================================================\n${plain}请自行选择您的安装方式:${yellow}\n1. Docker\n2. 独立安装${plain}"
|
||||
echo -e "${yellow}===================================================\n${plain}请自行选择您的安装方式:${yellow}\n1. docker\n2. 独立安装${plain}"
|
||||
while true; do
|
||||
read -e -r -p "请输入选择 [1-2]:" option
|
||||
case "${option}" in
|
||||
@@ -218,7 +224,7 @@ select_version() {
|
||||
fi
|
||||
}
|
||||
|
||||
install_base
|
||||
install_soft
|
||||
select_version
|
||||
|
||||
|
||||
|
@@ -4,6 +4,8 @@ using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.CodeAnalysis.Text;
|
||||
using System.Text;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace linker.gen
|
||||
{
|
||||
@@ -31,6 +33,8 @@ namespace linker.gen
|
||||
|
||||
context.RegisterSourceOutput(compilations, (sourceProductionContext, compilation) =>
|
||||
{
|
||||
|
||||
|
||||
foreach (GeneratorInfo info in generators)
|
||||
{
|
||||
var iFlowSymbol = compilation.GetTypeByMetadataName(info.InterfaceName);
|
||||
|
@@ -21,7 +21,7 @@ namespace linker.libs.api
|
||||
protected readonly Dictionary<string, PluginPathCacheInfo> plugins = new();
|
||||
protected readonly ConcurrentDictionary<uint, ConnectionTimeInfo> connectionTimes = new();
|
||||
public uint OnlineNum = 0;
|
||||
private Memory<byte> password = Helper.EmptyArray;
|
||||
private string password = string.Empty;
|
||||
|
||||
private WebSocketServer server;
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace linker.libs.api
|
||||
/// </summary>
|
||||
public void Websocket(int port, string password = "")
|
||||
{
|
||||
this.password = Encoding.UTF8.GetBytes(password);
|
||||
this.password = password;
|
||||
server = new WebSocketServer();
|
||||
try
|
||||
{
|
||||
@@ -46,10 +46,10 @@ namespace linker.libs.api
|
||||
}
|
||||
server.OnConnecting = (connection, header) =>
|
||||
{
|
||||
bool res = this.password.Length == 0 || this.password.Span.SequenceEqual(header.SecWebSocketProtocol.Span);
|
||||
bool res = string.IsNullOrWhiteSpace(this.password) || (header.TryGetHeaderValue(WebsocketHeaderKey.SecWebSocketProtocol, out string _password) && _password.Contains(this.password));
|
||||
if (res)
|
||||
{
|
||||
header.SecWebSocketExtensions = Helper.EmptyArray;
|
||||
header.SetHeaderValue(WebsocketHeaderKey.SecWebSocketExtensions, string.Empty);
|
||||
}
|
||||
return res;
|
||||
};
|
||||
|
@@ -1,5 +1,6 @@
|
||||
using linker.libs.jsonConverters;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Text.Unicode;
|
||||
|
||||
namespace linker.libs.extends
|
||||
@@ -23,15 +24,15 @@ namespace linker.libs.extends
|
||||
WriteIndented = true,
|
||||
Converters = { new IPAddressJsonConverter(), new IPEndpointJsonConverter(), new DateTimeConverter() }
|
||||
};
|
||||
private static JsonSerializerOptions jsonSerializerOptionsIndented = new JsonSerializerOptions
|
||||
public static void AddAOT(JsonSerializerContext[] contexts)
|
||||
{
|
||||
Encoder = System.Text.Encodings.Web.JavaScriptEncoder.Create(UnicodeRanges.All),
|
||||
AllowTrailingCommas = true,
|
||||
ReadCommentHandling = JsonCommentHandling.Skip,
|
||||
PropertyNameCaseInsensitive = true,
|
||||
WriteIndented = true,
|
||||
Converters = { new IPAddressJsonConverter(), new IPEndpointJsonConverter(), new DateTimeConverter() }
|
||||
};
|
||||
foreach (var context in contexts)
|
||||
{
|
||||
jsonSerializerOptions1.TypeInfoResolverChain.Insert(0, context);
|
||||
jsonSerializerOptions.TypeInfoResolverChain.Insert(0, context);
|
||||
}
|
||||
}
|
||||
|
||||
public static string ToJson(this object obj)
|
||||
{
|
||||
return JsonSerializer.Serialize(obj, jsonSerializerOptions1);
|
||||
@@ -45,4 +46,6 @@ namespace linker.libs.extends
|
||||
return JsonSerializer.Deserialize<T>(json, options: jsonSerializerOptions);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@@ -14,9 +14,9 @@
|
||||
<Copyright>snltty</Copyright>
|
||||
<PackageProjectUrl>https://github.com/snltty/linker</PackageProjectUrl>
|
||||
<RepositoryUrl>https://github.com/snltty/linker</RepositoryUrl>
|
||||
<Version>1.5.9</Version>
|
||||
<AssemblyVersion>1.5.9</AssemblyVersion>
|
||||
<FileVersion>1.5.9</FileVersion>
|
||||
<Version>1.6.0</Version>
|
||||
<AssemblyVersion>1.6.0</AssemblyVersion>
|
||||
<FileVersion>1.6.0</FileVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
<DebugType>full</DebugType>
|
||||
|
@@ -140,10 +140,9 @@ namespace linker.libs.websocket
|
||||
{
|
||||
|
||||
token.SecWebSocketKey = WebSocketParser.BuildSecWebSocketKey();
|
||||
byte[] connectData = WebSocketParser.BuildConnectData(new WebsocketHeaderInfo
|
||||
{
|
||||
SecWebSocketKey = token.SecWebSocketKey,
|
||||
});
|
||||
WebsocketHeaderInfo header = new WebsocketHeaderInfo();
|
||||
header.SetHeaderValue(WebsocketHeaderKey.SecWebSocketKey, token.SecWebSocketKey);
|
||||
byte[] connectData = WebSocketParser.BuildConnectData(header);
|
||||
|
||||
token.TargetSocket.Send(connectData, SocketFlags.None);
|
||||
|
||||
@@ -366,7 +365,7 @@ namespace linker.libs.websocket
|
||||
private void HandleConnect(AsyncServerUserToken token, Memory<byte> data)
|
||||
{
|
||||
WebsocketHeaderInfo header = WebsocketHeaderInfo.Parse(data);
|
||||
if (!WebSocketParser.VerifySecWebSocketAccept(token.SecWebSocketKey, header.SecWebSocketAccept))
|
||||
if (header.TryGetHeaderValue(WebsocketHeaderKey.SecWebSocketAccept, out string accept) == false || WebSocketParser.VerifySecWebSocketAccept(token.SecWebSocketKey, accept) == false)
|
||||
{
|
||||
OnConnectFail("Sec-WebSocket-Accept Invalid");
|
||||
CloseClientSocket();
|
||||
@@ -471,7 +470,7 @@ namespace linker.libs.websocket
|
||||
/// 当前帧的数据类型
|
||||
/// </summary>
|
||||
public WebSocketFrameInfo.EnumOpcode Opcode { get; set; }
|
||||
public Memory<byte> SecWebSocketKey { get; set; }
|
||||
public string SecWebSocketKey { get; set; }
|
||||
public byte[] PoolBuffer { get; set; }
|
||||
|
||||
public void Clear()
|
||||
|
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Buffers.Binary;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
@@ -13,7 +14,7 @@ namespace linker.libs.websocket
|
||||
public static class WebSocketParser
|
||||
{
|
||||
private readonly static SHA1 sha1 = SHA1.Create();
|
||||
private readonly static Memory<byte> magicCode = Encoding.ASCII.GetBytes("258EAFA5-E914-47DA-95CA-C5AB0DC85B11");
|
||||
private readonly static Memory<byte> magicCode = Encoding.UTF8.GetBytes("258EAFA5-E914-47DA-95CA-C5AB0DC85B11");
|
||||
/// <summary>
|
||||
/// 构建连接数据
|
||||
/// </summary>
|
||||
@@ -21,21 +22,23 @@ namespace linker.libs.websocket
|
||||
/// <returns></returns>
|
||||
public static byte[] BuildConnectData(WebsocketHeaderInfo header)
|
||||
{
|
||||
string path = header.Path.Length == 0 ? "/" : Encoding.UTF8.GetString(header.Path.Span);
|
||||
string path = header.Path.Length == 0 ? "/" : header.Path;
|
||||
|
||||
header.TryGetHeaderValue(WebsocketHeaderKey.SecWebSocketKey,out string key);
|
||||
|
||||
StringBuilder sb = new StringBuilder(10);
|
||||
sb.Append($"GET {path} HTTP/1.1\r\n");
|
||||
sb.Append($"Upgrade: websocket\r\n");
|
||||
sb.Append($"Connection: Upgrade\r\n");
|
||||
sb.Append($"Sec-WebSocket-Version: 13\r\n");
|
||||
sb.Append($"Sec-WebSocket-Key: {Encoding.UTF8.GetString(header.SecWebSocketKey.Span)}\r\n");
|
||||
if (header.SecWebSocketProtocol.Length > 0)
|
||||
sb.Append($"Sec-WebSocket-Key: {key}\r\n");
|
||||
if (header.TryGetHeaderValue(WebsocketHeaderKey.SecWebSocketProtocol, out string protocol))
|
||||
{
|
||||
sb.Append($"Sec-WebSocket-Protocol: {Encoding.UTF8.GetString(header.SecWebSocketProtocol.Span)}\r\n");
|
||||
sb.Append($"Sec-WebSocket-Protocol: {protocol}\r\n");
|
||||
}
|
||||
if (header.SecWebSocketExtensions.Length > 0)
|
||||
if (header.TryGetHeaderValue(WebsocketHeaderKey.SecWebSocketExtensions, out string extensions))
|
||||
{
|
||||
sb.Append($"Sec-WebSocket-Extensions: {Encoding.UTF8.GetString(header.SecWebSocketExtensions.Span)}\r\n");
|
||||
sb.Append($"Sec-WebSocket-Extensions: {extensions}\r\n");
|
||||
}
|
||||
sb.Append("\r\n");
|
||||
|
||||
@@ -48,30 +51,31 @@ namespace linker.libs.websocket
|
||||
/// <returns></returns>
|
||||
public static byte[] BuildConnectResponseData(WebsocketHeaderInfo header)
|
||||
{
|
||||
string acceptStr = BuildSecWebSocketAccept(header.SecWebSocketKey);
|
||||
header.TryGetHeaderValue(WebsocketHeaderKey.SecWebSocketKey,out string key);
|
||||
string acceptStr = BuildSecWebSocketAccept(key);
|
||||
|
||||
StringBuilder sb = new StringBuilder(10);
|
||||
sb.Append($"HTTP/1.1 {(int)header.StatusCode} {AddSpace(header.StatusCode)}\r\n");
|
||||
sb.Append($"Sec-WebSocket-Accept: {acceptStr}\r\n");
|
||||
if (header.Connection.Length > 0)
|
||||
if (header.TryGetHeaderValue(WebsocketHeaderKey.Connection, out string str1))
|
||||
{
|
||||
sb.Append($"Connection: {Encoding.UTF8.GetString(header.Connection.Span)}\r\n");
|
||||
sb.Append($"Connection: {str1}\r\n");
|
||||
}
|
||||
if (header.Upgrade.Length > 0)
|
||||
if (header.TryGetHeaderValue(WebsocketHeaderKey.Upgrade, out str1))
|
||||
{
|
||||
sb.Append($"Upgrade: {Encoding.UTF8.GetString(header.Upgrade.Span)}\r\n");
|
||||
sb.Append($"Upgrade: {str1}\r\n");
|
||||
}
|
||||
if (header.SecWebSocketVersion.Length > 0)
|
||||
if (header.TryGetHeaderValue(WebsocketHeaderKey.SecWebSocketVersion, out str1))
|
||||
{
|
||||
sb.Append($"Sec-WebSocket-Version: {Encoding.UTF8.GetString(header.SecWebSocketVersion.Span)}\r\n");
|
||||
sb.Append($"Sec-Websocket-Version: {str1}\r\n");
|
||||
}
|
||||
if (header.SecWebSocketProtocol.Length > 0)
|
||||
if (header.TryGetHeaderValue(WebsocketHeaderKey.SecWebSocketProtocol, out str1))
|
||||
{
|
||||
sb.Append($"Sec-WebSocket-Protocol: {Encoding.UTF8.GetString(header.SecWebSocketProtocol.Span)}\r\n");
|
||||
sb.Append($"Sec-WebSocket-Protocol: {str1}\r\n");
|
||||
}
|
||||
if (header.SecWebSocketExtensions.Length > 0)
|
||||
if (header.TryGetHeaderValue(WebsocketHeaderKey.SecWebSocketExtensions, out str1))
|
||||
{
|
||||
sb.Append($"Sec-WebSocket-Extensions: {Encoding.UTF8.GetString(header.SecWebSocketExtensions.Span)}\r\n");
|
||||
sb.Append($"Sec-WebSocket-Extensions: {str1}\r\n");
|
||||
}
|
||||
sb.Append("\r\n");
|
||||
|
||||
@@ -81,7 +85,7 @@ namespace linker.libs.websocket
|
||||
/// 生成随机key
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static byte[] BuildSecWebSocketKey()
|
||||
public static string BuildSecWebSocketKey()
|
||||
{
|
||||
byte[] bytes = new byte[16];
|
||||
Random random = new Random(DateTime.Now.Ticks.GetHashCode());
|
||||
@@ -89,8 +93,7 @@ namespace linker.libs.websocket
|
||||
{
|
||||
bytes[i] = (byte)random.Next(0, 255);
|
||||
}
|
||||
byte[] res = Encoding.UTF8.GetBytes(Convert.ToBase64String(bytes));
|
||||
return res;
|
||||
return Convert.ToBase64String(bytes);
|
||||
}
|
||||
/// <summary>
|
||||
/// 构建mask数据
|
||||
@@ -113,12 +116,12 @@ namespace linker.libs.websocket
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <returns></returns>
|
||||
private static string BuildSecWebSocketAccept(Memory<byte> key)
|
||||
private static string BuildSecWebSocketAccept(string key)
|
||||
{
|
||||
int keyLength = key.Length + magicCode.Length;
|
||||
byte[] acceptBytes = new byte[keyLength];
|
||||
|
||||
key.CopyTo(acceptBytes);
|
||||
Encoding.UTF8.GetBytes(key).AsMemory().CopyTo(acceptBytes);
|
||||
magicCode.CopyTo(acceptBytes.AsMemory(key.Length));
|
||||
|
||||
string acceptStr = Convert.ToBase64String(sha1.ComputeHash(acceptBytes, 0, keyLength));
|
||||
@@ -131,10 +134,10 @@ namespace linker.libs.websocket
|
||||
/// <param name="key"></param>
|
||||
/// <param name="accept"></param>
|
||||
/// <returns></returns>
|
||||
public static bool VerifySecWebSocketAccept(Memory<byte> key, Memory<byte> accept)
|
||||
public static bool VerifySecWebSocketAccept(string key, string accept)
|
||||
{
|
||||
string acceptStr = BuildSecWebSocketAccept(key);
|
||||
return acceptStr == Encoding.UTF8.GetString(accept.Span);
|
||||
return acceptStr == accept;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -536,113 +539,108 @@ namespace linker.libs.websocket
|
||||
/// </summary>
|
||||
public sealed class WebsocketHeaderInfo
|
||||
{
|
||||
static byte[][] bytes = new byte[][] {
|
||||
Encoding.ASCII.GetBytes("Connection: "),
|
||||
Encoding.ASCII.GetBytes("Upgrade: "),
|
||||
Encoding.ASCII.GetBytes("Origin: "),
|
||||
Encoding.ASCII.GetBytes("Sec-WebSocket-Version: "),
|
||||
Encoding.ASCII.GetBytes("Sec-WebSocket-Key: "),
|
||||
Encoding.ASCII.GetBytes("Sec-WebSocket-Extensions: "),
|
||||
Encoding.ASCII.GetBytes("Sec-WebSocket-Protocol: "),
|
||||
Encoding.ASCII.GetBytes("Sec-WebSocket-Accept: ")
|
||||
};
|
||||
static byte[] httpBytes = Encoding.UTF8.GetBytes("HTTP/");
|
||||
static byte[] endBytes = Encoding.UTF8.GetBytes("\r\n");
|
||||
static byte[] splitBytes = Encoding.UTF8.GetBytes(": ");
|
||||
|
||||
/// <summary>
|
||||
/// 状态码
|
||||
/// </summary>
|
||||
public HttpStatusCode StatusCode { get; set; } = HttpStatusCode.SwitchingProtocols;
|
||||
public Memory<byte> Method { get; private set; }
|
||||
/// <summary>
|
||||
/// 方法
|
||||
/// </summary>
|
||||
public string Method { get; private set; }
|
||||
/// <summary>
|
||||
/// 路径
|
||||
/// </summary>
|
||||
public string Path { get; set; }
|
||||
/// <summary>
|
||||
/// 请求头
|
||||
/// </summary>
|
||||
public Dictionary<string, string> Headers { get; private set; } = new Dictionary<string, string>();
|
||||
|
||||
private string _pathSet { get; set; }
|
||||
/// <summary>
|
||||
/// 用这个设置path值
|
||||
/// 获取请求头
|
||||
/// </summary>
|
||||
public string PathSet
|
||||
/// <param name="key"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public bool TryGetHeaderValue(string key, out string value)
|
||||
{
|
||||
get
|
||||
{
|
||||
return _pathSet;
|
||||
}
|
||||
set
|
||||
{
|
||||
_pathSet = value;
|
||||
Path = Encoding.UTF8.GetBytes(_pathSet);
|
||||
}
|
||||
return Headers.TryGetValue(key, out value) && string.IsNullOrWhiteSpace(value) == false;
|
||||
}
|
||||
/// <summary>
|
||||
/// 如果 仅1个字符,那就是 /
|
||||
/// 设置请求头
|
||||
/// </summary>
|
||||
public Memory<byte> Path { get; private set; }
|
||||
public Memory<byte> Connection { get; private set; }
|
||||
public Memory<byte> Upgrade { get; private set; }
|
||||
public Memory<byte> Origin { get; private set; }
|
||||
public Memory<byte> SecWebSocketVersion { get; private set; }
|
||||
public Memory<byte> SecWebSocketKey { get; set; }
|
||||
public Memory<byte> SecWebSocketExtensions { get; set; }
|
||||
public Memory<byte> SecWebSocketProtocol { get; set; }
|
||||
public Memory<byte> SecWebSocketAccept { get; set; }
|
||||
/// <param name="key"></param>
|
||||
/// <param name="value"></param>
|
||||
public void SetHeaderValue(string key, string value)
|
||||
{
|
||||
Headers[key] = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 解析websocket请求头
|
||||
/// </summary>
|
||||
/// <param name="header"></param>
|
||||
/// <returns></returns>
|
||||
public static WebsocketHeaderInfo Parse(Memory<byte> header)
|
||||
{
|
||||
Span<byte> span = header.Span;
|
||||
int flag = 0xff;
|
||||
int bit = 0x01;
|
||||
|
||||
ulong[] res = new ulong[bytes.Length];
|
||||
Span<byte> temp = span;
|
||||
WebsocketHeaderInfo headerInfo = new WebsocketHeaderInfo();
|
||||
|
||||
for (int i = 0, len = span.Length; i < len; i++)
|
||||
//跳过头
|
||||
temp = temp.Slice(temp.IndexOf(endBytes) + 2);
|
||||
int splitIndex = 0;
|
||||
//还有分割线
|
||||
while ((splitIndex = temp.IndexOf(splitBytes)) >= 0)
|
||||
{
|
||||
if (span[i] == 13 && span[i + 1] == 10 && span[i + 2] == 13 && span[i + 3] == 10)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (span[i] == 13 && span[i + 1] == 10)
|
||||
{
|
||||
int startIndex = i + 2;
|
||||
for (int k = 0; k < bytes.Length; k++)
|
||||
{
|
||||
if ((flag >> k & 1) == 1 && span[startIndex] == bytes[k][0])
|
||||
{
|
||||
if (span.Slice(startIndex, bytes[k].Length).SequenceEqual(bytes[k]))
|
||||
{
|
||||
int index = span.Slice(startIndex).IndexOf((byte)13);
|
||||
flag &= ~(bit << k);
|
||||
//取到key
|
||||
string key = Encoding.UTF8.GetString(temp.Slice(0, splitIndex)).ToLowerInvariant();
|
||||
//跳过key
|
||||
temp = temp.Slice(splitIndex + 2);
|
||||
|
||||
#pragma warning disable CS0675 // 对进行了带符号扩展的操作数使用了按位或运算符
|
||||
res[k] = (ulong)(startIndex + bytes[k].Length) << 32 | (ulong)(index - bytes[k].Length);
|
||||
#pragma warning restore CS0675 // 对进行了带符号扩展的操作数使用了按位或运算符
|
||||
//取到value
|
||||
int endIndex = temp.IndexOf(endBytes);
|
||||
string value = Encoding.UTF8.GetString(temp.Slice(0, endIndex));
|
||||
//跳过value
|
||||
temp = temp.Slice(endIndex + 2);
|
||||
|
||||
i += index + 1;
|
||||
break;
|
||||
headerInfo.Headers[key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WebsocketHeaderInfo headerInfo = new WebsocketHeaderInfo
|
||||
{
|
||||
Connection = header.Slice((int)(res[0] >> 32), (int)(res[0] & 0xffffffff)),
|
||||
Upgrade = header.Slice((int)(res[1] >> 32), (int)(res[1] & 0xffffffff)),
|
||||
Origin = header.Slice((int)(res[2] >> 32), (int)(res[2] & 0xffffffff)),
|
||||
SecWebSocketVersion = header.Slice((int)(res[3] >> 32), (int)(res[3] & 0xffffffff)),
|
||||
SecWebSocketKey = header.Slice((int)(res[4] >> 32), (int)(res[4] & 0xffffffff)),
|
||||
SecWebSocketExtensions = header.Slice((int)(res[5] >> 32), (int)(res[5] & 0xffffffff)),
|
||||
SecWebSocketProtocol = header.Slice((int)(res[6] >> 32), (int)(res[6] & 0xffffffff)),
|
||||
SecWebSocketAccept = header.Slice((int)(res[7] >> 32), (int)(res[7] & 0xffffffff)),
|
||||
};
|
||||
|
||||
int pathIndex = span.IndexOf((byte)32);
|
||||
int pathIndex1 = span.Slice(pathIndex + 1).IndexOf((byte)32);
|
||||
//响应的,获取状态码
|
||||
if (header.Slice(0, httpBytes.Length).Span.SequenceEqual(httpBytes))
|
||||
{
|
||||
int code = int.Parse(Encoding.UTF8.GetString(header.Slice(pathIndex + 1, pathIndex1).Span));
|
||||
headerInfo.StatusCode = (HttpStatusCode)code;
|
||||
}
|
||||
//请求的,获取路径和方法
|
||||
else
|
||||
{
|
||||
headerInfo.Path = header.Slice(pathIndex + 1, pathIndex1);
|
||||
headerInfo.Method = header.Slice(0, pathIndex);
|
||||
headerInfo.Path = Encoding.UTF8.GetString(span.Slice(pathIndex + 1, pathIndex1));
|
||||
headerInfo.Method = Encoding.UTF8.GetString(span.Slice(0, pathIndex));
|
||||
}
|
||||
|
||||
return headerInfo;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
public sealed class WebsocketHeaderKey
|
||||
{
|
||||
public static string Connection = "connection";
|
||||
public static string Upgrade = "upgrade";
|
||||
public static string Origin = "origin";
|
||||
public static string SecWebSocketVersion = "sec-websocket-version";
|
||||
public static string SecWebSocketKey = "sec-websocket-key";
|
||||
public static string SecWebSocketExtensions = "sec-websocket-extensions";
|
||||
public static string SecWebSocketProtocol = "sec-websocket-protocol";
|
||||
public static string SecWebSocketAccept = "sec-websocket-accept";
|
||||
}
|
||||
}
|
||||
|
@@ -25,7 +25,7 @@ namespace linker.libs.websocket
|
||||
/// </summary>
|
||||
public Func<WebsocketConnection, WebsocketHeaderInfo, bool> OnConnecting = (connection, header) =>
|
||||
{
|
||||
header.SecWebSocketExtensions = Helper.EmptyArray; return true;
|
||||
header.SetHeaderValue(WebsocketHeaderKey.SecWebSocketExtensions, string.Empty); return true;
|
||||
};
|
||||
/// <summary>
|
||||
/// 已断开连接,没有收到关闭帧
|
||||
@@ -351,7 +351,7 @@ namespace linker.libs.websocket
|
||||
private void HandleConnect(AsyncUserToken token, Memory<byte> data)
|
||||
{
|
||||
WebsocketHeaderInfo header = WebsocketHeaderInfo.Parse(data);
|
||||
if (header.SecWebSocketKey.Length == 0)
|
||||
if (header.TryGetHeaderValue(WebsocketHeaderKey.SecWebSocketKey,out string key) == false)
|
||||
{
|
||||
header.StatusCode = HttpStatusCode.MethodNotAllowed;
|
||||
token.Connectrion.ConnectResponse(header);
|
||||
|
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<project ver="10" name="linker.tray.win" libEmbed="true" icon="..\linker\favicon.ico" ui="win" output="linker.tray.win.exe" CompanyName="snltty" FileDescription="linker.tray.win" LegalCopyright="Copyright (C) snltty 2024" ProductName="linker.tray.win" InternalName="linker.install.win" FileVersion="0.0.0.175" ProductVersion="0.0.0.175" publishDir="/dist/" dstrip="false" local="false" ignored="false">
|
||||
<project ver="10" name="linker.tray.win" libEmbed="true" icon="..\linker\favicon.ico" ui="win" output="linker.tray.win.exe" CompanyName="snltty" FileDescription="linker.tray.win" LegalCopyright="Copyright (C) snltty 2024" ProductName="linker.tray.win" InternalName="linker.install.win" FileVersion="0.0.0.178" ProductVersion="0.0.0.178" publishDir="/dist/" dstrip="false" local="false" ignored="false">
|
||||
<file name="main.aardio" path="main.aardio" comment="main.aardio"/>
|
||||
<folder name="资源文件" path="res" embed="true" local="false" ignored="false">
|
||||
<file name="favicon.ico" path="res\favicon.ico" comment="res\favicon.ico"/>
|
||||
|
BIN
linker.tray.win/dist/linker.tray.win.exe
vendored
BIN
linker.tray.win/dist/linker.tray.win.exe
vendored
Binary file not shown.
@@ -16,9 +16,9 @@
|
||||
<PackageProjectUrl>https://github.com/snltty/linker</PackageProjectUrl>
|
||||
<RepositoryUrl>https://github.com/snltty/linker</RepositoryUrl>
|
||||
<PackageReleaseNotes>linker tun</PackageReleaseNotes>
|
||||
<Version>1.5.9</Version>
|
||||
<AssemblyVersion>1.5.9</AssemblyVersion>
|
||||
<FileVersion>1.5.9</FileVersion>
|
||||
<Version>1.6.0</Version>
|
||||
<AssemblyVersion>1.6.0</AssemblyVersion>
|
||||
<FileVersion>1.6.0</FileVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
|
@@ -16,9 +16,9 @@
|
||||
<PackageProjectUrl>https://github.com/snltty/linker</PackageProjectUrl>
|
||||
<RepositoryUrl>https://github.com/snltty/linker</RepositoryUrl>
|
||||
<PackageReleaseNotes>linker tunnel</PackageReleaseNotes>
|
||||
<Version>1.5.9</Version>
|
||||
<AssemblyVersion>1.5.9</AssemblyVersion>
|
||||
<FileVersion>1.5.9</FileVersion>
|
||||
<Version>1.6.0</Version>
|
||||
<AssemblyVersion>1.6.0</AssemblyVersion>
|
||||
<FileVersion>1.6.0</FileVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
|
@@ -1,4 +1,6 @@
|
||||
using System.Net;
|
||||
using linker.libs.extends;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
|
||||
namespace linker.tunnel.wanport
|
||||
{
|
||||
@@ -16,6 +18,7 @@ namespace linker.tunnel.wanport
|
||||
/// <param name="server">服务器</param>
|
||||
/// <returns></returns>
|
||||
public Task<TunnelWanPortEndPoint> GetAsync(IPAddress inter, IPEndPoint server);
|
||||
|
||||
}
|
||||
|
||||
public sealed class TunnelWanPortEndPoint
|
||||
|
@@ -3,6 +3,7 @@ using linker.libs.extends;
|
||||
using System.Buffers;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
|
||||
namespace linker.tunnel.wanport
|
||||
{
|
||||
@@ -23,13 +24,19 @@ namespace linker.tunnel.wanport
|
||||
udpClient.Client.ReuseBind(new IPEndPoint(localIP, 0));
|
||||
udpClient.Client.WindowsUdpBug();
|
||||
|
||||
byte[] buffer = ArrayPool<byte>.Shared.Rent(1024);
|
||||
try
|
||||
{
|
||||
for (int i = 0; i < 5; i++)
|
||||
await udpClient.SendAsync(BuildSendData(buffer, 0), server).ConfigureAwait(false);
|
||||
TimerHelper.Async(async () =>
|
||||
{
|
||||
try
|
||||
for (byte i = 1; i < 10; i++)
|
||||
{
|
||||
await udpClient.SendAsync(new byte[1] { 0 }, server).ConfigureAwait(false);
|
||||
await Task.Delay(15);
|
||||
await udpClient.SendAsync(BuildSendData(buffer, i), server).ConfigureAwait(false);
|
||||
}
|
||||
});
|
||||
|
||||
UdpReceiveResult result = await udpClient.ReceiveAsync().WaitAsync(TimeSpan.FromMilliseconds(2000)).ConfigureAwait(false);
|
||||
if (result.Buffer.Length == 0)
|
||||
{
|
||||
@@ -49,11 +56,6 @@ namespace linker.tunnel.wanport
|
||||
|
||||
return new TunnelWanPortEndPoint { Local = udpClient.Client.LocalEndPoint as IPEndPoint, Remote = remoteEP };
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
||||
@@ -61,11 +63,21 @@ namespace linker.tunnel.wanport
|
||||
}
|
||||
finally
|
||||
{
|
||||
ArrayPool<byte>.Shared.Return(buffer);
|
||||
udpClient.Close();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
private Memory<byte> BuildSendData(byte[] buffer, byte i)
|
||||
{
|
||||
byte[] temp = Encoding.UTF8.GetBytes(Environment.TickCount64.ToString().Md5().SubStr(0, new Random().Next(16, 32)));
|
||||
temp.AsMemory().CopyTo(buffer);
|
||||
buffer[0] = 0;
|
||||
buffer[1] = i;
|
||||
|
||||
return buffer.AsMemory(0, temp.Length);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -82,13 +94,15 @@ namespace linker.tunnel.wanport
|
||||
|
||||
public async Task<TunnelWanPortEndPoint> GetAsync(IPAddress localIP, IPEndPoint server)
|
||||
{
|
||||
byte[] buffer = ArrayPool<byte>.Shared.Rent(20);
|
||||
byte[] buffer = ArrayPool<byte>.Shared.Rent(1024);
|
||||
try
|
||||
{
|
||||
Socket socket = new Socket(server.AddressFamily, SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp);
|
||||
socket.ReuseBind(new IPEndPoint(localIP, 0));
|
||||
await socket.ConnectAsync(server).ConfigureAwait(false);
|
||||
await socket.SendAsync(new byte[] { 0 });
|
||||
|
||||
await socket.SendAsync(BuildSendData(buffer, (byte)new Random().Next(0, 255)));
|
||||
|
||||
int length = await socket.ReceiveAsync(buffer.AsMemory(), SocketFlags.None).ConfigureAwait(false);
|
||||
for (int j = 0; j < length; j++)
|
||||
{
|
||||
@@ -118,5 +132,15 @@ namespace linker.tunnel.wanport
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private Memory<byte> BuildSendData(byte[] buffer, byte i)
|
||||
{
|
||||
byte[] temp = Encoding.UTF8.GetBytes(Environment.TickCount64.ToString().Md5().SubStr(0, new Random().Next(16, 32)));
|
||||
temp.AsMemory().CopyTo(buffer);
|
||||
buffer[0] = 0;
|
||||
buffer[1] = i;
|
||||
|
||||
return buffer.AsMemory(0, temp.Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -4,7 +4,6 @@ using linker.startup;
|
||||
using linker.config;
|
||||
using System.ServiceProcess;
|
||||
using System.Diagnostics;
|
||||
using linker.libs.extends;
|
||||
|
||||
namespace linker
|
||||
{
|
||||
|
@@ -174,6 +174,7 @@ namespace linker.config
|
||||
}
|
||||
}
|
||||
|
||||
[JsonAotAttribute]
|
||||
public sealed partial class ConfigCommonInfo : IConfig
|
||||
{
|
||||
public ConfigCommonInfo() { }
|
||||
@@ -223,4 +224,8 @@ namespace linker.config
|
||||
return text.DeJson<ConfigCommonInfo>();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
public class JsonAotAttribute : Attribute { }
|
||||
}
|
||||
|
@@ -21,17 +21,16 @@
|
||||
<Title>linker</Title>
|
||||
<Authors>snltty</Authors>
|
||||
<Company>snltty</Company>
|
||||
<Description>1. 优化UI
|
||||
2. 优化网卡
|
||||
3. 修复网卡禁用自动重启
|
||||
4. 增加一键安装脚本</Description>
|
||||
<Description>1. 优化websocket(某些代理环境下可能请求头key名称不规范)
|
||||
2. 尝试解决UDP获取外网IP端口失败的问题
|
||||
3. 测试中</Description>
|
||||
<Copyright>snltty</Copyright>
|
||||
<PackageProjectUrl>https://github.com/snltty/linker</PackageProjectUrl>
|
||||
<RepositoryUrl>https://github.com/snltty/linker</RepositoryUrl>
|
||||
<PackageReleaseNotes>linker</PackageReleaseNotes>
|
||||
<Version>1.5.9</Version>
|
||||
<AssemblyVersion>1.5.9</AssemblyVersion>
|
||||
<FileVersion>1.5.9</FileVersion>
|
||||
<Version>1.6.0</Version>
|
||||
<AssemblyVersion>1.6.0</AssemblyVersion>
|
||||
<FileVersion>1.6.0</FileVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
@@ -76,4 +75,7 @@
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.1" />
|
||||
<PackageReference Include="System.ServiceProcess.ServiceController" Version="8.0.1" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="plugins\pcp\" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
@@ -7,6 +7,7 @@ using linker.plugins.client;
|
||||
using linker.plugins.tunnel;
|
||||
using linker.plugins.messenger;
|
||||
using linker.plugins.relay.client;
|
||||
using linker.client.config;
|
||||
|
||||
namespace linker.plugins.forward.proxy
|
||||
{
|
||||
@@ -18,8 +19,8 @@ namespace linker.plugins.forward.proxy
|
||||
|
||||
protected override string TransactionId => "forward";
|
||||
|
||||
public ForwardProxy(FileConfig config, TunnelTransfer tunnelTransfer, RelayTransfer relayTransfer, ClientSignInTransfer clientSignInTransfer, ClientSignInState clientSignInState)
|
||||
: base(config, tunnelTransfer, relayTransfer, clientSignInTransfer, clientSignInState)
|
||||
public ForwardProxy(FileConfig config, TunnelTransfer tunnelTransfer, RelayTransfer relayTransfer, ClientSignInTransfer clientSignInTransfer, ClientSignInState clientSignInState, RunningConfig runningConfig)
|
||||
: base(config, tunnelTransfer, relayTransfer, clientSignInTransfer, clientSignInState, runningConfig)
|
||||
{
|
||||
TaskUdp();
|
||||
}
|
||||
|
@@ -52,6 +52,8 @@ namespace linker.plugins.relay.client.transport
|
||||
relayInfo.FlowingId = relayAskResultInfo.FlowingId;
|
||||
if (relayInfo.FlowingId == 0 || relayAskResultInfo.Nodes.Count == 0)
|
||||
{
|
||||
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
||||
LoggerHelper.Instance.Error($"relay ask fail,flowid:{relayInfo.FlowingId},nodes:{relayAskResultInfo.Nodes.Count}");
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -65,12 +67,16 @@ namespace linker.plugins.relay.client.transport
|
||||
Socket socket = await ConnectNodeServer(relayInfo, relayAskResultInfo.Nodes);
|
||||
if (socket == null)
|
||||
{
|
||||
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
||||
LoggerHelper.Instance.Error($"relay connect server fail,flowid:{relayInfo.FlowingId},nodes:{relayAskResultInfo.Nodes.Count}");
|
||||
return null;
|
||||
}
|
||||
|
||||
//让对方确认中继
|
||||
if (await RelayConfirm(relayInfo) == false)
|
||||
{
|
||||
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
||||
LoggerHelper.Instance.Error($"relay confirm fail,flowid:{relayInfo.FlowingId},nodes:{relayAskResultInfo.Nodes.Count}");
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -212,9 +218,8 @@ namespace linker.plugins.relay.client.transport
|
||||
}
|
||||
|
||||
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
||||
{
|
||||
LoggerHelper.Instance.Debug($"connect relay server {ep}");
|
||||
}
|
||||
|
||||
//连接中继服务器
|
||||
Socket socket = new Socket(ep.AddressFamily, SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp);
|
||||
socket.KeepAlive();
|
||||
@@ -232,8 +237,13 @@ namespace linker.plugins.relay.client.transport
|
||||
await socket.SendAsync(new byte[] { (byte)ResolverType.Relay });
|
||||
await socket.SendAsync(MemoryPackSerializer.Serialize(relayMessage));
|
||||
|
||||
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG) LoggerHelper.Instance.Debug($"relay connected {ep}");
|
||||
|
||||
//是否允许连接
|
||||
int length = await socket.ReceiveAsync(buffer);
|
||||
int length = await socket.ReceiveAsync(buffer.AsMemory(0, 1));
|
||||
|
||||
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
||||
LoggerHelper.Instance.Debug($"relay connected {ep}->{buffer[0]}");
|
||||
if (buffer[0] == 0)
|
||||
{
|
||||
relayInfo.Server = node.EndPoint;
|
||||
|
@@ -5,6 +5,8 @@ using System.Collections.Concurrent;
|
||||
using linker.plugins.resolver;
|
||||
using System.Net;
|
||||
using MemoryPack;
|
||||
using linker.config;
|
||||
using linker.libs;
|
||||
|
||||
namespace linker.plugins.relay.server
|
||||
{
|
||||
@@ -51,10 +53,12 @@ namespace linker.plugins.relay.server
|
||||
int length = await socket.ReceiveAsync(buffer.AsMemory(), SocketFlags.None).ConfigureAwait(false);
|
||||
RelayMessage relayMessage = MemoryPackSerializer.Deserialize<RelayMessage>(buffer.AsMemory(0, length).Span);
|
||||
|
||||
if (relayMessage.Type == RelayMessengerType.Ask)
|
||||
if (relayMessage.Type == RelayMessengerType.Ask && relayMessage.NodeId != RelayNodeInfo.MASTER_NODE_ID)
|
||||
{
|
||||
if (relayServerNodeTransfer.Invalid())
|
||||
if (relayServerNodeTransfer.Validate() == false)
|
||||
{
|
||||
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
||||
LoggerHelper.Instance.Debug($"relay Validate false,flowid:{relayMessage.FlowId}");
|
||||
await socket.SendAsync(new byte[] { 1 });
|
||||
socket.SafeClose();
|
||||
return;
|
||||
|
@@ -75,9 +75,9 @@ namespace linker.plugins.relay.server
|
||||
/// 无效请求
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool Invalid()
|
||||
public bool Validate()
|
||||
{
|
||||
return ValidateConnection() == false || ValidateBytes() == false;
|
||||
return ValidateConnection() && ValidateBytes();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -100,7 +100,11 @@ namespace linker.plugins.relay.server
|
||||
/// <returns></returns>
|
||||
public bool ValidateConnection()
|
||||
{
|
||||
return fileConfig.Data.Server.Relay.Distributed.Node.MaxConnection == 0 || fileConfig.Data.Server.Relay.Distributed.Node.MaxConnection * 2 > connectionNum;
|
||||
bool res = fileConfig.Data.Server.Relay.Distributed.Node.MaxConnection == 0 || fileConfig.Data.Server.Relay.Distributed.Node.MaxConnection * 2 > connectionNum;
|
||||
if (res == false && LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
||||
LoggerHelper.Instance.Debug($"relay ValidateConnection false,{connectionNum}/{fileConfig.Data.Server.Relay.Distributed.Node.MaxConnection*2}");
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -109,8 +113,13 @@ namespace linker.plugins.relay.server
|
||||
/// <returns></returns>
|
||||
public bool ValidateBytes()
|
||||
{
|
||||
return fileConfig.Data.Server.Relay.Distributed.Node.MaxGbTotal == 0
|
||||
bool res= fileConfig.Data.Server.Relay.Distributed.Node.MaxGbTotal == 0
|
||||
|| (fileConfig.Data.Server.Relay.Distributed.Node.MaxGbTotal > 0 && fileConfig.Data.Server.Relay.Distributed.Node.MaxGbTotalLastBytes > 0);
|
||||
|
||||
if (res == false && LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
||||
LoggerHelper.Instance.Debug($"relay ValidateBytes false,{fileConfig.Data.Server.Relay.Distributed.Node.MaxGbTotalLastBytes}bytes/{fileConfig.Data.Server.Relay.Distributed.Node.MaxGbTotal}gb");
|
||||
|
||||
return res;
|
||||
}
|
||||
/// <summary>
|
||||
/// 添加流量
|
||||
|
@@ -13,6 +13,7 @@ using linker.plugins.socks5.config;
|
||||
using System.Text;
|
||||
using System.Collections.Generic;
|
||||
using linker.plugins.relay.client;
|
||||
using linker.client.config;
|
||||
|
||||
namespace linker.plugins.socks5
|
||||
{
|
||||
@@ -25,8 +26,8 @@ namespace linker.plugins.socks5
|
||||
|
||||
protected override string TransactionId => "socks5";
|
||||
|
||||
public TunnelProxy(FileConfig config, TunnelTransfer tunnelTransfer, RelayTransfer relayTransfer, ClientSignInTransfer clientSignInTransfer, ClientSignInState clientSignInState)
|
||||
: base(config, tunnelTransfer, relayTransfer, clientSignInTransfer, clientSignInState)
|
||||
public TunnelProxy(FileConfig config, TunnelTransfer tunnelTransfer, RelayTransfer relayTransfer, ClientSignInTransfer clientSignInTransfer, ClientSignInState clientSignInState, RunningConfig runningConfig)
|
||||
: base(config, tunnelTransfer, relayTransfer, clientSignInTransfer, clientSignInState, runningConfig)
|
||||
{
|
||||
TaskUdp();
|
||||
}
|
||||
|
@@ -3,6 +3,9 @@ using System.Net;
|
||||
using System.Buffers;
|
||||
using linker.libs.extends;
|
||||
using linker.plugins.resolver;
|
||||
using linker.libs;
|
||||
using System.Text;
|
||||
using System;
|
||||
|
||||
namespace linker.plugins.tunnel
|
||||
{
|
||||
@@ -28,6 +31,8 @@ namespace linker.plugins.tunnel
|
||||
/// <returns></returns>
|
||||
public async Task Resolve(Socket socket, IPEndPoint ep, Memory<byte> memory)
|
||||
{
|
||||
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG) LoggerHelper.Instance.Debug($"{ep} get udp external port");
|
||||
|
||||
AddReceive((ulong)memory.Length);
|
||||
byte[] sendData = ArrayPool<byte>.Shared.Rent(20);
|
||||
try
|
||||
@@ -36,8 +41,9 @@ namespace linker.plugins.tunnel
|
||||
AddSendt((ulong)send.Length);
|
||||
await socket.SendToAsync(send, SocketFlags.None, ep).ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception)
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG) LoggerHelper.Instance.Error(ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -51,15 +57,17 @@ namespace linker.plugins.tunnel
|
||||
/// <returns></returns>
|
||||
public async Task Resolve(Socket socket, Memory<byte> memory)
|
||||
{
|
||||
byte[] sendData = ArrayPool<byte>.Shared.Rent(20);
|
||||
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG) LoggerHelper.Instance.Debug($"{socket.RemoteEndPoint} get tcp external port");
|
||||
byte[] sendData = ArrayPool<byte>.Shared.Rent(1024);
|
||||
try
|
||||
{
|
||||
memory = BuildSendData(sendData, socket.RemoteEndPoint as IPEndPoint);
|
||||
AddSendt((ulong)memory.Length);
|
||||
await socket.SendAsync(memory, SocketFlags.None).ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception)
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG) LoggerHelper.Instance.Error(ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -78,7 +86,11 @@ namespace linker.plugins.tunnel
|
||||
{
|
||||
data[i] = (byte)(data[i] ^ byte.MaxValue);
|
||||
}
|
||||
return data.AsMemory(0, 1 + length + 2);
|
||||
|
||||
byte[] temp = Encoding.UTF8.GetBytes(Environment.TickCount64.ToString().Md5().SubStr(0, new Random().Next(16, 32)));
|
||||
temp.AsMemory().CopyTo(data.AsMemory(1 + length + 2));
|
||||
|
||||
return data.AsMemory(0, 1 + length + 2 + temp.Length);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -6,6 +6,7 @@ using linker.tunnel;
|
||||
using linker.tunnel.connection;
|
||||
using System.Collections.Concurrent;
|
||||
using linker.plugins.relay.client;
|
||||
using linker.client.config;
|
||||
|
||||
namespace linker.plugins.tunnel
|
||||
{
|
||||
@@ -21,16 +22,18 @@ namespace linker.plugins.tunnel
|
||||
private readonly RelayTransfer relayTransfer;
|
||||
private readonly ClientSignInTransfer clientSignInTransfer;
|
||||
private readonly ClientSignInState clientSignInState;
|
||||
private readonly RunningConfig runningConfig;
|
||||
|
||||
private uint maxTimes = 3;
|
||||
|
||||
public TunnelBase(FileConfig config, TunnelTransfer tunnelTransfer, RelayTransfer relayTransfer, ClientSignInTransfer clientSignInTransfer, ClientSignInState clientSignInState)
|
||||
public TunnelBase(FileConfig config, TunnelTransfer tunnelTransfer, RelayTransfer relayTransfer, ClientSignInTransfer clientSignInTransfer, ClientSignInState clientSignInState, RunningConfig runningConfig)
|
||||
{
|
||||
this.config = config;
|
||||
this.tunnelTransfer = tunnelTransfer;
|
||||
this.relayTransfer = relayTransfer;
|
||||
this.clientSignInTransfer = clientSignInTransfer;
|
||||
this.clientSignInState = clientSignInState;
|
||||
this.runningConfig = runningConfig;
|
||||
|
||||
//监听打洞成功
|
||||
tunnelTransfer.SetConnectedCallback(TransactionId, OnConnected);
|
||||
|
@@ -4,7 +4,6 @@ using linker.libs;
|
||||
using linker.plugins.client;
|
||||
using linker.plugins.decenter;
|
||||
using linker.plugins.messenger;
|
||||
using linker.plugins.tunnel.messenger;
|
||||
using linker.tunnel;
|
||||
using linker.tunnel.adapter;
|
||||
using MemoryPack;
|
||||
|
@@ -29,6 +29,7 @@ namespace linker.client.config
|
||||
|
||||
public int PortMapWan { get; set; }
|
||||
public int PortMapLan { get; set; }
|
||||
|
||||
}
|
||||
|
||||
[MemoryPackable]
|
||||
|
@@ -32,7 +32,7 @@ namespace linker.plugins.tuntap
|
||||
private readonly ClientSignInState clientSignInState;
|
||||
|
||||
public TuntapProxy(FileConfig config, RunningConfig runningConfig, TunnelTransfer tunnelTransfer, RelayTransfer relayTransfer, ClientSignInTransfer clientSignInTransfer, LinkerTunDeviceAdapter linkerTunDeviceAdapter, ClientSignInState clientSignInState)
|
||||
: base(config, tunnelTransfer, relayTransfer, clientSignInTransfer, clientSignInState)
|
||||
: base(config, tunnelTransfer, relayTransfer, clientSignInTransfer, clientSignInState, runningConfig)
|
||||
{
|
||||
this.config = config;
|
||||
this.runningConfig = runningConfig;
|
||||
|
@@ -33,16 +33,16 @@ do
|
||||
fi
|
||||
done
|
||||
cd public/publish/docker/linux-${p}-x64/${f}
|
||||
docker buildx build -f ${target}/public/publish/docker/linux-${p}-x64/${f}/Dockerfile-${p} --platform="linux/x86_64" --force-rm -t "${image}-${p}-x64:latest" -t "${image}-${p}-x64:v1.5.9" . --push
|
||||
docker buildx build -f ${target}/public/publish/docker/linux-${p}-x64/${f}/Dockerfile-${p} --platform="linux/x86_64" --force-rm -t "${image}-${p}-x64:latest" -t "${image}-${p}-x64:v1.6.0" . --push
|
||||
cd ../../../../../
|
||||
|
||||
|
||||
cd public/publish/docker/linux-${p}-arm64/${f}
|
||||
docker buildx build -f ${target}/public/publish/docker/linux-${p}-arm64/${f}/Dockerfile-${p} --platform="linux/arm64" --force-rm -t "${image}-${p}-arm64:latest" -t "${image}-${p}-arm64:v1.5.9" . --push
|
||||
docker buildx build -f ${target}/public/publish/docker/linux-${p}-arm64/${f}/Dockerfile-${p} --platform="linux/arm64" --force-rm -t "${image}-${p}-arm64:latest" -t "${image}-${p}-arm64:v1.6.0" . --push
|
||||
cd ../../../../../
|
||||
|
||||
cd public/publish/docker/linux-${p}-arm/${f}
|
||||
docker buildx build -f ${target}/public/publish/docker/linux-${p}-arm/${f}/Dockerfile-${p} --platform="linux/arm/v7" --force-rm -t "${image}-${p}-arm:latest" -t "${image}-${p}-arm:v1.5.9" . --push
|
||||
docker buildx build -f ${target}/public/publish/docker/linux-${p}-arm/${f}/Dockerfile-${p} --platform="linux/arm/v7" --force-rm -t "${image}-${p}-arm:latest" -t "${image}-${p}-arm:v1.6.0" . --push
|
||||
cd ../../../../../
|
||||
done
|
||||
done
|
11
version.txt
11
version.txt
@@ -1,6 +1,5 @@
|
||||
v1.5.9
|
||||
2024-11-22 17:23:21
|
||||
1. 优化UI
|
||||
2. 优化网卡
|
||||
3. 修复网卡禁用自动重启
|
||||
4. 增加一键安装脚本
|
||||
v1.6.0
|
||||
2024-11-29 00:49:22
|
||||
1. 优化websocket(某些代理环境下可能请求头key名称不规范)
|
||||
2. 尝试解决UDP获取外网IP端口失败的问题
|
||||
3. 测试中
|
Reference in New Issue
Block a user