Compare commits

..

28 Commits

Author SHA1 Message Date
asdlokj1qpi23
322924f24a fix actions issues 2023-12-25 12:44:00 +08:00
asdlokj1qpi23
04a2c24904 fix actions issues 2023-12-25 12:38:55 +08:00
asdlokj1qpi23
e80ce5833c add arm test 2023-12-25 11:33:22 +08:00
asdlokj1qpi23
31ba5373f0 add arm test 2023-12-25 11:10:37 +08:00
asdlokj1qpi23
d3801b7951 add arm test 2023-12-25 11:09:32 +08:00
asdlokj1qpi23
31775a91a8 add arm test 2023-12-25 11:01:34 +08:00
asdlokj1qpi23
af4dd857a8 Revert "fix vless short_id issue.(#1)"
This reverts commit 686f6b3517.
2023-12-25 11:00:27 +08:00
asdlokj1qpi23
686f6b3517 fix vless short_id issue.(#1) 2023-12-25 11:00:02 +08:00
asdlokj1qpi23
ebad0e96f7 fix vless short_id issue.(#1) 2023-12-25 10:51:21 +08:00
asdlokj1qpi23
927c828a27 Hy1 add ports support for clash export. 2023-12-25 10:22:33 +08:00
asdlokj1qpi23
13a372511b Hy1 add ports support. 2023-12-25 10:19:50 +08:00
asdlokj1qpi23
119df56f35 clean useless code. 2023-12-22 10:32:09 +08:00
asdlokj1qpi23
0672bd11cd Add auth-str for export Clash. 2023-12-22 10:23:44 +08:00
asdlokj1qpi23
f4de5097a6 remove clash api 2023-12-22 09:48:22 +08:00
asdlokj1qpi23
cb36b431ce Update singbox.json for clash API 2023-12-22 09:47:04 +08:00
asdlokj1qpi23
d5b3f920b8 fix path bug for vless websocket 2023-12-22 09:34:50 +08:00
asdlokj1qpi23
69e35d6657 add insecure for hy 2023-12-21 20:24:12 +08:00
asdlokj1qpi23
936ff011e9 add insecure for hy2 2023-12-21 20:19:57 +08:00
asdlokj1qpi23
0cda1641d3 update version.h 2023-12-21 19:50:10 +08:00
asdlokj1qpi23
5b85906be1 Fixing WireGuard, hy and hy2 Protocol export Issues. 2023-12-21 19:27:31 +08:00
asdlokj1qpi23
03b6f02573 Change readme and workflow. 2023-12-21 15:52:39 +08:00
asdlokj1qpi23
92db1f1f58 Change readme and workflow. 2023-12-21 15:50:13 +08:00
asdlokj1qpi23
d68a2217fe Fix bugs in vless reality protocol for Clash Meta and Singbox. Fix bug in hy2 for Singbox. 2023-12-21 14:25:33 +08:00
asdlokj1qpi23
ca6042bb8c fix hysteria2 password empty bug 2023-12-21 11:01:08 +08:00
asdlokj1qpi23
3b7b519584 remove shadowsocksr for singbox 2023-12-21 10:21:59 +08:00
asdlokj1qpi23
26f8f51eb5 fix vless support bug 2023-12-20 11:06:02 +08:00
asdlokj1qpi23
9f8067ab11 fix singbox transport of websocket bug 2023-12-20 10:42:42 +08:00
asdlokj1qpi23
3938ebfce9 add vless reality support. 2023-12-19 17:20:26 +08:00
10 changed files with 769 additions and 713 deletions

View File

@@ -1,7 +1,6 @@
name: GitHub CI
on:
push:
branches: [ master ]
tags:
- '**'
workflow_dispatch:
@@ -64,12 +63,14 @@ jobs:
armv7_build:
name: Linux armv7 Build
runs-on: [self-hosted, linux, ARM]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Add commit id into version
if: ${{ !startsWith(github.ref, 'refs/tags/') }}
run: SHA=$(git rev-parse --short HEAD) && sed -i 's/\(v[0-9]\.[0-9]\.[0-9]\)/\1-'"$SHA"'/' src/version.h
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Build
run: docker run --rm -v $GITHUB_WORKSPACE:/root/workdir multiarch/alpine:armv7-latest-stable /bin/sh -c "apk add bash git nodejs npm && cd /root/workdir && chmod +x scripts/build.alpine.release.sh && bash scripts/build.alpine.release.sh"
- name: Upload
@@ -89,12 +90,14 @@ jobs:
aarch64_build:
name: Linux aarch64 Build
runs-on: [self-hosted, linux, ARM64]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Add commit id into version
if: ${{ !startsWith(github.ref, 'refs/tags/') }}
run: SHA=$(git rev-parse --short HEAD) && sed -i 's/\(v[0-9]\.[0-9]\.[0-9]\)/\1-'"$SHA"'/' src/version.h
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Build
run: docker run --rm -v $GITHUB_WORKSPACE:/root/workdir multiarch/alpine:aarch64-latest-stable /bin/sh -c "apk add bash git nodejs npm && cd /root/workdir && chmod +x scripts/build.alpine.release.sh && bash scripts/build.alpine.release.sh"
- name: Upload

View File

@@ -106,7 +106,7 @@ jobs:
with:
platforms: linux/386
context: scripts/
tags: asdlokj1qpi23/subconverter:latest-x86
tags: asdlokj1qpi23/subconverter:latest
build-args: |
SHA=${{ steps.vars.outputs.sha_short }}
outputs: type=image,push=true
@@ -127,7 +127,7 @@ jobs:
with:
platforms: linux/386
context: scripts/
tags: asdlokj1qpi23/subconverter:${{steps.version.outputs.result}}-x86
tags: asdlokj1qpi23/subconverter:${{steps.version.outputs.result}}
outputs: type=image,push=true
- name: Save digest
@@ -146,13 +146,14 @@ jobs:
armv7_build:
name: Build ARMv7 Image
runs-on: [self-hosted, linux, ARM]
runs-on: ubuntu-latest
steps:
- name: Checkout base
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
@@ -173,7 +174,7 @@ jobs:
with:
platforms: linux/arm/v7
context: scripts/
tags: asdlokj1qpi23/subconverter:latest-armv7
tags: asdlokj1qpi23/subconverter:latest
build-args: |
SHA=${{ steps.vars.outputs.sha_short }}
THREADS=4
@@ -195,7 +196,7 @@ jobs:
with:
platforms: linux/arm/v7
context: scripts/
tags: asdlokj1qpi23/subconverter:${{steps.version.outputs.result}}-armv7
tags: asdlokj1qpi23/subconverter:${{steps.version.outputs.result}}
build-args: |
THREADS=4
outputs: type=image,push=true
@@ -216,13 +217,14 @@ jobs:
arm64_build:
name: Build ARM64 Image
runs-on: [self-hosted, linux, ARM64]
runs-on: ubuntu-latest
steps:
- name: Checkout base
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
@@ -243,7 +245,7 @@ jobs:
with:
platforms: linux/arm64
context: scripts/
tags: asdlokj1qpi23/subconverter:latest-arm64
tags: asdlokj1qpi23/subconverter:latest
build-args: |
SHA=${{ steps.vars.outputs.sha_short }}
THREADS=4
@@ -265,7 +267,7 @@ jobs:
with:
platforms: linux/arm64
context: scripts/
tags: asdlokj1qpi23/subconverter:${{steps.version.outputs.result}}-arm64
tags: asdlokj1qpi23/subconverter:${{steps.version.outputs.result}}
build-args: |
THREADS=4
outputs: type=image,push=true
@@ -287,6 +289,7 @@ jobs:
build:
name: Build
needs: [amd64_build, x86_build, armv7_build, arm64_build]
# needs: [amd64_build, x86_build]
runs-on: ubuntu-latest
steps:
- name: Checkout base

View File

@@ -1,11 +1,9 @@
# subconverter-docker
This is a minimized image to run https://github.com/tindy2013/subconverter.
For running this docker, simply use the following commands:
```bash
# run the container detached, forward internal port 25500 to host port 25500
docker run -d --restart=always -p 25500:25500 tindy2013/subconverter:latest
docker run -d --restart=always -p 25500:25500 asdlokj1qpi23/subconverter:latest
# then check its status
curl http://localhost:25500/version
# if you see `subconverter vx.x.x backend` then the container is up and running
@@ -16,7 +14,7 @@ Or run in docker-compose:
version: '3'
services:
subconverter:
image: tindy2013/subconverter:latest
image: asdlokj1qpi23/subconverter:latest
container_name: subconverter
ports:
- "15051:25500"

View File

@@ -2,23 +2,46 @@
Utility to convert between various proxy subscription formats.
[![Build Status](https://github.com/tindy2013/subconverter/actions/workflows/build.yml/badge.svg)](https://github.com/tindy2013/subconverter/actions)
[![GitHub tag (latest SemVer)](https://img.shields.io/github/tag/tindy2013/subconverter.svg)](https://github.com/tindy2013/subconverter/tags)
[![GitHub release](https://img.shields.io/github/release/tindy2013/subconverter.svg)](https://github.com/tindy2013/subconverter/releases)
[![GitHub license](https://img.shields.io/github/license/tindy2013/subconverter.svg)](https://github.com/tindy2013/subconverter/blob/master/LICENSE)
[![Build Status](https://github.com/asdlokj1qpi23/subconverter/actions/workflows/build.yml/badge.svg)](https://github.com/asdlokj1qpi23/subconverter/actions)
[![GitHub tag (latest SemVer)](https://img.shields.io/github/tag/asdlokj1qpi23/subconverter.svg)](https://github.com/asdlokj1qpi23/subconverter/tags)
[![GitHub release](https://img.shields.io/github/release/asdlokj1qpi23/subconverter.svg)](https://github.com/asdlokj1qpi23/subconverter/releases)
[![GitHub license](https://img.shields.io/github/license/asdlokj1qpi23/subconverter.svg)](https://github.com/tindy2013/subconverter/blob/master/LICENSE)
[Docker README](https://github.com/tindy2013/subconverter/blob/master/README-docker.md)
[Docker README](https://github.com/asdlokj1qpi23/subconverter/blob/master/README-docker.md)
[中文文档](https://github.com/tindy2013/subconverter/blob/master/README-cn.md)
[中文文档](https://github.com/asdlokj1qpi23/subconverter/blob/master/README-cn.md)
- [subconverter](#subconverter)
- [Docker](#docker)
- [Supported Types](#supported-types)
- [Quick Usage](#quick-usage)
- [Access Interface](#access-interface)
- [Description](#description)
- [Advanced Usage](#advanced-usage)
- [Auto Upload](#auto-upload)
## Docker
For running this docker, simply use the following commands:
```bash
# run the container detached, forward internal port 25500 to host port 25500
docker run -d --restart=always -p 25500:25500 asdlokj1qpi23/subconverter:latest
# then check its status
curl http://localhost:25500/version
# if you see `subconverter vx.x.x backend` then the container is up and running
```
Or run in docker-compose:
```yaml
---
version: '3'
services:
subconverter:
image: asdlokj1qpi23/subconverter:latest
container_name: subconverter
ports:
- "15051:25500"
restart: always
```
## Supported Types
| Type | As Source | As Target | Target Name |
@@ -95,7 +118,7 @@ Finally subscribe this link in Clash and you are done!
## Advanced Usage
Please refer to [中文文档](https://github.com/tindy2013/subconverter/blob/master/README-cn.md#%E8%BF%9B%E9%98%B6%E7%94%A8%E6%B3%95).
Please refer to [中文文档](https://github.com/asdlokj1qpi23/subconverter/blob/master/README-cn.md#%E8%BF%9B%E9%98%B6%E7%94%A8%E6%B3%95).
## Auto Upload
@@ -110,3 +133,6 @@ Example:
;uncomment the following line and enter your token to enable upload function
token = xxxxxxxxxxxxxxxxxxxxxxxx(Your Personal Access Token)
```
## Thanks
[tindy2013](https://github.com/tindy2013)
[https://github.com/tindy2013/subconverter](https://github.com/tindy2013/subconverter)

View File

@@ -436,10 +436,14 @@ proxyToClash(std::vector<Proxy> &nodes, YAML::Node &yamlnode, const ProxyGroupCo
case ProxyType::Hysteria:
singleproxy["type"] = "hysteria";
singleproxy["auth_str"] = x.Auth;
singleproxy["auth-str"] = x.Auth;
singleproxy["up"] = x.UpMbps;
singleproxy["down"] = x.DownMbps;
if (!tfo.is_undef())
singleproxy["fast-open"] = tfo.get();
if (!x.Ports.empty()) {
singleproxy["ports"] = x.Ports;
}
if (!tfo.is_undef()){
singleproxy["fast-open"] = tfo.get();}
if (!x.FakeType.empty())
singleproxy["protocol"] = x.FakeType;
if (!x.Host.empty())
@@ -492,6 +496,9 @@ proxyToClash(std::vector<Proxy> &nodes, YAML::Node &yamlnode, const ProxyGroupCo
if (!x.ShortId.empty()) {
singleproxy["reality-opts"]["short-id"] = x.ShortId;
}
if (!x.PublicKey.empty() || x.Flow == "xtls-rprx-vision") {
singleproxy["client-fingerprint"] = "chrome";
}
switch (hash_(x.TransferProtocol)) {
case "tcp"_hash:
break;
@@ -2109,6 +2116,15 @@ static rapidjson::Value stringArrayToJsonArray(const std::string &array, const s
return result;
}
bool isNumeric(const std::string &str) {
for (char c: str) {
if (!std::isdigit(static_cast<unsigned char>(c))) {
return false;
}
}
return true;
}
void
proxyToSingBox(std::vector<Proxy> &nodes, rapidjson::Document &json, std::vector<RulesetContent> &ruleset_content_array,
const ProxyGroupConfigs &extra_proxy_group, extra_settings &ext) {
@@ -2117,6 +2133,7 @@ proxyToSingBox(std::vector<Proxy> &nodes, rapidjson::Document &json, std::vector
rapidjson::Value outbounds(rapidjson::kArrayType), route(rapidjson::kArrayType);
std::vector<Proxy> nodelist;
string_array remarks_list;
std::string search = " Mbps";
if (!ext.nodelist) {
auto direct = buildObject(allocator, "type", "direct", "tag", "DIRECT");
@@ -2154,16 +2171,16 @@ proxyToSingBox(std::vector<Proxy> &nodes, rapidjson::Document &json, std::vector
}
break;
}
case ProxyType::ShadowsocksR: {
addSingBoxCommonMembers(proxy, x, "shadowsocksr", allocator);
proxy.AddMember("method", rapidjson::StringRef(x.EncryptMethod.c_str()), allocator);
proxy.AddMember("password", rapidjson::StringRef(x.Password.c_str()), allocator);
proxy.AddMember("protocol", rapidjson::StringRef(x.Protocol.c_str()), allocator);
proxy.AddMember("protocol_param", rapidjson::StringRef(x.ProtocolParam.c_str()), allocator);
proxy.AddMember("obfs", rapidjson::StringRef(x.OBFS.c_str()), allocator);
proxy.AddMember("obfs_param", rapidjson::StringRef(x.OBFSParam.c_str()), allocator);
break;
}
// case ProxyType::ShadowsocksR: {
// addSingBoxCommonMembers(proxy, x, "shadowsocksr", allocator);
// proxy.AddMember("method", rapidjson::StringRef(x.EncryptMethod.c_str()), allocator);
// proxy.AddMember("password", rapidjson::StringRef(x.Password.c_str()), allocator);
// proxy.AddMember("protocol", rapidjson::StringRef(x.Protocol.c_str()), allocator);
// proxy.AddMember("protocol_param", rapidjson::StringRef(x.ProtocolParam.c_str()), allocator);
// proxy.AddMember("obfs", rapidjson::StringRef(x.OBFS.c_str()), allocator);
// proxy.AddMember("obfs_param", rapidjson::StringRef(x.OBFSParam.c_str()), allocator);
// break;
// }
case ProxyType::VMess: {
addSingBoxCommonMembers(proxy, x, "vmess", allocator);
proxy.AddMember("uuid", rapidjson::StringRef(x.UserId.c_str()), allocator);
@@ -2175,49 +2192,50 @@ proxyToSingBox(std::vector<Proxy> &nodes, rapidjson::Document &json, std::vector
proxy.AddMember("transport", transport, allocator);
break;
}
// TODO VLESS后续支持
case ProxyType::VLESS: {
addSingBoxCommonMembers(proxy, x, "vmess", allocator);
addSingBoxCommonMembers(proxy, x, "vless", allocator);
proxy.AddMember("uuid", rapidjson::StringRef(x.UserId.c_str()), allocator);
if (xudp && udp)
proxy.AddMember("packet_encoding", rapidjson::StringRef("xudp"), allocator);
if (!x.Host.empty())
proxy.AddMember("server", rapidjson::StringRef(x.Host.c_str()), allocator);
if (!x.Flow.empty())
proxy.AddMember("flow", rapidjson::StringRef(x.Flow.c_str()), allocator);
rapidjson::Value transport(rapidjson::kObjectType);
rapidjson::Value vlesstransport(rapidjson::kObjectType);
rapidjson::Value vlessheaders(rapidjson::kObjectType);
switch (hash_(x.TransferProtocol)) {
case "tcp"_hash:
proxy.AddMember("network", rapidjson::StringRef("ws"), allocator);
break;
case "ws"_hash:
transport.AddMember("type", rapidjson::StringRef("ws"), allocator);
transport.AddMember("host", rapidjson::StringRef(x.Host.c_str()), allocator);
transport.AddMember("path", rapidjson::StringRef(x.Path.c_str()), allocator);
addHeaders(transport, x, allocator);
proxy.AddMember("transport", transport, allocator);
if (x.Path.empty())
vlesstransport.AddMember("path", "/", allocator);
else
vlesstransport.AddMember("path", rapidjson::StringRef(x.Path.c_str()), allocator);
if (!x.Host.empty())
vlessheaders.AddMember("Host", rapidjson::StringRef(x.Host.c_str()), allocator);
if (!x.Edge.empty())
vlessheaders.AddMember("Edge", rapidjson::StringRef(x.Edge.c_str()), allocator);
vlesstransport.AddMember("type", rapidjson::StringRef("ws"), allocator);
addHeaders(vlesstransport, x, allocator);
proxy.AddMember("transport", vlesstransport, allocator);
break;
case "http"_hash:
transport.AddMember("type", rapidjson::StringRef("http"), allocator);
transport.AddMember("host", rapidjson::StringRef(x.Host.c_str()), allocator);
transport.AddMember("method", rapidjson::StringRef("GET"), allocator);
transport.AddMember("path", rapidjson::StringRef(x.Path.c_str()), allocator);
addHeaders(transport, x, allocator);
proxy.AddMember("transport", transport, allocator);
vlesstransport.AddMember("type", rapidjson::StringRef("http"), allocator);
vlesstransport.AddMember("host", rapidjson::StringRef(x.Host.c_str()), allocator);
vlesstransport.AddMember("method", rapidjson::StringRef("GET"), allocator);
vlesstransport.AddMember("path", rapidjson::StringRef(x.Path.c_str()), allocator);
addHeaders(vlesstransport, x, allocator);
proxy.AddMember("transport", vlesstransport, allocator);
break;
case "h2"_hash:
transport.AddMember("type", rapidjson::StringRef("httpupgrade"), allocator);
transport.AddMember("host", rapidjson::StringRef(x.Host.c_str()), allocator);
transport.AddMember("path", rapidjson::StringRef(x.Path.c_str()), allocator);
proxy.AddMember("transport", transport, allocator);
vlesstransport.AddMember("type", rapidjson::StringRef("httpupgrade"), allocator);
vlesstransport.AddMember("host", rapidjson::StringRef(x.Host.c_str()), allocator);
vlesstransport.AddMember("path", rapidjson::StringRef(x.Path.c_str()), allocator);
proxy.AddMember("transport", vlesstransport, allocator);
break;
case "grpc"_hash:
transport.AddMember("type", rapidjson::StringRef("grpc"), allocator);
transport.AddMember("service_name", rapidjson::StringRef(x.GRPCServiceName.c_str()), allocator);
if (!x.GRPCMode.empty()) {
transport.AddMember("permit_without_stream", rapidjson::StringRef("true"), allocator);
}
proxy.AddMember("transport", transport, allocator);
vlesstransport.AddMember("type", rapidjson::StringRef("grpc"), allocator);
vlesstransport.AddMember("service_name", rapidjson::StringRef(x.GRPCServiceName.c_str()),
allocator);
proxy.AddMember("transport", vlesstransport, allocator);
break;
default:
continue;
@@ -2236,13 +2254,15 @@ proxyToSingBox(std::vector<Proxy> &nodes, rapidjson::Document &json, std::vector
case ProxyType::WireGuard: {
proxy.AddMember("type", "wireguard", allocator);
proxy.AddMember("tag", rapidjson::StringRef(x.Remark.c_str()), allocator);
proxy.AddMember("inet4_bind_address", rapidjson::StringRef(x.SelfIP.c_str()), allocator);
rapidjson::Value addresses(rapidjson::kArrayType);
addresses.PushBack(rapidjson::StringRef(x.SelfIP.c_str()), allocator);
if (!x.SelfIPv6.empty())
addresses.PushBack(rapidjson::StringRef(x.SelfIPv6.c_str()), allocator);
addresses.PushBack(rapidjson::StringRef(x.SelfIP.append("/32").c_str()), allocator);
// if (!x.SelfIPv6.empty())
// addresses.PushBack(rapidjson::StringRef(x.SelfIPv6.c_str()), allocator);
proxy.AddMember("local_address", addresses, allocator);
if (!x.SelfIPv6.empty())
proxy.AddMember("inet6_bind_address", rapidjson::StringRef(x.SelfIPv6.c_str()), allocator);
proxy.AddMember("private_key", rapidjson::StringRef(x.PrivateKey.c_str()), allocator);
rapidjson::Value peer(rapidjson::kObjectType);
peer.AddMember("server", rapidjson::StringRef(x.Hostname.c_str()), allocator);
peer.AddMember("server_port", x.Port, allocator);
@@ -2283,19 +2303,36 @@ proxyToSingBox(std::vector<Proxy> &nodes, rapidjson::Document &json, std::vector
case ProxyType::Hysteria: {
addSingBoxCommonMembers(proxy, x, "hysteria", allocator);
proxy.AddMember("auth_str", rapidjson::StringRef(x.Auth.c_str()), allocator);
proxy.AddMember("up", rapidjson::StringRef(x.UpMbps.c_str()), allocator);
proxy.AddMember("down", rapidjson::StringRef(x.DownMbps.c_str()), allocator);
rapidjson::Value tls(rapidjson::kObjectType);
tls.AddMember("enabled", true, allocator);
proxy.AddMember("tls", tls, allocator);
if (!tfo.is_undef())
proxy.AddMember("tcp_fast_open",
rapidjson::StringRef(std::string(tfo.get() ? "true" : "false").c_str()), allocator);
if (isNumeric(x.UpMbps)) {
proxy.AddMember("up_mbps", std::stoi(x.UpMbps), allocator);
} else {
size_t pos = x.UpMbps.find(search);
if (pos != std::string::npos) {
x.UpMbps.replace(pos, search.length(), "");
}
proxy.AddMember("up_mbps", std::stoi(x.UpMbps), allocator);
}
if (isNumeric(x.DownMbps)) {
proxy.AddMember("down_mbps", std::stoi(x.DownMbps), allocator);
} else {
size_t pos = x.DownMbps.find(search);
if (pos != std::string::npos) {
x.DownMbps.replace(pos, search.length(), "");
}
proxy.AddMember("down_mbps", std::stoi(x.DownMbps), allocator);
}
if (!x.TLSSecure) {
rapidjson::Value tls(rapidjson::kObjectType);
tls.AddMember("enabled", true, allocator);
if (!x.Alpn.empty()) {
auto alpns = stringArrayToJsonArray(x.Alpn, ",", allocator);
tls.AddMember("alpn", alpns, allocator);
}
tls.AddMember("insecure", buildBooleanValue(scv), allocator);
proxy.AddMember("tls", tls, allocator);
}
if (!x.FakeType.empty())
proxy.AddMember("network", rapidjson::StringRef(x.FakeType.c_str()), allocator);
if (!x.Alpn.empty())
proxy.AddMember("tls", rapidjson::StringRef(
std::string(R"({ "enabled": true,"alpn": [)" + x.Alpn + "],}").c_str()), allocator);
if (!x.OBFSParam.empty())
proxy.AddMember("obfs", rapidjson::StringRef(x.OBFSParam.c_str()), allocator);
break;
@@ -2303,16 +2340,34 @@ proxyToSingBox(std::vector<Proxy> &nodes, rapidjson::Document &json, std::vector
case ProxyType::Hysteria2: {
addSingBoxCommonMembers(proxy, x, "hysteria2", allocator);
proxy.AddMember("password", rapidjson::StringRef(x.Password.c_str()), allocator);
rapidjson::Value tls(rapidjson::kObjectType);
tls.AddMember("enabled", true, allocator);
proxy.AddMember("tls", tls, allocator);
if (!x.UpMbps.empty())
proxy.AddMember("up_mbps", rapidjson::StringRef(x.UpMbps.c_str()), allocator);
if (!x.DownMbps.empty())
proxy.AddMember("down_mbps", rapidjson::StringRef(x.DownMbps.c_str()), allocator);
if (!x.Alpn.empty())
proxy.AddMember("tls", rapidjson::StringRef(
std::string(R"({ "enabled": true,"alpn": [)" + x.Alpn + "],}").c_str()), allocator);
if (!x.TLSSecure) {
rapidjson::Value tls(rapidjson::kObjectType);
tls.AddMember("enabled", true, allocator);
if (!x.Alpn.empty()) {
auto alpns = stringArrayToJsonArray(x.Alpn, ",", allocator);
tls.AddMember("alpn", alpns, allocator);
}
tls.AddMember("insecure", buildBooleanValue(scv), allocator);
proxy.AddMember("tls", tls, allocator);
}
if (!x.UpMbps.empty()) {
if (!isNumeric(x.UpMbps)) {
size_t pos = x.UpMbps.find(search);
if (pos != std::string::npos) {
x.UpMbps.replace(pos, search.length(), "");
}
}
proxy.AddMember("up_mbps", std::stoi(x.UpMbps), allocator);
}
if (!x.DownMbps.empty()) {
if (!isNumeric(x.DownMbps)) {
size_t pos = x.DownMbps.find(search);
if (pos != std::string::npos) {
x.DownMbps.replace(pos, search.length(), "");
}
}
proxy.AddMember("down_mbps", std::stoi(x.DownMbps), allocator);
}
if (!x.OBFSParam.empty()) {
if (!x.OBFSPassword.empty()) {
proxy.AddMember("obfs", rapidjson::StringRef(std::string(
@@ -2334,18 +2389,31 @@ proxyToSingBox(std::vector<Proxy> &nodes, rapidjson::Document &json, std::vector
tls.AddMember("enabled", true, allocator);
if (!x.ServerName.empty())
tls.AddMember("server_name", rapidjson::StringRef(x.ServerName.c_str()), allocator);
if (!x.Alpn.empty())
tls.AddMember("alpn", rapidjson::StringRef(("[" + x.Alpn + "]").c_str()), allocator);
if (!x.Alpn.empty()) {
auto alpns = stringArrayToJsonArray(x.Alpn, ",", allocator);
tls.AddMember("alpn", alpns, allocator);
}
tls.AddMember("insecure", buildBooleanValue(scv), allocator);
if (x.Type == ProxyType::VLESS) {
rapidjson::Value reality(rapidjson::kObjectType);
if (!x.PublicKey.empty() || !x.ShortId.empty()) {
reality.AddMember("enabled", rapidjson::StringRef("false"), allocator);
if (!x.PublicKey.empty()) {
reality.AddMember("public_key", rapidjson::StringRef("false"), allocator);
if (!x.Host.empty()) {
tls.EraseMember("server_name");
tls.AddMember("server_name", rapidjson::StringRef(x.Host.c_str()), allocator);
}
rapidjson::Value utls(rapidjson::kObjectType);
utls.AddMember("enabled", true, allocator);
utls.AddMember("fingerprint", rapidjson::StringRef("chrome"), allocator);
tls.AddMember("utls", utls, allocator);
reality.AddMember("enabled", true, allocator);
if (!x.PublicKey.empty()) {
reality.AddMember("public_key", rapidjson::StringRef(x.PublicKey.c_str()), allocator);
}
// auto shortIds = stringArrayToJsonArray(x.ShortId, ",", allocator);
if (!x.ShortId.empty()) {
reality.AddMember("short_id", rapidjson::StringRef(("[" + x.ShortId + "]").c_str()), allocator);
reality.AddMember("short_id", rapidjson::StringRef(x.ShortId.c_str()), allocator);
} else {
reality.AddMember("short_id", rapidjson::StringRef(""), allocator);
}
tls.AddMember("reality", reality, allocator);
}

File diff suppressed because it is too large Load Diff

View File

@@ -78,6 +78,8 @@ struct Proxy {
uint16_t AlterId = 0;
String TransferProtocol;
String FakeType;
String AuthStr;
bool TLSSecure = false;
String Host;
@@ -107,7 +109,7 @@ struct Proxy {
uint16_t KeepAlive = 0;
String TestUrl;
String ClientId;
String Ports;
String Auth;
String Alpn;
String UpMbps;

View File

@@ -115,7 +115,8 @@ void httpConstruct(Proxy &node, const std::string &group, const std::string &rem
void trojanConstruct(Proxy &node, const std::string &group, const std::string &remarks, const std::string &server,
const std::string &port, const std::string &password, const std::string &network,
const std::string &host, const std::string &path, bool tlssecure, tribool udp, tribool tfo,
const std::string &host, const std::string &path, const std::string &fp, bool tlssecure,
tribool udp, tribool tfo,
tribool scv, tribool tls13) {
commonConstruct(node, ProxyType::Trojan, group, remarks, server, port, udp, tfo, scv, tls13);
node.Password = password;
@@ -123,6 +124,7 @@ void trojanConstruct(Proxy &node, const std::string &group, const std::string &r
node.TLSSecure = tlssecure;
node.TransferProtocol = network.empty() ? "tcp" : network;
node.Path = path;
node.Fingerprint = fp;
}
void snellConstruct(Proxy &node, const std::string &group, const std::string &remarks, const std::string &server,
@@ -154,9 +156,9 @@ void wireguardConstruct(Proxy &node, const std::string &group, const std::string
}
void hysteriaConstruct(Proxy &node, const std::string &group, const std::string &remarks, const std::string &add,
const std::string &port, const std::string &type, const std::string &auth,
const std::string &port, const std::string &type, const std::string &auth,const std::string &auth_str,
const std::string &host, const std::string &up, const std::string &down, const std::string &alpn,
const std::string &obfsParam, const std::string &insecure, tribool udp, tribool tfo, tribool scv,
const std::string &obfsParam, const std::string &insecure,const std::string &ports, tribool udp, tribool tfo, tribool scv,
tribool tls13) {
commonConstruct(node, ProxyType::Hysteria, group, remarks, add, port, udp, tfo, scv, tls13);
node.Auth = auth;
@@ -167,6 +169,8 @@ void hysteriaConstruct(Proxy &node, const std::string &group, const std::string
node.OBFSParam = obfsParam;
node.Insecure = insecure;
node.FakeType = type;
node.AuthStr = auth_str;
node.Ports = ports;
}
@@ -793,11 +797,15 @@ void explodeHTTPSub(std::string link, Proxy &node) {
}
void explodeTrojan(std::string trojan, Proxy &node) {
std::string server, port, psk, addition, group, remark, host, path, network;
std::string server, port, psk, addition, group, remark, host, path, network, fp;
tribool tfo, scv;
trojan.erase(0, 9);
if (startsWith(trojan, "trojan://")) {
trojan.erase(0, 9);
}
if (startsWith(trojan, "trojan-go://")) {
trojan.erase(0, 12);
}
string_size pos = trojan.rfind('#');
if (pos != std::string::npos) {
remark = urlDecode(trojan.substr(pos + 1));
trojan.erase(pos);
@@ -817,6 +825,7 @@ void explodeTrojan(std::string trojan, Proxy &node) {
if (host.empty())
host = getUrlArg(addition, "peer");
tfo = getUrlArg(addition, "tfo");
fp = getUrlArg(addition, "fp");
scv = getUrlArg(addition, "allowInsecure");
group = urlDecode(getUrlArg(addition, "group"));
@@ -838,7 +847,7 @@ void explodeTrojan(std::string trojan, Proxy &node) {
if (group.empty())
group = TROJAN_DEFAULT_GROUP;
trojanConstruct(node, group, remark, server, port, psk, network, host, path, true, tribool(), tfo, scv);
trojanConstruct(node, group, remark, server, port, psk, network, host, path, fp, true, tribool(), tfo, scv);
}
void explodeVless(std::string vless, Proxy &node) {
@@ -850,6 +859,7 @@ void explodeVless(std::string vless, Proxy &node) {
void explodeHysteria(std::string hysteria, Proxy &node) {
printf("explodeHysteria\n");
hysteria = regReplace(hysteria, "(hysteria|hy)://", "hysteria://");
if (regMatch(hysteria, "hysteria://(.*?)[:](.*)")) {
explodeStdHysteria(hysteria, node);
return;
@@ -932,7 +942,7 @@ void explodeQuan(const std::string &quan, Proxy &node) {
void explodeNetch(std::string netch, Proxy &node) {
Document json;
std::string type, group, remark, address, port, username, password, method, plugin, pluginopts;
std::string protocol, protoparam, obfs, obfsparam, id, aid, transprot, faketype, host, edge, path, tls, sni;
std::string protocol, protoparam, obfs, obfsparam, id, aid, transprot, faketype, host, edge, path, tls, sni, fp;
tribool udp, tfo, scv;
netch = urlSafeBase64Decode(netch.substr(8));
@@ -947,6 +957,7 @@ void explodeNetch(std::string netch, Proxy &node) {
tfo = GetMember(json, "EnableTFO");
scv = GetMember(json, "AllowInsecure");
port = GetMember(json, "Port");
fp = GetMember(json, "FingerPrint");
if (port == "0")
return;
method = GetMember(json, "EncryptMethod");
@@ -1014,7 +1025,7 @@ void explodeNetch(std::string netch, Proxy &node) {
tls = GetMember(json, "TLSSecure");
if (group.empty())
group = TROJAN_DEFAULT_GROUP;
trojanConstruct(node, group, remark, address, port, password, transprot, host, path, tls == "true", udp,
trojanConstruct(node, group, remark, address, port, password, transprot, host, path, fp, tls == "true", udp,
tfo, scv);
break;
case "Snell"_hash:
@@ -1031,7 +1042,7 @@ void explodeNetch(std::string netch, Proxy &node) {
}
void explodeClash(Node yamlnode, std::vector<Proxy> &nodes) {
std::string proxytype, ps, server, port, cipher, group, password,tempPassword; //common
std::string proxytype, ps, server, port, cipher, group, password = "",ports, tempPassword; //common
std::string type = "none", id, aid = "0", net = "tcp", path, host, edge, tls, sni; //vmess
std::string fp = "chrome", pbk, sid; //vless
std::string plugin, pluginopts, pluginopts_mode, pluginopts_host, pluginopts_mux; //ss
@@ -1039,7 +1050,7 @@ void explodeClash(Node yamlnode, std::vector<Proxy> &nodes) {
std::string flow, mode; //trojan
std::string user; //socks
std::string ip, ipv6, private_key, public_key, mtu; //wireguard
std::string auth, up, down, obfsParam, insecure,alpn;//hysteria
std::string auth, up, down, obfsParam, insecure, alpn;//hysteria
std::string obfsPassword;//hysteria2
string_array dns_server;
tribool udp, tfo, scv;
@@ -1217,7 +1228,7 @@ void explodeClash(Node yamlnode, std::vector<Proxy> &nodes) {
break;
}
trojanConstruct(node, group, ps, server, port, password, net, host, path, true, udp, tfo, scv);
trojanConstruct(node, group, ps, server, port, password, net, host, path, fp, true, udp, tfo, scv);
break;
case "snell"_hash:
group = SNELL_DEFAULT_GROUP;
@@ -1296,6 +1307,12 @@ void explodeClash(Node yamlnode, std::vector<Proxy> &nodes) {
case "hysteria"_hash:
group = HYSTERIA_DEFAULT_GROUP;
singleproxy["auth_str"] >> auth;
if (auth.empty()) {
singleproxy["auth-str"] >> auth;
if (auth.empty()) {
singleproxy["password"] >> auth;
}
}
singleproxy["up"] >> up;
singleproxy["down"] >> down;
singleproxy["obfs"] >> obfsParam;
@@ -1303,14 +1320,16 @@ void explodeClash(Node yamlnode, std::vector<Proxy> &nodes) {
singleproxy["sni"] >> host;
singleproxy["alpn"][0] >> alpn;
singleproxy["protocol"] >> insecure;
singleproxy["ports"] >> ports;
hysteriaConstruct(node, group, ps, server, port, type, auth, host, up, down, alpn, obfsParam, insecure,
hysteriaConstruct(node, group, ps, server, port, type, auth,"", host, up, down, alpn, obfsParam, insecure, ports,
udp, tfo, scv);
break;
case "hysteria2"_hash:
group = HYSTERIA2_DEFAULT_GROUP;
singleproxy["password"] >>= password;
singleproxy["auth"] >>= password;
if (password.empty())
singleproxy["auth"] >>= password;
singleproxy["up"] >>= up;
singleproxy["down"] >>= down;
singleproxy["obfs"] >>= obfsParam;
@@ -1373,7 +1392,7 @@ void explodeStdVMess(std::string vmess, Proxy &node) {
void explodeStdHysteria(std::string hysteria, Proxy &node) {
std::string add, port, type, auth, host, insecure, up, down, alpn, obfsParam, remarks;
std::string add, port, type, auth, host, insecure, up, down, alpn, obfsParam, remarks,auth_str;
std::string addition;
hysteria = hysteria.substr(11);
string_size pos;
@@ -1388,18 +1407,18 @@ void explodeStdHysteria(std::string hysteria, Proxy &node) {
return;
type = getUrlArg(addition, "protocol");
auth = getUrlArg(addition, "auth");
auth_str = getUrlArg(addition, "auth_str");
host = getUrlArg(addition, "peer");
insecure = getUrlArg(addition, "insecure");
up = getUrlArg(addition, "upmbps");
down = getUrlArg(addition, "downmbps");
alpn = getUrlArg(addition, "alpn");
obfsParam = getUrlArg(addition, "obfsParam");
if (remarks.empty())
remarks = add + ":" + port;
hysteriaConstruct(node, HYSTERIA_DEFAULT_GROUP, remarks, add, port, type, auth, host, up, down, alpn, obfsParam,
insecure);
hysteriaConstruct(node, HYSTERIA_DEFAULT_GROUP, remarks, add, port, type, auth,auth_str, host, up, down, alpn, obfsParam,
insecure,"");
return;
}
@@ -1641,7 +1660,7 @@ bool explodeSurge(std::string surge, std::vector<Proxy> &nodes) {
for (auto &x: proxies) {
std::string remarks, server, port, method, username, password; //common
std::string plugin, pluginopts, pluginopts_mode, pluginopts_host, mod_url, mod_md5; //ss
std::string id, net, tls, host, edge, path; //v2
std::string id, net, tls, host, edge, path, fp; //v2
std::string protocol, protoparam; //ssr
std::string section, ip, ipv6, private_key, public_key, mtu, test_url, client_id, peer, keepalive; //wireguard
string_array dns_servers;
@@ -1920,12 +1939,16 @@ bool explodeSurge(std::string surge, std::vector<Proxy> &nodes) {
case "skip-cert-verify"_hash:
scv = itemVal;
break;
case "fingerprint"_hash:
fp = itemVal;
break;
default:
continue;
}
}
trojanConstruct(node, TROJAN_DEFAULT_GROUP, remarks, server, port, password, "", host, "", true, udp,
trojanConstruct(node, TROJAN_DEFAULT_GROUP, remarks, server, port, password, "", host, "", fp, true,
udp,
tfo, scv);
break;
case "snell"_hash:
@@ -2226,6 +2249,9 @@ bool explodeSurge(std::string surge, std::vector<Proxy> &nodes) {
case "tls13"_hash:
tls13 = itemVal;
break;
case "fp"_hash:
fp = itemVal;
break;
default:
continue;
}
@@ -2233,7 +2259,7 @@ bool explodeSurge(std::string surge, std::vector<Proxy> &nodes) {
if (remarks.empty())
remarks = server + ":" + port;
trojanConstruct(node, TROJAN_DEFAULT_GROUP, remarks, server, port, password, "", host, "",
trojanConstruct(node, TROJAN_DEFAULT_GROUP, remarks, server, port, password, "", host, "", fp,
tls == "true", udp, tfo, scv, tls13);
break;
case "http"_hash: //quantumult x style http links
@@ -2433,11 +2459,11 @@ void explode(const std::string &link, Proxy &node) {
explodeHTTP(link, node);
else if (startsWith(link, "Netch://"))
explodeNetch(link, node);
else if (startsWith(link, "trojan://"))
else if (startsWith(link, "trojan://") || startsWith(link, "trojan-go://"))
explodeTrojan(link, node);
else if (strFind(link, "vless://") || strFind(link, "vless1://"))
explodeVless(link, node);
else if (strFind(link, "hysteria://"))
else if (strFind(link, "hysteria://") || strFind(link, "hy://"))
explodeHysteria(link, node);
else if (strFind(link, "hysteria2://") || strFind(link, "hy2://"))
explodeHysteria2(link, node);

View File

@@ -19,7 +19,7 @@ enum class ConfType
SUB,
Local
};
void hysteriaConstruct(Proxy &node, const std::string &group, const std::string &remarks, const std::string &add, const std::string &port, const std::string &type, const std::string &auth, const std::string &host, const std::string &up, const std::string &down, const std::string &alpn, const std::string &obfsParam, const std::string &insecure ,tribool udp = tribool(), tribool tfo = tribool(), tribool scv = tribool(), tribool tls13 = tribool());
void hysteriaConstruct(Proxy &node, const std::string &group, const std::string &remarks, const std::string &add, const std::string &port, const std::string &type, const std::string &auth, const std::string &auth_str, const std::string &host, const std::string &up, const std::string &down, const std::string &alpn, const std::string &obfsParam, const std::string &insecure,const std::string &ports,tribool udp = tribool(), tribool tfo = tribool(), tribool scv = tribool(), tribool tls13 = tribool());
void hysteria2Construct(Proxy &node, const std::string &group, const std::string &remarks, const std::string &add, const std::string &port, const std::string &password, const std::string &host, const std::string &up, const std::string &down, const std::string &alpn, const std::string &obfsParam, const std::string &obfsPassword, const std::string &insecure ,tribool udp = tribool(), tribool tfo = tribool(), tribool scv = tribool(), tribool tls13 = tribool());
void vlessConstruct(Proxy &node, const std::string &group, const std::string &remarks, const std::string &add, const std::string &port, const std::string &type, const std::string &id, const std::string &aid, const std::string &net, const std::string &cipher, const std::string &flow, const std::string &mode, const std::string &path, const std::string &host, const std::string &edge, const std::string &tls,const std::string &pkd, const std::string &sid, const std::string &fp, tribool udp = tribool(), tribool tfo = tribool(), tribool scv = tribool(), tribool tls13 = tribool());
void vmessConstruct(Proxy &node, const std::string &group, const std::string &remarks, const std::string &add, const std::string &port, const std::string &type, const std::string &id, const std::string &aid, const std::string &net, const std::string &cipher, const std::string &path, const std::string &host, const std::string &edge, const std::string &tls, const std::string &sni, tribool udp = tribool(), tribool tfo = tribool(), tribool scv = tribool(), tribool tls13 = tribool());
@@ -27,7 +27,7 @@ void ssrConstruct(Proxy &node, const std::string &group, const std::string &rema
void ssConstruct(Proxy &node, const std::string &group, const std::string &remarks, const std::string &server, const std::string &port, const std::string &password, const std::string &method, const std::string &plugin, const std::string &pluginopts, tribool udp = tribool(), tribool tfo = tribool(), tribool scv = tribool(), tribool tls13 = tribool());
void socksConstruct(Proxy &node, const std::string &group, const std::string &remarks, const std::string &server, const std::string &port, const std::string &username, const std::string &password, tribool udp = tribool(), tribool tfo = tribool(), tribool scv = tribool());
void httpConstruct(Proxy &node, const std::string &group, const std::string &remarks, const std::string &server, const std::string &port, const std::string &username, const std::string &password, bool tls, tribool tfo = tribool(), tribool scv = tribool(), tribool tls13 = tribool());
void trojanConstruct(Proxy &node, const std::string &group, const std::string &remarks, const std::string &server, const std::string &port, const std::string &password, const std::string &network, const std::string &host, const std::string &path, bool tlssecure, tribool udp = tribool(), tribool tfo = tribool(), tribool scv = tribool(), tribool tls13 = tribool());
void trojanConstruct(Proxy &node, const std::string &group, const std::string &remarks, const std::string &server, const std::string &port, const std::string &password, const std::string &network, const std::string &host, const std::string &path,const std::string &fp, bool tlssecure, tribool udp = tribool(), tribool tfo = tribool(), tribool scv = tribool(), tribool tls13 = tribool());
void snellConstruct(Proxy &node, const std::string &group, const std::string &remarks, const std::string &server, const std::string &port, const std::string &password, const std::string &obfs, const std::string &host, uint16_t version = 0, tribool udp = tribool(), tribool tfo = tribool(), tribool scv = tribool());
void explodeVmess(std::string vmess, Proxy &node);
void explodeSSR(std::string ssr, Proxy &node);

View File

@@ -1,6 +1,6 @@
#ifndef VERSION_H_INCLUDED
#define VERSION_H_INCLUDED
#define VERSION "v0.8.2"
#define VERSION "v0.9.1"
#endif // VERSION_H_INCLUDED