Compare commits

...

181 Commits

Author SHA1 Message Date
OPPO9008
ea125e4a4f
Update actions/upload-artifact: v3 to v4 (#742)
Some checks failed
CodeQL / Analyze (go) (push) Failing after 3m24s
Close inactive issues / close-issues (push) Successful in 7s
https://github.blog/changelog/2024-04-16-deprecation-notice-v3-of-the-artifact-actions/
2025-03-21 17:45:20 +08:00
kia678
6754483cca
Update docker.yml
Some checks failed
CodeQL / Analyze (go) (push) Failing after 39s
2025-03-21 02:27:52 +08:00
xrayrgoon
974abc9a98
xray-core v25.3.6 and other updates (#748)
Some checks failed
CodeQL / Analyze (go) (push) Failing after 4m49s
Build and Release / build (386, freebsd) (push) Failing after 8m40s
Build and Release / build (386, linux) (push) Failing after 7m10s
Build and Release / build (386, windows) (push) Failing after 6m49s
Build and Release / build (amd64, darwin) (push) Failing after 7m8s
Build and Release / build (amd64, freebsd) (push) Failing after 7m31s
Build and Release / build (amd64, linux) (push) Failing after 7m20s
Build and Release / build (amd64, openbsd) (push) Failing after 7m4s
Build and Release / build (amd64, windows) (push) Failing after 7m9s
Build and Release / build (arm, 5, linux) (push) Failing after 6m44s
Build and Release / build (arm, 6, linux) (push) Failing after 6m42s
Build and Release / build (arm, 7, freebsd) (push) Failing after 6m32s
Build and Release / build (arm, 7, linux) (push) Failing after 6m43s
Build and Release / build (arm64, android) (push) Failing after 6m59s
Build and Release / build (arm64, darwin) (push) Failing after 6m54s
Build and Release / build (arm64, freebsd) (push) Failing after 6m52s
Build and Release / build (arm64, linux) (push) Failing after 7m5s
Build and Release / build (mips, linux) (push) Failing after 12m35s
Build and Release / build (mips64, linux) (push) Failing after 7m4s
Build and Release / build (mips64le, linux) (push) Failing after 6m39s
Build and Release / build (mipsle, linux) (push) Failing after 11m56s
Build and Release / build (ppc64le, linux) (push) Failing after 6m54s
Build and Release / build (riscv64, linux) (push) Failing after 8m10s
Build and Release / build (s390x, linux) (push) Failing after 6m56s
Close inactive issues / close-issues (push) Successful in 25s
2025-03-21 02:07:22 +08:00
dependabot[bot]
b1f5ccfee8
build(deps): bump github.com/eko/gocache/store/go_cache/v4 (#701)
Bumps [github.com/eko/gocache/store/go_cache/v4](https://github.com/eko/gocache) from 4.2.1 to 4.2.2.
- [Release notes](https://github.com/eko/gocache/releases)
- [Commits](https://github.com/eko/gocache/compare/store/redis/v4.2.1...store/redis/v4.2.2)

---
updated-dependencies:
- dependency-name: github.com/eko/gocache/store/go_cache/v4
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-31 11:30:13 +08:00
dependabot[bot]
2f88334373
build(deps): bump golang.org/x/crypto from 0.25.0 to 0.28.0 (#704)
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.25.0 to 0.28.0.
- [Commits](https://github.com/golang/crypto/compare/v0.25.0...v0.28.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-31 11:29:51 +08:00
dependabot[bot]
35e726e766
build(deps): bump golang.org/x/time from 0.5.0 to 0.7.0 (#703)
Bumps [golang.org/x/time](https://github.com/golang/time) from 0.5.0 to 0.7.0.
- [Commits](https://github.com/golang/time/compare/v0.5.0...v0.7.0)

---
updated-dependencies:
- dependency-name: golang.org/x/time
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-31 11:29:31 +08:00
sakzri
4bbf3c9899
fix: handle domain with wildcards (#690) 2024-10-19 22:04:08 +08:00
RyarX
9391c759c9
New transports and api changes for V2RaySocks (#685)
* New transports and api changes for V2RaySocks

* version++
2024-10-19 22:03:05 +08:00
dependabot[bot]
eb16b709e2
build(deps): bump github.com/shirou/gopsutil/v3 from 3.24.2 to 3.24.5 (#666)
Bumps [github.com/shirou/gopsutil/v3](https://github.com/shirou/gopsutil) from 3.24.2 to 3.24.5.
- [Release notes](https://github.com/shirou/gopsutil/releases)
- [Commits](https://github.com/shirou/gopsutil/compare/v3.24.2...v3.24.5)

---
updated-dependencies:
- dependency-name: github.com/shirou/gopsutil/v3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-19 22:01:46 +08:00
dependabot[bot]
1f09502613
build(deps): bump github.com/spf13/cobra from 1.8.0 to 1.8.1 (#665)
Bumps [github.com/spf13/cobra](https://github.com/spf13/cobra) from 1.8.0 to 1.8.1.
- [Release notes](https://github.com/spf13/cobra/releases)
- [Commits](https://github.com/spf13/cobra/compare/v1.8.0...v1.8.1)

---
updated-dependencies:
- dependency-name: github.com/spf13/cobra
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-19 22:01:24 +08:00
dependabot[bot]
0ae73a0eca
build(deps): bump actions/download-artifact in /.github/workflows (#688)
Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 3 to 4.1.7.
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/v3...v4.1.7)

---
updated-dependencies:
- dependency-name: actions/download-artifact
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-19 22:00:58 +08:00
pings
63c1a18a7d
Optimize and upgrade docking parameters (#696) 2024-10-19 22:00:11 +08:00
dependabot[bot]
34726d1659
build(deps): bump github.com/eko/gocache/lib/v4 from 4.1.5 to 4.1.6 (#668)
Bumps [github.com/eko/gocache/lib/v4](https://github.com/eko/gocache) from 4.1.5 to 4.1.6.
- [Release notes](https://github.com/eko/gocache/releases)
- [Commits](https://github.com/eko/gocache/compare/lib/v4.1.5...lib/v4.1.6)

---
updated-dependencies:
- dependency-name: github.com/eko/gocache/lib/v4
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-19 21:59:06 +08:00
dependabot[bot]
5edc68d475
build(deps): bump github.com/redis/go-redis/v9 from 9.5.1 to 9.7.0 (#699)
Bumps [github.com/redis/go-redis/v9](https://github.com/redis/go-redis) from 9.5.1 to 9.7.0.
- [Release notes](https://github.com/redis/go-redis/releases)
- [Changelog](https://github.com/redis/go-redis/blob/master/CHANGELOG.md)
- [Commits](https://github.com/redis/go-redis/compare/v9.5.1...v9.7.0)

---
updated-dependencies:
- dependency-name: github.com/redis/go-redis/v9
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-19 21:57:38 +08:00
mengxin239
944e8cd6a8 version++ 2024-07-21 13:12:31 +08:00
wyx2685
c4581ad34b
Xray core1.8.20 & support splitHTTP (#661)
* upgrade xray core 1.8.20

* support splitHTTP
2024-07-21 10:59:38 +08:00
dependabot[bot]
127318ccbd
build(deps): bump github.com/go-resty/resty/v2 from 2.11.0 to 2.13.1 (#660)
Bumps [github.com/go-resty/resty/v2](https://github.com/go-resty/resty) from 2.11.0 to 2.13.1.
- [Release notes](https://github.com/go-resty/resty/releases)
- [Commits](https://github.com/go-resty/resty/compare/v2.11.0...v2.13.1)

---
updated-dependencies:
- dependency-name: github.com/go-resty/resty/v2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-20 20:49:16 +08:00
dependabot[bot]
db784f18e6
build(deps): bump google.golang.org/grpc from 1.64.0 to 1.64.1 (#659)
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.64.0 to 1.64.1.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.64.0...v1.64.1)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-20 19:59:59 +08:00
dependabot[bot]
8a5a5e4356
build(deps): bump github.com/Azure/azure-sdk-for-go/sdk/azidentity (#658)
Bumps [github.com/Azure/azure-sdk-for-go/sdk/azidentity](https://github.com/Azure/azure-sdk-for-go) from 1.5.1 to 1.6.0.
- [Release notes](https://github.com/Azure/azure-sdk-for-go/releases)
- [Changelog](https://github.com/Azure/azure-sdk-for-go/blob/main/documentation/release.md)
- [Commits](https://github.com/Azure/azure-sdk-for-go/compare/sdk/internal/v1.5.1...sdk/azcore/v1.6.0)

---
updated-dependencies:
- dependency-name: github.com/Azure/azure-sdk-for-go/sdk/azidentity
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-20 19:56:22 +08:00
dependabot[bot]
cfdb5166f3
build(deps): bump github.com/gogf/gf/v2 from 2.6.4 to 2.7.0 (#632)
Bumps [github.com/gogf/gf/v2](https://github.com/gogf/gf) from 2.6.4 to 2.7.0.
- [Release notes](https://github.com/gogf/gf/releases)
- [Commits](https://github.com/gogf/gf/compare/v2.6.4...v2.7.0)

---
updated-dependencies:
- dependency-name: github.com/gogf/gf/v2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-20 19:54:40 +08:00
dependabot[bot]
540be1b7c8
build(deps): bump github.com/hashicorp/go-retryablehttp (#657)
Bumps [github.com/hashicorp/go-retryablehttp](https://github.com/hashicorp/go-retryablehttp) from 0.7.5 to 0.7.7.
- [Changelog](https://github.com/hashicorp/go-retryablehttp/blob/main/CHANGELOG.md)
- [Commits](https://github.com/hashicorp/go-retryablehttp/compare/v0.7.5...v0.7.7)

---
updated-dependencies:
- dependency-name: github.com/hashicorp/go-retryablehttp
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-20 19:53:05 +08:00
dependabot[bot]
98014fa60f
build(deps): bump golang.org/x/net from 0.26.0 to 0.27.0 (#656)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.26.0 to 0.27.0.
- [Commits](https://github.com/golang/net/compare/v0.26.0...v0.27.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-20 19:41:24 +08:00
mengxin239
1de718a5fc Adjusting docker.yml triggers 2024-07-20 19:16:09 +08:00
MengXin239
81c068bad4 update config.yml.example 2024-06-21 12:49:12 +08:00
MengXin239
dbde0c24fc version++ 2024-06-09 22:19:33 +08:00
MengXin239
1bbd061d42 upgrade xray core 2024-06-09 22:12:24 +08:00
MengXin239
793f26e763 fixed some bug 2024-06-09 20:52:32 +08:00
MengXin239
175e46d0b7 add quic support and fixed some bug 2024-06-09 17:58:22 +08:00
_rave_cat_
9261a6063d
chore: fix typos. (#640)
* chore: fix typos.

* chore: makes go-staticcheck happy.
2024-06-09 15:21:27 +08:00
Blank Paper
5ee2679924
fix compatibility with Xray-core v1.8.10 (#629) 2024-04-16 22:46:28 +08:00
thh1451
06fe198243
add DeviceLimit to V2RaySocks (#622) 2024-04-10 17:57:19 +08:00
thh1451
b3f31bf06b
Modify the way v2raysocks obtains methods and audits (#616)
Co-authored-by: thank243 <thank243@gmail.com>
2024-03-19 00:01:19 +08:00
thank243
0010a876f3
Remove unnecessary user retrieval in v2raysocks (#617)
The updated code eliminates a redundant user retrieval operation in the v2raysocks module. This operation was not needed because the desired information (method) can be inferred elsewhere in the application. This change simplifies the code, improves efficiency, and may reduce potential errors related to user data retrieval.
2024-03-18 23:50:18 +08:00
Senis
dbed635aae
fixes, enhancing the efficiency and robustness of the system. 2024-03-15 21:44:15 +08:00
Senis
561f317e24
Update dependencies and upgrade Google Cloud services
Upgraded various dependencies and Google Cloud services to improve the application's performance and stability. Multiple version upgrades reflect ongoing development efforts and bug
2024-02-20 23:50:54 +08:00
dependabot[bot]
c24a2a28f2
build(deps): bump github.com/shirou/gopsutil/v3 from 3.23.12 to 3.24.1 (#589)
Bumps [github.com/shirou/gopsutil/v3](https://github.com/shirou/gopsutil) from 3.23.12 to 3.24.1.
- [Release notes](https://github.com/shirou/gopsutil/releases)
- [Commits](https://github.com/shirou/gopsutil/compare/v3.23.12...v3.24.1)

---
updated-dependencies:
- dependency-name: github.com/shirou/gopsutil/v3
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-03 20:34:51 +08:00
dependabot[bot]
fa80ed8014
build(deps): bump github.com/go-acme/lego/v4 from 4.14.2 to 4.15.0 (#588)
Bumps [github.com/go-acme/lego/v4](https://github.com/go-acme/lego) from 4.14.2 to 4.15.0.
- [Release notes](https://github.com/go-acme/lego/releases)
- [Changelog](https://github.com/go-acme/lego/blob/master/CHANGELOG.md)
- [Commits](https://github.com/go-acme/lego/compare/v4.14.2...v4.15.0)

---
updated-dependencies:
- dependency-name: github.com/go-acme/lego/v4
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-30 12:28:50 +08:00
dependabot[bot]
5409cb2dc3
build(deps): bump github.com/gogf/gf/v2 from 2.6.1 to 2.6.2 (#585)
Bumps [github.com/gogf/gf/v2](https://github.com/gogf/gf) from 2.6.1 to 2.6.2.
- [Release notes](https://github.com/gogf/gf/releases)
- [Commits](https://github.com/gogf/gf/compare/v2.6.1...v2.6.2)

---
updated-dependencies:
- dependency-name: github.com/gogf/gf/v2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-23 06:28:05 +08:00
壳壳中的宇宙
b8b3a16d3b
fix custom inbound listener to not use 0.0.0.0 (#584) 2024-01-20 09:23:12 +08:00
Jat
d1e5762937
support passing redis network and redis username to redis client (#576)
Signed-off-by: Jat <jat@sinosky.org>
2024-01-12 22:22:28 +08:00
dependabot[bot]
4f1dafa8ed
build(deps): bump golang.org/x/net from 0.19.0 to 0.20.0 (#578)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.19.0 to 0.20.0.
- [Commits](https://github.com/golang/net/compare/v0.19.0...v0.20.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-12 22:01:32 +08:00
dependabot[bot]
aae0f9b24d
build(deps): bump github.com/redis/go-redis/v9 from 9.3.1 to 9.4.0 (#574)
Bumps [github.com/redis/go-redis/v9](https://github.com/redis/go-redis) from 9.3.1 to 9.4.0.
- [Release notes](https://github.com/redis/go-redis/releases)
- [Changelog](https://github.com/redis/go-redis/blob/master/CHANGELOG.md)
- [Commits](https://github.com/redis/go-redis/compare/v9.3.1...v9.4.0)

---
updated-dependencies:
- dependency-name: github.com/redis/go-redis/v9
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-09 18:21:53 +08:00
dependabot[bot]
aee8ca2980
build(deps): bump github.com/xtls/xray-core from 1.8.6 to 1.8.7 (#573)
Bumps [github.com/xtls/xray-core](https://github.com/xtls/xray-core) from 1.8.6 to 1.8.7.
- [Release notes](https://github.com/xtls/xray-core/releases)
- [Commits](https://github.com/xtls/xray-core/compare/v1.8.6...v1.8.7)

---
updated-dependencies:
- dependency-name: github.com/xtls/xray-core
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-09 06:37:38 +08:00
dependabot[bot]
933e745a70
build(deps): bump github.com/sagernet/sing from 0.2.20 to 0.2.21 (#569)
Bumps [github.com/sagernet/sing](https://github.com/sagernet/sing) from 0.2.20 to 0.2.21.
- [Commits](https://github.com/sagernet/sing/compare/v0.2.20...v0.2.21)

---
updated-dependencies:
- dependency-name: github.com/sagernet/sing
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-07 10:26:37 +08:00
wyx2685
515fc708dc
Remove dragonfly compile. (#567)
Fix Actions
2024-01-03 10:21:46 +08:00
dependabot[bot]
5e134967fd
build(deps): bump github.com/shirou/gopsutil/v3 from 3.23.11 to 3.23.12 (#566)
Bumps [github.com/shirou/gopsutil/v3](https://github.com/shirou/gopsutil) from 3.23.11 to 3.23.12.
- [Release notes](https://github.com/shirou/gopsutil/releases)
- [Commits](https://github.com/shirou/gopsutil/compare/v3.23.11...v3.23.12)

---
updated-dependencies:
- dependency-name: github.com/shirou/gopsutil/v3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-03 10:20:56 +08:00
Senis
4a234d50e2
Add debug level logging option
This update introduces the ability to enable logging from the caller when the log level is set to "debug". This additional logging feature will provide more specificity and context for debugging tasks, aiding in quicker issue resolution.
2023-12-29 12:25:33 +08:00
Senis
115d7bad6f
Replace standard log package with logrus
The standard "log" package was replaced by the structured logger "github.com/sirupsen/logrus" for better log control in various files. This change will allow to tailor the logging information more precisely and make logs easier to read and analyze. All calls of standard log methods were replaced by their logrus counterparts.
2023-12-28 13:40:31 +08:00
dependabot[bot]
5ba0624bbc
build(deps): bump github.com/go-resty/resty/v2 from 2.10.0 to 2.11.0 (#564)
Bumps [github.com/go-resty/resty/v2](https://github.com/go-resty/resty) from 2.10.0 to 2.11.0.
- [Release notes](https://github.com/go-resty/resty/releases)
- [Commits](https://github.com/go-resty/resty/compare/v2.10.0...v2.11.0)

---
updated-dependencies:
- dependency-name: github.com/go-resty/resty/v2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-28 00:41:09 +08:00
dependabot[bot]
4439afa29b
build(deps): bump github.com/sagernet/sing from 0.2.19 to 0.2.20 (#558)
Bumps [github.com/sagernet/sing](https://github.com/sagernet/sing) from 0.2.19 to 0.2.20.
- [Commits](https://github.com/sagernet/sing/compare/v0.2.19...v0.2.20)

---
updated-dependencies:
- dependency-name: github.com/sagernet/sing
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-24 02:50:55 +08:00
dependabot[bot]
03c9fe4218
build(deps): bump github.com/gogf/gf/v2 from 2.6.0 to 2.6.1 (#560)
Bumps [github.com/gogf/gf/v2](https://github.com/gogf/gf) from 2.6.0 to 2.6.1.
- [Release notes](https://github.com/gogf/gf/releases)
- [Commits](https://github.com/gogf/gf/compare/v2.6.0...v2.6.1)

---
updated-dependencies:
- dependency-name: github.com/gogf/gf/v2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-24 02:49:39 +08:00
dependabot[bot]
f648aedc91
build(deps): bump google.golang.org/protobuf from 1.31.0 to 1.32.0 (#561)
Bumps google.golang.org/protobuf from 1.31.0 to 1.32.0.

---
updated-dependencies:
- dependency-name: google.golang.org/protobuf
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-24 02:49:28 +08:00
dependabot[bot]
1720fbdc4c
build(deps): bump github.com/redis/go-redis/v9 from 9.3.0 to 9.3.1 (#555)
Bumps [github.com/redis/go-redis/v9](https://github.com/redis/go-redis) from 9.3.0 to 9.3.1.
- [Release notes](https://github.com/redis/go-redis/releases)
- [Changelog](https://github.com/redis/go-redis/blob/master/CHANGELOG.md)
- [Commits](https://github.com/redis/go-redis/compare/v9.3.0...v9.3.1)

---
updated-dependencies:
- dependency-name: github.com/redis/go-redis/v9
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-24 02:49:13 +08:00
dependabot[bot]
cd7907c4c9
build(deps): bump github.com/spf13/viper from 1.18.1 to 1.18.2 (#556)
Bumps [github.com/spf13/viper](https://github.com/spf13/viper) from 1.18.1 to 1.18.2.
- [Release notes](https://github.com/spf13/viper/releases)
- [Commits](https://github.com/spf13/viper/compare/v1.18.1...v1.18.2)

---
updated-dependencies:
- dependency-name: github.com/spf13/viper
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-24 02:49:05 +08:00
dependabot[bot]
296ba86bdd
build(deps): bump golang.org/x/crypto from 0.16.0 to 0.17.0 (#554)
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.16.0 to 0.17.0.
- [Commits](https://github.com/golang/crypto/compare/v0.16.0...v0.17.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-19 08:18:48 +08:00
dependabot[bot]
43e6ec85cd
build(deps): bump github.com/gogf/gf/v2 from 2.5.7 to 2.6.0 (#553)
Bumps [github.com/gogf/gf/v2](https://github.com/gogf/gf) from 2.5.7 to 2.6.0.
- [Release notes](https://github.com/gogf/gf/releases)
- [Commits](https://github.com/gogf/gf/compare/v2.5.7...v2.6.0)

---
updated-dependencies:
- dependency-name: github.com/gogf/gf/v2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-19 00:03:33 +08:00
dependabot[bot]
7ba2d999f0
build(deps): bump github.com/sagernet/sing from 0.2.18 to 0.2.19 (#550)
Bumps [github.com/sagernet/sing](https://github.com/sagernet/sing) from 0.2.18 to 0.2.19.
- [Commits](https://github.com/sagernet/sing/compare/v0.2.18...v0.2.19)

---
updated-dependencies:
- dependency-name: github.com/sagernet/sing
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-12 21:22:06 +08:00
dependabot[bot]
53141f4416
build(deps): bump github.com/spf13/viper from 1.17.0 to 1.18.1 (#548)
Bumps [github.com/spf13/viper](https://github.com/spf13/viper) from 1.17.0 to 1.18.1.
- [Release notes](https://github.com/spf13/viper/releases)
- [Commits](https://github.com/spf13/viper/compare/v1.17.0...v1.18.1)

---
updated-dependencies:
- dependency-name: github.com/spf13/viper
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-09 22:46:41 +08:00
dependabot[bot]
e378f0a367
build(deps): bump github.com/sagernet/sing-shadowsocks (#549)
Bumps [github.com/sagernet/sing-shadowsocks](https://github.com/sagernet/sing-shadowsocks) from 0.2.5 to 0.2.6.
- [Commits](https://github.com/sagernet/sing-shadowsocks/compare/v0.2.5...v0.2.6)

---
updated-dependencies:
- dependency-name: github.com/sagernet/sing-shadowsocks
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-09 22:42:35 +08:00
dependabot[bot]
d01a4265cd
build(deps): bump github.com/sagernet/sing from 0.2.17 to 0.2.18 (#542)
Bumps [github.com/sagernet/sing](https://github.com/sagernet/sing) from 0.2.17 to 0.2.18.
- [Commits](https://github.com/sagernet/sing/compare/v0.2.17...v0.2.18)

---
updated-dependencies:
- dependency-name: github.com/sagernet/sing
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-05 06:59:19 +08:00
dependabot[bot]
94d2c7c23a
build(deps): bump github.com/shirou/gopsutil/v3 from 3.23.10 to 3.23.11 (#538)
Bumps [github.com/shirou/gopsutil/v3](https://github.com/shirou/gopsutil) from 3.23.10 to 3.23.11.
- [Release notes](https://github.com/shirou/gopsutil/releases)
- [Commits](https://github.com/shirou/gopsutil/compare/v3.23.10...v3.23.11)

---
updated-dependencies:
- dependency-name: github.com/shirou/gopsutil/v3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-03 19:42:23 +08:00
isluckys
3de7600a4c
修复类型判断问题 (#539)
之前一个pr写的if直接写成了vmess导致其他的比如说ss、Trojan的都会被覆盖
2023-12-03 19:42:03 +08:00
dependabot[bot]
a0378b6cff
build(deps): bump golang.org/x/net from 0.18.0 to 0.19.0 (#536)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.18.0 to 0.19.0.
- [Commits](https://github.com/golang/net/compare/v0.18.0...v0.19.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-29 18:13:52 +08:00
dependabot[bot]
4688833bc7
build(deps): bump golang.org/x/time from 0.4.0 to 0.5.0 (#537)
Bumps [golang.org/x/time](https://github.com/golang/time) from 0.4.0 to 0.5.0.
- [Commits](https://github.com/golang/time/compare/v0.4.0...v0.5.0)

---
updated-dependencies:
- dependency-name: golang.org/x/time
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-29 17:57:19 +08:00
dependabot[bot]
294a2dfacb
build(deps): bump golang.org/x/crypto from 0.15.0 to 0.16.0 (#535)
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.15.0 to 0.16.0.
- [Commits](https://github.com/golang/crypto/compare/v0.15.0...v0.16.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-29 17:55:38 +08:00
pennyMorant
5780731cd3
add bunpanel (#533) 2023-11-28 20:08:59 +08:00
betaxab
911b0c2ff5
api: newV2board: add Vless support (#534) 2023-11-28 20:08:44 +08:00
dependabot[bot]
fa7fb7087f
build(deps): bump github.com/gogf/gf/v2 from 2.5.6 to 2.5.7 (#526)
Bumps [github.com/gogf/gf/v2](https://github.com/gogf/gf) from 2.5.6 to 2.5.7.
- [Release notes](https://github.com/gogf/gf/releases)
- [Commits](https://github.com/gogf/gf/compare/v2.5.6...v2.5.7)

---
updated-dependencies:
- dependency-name: github.com/gogf/gf/v2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-25 08:36:36 +08:00
dependabot[bot]
0a6bca9755
build(deps): bump github.com/go-jose/go-jose/v3 from 3.0.0 to 3.0.1 (#524)
Bumps [github.com/go-jose/go-jose/v3](https://github.com/go-jose/go-jose) from 3.0.0 to 3.0.1.
- [Release notes](https://github.com/go-jose/go-jose/releases)
- [Changelog](https://github.com/go-jose/go-jose/blob/v3/CHANGELOG.md)
- [Commits](https://github.com/go-jose/go-jose/compare/v3.0.0...v3.0.1)

---
updated-dependencies:
- dependency-name: github.com/go-jose/go-jose/v3
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-25 08:36:27 +08:00
dependabot[bot]
8562c798a9
build(deps): bump github.com/xtls/xray-core from 1.8.5 to 1.8.6 (#523)
Bumps [github.com/xtls/xray-core](https://github.com/xtls/xray-core) from 1.8.5 to 1.8.6.
- [Release notes](https://github.com/xtls/xray-core/releases)
- [Commits](https://github.com/xtls/xray-core/compare/v1.8.5...v1.8.6)

---
updated-dependencies:
- dependency-name: github.com/xtls/xray-core
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-25 08:36:18 +08:00
thh1451
56199afa90
V2RaySocks supports Reality (remote config) (#521) 2023-11-18 06:21:08 +08:00
Senis
c688cf02b4
Update Go version and dependencies for better compatibility
Updated Go version in Dockerfile and go.mod to ensure better compatibility and unpinned the Go version in Dockerfile for increased flexibility. Multiple dependencies in go.mod and go.sum have been updated to their newer versions for improved functionality and security. This will keep the project up-to-date with the latest features and bug fixes offered by these dependencies. Removed unused dependencies to keep the project clean and efficient.
2023-11-14 11:32:21 +08:00
thh1451
c170272f40
Add Etag for V2RaySocks (#518) 2023-11-12 06:21:13 +08:00
dependabot[bot]
6ffbe599b4
build(deps): bump golang.org/x/net from 0.17.0 to 0.18.0 (#514)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.17.0 to 0.18.0.
- [Commits](https://github.com/golang/net/compare/v0.17.0...v0.18.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-10 21:24:01 +08:00
thh1451
78c2e31bdf
add 2 acts to V2RaySocks (#516) 2023-11-10 21:23:44 +08:00
dependabot[bot]
c04d52330d
合并拉取请求 #513
* build(deps): bump golang.org/x/crypto from 0.14.0 to 0.15.0
2023-11-10 11:52:49 +08:00
dependabot[bot]
6f4bf62113
build(deps): bump golang.org/x/time from 0.3.0 to 0.4.0 (#506)
Bumps [golang.org/x/time](https://github.com/golang/time) from 0.3.0 to 0.4.0.
- [Commits](https://github.com/golang/time/compare/v0.3.0...v0.4.0)

---
updated-dependencies:
- dependency-name: golang.org/x/time
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-08 19:28:10 +08:00
dependabot[bot]
56e993ce43
build(deps): bump github.com/spf13/cobra from 1.7.0 to 1.8.0 (#505)
Bumps [github.com/spf13/cobra](https://github.com/spf13/cobra) from 1.7.0 to 1.8.0.
- [Release notes](https://github.com/spf13/cobra/releases)
- [Commits](https://github.com/spf13/cobra/compare/v1.7.0...v1.8.0)

---
updated-dependencies:
- dependency-name: github.com/spf13/cobra
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-08 19:28:00 +08:00
dependabot[bot]
6d3d6f9e53
build(deps): bump github.com/sagernet/sing from 0.2.15 to 0.2.17 (#504)
Bumps [github.com/sagernet/sing](https://github.com/sagernet/sing) from 0.2.15 to 0.2.17.
- [Commits](https://github.com/sagernet/sing/compare/v0.2.15...v0.2.17)

---
updated-dependencies:
- dependency-name: github.com/sagernet/sing
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-08 19:27:49 +08:00
Senis
76076b2d6a Refactor variable assignments in sspanel.go
Simplified the variable assignment logic in sspanel.go to increase code efficiency and readability. "tlsType" is now conditionally initialized once instead of reset multiple times, and it is also properly scoped. Removed an unnecessary check for "nodeConfig.Security" in the "Trojan" case as this value is already taken into account in the efficient, updated logic.
2023-11-08 19:26:38 +08:00
dependabot[bot]
4e48fdbe61
build(deps): bump github.com/shirou/gopsutil/v3 from 3.23.9 to 3.23.10 (#502)
Bumps [github.com/shirou/gopsutil/v3](https://github.com/shirou/gopsutil) from 3.23.9 to 3.23.10.
- [Release notes](https://github.com/shirou/gopsutil/releases)
- [Commits](https://github.com/shirou/gopsutil/compare/v3.23.9...v3.23.10)

---
updated-dependencies:
- dependency-name: github.com/shirou/gopsutil/v3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-02 01:11:00 +08:00
dependabot[bot]
0f3a4a0008
build(deps): bump github.com/redis/go-redis/v9 from 9.2.1 to 9.3.0 (#501)
Bumps [github.com/redis/go-redis/v9](https://github.com/redis/go-redis) from 9.2.1 to 9.3.0.
- [Release notes](https://github.com/redis/go-redis/releases)
- [Changelog](https://github.com/redis/go-redis/blob/master/CHANGELOG.md)
- [Commits](https://github.com/redis/go-redis/compare/v9.2.1...v9.3.0)

---
updated-dependencies:
- dependency-name: github.com/redis/go-redis/v9
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-01 07:01:12 +08:00
Senis John
d9971b2181
Initialize server port in sspanel
This commit initializes the server port in sspanel.go if the userListResponse is not empty. This adds a level of preventative measure to ensure port is not left uninitialized.
2023-10-28 13:19:17 +08:00
dependabot[bot]
4d1ed21dc7
build(deps): bump github.com/sagernet/sing from 0.2.14 to 0.2.15 (#497)
Bumps [github.com/sagernet/sing](https://github.com/sagernet/sing) from 0.2.14 to 0.2.15.
- [Commits](https://github.com/sagernet/sing/compare/v0.2.14...v0.2.15)

---
updated-dependencies:
- dependency-name: github.com/sagernet/sing
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-27 07:05:28 +08:00
dependabot[bot]
9a03f85930
build(deps): bump github.com/gogf/gf/v2 from 2.5.5 to 2.5.6 (#495)
Bumps [github.com/gogf/gf/v2](https://github.com/gogf/gf) from 2.5.5 to 2.5.6.
- [Release notes](https://github.com/gogf/gf/releases)
- [Commits](https://github.com/gogf/gf/compare/v2.5.5...v2.5.6)

---
updated-dependencies:
- dependency-name: github.com/gogf/gf/v2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-24 23:51:15 +08:00
dependabot[bot]
11b46ea485
build(deps): bump github.com/fsnotify/fsnotify from 1.6.0 to 1.7.0 (#494)
Bumps [github.com/fsnotify/fsnotify](https://github.com/fsnotify/fsnotify) from 1.6.0 to 1.7.0.
- [Release notes](https://github.com/fsnotify/fsnotify/releases)
- [Changelog](https://github.com/fsnotify/fsnotify/blob/main/CHANGELOG.md)
- [Commits](https://github.com/fsnotify/fsnotify/compare/v1.6.0...v1.7.0)

---
updated-dependencies:
- dependency-name: github.com/fsnotify/fsnotify
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-24 23:51:06 +08:00
dependabot[bot]
dc3d256d85
build(deps): bump github.com/gogf/gf/v2 from 2.5.4 to 2.5.5 (#491)
Bumps [github.com/gogf/gf/v2](https://github.com/gogf/gf) from 2.5.4 to 2.5.5.
- [Release notes](https://github.com/gogf/gf/releases)
- [Commits](https://github.com/gogf/gf/compare/v2.5.4...v2.5.5)

---
updated-dependencies:
- dependency-name: github.com/gogf/gf/v2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-21 00:36:35 +08:00
Senis John
287c30e7d0
Update application dependencies and improve error logging
This commit updates the version of many dependencies in go.sum and go.mod. It improves error handling in sspanel.go by including both the HTTP response body and error in the logged message. It also updates the xray-core version.
2023-10-18 20:58:39 +08:00
Senis John
97d89549dd
Update application version and enhance error handling
The commit increases the version number from 0.9.1 to 0.9.2 in version.go. Additionally, an error check has been added in x25519.go to validate the private key size. Also, panel.go has been modified to accept both "NewV2board" and "V2board" as valid panel types.
2023-10-17 15:36:32 +08:00
dependabot[bot]
cac4288e07
build(deps): bump github.com/sagernet/sing from 0.2.13 to 0.2.14 (#485)
Bumps [github.com/sagernet/sing](https://github.com/sagernet/sing) from 0.2.13 to 0.2.14.
- [Commits](https://github.com/sagernet/sing/compare/v0.2.13...v0.2.14)

---
updated-dependencies:
- dependency-name: github.com/sagernet/sing
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-17 06:43:26 +08:00
dependabot[bot]
d1d5193cec
build(deps): bump github.com/spf13/cobra from 1.1.1 to 1.7.0 (#486)
Bumps [github.com/spf13/cobra](https://github.com/spf13/cobra) from 1.1.1 to 1.7.0.
- [Release notes](https://github.com/spf13/cobra/releases)
- [Commits](https://github.com/spf13/cobra/compare/v1.1.1...v1.7.0)

---
updated-dependencies:
- dependency-name: github.com/spf13/cobra
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-17 06:42:44 +08:00
dependabot[bot]
85607527a5
build(deps): bump github.com/go-resty/resty/v2 from 2.9.1 to 2.10.0 (#484)
Bumps [github.com/go-resty/resty/v2](https://github.com/go-resty/resty) from 2.9.1 to 2.10.0.
- [Release notes](https://github.com/go-resty/resty/releases)
- [Commits](https://github.com/go-resty/resty/compare/v2.9.1...v2.10.0)

---
updated-dependencies:
- dependency-name: github.com/go-resty/resty/v2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-17 06:41:58 +08:00
Senis John
fd0a23bf6c
"Add option to input private key for x25519 command"
Added a command line flag to allow the user to provide an input for the private key while utilizing the x25519 command. The function `x25519` was also modified to account for the possibility of a user-inputted private key. If no private key is provided, random bytes will be generated for the private key as before. This feature provides flexibility for the user in key management.
2023-10-14 21:46:00 +08:00
Senis John
b1bfd04895
Refactor main to use Cobra command line framework and package restructure
Reorganized the Go package structure, moving the main package to 'cmd'. Upgraded the flag library to Cobra for better management of CLI commands. This included moving the X25519 key generation from a flag to its own standalone Cobra command, which improves user interaction and code modularity. This structural change will benefit future additions and code maintainability.
2023-10-14 11:21:45 +08:00
Senis John
edf02307ad
Update Go dependencies and add secure key pair generation
Updated several Go dependencies for enhanced security and performance. Additionally, a command (`-x25519`) has been added for generating a secure key pair using X25519. This provides an easier and safer way for users to generate keys for secure communication. Further instructions have been reflected in the `config.yml.example` file.
2023-10-13 21:55:30 +08:00
dependabot[bot]
551e2d4299
build(deps): bump golang.org/x/net from 0.16.0 to 0.17.0
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.16.0 to 0.17.0.
- [Commits](https://github.com/golang/net/compare/v0.16.0...v0.17.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-11 15:27:30 +00:00
Senis John
0254c6c557
Update docker.yml 2023-10-09 10:06:46 +08:00
pings
4c52e33adb
对接GoV2Panel面板 (#474)
* Update actions

* up

---------

Co-authored-by: thank243 <thank243@gmail.com>
2023-10-08 12:56:26 +08:00
thank243
b8d40c201b
Update actions 2023-10-08 12:06:18 +08:00
Senis John
dbd4a85a6c
Update Mergo package and Go version
Replaced the Mergo package from "github.com/imdario/mergo" to "dario.cat/mergo". This change was necessary due to the new release from the Mergo package which includes bug fixes and performance improvements.
Moreover, updated the Go version from 1.20 to 1.21.1, including the toolchain version to stay up to date with the latest language features and bug fixes.
Lastly, other dependencies were updated and cleaned up for maintaining package stability and compatibility.
2023-10-08 09:21:39 +08:00
dependabot[bot]
8f28716b21
build(deps): bump github.com/spf13/viper from 1.16.0 to 1.17.0 (#469)
Bumps [github.com/spf13/viper](https://github.com/spf13/viper) from 1.16.0 to 1.17.0.
- [Release notes](https://github.com/spf13/viper/releases)
- [Commits](https://github.com/spf13/viper/compare/v1.16.0...v1.17.0)

---
updated-dependencies:
- dependency-name: github.com/spf13/viper
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-07 13:10:53 +08:00
Senis John
73bc37cb51
Add EnableREALITY field and update REALITYConfig parsing
Enabled the REALITY feature on both model.go and sspanel.go for the api and service assemblies and updated the inboundbuilder to switch the REALITY feature based on the new field and condition statements. This enhancement allows finer control and visibility of the REALITY feature's activation.

In addition, the REALITYConfig in config.go was updated to remove the DisableLocal field and add the DisableLocalREALITYConfig field. The main/config.yml.example file has also been updated to reflect these changes and provide users with a clearer understanding of the config setup.
2023-10-04 23:08:59 +08:00
M1Screw
78f2f88296
feat: update sspanel model (#467) 2023-10-04 20:28:03 +08:00
Senis John
42a2226769
Enhanced ssPanel API by adding panel version check and improving custom config parsing
Added a function to compare the ssPanel version with the baseline version and inform users if their panel version is outdated. Made changes to improve readability and clarity in variable naming and error handling. The handling of the custom config feature has also been significantly optimized, providing more efficient use and easier debugging of parsing issues. The overall changes lead to better compatibility with different ssPanel versions and a more user-friendly custom config feature.
2023-10-04 16:50:52 +08:00
M1Screw
71aba0601e
feat: unify trojan transport & add ss2022 related config (#465) 2023-10-04 10:44:45 +08:00
Senis John
5fe18e020d
Refactor sspanel and test files in the API
Fixed typos, changed variable naming to follow camel case convention, simplified the error handling, and refactored the function names in sspanel.go for improved readability and consistency. Accordingly, updated the test function names in sspanel_test.go to match the changes made in the main file. Additionally, the if condition in ParseSSPanelNodeInfo was streamlined to improve the function's readability and error handling. The changes will help in better understanding the code while debugging or adding new features.
2023-10-04 09:45:52 +08:00
dependabot[bot]
a0f2730bb2
build(deps): bump github.com/shirou/gopsutil/v3 from 3.23.8 to 3.23.9 (#462)
Bumps [github.com/shirou/gopsutil/v3](https://github.com/shirou/gopsutil) from 3.23.8 to 3.23.9.
- [Release notes](https://github.com/shirou/gopsutil/releases)
- [Commits](https://github.com/shirou/gopsutil/compare/v3.23.8...v3.23.9)

---
updated-dependencies:
- dependency-name: github.com/shirou/gopsutil/v3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-03 08:28:04 +08:00
dependabot[bot]
0c10c59877
build(deps): bump github.com/sagernet/sing from 0.2.11 to 0.2.12 (#461)
Bumps [github.com/sagernet/sing](https://github.com/sagernet/sing) from 0.2.11 to 0.2.12.
- [Commits](https://github.com/sagernet/sing/compare/v0.2.11...v0.2.12)

---
updated-dependencies:
- dependency-name: github.com/sagernet/sing
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-03 08:27:55 +08:00
dependabot[bot]
119e4810f2
build(deps): bump github.com/go-resty/resty/v2 from 2.8.0 to 2.9.1 (#463)
Bumps [github.com/go-resty/resty/v2](https://github.com/go-resty/resty) from 2.8.0 to 2.9.1.
- [Release notes](https://github.com/go-resty/resty/releases)
- [Commits](https://github.com/go-resty/resty/compare/v2.8.0...v2.9.1)

---
updated-dependencies:
- dependency-name: github.com/go-resty/resty/v2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-03 08:27:45 +08:00
dependabot[bot]
5dad910488
build(deps): bump github.com/redis/go-redis/v9 from 9.2.0 to 9.2.1 (#460)
Bumps [github.com/redis/go-redis/v9](https://github.com/redis/go-redis) from 9.2.0 to 9.2.1.
- [Release notes](https://github.com/redis/go-redis/releases)
- [Changelog](https://github.com/redis/go-redis/blob/master/CHANGELOG.md)
- [Commits](https://github.com/redis/go-redis/compare/v9.2.0...v9.2.1)

---
updated-dependencies:
- dependency-name: github.com/redis/go-redis/v9
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-02 23:29:38 +08:00
dependabot[bot]
8841e55f70
build(deps): bump github.com/sagernet/sing-shadowsocks (#458)
Bumps [github.com/sagernet/sing-shadowsocks](https://github.com/sagernet/sing-shadowsocks) from 0.2.4 to 0.2.5.
- [Commits](https://github.com/sagernet/sing-shadowsocks/compare/v0.2.4...v0.2.5)

---
updated-dependencies:
- dependency-name: github.com/sagernet/sing-shadowsocks
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-27 17:36:02 +08:00
dependabot[bot]
5d20732881
build(deps): bump github.com/sagernet/sing from 0.2.9 to 0.2.11 (#455)
Bumps [github.com/sagernet/sing](https://github.com/sagernet/sing) from 0.2.9 to 0.2.11.
- [Commits](https://github.com/sagernet/sing/compare/v0.2.9...v0.2.11)

---
updated-dependencies:
- dependency-name: github.com/sagernet/sing
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-21 23:30:29 +08:00
dependabot[bot]
d579933451
build(deps): bump github.com/go-acme/lego/v4 from 4.14.0 to 4.14.2 (#456)
Bumps [github.com/go-acme/lego/v4](https://github.com/go-acme/lego) from 4.14.0 to 4.14.2.
- [Release notes](https://github.com/go-acme/lego/releases)
- [Changelog](https://github.com/go-acme/lego/blob/master/CHANGELOG.md)
- [Commits](https://github.com/go-acme/lego/compare/v4.14.0...v4.14.2)

---
updated-dependencies:
- dependency-name: github.com/go-acme/lego/v4
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-21 08:20:31 +08:00
dependabot[bot]
46e836f93b
build(deps): bump github.com/redis/go-redis/v9 from 9.1.0 to 9.2.0 (#457)
Bumps [github.com/redis/go-redis/v9](https://github.com/redis/go-redis) from 9.1.0 to 9.2.0.
- [Release notes](https://github.com/redis/go-redis/releases)
- [Changelog](https://github.com/redis/go-redis/blob/master/CHANGELOG.md)
- [Commits](https://github.com/redis/go-redis/compare/v9.1.0...v9.2.0)

---
updated-dependencies:
- dependency-name: github.com/redis/go-redis/v9
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-21 08:20:21 +08:00
dependabot[bot]
e27b0c6cd8
build(deps): bump github.com/go-resty/resty/v2 from 2.7.0 to 2.8.0 (#453)
Bumps [github.com/go-resty/resty/v2](https://github.com/go-resty/resty) from 2.7.0 to 2.8.0.
- [Release notes](https://github.com/go-resty/resty/releases)
- [Commits](https://github.com/go-resty/resty/compare/v2.7.0...v2.8.0)

---
updated-dependencies:
- dependency-name: github.com/go-resty/resty/v2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-19 01:53:53 +08:00
Senis John
e34a3b4a94
Update dependencies and replace go-redis with redis library
Replaced go-redis older version with a more updated version of redis library in limiter.go and go.mod files. This change will help to improve the performance and efficiency of the existing code. Updated the versions of 'gocache/store/redis/v4' and 'bsm/gomega' in go.sum and go.mod files to keep the project's dependencies up-to-date and fix potential security vulnerabilities. Removed the unnecessary indirect dependency 'go-redis/redis/v8' from go.sum file. Added 'redis/go-redis/v9' instead, to ensure compatibility with the newer version of Redis.
2023-09-12 17:28:27 +08:00
Senis John
b366171401
Update golang.org/x/exp and golang.org/x/tools versions
Updated versions for golang.org/x/exp and golang.org/x/tools in go.sum and go.mod files. It is crucial to keep these dependencies up-to-date for maintaining the functionality of the project as well as addressing potential security vulnerabilities.
2023-09-12 07:06:49 +08:00
dependabot[bot]
b034a2d48f
build(deps): bump github.com/eko/gocache/store/go_cache/v4 (#449)
Bumps [github.com/eko/gocache/store/go_cache/v4](https://github.com/eko/gocache) from 4.2.0 to 4.2.1.
- [Release notes](https://github.com/eko/gocache/releases)
- [Commits](https://github.com/eko/gocache/compare/store/redis/v4.2.0...store/redis/v4.2.1)

---
updated-dependencies:
- dependency-name: github.com/eko/gocache/store/go_cache/v4
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-12 06:22:38 +08:00
dependabot[bot]
65b25ed3f6
build(deps): bump github.com/eko/gocache/lib/v4 from 4.1.4 to 4.1.5 (#448)
Bumps [github.com/eko/gocache/lib/v4](https://github.com/eko/gocache) from 4.1.4 to 4.1.5.
- [Release notes](https://github.com/eko/gocache/releases)
- [Commits](https://github.com/eko/gocache/compare/lib/v4.1.4...lib/v4.1.5)

---
updated-dependencies:
- dependency-name: github.com/eko/gocache/lib/v4
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-12 05:54:06 +08:00
dependabot[bot]
b65dfd7f92
build(deps): bump golang.org/x/net from 0.14.0 to 0.15.0 (#446)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.14.0 to 0.15.0.
- [Commits](https://github.com/golang/net/compare/v0.14.0...v0.15.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-07 05:00:29 +08:00
Senis John
6569a0bf36
Updated several Go dependencies in go.sum
Upgraded the version of multiple dependencies listed in go.sum to incorporate bug fixes, improvements and deal with any potential security vulnerabilities. Key changes include an update to packages such as github.com/BurntSushi/toml and github.com/aws/aws-sdk-go-v2 among others.
2023-09-04 09:59:14 +08:00
dependabot[bot]
e5e5e4ef92
build(deps): bump github.com/shirou/gopsutil/v3 from 3.23.7 to 3.23.8 (#442)
Bumps [github.com/shirou/gopsutil/v3](https://github.com/shirou/gopsutil) from 3.23.7 to 3.23.8.
- [Release notes](https://github.com/shirou/gopsutil/releases)
- [Commits](https://github.com/shirou/gopsutil/compare/v3.23.7...v3.23.8)

---
updated-dependencies:
- dependency-name: github.com/shirou/gopsutil/v3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-04 09:39:47 +08:00
Senis John
f35a056cc6
Update several dependencies for bug fixes and improvements
This commit includes updates to several dependencies in go.sum file in order to incorporate bug fixes and performance improvements. The updated dependencies include 'cloud.google.com/go/compute', 'github.com/gaukas/godicttls', 'github.com/google/pprof' and 'github.com/xtls/xray-core' among others.

These updates are crucial to ensure the project runs efficiently and securely, with all known issues in these dependencies addressed in their latest versions.
2023-09-04 08:53:08 +08:00
dependabot[bot]
73ffd3f505
build(deps): bump github.com/eko/gocache/lib/v4 from 4.1.3 to 4.1.4 (#433)
Bumps [github.com/eko/gocache/lib/v4](https://github.com/eko/gocache) from 4.1.3 to 4.1.4.
- [Release notes](https://github.com/eko/gocache/releases)
- [Commits](https://github.com/eko/gocache/compare/lib/v4.1.3...lib/v4.1.4)

---
updated-dependencies:
- dependency-name: github.com/eko/gocache/lib/v4
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-08 23:37:35 +08:00
dependabot[bot]
73c5e28f41
build(deps): bump github.com/eko/gocache/store/go_cache/v4 (#432)
Bumps [github.com/eko/gocache/store/go_cache/v4](https://github.com/eko/gocache) from 4.1.2 to 4.2.0.
- [Release notes](https://github.com/eko/gocache/releases)
- [Commits](https://github.com/eko/gocache/compare/lib/v4.1.2...store/redis/v4.2.0)

---
updated-dependencies:
- dependency-name: github.com/eko/gocache/store/go_cache/v4
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-08 01:17:18 +08:00
dependabot[bot]
f1b45c02f4
build(deps): bump golang.org/x/net from 0.13.0 to 0.14.0 (#426)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.13.0 to 0.14.0.
- [Commits](https://github.com/golang/net/compare/v0.13.0...v0.14.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-05 16:17:56 +08:00
dependabot[bot]
941f256ba5
build(deps): bump golang.org/x/net from 0.12.0 to 0.13.0 (#423)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.12.0 to 0.13.0.
- [Commits](https://github.com/golang/net/compare/v0.12.0...v0.13.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-05 14:00:23 +08:00
dependabot[bot]
2e547afdb7
build(deps): bump github.com/shirou/gopsutil/v3 from 3.23.6 to 3.23.7 (#421)
Bumps [github.com/shirou/gopsutil/v3](https://github.com/shirou/gopsutil) from 3.23.6 to 3.23.7.
- [Release notes](https://github.com/shirou/gopsutil/releases)
- [Commits](https://github.com/shirou/gopsutil/compare/v3.23.6...v3.23.7)

---
updated-dependencies:
- dependency-name: github.com/shirou/gopsutil/v3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-05 14:00:13 +08:00
dependabot[bot]
422ed1a311
build(deps): bump github.com/go-acme/lego/v4 from 4.13.2 to 4.13.3 (#418)
Bumps [github.com/go-acme/lego/v4](https://github.com/go-acme/lego) from 4.13.2 to 4.13.3.
- [Release notes](https://github.com/go-acme/lego/releases)
- [Changelog](https://github.com/go-acme/lego/blob/master/CHANGELOG.md)
- [Commits](https://github.com/go-acme/lego/compare/v4.13.2...v4.13.3)

---
updated-dependencies:
- dependency-name: github.com/go-acme/lego/v4
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-27 08:08:09 +08:00
dependabot[bot]
214e412993
build(deps): bump github.com/sagernet/sing-shadowsocks (#415)
Bumps [github.com/sagernet/sing-shadowsocks](https://github.com/sagernet/sing-shadowsocks) from 0.2.2 to 0.2.4.
- [Commits](https://github.com/sagernet/sing-shadowsocks/compare/v0.2.2...v0.2.4)

---
updated-dependencies:
- dependency-name: github.com/sagernet/sing-shadowsocks
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-24 22:32:14 +08:00
dependabot[bot]
f85f6b47ee
build(deps): bump github.com/go-acme/lego/v4 from 4.13.1 to 4.13.2 (#414)
Bumps [github.com/go-acme/lego/v4](https://github.com/go-acme/lego) from 4.13.1 to 4.13.2.
- [Release notes](https://github.com/go-acme/lego/releases)
- [Changelog](https://github.com/go-acme/lego/blob/master/CHANGELOG.md)
- [Commits](https://github.com/go-acme/lego/compare/v4.13.1...v4.13.2)

---
updated-dependencies:
- dependency-name: github.com/go-acme/lego/v4
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-24 22:32:05 +08:00
dependabot[bot]
7e09aef1cc
build(deps): bump github.com/go-acme/lego/v4 from 4.12.3 to 4.13.1 (#411)
Bumps [github.com/go-acme/lego/v4](https://github.com/go-acme/lego) from 4.12.3 to 4.13.1.
- [Release notes](https://github.com/go-acme/lego/releases)
- [Changelog](https://github.com/go-acme/lego/blob/master/CHANGELOG.md)
- [Commits](https://github.com/go-acme/lego/compare/v4.12.3...v4.13.1)

---
updated-dependencies:
- dependency-name: github.com/go-acme/lego/v4
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-23 21:07:59 +08:00
dependabot[bot]
0b4caba8f6
build(deps): bump golang.org/x/net from 0.11.0 to 0.12.0 (#403)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.11.0 to 0.12.0.
- [Commits](https://github.com/golang/net/compare/v0.11.0...v0.12.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-11 09:58:05 +08:00
dependabot[bot]
b0866011e5
build(deps): bump github.com/shirou/gopsutil/v3 from 3.23.5 to 3.23.6 (#401)
Bumps [github.com/shirou/gopsutil/v3](https://github.com/shirou/gopsutil) from 3.23.5 to 3.23.6.
- [Release notes](https://github.com/shirou/gopsutil/releases)
- [Commits](https://github.com/shirou/gopsutil/compare/v3.23.5...v3.23.6)

---
updated-dependencies:
- dependency-name: github.com/shirou/gopsutil/v3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-06 07:53:23 +08:00
dependabot[bot]
4d1d89b837
build(deps): bump github.com/sagernet/sing from 0.2.6 to 0.2.7 (#398)
Bumps [github.com/sagernet/sing](https://github.com/sagernet/sing) from 0.2.6 to 0.2.7.
- [Commits](https://github.com/sagernet/sing/compare/v0.2.6...v0.2.7)

---
updated-dependencies:
- dependency-name: github.com/sagernet/sing
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-27 06:17:09 +08:00
dependabot[bot]
0febf96021
build(deps): bump google.golang.org/protobuf from 1.30.0 to 1.31.0 (#397)
Bumps google.golang.org/protobuf from 1.30.0 to 1.31.0.

---
updated-dependencies:
- dependency-name: google.golang.org/protobuf
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-27 06:16:47 +08:00
Senis John
0f10e837e4
fix: typo 2023-06-25 12:05:14 +08:00
Senis John
5ab352f9c9
update: remove old v2board api
update: update xray-core to 1.8.3
alterID is not use anymore
2023-06-25 07:21:27 +08:00
OPPO9008
5d5470a919
修复http伪装配置解析 (#389)
根据sspanel代码,headerType 才是下发订阅的参数
2023-06-21 07:14:20 +08:00
dependabot[bot]
db27722bbc
build(deps): bump github.com/go-acme/lego/v4 from 4.12.2 to 4.12.3 (#395)
Bumps [github.com/go-acme/lego/v4](https://github.com/go-acme/lego) from 4.12.2 to 4.12.3.
- [Release notes](https://github.com/go-acme/lego/releases)
- [Changelog](https://github.com/go-acme/lego/blob/master/CHANGELOG.md)
- [Commits](https://github.com/go-acme/lego/compare/v4.12.2...v4.12.3)

---
updated-dependencies:
- dependency-name: github.com/go-acme/lego/v4
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-21 07:13:58 +08:00
dependabot[bot]
914510c687
build(deps): bump github.com/sagernet/sing from 0.2.3 to 0.2.6 (#394)
Bumps [github.com/sagernet/sing](https://github.com/sagernet/sing) from 0.2.3 to 0.2.6.
- [Commits](https://github.com/sagernet/sing/compare/v0.2.3...v0.2.6)

---
updated-dependencies:
- dependency-name: github.com/sagernet/sing
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-21 07:13:41 +08:00
dependabot[bot]
a8226b01e2
build(deps): bump github.com/go-acme/lego/v4 from 4.12.1 to 4.12.2 (#393)
Bumps [github.com/go-acme/lego/v4](https://github.com/go-acme/lego) from 4.12.1 to 4.12.2.
- [Release notes](https://github.com/go-acme/lego/releases)
- [Changelog](https://github.com/go-acme/lego/blob/master/CHANGELOG.md)
- [Commits](https://github.com/go-acme/lego/compare/v4.12.1...v4.12.2)

---
updated-dependencies:
- dependency-name: github.com/go-acme/lego/v4
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-20 08:08:50 +08:00
dependabot[bot]
54a958f39c
build(deps): bump github.com/sagernet/sing-shadowsocks (#392)
Bumps [github.com/sagernet/sing-shadowsocks](https://github.com/sagernet/sing-shadowsocks) from 0.2.1 to 0.2.2.
- [Commits](https://github.com/sagernet/sing-shadowsocks/compare/v0.2.1...v0.2.2)

---
updated-dependencies:
- dependency-name: github.com/sagernet/sing-shadowsocks
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-20 08:08:37 +08:00
dependabot[bot]
a1e407e18f
build(deps): bump golang.org/x/net from 0.10.0 to 0.11.0 (#387)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.10.0 to 0.11.0.
- [Commits](https://github.com/golang/net/compare/v0.10.0...v0.11.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-14 05:38:39 +08:00
Senis John
42da6c155d
fix: unexceptional etags handle 2023-06-11 20:07:43 +08:00
dependabot[bot]
89f2342a42
build(deps): bump github.com/go-acme/lego/v4 from 4.12.0 to 4.12.1 (#380)
Bumps [github.com/go-acme/lego/v4](https://github.com/go-acme/lego) from 4.12.0 to 4.12.1.
- [Release notes](https://github.com/go-acme/lego/releases)
- [Changelog](https://github.com/go-acme/lego/blob/master/CHANGELOG.md)
- [Commits](https://github.com/go-acme/lego/compare/v4.12.0...v4.12.1)

---
updated-dependencies:
- dependency-name: github.com/go-acme/lego/v4
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-08 00:06:31 +08:00
dependabot[bot]
ee1a606888
build(deps): bump github.com/bitly/go-simplejson from 0.5.0 to 0.5.1 (#379)
Bumps [github.com/bitly/go-simplejson](https://github.com/bitly/go-simplejson) from 0.5.0 to 0.5.1.
- [Release notes](https://github.com/bitly/go-simplejson/releases)
- [Commits](https://github.com/bitly/go-simplejson/compare/v0.5.0...v0.5.1)

---
updated-dependencies:
- dependency-name: github.com/bitly/go-simplejson
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-07 09:59:16 +08:00
dependabot[bot]
c183c6492e
build(deps): bump github.com/shirou/gopsutil/v3 from 3.23.4 to 3.23.5 (#373)
Bumps [github.com/shirou/gopsutil/v3](https://github.com/shirou/gopsutil) from 3.23.4 to 3.23.5.
- [Release notes](https://github.com/shirou/gopsutil/releases)
- [Commits](https://github.com/shirou/gopsutil/compare/v3.23.4...v3.23.5)

---
updated-dependencies:
- dependency-name: github.com/shirou/gopsutil/v3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-02 18:33:12 +08:00
OPPO9008
a70a0d9a31
初步适配sspanel ETag 功能 (#309)
在最新sspanel 版本 M1Screw 应该找到正确下发Etag的办法了,如果你是旧版本,可以尝试
修改
res.Header().Get("ETag")
为
res.Header().Get("webapi-etag")

Co-authored-by: admin <admin@justcn2.top>
2023-06-01 18:09:08 +08:00
dependabot[bot]
4c651e15fa
build(deps): bump github.com/stretchr/testify from 1.8.3 to 1.8.4 (#369)
Bumps [github.com/stretchr/testify](https://github.com/stretchr/testify) from 1.8.3 to 1.8.4.
- [Release notes](https://github.com/stretchr/testify/releases)
- [Commits](https://github.com/stretchr/testify/compare/v1.8.3...v1.8.4)

---
updated-dependencies:
- dependency-name: github.com/stretchr/testify
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-01 18:07:41 +08:00
dependabot[bot]
dda00c5dd6
build(deps): bump github.com/spf13/viper from 1.15.0 to 1.16.0 (#368)
Bumps [github.com/spf13/viper](https://github.com/spf13/viper) from 1.15.0 to 1.16.0.
- [Release notes](https://github.com/spf13/viper/releases)
- [Commits](https://github.com/spf13/viper/compare/v1.15.0...v1.16.0)

---
updated-dependencies:
- dependency-name: github.com/spf13/viper
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-31 00:27:41 +08:00
dependabot[bot]
28e1b82320
build(deps): bump github.com/imdario/mergo from 0.3.13 to 0.3.16 (#365)
Bumps [github.com/imdario/mergo](https://github.com/imdario/mergo) from 0.3.13 to 0.3.16.
- [Release notes](https://github.com/imdario/mergo/releases)
- [Commits](https://github.com/imdario/mergo/compare/v0.3.13...v0.3.16)

---
updated-dependencies:
- dependency-name: github.com/imdario/mergo
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-30 00:47:59 +08:00
dependabot[bot]
f1ab2eac13
build(deps): bump github.com/go-acme/lego/v4 from 4.10.2 to 4.12.0 (#364)
Bumps [github.com/go-acme/lego/v4](https://github.com/go-acme/lego) from 4.10.2 to 4.12.0.
- [Release notes](https://github.com/go-acme/lego/releases)
- [Changelog](https://github.com/go-acme/lego/blob/master/CHANGELOG.md)
- [Commits](https://github.com/go-acme/lego/compare/v4.10.2...v4.12.0)

---
updated-dependencies:
- dependency-name: github.com/go-acme/lego/v4
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-30 00:47:50 +08:00
Senis John
4f13aac094
fix: sspanel custom flow config doesn't work 2023-05-25 21:08:56 +08:00
Senis John
4ab196ad29
fix: local vless flow config doesn't work 2023-05-25 20:39:46 +08:00
Senis John
9590697c29
update: switch vless flow on local config 2023-05-25 10:12:16 +08:00
Senis John
0bec6c4fdf
fix: vless and trojan flow mode 2023-05-24 20:44:26 +08:00
dependabot[bot]
223589ba14
build(deps): bump github.com/stretchr/testify from 1.8.2 to 1.8.3 (#355)
Bumps [github.com/stretchr/testify](https://github.com/stretchr/testify) from 1.8.2 to 1.8.3.
- [Release notes](https://github.com/stretchr/testify/releases)
- [Commits](https://github.com/stretchr/testify/compare/v1.8.2...v1.8.3)

---
updated-dependencies:
- dependency-name: github.com/stretchr/testify
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-20 00:03:43 +08:00
dependabot[bot]
6ba7fe2776
build(deps): bump golang.org/x/net from 0.9.0 to 0.10.0 (#346)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.9.0 to 0.10.0.
- [Commits](https://github.com/golang/net/compare/v0.9.0...v0.10.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-20 00:03:16 +08:00
Senis John
b49798ab16
fix: sspanel version >= 2023.2 will discard node status report.
fix: return error message for null user list
2023-05-18 01:23:46 +08:00
dependabot[bot]
af9224f5bb
build(deps): bump github.com/shirou/gopsutil/v3 from 3.23.2 to 3.23.4 (#337)
Bumps [github.com/shirou/gopsutil/v3](https://github.com/shirou/gopsutil) from 3.23.2 to 3.23.4.
- [Release notes](https://github.com/shirou/gopsutil/releases)
- [Commits](https://github.com/shirou/gopsutil/compare/v3.23.2...v3.23.4)

---
updated-dependencies:
- dependency-name: github.com/shirou/gopsutil/v3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-05 05:27:31 +08:00
Senis John
c54650f195
update: add readme for REALITY proto params 2023-04-22 17:49:07 +08:00
Senis John
c73af2309b
fix: When server port is 0, the program will not exit normally 2023-04-22 17:05:10 +08:00
thank243
169f742b76
Update core to 1.8.1 and support Reality proto (#326)
* update: Support reality proto

* fix: typo
2023-04-22 16:41:22 +08:00
pocketW
0fa8a45e51
Merge pull request #287 from XrayR-project/dependabot/go_modules/google.golang.org/protobuf-1.29.1
build(deps): bump google.golang.org/protobuf from 1.29.0 to 1.29.1
2023-03-15 10:34:09 +11:00
dependabot[bot]
17c538a5b7
build(deps): bump google.golang.org/protobuf from 1.29.0 to 1.29.1
Bumps [google.golang.org/protobuf](https://github.com/protocolbuffers/protobuf-go) from 1.29.0 to 1.29.1.
- [Release notes](https://github.com/protocolbuffers/protobuf-go/releases)
- [Changelog](https://github.com/protocolbuffers/protobuf-go/blob/master/release.bash)
- [Commits](https://github.com/protocolbuffers/protobuf-go/compare/v1.29.0...v1.29.1)

---
updated-dependencies:
- dependency-name: google.golang.org/protobuf
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-14 23:08:17 +00:00
pocketW
5625d570fd
Merge pull request #284 from XrayR-project/dependabot/go_modules/github.com/xtls/xray-core-1.8.0
build(deps): bump github.com/xtls/xray-core from 1.7.5 to 1.8.0
2023-03-11 18:27:02 +08:00
pocketW
9b0e55f037
Merge pull request #283 from XrayR-project/dependabot/go_modules/github.com/sagernet/sing-0.1.8
build(deps): bump github.com/sagernet/sing from 0.1.7 to 0.1.8
2023-03-11 18:26:50 +08:00
dependabot[bot]
4597d6ac56
build(deps): bump github.com/xtls/xray-core from 1.7.5 to 1.8.0
Bumps [github.com/xtls/xray-core](https://github.com/xtls/xray-core) from 1.7.5 to 1.8.0.
- [Release notes](https://github.com/xtls/xray-core/releases)
- [Commits](https://github.com/xtls/xray-core/compare/v1.7.5...v1.8.0)

---
updated-dependencies:
- dependency-name: github.com/xtls/xray-core
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-09 15:15:48 +00:00
dependabot[bot]
9aaad5e8ad
build(deps): bump github.com/sagernet/sing from 0.1.7 to 0.1.8
Bumps [github.com/sagernet/sing](https://github.com/sagernet/sing) from 0.1.7 to 0.1.8.
- [Release notes](https://github.com/sagernet/sing/releases)
- [Commits](https://github.com/sagernet/sing/compare/v0.1.7...v0.1.8)

---
updated-dependencies:
- dependency-name: github.com/sagernet/sing
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-09 15:15:03 +00:00
dependabot[bot]
94d82f33ea
build(deps): bump google.golang.org/protobuf from 1.28.1 to 1.29.0 (#282)
Bumps [google.golang.org/protobuf](https://github.com/protocolbuffers/protobuf-go) from 1.28.1 to 1.29.0.
- [Release notes](https://github.com/protocolbuffers/protobuf-go/releases)
- [Changelog](https://github.com/protocolbuffers/protobuf-go/blob/master/release.bash)
- [Commits](https://github.com/protocolbuffers/protobuf-go/compare/v1.28.1...v1.29.0)

---
updated-dependencies:
- dependency-name: google.golang.org/protobuf
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-09 02:08:25 +08:00
pocketW
49aa520d67
Merge pull request #280 from XrayR-project/dependabot/go_modules/golang.org/x/crypto-0.7.0
build(deps): bump golang.org/x/crypto from 0.6.0 to 0.7.0
2023-03-08 20:03:21 +08:00
dependabot[bot]
73c3047651
build(deps): bump golang.org/x/crypto from 0.6.0 to 0.7.0
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.6.0 to 0.7.0.
- [Release notes](https://github.com/golang/crypto/releases)
- [Commits](https://github.com/golang/crypto/compare/v0.6.0...v0.7.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-06 16:12:02 +00:00
dependabot[bot]
613da96543
build(deps): bump github.com/shirou/gopsutil/v3 from 3.23.1 to 3.23.2 (#278)
Bumps [github.com/shirou/gopsutil/v3](https://github.com/shirou/gopsutil) from 3.23.1 to 3.23.2.
- [Release notes](https://github.com/shirou/gopsutil/releases)
- [Commits](https://github.com/shirou/gopsutil/compare/v3.23.1...v3.23.2)

---
updated-dependencies:
- dependency-name: github.com/shirou/gopsutil/v3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-02 00:31:15 +08:00
dependabot[bot]
76127f4757
build(deps): bump github.com/stretchr/testify from 1.8.1 to 1.8.2 (#274)
Bumps [github.com/stretchr/testify](https://github.com/stretchr/testify) from 1.8.1 to 1.8.2.
- [Release notes](https://github.com/stretchr/testify/releases)
- [Commits](https://github.com/stretchr/testify/compare/v1.8.1...v1.8.2)

---
updated-dependencies:
- dependency-name: github.com/stretchr/testify
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-28 19:09:42 +08:00
dependabot[bot]
1d5a34cf98
build(deps): bump github.com/go-acme/lego/v4 from 4.10.0 to 4.10.2 (#273)
Bumps [github.com/go-acme/lego/v4](https://github.com/go-acme/lego) from 4.10.0 to 4.10.2.
- [Release notes](https://github.com/go-acme/lego/releases)
- [Changelog](https://github.com/go-acme/lego/blob/master/CHANGELOG.md)
- [Commits](https://github.com/go-acme/lego/compare/v4.10.0...v4.10.2)

---
updated-dependencies:
- dependency-name: github.com/go-acme/lego/v4
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-28 19:09:29 +08:00
dependabot[bot]
bf13971502
build(deps): bump github.com/eko/gocache/lib/v4 from 4.1.2 to 4.1.3 (#272)
Bumps [github.com/eko/gocache/lib/v4](https://github.com/eko/gocache) from 4.1.2 to 4.1.3.
- [Release notes](https://github.com/eko/gocache/releases)
- [Commits](https://github.com/eko/gocache/compare/lib/v4.1.2...lib/v4.1.3)

---
updated-dependencies:
- dependency-name: github.com/eko/gocache/lib/v4
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-28 19:09:20 +08:00
pocketW
572be38ae4
Merge pull request #267 from XrayR-project/dependabot/go_modules/github.com/sagernet/sing-shadowsocks-0.1.1
build(deps): bump github.com/sagernet/sing-shadowsocks from 0.1.1-0.20230202035033-e3123545f2f7 to 0.1.1
2023-02-24 23:45:09 +11:00
pocketW
34d96c9338
Merge pull request #266 from XrayR-project/dependabot/go_modules/github.com/go-acme/lego/v4-4.10.0
build(deps): bump github.com/go-acme/lego/v4 from 4.9.2-0.20221210101705-6695fcc87344 to 4.10.0
2023-02-24 23:44:55 +11:00
dependabot[bot]
4e69c0656e
build(deps): bump github.com/sagernet/sing-shadowsocks
Bumps [github.com/sagernet/sing-shadowsocks](https://github.com/sagernet/sing-shadowsocks) from 0.1.1-0.20230202035033-e3123545f2f7 to 0.1.1.
- [Release notes](https://github.com/sagernet/sing-shadowsocks/releases)
- [Commits](https://github.com/sagernet/sing-shadowsocks/commits/v0.1.1)

---
updated-dependencies:
- dependency-name: github.com/sagernet/sing-shadowsocks
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-23 15:21:36 +00:00
dependabot[bot]
88f7709fad
build(deps): bump github.com/go-acme/lego/v4
Bumps [github.com/go-acme/lego/v4](https://github.com/go-acme/lego) from 4.9.2-0.20221210101705-6695fcc87344 to 4.10.0.
- [Release notes](https://github.com/go-acme/lego/releases)
- [Commits](https://github.com/go-acme/lego/commits/v4.10.0)

---
updated-dependencies:
- dependency-name: github.com/go-acme/lego/v4
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-23 15:21:30 +00:00
66 changed files with 4258 additions and 1878 deletions

View File

@ -46,7 +46,11 @@ jobs:
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
- name: Install Go
uses: actions/setup-go@v4
with:
go-version-file: go.mod
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild

View File

@ -1,44 +1,94 @@
name: Publish Docker image
on:
workflow_dispatch:
push:
branches:
- master
paths:
- "**/*.go"
- "go.mod"
- "go.sum"
- ".github/workflows/*.yml"
tags:
- 'v*'
pull_request:
branches:
- 'master'
release:
types:
- published
env:
REGISTRY: ghcr.io
IMAGE_NAME: xrayr-project/xrayr
jobs:
push_to_registry:
name: Push Docker image to Docker Hub
build:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
platform:
- linux/amd64
- linux/arm/v6
- linux/arm/v7
- linux/arm64
- linux/s390x
steps:
- name: Check out the repo
uses: actions/checkout@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Log in to the Container registry
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Checkout
uses: actions/checkout@v4
- name: Docker meta
id: meta
uses: docker/metadata-action@v4
uses: docker/metadata-action@v5
with:
images: ghcr.io/${{ github.repository }}
- name: Build and push
uses: docker/build-push-action@v3
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push by digest
id: build
uses: docker/build-push-action@v5
with:
context: .
platforms: linux/arm/v7,linux/arm64,linux/amd64,linux/s390x
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
platforms: ${{ matrix.platform }}
labels: ${{ steps.meta.outputs.labels }}
outputs: type=image,name=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=true
- name: Export digest
run: |
mkdir -p /tmp/digests
digest="${{ steps.build.outputs.digest }}"
touch "/tmp/digests/${digest#sha256:}"
- name: Upload digest
uses: actions/upload-artifact@v4
with:
name: digests
path: /tmp/digests/*
if-no-files-found: error
retention-days: 1
merge:
runs-on: ubuntu-latest
needs:
- build
steps:
- name: Download digests
uses: actions/download-artifact@v4.1.7
with:
name: digests
path: /tmp/digests
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Create manifest list and push
working-directory: /tmp/digests
run: |
ls -al
echo docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
$(printf '${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@sha256:%s ' *)
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
$(printf '${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@sha256:%s ' *)
- name: Inspect image
run: |
docker buildx imagetools inspect ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.meta.outputs.version }}

View File

@ -26,12 +26,10 @@ jobs:
strategy:
matrix:
# Include amd64 on all platforms.
goos: [ windows, freebsd, openbsd, linux, dragonfly, darwin ]
goos: [ windows, freebsd, openbsd, linux, darwin ]
goarch: [ amd64, 386 ]
exclude:
# Exclude i386 on darwin and dragonfly.
- goarch: 386
goos: dragonfly
# Exclude i386 on darwin.
- goarch: 386
goos: darwin
- goarch: 386
@ -122,12 +120,12 @@ jobs:
- name: Build XrayR
run: |
mkdir -p build_assets
go build -v -o build_assets/XrayR -trimpath -ldflags "-s -w -buildid=" ./main
go build -v -o build_assets/XrayR -trimpath -ldflags "-s -w -buildid="
- name: Build Mips softfloat XrayR
if: matrix.goarch == 'mips' || matrix.goarch == 'mipsle'
run: |
GOMIPS=softfloat go build -v -o build_assets/XrayR_softfloat -trimpath -ldflags "-s -w -buildid=" ./main
GOMIPS=softfloat go build -v -o build_assets/XrayR_softfloat -trimpath -ldflags "-s -w -buildid="
- name: Rename Windows XrayR
if: matrix.goos == 'windows'
run: |
@ -143,12 +141,12 @@ jobs:
command: |
cp ${GITHUB_WORKSPACE}/README.md ./build_assets/README.md
cp ${GITHUB_WORKSPACE}/LICENSE ./build_assets/LICENSE
cp ${GITHUB_WORKSPACE}/main/dns.json ./build_assets/dns.json
cp ${GITHUB_WORKSPACE}/main/route.json ./build_assets/route.json
cp ${GITHUB_WORKSPACE}/main/custom_outbound.json ./build_assets/custom_outbound.json
cp ${GITHUB_WORKSPACE}/main/custom_inbound.json ./build_assets/custom_inbound.json
cp ${GITHUB_WORKSPACE}/main/rulelist ./build_assets/rulelist
cp ${GITHUB_WORKSPACE}/main/config.yml.example ./build_assets/config.yml
cp ${GITHUB_WORKSPACE}/release/config/dns.json ./build_assets/dns.json
cp ${GITHUB_WORKSPACE}/release/config/route.json ./build_assets/route.json
cp ${GITHUB_WORKSPACE}/release/config/custom_outbound.json ./build_assets/custom_outbound.json
cp ${GITHUB_WORKSPACE}/release/config/custom_inbound.json ./build_assets/custom_inbound.json
cp ${GITHUB_WORKSPACE}/release/config/rulelist ./build_assets/rulelist
cp ${GITHUB_WORKSPACE}/release/config/config.yml.example ./build_assets/config.yml
LIST=('geoip geoip geoip' 'domain-list-community dlc geosite')
for i in "${LIST[@]}"
do
@ -178,7 +176,7 @@ jobs:
run: |
mv build_assets XrayR-$ASSET_NAME
- name: Upload files to Artifacts
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: XrayR-${{ steps.get_filename.outputs.ASSET_NAME }}
path: |

38
.gitignore vendored
View File

@ -1,18 +1,20 @@
main/main
main/XrayR
main/XrayR*
main/mytest
main/access.logo
main/error.log
api/chooseparser.go.bak
common/Inboundbuilder/.lego/
common/legocmd/.lego/
.vscode/launch.json
main/.lego
main/cert
main/config.yml
./vscode
.idea/*
.DS_Store
*.bak
go.work*
.idea
*.iml
out
gen
*.exe
*.exe~
*.dll
*.so
*.dylib
*.test
*.out
go.work
main
XrayR
XrayR*
access.log
error.log
.lego
cert
config.yml

View File

@ -1,10 +1,10 @@
# Build go
FROM golang:1.20-alpine AS builder
FROM golang:1.22.0-alpine AS builder
WORKDIR /app
COPY . .
ENV CGO_ENABLED=0
RUN go mod download
RUN go build -v -o XrayR -trimpath -ldflags "-s -w -buildid=" ./main
RUN go build -v -o XrayR -trimpath -ldflags "-s -w -buildid="
# Release
FROM alpine

View File

@ -64,6 +64,7 @@ This project is just my personal learning and development and maintenance. I do
| [PMPanel](https://github.com/ByteInternetHK/PMPanel) | √ | √ | √ |
| [ProxyPanel](https://github.com/ProxyPanel/ProxyPanel) | √ | √ | √ |
| [WHMCS (V2RaySocks)](https://v2raysocks.doxtex.com/) | √ | √ | √ |
| [BunPanel](https://github.com/pennyMorant/bunpanel-release) | √ | √ | √ |
## Software Installation

View File

@ -61,6 +61,7 @@ Dự án này chỉ là học tập và phát triển và bảo trì cá nhân c
| [PMPanel](https://github.com/ByteInternetHK/PMPanel) | √ | √ | √ |
| [ProxyPanel](https://github.com/ProxyPanel/ProxyPanel) | √ | √ | √ |
| [WHMCS (V2RaySocks)](https://v2raysocks.doxtex.com/) | √ | √ | √ |
| [BunPanel](https://github.com/pennyMorant/bunpanel-release) | √ | √ | √ |
## Cài đặt phần mềm

View File

@ -62,6 +62,8 @@ A Xray backend framework that can easily support many panels.
| [PMPanel](https://github.com/ByteInternetHK/PMPanel) | √ | √ | √ |
| [ProxyPanel](https://github.com/ProxyPanel/ProxyPanel) | √ | √ | √ |
| [WHMCS (V2RaySocks)](https://v2raysocks.doxtex.com/) | √ | √ | √ |
| [GoV2Panel](https://github.com/pingProMax/gov2panel) | √ | √ | √ |
| [BunPanel](https://github.com/pennyMorant/bunpanel-release) | √ | √ | √ |
## 软件安装

View File

@ -59,6 +59,7 @@
| [PMPanel](https://github.com/ByteInternetHK/PMPanel) | √ | √ | √ |
| [ProxyPanel](https://github.com/ProxyPanel/ProxyPanel) | √ | √ | √ |
| [WHMCS (V2RaySocks)](https://v2raysocks.doxtex.com/) | √ | √ | √ |
| [BunPanel](https://github.com/pennyMorant/bunpanel-release) | √ | √ | √ |
## نصب نرم افزار

View File

@ -7,6 +7,12 @@ import (
"github.com/xtls/xray-core/infra/conf"
)
const (
UserNotModified = "users not modified"
NodeNotModified = "node not modified"
RuleNotModified = "rules not modified"
)
// Config API config
type Config struct {
APIHost string `mapstructure:"ApiHost"`
@ -14,7 +20,7 @@ type Config struct {
Key string `mapstructure:"ApiKey"`
NodeType string `mapstructure:"NodeType"`
EnableVless bool `mapstructure:"EnableVless"`
EnableXTLS bool `mapstructure:"EnableXTLS"`
VlessFlow string `mapstructure:"VlessFlow"`
Timeout int `mapstructure:"Timeout"`
SpeedLimit float64 `mapstructure:"SpeedLimit"`
DeviceLimit int `mapstructure:"DeviceLimit"`
@ -31,39 +37,59 @@ type NodeStatus struct {
}
type NodeInfo struct {
NodeType string // Must be V2ray, Trojan, and Shadowsocks
NodeID int
Port uint32
SpeedLimit uint64 // Bps
AlterID uint16
TransportProtocol string
FakeType string
Host string
Path string
EnableTLS bool
TLSType string
EnableVless bool
CypherMethod string
ServerKey string
ServiceName string
Header json.RawMessage
NameServerConfig []*conf.NameServerConfig
AcceptProxyProtocol bool
Authority string
NodeType string // Must be V2ray, Trojan, and Shadowsocks
NodeID int
Port uint32
SpeedLimit uint64 // Bps
AlterID uint16
TransportProtocol string
FakeType string
Host string
Path string
EnableTLS bool
EnableSniffing bool
RouteOnly bool
EnableVless bool
VlessFlow string
CypherMethod string
ServerKey string
ServiceName string
Method string
Header json.RawMessage
HttpHeaders map[string]*conf.StringList
Headers map[string]string
NameServerConfig []*conf.NameServerConfig
EnableREALITY bool
REALITYConfig *REALITYConfig
Show bool
EnableTFO bool
Dest string
ProxyProtocolVer uint64
ServerNames []string
PrivateKey string
MinClientVer string
MaxClientVer string
MaxTimeDiff uint64
ShortIds []string
Xver uint64
Flow string
Security string
Key string
RejectUnknownSni bool
}
type UserInfo struct {
UID int
Email string
Passwd string
Port uint32
Method string
SpeedLimit uint64 // Bps
DeviceLimit int
Protocol string
ProtocolParam string
Obfs string
ObfsParam string
UUID string
AlterID uint16
UID int
Email string
UUID string
Passwd string
Port uint32
AlterID uint16
Method string
SpeedLimit uint64 // Bps
DeviceLimit int
}
type OnlineUser struct {
@ -94,3 +120,14 @@ type DetectResult struct {
UID int
RuleID int
}
type REALITYConfig struct {
Dest string
ProxyProtocolVer uint64
ServerNames []string
PrivateKey string
MinClientVer string
MaxClientVer string
MaxTimeDiff uint64
ShortIds []string
}

427
api/bunpanel/bunpanel.go Normal file
View File

@ -0,0 +1,427 @@
package bunpanel
import (
"bufio"
"encoding/json"
"errors"
"fmt"
"os"
"reflect"
"regexp"
"strconv"
"strings"
"sync"
"time"
log "github.com/sirupsen/logrus"
"github.com/go-resty/resty/v2"
"github.com/XrayR-project/XrayR/api"
)
type APIClient struct {
client *resty.Client
APIHost string
NodeID int
Key string
NodeType string
EnableVless bool
VlessFlow string
SpeedLimit float64
DeviceLimit int
LocalRuleList []api.DetectRule
LastReportOnline map[int]int
access sync.Mutex
eTags map[string]string
}
// ReportIllegal implements api.API.
func (*APIClient) ReportIllegal(detectResultList *[]api.DetectResult) (err error) {
return nil
}
// ReportNodeStatus implements api.API.
func (*APIClient) ReportNodeStatus(nodeStatus *api.NodeStatus) (err error) {
return nil
}
// GetNodeRule implements api.API.
func (c *APIClient) GetNodeRule() (*[]api.DetectRule, error) {
ruleList := c.LocalRuleList
return &ruleList, nil
}
func New(apiConfig *api.Config) *APIClient {
client := resty.New()
client.SetRetryCount(3)
if apiConfig.Timeout > 0 {
client.SetTimeout(time.Duration(apiConfig.Timeout) * time.Second)
} else {
client.SetTimeout(5 * time.Second)
}
client.OnError(func(req *resty.Request, err error) {
if v, ok := err.(*resty.ResponseError); ok {
// v.Response contains the last response from the server
// v.Err contains the original error
log.Print(v.Err)
}
})
client.SetBaseURL(apiConfig.APIHost)
// Create Key for each requests
client.SetQueryParams(map[string]string{
"serverId": strconv.Itoa(apiConfig.NodeID),
"nodeType": strings.ToLower(apiConfig.NodeType),
"token": apiConfig.Key,
})
// Read local rule list
localRuleList := readLocalRuleList(apiConfig.RuleListPath)
apiClient := &APIClient{
client: client,
NodeID: apiConfig.NodeID,
Key: apiConfig.Key,
APIHost: apiConfig.APIHost,
NodeType: apiConfig.NodeType,
EnableVless: apiConfig.EnableVless,
VlessFlow: apiConfig.VlessFlow,
SpeedLimit: apiConfig.SpeedLimit,
DeviceLimit: apiConfig.DeviceLimit,
LocalRuleList: localRuleList,
eTags: make(map[string]string),
}
return apiClient
}
// readLocalRuleList reads the local rule list file
func readLocalRuleList(path string) (LocalRuleList []api.DetectRule) {
LocalRuleList = make([]api.DetectRule, 0)
if path != "" {
// open the file
file, err := os.Open(path)
// handle errors while opening
if err != nil {
log.Printf("Error when opening file: %s", err)
return LocalRuleList
}
defer file.Close()
fileScanner := bufio.NewScanner(file)
// read line by line
for fileScanner.Scan() {
LocalRuleList = append(LocalRuleList, api.DetectRule{
ID: -1,
Pattern: regexp.MustCompile(fileScanner.Text()),
})
}
// handle first encountered error while reading
if err := fileScanner.Err(); err != nil {
log.Fatalf("Error while reading file: %s", err)
return
}
}
return LocalRuleList
}
// Describe return a description of the client
func (c *APIClient) Describe() api.ClientInfo {
return api.ClientInfo{APIHost: c.APIHost, NodeID: c.NodeID, Key: c.Key, NodeType: c.NodeType}
}
// Debug set the client debug for client
func (c *APIClient) Debug() {
c.client.SetDebug(true)
}
func (c *APIClient) assembleURL(path string) string {
return c.APIHost + path
}
func (c *APIClient) parseResponse(res *resty.Response, path string, err error) (*Response, error) {
if err != nil {
return nil, fmt.Errorf("request %s failed: %s", c.assembleURL(path), err)
}
if res.StatusCode() > 400 {
body := res.Body()
return nil, fmt.Errorf("request %s failed: %s, %v", c.assembleURL(path), string(body), err)
}
response := res.Result().(*Response)
if response.StatusCode != 200 {
res, _ := json.Marshal(&response)
return nil, fmt.Errorf("statusCode %s invalid", string(res))
}
return response, nil
}
func (c *APIClient) GetNodeInfo() (nodeInfo *api.NodeInfo, err error) {
path := fmt.Sprintf("/v2/server/%d/get", c.NodeID)
res, err := c.client.R().
SetResult(&Response{}).
SetHeader("If-None-Match", c.eTags["node"]).
ForceContentType("application/json").
Get(path)
// Etag identifier for a specific version of a resource. StatusCode = 304 means no changed
if res.StatusCode() == 304 {
return nil, errors.New(api.NodeNotModified)
}
if res.Header().Get("ETag") != "" && res.Header().Get("ETag") != c.eTags["node"] {
c.eTags["node"] = res.Header().Get("ETag")
}
response, err := c.parseResponse(res, path, err)
if err != nil {
return nil, err
}
nodeInfoResponse := new(Server)
if err := json.Unmarshal(response.Datas, nodeInfoResponse); err != nil {
return nil, fmt.Errorf("unmarshal %s failed: %s", reflect.TypeOf(nodeInfoResponse), err)
}
nodeInfo, err = c.ParseNodeInfo(nodeInfoResponse)
if err != nil {
res, _ := json.Marshal(nodeInfoResponse)
return nil, fmt.Errorf("parse node info failed: %s, \nError: %s, \nPlease check the doc of custom_config for help: https://xrayr-project.github.io/XrayR-doc/dui-jie-sspanel/sspanel/sspanel_custom_config", string(res), err)
}
if err != nil {
res, _ := json.Marshal(nodeInfoResponse)
return nil, fmt.Errorf("parse node info failed: %s, \nError: %s", string(res), err)
}
return nodeInfo, nil
}
func (c *APIClient) GetUserList() (UserList *[]api.UserInfo, err error) {
path := "/v2/user/get"
res, err := c.client.R().
SetQueryParam("serverId", strconv.Itoa(c.NodeID)).
SetHeader("If-None-Match", c.eTags["users"]).
SetResult(&Response{}).
ForceContentType("application/json").
Get(path)
// Etag identifier for a specific version of a resource. StatusCode = 304 means no changed
if res.StatusCode() == 304 {
return nil, errors.New(api.UserNotModified)
}
if res.Header().Get("ETag") != "" && res.Header().Get("ETag") != c.eTags["users"] {
c.eTags["users"] = res.Header().Get("ETag")
}
response, err := c.parseResponse(res, path, err)
if err != nil {
return nil, err
}
userListResponse := new([]User)
if err := json.Unmarshal(response.Datas, userListResponse); err != nil {
return nil, fmt.Errorf("unmarshal %s failed: %s", reflect.TypeOf(userListResponse), err)
}
userList, err := c.ParseUserListResponse(userListResponse)
if err != nil {
res, _ := json.Marshal(userListResponse)
return nil, fmt.Errorf("parse user list failed: %s", string(res))
}
return userList, nil
}
func (c *APIClient) ReportNodeOnlineUsers(onlineUserList *[]api.OnlineUser) error {
c.access.Lock()
defer c.access.Unlock()
reportOnline := make(map[int]int)
data := make([]OnlineUser, len(*onlineUserList))
for i, user := range *onlineUserList {
data[i] = OnlineUser{UID: user.UID, IP: user.IP}
reportOnline[user.UID]++
}
c.LastReportOnline = reportOnline // Update LastReportOnline
postData := &PostData{Data: data}
path := "/v2/user/online/create"
res, err := c.client.R().
SetQueryParam("serverId", strconv.Itoa(c.NodeID)).
SetBody(postData).
SetResult(&Response{}).
ForceContentType("application/json").
Post(path)
_, err = c.parseResponse(res, path, err)
if err != nil {
return err
}
return nil
}
func (c *APIClient) ReportUserTraffic(userTraffic *[]api.UserTraffic) error {
data := make([]UserTraffic, len(*userTraffic))
for i, traffic := range *userTraffic {
data[i] = UserTraffic{
UID: traffic.UID,
Upload: traffic.Upload,
Download: traffic.Download}
}
postData := &PostData{Data: data}
path := "/v2/user/data-usage/create"
res, err := c.client.R().
SetQueryParam("serverId", strconv.Itoa(c.NodeID)).
SetBody(postData).
SetResult(&Response{}).
ForceContentType("application/json").
Post(path)
_, err = c.parseResponse(res, path, err)
if err != nil {
return err
}
return nil
}
func (c *APIClient) ParseUserListResponse(userInfoResponse *[]User) (*[]api.UserInfo, error) {
c.access.Lock()
// Clear Last report log
defer func() {
c.LastReportOnline = make(map[int]int)
c.access.Unlock()
}()
var deviceLimit, localDeviceLimit = 0, 0
var speedLimit uint64 = 0
var userList []api.UserInfo
for _, user := range *userInfoResponse {
if c.DeviceLimit > 0 {
deviceLimit = c.DeviceLimit
} else {
deviceLimit = user.DeviceLimit
}
// If there is still device available, add the user
if deviceLimit > 0 && user.AliveIP > 0 {
lastOnline := 0
if v, ok := c.LastReportOnline[user.ID]; ok {
lastOnline = v
}
// If there are any available device.
if localDeviceLimit = deviceLimit - user.AliveIP + lastOnline; localDeviceLimit > 0 {
deviceLimit = localDeviceLimit
// If this backend server has reported any user in the last reporting period.
} else if lastOnline > 0 {
deviceLimit = lastOnline
// Remove this user.
} else {
continue
}
}
if c.SpeedLimit > 0 {
speedLimit = uint64((c.SpeedLimit * 1000000) / 8)
} else {
speedLimit = uint64((user.SpeedLimit * 1000000) / 8)
}
userList = append(userList, api.UserInfo{
UID: user.ID,
UUID: user.UUID,
SpeedLimit: speedLimit,
DeviceLimit: deviceLimit,
Passwd: user.UUID,
Email: user.UUID + "@bunpanel.user",
})
}
return &userList, nil
}
func (c *APIClient) ParseNodeInfo(nodeInfoResponse *Server) (*api.NodeInfo, error) {
var (
speedLimit uint64 = 0
enableTLS, enableVless, enableREALITY bool
alterID uint16 = 0
tlsType, transportProtocol string
)
nodeConfig := nodeInfoResponse
port := uint32(nodeConfig.Port)
switch c.NodeType {
case "Shadowsocks":
transportProtocol = "tcp"
case "V2ray":
transportProtocol = nodeConfig.Network
tlsType = nodeConfig.Security
if tlsType == "tls" || tlsType == "xtls" {
enableTLS = true
}
if tlsType == "reality" {
enableREALITY = true
enableVless = true
}
case "Trojan":
enableTLS = true
tlsType = "tls"
transportProtocol = "tcp"
}
// parse reality config
realityConfig := new(api.REALITYConfig)
if nodeConfig.RealitySettings != nil {
r := new(RealitySettings)
json.Unmarshal(nodeConfig.RealitySettings, r)
realityConfig = &api.REALITYConfig{
Dest: r.Dest,
ProxyProtocolVer: r.ProxyProtocolVer,
ServerNames: r.ServerNames,
PrivateKey: r.PrivateKey,
MinClientVer: r.MinClientVer,
MaxClientVer: r.MaxClientVer,
MaxTimeDiff: r.MaxTimeDiff,
ShortIds: r.ShortIds,
}
}
wsConfig := new(WsSettings)
if nodeConfig.WsSettings != nil {
json.Unmarshal(nodeConfig.WsSettings, wsConfig)
}
grpcConfig := new(GrpcSettigns)
if nodeConfig.GrpcSettings != nil {
json.Unmarshal(nodeConfig.GrpcSettings, grpcConfig)
}
tcpConfig := new(TcpSettings)
if nodeConfig.TcpSettings != nil {
json.Unmarshal(nodeConfig.TcpSettings, tcpConfig)
}
// Create GeneralNodeInfo
nodeInfo := &api.NodeInfo{
NodeType: c.NodeType,
NodeID: c.NodeID,
Port: port,
SpeedLimit: speedLimit,
AlterID: alterID,
TransportProtocol: transportProtocol,
Host: wsConfig.Headers.Host,
Path: wsConfig.Path,
EnableTLS: enableTLS,
EnableVless: enableVless,
VlessFlow: nodeConfig.Flow,
CypherMethod: nodeConfig.Method,
ServiceName: grpcConfig.ServiceName,
Header: tcpConfig.Header,
EnableREALITY: enableREALITY,
REALITYConfig: realityConfig,
}
return nodeInfo, nil
}

View File

@ -1,24 +1,24 @@
package v2board_test
package bunpanel_test
import (
"testing"
"github.com/XrayR-project/XrayR/api"
"github.com/XrayR-project/XrayR/api/v2board"
"github.com/XrayR-project/XrayR/api/bunpanel"
)
func CreateClient() api.API {
apiConfig := &api.Config{
APIHost: "http://localhost:9897",
Key: "qwertyuiopasdfghjkl",
APIHost: "http://localhost:8080",
Key: "123456",
NodeID: 1,
NodeType: "V2ray",
}
client := v2board.New(apiConfig)
client := bunpanel.New(apiConfig)
return client
}
func TestGetV2rayNodeinfo(t *testing.T) {
func TestGetV2rayNodeInfo(t *testing.T) {
client := CreateClient()
nodeInfo, err := client.GetNodeInfo()
if err != nil {
@ -27,14 +27,14 @@ func TestGetV2rayNodeinfo(t *testing.T) {
t.Log(nodeInfo)
}
func TestGetSSNodeinfo(t *testing.T) {
func TestGetSSNodeInfo(t *testing.T) {
apiConfig := &api.Config{
APIHost: "http://127.0.0.1:668",
Key: "qwertyuiopasdfghjkl",
NodeID: 1,
NodeType: "Shadowsocks",
}
client := v2board.New(apiConfig)
client := bunpanel.New(apiConfig)
nodeInfo, err := client.GetNodeInfo()
if err != nil {
t.Error(err)
@ -42,14 +42,14 @@ func TestGetSSNodeinfo(t *testing.T) {
t.Log(nodeInfo)
}
func TestGetTrojanNodeinfo(t *testing.T) {
func TestGetTrojanNodeInfo(t *testing.T) {
apiConfig := &api.Config{
APIHost: "http://127.0.0.1:668",
Key: "qwertyuiopasdfghjkl",
NodeID: 1,
NodeType: "Trojan",
}
client := v2board.New(apiConfig)
client := bunpanel.New(apiConfig)
nodeInfo, err := client.GetNodeInfo()
if err != nil {
t.Error(err)
@ -78,8 +78,8 @@ func TestReportReportUserTraffic(t *testing.T) {
for i, userInfo := range *userList {
generalUserTraffic[i] = api.UserTraffic{
UID: userInfo.UID,
Upload: 114514,
Download: 114514,
Upload: 1111,
Download: 2222,
}
}
// client.Debug()

72
api/bunpanel/model.go Normal file
View File

@ -0,0 +1,72 @@
package bunpanel
import "encoding/json"
type Server struct {
Port int `json:"serverPort"`
Network string `json:"network"`
Method string `json:"method"`
Security string `json:"security"`
Flow string `json:"flow"`
WsSettings json.RawMessage `json:"wsSettings"`
RealitySettings json.RawMessage `json:"realitySettings"`
GrpcSettings json.RawMessage `json:"grpcSettings"`
TcpSettings json.RawMessage `json:"tcpSettings"`
}
type WsSettings struct {
Path string `json:"path"`
Headers struct {
Host string `json:"Host"`
} `json:"headers"`
}
type GrpcSettigns struct {
ServiceName string `json:"serviceName"`
}
type TcpSettings struct {
Header json.RawMessage `json:"header"`
}
type RealitySettings struct {
Show bool `json:"show"`
Dest string `json:"dest"`
Xver uint64 `json:"xver"`
ServerNames []string `json:"serverNames"`
PrivateKey string `json:"privateKey"`
MinClientVer string `json:"minClientVer"`
MaxClientVer string `json:"maxClientVer"`
MaxTimeDiff uint64 `json:"maxTimeDiff"`
ProxyProtocolVer uint64 `json:"proxyProtocolVer"`
ShortIds []string `json:"shortIds"`
}
type User struct {
ID int `json:"id"`
UUID string `json:"uuid"`
SpeedLimit float64 `json:"speedLimit"`
DeviceLimit int `json:"ipLimit"`
AliveIP int `json:"onlineIp"`
}
type OnlineUser struct {
UID int `json:"userId"`
IP string `json:"ip"`
}
// UserTraffic is the data structure of traffic
type UserTraffic struct {
UID int `json:"userId"`
Upload int64 `json:"u"`
Download int64 `json:"d"`
}
type Response struct {
StatusCode int `json:"statusCode"`
Datas json.RawMessage `json:"datas"`
}
type PostData struct {
Data interface{} `json:"data"`
}

329
api/gov2panel/gov2panel.go Normal file
View File

@ -0,0 +1,329 @@
package gov2panel
import (
"bufio"
"context"
"errors"
"fmt"
"log"
"os"
"regexp"
"time"
"github.com/XrayR-project/XrayR/api"
"github.com/gogf/gf/v2/encoding/gjson"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/gclient"
"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/infra/conf"
)
// APIClient API config
type APIClient struct {
ctx context.Context
APIHost string
NodeID int
Key string
NodeType string
EnableVless bool
VlessFlow string
Timeout int
SpeedLimit float64
DeviceLimit int
RuleListPath string
DisableCustomConfig bool
LocalRuleList []api.DetectRule
}
// New create an api instance
func New(apiConfig *api.Config) *APIClient {
//https://goframe.org/pages/viewpage.action?pageId=1114381
apiClient := &APIClient{
ctx: context.Background(),
APIHost: apiConfig.APIHost,
NodeID: apiConfig.NodeID,
Key: apiConfig.Key,
NodeType: apiConfig.NodeType,
EnableVless: apiConfig.EnableVless,
VlessFlow: apiConfig.VlessFlow,
Timeout: apiConfig.Timeout,
DeviceLimit: apiConfig.DeviceLimit,
RuleListPath: apiConfig.RuleListPath,
DisableCustomConfig: apiConfig.DisableCustomConfig,
LocalRuleList: readLocalRuleList(apiConfig.RuleListPath), //加载本地路由规则
}
return apiClient
}
// readLocalRuleList reads the local rule list file
func readLocalRuleList(path string) (LocalRuleList []api.DetectRule) {
LocalRuleList = make([]api.DetectRule, 0)
if path != "" {
// open the file
file, err := os.Open(path)
// handle errors while opening
if err != nil {
log.Printf("Error when opening file: %s", err)
return LocalRuleList
}
fileScanner := bufio.NewScanner(file)
// read line by line
for fileScanner.Scan() {
LocalRuleList = append(LocalRuleList, api.DetectRule{
ID: -1,
Pattern: regexp.MustCompile(fileScanner.Text()),
})
}
// handle first encountered error while reading
if err := fileScanner.Err(); err != nil {
log.Fatalf("Error while reading file: %s", err)
return
}
file.Close()
}
return LocalRuleList
}
func (c *APIClient) GetNodeInfo() (nodeInfo *api.NodeInfo, err error) {
apiPath := "/api/server/config"
reslutJson, err := c.sendRequest(
nil,
"POST",
apiPath,
g.Map{})
if err != nil {
return nil, err
}
if reslutJson.Get("data").String() == "" {
return nil, errors.New("gov2panel node config data is null")
}
if reslutJson.Get("data.port").Int() == 0 {
return nil, errors.New("server port must > 0")
}
nodeInfo = new(api.NodeInfo)
err = reslutJson.Get("data").Scan(nodeInfo)
if err != nil {
return nil, fmt.Errorf("parse node info failed: \nError: %v", err)
}
routes := make([]route, 0)
err = reslutJson.Get("data.routes").Scan(&routes)
if err != nil {
return nil, fmt.Errorf("parse node routes failed: \nError: %v", err)
}
nodeInfo.NodeType = c.NodeType
nodeInfo.NodeID = c.NodeID
nodeInfo.EnableVless = c.EnableVless
nodeInfo.VlessFlow = c.VlessFlow
nodeInfo.AlterID = 0
nodeInfo.NameServerConfig = parseDNSConfig(routes)
return nodeInfo, nil
}
func parseDNSConfig(routes []route) (nameServerList []*conf.NameServerConfig) {
nameServerList = make([]*conf.NameServerConfig, 0)
for i := range routes {
if routes[i].Action == "dns" {
nameServerList = append(nameServerList, &conf.NameServerConfig{
Address: &conf.Address{Address: net.ParseAddress(routes[i].ActionValue)},
Domains: routes[i].Match,
})
}
}
return
}
// GetUserList will pull user form panel
func (c *APIClient) GetUserList() (UserList *[]api.UserInfo, err error) {
apiPath := "/api/server/user"
switch c.NodeType {
case "V2ray", "Trojan", "Shadowsocks", "Vmess", "Vless":
break
default:
return nil, fmt.Errorf("unsupported node type: %s", c.NodeType)
}
reslutJson, err := c.sendRequest(
nil,
"GET",
apiPath,
g.Map{})
if err != nil {
return nil, err
}
var users []*user
reslutJson.Get("data.users").Scan(&users)
userList := make([]api.UserInfo, len(users))
for i := 0; i < len(users); i++ {
u := api.UserInfo{
UID: users[i].Id,
UUID: users[i].Uuid,
}
// Support 1.7.1 speed limit
if c.SpeedLimit > 0 {
u.SpeedLimit = uint64(c.SpeedLimit * 1000000 / 8)
} else {
u.SpeedLimit = uint64(users[i].SpeedLimit * 1000000 / 8)
}
u.DeviceLimit = c.DeviceLimit // todo waiting v2board send configuration
u.Email = u.UUID + "@gov2panel.user"
if c.NodeType == "Shadowsocks" {
u.Passwd = u.UUID
}
userList[i] = u
}
return &userList, nil
}
func (c *APIClient) ReportNodeStatus(nodeStatus *api.NodeStatus) (err error) {
return
}
func (c *APIClient) ReportNodeOnlineUsers(onlineUser *[]api.OnlineUser) (err error) {
return
}
// ReportUserTraffic reports the user traffic
func (c *APIClient) ReportUserTraffic(userTraffic *[]api.UserTraffic) (err error) {
apiPath := "/api/server/push"
reslutJson, err := c.sendRequest(
nil,
"POST",
apiPath,
g.Map{
"data": userTraffic,
})
if err != nil {
return err
}
if reslutJson.Get("code").Int() != 0 {
return errors.New(reslutJson.Get("message").String())
}
return
}
func (c *APIClient) Describe() api.ClientInfo {
return api.ClientInfo{APIHost: c.APIHost, NodeID: c.NodeID, Key: c.Key, NodeType: c.NodeType}
}
// GetNodeRule implements the API interface
func (c *APIClient) GetNodeRule() (*[]api.DetectRule, error) {
ruleList := c.LocalRuleList
apiPath := "/api/server/config"
reslutJson, err := c.sendRequest(
nil,
"POST",
apiPath,
g.Map{})
if err != nil {
return nil, err
}
routes := make([]route, 0)
err = reslutJson.Get("data.routes").Scan(&routes)
if err != nil {
return nil, fmt.Errorf("parse node routes failed: \nError: %v", err)
}
for i := range routes {
if routes[i].Action == "block" {
for _, v := range routes[i].Match {
ruleList = append(ruleList, api.DetectRule{
ID: i,
Pattern: regexp.MustCompile(v),
})
}
}
}
return &ruleList, nil
}
func (c *APIClient) ReportIllegal(detectResultList *[]api.DetectResult) (err error) {
return
}
func (c *APIClient) Debug() {
}
// request 统一请求接口
func (c *APIClient) sendRequest(headerM map[string]string, method string, url string, data g.Map) (reslutJson *gjson.Json, err error) {
url = c.APIHost + url
client := gclient.New()
var gResponse *gclient.Response
if c.Timeout > 0 {
client.SetTimeout(time.Duration(c.Timeout) * time.Second) //方法用于设置当前请求超时时间
} else {
client.SetTimeout(5 * time.Second)
}
client.Retry(3, 10*time.Second) //方法用于设置请求失败时重连次数和重连间隔。
client.SetHeaderMap(headerM)
client.SetHeader("Content-Type", "application/json")
data["token"] = c.Key
data["node_id"] = c.NodeID
switch method {
case "GET":
gResponse, err = client.Get(c.ctx, url, data)
case "POST":
gResponse, err = client.Post(c.ctx, url, data)
default:
err = fmt.Errorf("unsupported method: %s", method)
return
}
if err != nil {
return
}
defer gResponse.Close()
reslutJson = gjson.New(gResponse.ReadAllString())
if reslutJson == nil {
err = fmt.Errorf("http reslut to json, err : %s", gResponse.ReadAllString())
}
if reslutJson.Get("code").Int() != 0 {
err = errors.New(reslutJson.Get("message").String())
return
}
return
}

View File

@ -0,0 +1,83 @@
package gov2panel_test
import (
"testing"
"github.com/XrayR-project/XrayR/api"
"github.com/XrayR-project/XrayR/api/gov2panel"
"github.com/gogf/gf/v2/encoding/gjson"
"github.com/gogf/gf/v2/util/gconv"
)
func CreateClient() api.API {
apiConfig := &api.Config{
APIHost: "http://localhost:8080",
Key: "123456",
NodeID: 90,
NodeType: "V2ray",
}
client := gov2panel.New(apiConfig)
return client
}
func TestGetNodeInfo(t *testing.T) {
client := CreateClient()
nodeInfo, err := client.GetNodeInfo()
if err != nil {
t.Error(err)
}
nodeInfoJson := gjson.New(nodeInfo)
t.Log(nodeInfoJson.String())
t.Log(nodeInfoJson.String())
}
func TestGetUserList(t *testing.T) {
client := CreateClient()
userList, err := client.GetUserList()
if err != nil {
t.Error(err)
}
t.Log(len(*userList))
t.Log(userList)
}
func TestReportReportUserTraffic(t *testing.T) {
client := CreateClient()
userList, err := client.GetUserList()
if err != nil {
t.Error(err)
}
t.Log(userList)
generalUserTraffic := make([]api.UserTraffic, len(*userList))
for i, userInfo := range *userList {
generalUserTraffic[i] = api.UserTraffic{
UID: userInfo.UID,
Upload: 1073741824,
Download: 1073741824,
}
}
t.Log(gconv.String(generalUserTraffic))
client = CreateClient()
err = client.ReportUserTraffic(&generalUserTraffic)
if err != nil {
t.Error(err)
}
t.Error(err)
}
func TestGetNodeRule(t *testing.T) {
client := CreateClient()
client.Debug()
ruleList, err := client.GetNodeRule()
if err != nil {
t.Error(err)
}
t.Log(ruleList)
}

14
api/gov2panel/model.go Normal file
View File

@ -0,0 +1,14 @@
package gov2panel
type user struct {
Id int `json:"id"`
Uuid string `json:"uuid"`
SpeedLimit int `json:"speed_limit"`
}
type route struct {
Id int `json:"id"`
Match []string `json:"match"`
Action string `json:"action"`
ActionValue string `json:"action_value"`
}

View File

@ -31,10 +31,27 @@ type v2ray struct {
Network string `json:"network"`
NetworkSettings struct {
Path string `json:"path"`
Host string `json:"host"`
Headers *json.RawMessage `json:"headers"`
ServiceName string `json:"serviceName"`
Header *json.RawMessage `json:"header"`
} `json:"networkSettings"`
VlessNetworkSettings struct {
Path string `json:"path"`
Host string `json:"host"`
Headers *json.RawMessage `json:"headers"`
ServiceName string `json:"serviceName"`
Header *json.RawMessage `json:"header"`
} `json:"network_settings"`
VlessFlow string `json:"flow"`
VlessTlsSettings struct {
ServerPort string `json:"server_port"`
Dest string `json:"dest"`
xVer uint64 `json:"xver"`
Sni string `json:"server_name"`
PrivateKey string `json:"private_key"`
ShortId string `json:"short_id"`
} `json:"tls_settings"`
Tls int `json:"tls"`
}

View File

@ -5,7 +5,6 @@ import (
"encoding/json"
"errors"
"fmt"
"log"
"os"
"regexp"
"strconv"
@ -13,6 +12,8 @@ import (
"sync/atomic"
"time"
log "github.com/sirupsen/logrus"
"github.com/bitly/go-simplejson"
"github.com/go-resty/resty/v2"
"github.com/xtls/xray-core/common/net"
@ -29,12 +30,12 @@ type APIClient struct {
Key string
NodeType string
EnableVless bool
EnableXTLS bool
VlessFlow string
SpeedLimit float64
DeviceLimit int
LocalRuleList []api.DetectRule
resp atomic.Value
eTag string
eTags map[string]string
}
// New create an api instance
@ -54,10 +55,18 @@ func New(apiConfig *api.Config) *APIClient {
}
})
client.SetBaseURL(apiConfig.APIHost)
var nodeType string
if apiConfig.NodeType == "V2ray" && apiConfig.EnableVless {
nodeType = "vless"
} else {
nodeType = strings.ToLower(apiConfig.NodeType)
}
// Create Key for each requests
client.SetQueryParams(map[string]string{
"node_id": strconv.Itoa(apiConfig.NodeID),
"node_type": strings.ToLower(apiConfig.NodeType),
"node_type": nodeType,
"token": apiConfig.Key,
})
// Read local rule list
@ -69,10 +78,11 @@ func New(apiConfig *api.Config) *APIClient {
APIHost: apiConfig.APIHost,
NodeType: apiConfig.NodeType,
EnableVless: apiConfig.EnableVless,
EnableXTLS: apiConfig.EnableXTLS,
VlessFlow: apiConfig.VlessFlow,
SpeedLimit: apiConfig.SpeedLimit,
DeviceLimit: apiConfig.DeviceLimit,
LocalRuleList: localRuleList,
eTags: make(map[string]string),
}
return apiClient
}
@ -147,9 +157,19 @@ func (c *APIClient) GetNodeInfo() (nodeInfo *api.NodeInfo, err error) {
path := "/api/v1/server/UniProxy/config"
res, err := c.client.R().
SetHeader("If-None-Match", c.eTags["node"]).
ForceContentType("application/json").
Get(path)
// Etag identifier for a specific version of a resource. StatusCode = 304 means no changed
if res.StatusCode() == 304 {
return nil, errors.New(api.NodeNotModified)
}
// update etag
if res.Header().Get("Etag") != "" && res.Header().Get("Etag") != c.eTags["node"] {
c.eTags["node"] = res.Header().Get("Etag")
}
nodeInfoResp, err := c.parseResponse(res, path, err)
if err != nil {
return nil, err
@ -164,7 +184,7 @@ func (c *APIClient) GetNodeInfo() (nodeInfo *api.NodeInfo, err error) {
c.resp.Store(server)
switch c.NodeType {
case "V2ray":
case "V2ray", "Vmess", "Vless":
nodeInfo, err = c.parseV2rayNodeResponse(server)
case "Trojan":
nodeInfo, err = c.parseTrojanNodeResponse(server)
@ -187,24 +207,24 @@ func (c *APIClient) GetUserList() (UserList *[]api.UserInfo, err error) {
path := "/api/v1/server/UniProxy/user"
switch c.NodeType {
case "V2ray", "Trojan", "Shadowsocks":
case "V2ray", "Trojan", "Shadowsocks", "Vmess", "Vless":
break
default:
return nil, fmt.Errorf("unsupported node type: %s", c.NodeType)
}
res, err := c.client.R().
SetHeader("If-None-Match", c.eTag).
SetHeader("If-None-Match", c.eTags["users"]).
ForceContentType("application/json").
Get(path)
// Etag identifier for a specific version of a resource. StatusCode = 304 means no changed
if res.StatusCode() == 304 {
return nil, errors.New("users no change")
return nil, errors.New(api.UserNotModified)
}
// update etag
if res.Header().Get("Etag") != "" && res.Header().Get("Etag") != c.eTag {
c.eTag = res.Header().Get("Etag")
if res.Header().Get("Etag") != "" && res.Header().Get("Etag") != c.eTags["users"] {
c.eTags["users"] = res.Header().Get("Etag")
}
usersResp, err := c.parseResponse(res, path, err)
@ -213,6 +233,9 @@ func (c *APIClient) GetUserList() (UserList *[]api.UserInfo, err error) {
}
b, _ := usersResp.Get("users").Encode()
json.Unmarshal(b, &users)
if len(users) == 0 {
return nil, errors.New("users is null")
}
userList := make([]api.UserInfo, len(users))
for i := 0; i < len(users); i++ {
@ -293,11 +316,6 @@ func (c *APIClient) ReportIllegal(detectResultList *[]api.DetectResult) error {
// parseTrojanNodeResponse parse the response for the given nodeInfo format
func (c *APIClient) parseTrojanNodeResponse(s *serverConfig) (*api.NodeInfo, error) {
var TLSType = "tls"
if c.EnableXTLS {
TLSType = "xtls"
}
// Create GeneralNodeInfo
nodeInfo := &api.NodeInfo{
NodeType: c.NodeType,
@ -305,7 +323,6 @@ func (c *APIClient) parseTrojanNodeResponse(s *serverConfig) (*api.NodeInfo, err
Port: uint32(s.ServerPort),
TransportProtocol: "tcp",
EnableTLS: true,
TLSType: TLSType,
Host: s.Host,
ServiceName: s.ServerName,
NameServerConfig: s.parseDNSConfig(),
@ -347,14 +364,35 @@ func (c *APIClient) parseSSNodeResponse(s *serverConfig) (*api.NodeInfo, error)
// parseV2rayNodeResponse parse the response for the given nodeInfo format
func (c *APIClient) parseV2rayNodeResponse(s *serverConfig) (*api.NodeInfo, error) {
var (
TLSType = "tls"
host string
header json.RawMessage
enableTLS bool
host string
header json.RawMessage
enableTLS bool
enableREALITY bool
dest string
xVer uint64
)
if c.EnableXTLS {
TLSType = "xtls"
if s.VlessTlsSettings.Dest != "" {
dest = s.VlessTlsSettings.Dest
} else {
dest = s.VlessTlsSettings.Sni
}
if s.VlessTlsSettings.xVer != 0 {
xVer = s.VlessTlsSettings.xVer
} else {
xVer = 0
}
realityConfig := api.REALITYConfig{
Dest: dest + ":" + s.VlessTlsSettings.ServerPort,
ProxyProtocolVer: xVer,
ServerNames: []string{s.VlessTlsSettings.Sni},
PrivateKey: s.VlessTlsSettings.PrivateKey,
ShortIds: []string{s.VlessTlsSettings.ShortId},
}
if c.EnableVless {
s.NetworkSettings = s.VlessNetworkSettings
}
switch s.Network {
@ -375,10 +413,30 @@ func (c *APIClient) parseV2rayNodeResponse(s *serverConfig) (*api.NodeInfo, erro
header = httpHeader
}
}
case "httpupgrade", "splithttp":
if s.NetworkSettings.Headers != nil {
if httpHeaders, err := s.NetworkSettings.Headers.MarshalJSON(); err != nil {
return nil, err
} else {
b, _ := simplejson.NewJson(httpHeaders)
host = b.Get("Host").MustString()
}
}
if s.NetworkSettings.Host != "" {
host = s.NetworkSettings.Host
}
}
if s.Tls == 1 {
switch s.Tls {
case 0:
enableTLS = false
enableREALITY = false
case 1:
enableTLS = true
enableREALITY = false
case 2:
enableTLS = true
enableREALITY = true
}
// Create GeneralNodeInfo
@ -389,12 +447,14 @@ func (c *APIClient) parseV2rayNodeResponse(s *serverConfig) (*api.NodeInfo, erro
AlterID: 0,
TransportProtocol: s.Network,
EnableTLS: enableTLS,
TLSType: TLSType,
Path: s.NetworkSettings.Path,
Host: host,
EnableVless: c.EnableVless,
VlessFlow: s.VlessFlow,
ServiceName: s.NetworkSettings.ServiceName,
Header: header,
EnableREALITY: enableREALITY,
REALITYConfig: &realityConfig,
NameServerConfig: s.parseDNSConfig(),
}, nil
}

View File

@ -4,13 +4,14 @@ import (
"bufio"
"encoding/json"
"fmt"
"log"
"os"
"reflect"
"regexp"
"strconv"
"time"
log "github.com/sirupsen/logrus"
"github.com/go-resty/resty/v2"
"github.com/XrayR-project/XrayR/api"
@ -24,7 +25,7 @@ type APIClient struct {
Key string
NodeType string
EnableVless bool
EnableXTLS bool
VlessFlow string
SpeedLimit float64
DeviceLimit int
LocalRuleList []api.DetectRule
@ -61,7 +62,7 @@ func New(apiConfig *api.Config) *APIClient {
APIHost: apiConfig.APIHost,
NodeType: apiConfig.NodeType,
EnableVless: apiConfig.EnableVless,
EnableXTLS: apiConfig.EnableXTLS,
VlessFlow: apiConfig.VlessFlow,
SpeedLimit: apiConfig.SpeedLimit,
DeviceLimit: apiConfig.DeviceLimit,
LocalRuleList: localRuleList,
@ -359,8 +360,8 @@ func (c *APIClient) ReportIllegal(detectResultList *[]api.DetectResult) error {
// ParseV2rayNodeResponse parse the response for the given nodeinfor format
func (c *APIClient) ParseV2rayNodeResponse(nodeInfoResponse *NodeInfoResponse) (*api.NodeInfo, error) {
var enableTLS bool
var path, host, TLStype, transportProtocol, serviceName string
var speedlimit uint64 = 0
var path, host, transportProtocol, serviceName string
var speedLimit uint64 = 0
port := nodeInfoResponse.Port
alterID := nodeInfoResponse.AlterId
@ -376,34 +377,29 @@ func (c *APIClient) ParseV2rayNodeResponse(nodeInfoResponse *NodeInfoResponse) (
}
// Compatible with more node types config
switch nodeInfoResponse.Security {
case "tls", "xtls":
if c.EnableXTLS {
TLStype = "xtls"
} else {
TLStype = "tls"
}
case "tls":
enableTLS = true
default:
enableTLS = false
}
if c.SpeedLimit > 0 {
speedlimit = uint64((c.SpeedLimit * 1000000) / 8)
speedLimit = uint64((c.SpeedLimit * 1000000) / 8)
} else {
speedlimit = uint64((nodeInfoResponse.SpeedLimit * 1000000) / 8)
speedLimit = uint64((nodeInfoResponse.SpeedLimit * 1000000) / 8)
}
// Create GeneralNodeInfo
nodeinfo := &api.NodeInfo{
NodeType: c.NodeType,
NodeID: c.NodeID,
Port: port,
SpeedLimit: speedlimit,
SpeedLimit: speedLimit,
AlterID: alterID,
TransportProtocol: transportProtocol,
EnableTLS: enableTLS,
TLSType: TLStype,
Path: path,
Host: host,
EnableVless: c.EnableVless,
VlessFlow: c.VlessFlow,
ServiceName: serviceName,
}
@ -412,38 +408,33 @@ func (c *APIClient) ParseV2rayNodeResponse(nodeInfoResponse *NodeInfoResponse) (
// ParseSSNodeResponse parse the response for the given nodeinfor format
func (c *APIClient) ParseSSNodeResponse(nodeInfoResponse *NodeInfoResponse) (*api.NodeInfo, error) {
var speedlimit uint64 = 0
var speedLimit uint64 = 0
if c.SpeedLimit > 0 {
speedlimit = uint64((c.SpeedLimit * 1000000) / 8)
speedLimit = uint64((c.SpeedLimit * 1000000) / 8)
} else {
speedlimit = uint64((nodeInfoResponse.SpeedLimit * 1000000) / 8)
speedLimit = uint64((nodeInfoResponse.SpeedLimit * 1000000) / 8)
}
// Create GeneralNodeInfo
nodeinfo := &api.NodeInfo{
nodeInfo := &api.NodeInfo{
NodeType: c.NodeType,
NodeID: c.NodeID,
Port: nodeInfoResponse.Port,
SpeedLimit: speedlimit,
SpeedLimit: speedLimit,
TransportProtocol: "tcp",
CypherMethod: nodeInfoResponse.Method,
}
return nodeinfo, nil
return nodeInfo, nil
}
// ParseTrojanNodeResponse parse the response for the given nodeinfor format
func (c *APIClient) ParseTrojanNodeResponse(nodeInfoResponse *NodeInfoResponse) (*api.NodeInfo, error) {
// 域名或IP;port=连接端口#偏移端口|host=xx
// gz.aaa.com;port=443#12345|host=hk.aaa.com
var TLSType, host string
var host string
var transportProtocol = "tcp"
var speedlimit uint64 = 0
if c.EnableXTLS {
TLSType = "xtls"
} else {
TLSType = "tls"
}
host = nodeInfoResponse.Host
port := nodeInfoResponse.Port
@ -456,25 +447,24 @@ func (c *APIClient) ParseTrojanNodeResponse(nodeInfoResponse *NodeInfoResponse)
transportProtocol = "grpc"
}
// Create GeneralNodeInfo
nodeinfo := &api.NodeInfo{
nodeInfo := &api.NodeInfo{
NodeType: c.NodeType,
NodeID: c.NodeID,
Port: port,
SpeedLimit: speedlimit,
TransportProtocol: transportProtocol,
EnableTLS: true,
TLSType: TLSType,
Host: host,
ServiceName: nodeInfoResponse.Sni,
}
return nodeinfo, nil
return nodeInfo, nil
}
// ParseUserListResponse parse the response for the given nodeinfo format
func (c *APIClient) ParseUserListResponse(userInfoResponse *[]UserResponse) (*[]api.UserInfo, error) {
var deviceLimit int = 0
var speedlimit uint64 = 0
var deviceLimit = 0
var speedLimit uint64 = 0
userList := make([]api.UserInfo, len(*userInfoResponse))
for i, user := range *userInfoResponse {
if c.DeviceLimit > 0 {
@ -483,15 +473,15 @@ func (c *APIClient) ParseUserListResponse(userInfoResponse *[]UserResponse) (*[]
deviceLimit = user.DeviceLimit
}
if c.SpeedLimit > 0 {
speedlimit = uint64((c.SpeedLimit * 1000000) / 8)
speedLimit = uint64((c.SpeedLimit * 1000000) / 8)
} else {
speedlimit = uint64((user.SpeedLimit * 1000000) / 8)
speedLimit = uint64((user.SpeedLimit * 1000000) / 8)
}
userList[i] = api.UserInfo{
UID: user.ID,
Passwd: user.Passwd,
UUID: user.Passwd,
SpeedLimit: speedlimit,
SpeedLimit: speedLimit,
DeviceLimit: deviceLimit,
}
}

View File

@ -4,13 +4,14 @@ import (
"bufio"
"encoding/json"
"fmt"
"log"
"os"
"reflect"
"regexp"
"strconv"
"time"
log "github.com/sirupsen/logrus"
"github.com/go-resty/resty/v2"
"github.com/XrayR-project/XrayR/api"
@ -24,7 +25,7 @@ type APIClient struct {
Key string
NodeType string
EnableVless bool
EnableXTLS bool
VlessFlow string
SpeedLimit float64
DeviceLimit int
LocalRuleList []api.DetectRule
@ -57,7 +58,7 @@ func New(apiConfig *api.Config) *APIClient {
APIHost: apiConfig.APIHost,
NodeType: apiConfig.NodeType,
EnableVless: apiConfig.EnableVless,
EnableXTLS: apiConfig.EnableXTLS,
VlessFlow: apiConfig.VlessFlow,
SpeedLimit: apiConfig.SpeedLimit,
DeviceLimit: apiConfig.DeviceLimit,
LocalRuleList: localRuleList,
@ -144,7 +145,7 @@ func (c *APIClient) parseResponse(res *resty.Response, path string, err error) (
func (c *APIClient) GetNodeInfo() (nodeInfo *api.NodeInfo, err error) {
var path string
switch c.NodeType {
case "V2ray":
case "V2ray", "Vmess", "Vless":
path = fmt.Sprintf("/api/v2ray/v1/node/%d", c.NodeID)
case "Trojan":
path = fmt.Sprintf("/api/trojan/v1/node/%d", c.NodeID)
@ -165,7 +166,7 @@ func (c *APIClient) GetNodeInfo() (nodeInfo *api.NodeInfo, err error) {
}
switch c.NodeType {
case "V2ray":
case "V2ray", "Vmess", "Vless":
nodeInfo, err = c.ParseV2rayNodeResponse(&response.Data)
case "Trojan":
nodeInfo, err = c.ParseTrojanNodeResponse(&response.Data)
@ -177,7 +178,7 @@ func (c *APIClient) GetNodeInfo() (nodeInfo *api.NodeInfo, err error) {
if err != nil {
res, _ := json.Marshal(response.Data)
return nil, fmt.Errorf("Parse node info failed: %s, \nError: %s", string(res), err)
return nil, fmt.Errorf("parse node info failed: %s, \nError: %s", string(res), err)
}
return nodeInfo, nil
@ -187,7 +188,7 @@ func (c *APIClient) GetNodeInfo() (nodeInfo *api.NodeInfo, err error) {
func (c *APIClient) GetUserList() (UserList *[]api.UserInfo, err error) {
var path string
switch c.NodeType {
case "V2ray":
case "V2ray", "Vmess", "Vless":
path = fmt.Sprintf("/api/v2ray/v1/userList/%d", c.NodeID)
case "Trojan":
path = fmt.Sprintf("/api/trojan/v1/userList/%d", c.NodeID)
@ -208,7 +209,7 @@ func (c *APIClient) GetUserList() (UserList *[]api.UserInfo, err error) {
}
userList := new([]api.UserInfo)
switch c.NodeType {
case "V2ray":
case "V2ray", "Vmess", "Vless":
userList, err = c.ParseV2rayUserListResponse(&response.Data)
case "Trojan":
userList, err = c.ParseTrojanUserListResponse(&response.Data)
@ -228,7 +229,7 @@ func (c *APIClient) GetUserList() (UserList *[]api.UserInfo, err error) {
func (c *APIClient) ReportNodeStatus(nodeStatus *api.NodeStatus) (err error) {
var path string
switch c.NodeType {
case "V2ray":
case "V2ray", "Vmess", "Vless":
path = fmt.Sprintf("/api/v2ray/v1/nodeStatus/%d", c.NodeID)
case "Trojan":
path = fmt.Sprintf("/api/trojan/v1/nodeStatus/%d", c.NodeID)
@ -264,7 +265,7 @@ func (c *APIClient) ReportNodeOnlineUsers(onlineUserList *[]api.OnlineUser) erro
var path string
switch c.NodeType {
case "V2ray":
case "V2ray", "Vmess", "Vless":
path = fmt.Sprintf("/api/v2ray/v1/nodeOnline/%d", c.NodeID)
case "Trojan":
path = fmt.Sprintf("/api/trojan/v1/nodeOnline/%d", c.NodeID)
@ -297,7 +298,7 @@ func (c *APIClient) ReportNodeOnlineUsers(onlineUserList *[]api.OnlineUser) erro
func (c *APIClient) ReportUserTraffic(userTraffic *[]api.UserTraffic) error {
var path string
switch c.NodeType {
case "V2ray":
case "V2ray", "Vmess", "Vless":
path = fmt.Sprintf("/api/v2ray/v1/userTraffic/%d", c.NodeID)
case "Trojan":
path = fmt.Sprintf("/api/trojan/v1/userTraffic/%d", c.NodeID)
@ -332,7 +333,7 @@ func (c *APIClient) ReportUserTraffic(userTraffic *[]api.UserTraffic) error {
func (c *APIClient) GetNodeRule() (*[]api.DetectRule, error) {
var path string
switch c.NodeType {
case "V2ray":
case "V2ray", "Vmess", "Vless":
path = fmt.Sprintf("/api/v2ray/v1/nodeRule/%d", c.NodeID)
case "Trojan":
path = fmt.Sprintf("/api/trojan/v1/nodeRule/%d", c.NodeID)
@ -380,7 +381,7 @@ func (c *APIClient) GetNodeRule() (*[]api.DetectRule, error) {
func (c *APIClient) ReportIllegal(detectResultList *[]api.DetectResult) error {
var path string
switch c.NodeType {
case "V2ray":
case "V2ray", "Vmess", "Vless":
path = fmt.Sprintf("/api/v2ray/v1/trigger/%d", c.NodeID)
case "Trojan":
path = fmt.Sprintf("/api/trojan/v1/trigger/%d", c.NodeID)
@ -412,13 +413,7 @@ func (c *APIClient) ReportIllegal(detectResultList *[]api.DetectResult) error {
// ParseV2rayNodeResponse parse the response for the given nodeinfor format
func (c *APIClient) ParseV2rayNodeResponse(nodeInfoResponse *json.RawMessage) (*api.NodeInfo, error) {
var TLStype string
var speedlimit uint64 = 0
if c.EnableXTLS {
TLStype = "xtls"
} else {
TLStype = "tls"
}
var speedLimit uint64 = 0
v2rayNodeInfo := new(V2rayNodeInfo)
if err := json.Unmarshal(*nodeInfoResponse, v2rayNodeInfo); err != nil {
@ -426,9 +421,9 @@ func (c *APIClient) ParseV2rayNodeResponse(nodeInfoResponse *json.RawMessage) (*
}
if c.SpeedLimit > 0 {
speedlimit = uint64((c.SpeedLimit * 1000000) / 8)
speedLimit = uint64((c.SpeedLimit * 1000000) / 8)
} else {
speedlimit = uint64((v2rayNodeInfo.SpeedLimit * 1000000) / 8)
speedLimit = (v2rayNodeInfo.SpeedLimit * 1000000) / 8
}
if c.DeviceLimit == 0 && v2rayNodeInfo.ClientLimit > 0 {
@ -436,72 +431,65 @@ func (c *APIClient) ParseV2rayNodeResponse(nodeInfoResponse *json.RawMessage) (*
}
// Create GeneralNodeInfo
nodeinfo := &api.NodeInfo{
nodeInfo := &api.NodeInfo{
NodeType: c.NodeType,
NodeID: c.NodeID,
Port: v2rayNodeInfo.V2Port,
SpeedLimit: speedlimit,
SpeedLimit: speedLimit,
AlterID: v2rayNodeInfo.V2AlterID,
TransportProtocol: v2rayNodeInfo.V2Net,
FakeType: v2rayNodeInfo.V2Type,
EnableTLS: v2rayNodeInfo.V2TLS,
TLSType: TLStype,
Path: v2rayNodeInfo.V2Path,
Host: v2rayNodeInfo.V2Host,
EnableVless: c.EnableVless,
VlessFlow: c.VlessFlow,
}
return nodeinfo, nil
return nodeInfo, nil
}
// ParseSSNodeResponse parse the response for the given nodeinfor format
func (c *APIClient) ParseSSNodeResponse(nodeInfoResponse *json.RawMessage) (*api.NodeInfo, error) {
var speedlimit uint64 = 0
var speedLimit uint64 = 0
shadowsocksNodeInfo := new(ShadowsocksNodeInfo)
if err := json.Unmarshal(*nodeInfoResponse, shadowsocksNodeInfo); err != nil {
return nil, fmt.Errorf("unmarshal %s failed: %s", reflect.TypeOf(*nodeInfoResponse), err)
}
if c.SpeedLimit > 0 {
speedlimit = uint64((c.SpeedLimit * 1000000) / 8)
speedLimit = uint64((c.SpeedLimit * 1000000) / 8)
} else {
speedlimit = uint64((shadowsocksNodeInfo.SpeedLimit * 1000000) / 8)
speedLimit = uint64((shadowsocksNodeInfo.SpeedLimit * 1000000) / 8)
}
if c.DeviceLimit == 0 && shadowsocksNodeInfo.ClientLimit > 0 {
c.DeviceLimit = shadowsocksNodeInfo.ClientLimit
}
// Create GeneralNodeInfo
nodeinfo := &api.NodeInfo{
nodeInfo := &api.NodeInfo{
NodeType: c.NodeType,
NodeID: c.NodeID,
Port: shadowsocksNodeInfo.Port,
SpeedLimit: speedlimit,
SpeedLimit: speedLimit,
TransportProtocol: "tcp",
CypherMethod: shadowsocksNodeInfo.Method,
}
return nodeinfo, nil
return nodeInfo, nil
}
// ParseTrojanNodeResponse parse the response for the given nodeinfor format
func (c *APIClient) ParseTrojanNodeResponse(nodeInfoResponse *json.RawMessage) (*api.NodeInfo, error) {
var TLSType string
var speedlimit uint64 = 0
if c.EnableXTLS {
TLSType = "xtls"
} else {
TLSType = "tls"
}
var speedLimit uint64 = 0
trojanNodeInfo := new(TrojanNodeInfo)
if err := json.Unmarshal(*nodeInfoResponse, trojanNodeInfo); err != nil {
return nil, fmt.Errorf("unmarshal %s failed: %s", reflect.TypeOf(*nodeInfoResponse), err)
}
if c.SpeedLimit > 0 {
speedlimit = uint64((c.SpeedLimit * 1000000) / 8)
speedLimit = uint64((c.SpeedLimit * 1000000) / 8)
} else {
speedlimit = uint64((trojanNodeInfo.SpeedLimit * 1000000) / 8)
speedLimit = (trojanNodeInfo.SpeedLimit * 1000000) / 8
}
if c.DeviceLimit == 0 && trojanNodeInfo.ClientLimit > 0 {
@ -509,22 +497,21 @@ func (c *APIClient) ParseTrojanNodeResponse(nodeInfoResponse *json.RawMessage) (
}
// Create GeneralNodeInfo
nodeinfo := &api.NodeInfo{
nodeInfo := &api.NodeInfo{
NodeType: c.NodeType,
NodeID: c.NodeID,
Port: trojanNodeInfo.TrojanPort,
SpeedLimit: speedlimit,
SpeedLimit: speedLimit,
TransportProtocol: "tcp",
EnableTLS: true,
TLSType: TLSType,
}
return nodeinfo, nil
return nodeInfo, nil
}
// ParseV2rayUserListResponse parse the response for the given userinfo format
func (c *APIClient) ParseV2rayUserListResponse(userInfoResponse *json.RawMessage) (*[]api.UserInfo, error) {
var speedlimit uint64 = 0
var speedLimit uint64 = 0
vmessUserList := new([]*VMessUser)
if err := json.Unmarshal(*userInfoResponse, vmessUserList); err != nil {
@ -534,16 +521,16 @@ func (c *APIClient) ParseV2rayUserListResponse(userInfoResponse *json.RawMessage
userList := make([]api.UserInfo, len(*vmessUserList))
for i, user := range *vmessUserList {
if c.SpeedLimit > 0 {
speedlimit = uint64((c.SpeedLimit * 1000000) / 8)
speedLimit = uint64((c.SpeedLimit * 1000000) / 8)
} else {
speedlimit = uint64((user.SpeedLimit * 1000000) / 8)
speedLimit = (user.SpeedLimit * 1000000) / 8
}
userList[i] = api.UserInfo{
UID: user.UID,
Email: "",
UUID: user.VmessUID,
DeviceLimit: c.DeviceLimit,
SpeedLimit: speedlimit,
SpeedLimit: speedLimit,
}
}
@ -552,7 +539,7 @@ func (c *APIClient) ParseV2rayUserListResponse(userInfoResponse *json.RawMessage
// ParseTrojanUserListResponse parse the response for the given userinfo format
func (c *APIClient) ParseTrojanUserListResponse(userInfoResponse *json.RawMessage) (*[]api.UserInfo, error) {
var speedlimit uint64 = 0
var speedLimit uint64 = 0
trojanUserList := new([]*TrojanUser)
if err := json.Unmarshal(*userInfoResponse, trojanUserList); err != nil {
@ -562,16 +549,16 @@ func (c *APIClient) ParseTrojanUserListResponse(userInfoResponse *json.RawMessag
userList := make([]api.UserInfo, len(*trojanUserList))
for i, user := range *trojanUserList {
if c.SpeedLimit > 0 {
speedlimit = uint64((c.SpeedLimit * 1000000) / 8)
speedLimit = uint64((c.SpeedLimit * 1000000) / 8)
} else {
speedlimit = (user.SpeedLimit * 1000000) / 8
speedLimit = (user.SpeedLimit * 1000000) / 8
}
userList[i] = api.UserInfo{
UID: user.UID,
Email: "",
UUID: user.Password,
DeviceLimit: c.DeviceLimit,
SpeedLimit: speedlimit,
SpeedLimit: speedLimit,
}
}
@ -580,7 +567,7 @@ func (c *APIClient) ParseTrojanUserListResponse(userInfoResponse *json.RawMessag
// ParseSSUserListResponse parse the response for the given userinfo format
func (c *APIClient) ParseSSUserListResponse(userInfoResponse *json.RawMessage) (*[]api.UserInfo, error) {
var speedlimit uint64 = 0
var speedLimit uint64 = 0
ssUserList := new([]*SSUser)
if err := json.Unmarshal(*userInfoResponse, ssUserList); err != nil {
@ -590,16 +577,16 @@ func (c *APIClient) ParseSSUserListResponse(userInfoResponse *json.RawMessage) (
userList := make([]api.UserInfo, len(*ssUserList))
for i, user := range *ssUserList {
if c.SpeedLimit > 0 {
speedlimit = uint64((c.SpeedLimit * 1000000) / 8)
speedLimit = uint64((c.SpeedLimit * 1000000) / 8)
} else {
speedlimit = uint64(user.SpeedLimit * 1000000 / 8)
speedLimit = uint64(user.SpeedLimit * 1000000 / 8)
}
userList[i] = api.UserInfo{
UID: user.UID,
Email: "",
Passwd: user.Password,
DeviceLimit: c.DeviceLimit,
SpeedLimit: speedlimit,
SpeedLimit: speedLimit,
}
}

View File

@ -154,8 +154,8 @@ func TestReportIllegal(t *testing.T) {
client := CreateClient()
detectResult := []api.DetectResult{
{1, 1},
{1, 2},
{UID: 1, RuleID: 1},
{UID: 1, RuleID: 2},
}
client.Debug()
err := client.ReportIllegal(&detectResult)

View File

@ -8,7 +8,6 @@ type NodeInfoResponse struct {
Class int `json:"node_class"`
SpeedLimit float64 `json:"node_speedlimit"`
TrafficRate float64 `json:"traffic_rate"`
MuOnly int `json:"mu_only"`
Sort int `json:"sort"`
RawServerString string `json:"server"`
Type string `json:"type"`
@ -17,51 +16,35 @@ type NodeInfoResponse struct {
}
type CustomConfig struct {
OffsetPortUser string `json:"offset_port_user"`
OffsetPortNode string `json:"offset_port_node"`
ServerSub string `json:"server_sub"`
Host string `json:"host"`
MuPort string `json:"mu_port"`
MuEncryption string `json:"mu_encryption"`
MuProtocol string `json:"mu_protocol"`
MuObfs string `json:"mu_obfs"`
MuSuffix string `json:"mu_suffix"`
V2Port string `json:"v2_port"`
Method string `json:"method"`
TLS string `json:"tls"`
EnableVless string `json:"enable_vless"`
AlterID string `json:"alter_id"`
Network string `json:"network"`
Security string `json:"security"`
Path string `json:"path"`
VerifyCert bool `json:"verify_cert"`
Obfs string `json:"obfs"`
Header json.RawMessage `json:"header"`
TrojanPort string `json:"trojan_port"`
AllowInsecure string `json:"allow_insecure"`
Grpc string `json:"grpc"`
Servicename string `json:"servicename"`
EnableXtls string `json:"enable_xtls"`
Flow string `json:"flow"`
EnableREALITY bool `json:"enable_reality"`
RealityOpts *REALITYConfig `json:"reality-opts"`
}
// UserResponse is the response of user
type UserResponse struct {
ID int `json:"id"`
Email string `json:"email"`
Passwd string `json:"passwd"`
Port uint32 `json:"port"`
Method string `json:"method"`
SpeedLimit float64 `json:"node_speedlimit"`
DeviceLimit int `json:"node_connector"`
Protocol string `json:"protocol"`
ProtocolParam string `json:"protocol_param"`
Obfs string `json:"obfs"`
ObfsParam string `json:"obfs_param"`
ForbiddenIP string `json:"forbidden_ip"`
ForbiddenPort string `json:"forbidden_port"`
UUID string `json:"uuid"`
MultiUser int `json:"is_multi_user"`
AliveIP int `json:"alive_ip"`
ID int `json:"id"`
Passwd string `json:"passwd"`
Port uint32 `json:"port"`
Method string `json:"method"`
SpeedLimit float64 `json:"node_speedlimit"`
DeviceLimit int `json:"node_iplimit"`
UUID string `json:"uuid"`
AliveIP int `json:"alive_ip"`
}
// Response is the common response
@ -75,7 +58,7 @@ type PostData struct {
Data interface{} `json:"data"`
}
// SystemLoad is the data structure of systemload
// SystemLoad is the data structure of system load
type SystemLoad struct {
Uptime string `json:"uptime"`
Load string `json:"load"`
@ -103,3 +86,14 @@ type IllegalItem struct {
ID int `json:"list_id"`
UID int `json:"user_id"`
}
type REALITYConfig struct {
Dest string `json:"dest,omitempty"`
ProxyProtocolVer uint64 `json:"proxy_protocol_ver,omitempty"`
ServerNames []string `json:"server_names,omitempty"`
PrivateKey string `json:"private_key,omitempty"`
MinClientVer string `json:"min_client_ver,omitempty"`
MaxClientVer string `json:"max_client_ver,omitempty"`
MaxTimeDiff uint64 `json:"max_time_diff,omitempty"`
ShortIds []string `json:"short_ids,omitempty"`
}

View File

@ -3,8 +3,8 @@ package sspanel
import (
"bufio"
"encoding/json"
"errors"
"fmt"
"log"
"os"
"reflect"
"regexp"
@ -13,6 +13,8 @@ import (
"sync"
"time"
log "github.com/sirupsen/logrus"
"github.com/go-resty/resty/v2"
"github.com/XrayR-project/XrayR/api"
@ -32,19 +34,21 @@ type APIClient struct {
Key string
NodeType string
EnableVless bool
EnableXTLS bool
VlessFlow string
SpeedLimit float64
DeviceLimit int
DisableCustomConfig bool
LocalRuleList []api.DetectRule
LastReportOnline map[int]int
access sync.Mutex
version string
eTags map[string]string
}
// New creat a api instance
// New create api instance
func New(apiConfig *api.Config) *APIClient {
client := resty.New()
client.SetRetryCount(3)
if apiConfig.Timeout > 0 {
client.SetTimeout(time.Duration(apiConfig.Timeout) * time.Second)
@ -52,12 +56,14 @@ func New(apiConfig *api.Config) *APIClient {
client.SetTimeout(5 * time.Second)
}
client.OnError(func(req *resty.Request, err error) {
if v, ok := err.(*resty.ResponseError); ok {
var v *resty.ResponseError
if errors.As(err, &v) {
// v.Response contains the last response from the server
// v.Err contains the original error
log.Print(v.Err)
}
})
client.SetBaseURL(apiConfig.APIHost)
// Create Key for each requests
client.SetQueryParam("key", apiConfig.Key)
@ -73,23 +79,29 @@ func New(apiConfig *api.Config) *APIClient {
APIHost: apiConfig.APIHost,
NodeType: apiConfig.NodeType,
EnableVless: apiConfig.EnableVless,
EnableXTLS: apiConfig.EnableXTLS,
VlessFlow: apiConfig.VlessFlow,
SpeedLimit: apiConfig.SpeedLimit,
DeviceLimit: apiConfig.DeviceLimit,
LocalRuleList: localRuleList,
DisableCustomConfig: apiConfig.DisableCustomConfig,
LastReportOnline: make(map[int]int),
eTags: make(map[string]string),
}
}
// readLocalRuleList reads the local rule list file
func readLocalRuleList(path string) (LocalRuleList []api.DetectRule) {
LocalRuleList = make([]api.DetectRule, 0)
if path != "" {
// open the file
file, err := os.Open(path)
defer func(file *os.File) {
err := file.Close()
if err != nil {
log.Printf("Error when closing file: %s", err)
}
}(file)
// handle errors while opening
if err != nil {
log.Printf("Error when opening file: %s", err)
@ -110,8 +122,6 @@ func readLocalRuleList(path string) (LocalRuleList []api.DetectRule) {
log.Fatalf("Error while reading file: %s", err)
return
}
file.Close()
}
return LocalRuleList
@ -138,7 +148,7 @@ func (c *APIClient) parseResponse(res *resty.Response, path string, err error) (
if res.StatusCode() > 400 {
body := res.Body()
return nil, fmt.Errorf("request %s failed: %s, %s", c.assembleURL(path), string(body), err)
return nil, fmt.Errorf("request %s failed: %s, %v", c.assembleURL(path), string(body), err)
}
response := res.Result().(*Response)
@ -149,13 +159,22 @@ func (c *APIClient) parseResponse(res *resty.Response, path string, err error) (
return response, nil
}
// GetNodeInfo will pull NodeInfo Config from sspanel
// GetNodeInfo will pull NodeInfo Config from ssPanel
func (c *APIClient) GetNodeInfo() (nodeInfo *api.NodeInfo, err error) {
path := fmt.Sprintf("/mod_mu/nodes/%d/info", c.NodeID)
res, err := c.client.R().
SetResult(&Response{}).
SetHeader("If-None-Match", c.eTags["node"]).
ForceContentType("application/json").
Get(path)
// Etag identifier for a specific version of a resource. StatusCode = 304 means no changed
if res.StatusCode() == 304 {
return nil, errors.New(api.NodeNotModified)
}
if res.Header().Get("ETag") != "" && res.Header().Get("ETag") != c.eTags["node"] {
c.eTags["node"] = res.Header().Get("ETag")
}
response, err := c.parseResponse(res, path, err)
if err != nil {
@ -168,25 +187,18 @@ func (c *APIClient) GetNodeInfo() (nodeInfo *api.NodeInfo, err error) {
return nil, fmt.Errorf("unmarshal %s failed: %s", reflect.TypeOf(nodeInfoResponse), err)
}
// New sspanel API
disableCustomConfig := c.DisableCustomConfig
if nodeInfoResponse.Version != "" && !disableCustomConfig {
// Check if custom_config is empty
if configString, err := json.Marshal(nodeInfoResponse.CustomConfig); err != nil || string(configString) == "[]" {
log.Printf("custom_config is empty! take config from address now.")
disableCustomConfig = true
}
} else {
disableCustomConfig = true
// determine ssPanel version, if disable custom config or version < 2021.11, then use old api
c.version = nodeInfoResponse.Version
var isExpired bool
if compareVersion(c.version, "2021.11") == -1 {
isExpired = true
}
if !disableCustomConfig {
nodeInfo, err = c.ParseSSPanelNodeInfo(nodeInfoResponse)
if err != nil {
res, _ := json.Marshal(nodeInfoResponse)
return nil, fmt.Errorf("Parse node info failed: %s, \nError: %s, \nPlease check the doc of custom_config for help: https://xrayr-project.github.io/XrayR-doc/dui-jie-sspanel/sspanel/sspanel_custom_config", string(res), err)
if c.DisableCustomConfig || isExpired {
if isExpired {
log.Print("The panel version is expired, it is recommended to update immediately")
}
} else {
switch c.NodeType {
case "V2ray":
nodeInfo, err = c.ParseV2rayNodeResponse(nodeInfoResponse)
@ -199,24 +211,39 @@ func (c *APIClient) GetNodeInfo() (nodeInfo *api.NodeInfo, err error) {
default:
return nil, fmt.Errorf("unsupported Node type: %s", c.NodeType)
}
} else {
nodeInfo, err = c.ParseSSPanelNodeInfo(nodeInfoResponse)
if err != nil {
res, _ := json.Marshal(nodeInfoResponse)
return nil, fmt.Errorf("parse node info failed: %s, \nError: %s, \nPlease check the doc of custom_config for help: https://xrayr-project.github.io/XrayR-doc/dui-jie-sspanel/sspanel/sspanel_custom_config", string(res), err)
}
}
if err != nil {
res, _ := json.Marshal(nodeInfoResponse)
return nil, fmt.Errorf("Parse node info failed: %s, \nError: %s", string(res), err)
return nil, fmt.Errorf("parse node info failed: %s, \nError: %s", string(res), err)
}
return nodeInfo, nil
}
// GetUserList will pull user form sspanel
// GetUserList will pull user form ssPanel
func (c *APIClient) GetUserList() (UserList *[]api.UserInfo, err error) {
path := "/mod_mu/users"
res, err := c.client.R().
SetQueryParam("node_id", strconv.Itoa(c.NodeID)).
SetHeader("If-None-Match", c.eTags["users"]).
SetResult(&Response{}).
ForceContentType("application/json").
Get(path)
// Etag identifier for a specific version of a resource. StatusCode = 304 means no changed
if res.StatusCode() == 304 {
return nil, errors.New(api.UserNotModified)
}
if res.Header().Get("ETag") != "" && res.Header().Get("ETag") != c.eTags["users"] {
c.eTags["users"] = res.Header().Get("ETag")
}
response, err := c.parseResponse(res, path, err)
if err != nil {
@ -236,25 +263,27 @@ func (c *APIClient) GetUserList() (UserList *[]api.UserInfo, err error) {
return userList, nil
}
// ReportNodeStatus reports the node status to the sspanel
// ReportNodeStatus reports the node status to the ssPanel
func (c *APIClient) ReportNodeStatus(nodeStatus *api.NodeStatus) (err error) {
path := fmt.Sprintf("/mod_mu/nodes/%d/info", c.NodeID)
systemload := SystemLoad{
Uptime: strconv.FormatUint(nodeStatus.Uptime, 10),
Load: fmt.Sprintf("%.2f %.2f %.2f", nodeStatus.CPU/100, nodeStatus.Mem/100, nodeStatus.Disk/100),
// Determine whether a status report is in need
if compareVersion(c.version, "2023.2") == -1 {
path := fmt.Sprintf("/mod_mu/nodes/%d/info", c.NodeID)
systemLoad := SystemLoad{
Uptime: strconv.FormatUint(nodeStatus.Uptime, 10),
Load: fmt.Sprintf("%.2f %.2f %.2f", nodeStatus.CPU/100, nodeStatus.Mem/100, nodeStatus.Disk/100),
}
res, err := c.client.R().
SetBody(systemLoad).
SetResult(&Response{}).
ForceContentType("application/json").
Post(path)
_, err = c.parseResponse(res, path, err)
if err != nil {
return err
}
}
res, err := c.client.R().
SetBody(systemload).
SetResult(&Response{}).
ForceContentType("application/json").
Post(path)
_, err = c.parseResponse(res, path, err)
if err != nil {
return err
}
return nil
}
@ -267,16 +296,12 @@ func (c *APIClient) ReportNodeOnlineUsers(onlineUserList *[]api.OnlineUser) erro
data := make([]OnlineUser, len(*onlineUserList))
for i, user := range *onlineUserList {
data[i] = OnlineUser{UID: user.UID, IP: user.IP}
if _, ok := reportOnline[user.UID]; ok {
reportOnline[user.UID]++
} else {
reportOnline[user.UID] = 1
}
reportOnline[user.UID]++ // will start from 1 if key doesnt exist
}
c.LastReportOnline = reportOnline // Update LastReportOnline
postData := &PostData{Data: data}
path := fmt.Sprintf("/mod_mu/users/aliveip")
path := "/mod_mu/users/aliveip"
res, err := c.client.R().
SetQueryParam("node_id", strconv.Itoa(c.NodeID)).
SetBody(postData).
@ -318,15 +343,25 @@ func (c *APIClient) ReportUserTraffic(userTraffic *[]api.UserTraffic) error {
return nil
}
// GetNodeRule will pull the audit rule form sspanel
// GetNodeRule will pull the audit rule form ssPanel
func (c *APIClient) GetNodeRule() (*[]api.DetectRule, error) {
ruleList := c.LocalRuleList
path := "/mod_mu/func/detect_rules"
res, err := c.client.R().
SetResult(&Response{}).
SetHeader("If-None-Match", c.eTags["rules"]).
ForceContentType("application/json").
Get(path)
// Etag identifier for a specific version of a resource. StatusCode = 304 means no changed
if res.StatusCode() == 304 {
return nil, errors.New(api.RuleNotModified)
}
if res.Header().Get("ETag") != "" && res.Header().Get("ETag") != c.eTags["rules"] {
c.eTags["rules"] = res.Header().Get("ETag")
}
response, err := c.parseResponse(res, path, err)
if err != nil {
return nil, err
@ -372,12 +407,12 @@ func (c *APIClient) ReportIllegal(detectResultList *[]api.DetectResult) error {
return nil
}
// ParseV2rayNodeResponse parse the response for the given nodeinfor format
// ParseV2rayNodeResponse parse the response for the given node info format
func (c *APIClient) ParseV2rayNodeResponse(nodeInfoResponse *NodeInfoResponse) (*api.NodeInfo, error) {
var enableTLS bool
var path, host, TLStype, transportProtocol, serviceName, HeaderType string
var path, host, transportProtocol, serviceName, HeaderType string
var header json.RawMessage
var speedlimit uint64 = 0
var speedLimit uint64 = 0
if nodeInfoResponse.RawServerString == "" {
return nil, fmt.Errorf("no server info in response")
}
@ -399,12 +434,7 @@ func (c *APIClient) ParseV2rayNodeResponse(nodeInfoResponse *NodeInfoResponse) (
// Compatible with more node types config
for _, value := range serverConf[3:5] {
switch value {
case "tls", "xtls":
if c.EnableXTLS {
TLStype = "xtls"
} else {
TLStype = "tls"
}
case "tls":
enableTLS = true
default:
if value != "" {
@ -429,14 +459,14 @@ func (c *APIClient) ParseV2rayNodeResponse(nodeInfoResponse *NodeInfoResponse) (
host = value
case "servicename":
serviceName = value
case "headertype":
case "headerType":
HeaderType = value
}
}
if c.SpeedLimit > 0 {
speedlimit = uint64((c.SpeedLimit * 1000000) / 8)
speedLimit = uint64((c.SpeedLimit * 1000000) / 8)
} else {
speedlimit = uint64((nodeInfoResponse.SpeedLimit * 1000000) / 8)
speedLimit = uint64((nodeInfoResponse.SpeedLimit * 1000000) / 8)
}
if HeaderType != "" {
@ -445,33 +475,33 @@ func (c *APIClient) ParseV2rayNodeResponse(nodeInfoResponse *NodeInfoResponse) (
}
if err != nil {
return nil, fmt.Errorf("marshal Header Type %s into config fialed: %s", header, err)
return nil, fmt.Errorf("marshal Header Type %s into config failed: %s", header, err)
}
// Create GeneralNodeInfo
nodeinfo := &api.NodeInfo{
nodeInfo := &api.NodeInfo{
NodeType: c.NodeType,
NodeID: c.NodeID,
Port: port,
SpeedLimit: speedlimit,
SpeedLimit: speedLimit,
AlterID: alterID,
TransportProtocol: transportProtocol,
EnableTLS: enableTLS,
TLSType: TLStype,
Path: path,
Host: host,
EnableVless: c.EnableVless,
VlessFlow: c.VlessFlow,
ServiceName: serviceName,
Header: header,
}
return nodeinfo, nil
return nodeInfo, nil
}
// ParseSSNodeResponse parse the response for the given nodeinfor format
// ParseSSNodeResponse parse the response for the given node info format
func (c *APIClient) ParseSSNodeResponse(nodeInfoResponse *NodeInfoResponse) (*api.NodeInfo, error) {
var port uint32 = 0
var speedlimit uint64 = 0
var speedLimit uint64 = 0
var method string
path := "/mod_mu/users"
res, err := c.client.R().
@ -490,41 +520,35 @@ func (c *APIClient) ParseSSNodeResponse(nodeInfoResponse *NodeInfoResponse) (*ap
if err := json.Unmarshal(response.Data, userListResponse); err != nil {
return nil, fmt.Errorf("unmarshal %s failed: %s", reflect.TypeOf(userListResponse), err)
}
// Find the multi-user
for _, u := range *userListResponse {
if u.MultiUser > 0 {
port = u.Port
method = u.Method
break
}
}
if port == 0 || method == "" {
return nil, fmt.Errorf("cant find the single port multi user")
// init server port
if len(*userListResponse) != 0 {
port = (*userListResponse)[0].Port
}
if c.SpeedLimit > 0 {
speedlimit = uint64((c.SpeedLimit * 1000000) / 8)
speedLimit = uint64((c.SpeedLimit * 1000000) / 8)
} else {
speedlimit = uint64((nodeInfoResponse.SpeedLimit * 1000000) / 8)
speedLimit = uint64((nodeInfoResponse.SpeedLimit * 1000000) / 8)
}
// Create GeneralNodeInfo
nodeinfo := &api.NodeInfo{
nodeInfo := &api.NodeInfo{
NodeType: c.NodeType,
NodeID: c.NodeID,
Port: port,
SpeedLimit: speedlimit,
SpeedLimit: speedLimit,
TransportProtocol: "tcp",
CypherMethod: method,
}
return nodeinfo, nil
return nodeInfo, nil
}
// ParseSSPluginNodeResponse parse the response for the given nodeinfor format
// ParseSSPluginNodeResponse parse the response for the given node info format
func (c *APIClient) ParseSSPluginNodeResponse(nodeInfoResponse *NodeInfoResponse) (*api.NodeInfo, error) {
var enableTLS bool
var path, host, TLStype, transportProtocol string
var speedlimit uint64 = 0
var path, host, transportProtocol string
var speedLimit uint64 = 0
serverConf := strings.Split(nodeInfoResponse.RawServerString, ";")
parsedPort, err := strconv.ParseInt(serverConf[1], 10, 32)
@ -539,12 +563,7 @@ func (c *APIClient) ParseSSPluginNodeResponse(nodeInfoResponse *NodeInfoResponse
// Compatible with more node types config
for _, value := range serverConf[3:5] {
switch value {
case "tls", "xtls":
if c.EnableXTLS {
TLStype = "xtls"
} else {
TLStype = "tls"
}
case "tls":
enableTLS = true
case "ws":
transportProtocol = "ws"
@ -570,38 +589,32 @@ func (c *APIClient) ParseSSPluginNodeResponse(nodeInfoResponse *NodeInfoResponse
}
}
if c.SpeedLimit > 0 {
speedlimit = uint64((c.SpeedLimit * 1000000) / 8)
speedLimit = uint64((c.SpeedLimit * 1000000) / 8)
} else {
speedlimit = uint64((nodeInfoResponse.SpeedLimit * 1000000) / 8)
speedLimit = uint64((nodeInfoResponse.SpeedLimit * 1000000) / 8)
}
// Create GeneralNodeInfo
nodeinfo := &api.NodeInfo{
nodeInfo := &api.NodeInfo{
NodeType: c.NodeType,
NodeID: c.NodeID,
Port: port,
SpeedLimit: speedlimit,
SpeedLimit: speedLimit,
TransportProtocol: transportProtocol,
EnableTLS: enableTLS,
TLSType: TLStype,
Path: path,
Host: host,
}
return nodeinfo, nil
return nodeInfo, nil
}
// ParseTrojanNodeResponse parse the response for the given nodeinfor format
// ParseTrojanNodeResponse parse the response for the given node info format
func (c *APIClient) ParseTrojanNodeResponse(nodeInfoResponse *NodeInfoResponse) (*api.NodeInfo, error) {
// 域名或IP;port=连接端口#偏移端口|host=xx
// gz.aaa.com;port=443#12345|host=hk.aaa.com
var p, TLSType, host, outsidePort, insidePort, transportProtocol, serviceName string
var speedlimit uint64 = 0
if c.EnableXTLS {
TLSType = "xtls"
} else {
TLSType = "tls"
}
var p, host, outsidePort, insidePort, transportProtocol, serviceName string
var speedLimit uint64 = 0
if nodeInfoResponse.RawServerString == "" {
return nil, fmt.Errorf("no server info in response")
@ -648,27 +661,26 @@ func (c *APIClient) ParseTrojanNodeResponse(nodeInfoResponse *NodeInfoResponse)
}
if c.SpeedLimit > 0 {
speedlimit = uint64((c.SpeedLimit * 1000000) / 8)
speedLimit = uint64((c.SpeedLimit * 1000000) / 8)
} else {
speedlimit = uint64((nodeInfoResponse.SpeedLimit * 1000000) / 8)
speedLimit = uint64((nodeInfoResponse.SpeedLimit * 1000000) / 8)
}
// Create GeneralNodeInfo
nodeinfo := &api.NodeInfo{
nodeInfo := &api.NodeInfo{
NodeType: c.NodeType,
NodeID: c.NodeID,
Port: port,
SpeedLimit: speedlimit,
SpeedLimit: speedLimit,
TransportProtocol: transportProtocol,
EnableTLS: true,
TLSType: TLSType,
Host: host,
ServiceName: serviceName,
}
return nodeinfo, nil
return nodeInfo, nil
}
// ParseUserListResponse parse the response for the given nodeinfo format
// ParseUserListResponse parse the response for the given node info format
func (c *APIClient) ParseUserListResponse(userInfoResponse *[]UserResponse) (*[]api.UserInfo, error) {
c.access.Lock()
// Clear Last report log
@ -677,8 +689,8 @@ func (c *APIClient) ParseUserListResponse(userInfoResponse *[]UserResponse) (*[]
c.access.Unlock()
}()
var deviceLimit, localDeviceLimit int = 0, 0
var speedlimit uint64 = 0
var deviceLimit, localDeviceLimit = 0, 0
var speedLimit uint64 = 0
var userList []api.UserInfo
for _, user := range *userInfoResponse {
if c.DeviceLimit > 0 {
@ -706,111 +718,142 @@ func (c *APIClient) ParseUserListResponse(userInfoResponse *[]UserResponse) (*[]
}
if c.SpeedLimit > 0 {
speedlimit = uint64((c.SpeedLimit * 1000000) / 8)
speedLimit = uint64((c.SpeedLimit * 1000000) / 8)
} else {
speedlimit = uint64((user.SpeedLimit * 1000000) / 8)
speedLimit = uint64((user.SpeedLimit * 1000000) / 8)
}
userList = append(userList, api.UserInfo{
UID: user.ID,
Email: user.Email,
UUID: user.UUID,
Passwd: user.Passwd,
SpeedLimit: speedlimit,
DeviceLimit: deviceLimit,
Port: user.Port,
Method: user.Method,
Protocol: user.Protocol,
ProtocolParam: user.ProtocolParam,
Obfs: user.Obfs,
ObfsParam: user.ObfsParam,
UID: user.ID,
UUID: user.UUID,
Passwd: user.Passwd,
SpeedLimit: speedLimit,
DeviceLimit: deviceLimit,
Port: user.Port,
Method: user.Method,
})
}
return &userList, nil
}
// ParseSSPanelNodeInfo parse the response for the given nodeinfor format
// Only used for SSPanel version >= 2021.11
// ParseSSPanelNodeInfo parse the response for the given node info format
// Only available for SSPanel version >= 2021.11
func (c *APIClient) ParseSSPanelNodeInfo(nodeInfoResponse *NodeInfoResponse) (*api.NodeInfo, error) {
var (
speedLimit uint64 = 0
enableTLS, enableVless bool
alterID uint16 = 0
transportProtocol string
)
var speedlimit uint64 = 0
var EnableTLS, EnableVless bool
var AlterID uint16 = 0
var TLSType, transportProtocol string
// Check if custom_config is null
if len(nodeInfoResponse.CustomConfig) == 0 {
return nil, errors.New("custom_config is empty, disable custom config")
}
nodeConfig := new(CustomConfig)
json.Unmarshal(nodeInfoResponse.CustomConfig, nodeConfig)
err := json.Unmarshal(nodeInfoResponse.CustomConfig, nodeConfig)
if err != nil {
return nil, fmt.Errorf("custom_config format error: %v", err)
}
if c.SpeedLimit > 0 {
speedlimit = uint64((c.SpeedLimit * 1000000) / 8)
speedLimit = uint64((c.SpeedLimit * 1000000) / 8)
} else {
speedlimit = uint64((nodeInfoResponse.SpeedLimit * 1000000) / 8)
speedLimit = uint64((nodeInfoResponse.SpeedLimit * 1000000) / 8)
}
parsedPort, err := strconv.ParseInt(nodeConfig.OffsetPortNode, 10, 32)
if err != nil {
return nil, err
}
port := uint32(parsedPort)
if c.NodeType == "Shadowsocks" {
switch c.NodeType {
case "Shadowsocks":
transportProtocol = "tcp"
}
if c.NodeType == "V2ray" {
case "V2ray":
transportProtocol = nodeConfig.Network
TLSType = nodeConfig.Security
if parsedAlterID, err := strconv.ParseInt(nodeConfig.AlterID, 10, 16); err != nil {
return nil, err
} else {
AlterID = uint16(parsedAlterID)
tlsType := nodeConfig.Security
if tlsType == "tls" || tlsType == "xtls" {
enableTLS = true
}
if TLSType == "tls" || TLSType == "xtls" {
EnableTLS = true
}
if nodeConfig.EnableVless == "1" {
EnableVless = true
enableVless = true
}
}
if c.NodeType == "Trojan" {
EnableTLS = true
TLSType = "tls"
case "Trojan":
enableTLS = true
transportProtocol = "tcp"
// Select security type
if nodeConfig.EnableXtls == "1" {
TLSType = "xtls"
} else if nodeConfig.Security != "" {
TLSType = nodeConfig.Security // try to read security from config
}
// Select transport protocol
if nodeConfig.Grpc == "1" {
transportProtocol = "grpc"
} else if nodeConfig.Network != "" {
if nodeConfig.Network != "" {
transportProtocol = nodeConfig.Network // try to read transport protocol from config
}
}
// parse reality config
realityConfig := new(api.REALITYConfig)
if nodeConfig.RealityOpts != nil {
r := nodeConfig.RealityOpts
realityConfig = &api.REALITYConfig{
Dest: r.Dest,
ProxyProtocolVer: r.ProxyProtocolVer,
ServerNames: r.ServerNames,
PrivateKey: r.PrivateKey,
MinClientVer: r.MinClientVer,
MaxClientVer: r.MaxClientVer,
MaxTimeDiff: r.MaxTimeDiff,
ShortIds: r.ShortIds,
}
}
// Create GeneralNodeInfo
nodeinfo := &api.NodeInfo{
nodeInfo := &api.NodeInfo{
NodeType: c.NodeType,
NodeID: c.NodeID,
Port: port,
SpeedLimit: speedlimit,
AlterID: AlterID,
SpeedLimit: speedLimit,
AlterID: alterID,
TransportProtocol: transportProtocol,
Host: nodeConfig.Host,
Path: nodeConfig.Path,
EnableTLS: EnableTLS,
TLSType: TLSType,
EnableVless: EnableVless,
CypherMethod: nodeConfig.MuEncryption,
EnableTLS: enableTLS,
EnableVless: enableVless,
VlessFlow: nodeConfig.Flow,
CypherMethod: nodeConfig.Method,
ServiceName: nodeConfig.Servicename,
Header: nodeConfig.Header,
EnableREALITY: nodeConfig.EnableREALITY,
REALITYConfig: realityConfig,
}
return nodeinfo, nil
return nodeInfo, nil
}
// compareVersion, version1 > version2 return 1, version1 < version2 return -1, 0 means equal
func compareVersion(version1, version2 string) int {
n, m := len(version1), len(version2)
i, j := 0, 0
for i < n || j < m {
x := 0
for ; i < n && version1[i] != '.'; i++ {
x = x*10 + int(version1[i]-'0')
}
i++ // jump dot
y := 0
for ; j < m && version2[j] != '.'; j++ {
y = y*10 + int(version2[j]-'0')
}
j++ // jump dot
if x > y {
return 1
}
if x < y {
return -1
}
}
return 0
}

View File

@ -19,7 +19,7 @@ func CreateClient() api.API {
return client
}
func TestGetV2rayNodeinfo(t *testing.T) {
func TestGetV2rayNodeInfo(t *testing.T) {
client := CreateClient()
nodeInfo, err := client.GetNodeInfo()
@ -29,7 +29,7 @@ func TestGetV2rayNodeinfo(t *testing.T) {
t.Log(nodeInfo)
}
func TestGetSSNodeinfo(t *testing.T) {
func TestGetSSNodeInfo(t *testing.T) {
apiConfig := &api.Config{
APIHost: "http://127.0.0.1:667",
Key: "123",
@ -44,7 +44,7 @@ func TestGetSSNodeinfo(t *testing.T) {
t.Log(nodeInfo)
}
func TestGetTrojanNodeinfo(t *testing.T) {
func TestGetTrojanNodeInfo(t *testing.T) {
apiConfig := &api.Config{
APIHost: "http://127.0.0.1:667",
Key: "123",
@ -59,7 +59,7 @@ func TestGetTrojanNodeinfo(t *testing.T) {
t.Log(nodeInfo)
}
func TestGetSSinfo(t *testing.T) {
func TestGetSSInfo(t *testing.T) {
client := CreateClient()
nodeInfo, err := client.GetNodeInfo()
@ -148,8 +148,8 @@ func TestReportIllegal(t *testing.T) {
client := CreateClient()
detectResult := []api.DetectResult{
{1, 2},
{1, 3},
{UID: 1, RuleID: 2},
{UID: 1, RuleID: 3},
}
client.Debug()
err := client.ReportIllegal(&detectResult)

View File

@ -1,8 +0,0 @@
// Deprecated: after 2023.6.1
package v2board
type UserTraffic struct {
UID int `json:"user_id"`
Upload int64 `json:"u"`
Download int64 `json:"d"`
}

View File

@ -1,425 +0,0 @@
package v2board
import (
"bufio"
"encoding/json"
"errors"
"fmt"
"log"
"os"
"regexp"
"strconv"
"strings"
"sync"
"time"
"github.com/bitly/go-simplejson"
"github.com/go-resty/resty/v2"
"github.com/XrayR-project/XrayR/api"
)
// APIClient create an api client to the panel.
type APIClient struct {
client *resty.Client
APIHost string
NodeID int
Key string
NodeType string
EnableVless bool
EnableXTLS bool
SpeedLimit float64
DeviceLimit int
LocalRuleList []api.DetectRule
ConfigResp *simplejson.Json
access sync.Mutex
}
// New create an api instance
func New(apiConfig *api.Config) *APIClient {
client := resty.New()
client.SetRetryCount(3)
if apiConfig.Timeout > 0 {
client.SetTimeout(time.Duration(apiConfig.Timeout) * time.Second)
} else {
client.SetTimeout(5 * time.Second)
}
client.OnError(func(req *resty.Request, err error) {
if v, ok := err.(*resty.ResponseError); ok {
// v.Response contains the last response from the server
// v.Err contains the original error
log.Print(v.Err)
}
})
client.SetBaseURL(apiConfig.APIHost)
// Create Key for each requests
client.SetQueryParams(map[string]string{
"node_id": strconv.Itoa(apiConfig.NodeID),
"token": apiConfig.Key,
})
// Read local rule list
localRuleList := readLocalRuleList(apiConfig.RuleListPath)
apiClient := &APIClient{
client: client,
NodeID: apiConfig.NodeID,
Key: apiConfig.Key,
APIHost: apiConfig.APIHost,
NodeType: apiConfig.NodeType,
EnableVless: apiConfig.EnableVless,
EnableXTLS: apiConfig.EnableXTLS,
SpeedLimit: apiConfig.SpeedLimit,
DeviceLimit: apiConfig.DeviceLimit,
LocalRuleList: localRuleList,
}
return apiClient
}
// readLocalRuleList reads the local rule list file
func readLocalRuleList(path string) (LocalRuleList []api.DetectRule) {
LocalRuleList = make([]api.DetectRule, 0)
if path != "" {
// open the file
file, err := os.Open(path)
// handle errors while opening
if err != nil {
log.Printf("Error when opening file: %s", err)
return LocalRuleList
}
fileScanner := bufio.NewScanner(file)
// read line by line
for fileScanner.Scan() {
LocalRuleList = append(LocalRuleList, api.DetectRule{
ID: -1,
Pattern: regexp.MustCompile(fileScanner.Text()),
})
}
// handle first encountered error while reading
if err := fileScanner.Err(); err != nil {
log.Fatalf("Error while reading file: %s", err)
return
}
file.Close()
}
return LocalRuleList
}
// Describe return a description of the client
func (c *APIClient) Describe() api.ClientInfo {
return api.ClientInfo{APIHost: c.APIHost, NodeID: c.NodeID, Key: c.Key, NodeType: c.NodeType}
}
// Debug set the client debug for client
func (c *APIClient) Debug() {
c.client.SetDebug(true)
}
func (c *APIClient) assembleURL(path string) string {
return c.APIHost + path
}
func (c *APIClient) parseResponse(res *resty.Response, path string, err error) (*simplejson.Json, error) {
if err != nil {
return nil, fmt.Errorf("request %s failed: %s", c.assembleURL(path), err)
}
if res.StatusCode() > 400 {
body := res.Body()
return nil, fmt.Errorf("request %s failed: %s, %s", c.assembleURL(path), string(body), err)
}
rtn, err := simplejson.NewJson(res.Body())
if err != nil {
return nil, fmt.Errorf("ret %s invalid", res.String())
}
return rtn, nil
}
// GetNodeInfo will pull NodeInfo Config from sspanel
func (c *APIClient) GetNodeInfo() (nodeInfo *api.NodeInfo, err error) {
var path string
switch c.NodeType {
case "V2ray":
path = "/api/v1/server/Deepbwork/config"
case "Trojan":
path = "/api/v1/server/TrojanTidalab/config"
case "Shadowsocks":
if nodeInfo, err = c.ParseSSNodeResponse(); err == nil {
return nodeInfo, nil
} else {
return nil, err
}
default:
return nil, fmt.Errorf("unsupported Node type: %s", c.NodeType)
}
res, err := c.client.R().
SetQueryParam("local_port", "1").
ForceContentType("application/json").
Get(path)
response, err := c.parseResponse(res, path, err)
c.access.Lock()
defer c.access.Unlock()
c.ConfigResp = response
if err != nil {
return nil, err
}
switch c.NodeType {
case "V2ray":
nodeInfo, err = c.ParseV2rayNodeResponse(response)
case "Trojan":
nodeInfo, err = c.ParseTrojanNodeResponse(response)
case "Shadowsocks":
nodeInfo, err = c.ParseSSNodeResponse()
default:
return nil, fmt.Errorf("unsupported Node type: %s", c.NodeType)
}
if err != nil {
res, _ := response.MarshalJSON()
return nil, fmt.Errorf("Parse node info failed: %s, \nError: %s", string(res), err)
}
return nodeInfo, nil
}
// GetUserList will pull user form sspanel
func (c *APIClient) GetUserList() (UserList *[]api.UserInfo, err error) {
var path string
switch c.NodeType {
case "V2ray":
path = "/api/v1/server/Deepbwork/user"
case "Trojan":
path = "/api/v1/server/TrojanTidalab/user"
case "Shadowsocks":
path = "/api/v1/server/ShadowsocksTidalab/user"
default:
return nil, fmt.Errorf("unsupported Node type: %s", c.NodeType)
}
res, err := c.client.R().
ForceContentType("application/json").
Get(path)
response, err := c.parseResponse(res, path, err)
if err != nil {
return nil, err
}
numOfUsers := len(response.Get("data").MustArray())
userList := make([]api.UserInfo, numOfUsers)
for i := 0; i < numOfUsers; i++ {
user := api.UserInfo{}
user.UID = response.Get("data").GetIndex(i).Get("id").MustInt()
user.SpeedLimit = uint64(c.SpeedLimit * 1000000 / 8)
user.DeviceLimit = c.DeviceLimit
switch c.NodeType {
case "Shadowsocks":
user.Email = response.Get("data").GetIndex(i).Get("secret").MustString()
user.Passwd = response.Get("data").GetIndex(i).Get("secret").MustString()
user.Method = response.Get("data").GetIndex(i).Get("cipher").MustString()
user.Port = uint32(response.Get("data").GetIndex(i).Get("port").MustUint64())
case "Trojan":
user.UUID = response.Get("data").GetIndex(i).Get("trojan_user").Get("password").MustString()
user.Email = response.Get("data").GetIndex(i).Get("trojan_user").Get("password").MustString()
case "V2ray":
user.UUID = response.Get("data").GetIndex(i).Get("v2ray_user").Get("uuid").MustString()
user.Email = response.Get("data").GetIndex(i).Get("v2ray_user").Get("email").MustString()
user.AlterID = uint16(response.Get("data").GetIndex(i).Get("v2ray_user").Get("alter_id").MustUint64())
}
userList[i] = user
}
return &userList, nil
}
// ReportUserTraffic reports the user traffic
func (c *APIClient) ReportUserTraffic(userTraffic *[]api.UserTraffic) error {
var path string
switch c.NodeType {
case "V2ray":
path = "/api/v1/server/Deepbwork/submit"
case "Trojan":
path = "/api/v1/server/TrojanTidalab/submit"
case "Shadowsocks":
path = "/api/v1/server/ShadowsocksTidalab/submit"
}
data := make([]UserTraffic, len(*userTraffic))
for i, traffic := range *userTraffic {
data[i] = UserTraffic{
UID: traffic.UID,
Upload: traffic.Upload,
Download: traffic.Download}
}
res, err := c.client.R().
SetQueryParam("node_id", strconv.Itoa(c.NodeID)).
SetBody(data).
ForceContentType("application/json").
Post(path)
_, err = c.parseResponse(res, path, err)
if err != nil {
return err
}
return nil
}
// GetNodeRule implements the API interface
func (c *APIClient) GetNodeRule() (*[]api.DetectRule, error) {
ruleList := c.LocalRuleList
if c.NodeType != "V2ray" {
return &ruleList, nil
}
// V2board only support the rule for v2ray
// fix: reuse config response
c.access.Lock()
defer c.access.Unlock()
ruleListResponse := c.ConfigResp.Get("routing").Get("rules").GetIndex(1).Get("domain").MustStringArray()
for i, rule := range ruleListResponse {
rule = strings.TrimPrefix(rule, "regexp:")
ruleListItem := api.DetectRule{
ID: i,
Pattern: regexp.MustCompile(rule),
}
ruleList = append(ruleList, ruleListItem)
}
return &ruleList, nil
}
// ReportNodeStatus implements the API interface
func (c *APIClient) ReportNodeStatus(nodeStatus *api.NodeStatus) (err error) {
return nil
}
// ReportNodeOnlineUsers implements the API interface
func (c *APIClient) ReportNodeOnlineUsers(onlineUserList *[]api.OnlineUser) error {
return nil
}
// ReportIllegal implements the API interface
func (c *APIClient) ReportIllegal(detectResultList *[]api.DetectResult) error {
return nil
}
// ParseTrojanNodeResponse parse the response for the given nodeinfor format
func (c *APIClient) ParseTrojanNodeResponse(nodeInfoResponse *simplejson.Json) (*api.NodeInfo, error) {
var TLSType = "tls"
if c.EnableXTLS {
TLSType = "xtls"
}
port := uint32(nodeInfoResponse.Get("local_port").MustUint64())
host := nodeInfoResponse.Get("ssl").Get("sni").MustString()
// Create GeneralNodeInfo
nodeinfo := &api.NodeInfo{
NodeType: c.NodeType,
NodeID: c.NodeID,
Port: port,
TransportProtocol: "tcp",
EnableTLS: true,
TLSType: TLSType,
Host: host,
}
return nodeinfo, nil
}
// ParseSSNodeResponse parse the response for the given nodeinfor format
func (c *APIClient) ParseSSNodeResponse() (*api.NodeInfo, error) {
var port uint32
var method string
userInfo, err := c.GetUserList()
if err != nil {
return nil, err
}
if len(*userInfo) > 0 {
port = (*userInfo)[0].Port
method = (*userInfo)[0].Method
} else {
return nil, errors.New("the number of node users is 0")
}
// Create GeneralNodeInfo
nodeinfo := &api.NodeInfo{
NodeType: c.NodeType,
NodeID: c.NodeID,
Port: port,
TransportProtocol: "tcp",
CypherMethod: method,
}
return nodeinfo, nil
}
// ParseV2rayNodeResponse parse the response for the given nodeinfor format
func (c *APIClient) ParseV2rayNodeResponse(nodeInfoResponse *simplejson.Json) (*api.NodeInfo, error) {
var TLSType string = "tls"
var path, host, serviceName string
var header json.RawMessage
var enableTLS bool
var alterID uint16 = 0
if c.EnableXTLS {
TLSType = "xtls"
}
inboundInfo := simplejson.New()
if tmpInboundInfo, ok := nodeInfoResponse.CheckGet("inbound"); ok {
inboundInfo = tmpInboundInfo
// Compatible with v2board 1.5.5-dev
} else if tmpInboundInfo, ok := nodeInfoResponse.CheckGet("inbounds"); ok {
tmpInboundInfo := tmpInboundInfo.MustArray()
marshalByte, _ := json.Marshal(tmpInboundInfo[0].(map[string]interface{}))
inboundInfo, _ = simplejson.NewJson(marshalByte)
} else {
return nil, fmt.Errorf("unable to find inbound(s) in the nodeInfo")
}
port := uint32(inboundInfo.Get("port").MustUint64())
transportProtocol := inboundInfo.Get("streamSettings").Get("network").MustString()
switch transportProtocol {
case "ws":
path = inboundInfo.Get("streamSettings").Get("wsSettings").Get("path").MustString()
host = inboundInfo.Get("streamSettings").Get("wsSettings").Get("headers").Get("Host").MustString()
case "grpc":
if data, ok := inboundInfo.Get("streamSettings").Get("grpcSettings").CheckGet("serviceName"); ok {
serviceName = data.MustString()
}
case "tcp":
if data, ok := inboundInfo.Get("streamSettings").Get("tcpSettings").CheckGet("header"); ok {
if httpHeader, err := data.MarshalJSON(); err != nil {
return nil, err
} else {
header = httpHeader
}
}
}
if inboundInfo.Get("streamSettings").Get("security").MustString() == "tls" {
enableTLS = true
} else {
enableTLS = false
}
// Create GeneralNodeInfo
// AlterID will be updated after next sync
nodeInfo := &api.NodeInfo{
NodeType: c.NodeType,
NodeID: c.NodeID,
Port: port,
AlterID: alterID,
TransportProtocol: transportProtocol,
EnableTLS: enableTLS,
TLSType: TLSType,
Path: path,
Host: host,
EnableVless: c.EnableVless,
ServiceName: serviceName,
Header: header,
}
return nodeInfo, nil
}

View File

@ -1,7 +1,35 @@
package v2raysocks
type UserTraffic struct {
UID int `json:"user_id"`
UID int `json:"uid"`
Upload int64 `json:"u"`
Download int64 `json:"d"`
}
type NodeStatus struct {
CPU string `json:"cpu"`
Mem string `json:"mem"`
Net string `json:"net"`
Disk string `json:"disk"`
Uptime int `json:"uptime"`
}
type NodeOnline struct {
UID int `json:"uid"`
IP string `json:"ip"`
}
type IllegalItem struct {
UID int `json:"uid"`
}
type REALITYConfig struct {
Dest string `json:"dest,omitempty"`
ProxyProtocolVer uint64 `json:"proxy_protocol_ver,omitempty"`
ServerNames []string `json:"server_names,omitempty"`
PrivateKey string `json:"private_key,omitempty"`
MinClientVer string `json:"min_client_ver,omitempty"`
MaxClientVer string `json:"max_client_ver,omitempty"`
MaxTimeDiff uint64 `json:"max_time_diff,omitempty"`
ShortIds []string `json:"short_ids,omitempty"`
}

View File

@ -3,8 +3,8 @@ package v2raysocks
import (
"bufio"
"encoding/json"
"errors"
"fmt"
"log"
"os"
"regexp"
"strconv"
@ -12,6 +12,8 @@ import (
"sync"
"time"
log "github.com/sirupsen/logrus"
"github.com/bitly/go-simplejson"
"github.com/go-resty/resty/v2"
"github.com/sagernet/sing-shadowsocks/shadowaead_2022"
@ -28,12 +30,13 @@ type APIClient struct {
Key string
NodeType string
EnableVless bool
EnableXTLS bool
VlessFlow string
SpeedLimit float64
DeviceLimit int
LocalRuleList []api.DetectRule
ConfigResp *simplejson.Json
access sync.Mutex
eTags map[string]string
}
// New create an api instance
@ -46,13 +49,16 @@ func New(apiConfig *api.Config) *APIClient {
} else {
client.SetTimeout(5 * time.Second)
}
client.OnError(func(req *resty.Request, err error) {
if v, ok := err.(*resty.ResponseError); ok {
var v *resty.ResponseError
if errors.As(err, &v) {
// v.Response contains the last response from the server
// v.Err contains the original error
log.Print(v.Err)
}
})
// Create Key for each requests
client.SetQueryParams(map[string]string{
"node_id": strconv.Itoa(apiConfig.NodeID),
@ -67,10 +73,11 @@ func New(apiConfig *api.Config) *APIClient {
APIHost: apiConfig.APIHost,
NodeType: apiConfig.NodeType,
EnableVless: apiConfig.EnableVless,
EnableXTLS: apiConfig.EnableXTLS,
VlessFlow: apiConfig.VlessFlow,
SpeedLimit: apiConfig.SpeedLimit,
DeviceLimit: apiConfig.DeviceLimit,
LocalRuleList: localRuleList,
eTags: make(map[string]string),
}
return apiClient
}
@ -144,19 +151,29 @@ func (c *APIClient) parseResponse(res *resty.Response, path string, err error) (
func (c *APIClient) GetNodeInfo() (nodeInfo *api.NodeInfo, err error) {
var nodeType string
switch c.NodeType {
case "V2ray", "Trojan", "Shadowsocks":
case "V2ray", "Vmess", "Vless", "Trojan", "Shadowsocks":
nodeType = strings.ToLower(c.NodeType)
default:
return nil, fmt.Errorf("unsupported Node type: %s", c.NodeType)
}
res, err := c.client.R().
SetHeader("If-None-Match", c.eTags["config"]).
SetQueryParams(map[string]string{
"act": "config",
"nodetype": nodeType,
"act": "config",
"node_type": nodeType,
}).
ForceContentType("application/json").
Get(c.APIHost)
// Etag identifier for a specific version of a resource. StatusCode = 304 means no changed
if res.StatusCode() == 304 {
return nil, errors.New(api.NodeNotModified)
}
// update etag
if res.Header().Get("Etag") != "" && res.Header().Get("Etag") != c.eTags["config"] {
c.eTags["config"] = res.Header().Get("Etag")
}
response, err := c.parseResponse(res, "", err)
c.access.Lock()
defer c.access.Unlock()
@ -166,7 +183,7 @@ func (c *APIClient) GetNodeInfo() (nodeInfo *api.NodeInfo, err error) {
}
switch c.NodeType {
case "V2ray":
case "V2ray", "Vmess", "Vless":
nodeInfo, err = c.ParseV2rayNodeResponse(response)
case "Trojan":
nodeInfo, err = c.ParseTrojanNodeResponse(response)
@ -178,7 +195,7 @@ func (c *APIClient) GetNodeInfo() (nodeInfo *api.NodeInfo, err error) {
if err != nil {
res, _ := response.MarshalJSON()
return nil, fmt.Errorf("Parse node info failed: %s, \nError: %s", string(res), err)
return nil, fmt.Errorf("parse node info failed: %s, \nError: %s", string(res), err)
}
return nodeInfo, nil
@ -188,19 +205,29 @@ func (c *APIClient) GetNodeInfo() (nodeInfo *api.NodeInfo, err error) {
func (c *APIClient) GetUserList() (UserList *[]api.UserInfo, err error) {
var nodeType string
switch c.NodeType {
case "V2ray", "Trojan", "Shadowsocks":
case "V2ray", "Vmess", "Vless", "Trojan", "Shadowsocks":
nodeType = strings.ToLower(c.NodeType)
default:
return nil, fmt.Errorf("unsupported Node type: %s", c.NodeType)
}
res, err := c.client.R().
SetHeader("If-None-Match", c.eTags["user"]).
SetQueryParams(map[string]string{
"act": "user",
"nodetype": nodeType,
"act": "user",
"node_type": nodeType,
}).
ForceContentType("application/json").
Get(c.APIHost)
// Etag identifier for a specific version of a resource. StatusCode = 304 means no changed
if res.StatusCode() == 304 {
return nil, errors.New(api.UserNotModified)
}
// update etag
if res.Header().Get("Etag") != "" && res.Header().Get("Etag") != c.eTags["user"] {
c.eTags["user"] = res.Header().Get("Etag")
}
response, err := c.parseResponse(res, "", err)
if err != nil {
return nil, err
@ -212,24 +239,30 @@ func (c *APIClient) GetUserList() (UserList *[]api.UserInfo, err error) {
user.UID = response.Get("data").GetIndex(i).Get("id").MustInt()
switch c.NodeType {
case "Shadowsocks":
user.Email = response.Get("data").GetIndex(i).Get("shadowsocks_user").Get("secret").MustString()
user.Passwd = response.Get("data").GetIndex(i).Get("shadowsocks_user").Get("secret").MustString()
user.Method = response.Get("data").GetIndex(i).Get("shadowsocks_user").Get("cipher").MustString()
user.SpeedLimit = response.Get("data").GetIndex(i).Get("shadowsocks_user").Get("speed_limit").MustUint64() * 1000000 / 8
user.Email = response.Get("data").GetIndex(i).Get("secret").MustString()
user.Passwd = response.Get("data").GetIndex(i).Get("secret").MustString()
user.Method = response.Get("data").GetIndex(i).Get("cipher").MustString()
user.SpeedLimit = response.Get("data").GetIndex(i).Get("st").MustUint64() * 1000000 / 8
user.DeviceLimit = response.Get("data").GetIndex(i).Get("dt").MustInt()
case "Trojan":
user.UUID = response.Get("data").GetIndex(i).Get("trojan_user").Get("password").MustString()
user.Email = response.Get("data").GetIndex(i).Get("trojan_user").Get("password").MustString()
user.SpeedLimit = response.Get("data").GetIndex(i).Get("trojan_user").Get("speed_limit").MustUint64() * 1000000 / 8
case "V2ray":
user.UUID = response.Get("data").GetIndex(i).Get("v2ray_user").Get("uuid").MustString()
user.Email = response.Get("data").GetIndex(i).Get("v2ray_user").Get("email").MustString()
user.AlterID = uint16(response.Get("data").GetIndex(i).Get("v2ray_user").Get("alter_id").MustUint64())
user.SpeedLimit = response.Get("data").GetIndex(i).Get("v2ray_user").Get("speed_limit").MustUint64() * 1000000 / 8
user.UUID = response.Get("data").GetIndex(i).Get("password").MustString()
user.Email = response.Get("data").GetIndex(i).Get("password").MustString()
user.SpeedLimit = response.Get("data").GetIndex(i).Get("st").MustUint64() * 1000000 / 8
user.DeviceLimit = response.Get("data").GetIndex(i).Get("dt").MustInt()
case "V2ray", "Vmess", "Vless":
user.UUID = response.Get("data").GetIndex(i).Get("uuid").MustString()
user.Email = user.UUID + "@x.com"
user.SpeedLimit = response.Get("data").GetIndex(i).Get("st").MustUint64() * 1000000 / 8
user.DeviceLimit = response.Get("data").GetIndex(i).Get("dt").MustInt()
}
if c.SpeedLimit > 0 {
user.SpeedLimit = uint64((c.SpeedLimit * 1000000) / 8)
}
user.DeviceLimit = c.DeviceLimit
if c.DeviceLimit > 0 {
user.DeviceLimit = c.DeviceLimit
}
userList[i] = user
}
return &userList, nil
@ -249,8 +282,8 @@ func (c *APIClient) ReportUserTraffic(userTraffic *[]api.UserTraffic) error {
res, err := c.client.R().
SetQueryParam("node_id", strconv.Itoa(c.NodeID)).
SetQueryParams(map[string]string{
"act": "submit",
"nodetype": strings.ToLower(c.NodeType),
"act": "submit",
"node_type": strings.ToLower(c.NodeType),
}).
SetBody(data).
ForceContentType("application/json").
@ -265,11 +298,7 @@ func (c *APIClient) ReportUserTraffic(userTraffic *[]api.UserTraffic) error {
// GetNodeRule implements the API interface
func (c *APIClient) GetNodeRule() (*[]api.DetectRule, error) {
ruleList := c.LocalRuleList
if c.NodeType != "V2ray" {
return &ruleList, nil
}
// Only support the rule for v2ray
// fix: reuse config response
c.access.Lock()
defer c.access.Unlock()
@ -287,26 +316,79 @@ func (c *APIClient) GetNodeRule() (*[]api.DetectRule, error) {
// ReportNodeStatus implements the API interface
func (c *APIClient) ReportNodeStatus(nodeStatus *api.NodeStatus) (err error) {
systemload := NodeStatus{
Uptime: int(nodeStatus.Uptime),
CPU: fmt.Sprintf("%d%%", int(nodeStatus.CPU)),
Mem: fmt.Sprintf("%d%%", int(nodeStatus.Mem)),
Disk: fmt.Sprintf("%d%%", int(nodeStatus.Disk)),
}
res, err := c.client.R().
SetQueryParam("node_id", strconv.Itoa(c.NodeID)).
SetQueryParams(map[string]string{
"act": "nodestatus",
"node_type": strings.ToLower(c.NodeType),
}).
SetBody(systemload).
ForceContentType("application/json").
Post(c.APIHost)
_, err = c.parseResponse(res, "", err)
if err != nil {
return err
}
return nil
}
// ReportNodeOnlineUsers implements the API interface
func (c *APIClient) ReportNodeOnlineUsers(onlineUserList *[]api.OnlineUser) error {
data := make([]NodeOnline, len(*onlineUserList))
for i, user := range *onlineUserList {
data[i] = NodeOnline{UID: user.UID, IP: user.IP}
}
res, err := c.client.R().
SetQueryParam("node_id", strconv.Itoa(c.NodeID)).
SetQueryParams(map[string]string{
"act": "onlineusers",
"node_type": strings.ToLower(c.NodeType),
}).
SetBody(data).
ForceContentType("application/json").
Post(c.APIHost)
_, err = c.parseResponse(res, "", err)
if err != nil {
return err
}
return nil
}
// ReportIllegal implements the API interface
func (c *APIClient) ReportIllegal(detectResultList *[]api.DetectResult) error {
data := make([]IllegalItem, len(*detectResultList))
for i, r := range *detectResultList {
data[i] = IllegalItem{
UID: r.UID,
}
}
res, err := c.client.R().
SetQueryParam("node_id", strconv.Itoa(c.NodeID)).
SetQueryParams(map[string]string{
"act": "illegal",
"node_type": strings.ToLower(c.NodeType),
}).
SetBody(data).
ForceContentType("application/json").
Post(c.APIHost)
_, err = c.parseResponse(res, "", err)
if err != nil {
return err
}
return nil
}
// ParseTrojanNodeResponse parse the response for the given nodeInfo format
func (c *APIClient) ParseTrojanNodeResponse(nodeInfoResponse *simplejson.Json) (*api.NodeInfo, error) {
var TLSType = "tls"
if c.EnableXTLS {
TLSType = "xtls"
}
tmpInboundInfo := nodeInfoResponse.Get("inbounds").MustArray()
marshalByte, _ := json.Marshal(tmpInboundInfo[0].(map[string]interface{}))
inboundInfo, _ := simplejson.NewJson(marshalByte)
@ -321,7 +403,6 @@ func (c *APIClient) ParseTrojanNodeResponse(nodeInfoResponse *simplejson.Json) (
Port: port,
TransportProtocol: "tcp",
EnableTLS: true,
TLSType: TLSType,
Host: host,
}
return nodeInfo, nil
@ -339,14 +420,6 @@ func (c *APIClient) ParseSSNodeResponse(nodeInfoResponse *simplejson.Json) (*api
// Shadowsocks 2022
if C.Contains(shadowaead_2022.List, method) {
serverPsk = inboundInfo.Get("settings").Get("password").MustString()
} else {
userInfo, err := c.GetUserList()
if err != nil {
return nil, err
}
if len(*userInfo) > 0 {
method = (*userInfo)[0].Method
}
}
// Create GeneralNodeInfo
@ -364,14 +437,12 @@ func (c *APIClient) ParseSSNodeResponse(nodeInfoResponse *simplejson.Json) (*api
// ParseV2rayNodeResponse parse the response for the given nodeInfo format
func (c *APIClient) ParseV2rayNodeResponse(nodeInfoResponse *simplejson.Json) (*api.NodeInfo, error) {
var TLSType = "tls"
var path, host, serviceName string
var header json.RawMessage
var enableTLS bool
var alterID uint16 = 0
if c.EnableXTLS {
TLSType = "xtls"
}
var enableVless bool
var enableReality bool
var vlessFlow string
tmpInboundInfo := nodeInfoResponse.Get("inbounds").MustArray()
marshalByte, _ := json.Marshal(tmpInboundInfo[0].(map[string]interface{}))
@ -384,6 +455,12 @@ func (c *APIClient) ParseV2rayNodeResponse(nodeInfoResponse *simplejson.Json) (*
case "ws":
path = inboundInfo.Get("streamSettings").Get("wsSettings").Get("path").MustString()
host = inboundInfo.Get("streamSettings").Get("wsSettings").Get("headers").Get("Host").MustString()
case "httpupgrade":
host = inboundInfo.Get("streamSettings").Get("httpupgradeSettings").Get("Host").MustString()
path = inboundInfo.Get("streamSettings").Get("httpupgradeSettings").Get("path").MustString()
case "splithttp":
host = inboundInfo.Get("streamSettings").Get("splithttpSettings").Get("Host").MustString()
path = inboundInfo.Get("streamSettings").Get("splithttpSettings").Get("path").MustString()
case "grpc":
if data, ok := inboundInfo.Get("streamSettings").Get("grpcSettings").CheckGet("serviceName"); ok {
serviceName = data.MustString()
@ -396,12 +473,34 @@ func (c *APIClient) ParseV2rayNodeResponse(nodeInfoResponse *simplejson.Json) (*
header = httpHeader
}
}
}
if inboundInfo.Get("streamSettings").Get("security").MustString() == "tls" {
enableTLS = true
enableTLS = inboundInfo.Get("streamSettings").Get("security").MustString() == "tls"
enableVless = inboundInfo.Get("protocol").MustString() == "vless"
enableReality = inboundInfo.Get("streamSettings").Get("security").MustString() == "reality"
realityConfig := new(api.REALITYConfig)
if enableVless {
// parse reality config
realityConfig = &api.REALITYConfig{
Dest: inboundInfo.Get("streamSettings").Get("realitySettings").Get("dest").MustString(),
ProxyProtocolVer: inboundInfo.Get("streamSettings").Get("realitySettings").Get("xver").MustUint64(),
ServerNames: inboundInfo.Get("streamSettings").Get("realitySettings").Get("serverNames").MustStringArray(),
PrivateKey: inboundInfo.Get("streamSettings").Get("realitySettings").Get("privateKey").MustString(),
MinClientVer: inboundInfo.Get("streamSettings").Get("realitySettings").Get("minClientVer").MustString(),
MaxClientVer: inboundInfo.Get("streamSettings").Get("realitySettings").Get("maxClientVer").MustString(),
MaxTimeDiff: inboundInfo.Get("streamSettings").Get("realitySettings").Get("maxTimeDiff").MustUint64(),
ShortIds: inboundInfo.Get("streamSettings").Get("realitySettings").Get("shortIds").MustStringArray(),
}
}
// XTLS only supports TLS and REALITY directly for now
if (transportProtocol == "grpc" || transportProtocol == "h2") && enableReality {
vlessFlow = ""
} else if transportProtocol == "tcp" && enableReality {
vlessFlow = "xtls-rprx-vision"
} else {
enableTLS = false
vlessFlow = c.VlessFlow
}
// Create GeneralNodeInfo
@ -410,15 +509,17 @@ func (c *APIClient) ParseV2rayNodeResponse(nodeInfoResponse *simplejson.Json) (*
NodeType: c.NodeType,
NodeID: c.NodeID,
Port: port,
AlterID: alterID,
AlterID: 0,
TransportProtocol: transportProtocol,
EnableTLS: enableTLS,
TLSType: TLSType,
Path: path,
Host: host,
EnableVless: c.EnableVless,
EnableVless: enableVless,
VlessFlow: vlessFlow,
ServiceName: serviceName,
Header: header,
EnableREALITY: enableReality,
REALITYConfig: realityConfig,
}
return nodeInfo, nil
}

View File

@ -11,6 +11,7 @@ import (
"github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/buf"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/log"
"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/protocol"
@ -106,7 +107,7 @@ func init() {
common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
d := new(DefaultDispatcher)
if err := core.RequireFeatures(ctx, func(om outbound.Manager, router routing.Router, pm policy.Manager, sm stats.Manager, dc dns.Client) error {
core.RequireFeatures(ctx, func(fdns dns.FakeDNSEngine) {
core.OptionalFeatures(ctx, func(fdns dns.FakeDNSEngine) {
d.fdns = fdns
})
return d.Init(config.(*Config), om, router, pm, sm, dc)
@ -144,77 +145,10 @@ func (*DefaultDispatcher) Close() error {
return nil
}
func (d *DefaultDispatcher) getLink(ctx context.Context, network net.Network, sniffing session.SniffingRequest) (*transport.Link, *transport.Link, error) {
downOpt := pipe.OptionsFromContext(ctx)
upOpt := downOpt
if network == net.Network_UDP {
var ip2domain *sync.Map // net.IP.String() => domain, this map is used by server side when client turn on fakedns
// Client will send domain address in the buffer.UDP.Address, server record all possible target IP addrs.
// When target replies, server will restore the domain and send back to client.
// Note: this map is not global but per connection context
upOpt = append(upOpt, pipe.OnTransmission(func(mb buf.MultiBuffer) buf.MultiBuffer {
for i, buffer := range mb {
if buffer.UDP == nil {
continue
}
addr := buffer.UDP.Address
if addr.Family().IsIP() {
if fkr0, ok := d.fdns.(dns.FakeDNSEngineRev0); ok && fkr0.IsIPInIPPool(addr) && sniffing.Enabled {
domain := fkr0.GetDomainFromFakeDNS(addr)
if len(domain) > 0 {
buffer.UDP.Address = net.DomainAddress(domain)
newError("[fakedns client] override with domain: ", domain, " for xUDP buffer at ", i).WriteToLog(session.ExportIDToError(ctx))
} else {
newError("[fakedns client] failed to find domain! :", addr.String(), " for xUDP buffer at ", i).AtWarning().WriteToLog(session.ExportIDToError(ctx))
}
}
} else {
if ip2domain == nil {
ip2domain = new(sync.Map)
newError("[fakedns client] create a new map").WriteToLog(session.ExportIDToError(ctx))
}
domain := addr.Domain()
ips, err := d.dns.LookupIP(domain, dns.IPOption{IPv4Enable: true, IPv6Enable: true})
if err == nil {
for _, ip := range ips {
ip2domain.Store(ip.String(), domain)
}
newError("[fakedns client] candidate ip: "+fmt.Sprintf("%v", ips), " for xUDP buffer at ", i).WriteToLog(session.ExportIDToError(ctx))
} else {
newError("[fakedns client] failed to look up IP for ", domain, " for xUDP buffer at ", i).Base(err).WriteToLog(session.ExportIDToError(ctx))
}
}
}
return mb
}))
downOpt = append(downOpt, pipe.OnTransmission(func(mb buf.MultiBuffer) buf.MultiBuffer {
for i, buffer := range mb {
if buffer.UDP == nil {
continue
}
addr := buffer.UDP.Address
if addr.Family().IsIP() {
if ip2domain == nil {
continue
}
if domain, found := ip2domain.Load(addr.IP().String()); found {
buffer.UDP.Address = net.DomainAddress(domain.(string))
newError("[fakedns client] restore domain: ", domain.(string), " for xUDP buffer at ", i).WriteToLog(session.ExportIDToError(ctx))
}
} else {
if fkr0, ok := d.fdns.(dns.FakeDNSEngineRev0); ok {
fakeIp := fkr0.GetFakeIPForDomain(addr.Domain())
buffer.UDP.Address = fakeIp[0]
newError("[fakedns client] restore FakeIP: ", buffer.UDP, fmt.Sprintf("%v", fakeIp), " for xUDP buffer at ", i).WriteToLog(session.ExportIDToError(ctx))
}
}
}
return mb
}))
}
uplinkReader, uplinkWriter := pipe.New(upOpt...)
downlinkReader, downlinkWriter := pipe.New(downOpt...)
func (d *DefaultDispatcher) getLink(ctx context.Context) (*transport.Link, *transport.Link, error) {
opt := pipe.OptionsFromContext(ctx)
uplinkReader, uplinkWriter := pipe.New(opt...)
downlinkReader, downlinkWriter := pipe.New(opt...)
inboundLink := &transport.Link{
Reader: downlinkReader,
@ -236,7 +170,7 @@ func (d *DefaultDispatcher) getLink(ctx context.Context, network net.Network, sn
// Speed Limit and Device Limit
bucket, ok, reject := d.Limiter.GetUserBucket(sessionInbound.Tag, user.Email, sessionInbound.Source.Address.IP().String())
if reject {
newError("Devices reach the limit: ", user.Email).AtWarning().WriteToLog()
errors.LogWarning(ctx, "Devices reach the limit: ", user.Email)
common.Close(outboundLink.Writer)
common.Close(inboundLink.Writer)
common.Interrupt(outboundLink.Reader)
@ -247,6 +181,7 @@ func (d *DefaultDispatcher) getLink(ctx context.Context, network net.Network, sn
inboundLink.Writer = d.Limiter.RateWriter(inboundLink.Writer, bucket)
outboundLink.Writer = d.Limiter.RateWriter(outboundLink.Writer, bucket)
}
p := d.policy.ForLevel(user.Level)
if p.Stats.UserUplink {
name := "user>>>" + user.Email + ">>>traffic>>>uplink"
@ -283,12 +218,12 @@ func (d *DefaultDispatcher) shouldOverride(ctx context.Context, result SniffResu
protocolString = resComp.ProtocolForDomainResult()
}
for _, p := range request.OverrideDestinationForProtocol {
if strings.HasPrefix(protocolString, p) {
if strings.HasPrefix(protocolString, p) || strings.HasPrefix(p, protocolString) {
return true
}
if fkr0, ok := d.fdns.(dns.FakeDNSEngineRev0); ok && protocolString != "bittorrent" && p == "fakedns" &&
destination.Address.Family().IsIP() && fkr0.IsIPInIPPool(destination.Address) {
newError("Using sniffer ", protocolString, " since the fake DNS missed").WriteToLog(session.ExportIDToError(ctx))
errors.LogInfo(ctx, "Using sniffer ", protocolString, " since the fake DNS missed")
return true
}
if resultSubset, ok := result.(SnifferIsProtoSubsetOf); ok {
@ -306,10 +241,14 @@ func (d *DefaultDispatcher) Dispatch(ctx context.Context, destination net.Destin
if !destination.IsValid() {
panic("Dispatcher: Invalid destination.")
}
ob := &session.Outbound{
Target: destination,
outbounds := session.OutboundsFromContext(ctx)
if len(outbounds) == 0 {
outbounds = []*session.Outbound{{}}
ctx = session.ContextWithOutbounds(ctx, outbounds)
}
ctx = session.ContextWithOutbound(ctx, ob)
ob := outbounds[len(outbounds)-1]
ob.OriginalTarget = destination
ob.Target = destination
content := session.ContentFromContext(ctx)
if content == nil {
content = new(session.Content)
@ -317,7 +256,7 @@ func (d *DefaultDispatcher) Dispatch(ctx context.Context, destination net.Destin
}
sniffingRequest := content.SniffingRequest
inbound, outbound, err := d.getLink(ctx, destination.Network, sniffingRequest)
inbound, outbound, err := d.getLink(ctx)
if err != nil {
return nil, err
}
@ -335,7 +274,7 @@ func (d *DefaultDispatcher) Dispatch(ctx context.Context, destination net.Destin
}
if err == nil && d.shouldOverride(ctx, result, sniffingRequest, destination) {
domain := result.Domain()
newError("sniffed domain: ", domain).WriteToLog(session.ExportIDToError(ctx))
errors.LogInfo(ctx, "sniffed domain: ", domain)
destination.Address = net.ParseAddress(domain)
if sniffingRequest.RouteOnly && result.Protocol() != "fakedns" {
ob.RouteTarget = destination
@ -354,10 +293,14 @@ func (d *DefaultDispatcher) DispatchLink(ctx context.Context, destination net.De
if !destination.IsValid() {
return newError("Dispatcher: Invalid destination.")
}
ob := &session.Outbound{
Target: destination,
outbounds := session.OutboundsFromContext(ctx)
if len(outbounds) == 0 {
outbounds = []*session.Outbound{{}}
ctx = session.ContextWithOutbounds(ctx, outbounds)
}
ctx = session.ContextWithOutbound(ctx, ob)
ob := outbounds[len(outbounds)-1]
ob.OriginalTarget = destination
ob.Target = destination
content := session.ContentFromContext(ctx)
if content == nil {
content = new(session.Content)
@ -378,7 +321,7 @@ func (d *DefaultDispatcher) DispatchLink(ctx context.Context, destination net.De
}
if err == nil && d.shouldOverride(ctx, result, sniffingRequest, destination) {
domain := result.Domain()
newError("sniffed domain: ", domain).WriteToLog(session.ExportIDToError(ctx))
errors.LogInfo(ctx, "sniffed domain: ", domain)
destination.Address = net.ParseAddress(domain)
if sniffingRequest.RouteOnly && result.Protocol() != "fakedns" {
ob.RouteTarget = destination
@ -440,7 +383,8 @@ func sniffer(ctx context.Context, cReader *cachedReader, metadataOnly bool, netw
}
func (d *DefaultDispatcher) routedDispatch(ctx context.Context, link *transport.Link, destination net.Destination) {
ob := session.OutboundFromContext(ctx)
outbounds := session.OutboundsFromContext(ctx)
ob := outbounds[len(outbounds)-1]
if hosts, ok := d.dns.(dns.HostsLookup); ok && destination.Address.Family().IsDomain() {
proxied := hosts.LookupHosts(ob.Target.String())
if proxied != nil {
@ -461,7 +405,7 @@ func (d *DefaultDispatcher) routedDispatch(ctx context.Context, link *transport.
// Whether the inbound connection contains a user
if sessionInbound.User != nil {
if d.RuleManager.Detect(sessionInbound.Tag, destination.String(), sessionInbound.User.Email) {
newError(fmt.Sprintf("User %s access %s reject by rule", sessionInbound.User.Email, destination.String())).AtError().WriteToLog()
errors.LogError(ctx, fmt.Sprintf("User %s access %s reject by rule", sessionInbound.User.Email, destination.String()))
newError("destination is reject by rule")
common.Close(link.Writer)
common.Interrupt(link.Reader)
@ -476,10 +420,10 @@ func (d *DefaultDispatcher) routedDispatch(ctx context.Context, link *transport.
ctx = session.SetForcedOutboundTagToContext(ctx, "")
if h := d.ohm.GetHandler(forcedOutboundTag); h != nil {
isPickRoute = 1
newError("taking platform initialized detour [", forcedOutboundTag, "] for [", destination, "]").WriteToLog(session.ExportIDToError(ctx))
errors.LogInfo(ctx, "taking platform initialized detour [", forcedOutboundTag, "] for [", destination, "]")
handler = h
} else {
newError("non existing tag for platform initialized detour: ", forcedOutboundTag).AtError().WriteToLog(session.ExportIDToError(ctx))
errors.LogError(ctx, "non existing tag for platform initialized detour: ", forcedOutboundTag)
common.Close(link.Writer)
common.Interrupt(link.Reader)
return
@ -489,13 +433,13 @@ func (d *DefaultDispatcher) routedDispatch(ctx context.Context, link *transport.
outTag := route.GetOutboundTag()
if h := d.ohm.GetHandler(outTag); h != nil {
isPickRoute = 2
newError("taking detour [", outTag, "] for [", destination, "]").WriteToLog(session.ExportIDToError(ctx))
errors.LogInfo(ctx, "taking detour [", outTag, "] for [", destination, "]")
handler = h
} else {
newError("non existing outTag: ", outTag).AtWarning().WriteToLog(session.ExportIDToError(ctx))
errors.LogWarning(ctx, "non existing outTag: ", outTag)
}
} else {
newError("default route for ", destination).WriteToLog(session.ExportIDToError(ctx))
errors.LogInfo(ctx, "default route for ", destination)
}
}
@ -509,7 +453,7 @@ func (d *DefaultDispatcher) routedDispatch(ctx context.Context, link *transport.
}
if handler == nil {
newError("default outbound handler not exist").WriteToLog(session.ExportIDToError(ctx))
errors.LogInfo(ctx, "default outbound handler not exist")
common.Close(link.Writer)
common.Interrupt(link.Reader)
return

View File

@ -5,6 +5,7 @@ import (
"strings"
"github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/session"
"github.com/xtls/xray-core/core"
@ -26,11 +27,13 @@ func newFakeDNSSniffer(ctx context.Context) (protocolSnifferWithMetadata, error)
return protocolSnifferWithMetadata{}, errNotInit
}
return protocolSnifferWithMetadata{protocolSniffer: func(ctx context.Context, bytes []byte) (SniffResult, error) {
Target := session.OutboundFromContext(ctx).Target
outbounds := session.OutboundsFromContext(ctx)
ob := outbounds[len(outbounds)-1]
Target := ob.Target
if Target.Network == net.Network_TCP || Target.Network == net.Network_UDP {
domainFromFakeDNS := fakeDNSEngine.GetDomainFromFakeDNS(Target.Address)
if domainFromFakeDNS != "" {
newError("fake dns got domain: ", domainFromFakeDNS, " for ip: ", Target.Address.String()).WriteToLog(session.ExportIDToError(ctx))
errors.LogInfo(ctx, "fake dns got domain: ", domainFromFakeDNS, " for ip: ", ob.Target.Address.String())
return &fakeDNSSniffResult{domainName: domainFromFakeDNS}, nil
}
}
@ -107,10 +110,10 @@ func newFakeDNSThenOthers(ctx context.Context, fakeDNSSniffer protocolSnifferWit
}
return nil, common.ErrNoClue
}
newError("ip address not in fake dns range, return as is").AtDebug().WriteToLog()
errors.LogDebug(ctx, "ip address not in fake dns range, return as is")
return nil, common.ErrNoClue
}
newError("fake dns sniffer did not set address in range option, assume false.").AtWarning().WriteToLog()
errors.LogWarning(ctx, "fake dns sniffer did not set address in range option, assume false.")
return nil, common.ErrNoClue
},
metadataSniffer: false,

View File

@ -34,7 +34,7 @@ type Sniffer struct {
func NewSniffer(ctx context.Context) *Sniffer {
ret := &Sniffer{
sniffer: []protocolSnifferWithMetadata{
{func(c context.Context, b []byte) (SniffResult, error) { return http.SniffHTTP(b) }, false, net.Network_TCP},
{func(c context.Context, b []byte) (SniffResult, error) { return http.SniffHTTP(b, ctx) }, false, net.Network_TCP},
{func(c context.Context, b []byte) (SniffResult, error) { return tls.SniffTLS(b) }, false, net.Network_TCP},
{func(c context.Context, b []byte) (SniffResult, error) { return bittorrent.SniffBittorrent(b) }, false, net.Network_TCP},
{func(c context.Context, b []byte) (SniffResult, error) { return quic.SniffQUIC(b) }, false, net.Network_UDP},

View File

@ -31,25 +31,26 @@ import (
_ "github.com/xtls/xray-core/proxy/dokodemo"
_ "github.com/xtls/xray-core/proxy/freedom"
_ "github.com/xtls/xray-core/proxy/http"
_ "github.com/xtls/xray-core/proxy/mtproto"
_ "github.com/xtls/xray-core/proxy/loopback"
_ "github.com/xtls/xray-core/proxy/shadowsocks"
_ "github.com/xtls/xray-core/proxy/shadowsocks_2022"
_ "github.com/xtls/xray-core/proxy/socks"
_ "github.com/xtls/xray-core/proxy/trojan"
_ "github.com/xtls/xray-core/proxy/vless/inbound"
_ "github.com/xtls/xray-core/proxy/vless/outbound"
_ "github.com/xtls/xray-core/proxy/vmess/inbound"
_ "github.com/xtls/xray-core/proxy/vmess/outbound"
_ "github.com/xtls/xray-core/proxy/wireguard"
// Transports
_ "github.com/xtls/xray-core/transport/internet/domainsocket"
_ "github.com/xtls/xray-core/transport/internet/http"
_ "github.com/xtls/xray-core/transport/internet/grpc"
_ "github.com/xtls/xray-core/transport/internet/kcp"
_ "github.com/xtls/xray-core/transport/internet/quic"
_ "github.com/xtls/xray-core/transport/internet/reality"
_ "github.com/xtls/xray-core/transport/internet/splithttp"
_ "github.com/xtls/xray-core/transport/internet/tcp"
_ "github.com/xtls/xray-core/transport/internet/tls"
_ "github.com/xtls/xray-core/transport/internet/udp"
_ "github.com/xtls/xray-core/transport/internet/websocket"
_ "github.com/xtls/xray-core/transport/internet/xtls"
// Transport headers
_ "github.com/xtls/xray-core/transport/internet/headers/http"

View File

@ -1,9 +1,7 @@
package main
package cmd
import (
"flag"
"fmt"
"log"
"os"
"os/signal"
"path"
@ -12,36 +10,40 @@ import (
"syscall"
"time"
log "github.com/sirupsen/logrus"
"github.com/fsnotify/fsnotify"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/XrayR-project/XrayR/panel"
)
var (
configFile = flag.String("config", "", "Config file for XrayR.")
printVersion = flag.Bool("version", false, "show version")
cfgFile string
rootCmd = &cobra.Command{
Use: "XrayR",
Run: func(cmd *cobra.Command, args []string) {
if err := run(); err != nil {
log.Fatal(err)
}
},
}
)
var (
version = "0.9.0"
codename = "XrayR"
intro = "A Xray backend that supports many panels"
)
func showVersion() {
fmt.Printf("%s %s (%s) \n", codename, version, intro)
func init() {
rootCmd.PersistentFlags().StringVarP(&cfgFile, "config", "c", "", "Config file for XrayR.")
}
func getConfig() *viper.Viper {
config := viper.New()
// Set custom path and name
if *configFile != "" {
configName := path.Base(*configFile)
configFileExt := path.Ext(*configFile)
if cfgFile != "" {
configName := path.Base(cfgFile)
configFileExt := path.Ext(cfgFile)
configNameOnly := strings.TrimSuffix(configName, configFileExt)
configPath := path.Dir(*configFile)
configPath := path.Dir(cfgFile)
config.SetConfigName(configNameOnly)
config.SetConfigType(strings.TrimPrefix(configFileExt, "."))
config.AddConfigPath(configPath)
@ -65,18 +67,19 @@ func getConfig() *viper.Viper {
return config
}
func main() {
flag.Parse()
func run() error {
showVersion()
if *printVersion {
return
}
config := getConfig()
panelConfig := &panel.Config{}
if err := config.Unmarshal(panelConfig); err != nil {
log.Panicf("Parse config file %v failed: %s \n", configFile, err)
return fmt.Errorf("Parse config file %v failed: %s \n", cfgFile, err)
}
if panelConfig.LogConfig.Level == "debug" {
log.SetReportCaller(true)
}
p := panel.New(panelConfig)
lastTime := time.Now()
config.OnConfigChange(func(e fsnotify.Event) {
@ -88,21 +91,31 @@ func main() {
// Delete old instance and trigger GC
runtime.GC()
if err := config.Unmarshal(panelConfig); err != nil {
log.Panicf("Parse config file %v failed: %s \n", configFile, err)
log.Panicf("Parse config file %v failed: %s \n", cfgFile, err)
}
if panelConfig.LogConfig.Level == "debug" {
log.SetReportCaller(true)
}
p.Start()
lastTime = time.Now()
}
})
p.Start()
defer p.Close()
// Explicitly triggering GC to remove garbage from config loading.
runtime.GC()
// Running backend
{
osSignals := make(chan os.Signal, 1)
signal.Notify(osSignals, os.Interrupt, os.Kill, syscall.SIGTERM)
<-osSignals
}
osSignals := make(chan os.Signal, 1)
signal.Notify(osSignals, os.Interrupt, os.Kill, syscall.SIGTERM)
<-osSignals
return nil
}
func Execute() error {
return rootCmd.Execute()
}

27
cmd/version.go Normal file
View File

@ -0,0 +1,27 @@
package cmd
import (
"fmt"
"github.com/spf13/cobra"
)
var (
version = "0.9.5"
codename = "XrayR"
intro = "A Xray backend that supports many panels"
)
func init() {
rootCmd.AddCommand(&cobra.Command{
Use: "version",
Short: "Print current version of XrayR",
Run: func(cmd *cobra.Command, args []string) {
showVersion()
},
})
}
func showVersion() {
fmt.Printf("%s %s (%s) \n", codename, version, intro)
}

66
cmd/x25519.go Normal file
View File

@ -0,0 +1,66 @@
package cmd
import (
"crypto/rand"
"encoding/base64"
"errors"
"fmt"
"github.com/spf13/cobra"
"golang.org/x/crypto/curve25519"
)
var (
priKey string
x25519Cmd = &cobra.Command{
Use: "x25519",
Short: "Generate key pair for x25519 key exchange",
Run: func(cmd *cobra.Command, args []string) {
if err := x25519(); err != nil {
fmt.Println(err)
}
},
}
)
func init() {
x25519Cmd.PersistentFlags().StringVarP(&priKey, "input", "i", "", "Input private key (base64.RawURLEncoding)")
rootCmd.AddCommand(x25519Cmd)
}
func x25519() error {
privateKey := make([]byte, curve25519.ScalarSize)
if priKey == "" {
if _, err := rand.Read(privateKey); err != nil {
return err
}
} else {
p, err := base64.RawURLEncoding.DecodeString(priKey)
if err != nil {
return err
}
if len(p) != curve25519.ScalarSize {
return errors.New("invalid private key")
}
privateKey = p
}
// Modify random bytes using algorithm described at:
// https://cr.yp.to/ecdh.html.
privateKey[0] &= 248
privateKey[31] &= 127
privateKey[31] |= 64
publicKey, err := curve25519.X25519(privateKey, curve25519.Basepoint)
if err != nil {
return err
}
output := fmt.Sprintf("Private key: %v\nPublic key: %v",
base64.RawURLEncoding.EncodeToString(privateKey),
base64.RawURLEncoding.EncodeToString(publicKey))
fmt.Println(output)
return nil
}

View File

@ -1,7 +0,0 @@
package limiter
import "github.com/xtls/xray-core/common/errors"
func newError(values ...interface{}) *errors.Error {
return errors.New(values...)
}

View File

@ -14,8 +14,9 @@ import (
"github.com/eko/gocache/lib/v4/store"
goCacheStore "github.com/eko/gocache/store/go_cache/v4"
redisStore "github.com/eko/gocache/store/redis/v4"
"github.com/go-redis/redis/v8"
goCache "github.com/patrickmn/go-cache"
"github.com/redis/go-redis/v9"
"github.com/xtls/xray-core/common/errors"
"golang.org/x/time/rate"
"github.com/XrayR-project/XrayR/api"
@ -66,7 +67,9 @@ func (l *Limiter) AddInboundLimiter(tag string, nodeSpeedLimit uint64, userList
// init redis store
rs := redisStore.NewRedis(redis.NewClient(
&redis.Options{
Network: globalLimit.RedisNetwork,
Addr: globalLimit.RedisAddr,
Username: globalLimit.RedisUsername,
Password: globalLimit.RedisPassword,
DB: globalLimit.RedisDB,
}),
@ -216,7 +219,7 @@ func (l *Limiter) GetUserBucket(tag string, email string, ip string) (limiter *r
return nil, false, false
}
} else {
newError("Get Inbound Limiter information failed").AtDebug().WriteToLog()
errors.LogDebug(context.Background(), "Get Inbound Limiter information failed")
return nil, false, false
}
}
@ -236,7 +239,7 @@ func globalLimit(inboundInfo *InboundInfo, email string, uid int, ip string, dev
// If the email is a new device
go pushIP(inboundInfo, uniqueKey, &map[string]int{ip: uid})
} else {
newError("cache service").Base(err).AtError().WriteToLog()
errors.LogErrorInner(context.Background(), err, "cache service")
}
return false
}
@ -262,7 +265,7 @@ func pushIP(inboundInfo *InboundInfo, uniqueKey string, ipMap *map[string]int) {
defer cancel()
if err := inboundInfo.GlobalLimit.globalOnlineIP.Set(ctx, uniqueKey, ipMap); err != nil {
newError("cache service").Base(err).AtError().WriteToLog()
errors.LogErrorInner(context.Background(), err, "cache service")
}
}

View File

@ -2,7 +2,9 @@ package limiter
type GlobalDeviceLimitConfig struct {
Enable bool `mapstructure:"Enable"`
RedisAddr string `mapstructure:"RedisAddr"` // host:port
RedisNetwork string `mapstructure:"RedisNetwork"` // tcp or unix
RedisAddr string `mapstructure:"RedisAddr"` // host:port, or /path/to/unix.sock
RedisUsername string `mapstructure:"RedisUsername"`
RedisPassword string `mapstructure:"RedisPassword"`
RedisDB int `mapstructure:"RedisDB"`
Timeout int `mapstructure:"Timeout"`

View File

@ -6,12 +6,13 @@ import (
"encoding/json"
"encoding/pem"
"errors"
"log"
"net/url"
"os"
"path/filepath"
"strings"
log "github.com/sirupsen/logrus"
"github.com/go-acme/lego/v4/certcrypto"
"github.com/go-acme/lego/v4/lego"
"github.com/go-acme/lego/v4/registration"

View File

@ -4,11 +4,12 @@ import (
"bytes"
"crypto/x509"
"encoding/json"
"log"
"os"
"path/filepath"
"strings"
log "github.com/sirupsen/logrus"
"github.com/go-acme/lego/v4/certcrypto"
"github.com/go-acme/lego/v4/certificate"
"golang.org/x/net/idna"

View File

@ -149,8 +149,8 @@ func (l *LegoCMD) RenewCert() (CertPath string, KeyPath string, ok bool, err err
}
func checkCertFile(domain string) (string, string, error) {
keyPath := path.Join(defaultPath, "certificates", fmt.Sprintf("%s.key", domain))
certPath := path.Join(defaultPath, "certificates", fmt.Sprintf("%s.crt", domain))
keyPath := path.Join(defaultPath, "certificates", fmt.Sprintf("%s.key", sanitizedDomain(domain)))
certPath := path.Join(defaultPath, "certificates", fmt.Sprintf("%s.crt", sanitizedDomain(domain)))
if _, err := os.Stat(keyPath); os.IsNotExist(err) {
return "", "", fmt.Errorf("cert key failed: %s", domain)
}

View File

@ -3,9 +3,10 @@ package mylego
import (
"crypto"
"crypto/x509"
"log"
"time"
log "github.com/sirupsen/logrus"
"github.com/go-acme/lego/v4/certcrypto"
"github.com/go-acme/lego/v4/certificate"
"github.com/go-acme/lego/v4/lego"

View File

@ -2,11 +2,11 @@ package mylego
import (
"fmt"
"log"
"github.com/go-acme/lego/v4/certificate"
"github.com/go-acme/lego/v4/lego"
"github.com/go-acme/lego/v4/registration"
log "github.com/sirupsen/logrus"
)
const rootPathWarningMessage = `!!!! HEADS UP !!!!

View File

@ -1,10 +1,11 @@
package mylego
import (
"log"
"os"
"time"
log "github.com/sirupsen/logrus"
"github.com/go-acme/lego/v4/certcrypto"
"github.com/go-acme/lego/v4/challenge/dns01"
"github.com/go-acme/lego/v4/challenge/http01"

View File

@ -1,7 +0,0 @@
package rule
import "github.com/xtls/xray-core/common/errors"
func newError(values ...interface{}) *errors.Error {
return errors.New(values...)
}

View File

@ -2,6 +2,7 @@
package rule
import (
"context"
"fmt"
"reflect"
"strconv"
@ -9,6 +10,7 @@ import (
"sync"
mapset "github.com/deckarep/golang-set"
"github.com/xtls/xray-core/common/errors"
"github.com/XrayR-project/XrayR/api"
)
@ -65,7 +67,7 @@ func (r *Manager) Detect(tag string, destination string, email string) (reject b
l := strings.Split(email, "|")
uid, err := strconv.Atoi(l[len(l)-1])
if err != nil {
newError(fmt.Sprintf("Record illegal behavior failed! Cannot find user's uid: %s", email)).AtDebug().WriteToLog()
errors.LogDebug(context.Background(), fmt.Sprintf("Record illegal behavior failed! Cannot find user's uid: %s", email))
return reject
}
newSet := mapset.NewSetWith(api.DetectResult{UID: uid, RuleID: hitRuleID})

380
go.mod
View File

@ -1,193 +1,311 @@
module github.com/XrayR-project/XrayR
go 1.20
go 1.24
toolchain go1.24.1
require (
github.com/bitly/go-simplejson v0.5.0
dario.cat/mergo v1.0.0
github.com/bitly/go-simplejson v0.5.1
github.com/deckarep/golang-set v1.8.0
github.com/eko/gocache/lib/v4 v4.1.2
github.com/eko/gocache/store/go_cache/v4 v4.1.2
github.com/eko/gocache/store/redis/v4 v4.1.2
github.com/fsnotify/fsnotify v1.6.0
github.com/go-acme/lego/v4 v4.9.2-0.20221210101705-6695fcc87344
github.com/go-redis/redis/v8 v8.11.5
github.com/go-resty/resty/v2 v2.7.0
github.com/imdario/mergo v0.3.13
github.com/eko/gocache/lib/v4 v4.1.6
github.com/eko/gocache/store/go_cache/v4 v4.2.2
github.com/eko/gocache/store/redis/v4 v4.2.1
github.com/fsnotify/fsnotify v1.7.0
github.com/go-acme/lego/v4 v4.16.1
github.com/go-resty/resty/v2 v2.13.1
github.com/gogf/gf/v2 v2.7.0
github.com/patrickmn/go-cache v2.1.0+incompatible
github.com/r3labs/diff/v2 v2.15.1
github.com/sagernet/sing v0.1.7
github.com/sagernet/sing-shadowsocks v0.1.1-0.20230202035033-e3123545f2f7
github.com/shirou/gopsutil/v3 v3.23.1
github.com/spf13/viper v1.15.0
github.com/stretchr/testify v1.8.1
github.com/xtls/xray-core v1.7.5
golang.org/x/crypto v0.6.0
golang.org/x/net v0.7.0
golang.org/x/time v0.3.0
google.golang.org/protobuf v1.28.1
github.com/redis/go-redis/v9 v9.7.0
github.com/sagernet/sing v0.5.1
github.com/sagernet/sing-shadowsocks v0.2.7
github.com/shirou/gopsutil/v3 v3.24.5
github.com/sirupsen/logrus v1.9.3
github.com/spf13/cobra v1.8.1
github.com/spf13/viper v1.18.2
github.com/stretchr/testify v1.10.0
github.com/xtls/xray-core v1.250306.0
golang.org/x/crypto v0.36.0
golang.org/x/net v0.37.0
golang.org/x/time v0.7.0
google.golang.org/protobuf v1.36.5
)
require (
cloud.google.com/go/compute v1.15.1 // indirect
cloud.google.com/go/compute/metadata v0.2.3 // indirect
github.com/Azure/azure-sdk-for-go v32.4.0+incompatible // indirect
cloud.google.com/go/compute/metadata v0.6.0 // indirect
github.com/AdamSLevy/jsonrpc2/v14 v14.1.0 // indirect
github.com/Azure/azure-sdk-for-go v68.0.0+incompatible // indirect
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1 // indirect
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.6.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/internal v1.8.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dns/armdns v1.2.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/privatedns/armprivatedns v1.2.0 // indirect
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
github.com/Azure/go-autorest/autorest v0.11.24 // indirect
github.com/Azure/go-autorest/autorest/adal v0.9.18 // indirect
github.com/Azure/go-autorest/autorest/azure/auth v0.5.11 // indirect
github.com/Azure/go-autorest/autorest/azure/cli v0.4.5 // indirect
github.com/Azure/go-autorest/autorest v0.11.29 // indirect
github.com/Azure/go-autorest/autorest/adal v0.9.23 // indirect
github.com/Azure/go-autorest/autorest/azure/auth v0.5.12 // indirect
github.com/Azure/go-autorest/autorest/azure/cli v0.4.6 // indirect
github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect
github.com/Azure/go-autorest/autorest/to v0.4.0 // indirect
github.com/Azure/go-autorest/autorest/validation v0.3.1 // indirect
github.com/Azure/go-autorest/logger v0.2.1 // indirect
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 // indirect
github.com/BurntSushi/toml v1.3.2 // indirect
github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 // indirect
github.com/CloudyKit/jet/v6 v6.2.0 // indirect
github.com/Joker/jade v1.1.3 // indirect
github.com/OmarTariq612/goech v0.0.0-20240405204721-8e2e1dafd3a0 // indirect
github.com/OpenDNS/vegadns2client v0.0.0-20180418235048-a3fa4a771d87 // indirect
github.com/akamai/AkamaiOPEN-edgegrid-golang v1.2.1 // indirect
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1755 // indirect
github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129 // indirect
github.com/andybalholm/brotli v1.0.4 // indirect
github.com/aws/aws-sdk-go v1.39.0 // indirect
github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 // indirect
github.com/akamai/AkamaiOPEN-edgegrid-golang v1.2.2 // indirect
github.com/aliyun/alibaba-cloud-sdk-go v1.62.695 // indirect
github.com/andybalholm/brotli v1.1.0 // indirect
github.com/apapsch/go-jsonmerge/v2 v2.0.0 // indirect
github.com/aws/aws-sdk-go-v2 v1.25.3 // indirect
github.com/aws/aws-sdk-go-v2/config v1.27.7 // indirect
github.com/aws/aws-sdk-go-v2/credentials v1.17.7 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.15.3 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.3 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.3 // indirect
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.1 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.5 // indirect
github.com/aws/aws-sdk-go-v2/service/lightsail v1.36.2 // indirect
github.com/aws/aws-sdk-go-v2/service/route53 v1.40.2 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.20.2 // indirect
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.2 // indirect
github.com/aws/aws-sdk-go-v2/service/sts v1.28.4 // indirect
github.com/aws/smithy-go v1.20.1 // indirect
github.com/aymerick/douceur v0.2.0 // indirect
github.com/benbjohnson/clock v1.3.5 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc // indirect
github.com/cenkalti/backoff/v4 v4.1.3 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/civo/civogo v0.3.11 // indirect
github.com/cloudflare/cloudflare-go v0.49.0 // indirect
github.com/boombuler/barcode v1.0.1 // indirect
github.com/bytedance/sonic v1.11.3 // indirect
github.com/cenkalti/backoff/v4 v4.2.1 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect
github.com/chenzhuoyu/iasm v0.9.1 // indirect
github.com/civo/civogo v0.3.63 // indirect
github.com/clbanning/mxj/v2 v2.7.0 // indirect
github.com/cloudflare/circl v1.6.0 // indirect
github.com/cloudflare/cloudflare-go v0.90.0 // indirect
github.com/cpu/goacmedns v0.1.1 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/deepmap/oapi-codegen v1.9.1 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/deepmap/oapi-codegen v1.16.2 // indirect
github.com/dgryski/go-metro v0.0.0-20211217172704-adc40b04c140 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/dimchansky/utfbom v1.1.1 // indirect
github.com/dnsimple/dnsimple-go v0.71.1 // indirect
github.com/exoscale/egoscale v0.93.0 // indirect
github.com/dnsimple/dnsimple-go v1.7.0 // indirect
github.com/exoscale/egoscale v1.19.0 // indirect
github.com/fatih/color v1.16.0 // indirect
github.com/fatih/structs v1.1.0 // indirect
github.com/francoispqt/gojay v1.2.13 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/flosch/pongo2/v4 v4.0.2 // indirect
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
github.com/ghodss/yaml v1.0.1-0.20220118164431-d8423dcdf344 // indirect
github.com/go-errors/errors v1.0.1 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect
github.com/gofrs/uuid v4.3.1+incompatible // indirect
github.com/golang-jwt/jwt/v4 v4.2.0 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/gin-gonic/gin v1.9.1 // indirect
github.com/go-errors/errors v1.5.1 // indirect
github.com/go-jose/go-jose/v4 v4.0.1 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-ole/go-ole v1.3.0 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.19.0 // indirect
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 // indirect
github.com/goccy/go-json v0.10.2 // indirect
github.com/gofrs/uuid v4.4.0+incompatible // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
github.com/golang-jwt/jwt/v5 v5.2.1 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/mock v1.6.0 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/golang/mock v1.7.0-rc.1 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/gomarkdown/markdown v0.0.0-20231222211730-1d6d20845b47 // indirect
github.com/google/btree v1.1.2 // indirect
github.com/google/go-querystring v1.1.0 // indirect
github.com/google/pprof v0.0.0-20230207041349-798e818bf904 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.2.1 // indirect
github.com/googleapis/gax-go/v2 v2.7.0 // indirect
github.com/gophercloud/gophercloud v1.0.0 // indirect
github.com/gophercloud/utils v0.0.0-20210216074907-f6de111f2eae // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/hashicorp/errwrap v1.0.0 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/pprof v0.0.0-20240528025155-186aa0362fba // indirect
github.com/google/s2a-go v0.1.7 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect
github.com/googleapis/gax-go/v2 v2.12.3 // indirect
github.com/gophercloud/gophercloud v1.11.0 // indirect
github.com/gophercloud/utils v0.0.0-20231010081019-80377eca5d56 // indirect
github.com/gorilla/css v1.0.1 // indirect
github.com/gorilla/websocket v1.5.3 // indirect
github.com/grokify/html-strip-tags-go v0.0.1 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/hashicorp/go-retryablehttp v0.7.1 // indirect
github.com/hashicorp/go-retryablehttp v0.7.7 // indirect
github.com/hashicorp/go-uuid v1.0.3 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/infobloxopen/infoblox-go-client v1.1.1 // indirect
github.com/iris-contrib/schema v0.0.6 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213 // indirect
github.com/klauspost/compress v1.15.15 // indirect
github.com/klauspost/cpuid/v2 v2.2.3 // indirect
github.com/kolo/xmlrpc v0.0.0-20200310150728-e0350524596b // indirect
github.com/kataras/blocks v0.0.8 // indirect
github.com/kataras/golog v0.1.11 // indirect
github.com/kataras/iris/v12 v12.2.10 // indirect
github.com/kataras/pio v0.0.13 // indirect
github.com/kataras/sitemap v0.0.6 // indirect
github.com/kataras/tunnel v0.0.4 // indirect
github.com/klauspost/compress v1.17.8 // indirect
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
github.com/kolo/xmlrpc v0.0.0-20220921171641-a4b6fa1dd06b // indirect
github.com/kylelemons/godebug v1.1.0 // indirect
github.com/labbsr0x/bindman-dns-webhook v1.0.2 // indirect
github.com/labbsr0x/goh v1.0.1 // indirect
github.com/linode/linodego v1.9.1 // indirect
github.com/liquidweb/go-lwApi v0.0.5 // indirect
github.com/liquidweb/liquidweb-cli v0.6.9 // indirect
github.com/liquidweb/liquidweb-go v1.6.3 // indirect
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
github.com/labstack/echo/v4 v4.11.4 // indirect
github.com/labstack/gommon v0.4.2 // indirect
github.com/leodido/go-urn v1.4.0 // indirect
github.com/linode/linodego v1.30.0 // indirect
github.com/liquidweb/liquidweb-cli v0.7.0 // indirect
github.com/liquidweb/liquidweb-go v1.6.4 // indirect
github.com/lufia/plan9stats v0.0.0-20240226150601-1dcf7310316a // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mattn/go-isatty v0.0.16 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
github.com/miekg/dns v1.1.50 // indirect
github.com/mimuret/golang-iij-dpf v0.7.1 // indirect
github.com/mailgun/raymond/v2 v2.0.48 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-runewidth v0.0.15 // indirect
github.com/microcosm-cc/bluemonday v1.0.26 // indirect
github.com/miekg/dns v1.1.63 // indirect
github.com/mimuret/golang-iij-dpf v0.9.1 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/namedotcom/go v0.0.0-20180403034216-08470befbe04 // indirect
github.com/nrdcg/auroradns v1.1.0 // indirect
github.com/nrdcg/desec v0.6.0 // indirect
github.com/nrdcg/bunny-go v0.0.0-20240207213615-dde5bf4577a3 // indirect
github.com/nrdcg/desec v0.7.0 // indirect
github.com/nrdcg/dnspod-go v0.4.0 // indirect
github.com/nrdcg/freemyip v0.2.0 // indirect
github.com/nrdcg/goinwx v0.8.1 // indirect
github.com/nrdcg/goinwx v0.10.0 // indirect
github.com/nrdcg/mailinabox v0.2.0 // indirect
github.com/nrdcg/namesilo v0.2.1 // indirect
github.com/nrdcg/porkbun v0.1.1 // indirect
github.com/onsi/ginkgo/v2 v2.8.0 // indirect
github.com/nrdcg/nodion v0.1.0 // indirect
github.com/nrdcg/porkbun v0.3.0 // indirect
github.com/nzdjb/go-metaname v1.0.0 // indirect
github.com/olekukonko/tablewriter v0.0.5 // indirect
github.com/onsi/ginkgo/v2 v2.19.0 // indirect
github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b // indirect
github.com/oracle/oci-go-sdk v24.3.0+incompatible // indirect
github.com/ovh/go-ovh v1.1.0 // indirect
github.com/ovh/go-ovh v1.4.3 // indirect
github.com/pelletier/go-toml v1.9.5 // indirect
github.com/pelletier/go-toml/v2 v2.0.6 // indirect
github.com/pires/go-proxyproto v0.6.2 // indirect
github.com/pelletier/go-toml/v2 v2.1.1 // indirect
github.com/pires/go-proxyproto v0.8.0 // indirect
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
github.com/pquerna/otp v1.3.0 // indirect
github.com/prometheus/client_golang v1.14.0 // indirect
github.com/prometheus/client_model v0.3.0 // indirect
github.com/prometheus/common v0.37.0 // indirect
github.com/prometheus/procfs v0.8.0 // indirect
github.com/quic-go/qtls-go1-18 v0.2.0 // indirect
github.com/quic-go/qtls-go1-19 v0.2.0 // indirect
github.com/quic-go/qtls-go1-20 v0.1.0 // indirect
github.com/quic-go/quic-go v0.32.0 // indirect
github.com/refraction-networking/utls v1.2.2-0.20230207151345-a75a4b484849 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect
github.com/pquerna/otp v1.4.0 // indirect
github.com/prometheus/client_golang v1.19.1 // indirect
github.com/prometheus/client_model v0.6.0 // indirect
github.com/prometheus/common v0.50.0 // indirect
github.com/prometheus/procfs v0.13.0 // indirect
github.com/quic-go/qpack v0.5.1 // indirect
github.com/quic-go/quic-go v0.50.0 // indirect
github.com/refraction-networking/utls v1.6.7 // indirect
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 // indirect
github.com/sacloud/api-client-go v0.2.1 // indirect
github.com/sacloud/go-http v0.1.2 // indirect
github.com/sacloud/iaas-api-go v1.3.2 // indirect
github.com/sacloud/packages-go v0.0.5 // indirect
github.com/sagernet/wireguard-go v0.0.0-20221116151939-c99467f53f2c // indirect
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.9 // indirect
github.com/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb // indirect
github.com/sirupsen/logrus v1.8.1 // indirect
github.com/rivo/uniseg v0.2.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/sacloud/api-client-go v0.2.10 // indirect
github.com/sacloud/go-http v0.1.8 // indirect
github.com/sacloud/iaas-api-go v1.11.2 // indirect
github.com/sacloud/packages-go v0.0.10 // indirect
github.com/sagikazarmark/locafero v0.4.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.25 // indirect
github.com/schollz/closestmatch v2.1.0+incompatible // indirect
github.com/seiflotfy/cuckoofilter v0.0.0-20240715131351-a2f2c23f1771 // indirect
github.com/shoenig/go-m1cpu v0.1.6 // indirect
github.com/shopspring/decimal v1.3.1 // indirect
github.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9 // indirect
github.com/softlayer/softlayer-go v1.0.6 // indirect
github.com/softlayer/softlayer-go v1.1.3 // indirect
github.com/softlayer/xmlrpc v0.0.0-20200409220501-5f089df7cb7e // indirect
github.com/spf13/afero v1.9.3 // indirect
github.com/spf13/cast v1.5.0 // indirect
github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
github.com/spf13/afero v1.11.0 // indirect
github.com/spf13/cast v1.6.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/stretchr/objx v0.5.0 // indirect
github.com/subosito/gotenv v1.4.2 // indirect
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.490 // indirect
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.490 // indirect
github.com/tklauser/go-sysconf v0.3.11 // indirect
github.com/tklauser/numcpus v0.6.0 // indirect
github.com/transip/gotransip/v6 v6.17.0 // indirect
github.com/stretchr/objx v0.5.2 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
github.com/tdewolff/minify/v2 v2.20.19 // indirect
github.com/tdewolff/parse/v2 v2.7.12 // indirect
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.878 // indirect
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.878 // indirect
github.com/tklauser/go-sysconf v0.3.13 // indirect
github.com/tklauser/numcpus v0.7.0 // indirect
github.com/transip/gotransip/v6 v6.23.0 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.12 // indirect
github.com/ultradns/ultradns-go-sdk v1.6.1-20231103022937-8589b6a // indirect
github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasttemplate v1.2.2 // indirect
github.com/vinyldns/go-vinyldns v0.9.16 // indirect
github.com/vishvananda/netlink v1.3.0 // indirect
github.com/vishvananda/netns v0.0.4 // indirect
github.com/vmihailenco/msgpack v4.0.4+incompatible // indirect
github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
github.com/vultr/govultr/v2 v2.17.2 // indirect
github.com/xtls/go v0.0.0-20230107031059-4610f88d00f3 // indirect
github.com/yandex-cloud/go-genproto v0.0.0-20220805142335-27b56ddae16f // indirect
github.com/yandex-cloud/go-sdk v0.0.0-20220805164847-cf028e604997 // indirect
github.com/yusufpapurcu/wmi v1.2.2 // indirect
github.com/xtls/reality v0.0.0-20240712055506-48f0b2d5ed6d // indirect
github.com/yandex-cloud/go-genproto v0.0.0-20240311082839-58e1a7554a75 // indirect
github.com/yandex-cloud/go-sdk v0.0.0-20240311083148-81c0846b96cd // indirect
github.com/yosssi/ace v0.0.5 // indirect
github.com/yusufpapurcu/wmi v1.2.4 // indirect
go.opencensus.io v0.24.0 // indirect
go.starlark.net v0.0.0-20230128213706-3f75dec8e403 // indirect
go.uber.org/atomic v1.10.0 // indirect
go.uber.org/ratelimit v0.2.0 // indirect
golang.org/x/exp v0.0.0-20230206171751-46f607a40771 // indirect
golang.org/x/mod v0.7.0 // indirect
golang.org/x/oauth2 v0.4.0 // indirect
golang.org/x/sys v0.5.0 // indirect
golang.org/x/text v0.7.0 // indirect
golang.org/x/tools v0.5.0 // indirect
google.golang.org/api v0.107.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20230202175211-008b39050e57 // indirect
google.golang.org/grpc v1.53.0 // indirect
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect
go.opentelemetry.io/otel v1.34.0 // indirect
go.opentelemetry.io/otel/metric v1.34.0 // indirect
go.opentelemetry.io/otel/sdk v1.34.0 // indirect
go.opentelemetry.io/otel/trace v1.34.0 // indirect
go.uber.org/atomic v1.11.0 // indirect
go.uber.org/mock v0.5.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/ratelimit v0.3.1 // indirect
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba // indirect
golang.org/x/arch v0.7.0 // indirect
golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc // indirect
golang.org/x/mod v0.21.0 // indirect
golang.org/x/oauth2 v0.25.0 // indirect
golang.org/x/sync v0.12.0 // indirect
golang.org/x/sys v0.31.0 // indirect
golang.org/x/text v0.23.0 // indirect
golang.org/x/tools v0.26.0 // indirect
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173 // indirect
google.golang.org/api v0.170.0 // indirect
google.golang.org/appengine v1.6.8 // indirect
google.golang.org/genproto v0.0.0-20240314234333-6e1732d8331c // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20250106144421-5f5ef82da422 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f // indirect
google.golang.org/grpc v1.71.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/ns1/ns1-go.v2 v2.6.5 // indirect
gopkg.in/square/go-jose.v2 v2.6.0 // indirect
gopkg.in/ns1/ns1-go.v2 v2.9.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
gvisor.dev/gvisor v0.0.0-20220901235040-6ca97ef2ce1c // indirect
lukechampine.com/blake3 v1.1.7 // indirect
gvisor.dev/gvisor v0.0.0-20240320123526-dc6abceb7ff0 // indirect
k8s.io/api v0.29.2 // indirect
k8s.io/apimachinery v0.29.2 // indirect
k8s.io/klog/v2 v2.120.1 // indirect
k8s.io/utils v0.0.0-20240310230437-4693a0247e57 // indirect
lukechampine.com/blake3 v1.4.0 // indirect
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
)
replace github.com/exoscale/egoscale => github.com/exoscale/egoscale v0.102.3

2074
go.sum

File diff suppressed because it is too large Load Diff

13
main.go Normal file
View File

@ -0,0 +1,13 @@
package main
import (
log "github.com/sirupsen/logrus"
"github.com/XrayR-project/XrayR/cmd"
)
func main() {
if err := cmd.Execute(); err != nil {
log.Fatal(err)
}
}

View File

@ -1,91 +0,0 @@
Log:
Level: warning # Log level: none, error, warning, info, debug
AccessPath: # /etc/XrayR/access.Log
ErrorPath: # /etc/XrayR/error.log
DnsConfigPath: # /etc/XrayR/dns.json # Path to dns config, check https://xtls.github.io/config/dns.html for help
RouteConfigPath: # /etc/XrayR/route.json # Path to route config, check https://xtls.github.io/config/routing.html for help
InboundConfigPath: # /etc/XrayR/custom_inbound.json # Path to custom inbound config, check https://xtls.github.io/config/inbound.html for help
OutboundConfigPath: # /etc/XrayR/custom_outbound.json # Path to custom outbound config, check https://xtls.github.io/config/outbound.html for help
ConnectionConfig:
Handshake: 4 # Handshake time limit, Second
ConnIdle: 30 # Connection idle time limit, Second
UplinkOnly: 2 # Time limit when the connection downstream is closed, Second
DownlinkOnly: 4 # Time limit when the connection is closed after the uplink is closed, Second
BufferSize: 64 # The internal cache size of each connection, kB
Nodes:
-
PanelType: "SSpanel" # Panel type: SSpanel, V2board, NewV2board, PMpanel, Proxypanel, V2RaySocks
ApiConfig:
ApiHost: "http://127.0.0.1:667"
ApiKey: "123"
NodeID: 41
NodeType: V2ray # Node type: V2ray, Shadowsocks, Trojan, Shadowsocks-Plugin
Timeout: 30 # Timeout for the api request
EnableVless: false # Enable Vless for V2ray Type
EnableXTLS: false # Enable XTLS for V2ray and Trojan
SpeedLimit: 0 # Mbps, Local settings will replace remote settings, 0 means disable
DeviceLimit: 0 # Local settings will replace remote settings, 0 means disable
RuleListPath: # /etc/XrayR/rulelist Path to local rulelist file
ControllerConfig:
ListenIP: 0.0.0.0 # IP address you want to listen
SendIP: 0.0.0.0 # IP address you want to send pacakage
UpdatePeriodic: 60 # Time to update the nodeinfo, how many sec.
EnableDNS: false # Use custom DNS config, Please ensure that you set the dns.json well
DNSType: AsIs # AsIs, UseIP, UseIPv4, UseIPv6, DNS strategy
EnableProxyProtocol: false # Only works for WebSocket and TCP
AutoSpeedLimitConfig:
Limit: 0 # Warned speed. Set to 0 to disable AutoSpeedLimit (mbps)
WarnTimes: 0 # After (WarnTimes) consecutive warnings, the user will be limited. Set to 0 to punish overspeed user immediately.
LimitSpeed: 0 # The speedlimit of a limited user (unit: mbps)
LimitDuration: 0 # How many minutes will the limiting last (unit: minute)
GlobalDeviceLimitConfig:
Enable: false # Enable the global device limit of a user
RedisAddr: 127.0.0.1:6379 # The redis server address
RedisPassword: YOUR PASSWORD # Redis password
RedisDB: 0 # Redis DB
Timeout: 5 # Timeout for redis request
Expiry: 60 # Expiry time (second)
EnableFallback: false # Only support for Trojan and Vless
FallBackConfigs: # Support multiple fallbacks
-
SNI: # TLS SNI(Server Name Indication), Empty for any
Alpn: # Alpn, Empty for any
Path: # HTTP PATH, Empty for any
Dest: 80 # Required, Destination of fallback, check https://xtls.github.io/config/features/fallback.html for details.
ProxyProtocolVer: 0 # Send PROXY protocol version, 0 for dsable
CertConfig:
CertMode: dns # Option about how to get certificate: none, file, http, tls, dns. Choose "none" will forcedly disable the tls config.
CertDomain: "node1.test.com" # Domain to cert
CertFile: /etc/XrayR/cert/node1.test.com.cert # Provided if the CertMode is file
KeyFile: /etc/XrayR/cert/node1.test.com.key
Provider: alidns # DNS cert provider, Get the full support list here: https://go-acme.github.io/lego/dns/
Email: test@me.com
DNSEnv: # DNS ENV option used by DNS provider
ALICLOUD_ACCESS_KEY: aaa
ALICLOUD_SECRET_KEY: bbb
# -
# PanelType: "NewV2board" # Panel type: SSpanel, V2board, NewV2board, PMpanel, Proxypanel, V2RaySocks
# ApiConfig:
# ApiHost: "http://127.0.0.1:668"
# ApiKey: "123"
# NodeID: 4
# NodeType: Shadowsocks # Node type: V2ray, Shadowsocks, Trojan
# Timeout: 30 # Timeout for the api request
# EnableVless: false # Enable Vless for V2ray Type
# EnableXTLS: false # Enable XTLS for V2ray and Trojan
# SpeedLimit: 0 # Mbps, Local settings will replace remote settings
# DeviceLimit: 0 # Local settings will replace remote settings
# ControllerConfig:
# ListenIP: 0.0.0.0 # IP address you want to listen
# UpdatePeriodic: 10 # Time to update the nodeinfo, how many sec.
# EnableDNS: false # Use custom DNS config, Please ensure that you set the dns.json well
# CertConfig:
# CertMode: dns # Option about how to get certificate: none, file, http, dns
# CertDomain: "node1.test.com" # Domain to cert
# CertFile: /etc/XrayR/cert/node1.test.com.cert # Provided if the CertMode is file
# KeyFile: /etc/XrayR/cert/node1.test.com.pem
# Provider: alidns # DNS cert provider, Get the full support list here: https://go-acme.github.io/lego/dns/
# Email: test@me.com
# DNSEnv: # DNS ENV option used by DNS provider
# ALICLOUD_ACCESS_KEY: aaa
# ALICLOUD_SECRET_KEY: bbb

View File

@ -2,15 +2,12 @@ package panel
import (
"encoding/json"
"log"
"os"
"sync"
"github.com/XrayR-project/XrayR/api/newV2board"
"github.com/XrayR-project/XrayR/app/mydispatcher"
"github.com/imdario/mergo"
"dario.cat/mergo"
"github.com/r3labs/diff/v2"
log "github.com/sirupsen/logrus"
"github.com/xtls/xray-core/app/proxyman"
"github.com/xtls/xray-core/app/stats"
"github.com/xtls/xray-core/common/serial"
@ -18,12 +15,15 @@ import (
"github.com/xtls/xray-core/infra/conf"
"github.com/XrayR-project/XrayR/api"
"github.com/XrayR-project/XrayR/api/bunpanel"
"github.com/XrayR-project/XrayR/api/gov2panel"
"github.com/XrayR-project/XrayR/api/newV2board"
"github.com/XrayR-project/XrayR/api/pmpanel"
"github.com/XrayR-project/XrayR/api/proxypanel"
"github.com/XrayR-project/XrayR/api/sspanel"
"github.com/XrayR-project/XrayR/api/v2board"
"github.com/XrayR-project/XrayR/api/v2raysocks"
_ "github.com/XrayR-project/XrayR/main/distro/all"
"github.com/XrayR-project/XrayR/app/mydispatcher"
_ "github.com/XrayR-project/XrayR/cmd/distro/all"
"github.com/XrayR-project/XrayR/service"
"github.com/XrayR-project/XrayR/service/controller"
)
@ -154,7 +154,6 @@ func (p *Panel) loadCore(panelConfig *Config) *core.Instance {
if err != nil {
log.Panicf("failed to create instance: %s", err)
}
log.Printf("Xray Core Version: %s", core.Version())
return server
}
@ -177,10 +176,7 @@ func (p *Panel) Start() {
switch nodeConfig.PanelType {
case "SSpanel":
apiClient = sspanel.New(nodeConfig.ApiConfig)
// todo Deprecated after 2023.6.1
case "V2board":
apiClient = v2board.New(nodeConfig.ApiConfig)
case "NewV2board":
case "NewV2board", "V2board":
apiClient = newV2board.New(nodeConfig.ApiConfig)
case "PMpanel":
apiClient = pmpanel.New(nodeConfig.ApiConfig)
@ -188,6 +184,10 @@ func (p *Panel) Start() {
apiClient = proxypanel.New(nodeConfig.ApiConfig)
case "V2RaySocks":
apiClient = v2raysocks.New(nodeConfig.ApiConfig)
case "GoV2Panel":
apiClient = gov2panel.New(nodeConfig.ApiConfig)
case "BunPanel":
apiClient = bunpanel.New(nodeConfig.ApiConfig)
default:
log.Panicf("Unsupport panel type: %s", nodeConfig.PanelType)
}
@ -208,7 +208,7 @@ func (p *Panel) Start() {
for _, s := range p.Service {
err := s.Start()
if err != nil {
log.Panicf("Panel Start fialed: %s", err)
log.Panicf("Panel Start failed: %s", err)
}
}
p.Running = true
@ -222,7 +222,7 @@ func (p *Panel) Close() {
for _, s := range p.Service {
err := s.Close()
if err != nil {
log.Panicf("Panel Close fialed: %s", err)
log.Panicf("Panel Close failed: %s", err)
}
}
p.Service = nil

View File

@ -0,0 +1,144 @@
Log:
Level: warning # Log level: none, error, warning, info, debug
AccessPath: # /etc/XrayR/access.Log
ErrorPath: # /etc/XrayR/error.log
DnsConfigPath: # /etc/XrayR/dns.json # Path to dns config, check https://xtls.github.io/config/dns.html for help
RouteConfigPath: # /etc/XrayR/route.json # Path to route config, check https://xtls.github.io/config/routing.html for help
InboundConfigPath: # /etc/XrayR/custom_inbound.json # Path to custom inbound config, check https://xtls.github.io/config/inbound.html for help
OutboundConfigPath: # /etc/XrayR/custom_outbound.json # Path to custom outbound config, check https://xtls.github.io/config/outbound.html for help
ConnectionConfig:
Handshake: 4 # Handshake time limit, Second
ConnIdle: 30 # Connection idle time limit, Second
UplinkOnly: 2 # Time limit when the connection downstream is closed, Second
DownlinkOnly: 4 # Time limit when the connection is closed after the uplink is closed, Second
BufferSize: 64 # The internal cache size of each connection, kB
Nodes:
- PanelType: "SSpanel" # Panel type: SSpanel, NewV2board, PMpanel, Proxypanel, V2RaySocks, GoV2Panel, BunPanel
ApiConfig:
ApiHost: "http://127.0.0.1:667"
ApiKey: "123"
NodeID: 41
NodeType: V2ray # Node type: V2ray, Vmess, Vless, Shadowsocks, Trojan, Shadowsocks-Plugin
Timeout: 30 # Timeout for the api request
EnableVless: false # Enable Vless for V2ray Type
VlessFlow: "xtls-rprx-vision" # Only support vless
SpeedLimit: 0 # Mbps, Local settings will replace remote settings, 0 means disable
DeviceLimit: 0 # Local settings will replace remote settings, 0 means disable
RuleListPath: # /etc/XrayR/rulelist Path to local rulelist file
DisableCustomConfig: false # disable custom config for sspanel
ControllerConfig:
ListenIP: 0.0.0.0 # IP address you want to listen
SendIP: 0.0.0.0 # IP address you want to send pacakage
UpdatePeriodic: 60 # Time to update the nodeinfo, how many sec.
EnableDNS: false # Use custom DNS config, Please ensure that you set the dns.json well
DNSType: AsIs # AsIs, UseIP, UseIPv4, UseIPv6, DNS strategy
EnableProxyProtocol: false # Only works for WebSocket and TCP
AutoSpeedLimitConfig:
Limit: 0 # Warned speed. Set to 0 to disable AutoSpeedLimit (mbps)
WarnTimes: 0 # After (WarnTimes) consecutive warnings, the user will be limited. Set to 0 to punish overspeed user immediately.
LimitSpeed: 0 # The speedlimit of a limited user (unit: mbps)
LimitDuration: 0 # How many minutes will the limiting last (unit: minute)
GlobalDeviceLimitConfig:
Enable: false # Enable the global device limit of a user
RedisNetwork: tcp # Redis protocol, tcp or unix
RedisAddr: 127.0.0.1:6379 # Redis server address, or unix socket path
RedisUsername: # Redis username
RedisPassword: YOUR PASSWORD # Redis password
RedisDB: 0 # Redis DB
Timeout: 5 # Timeout for redis request
Expiry: 60 # Expiry time (second)
EnableFallback: false # Only support for Trojan and Vless
FallBackConfigs: # Support multiple fallbacks
- SNI: # TLS SNI(Server Name Indication), Empty for any
Alpn: # Alpn, Empty for any
Path: # HTTP PATH, Empty for any
Dest: 80 # Required, Destination of fallback, check https://xtls.github.io/config/features/fallback.html for details.
ProxyProtocolVer: 0 # Send PROXY protocol version, 0 for disable
DisableLocalREALITYConfig: false # disable local reality config
EnableREALITY: false # Enable REALITY
REALITYConfigs:
Show: true # Show REALITY debug
Dest: www.amazon.com:443 # Required, Same as fallback
ProxyProtocolVer: 0 # Send PROXY protocol version, 0 for disable
ServerNames: # Required, list of available serverNames for the client, * wildcard is not supported at the moment.
- www.amazon.com
PrivateKey: YOUR_PRIVATE_KEY # Required, execute './XrayR x25519' to generate.
MinClientVer: # Optional, minimum version of Xray client, format is x.y.z.
MaxClientVer: # Optional, maximum version of Xray client, format is x.y.z.
MaxTimeDiff: 0 # Optional, maximum allowed time difference, unit is in milliseconds.
ShortIds: # Required, list of available shortIds for the client, can be used to differentiate between different clients.
- ""
- 0123456789abcdef
CertConfig:
CertMode: dns # Option about how to get certificate: none, file, http, tls, dns. Choose "none" will forcedly disable the tls config.
CertDomain: "node1.test.com" # Domain to cert
CertFile: /etc/XrayR/cert/node1.test.com.cert # Provided if the CertMode is file
KeyFile: /etc/XrayR/cert/node1.test.com.key
Provider: alidns # DNS cert provider, Get the full support list here: https://go-acme.github.io/lego/dns/
Email: test@me.com
DNSEnv: # DNS ENV option used by DNS provider
ALICLOUD_ACCESS_KEY: aaa
ALICLOUD_SECRET_KEY: bbb
# - PanelType: "SSpanel" # Panel type: SSpanel, V2board, NewV2board, PMpanel, Proxypanel, V2RaySocks, GoV2Panel
# ApiConfig:
# ApiHost: "http://127.0.0.1:668"
# ApiKey: "123"
# NodeID: 41
# NodeType: V2ray # Node type: V2ray, Shadowsocks, Trojan, Shadowsocks-Plugin
# Timeout: 30 # Timeout for the api request
# EnableVless: false # Enable Vless for V2ray Type
# VlessFlow: "xtls-rprx-vision" # Only support vless
# SpeedLimit: 0 # Mbps, Local settings will replace remote settings, 0 means disable
# DeviceLimit: 0 # Local settings will replace remote settings, 0 means disable
# RuleListPath: # /etc/XrayR/rulelist Path to local rulelist file
# ControllerConfig:
# ListenIP: 0.0.0.0 # IP address you want to listen
# SendIP: 0.0.0.0 # IP address you want to send pacakage
# UpdatePeriodic: 60 # Time to update the nodeinfo, how many sec.
# EnableDNS: false # Use custom DNS config, Please ensure that you set the dns.json well
# DNSType: AsIs # AsIs, UseIP, UseIPv4, UseIPv6, DNS strategy
# EnableProxyProtocol: false # Only works for WebSocket and TCP
# AutoSpeedLimitConfig:
# Limit: 0 # Warned speed. Set to 0 to disable AutoSpeedLimit (mbps)
# WarnTimes: 0 # After (WarnTimes) consecutive warnings, the user will be limited. Set to 0 to punish overspeed user immediately.
# LimitSpeed: 0 # The speedlimit of a limited user (unit: mbps)
# LimitDuration: 0 # How many minutes will the limiting last (unit: minute)
# GlobalDeviceLimitConfig:
# Enable: false # Enable the global device limit of a user
# RedisAddr: 127.0.0.1:6379 # The redis server address
# RedisPassword: YOUR PASSWORD # Redis password
# RedisDB: 0 # Redis DB
# Timeout: 5 # Timeout for redis request
# Expiry: 60 # Expiry time (second)
# EnableFallback: false # Only support for Trojan and Vless
# FallBackConfigs: # Support multiple fallbacks
# - SNI: # TLS SNI(Server Name Indication), Empty for any
# Alpn: # Alpn, Empty for any
# Path: # HTTP PATH, Empty for any
# Dest: 80 # Required, Destination of fallback, check https://xtls.github.io/config/features/fallback.html for details.
# ProxyProtocolVer: 0 # Send PROXY protocol version, 0 for disable
# EnableREALITY: true # Enable REALITY
# REALITYConfigs:
# Show: true # Show REALITY debug
# Dest: www.amazon.com:443 # Required, Same as fallback
# ProxyProtocolVer: 0 # Send PROXY protocol version, 0 for disable
# ServerNames: # Required, list of available serverNames for the client, * wildcard is not supported at the moment.
# - www.amazon.com
# PrivateKey: YOUR_PRIVATE_KEY # Required, execute './XrayR x25519' to generate.
# MinClientVer: # Optional, minimum version of Xray client, format is x.y.z.
# MaxClientVer: # Optional, maximum version of Xray client, format is x.y.z.
# MaxTimeDiff: 0 # Optional, maximum allowed time difference, unit is in milliseconds.
# ShortIds: # Required, list of available shortIds for the client, can be used to differentiate between different clients.
# - ""
# - 0123456789abcdef
# CertConfig:
# CertMode: dns # Option about how to get certificate: none, file, http, tls, dns. Choose "none" will forcedly disable the tls config.
# CertDomain: "node1.test.com" # Domain to cert
# CertFile: /etc/XrayR/cert/node1.test.com.cert # Provided if the CertMode is file
# KeyFile: /etc/XrayR/cert/node1.test.com.key
# Provider: alidns # DNS cert provider, Get the full support list here: https://go-acme.github.io/lego/dns/
# Email: test@me.com
# DNSEnv: # DNS ENV option used by DNS provider
# ALICLOUD_ACCESS_KEY: aaa
# ALICLOUD_SECRET_KEY: bbb

View File

@ -1,6 +1,6 @@
[
{
"listen": "0.0.0.0",
"listen": "127.0.0.1",
"port": 1234,
"protocol": "socks",
"settings": {

View File

@ -6,21 +6,24 @@ import (
)
type Config struct {
ListenIP string `mapstructure:"ListenIP"`
SendIP string `mapstructure:"SendIP"`
UpdatePeriodic int `mapstructure:"UpdatePeriodic"`
CertConfig *mylego.CertConfig `mapstructure:"CertConfig"`
EnableDNS bool `mapstructure:"EnableDNS"`
DNSType string `mapstructure:"DNSType"`
DisableUploadTraffic bool `mapstructure:"DisableUploadTraffic"`
DisableGetRule bool `mapstructure:"DisableGetRule"`
EnableProxyProtocol bool `mapstructure:"EnableProxyProtocol"`
EnableFallback bool `mapstructure:"EnableFallback"`
DisableIVCheck bool `mapstructure:"DisableIVCheck"`
DisableSniffing bool `mapstructure:"DisableSniffing"`
AutoSpeedLimitConfig *AutoSpeedLimitConfig `mapstructure:"AutoSpeedLimitConfig"`
GlobalDeviceLimitConfig *limiter.GlobalDeviceLimitConfig `mapstructure:"GlobalDeviceLimitConfig"`
FallBackConfigs []*FallBackConfig `mapstructure:"FallBackConfigs"`
ListenIP string `mapstructure:"ListenIP"`
SendIP string `mapstructure:"SendIP"`
UpdatePeriodic int `mapstructure:"UpdatePeriodic"`
CertConfig *mylego.CertConfig `mapstructure:"CertConfig"`
EnableDNS bool `mapstructure:"EnableDNS"`
DNSType string `mapstructure:"DNSType"`
DisableUploadTraffic bool `mapstructure:"DisableUploadTraffic"`
DisableGetRule bool `mapstructure:"DisableGetRule"`
EnableProxyProtocol bool `mapstructure:"EnableProxyProtocol"`
EnableFallback bool `mapstructure:"EnableFallback"`
DisableIVCheck bool `mapstructure:"DisableIVCheck"`
DisableSniffing bool `mapstructure:"DisableSniffing"`
AutoSpeedLimitConfig *AutoSpeedLimitConfig `mapstructure:"AutoSpeedLimitConfig"`
GlobalDeviceLimitConfig *limiter.GlobalDeviceLimitConfig `mapstructure:"GlobalDeviceLimitConfig"`
FallBackConfigs []*FallBackConfig `mapstructure:"FallBackConfigs"`
DisableLocalREALITYConfig bool `mapstructure:"DisableLocalREALITYConfig"`
EnableREALITY bool `mapstructure:"EnableREALITY"`
REALITYConfigs *REALITYConfig `mapstructure:"REALITYConfigs"`
}
type AutoSpeedLimitConfig struct {
@ -37,3 +40,15 @@ type FallBackConfig struct {
Dest string `mapstructure:"Dest"`
ProxyProtocolVer uint64 `mapstructure:"ProxyProtocolVer"`
}
type REALITYConfig struct {
Show bool `mapstructure:"Show"`
Dest string `mapstructure:"Dest"`
ProxyProtocolVer uint64 `mapstructure:"ProxyProtocolVer"`
ServerNames []string `mapstructure:"ServerNames"`
PrivateKey string `mapstructure:"PrivateKey"`
MinClientVer string `mapstructure:"MinClientVer"`
MaxClientVer string `mapstructure:"MaxClientVer"`
MaxTimeDiff uint64 `mapstructure:"MaxTimeDiff"`
ShortIds []string `mapstructure:"ShortIds"`
}

View File

@ -1,11 +1,12 @@
package controller
import (
"errors"
"fmt"
"log"
"reflect"
"time"
log "github.com/sirupsen/logrus"
"github.com/xtls/xray-core/common/protocol"
"github.com/xtls/xray-core/common/task"
"github.com/xtls/xray-core/core"
@ -43,6 +44,7 @@ type Controller struct {
stm stats.Manager
dispatcher *mydispatcher.DefaultDispatcher
startAt time.Time
logger *log.Entry
}
type periodicTask struct {
@ -52,6 +54,11 @@ type periodicTask struct {
// New return a Controller service with default parameters.
func New(server *core.Instance, api api.API, config *Config, panelType string) *Controller {
logger := log.NewEntry(log.StandardLogger()).WithFields(log.Fields{
"Host": api.Describe().APIHost,
"Type": api.Describe().NodeType,
"ID": api.Describe().NodeID,
})
controller := &Controller{
server: server,
config: config,
@ -62,6 +69,7 @@ func New(server *core.Instance, api api.API, config *Config, panelType string) *
stm: server.GetFeature(stats.ManagerType()).(stats.Manager),
dispatcher: server.GetFeature(routing.DispatcherType()).(*mydispatcher.DefaultDispatcher),
startAt: time.Now(),
logger: logger,
}
return controller
@ -75,13 +83,16 @@ func (c *Controller) Start() error {
if err != nil {
return err
}
if newNodeInfo.Port == 0 {
return errors.New("server port must > 0")
}
c.nodeInfo = newNodeInfo
c.Tag = c.buildNodeTag()
// Add new tag
err = c.addNewTag(newNodeInfo)
if err != nil {
log.Panic(err)
c.logger.Panic(err)
return err
}
// Update user
@ -100,16 +111,16 @@ func (c *Controller) Start() error {
// Add Limiter
if err := c.AddInboundLimiter(c.Tag, newNodeInfo.SpeedLimit, userInfo, c.config.GlobalDeviceLimitConfig); err != nil {
log.Print(err)
c.logger.Print(err)
}
// Add Rule Manager
if !c.config.DisableGetRule {
if ruleList, err := c.apiClient.GetNodeRule(); err != nil {
log.Printf("Get rule list filed: %s", err)
c.logger.Printf("Get rule list filed: %s", err)
} else if len(*ruleList) > 0 {
if err := c.UpdateRule(c.Tag, *ruleList); err != nil {
log.Print(err)
c.logger.Print(err)
}
}
}
@ -140,7 +151,7 @@ func (c *Controller) Start() error {
)
// Check cert service in need
if c.nodeInfo.EnableTLS {
if c.nodeInfo.EnableTLS && c.config.EnableREALITY == false {
c.tasks = append(c.tasks, periodicTask{
tag: "cert monitor",
Periodic: &task.Periodic{
@ -151,7 +162,7 @@ func (c *Controller) Start() error {
// Start periodic tasks
for i := range c.tasks {
log.Printf("%s Start %s periodic task", c.logPrefix(), c.tasks[i].tag)
c.logger.Printf("Start %s periodic task", c.tasks[i].tag)
go c.tasks[i].Start()
}
@ -163,7 +174,7 @@ func (c *Controller) Close() error {
for i := range c.tasks {
if c.tasks[i].Periodic != nil {
if err := c.tasks[i].Periodic.Close(); err != nil {
log.Panicf("%s %s periodic task close failed: %s", c.logPrefix(), c.tasks[i].tag, err)
c.logger.Panicf("%s periodic task close failed: %s", c.tasks[i].tag, err)
}
}
}
@ -178,65 +189,79 @@ func (c *Controller) nodeInfoMonitor() (err error) {
}
// First fetch Node Info
var nodeInfoChanged = true
newNodeInfo, err := c.apiClient.GetNodeInfo()
if err != nil {
log.Print(err)
return nil
if err.Error() == api.NodeNotModified {
nodeInfoChanged = false
newNodeInfo = c.nodeInfo
} else {
c.logger.Print(err)
return nil
}
}
if newNodeInfo.Port == 0 {
return errors.New("server port must > 0")
}
// Update User
var usersChanged = true
newUserInfo, err := c.apiClient.GetUserList()
if err != nil {
if err.Error() == "users no change" {
if err.Error() == api.UserNotModified {
usersChanged = false
newUserInfo = c.userList
} else {
log.Print(err)
c.logger.Print(err)
return nil
}
}
var nodeInfoChanged = false
// If nodeInfo changed
if !reflect.DeepEqual(c.nodeInfo, newNodeInfo) {
// Remove old tag
oldTag := c.Tag
err := c.removeOldTag(oldTag)
if err != nil {
log.Print(err)
return nil
}
if c.nodeInfo.NodeType == "Shadowsocks-Plugin" {
err = c.removeOldTag(fmt.Sprintf("dokodemo-door_%s+1", c.Tag))
}
if err != nil {
log.Print(err)
return nil
}
// Add new tag
c.nodeInfo = newNodeInfo
c.Tag = c.buildNodeTag()
err = c.addNewTag(newNodeInfo)
if err != nil {
log.Print(err)
return nil
}
nodeInfoChanged = true
// Remove Old limiter
if err = c.DeleteInboundLimiter(oldTag); err != nil {
log.Print(err)
return nil
if nodeInfoChanged {
if !reflect.DeepEqual(c.nodeInfo, newNodeInfo) {
// Remove old tag
oldTag := c.Tag
err := c.removeOldTag(oldTag)
if err != nil {
c.logger.Print(err)
return nil
}
if c.nodeInfo.NodeType == "Shadowsocks-Plugin" {
err = c.removeOldTag(fmt.Sprintf("dokodemo-door_%s+1", c.Tag))
}
if err != nil {
c.logger.Print(err)
return nil
}
// Add new tag
c.nodeInfo = newNodeInfo
c.Tag = c.buildNodeTag()
err = c.addNewTag(newNodeInfo)
if err != nil {
c.logger.Print(err)
return nil
}
nodeInfoChanged = true
// Remove Old limiter
if err = c.DeleteInboundLimiter(oldTag); err != nil {
c.logger.Print(err)
return nil
}
} else {
nodeInfoChanged = false
}
}
// Check Rule
if !c.config.DisableGetRule {
if ruleList, err := c.apiClient.GetNodeRule(); err != nil {
log.Printf("Get rule list filed: %s", err)
if err.Error() != api.RuleNotModified {
c.logger.Printf("Get rule list filed: %s", err)
}
} else if len(*ruleList) > 0 {
if err := c.UpdateRule(c.Tag, *ruleList); err != nil {
log.Print(err)
c.logger.Print(err)
}
}
}
@ -244,13 +269,13 @@ func (c *Controller) nodeInfoMonitor() (err error) {
if nodeInfoChanged {
err = c.addNewUser(newUserInfo, newNodeInfo)
if err != nil {
log.Print(err)
c.logger.Print(err)
return nil
}
// Add Limiter
if err := c.AddInboundLimiter(c.Tag, newNodeInfo.SpeedLimit, newUserInfo, c.config.GlobalDeviceLimitConfig); err != nil {
log.Print(err)
c.logger.Print(err)
return nil
}
@ -265,21 +290,21 @@ func (c *Controller) nodeInfoMonitor() (err error) {
}
err := c.removeUsers(deletedEmail, c.Tag)
if err != nil {
log.Print(err)
c.logger.Print(err)
}
}
if len(added) > 0 {
err = c.addNewUser(&added, c.nodeInfo)
if err != nil {
log.Print(err)
c.logger.Print(err)
}
// Update Limiter
if err := c.UpdateInboundLimiter(c.Tag, &added); err != nil {
log.Print(err)
c.logger.Print(err)
}
}
}
log.Printf("%s %d user deleted, %d user added", c.logPrefix(), len(deleted), len(added))
c.logger.Printf("%d user deleted, %d user added", len(deleted), len(added))
}
c.userList = newUserInfo
return nil
@ -380,18 +405,11 @@ func (c *Controller) addInboundForSSPlugin(newNodeInfo api.NodeInfo) (err error)
func (c *Controller) addNewUser(userInfo *[]api.UserInfo, nodeInfo *api.NodeInfo) (err error) {
users := make([]*protocol.User, 0)
switch nodeInfo.NodeType {
case "V2ray":
if nodeInfo.EnableVless {
case "V2ray", "Vmess", "Vless":
if nodeInfo.EnableVless || (nodeInfo.NodeType == "Vless" && nodeInfo.NodeType != "Vmess") {
users = c.buildVlessUser(userInfo)
} else {
var alterID uint16 = 0
if (c.panelType == "V2board" || c.panelType == "V2RaySocks") && len(*userInfo) > 0 {
// use latest userInfo
alterID = (*userInfo)[0].AlterID
} else {
alterID = nodeInfo.AlterID
}
users = c.buildVmessUser(userInfo, alterID)
users = c.buildVmessUser(userInfo)
}
case "Trojan":
users = c.buildTrojanUser(userInfo)
@ -407,7 +425,7 @@ func (c *Controller) addNewUser(userInfo *[]api.UserInfo, nodeInfo *api.NodeInfo
if err != nil {
return err
}
log.Printf("%s Added %d new users", c.logPrefix(), len(*userInfo))
c.logger.Printf("Added %d new users", len(*userInfo))
return nil
}
@ -455,7 +473,7 @@ func limitUser(c *Controller, user api.UserInfo, silentUsers *[]api.UserInfo) {
currentSpeedLimit: c.config.AutoSpeedLimitConfig.LimitSpeed,
originSpeedLimit: user.SpeedLimit,
}
log.Printf("Limit User: %s Speed: %d End: %s", c.buildUserTag(&user), c.config.AutoSpeedLimitConfig.LimitSpeed, time.Unix(c.limitedUsers[user].end, 0).Format("01-02 15:04:05"))
c.logger.Printf("Limit User: %s Speed: %d End: %s", c.buildUserTag(&user), c.config.AutoSpeedLimitConfig.LimitSpeed, time.Unix(c.limitedUsers[user].end, 0).Format("01-02 15:04:05"))
user.SpeedLimit = uint64((c.config.AutoSpeedLimitConfig.LimitSpeed * 1000000) / 8)
*silentUsers = append(*silentUsers, user)
}
@ -469,7 +487,7 @@ func (c *Controller) userInfoMonitor() (err error) {
// Get server status
CPU, Mem, Disk, Uptime, err := serverstatus.GetSystemInfo()
if err != nil {
log.Print(err)
c.logger.Print(err)
}
err = c.apiClient.ReportNodeStatus(
&api.NodeStatus{
@ -479,25 +497,25 @@ func (c *Controller) userInfoMonitor() (err error) {
Uptime: Uptime,
})
if err != nil {
log.Print(err)
c.logger.Print(err)
}
// Unlock users
if c.config.AutoSpeedLimitConfig.Limit > 0 && len(c.limitedUsers) > 0 {
log.Printf("%s Limited users:", c.logPrefix())
c.logger.Printf("Limited users:")
toReleaseUsers := make([]api.UserInfo, 0)
for user, limitInfo := range c.limitedUsers {
if time.Now().Unix() > limitInfo.end {
user.SpeedLimit = limitInfo.originSpeedLimit
toReleaseUsers = append(toReleaseUsers, user)
log.Printf("User: %s Speed: %d End: nil (Unlimit)", c.buildUserTag(&user), user.SpeedLimit)
c.logger.Printf("User: %s Speed: %d End: nil (Unlimit)", c.buildUserTag(&user), user.SpeedLimit)
delete(c.limitedUsers, user)
} else {
log.Printf("User: %s Speed: %d End: %s", c.buildUserTag(&user), limitInfo.currentSpeedLimit, time.Unix(c.limitedUsers[user].end, 0).Format("01-02 15:04:05"))
c.logger.Printf("User: %s Speed: %d End: %s", c.buildUserTag(&user), limitInfo.currentSpeedLimit, time.Unix(c.limitedUsers[user].end, 0).Format("01-02 15:04:05"))
}
}
if len(toReleaseUsers) > 0 {
if err := c.UpdateInboundLimiter(c.Tag, &toReleaseUsers); err != nil {
log.Print(err)
c.logger.Print(err)
}
}
}
@ -548,7 +566,7 @@ func (c *Controller) userInfoMonitor() (err error) {
}
if len(limitedUsers) > 0 {
if err := c.UpdateInboundLimiter(c.Tag, &limitedUsers); err != nil {
log.Print(err)
c.logger.Print(err)
}
}
if len(userTraffic) > 0 {
@ -558,7 +576,7 @@ func (c *Controller) userInfoMonitor() (err error) {
}
// If report traffic error, not clear the traffic
if err != nil {
log.Print(err)
c.logger.Print(err)
} else {
c.resetTraffic(&upCounterList, &downCounterList)
}
@ -566,23 +584,23 @@ func (c *Controller) userInfoMonitor() (err error) {
// Report Online info
if onlineDevice, err := c.GetOnlineDevice(c.Tag); err != nil {
log.Print(err)
c.logger.Print(err)
} else if len(*onlineDevice) > 0 {
if err = c.apiClient.ReportNodeOnlineUsers(onlineDevice); err != nil {
log.Print(err)
c.logger.Print(err)
} else {
log.Printf("%s Report %d online users", c.logPrefix(), len(*onlineDevice))
c.logger.Printf("Report %d online users", len(*onlineDevice))
}
}
// Report Illegal user
if detectResult, err := c.GetDetectResult(c.Tag); err != nil {
log.Print(err)
c.logger.Print(err)
} else if len(*detectResult) > 0 {
if err = c.apiClient.ReportIllegal(detectResult); err != nil {
log.Print(err)
c.logger.Print(err)
} else {
log.Printf("%s Report %d illegal behaviors", c.logPrefix(), len(*detectResult))
c.logger.Printf("Report %d illegal behaviors", len(*detectResult))
}
}
@ -593,23 +611,23 @@ func (c *Controller) buildNodeTag() string {
return fmt.Sprintf("%s_%s_%d", c.nodeInfo.NodeType, c.config.ListenIP, c.nodeInfo.Port)
}
func (c *Controller) logPrefix() string {
return fmt.Sprintf("[%s] %s(ID=%d)", c.clientInfo.APIHost, c.nodeInfo.NodeType, c.nodeInfo.NodeID)
}
// func (c *Controller) logPrefix() string {
// return fmt.Sprintf("[%s] %s(ID=%d)", c.clientInfo.APIHost, c.nodeInfo.NodeType, c.nodeInfo.NodeID)
// }
// Check Cert
func (c *Controller) certMonitor() error {
if c.nodeInfo.EnableTLS {
if c.nodeInfo.EnableTLS && c.config.EnableREALITY == false {
switch c.config.CertConfig.CertMode {
case "dns", "http", "tls":
lego, err := mylego.New(c.config.CertConfig)
if err != nil {
log.Print(err)
c.logger.Print(err)
}
// Xray-core supports the OcspStapling certification hot renew
_, _, _, err = lego.RenewCert()
if err != nil {
log.Print(err)
c.logger.Print(err)
}
}
}

View File

@ -13,8 +13,8 @@ import (
"github.com/XrayR-project/XrayR/api"
"github.com/XrayR-project/XrayR/api/sspanel"
_ "github.com/XrayR-project/XrayR/cmd/distro/all"
"github.com/XrayR-project/XrayR/common/mylego"
_ "github.com/XrayR-project/XrayR/main/distro/all"
. "github.com/XrayR-project/XrayR/service/controller"
)

View File

@ -41,7 +41,7 @@ func InboundBuilder(config *Config, nodeInfo *api.NodeInfo, tag string) (*core.I
// SniffingConfig
sniffingConfig := &conf.SniffingConfig{
Enabled: true,
DestOverride: &conf.StringList{"http", "tls"},
DestOverride: &conf.StringList{"http", "tls", "quic", "fakedns"},
}
if config.DisableSniffing {
sniffingConfig.Enabled = false
@ -57,8 +57,8 @@ func InboundBuilder(config *Config, nodeInfo *api.NodeInfo, tag string) (*core.I
var proxySetting any
// Build Protocol and Protocol setting
switch nodeInfo.NodeType {
case "V2ray":
if nodeInfo.EnableVless {
case "V2ray", "Vmess", "Vless":
if nodeInfo.EnableVless || (nodeInfo.NodeType == "Vless" && nodeInfo.NodeType != "Vmess") {
protocol = "vless"
// Enable fallback
if config.EnableFallback {
@ -139,7 +139,7 @@ func InboundBuilder(config *Config, nodeInfo *api.NodeInfo, tag string) (*core.I
setting, err := json.Marshal(proxySetting)
if err != nil {
return nil, fmt.Errorf("marshal proxy %s config fialed: %s", nodeInfo.NodeType, err)
return nil, fmt.Errorf("marshal proxy %s config failed: %s", nodeInfo.NodeType, err)
}
inboundDetourConfig.Protocol = protocol
inboundDetourConfig.Settings = &setting
@ -164,47 +164,82 @@ func InboundBuilder(config *Config, nodeInfo *api.NodeInfo, tag string) (*core.I
headers["Host"] = nodeInfo.Host
wsSettings := &conf.WebSocketConfig{
AcceptProxyProtocol: config.EnableProxyProtocol,
Host: nodeInfo.Host,
Path: nodeInfo.Path,
Headers: headers,
}
streamSetting.WSSettings = wsSettings
case "http":
hosts := conf.StringList{nodeInfo.Host}
httpSettings := &conf.HTTPConfig{
Host: &hosts,
Path: nodeInfo.Path,
}
streamSetting.HTTPSettings = httpSettings
case "grpc":
grpcSettings := &conf.GRPCConfig{
ServiceName: nodeInfo.ServiceName,
Authority: nodeInfo.Authority,
}
streamSetting.GRPCConfig = grpcSettings
streamSetting.GRPCSettings = grpcSettings
case "httpupgrade":
httpupgradeSettings := &conf.HttpUpgradeConfig{
Headers: nodeInfo.Headers,
Path: nodeInfo.Path,
Host: nodeInfo.Host,
AcceptProxyProtocol: nodeInfo.AcceptProxyProtocol,
}
streamSetting.HTTPUPGRADESettings = httpupgradeSettings
case "splithttp", "xhttp":
splithttpSetting := &conf.SplitHTTPConfig{
Path: nodeInfo.Path,
Host: nodeInfo.Host,
}
streamSetting.SplitHTTPSettings = splithttpSetting
}
streamSetting.Network = &transportProtocol
// Build TLS and XTLS settings
if nodeInfo.EnableTLS && config.CertConfig.CertMode != "none" {
streamSetting.Security = nodeInfo.TLSType
// Build TLS and REALITY settings
var isREALITY bool
if config.DisableLocalREALITYConfig {
if nodeInfo.REALITYConfig != nil && nodeInfo.EnableREALITY {
isREALITY = true
streamSetting.Security = "reality"
r := nodeInfo.REALITYConfig
streamSetting.REALITYSettings = &conf.REALITYConfig{
Show: config.REALITYConfigs.Show,
Dest: []byte(`"` + r.Dest + `"`),
Xver: r.ProxyProtocolVer,
ServerNames: r.ServerNames,
PrivateKey: r.PrivateKey,
MinClientVer: r.MinClientVer,
MaxClientVer: r.MaxClientVer,
MaxTimeDiff: r.MaxTimeDiff,
ShortIds: r.ShortIds,
}
}
} else if config.EnableREALITY && config.REALITYConfigs != nil {
isREALITY = true
streamSetting.Security = "reality"
streamSetting.REALITYSettings = &conf.REALITYConfig{
Show: config.REALITYConfigs.Show,
Dest: []byte(`"` + config.REALITYConfigs.Dest + `"`),
Xver: config.REALITYConfigs.ProxyProtocolVer,
ServerNames: config.REALITYConfigs.ServerNames,
PrivateKey: config.REALITYConfigs.PrivateKey,
MinClientVer: config.REALITYConfigs.MinClientVer,
MaxClientVer: config.REALITYConfigs.MaxClientVer,
MaxTimeDiff: config.REALITYConfigs.MaxTimeDiff,
ShortIds: config.REALITYConfigs.ShortIds,
}
}
if !isREALITY && nodeInfo.EnableTLS && config.CertConfig.CertMode != "none" {
streamSetting.Security = "tls"
certFile, keyFile, err := getCertFile(config.CertConfig)
if err != nil {
return nil, err
}
if nodeInfo.TLSType == "tls" {
tlsSettings := &conf.TLSConfig{
RejectUnknownSNI: config.CertConfig.RejectUnknownSni,
}
tlsSettings.Certs = append(tlsSettings.Certs, &conf.TLSCertConfig{CertFile: certFile, KeyFile: keyFile, OcspStapling: 3600})
streamSetting.TLSSettings = tlsSettings
} else if nodeInfo.TLSType == "xtls" {
xtlsSettings := &conf.XTLSConfig{
RejectUnknownSNI: config.CertConfig.RejectUnknownSni,
}
xtlsSettings.Certs = append(xtlsSettings.Certs, &conf.XTLSCertConfig{CertFile: certFile, KeyFile: keyFile, OcspStapling: 3600})
streamSetting.XTLSSettings = xtlsSettings
tlsSettings := &conf.TLSConfig{
RejectUnknownSNI: config.CertConfig.RejectUnknownSni,
}
tlsSettings.Certs = append(tlsSettings.Certs, &conf.TLSCertConfig{CertFile: certFile, KeyFile: keyFile, OcspStapling: 3600})
streamSetting.TLSSettings = tlsSettings
}
// Support ProxyProtocol for any transport protocol
@ -260,13 +295,13 @@ func buildVlessFallbacks(fallbackConfigs []*FallBackConfig) ([]*conf.VLessInboun
for i, c := range fallbackConfigs {
if c.Dest == "" {
return nil, fmt.Errorf("dest is required for fallback fialed")
return nil, fmt.Errorf("dest is required for fallback failed")
}
var dest json.RawMessage
dest, err := json.Marshal(c.Dest)
if err != nil {
return nil, fmt.Errorf("marshal dest %s config fialed: %s", dest, err)
return nil, fmt.Errorf("marshal dest %s config failed: %s", dest, err)
}
vlessFallBacks[i] = &conf.VLessInboundFallback{
Name: c.SNI,
@ -288,13 +323,13 @@ func buildTrojanFallbacks(fallbackConfigs []*FallBackConfig) ([]*conf.TrojanInbo
for i, c := range fallbackConfigs {
if c.Dest == "" {
return nil, fmt.Errorf("dest is required for fallback fialed")
return nil, fmt.Errorf("dest is required for fallback failed")
}
var dest json.RawMessage
dest, err := json.Marshal(c.Dest)
if err != nil {
return nil, fmt.Errorf("marshal dest %s config fialed: %s", dest, err)
return nil, fmt.Errorf("marshal dest %s config failed: %s", dest, err)
}
trojanFallBacks[i] = &conf.TrojanInboundFallback{
Name: c.SNI,

View File

@ -19,7 +19,6 @@ func TestBuildV2ray(t *testing.T) {
Host: "test.test.tk",
Path: "v2ray",
EnableTLS: false,
TLSType: "tls",
}
certConfig := &mylego.CertConfig{
CertMode: "http",
@ -47,7 +46,6 @@ func TestBuildTrojan(t *testing.T) {
Host: "trojan.test.tk",
Path: "v2ray",
EnableTLS: false,
TLSType: "tls",
}
DNSEnv := make(map[string]string)
DNSEnv["ALICLOUD_ACCESS_KEY"] = "aaa"
@ -79,7 +77,6 @@ func TestBuildSS(t *testing.T) {
Host: "test.test.tk",
Path: "v2ray",
EnableTLS: false,
TLSType: "tls",
}
DNSEnv := make(map[string]string)
DNSEnv["ALICLOUD_ACCESS_KEY"] = "aaa"

View File

@ -4,7 +4,6 @@ import (
"encoding/json"
"fmt"
"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/core"
"github.com/xtls/xray-core/infra/conf"
@ -17,11 +16,8 @@ func OutboundBuilder(config *Config, nodeInfo *api.NodeInfo, tag string) (*core.
outboundDetourConfig.Protocol = "freedom"
outboundDetourConfig.Tag = tag
// Build Send IP address
if config.SendIP != "" {
ipAddress := net.ParseAddress(config.SendIP)
outboundDetourConfig.SendThrough = &conf.Address{Address: ipAddress}
}
// SendThrough setting
outboundDetourConfig.SendThrough = &config.SendIP
// Freedom Protocol setting
var domainStrategy = "Asis"
@ -42,7 +38,7 @@ func OutboundBuilder(config *Config, nodeInfo *api.NodeInfo, tag string) (*core.
var setting json.RawMessage
setting, err := json.Marshal(proxySetting)
if err != nil {
return nil, fmt.Errorf("marshal proxy %s config fialed: %s", nodeInfo.NodeType, err)
return nil, fmt.Errorf("marshal proxy %s config failed: %s", nodeInfo.NodeType, err)
}
outboundDetourConfig.Settings = &setting
return outboundDetourConfig.Build()

View File

@ -1,12 +1,14 @@
package controller
import (
"context"
"encoding/base64"
"fmt"
"strings"
"github.com/sagernet/sing-shadowsocks/shadowaead_2022"
C "github.com/sagernet/sing/common"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/protocol"
"github.com/xtls/xray-core/common/serial"
"github.com/xtls/xray-core/infra/conf"
@ -25,12 +27,11 @@ var AEADMethod = map[shadowsocks.CipherType]uint8{
shadowsocks.CipherType_XCHACHA20_POLY1305: 0,
}
func (c *Controller) buildVmessUser(userInfo *[]api.UserInfo, serverAlterID uint16) (users []*protocol.User) {
func (c *Controller) buildVmessUser(userInfo *[]api.UserInfo) (users []*protocol.User) {
users = make([]*protocol.User, len(*userInfo))
for i, user := range *userInfo {
vmessAccount := &conf.VMessAccount{
ID: user.UUID,
AlterIds: serverAlterID,
Security: "auto",
}
users[i] = &protocol.User{
@ -47,7 +48,7 @@ func (c *Controller) buildVlessUser(userInfo *[]api.UserInfo) (users []*protocol
for i, user := range *userInfo {
vlessAccount := &vless.Account{
Id: user.UUID,
Flow: "xtls-rprx-vision,none",
Flow: c.nodeInfo.VlessFlow,
}
users[i] = &protocol.User{
Level: 0,
@ -63,7 +64,6 @@ func (c *Controller) buildTrojanUser(userInfo *[]api.UserInfo) (users []*protoco
for i, user := range *userInfo {
trojanAccount := &trojan.Account{
Password: user.UUID,
Flow: "xtls-rprx-direct",
}
users[i] = &protocol.User{
Level: 0,
@ -83,16 +83,14 @@ func (c *Controller) buildSSUser(userInfo *[]api.UserInfo, method string) (users
e := c.buildUserTag(&user)
userKey, err := c.checkShadowsocksPassword(user.Passwd, method)
if err != nil {
newError(fmt.Errorf("[UID: %d] %s", user.UID, err)).AtError().WriteToLog()
errors.LogError(context.Background(), "[UID: %d] %s", user.UID, err)
continue
}
users[i] = &protocol.User{
Level: 0,
Email: e,
Account: serial.ToTypedMessage(&shadowsocks_2022.User{
Account: serial.ToTypedMessage(&shadowsocks_2022.Account{
Key: userKey,
Email: e,
Level: 0,
}),
}
} else {
@ -118,16 +116,14 @@ func (c *Controller) buildSSPluginUser(userInfo *[]api.UserInfo) (users []*proto
e := c.buildUserTag(&user)
userKey, err := c.checkShadowsocksPassword(user.Passwd, user.Method)
if err != nil {
newError(fmt.Errorf("[UID: %d] %s", user.UID, err)).AtError().WriteToLog()
errors.LogError(context.Background(), "[UID: %d] %s", user.UID, err)
continue
}
users[i] = &protocol.User{
Level: 0,
Email: e,
Account: serial.ToTypedMessage(&shadowsocks_2022.User{
Account: serial.ToTypedMessage(&shadowsocks_2022.Account{
Key: userKey,
Email: e,
Level: 0,
}),
}
} else {