mirror of
https://github.com/XrayR-project/XrayR.git
synced 2025-08-17 23:01:47 +00:00
Compare commits
73 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
0bea22e145 | ||
![]() |
f25d5993f3 | ||
![]() |
676365b13b | ||
![]() |
e774d5c822 | ||
![]() |
be4f9cdac1 | ||
![]() |
9a06f78653 | ||
![]() |
85d73408c3 | ||
![]() |
c93fdb4cf3 | ||
![]() |
0d565b034b | ||
![]() |
212f0ff135 | ||
![]() |
608764a8a0 | ||
![]() |
fc16cb0972 | ||
![]() |
5397720430 | ||
![]() |
839b15c22c | ||
![]() |
5b45b8ffe8 | ||
![]() |
a56cd91b34 | ||
![]() |
b6600729b2 | ||
![]() |
8d0225bcbb | ||
![]() |
ce5fe799f4 | ||
![]() |
8763d5960f | ||
![]() |
7a452a4a53 | ||
![]() |
fac8b62286 | ||
![]() |
d320aadb54 | ||
![]() |
40ae48f507 | ||
![]() |
d1bc36782b | ||
![]() |
c04330d0bf | ||
![]() |
872eb12d35 | ||
![]() |
e1d4428d98 | ||
![]() |
0fef3cf278 | ||
![]() |
a4ca37b1de | ||
![]() |
74f3a75682 | ||
![]() |
183b1be519 | ||
![]() |
2f10c3f6b8 | ||
![]() |
86324ff1ae | ||
![]() |
1897404c9d | ||
![]() |
ee53e746c5 | ||
![]() |
656df61c17 | ||
![]() |
e0237f5c54 | ||
![]() |
e16d94fb4a | ||
![]() |
e357fc438f | ||
![]() |
cb1638ac21 | ||
![]() |
de0da25c21 | ||
![]() |
faec840c23 | ||
![]() |
a6a1baf70c | ||
![]() |
4013f71e4c | ||
![]() |
c8f0981b0e | ||
![]() |
5274edf657 | ||
![]() |
e6232c1852 | ||
![]() |
e0688fc609 | ||
![]() |
ffa444f2ab | ||
![]() |
81ba4ebb43 | ||
![]() |
f50c61c782 | ||
![]() |
9c356cd28c | ||
![]() |
310353f344 | ||
![]() |
808b5ecc3c | ||
![]() |
c4ef5bb843 | ||
![]() |
ddce3fa86d | ||
![]() |
209f5a17d6 | ||
![]() |
af3fae9cdb | ||
![]() |
3b96b352cb | ||
![]() |
398c3133d3 | ||
![]() |
a397af5d73 | ||
![]() |
b47954ea64 | ||
![]() |
9a2188cb0c | ||
![]() |
c7af43fc49 | ||
![]() |
87aa855154 | ||
![]() |
37eff6755c | ||
![]() |
5e346ddfee | ||
![]() |
838c667a87 | ||
![]() |
057f4156bf | ||
![]() |
1f59a7cd7a | ||
![]() |
2b5fa4feee | ||
![]() |
571191a190 |
126
.github/build/friendly-filenames.json
vendored
126
.github/build/friendly-filenames.json
vendored
@@ -1,33 +1,95 @@
|
|||||||
{
|
{
|
||||||
"android-arm64": { "friendlyName": "android-arm64-v8a" },
|
"android-arm64": {
|
||||||
"darwin-amd64": { "friendlyName": "macos-64" },
|
"friendlyName": "android-arm64-v8a"
|
||||||
"darwin-arm64": { "friendlyName": "macos-arm64-v8a" },
|
},
|
||||||
"dragonfly-amd64": { "friendlyName": "dragonfly-64" },
|
"darwin-amd64": {
|
||||||
"freebsd-386": { "friendlyName": "freebsd-32" },
|
"friendlyName": "macos-64"
|
||||||
"freebsd-amd64": { "friendlyName": "freebsd-64" },
|
},
|
||||||
"freebsd-arm64": { "friendlyName": "freebsd-arm64-v8a" },
|
"darwin-arm64": {
|
||||||
"freebsd-arm7": { "friendlyName": "freebsd-arm32-v7a" },
|
"friendlyName": "macos-arm64-v8a"
|
||||||
"linux-386": { "friendlyName": "linux-32" },
|
},
|
||||||
"linux-amd64": { "friendlyName": "linux-64" },
|
"dragonfly-amd64": {
|
||||||
"linux-arm5": { "friendlyName": "linux-arm32-v5" },
|
"friendlyName": "dragonfly-64"
|
||||||
"linux-arm64": { "friendlyName": "linux-arm64-v8a" },
|
},
|
||||||
"linux-arm6": { "friendlyName": "linux-arm32-v6" },
|
"freebsd-386": {
|
||||||
"linux-arm7": { "friendlyName": "linux-arm32-v7a" },
|
"friendlyName": "freebsd-32"
|
||||||
"linux-mips64le": { "friendlyName": "linux-mips64le" },
|
},
|
||||||
"linux-mips64": { "friendlyName": "linux-mips64" },
|
"freebsd-amd64": {
|
||||||
"linux-mipslesoftfloat": { "friendlyName": "linux-mips32le-softfloat" },
|
"friendlyName": "freebsd-64"
|
||||||
"linux-mipsle": { "friendlyName": "linux-mips32le" },
|
},
|
||||||
"linux-mipssoftfloat": { "friendlyName": "linux-mips32-softfloat" },
|
"freebsd-arm64": {
|
||||||
"linux-mips": { "friendlyName": "linux-mips32" },
|
"friendlyName": "freebsd-arm64-v8a"
|
||||||
"linux-ppc64le": { "friendlyName": "linux-ppc64le" },
|
},
|
||||||
"linux-ppc64": { "friendlyName": "linux-ppc64" },
|
"freebsd-arm7": {
|
||||||
"linux-riscv64": { "friendlyName": "linux-riscv64" },
|
"friendlyName": "freebsd-arm32-v7a"
|
||||||
"linux-s390x": { "friendlyName": "linux-s390x" },
|
},
|
||||||
"openbsd-386": { "friendlyName": "openbsd-32" },
|
"linux-386": {
|
||||||
"openbsd-amd64": { "friendlyName": "openbsd-64" },
|
"friendlyName": "linux-32"
|
||||||
"openbsd-arm64": { "friendlyName": "openbsd-arm64-v8a" },
|
},
|
||||||
"openbsd-arm7": { "friendlyName": "openbsd-arm32-v7a" },
|
"linux-amd64": {
|
||||||
"windows-386": { "friendlyName": "windows-32" },
|
"friendlyName": "linux-64"
|
||||||
"windows-amd64": { "friendlyName": "windows-64" },
|
},
|
||||||
"windows-arm7": { "friendlyName": "windows-arm32-v7a" }
|
"linux-arm5": {
|
||||||
}
|
"friendlyName": "linux-arm32-v5"
|
||||||
|
},
|
||||||
|
"linux-arm64": {
|
||||||
|
"friendlyName": "linux-arm64-v8a"
|
||||||
|
},
|
||||||
|
"linux-arm6": {
|
||||||
|
"friendlyName": "linux-arm32-v6"
|
||||||
|
},
|
||||||
|
"linux-arm7": {
|
||||||
|
"friendlyName": "linux-arm32-v7a"
|
||||||
|
},
|
||||||
|
"linux-mips64le": {
|
||||||
|
"friendlyName": "linux-mips64le"
|
||||||
|
},
|
||||||
|
"linux-mips64": {
|
||||||
|
"friendlyName": "linux-mips64"
|
||||||
|
},
|
||||||
|
"linux-mipslesoftfloat": {
|
||||||
|
"friendlyName": "linux-mips32le-softfloat"
|
||||||
|
},
|
||||||
|
"linux-mipsle": {
|
||||||
|
"friendlyName": "linux-mips32le"
|
||||||
|
},
|
||||||
|
"linux-mipssoftfloat": {
|
||||||
|
"friendlyName": "linux-mips32-softfloat"
|
||||||
|
},
|
||||||
|
"linux-mips": {
|
||||||
|
"friendlyName": "linux-mips32"
|
||||||
|
},
|
||||||
|
"linux-ppc64le": {
|
||||||
|
"friendlyName": "linux-ppc64le"
|
||||||
|
},
|
||||||
|
"linux-ppc64": {
|
||||||
|
"friendlyName": "linux-ppc64"
|
||||||
|
},
|
||||||
|
"linux-riscv64": {
|
||||||
|
"friendlyName": "linux-riscv64"
|
||||||
|
},
|
||||||
|
"linux-s390x": {
|
||||||
|
"friendlyName": "linux-s390x"
|
||||||
|
},
|
||||||
|
"openbsd-386": {
|
||||||
|
"friendlyName": "openbsd-32"
|
||||||
|
},
|
||||||
|
"openbsd-amd64": {
|
||||||
|
"friendlyName": "openbsd-64"
|
||||||
|
},
|
||||||
|
"openbsd-arm64": {
|
||||||
|
"friendlyName": "openbsd-arm64-v8a"
|
||||||
|
},
|
||||||
|
"openbsd-arm7": {
|
||||||
|
"friendlyName": "openbsd-arm32-v7a"
|
||||||
|
},
|
||||||
|
"windows-386": {
|
||||||
|
"friendlyName": "windows-32"
|
||||||
|
},
|
||||||
|
"windows-amd64": {
|
||||||
|
"friendlyName": "windows-64"
|
||||||
|
},
|
||||||
|
"windows-arm7": {
|
||||||
|
"friendlyName": "windows-arm32-v7a"
|
||||||
|
}
|
||||||
|
}
|
50
.github/workflows/codeql-analysis.yml
vendored
50
.github/workflows/codeql-analysis.yml
vendored
@@ -34,34 +34,34 @@ jobs:
|
|||||||
# https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
|
# https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
# Initializes the CodeQL tools for scanning.
|
# Initializes the CodeQL tools for scanning.
|
||||||
- name: Initialize CodeQL
|
- name: Initialize CodeQL
|
||||||
uses: github/codeql-action/init@v2
|
uses: github/codeql-action/init@v2
|
||||||
with:
|
with:
|
||||||
languages: ${{ matrix.language }}
|
languages: ${{ matrix.language }}
|
||||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||||
# By default, queries listed here will override any specified in a config file.
|
# 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.
|
# 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
|
# queries: ./path/to/local/query, your-org/your-repo/queries@main
|
||||||
|
|
||||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
# 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)
|
# If this step fails, then you should remove it and run the build manually (see below)
|
||||||
- name: Autobuild
|
- name: Autobuild
|
||||||
uses: github/codeql-action/autobuild@v2
|
uses: github/codeql-action/autobuild@v2
|
||||||
|
|
||||||
# ℹ️ Command-line programs to run using the OS shell.
|
# ℹ️ Command-line programs to run using the OS shell.
|
||||||
# 📚 https://git.io/JvXDl
|
# 📚 https://git.io/JvXDl
|
||||||
|
|
||||||
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
|
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
|
||||||
# and modify them (or add more) to build your code if your project
|
# and modify them (or add more) to build your code if your project
|
||||||
# uses a compiled language
|
# uses a compiled language
|
||||||
|
|
||||||
#- run: |
|
#- run: |
|
||||||
# make bootstrap
|
# make bootstrap
|
||||||
# make release
|
# make release
|
||||||
|
|
||||||
- name: Perform CodeQL Analysis
|
- name: Perform CodeQL Analysis
|
||||||
uses: github/codeql-action/analyze@v2
|
uses: github/codeql-action/analyze@v2
|
||||||
|
18
.github/workflows/docker.yml
vendored
18
.github/workflows/docker.yml
vendored
@@ -20,26 +20,22 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Check out the repo
|
- name: Check out the repo
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
-
|
- name: Set up Docker Buildx
|
||||||
name: Set up Docker Buildx
|
uses: docker/setup-buildx-action@v2
|
||||||
uses: docker/setup-buildx-action@v1
|
- name: Log in to the Container registry
|
||||||
-
|
|
||||||
name: Log in to the Container registry
|
|
||||||
uses: docker/login-action@v2
|
uses: docker/login-action@v2
|
||||||
with:
|
with:
|
||||||
registry: ghcr.io
|
registry: ghcr.io
|
||||||
username: ${{ github.actor }}
|
username: ${{ github.actor }}
|
||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
-
|
- name: Docker meta
|
||||||
name: Docker meta
|
|
||||||
id: meta
|
id: meta
|
||||||
uses: docker/metadata-action@v4
|
uses: docker/metadata-action@v4
|
||||||
with:
|
with:
|
||||||
images: ghcr.io/${{ github.repository }}
|
images: ghcr.io/${{ github.repository }}
|
||||||
-
|
- name: Build and push
|
||||||
name: Build and push
|
uses: docker/build-push-action@v3
|
||||||
uses: docker/build-push-action@v2
|
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
platforms: linux/arm/v7,linux/arm64,linux/amd64,linux/s390x
|
platforms: linux/arm/v7,linux/arm64,linux/amd64,linux/s390x
|
||||||
|
24
.github/workflows/release.yml
vendored
24
.github/workflows/release.yml
vendored
@@ -11,14 +11,14 @@ on:
|
|||||||
- "go.sum"
|
- "go.sum"
|
||||||
- ".github/workflows/*.yml"
|
- ".github/workflows/*.yml"
|
||||||
pull_request:
|
pull_request:
|
||||||
types: [opened, synchronize, reopened]
|
types: [ opened, synchronize, reopened ]
|
||||||
paths:
|
paths:
|
||||||
- "**/*.go"
|
- "**/*.go"
|
||||||
- "go.mod"
|
- "go.mod"
|
||||||
- "go.sum"
|
- "go.sum"
|
||||||
- ".github/workflows/*.yml"
|
- ".github/workflows/*.yml"
|
||||||
release:
|
release:
|
||||||
types: [published]
|
types: [ published ]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
|
||||||
@@ -26,8 +26,8 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
# Include amd64 on all platforms.
|
# Include amd64 on all platforms.
|
||||||
goos: [windows, freebsd, openbsd, linux, dragonfly, darwin]
|
goos: [ windows, freebsd, openbsd, linux, dragonfly, darwin ]
|
||||||
goarch: [amd64, 386]
|
goarch: [ amd64, 386 ]
|
||||||
exclude:
|
exclude:
|
||||||
# Exclude i386 on darwin and dragonfly.
|
# Exclude i386 on darwin and dragonfly.
|
||||||
- goarch: 386
|
- goarch: 386
|
||||||
@@ -92,7 +92,7 @@ jobs:
|
|||||||
# END S390X
|
# END S390X
|
||||||
# END Other architectures
|
# END Other architectures
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
env:
|
env:
|
||||||
GOOS: ${{ matrix.goos }}
|
GOOS: ${{ matrix.goos }}
|
||||||
@@ -101,17 +101,17 @@ jobs:
|
|||||||
CGO_ENABLED: 0
|
CGO_ENABLED: 0
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout codebase
|
- name: Checkout codebase
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
- name: Show workflow information
|
- name: Show workflow information
|
||||||
id: get_filename
|
id: get_filename
|
||||||
run: |
|
run: |
|
||||||
export _NAME=$(jq ".[\"$GOOS-$GOARCH$GOARM$GOMIPS\"].friendlyName" -r < .github/build/friendly-filenames.json)
|
export _NAME=$(jq ".[\"$GOOS-$GOARCH$GOARM$GOMIPS\"].friendlyName" -r < .github/build/friendly-filenames.json)
|
||||||
echo "GOOS: $GOOS, GOARCH: $GOARCH, GOARM: $GOARM, GOMIPS: $GOMIPS, RELEASE_NAME: $_NAME"
|
echo "GOOS: $GOOS, GOARCH: $GOARCH, GOARM: $GOARM, GOMIPS: $GOMIPS, RELEASE_NAME: $_NAME"
|
||||||
echo "::set-output name=ASSET_NAME::$_NAME"
|
echo "ASSET_NAME=$_NAME" >> $GITHUB_OUTPUT
|
||||||
echo "ASSET_NAME=$_NAME" >> $GITHUB_ENV
|
echo "ASSET_NAME=$_NAME" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: Set up Go
|
- name: Set up Go
|
||||||
uses: actions/setup-go@v2
|
uses: actions/setup-go@v3
|
||||||
with:
|
with:
|
||||||
go-version: ^1.19
|
go-version: ^1.19
|
||||||
|
|
||||||
@@ -123,7 +123,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
mkdir -p build_assets
|
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=" ./main
|
||||||
|
|
||||||
- name: Build Mips softfloat XrayR
|
- name: Build Mips softfloat XrayR
|
||||||
if: matrix.goarch == 'mips' || matrix.goarch == 'mipsle'
|
if: matrix.goarch == 'mips' || matrix.goarch == 'mipsle'
|
||||||
run: |
|
run: |
|
||||||
@@ -173,7 +173,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
mv build_assets XrayR-$ASSET_NAME
|
mv build_assets XrayR-$ASSET_NAME
|
||||||
- name: Upload files to Artifacts
|
- name: Upload files to Artifacts
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: XrayR-${{ steps.get_filename.outputs.ASSET_NAME }}
|
name: XrayR-${{ steps.get_filename.outputs.ASSET_NAME }}
|
||||||
path: |
|
path: |
|
||||||
|
4
.gitignore
vendored
4
.gitignore
vendored
@@ -13,4 +13,6 @@ main/cert
|
|||||||
main/config.yml
|
main/config.yml
|
||||||
./vscode
|
./vscode
|
||||||
.idea/*
|
.idea/*
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
*.bak
|
||||||
|
go.work*
|
31
README.md
31
README.md
@@ -1,4 +1,5 @@
|
|||||||
# XrayR
|
# XrayR
|
||||||
|
|
||||||
[](https://t.me/XrayR_project)
|
[](https://t.me/XrayR_project)
|
||||||
[](https://t.me/XrayR_channel)
|
[](https://t.me/XrayR_channel)
|
||||||

|

|
||||||
@@ -14,11 +15,13 @@ A Xray backend framework that can easily support many panels.
|
|||||||
如果您喜欢本项目,可以右上角点个star+watch,持续关注本项目的进展。
|
如果您喜欢本项目,可以右上角点个star+watch,持续关注本项目的进展。
|
||||||
|
|
||||||
使用教程:[详细使用教程](https://xrayr-project.github.io/XrayR-doc/)
|
使用教程:[详细使用教程](https://xrayr-project.github.io/XrayR-doc/)
|
||||||
|
|
||||||
## 免责声明
|
## 免责声明
|
||||||
|
|
||||||
本项目只是本人个人学习开发并维护,本人不保证任何可用性,也不对使用本软件造成的任何后果负责。
|
本项目只是本人个人学习开发并维护,本人不保证任何可用性,也不对使用本软件造成的任何后果负责。
|
||||||
|
|
||||||
## 特点
|
## 特点
|
||||||
|
|
||||||
* 永久开源且免费。
|
* 永久开源且免费。
|
||||||
* 支持V2ray,Trojan, Shadowsocks多种协议。
|
* 支持V2ray,Trojan, Shadowsocks多种协议。
|
||||||
* 支持Vless和XTLS等新特性。
|
* 支持Vless和XTLS等新特性。
|
||||||
@@ -31,39 +34,45 @@ A Xray backend framework that can easily support many panels.
|
|||||||
|
|
||||||
## 功能介绍
|
## 功能介绍
|
||||||
|
|
||||||
| 功能 | v2ray | trojan | shadowsocks |
|
| 功能 | v2ray | trojan | shadowsocks |
|
||||||
| --------------- | ----- | ------ | ----------- |
|
|-----------|-------|--------|-------------|
|
||||||
| 获取节点信息 | √ | √ | √ |
|
| 获取节点信息 | √ | √ | √ |
|
||||||
| 获取用户信息 | √ | √ | √ |
|
| 获取用户信息 | √ | √ | √ |
|
||||||
| 用户流量统计 | √ | √ | √ |
|
| 用户流量统计 | √ | √ | √ |
|
||||||
| 服务器信息上报 | √ | √ | √ |
|
| 服务器信息上报 | √ | √ | √ |
|
||||||
| 自动申请tls证书 | √ | √ | √ |
|
| 自动申请tls证书 | √ | √ | √ |
|
||||||
| 自动续签tls证书 | √ | √ | √ |
|
| 自动续签tls证书 | √ | √ | √ |
|
||||||
| 在线人数统计 | √ | √ | √ |
|
| 在线人数统计 | √ | √ | √ |
|
||||||
| 在线用户限制 | √ | √ | √ |
|
| 在线用户限制 | √ | √ | √ |
|
||||||
| 审计规则 | √ | √ | √ |
|
| 审计规则 | √ | √ | √ |
|
||||||
| 节点端口限速 | √ | √ | √ |
|
| 节点端口限速 | √ | √ | √ |
|
||||||
| 按照用户限速 | √ | √ | √ |
|
| 按照用户限速 | √ | √ | √ |
|
||||||
| 自定义DNS | √ | √ | √ |
|
| 自定义DNS | √ | √ | √ |
|
||||||
|
|
||||||
## 支持前端
|
## 支持前端
|
||||||
|
|
||||||
| 前端 | v2ray | trojan | shadowsocks |
|
| 前端 | v2ray | trojan | shadowsocks |
|
||||||
| ------------------------------------------------------ | ----- | ------ | ------------------------------ |
|
|--------------------------------------------------------|-------|--------|-------------------------|
|
||||||
| sspanel-uim | √ | √ | √ (单端口多用户和V2ray-Plugin) |
|
| sspanel-uim | √ | √ | √ (单端口多用户和V2ray-Plugin) |
|
||||||
| v2board | √ | √ | √ |
|
| v2board | √ | √ | √ |
|
||||||
| [PMPanel](https://github.com/ByteInternetHK/PMPanel) | √ | √ | √ |
|
| [PMPanel](https://github.com/ByteInternetHK/PMPanel) | √ | √ | √ |
|
||||||
| [ProxyPanel](https://github.com/ProxyPanel/ProxyPanel) | √ | √ | √ |
|
| [ProxyPanel](https://github.com/ProxyPanel/ProxyPanel) | √ | √ | √ |
|
||||||
| [WHMCS (V2RaySocks)](https://v2raysocks.doxtex.com/) | √ | √ | √ |
|
| [WHMCS (V2RaySocks)](https://v2raysocks.doxtex.com/) | √ | √ | √ |
|
||||||
|
|
||||||
## 软件安装
|
## 软件安装
|
||||||
|
|
||||||
### 一键安装
|
### 一键安装
|
||||||
|
|
||||||
```
|
```
|
||||||
wget -N https://raw.githubusercontent.com/XrayR-project/XrayR-release/master/install.sh && bash install.sh
|
wget -N https://raw.githubusercontent.com/XrayR-project/XrayR-release/master/install.sh && bash install.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
### 使用Docker部署软件
|
### 使用Docker部署软件
|
||||||
|
|
||||||
[Docker部署教程](https://xrayr-project.github.io/XrayR-doc/xrayr-xia-zai-he-an-zhuang/install/docker)
|
[Docker部署教程](https://xrayr-project.github.io/XrayR-doc/xrayr-xia-zai-he-an-zhuang/install/docker)
|
||||||
|
|
||||||
### 手动安装
|
### 手动安装
|
||||||
|
|
||||||
[手动安装教程](https://xrayr-project.github.io/XrayR-doc/xrayr-xia-zai-he-an-zhuang/install/manual)
|
[手动安装教程](https://xrayr-project.github.io/XrayR-doc/xrayr-xia-zai-he-an-zhuang/install/manual)
|
||||||
|
|
||||||
## 配置文件及详细使用教程
|
## 配置文件及详细使用教程
|
||||||
|
@@ -5,7 +5,7 @@ import (
|
|||||||
"regexp"
|
"regexp"
|
||||||
)
|
)
|
||||||
|
|
||||||
// API config
|
// Config API config
|
||||||
type Config struct {
|
type Config struct {
|
||||||
APIHost string `mapstructure:"ApiHost"`
|
APIHost string `mapstructure:"ApiHost"`
|
||||||
NodeID int `mapstructure:"NodeID"`
|
NodeID int `mapstructure:"NodeID"`
|
||||||
@@ -20,7 +20,7 @@ type Config struct {
|
|||||||
DisableCustomConfig bool `mapstructure:"DisableCustomConfig"`
|
DisableCustomConfig bool `mapstructure:"DisableCustomConfig"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Node status
|
// NodeStatus Node status
|
||||||
type NodeStatus struct {
|
type NodeStatus struct {
|
||||||
CPU float64
|
CPU float64
|
||||||
Mem float64
|
Mem float64
|
||||||
@@ -42,6 +42,7 @@ type NodeInfo struct {
|
|||||||
TLSType string
|
TLSType string
|
||||||
EnableVless bool
|
EnableVless bool
|
||||||
CypherMethod string
|
CypherMethod string
|
||||||
|
ServerKey string
|
||||||
ServiceName string
|
ServiceName string
|
||||||
Header json.RawMessage
|
Header json.RawMessage
|
||||||
}
|
}
|
||||||
|
1
api/newV2board/model.go
Normal file
1
api/newV2board/model.go
Normal file
@@ -0,0 +1 @@
|
|||||||
|
package newV2board
|
369
api/newV2board/v2board.go
Normal file
369
api/newV2board/v2board.go
Normal file
@@ -0,0 +1,369 @@
|
|||||||
|
package newV2board
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"regexp"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"sync/atomic"
|
||||||
|
"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
|
||||||
|
resp atomic.Value
|
||||||
|
eTag string
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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),
|
||||||
|
"node_type": 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,
|
||||||
|
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() > 399 {
|
||||||
|
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 panel
|
||||||
|
func (c *APIClient) GetNodeInfo() (nodeInfo *api.NodeInfo, err error) {
|
||||||
|
path := "/api/v1/server/UniProxy/config"
|
||||||
|
|
||||||
|
res, err := c.client.R().
|
||||||
|
ForceContentType("application/json").
|
||||||
|
Get(path)
|
||||||
|
|
||||||
|
response, err := c.parseResponse(res, path, err)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
c.resp.Store(response)
|
||||||
|
|
||||||
|
switch c.NodeType {
|
||||||
|
case "V2ray":
|
||||||
|
nodeInfo, err = c.parseV2rayNodeResponse(response)
|
||||||
|
case "Trojan":
|
||||||
|
nodeInfo, err = c.parseTrojanNodeResponse(response)
|
||||||
|
case "Shadowsocks":
|
||||||
|
nodeInfo, err = c.parseSSNodeResponse(response)
|
||||||
|
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 panel
|
||||||
|
func (c *APIClient) GetUserList() (UserList *[]api.UserInfo, err error) {
|
||||||
|
path := "/api/v1/server/UniProxy/user"
|
||||||
|
|
||||||
|
switch c.NodeType {
|
||||||
|
case "V2ray", "Trojan", "Shadowsocks":
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("unsupported Node type: %s", c.NodeType)
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := c.client.R().
|
||||||
|
SetHeader("If-None-Match", c.eTag).
|
||||||
|
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")
|
||||||
|
}
|
||||||
|
// update etag
|
||||||
|
if res.Header().Get("Etag") != "" && res.Header().Get("Etag") != c.eTag {
|
||||||
|
c.eTag = res.Header().Get("Etag")
|
||||||
|
}
|
||||||
|
|
||||||
|
response, err := c.parseResponse(res, path, err)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
numOfUsers := len(response.Get("users").MustArray())
|
||||||
|
userList := make([]api.UserInfo, numOfUsers)
|
||||||
|
for i := 0; i < numOfUsers; i++ {
|
||||||
|
user := response.Get("users").GetIndex(i)
|
||||||
|
u := api.UserInfo{}
|
||||||
|
u.UID = user.Get("id").MustInt()
|
||||||
|
u.SpeedLimit = uint64(c.SpeedLimit * 1000000 / 8) // todo waiting v2board send configuration
|
||||||
|
u.DeviceLimit = c.DeviceLimit // todo waiting v2board send configuration
|
||||||
|
u.UUID = user.Get("uuid").MustString()
|
||||||
|
u.Email = u.UUID + "@v2board.user"
|
||||||
|
if c.NodeType == "Shadowsocks" {
|
||||||
|
u.Passwd = u.UUID
|
||||||
|
}
|
||||||
|
userList[i] = u
|
||||||
|
}
|
||||||
|
|
||||||
|
return &userList, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReportUserTraffic reports the user traffic
|
||||||
|
func (c *APIClient) ReportUserTraffic(userTraffic *[]api.UserTraffic) error {
|
||||||
|
path := "/api/v1/server/UniProxy/push"
|
||||||
|
|
||||||
|
// json structure: {uid1: [u, d], uid2: [u, d], uid1: [u, d], uid3: [u, d]}
|
||||||
|
data := make(map[int][]int64, len(*userTraffic))
|
||||||
|
for _, traffic := range *userTraffic {
|
||||||
|
data[traffic.UID] = []int64{traffic.Upload, traffic.Download}
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := c.client.R().
|
||||||
|
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
|
||||||
|
|
||||||
|
nodeInfoResponse := c.resp.Load().(*simplejson.Json)
|
||||||
|
for i, rule := range nodeInfoResponse.Get("routes").MustArray() {
|
||||||
|
r := rule.(map[string]any)
|
||||||
|
if r["action"] == "block" {
|
||||||
|
ruleListItem := api.DetectRule{
|
||||||
|
ID: i,
|
||||||
|
Pattern: regexp.MustCompile(r["match"].(string)),
|
||||||
|
}
|
||||||
|
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 nodeInfo format
|
||||||
|
func (c *APIClient) parseTrojanNodeResponse(nodeInfoResponse *simplejson.Json) (*api.NodeInfo, error) {
|
||||||
|
var TLSType = "tls"
|
||||||
|
if c.EnableXTLS {
|
||||||
|
TLSType = "xtls"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create GeneralNodeInfo
|
||||||
|
nodeInfo := &api.NodeInfo{
|
||||||
|
NodeType: c.NodeType,
|
||||||
|
NodeID: c.NodeID,
|
||||||
|
Port: uint32(nodeInfoResponse.Get("server_port").MustUint64()),
|
||||||
|
TransportProtocol: "tcp",
|
||||||
|
EnableTLS: true,
|
||||||
|
TLSType: TLSType,
|
||||||
|
Host: nodeInfoResponse.Get("host").MustString(),
|
||||||
|
ServiceName: nodeInfoResponse.Get("server_name").MustString(),
|
||||||
|
}
|
||||||
|
return nodeInfo, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseSSNodeResponse parse the response for the given nodeInfo format
|
||||||
|
func (c *APIClient) parseSSNodeResponse(nodeInfoResponse *simplejson.Json) (*api.NodeInfo, error) {
|
||||||
|
// Create GeneralNodeInfo
|
||||||
|
return &api.NodeInfo{
|
||||||
|
NodeType: c.NodeType,
|
||||||
|
NodeID: c.NodeID,
|
||||||
|
Port: uint32(nodeInfoResponse.Get("server_port").MustUint64()),
|
||||||
|
TransportProtocol: "tcp",
|
||||||
|
CypherMethod: nodeInfoResponse.Get("cipher").MustString(),
|
||||||
|
ServerKey: nodeInfoResponse.Get("server_key").MustString(), // shadowsocks2022 share key
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseV2rayNodeResponse parse the response for the given nodeInfo format
|
||||||
|
func (c *APIClient) parseV2rayNodeResponse(nodeInfoResponse *simplejson.Json) (*api.NodeInfo, error) {
|
||||||
|
var (
|
||||||
|
TLSType = "tls"
|
||||||
|
path, host, serviceName string
|
||||||
|
header json.RawMessage
|
||||||
|
enableTLS bool
|
||||||
|
alterID uint16 = 0
|
||||||
|
)
|
||||||
|
|
||||||
|
if c.EnableXTLS {
|
||||||
|
TLSType = "xtls"
|
||||||
|
}
|
||||||
|
|
||||||
|
transportProtocol := nodeInfoResponse.Get("network").MustString()
|
||||||
|
|
||||||
|
switch transportProtocol {
|
||||||
|
case "ws":
|
||||||
|
path = nodeInfoResponse.Get("networkSettings").Get("path").MustString()
|
||||||
|
host = nodeInfoResponse.Get("networkSettings").Get("headers").Get("Host").MustString()
|
||||||
|
case "grpc":
|
||||||
|
if data, ok := nodeInfoResponse.Get("networkSettings").CheckGet("serviceName"); ok {
|
||||||
|
serviceName = data.MustString()
|
||||||
|
}
|
||||||
|
case "tcp":
|
||||||
|
if data, ok := nodeInfoResponse.Get("networkSettings").CheckGet("headers"); ok {
|
||||||
|
if httpHeader, err := data.MarshalJSON(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else {
|
||||||
|
header = httpHeader
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if nodeInfoResponse.Get("tls").MustInt() == 1 {
|
||||||
|
enableTLS = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create GeneralNodeInfo
|
||||||
|
return &api.NodeInfo{
|
||||||
|
NodeType: c.NodeType,
|
||||||
|
NodeID: c.NodeID,
|
||||||
|
Port: uint32(nodeInfoResponse.Get("server_port").MustUint64()),
|
||||||
|
AlterID: alterID,
|
||||||
|
TransportProtocol: transportProtocol,
|
||||||
|
EnableTLS: enableTLS,
|
||||||
|
TLSType: TLSType,
|
||||||
|
Path: path,
|
||||||
|
Host: host,
|
||||||
|
EnableVless: c.EnableVless,
|
||||||
|
ServiceName: serviceName,
|
||||||
|
Header: header,
|
||||||
|
}, nil
|
||||||
|
}
|
101
api/newV2board/v2board_test.go
Normal file
101
api/newV2board/v2board_test.go
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
package newV2board_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/XrayR-project/XrayR/api"
|
||||||
|
"github.com/XrayR-project/XrayR/api/newV2board"
|
||||||
|
)
|
||||||
|
|
||||||
|
func CreateClient() api.API {
|
||||||
|
apiConfig := &api.Config{
|
||||||
|
APIHost: "http://localhost:9897",
|
||||||
|
Key: "qwertyuiopasdfghjkl",
|
||||||
|
NodeID: 1,
|
||||||
|
NodeType: "V2ray",
|
||||||
|
}
|
||||||
|
client := newV2board.New(apiConfig)
|
||||||
|
return client
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetV2rayNodeInfo(t *testing.T) {
|
||||||
|
client := CreateClient()
|
||||||
|
nodeInfo, err := client.GetNodeInfo()
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
t.Log(nodeInfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetSSNodeInfo(t *testing.T) {
|
||||||
|
apiConfig := &api.Config{
|
||||||
|
APIHost: "http://127.0.0.1:668",
|
||||||
|
Key: "qwertyuiopasdfghjkl",
|
||||||
|
NodeID: 1,
|
||||||
|
NodeType: "Shadowsocks",
|
||||||
|
}
|
||||||
|
client := newV2board.New(apiConfig)
|
||||||
|
nodeInfo, err := client.GetNodeInfo()
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
t.Log(nodeInfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetTrojanNodeInfo(t *testing.T) {
|
||||||
|
apiConfig := &api.Config{
|
||||||
|
APIHost: "http://127.0.0.1:668",
|
||||||
|
Key: "qwertyuiopasdfghjkl",
|
||||||
|
NodeID: 1,
|
||||||
|
NodeType: "Trojan",
|
||||||
|
}
|
||||||
|
client := newV2board.New(apiConfig)
|
||||||
|
nodeInfo, err := client.GetNodeInfo()
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
t.Log(nodeInfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetUserList(t *testing.T) {
|
||||||
|
client := CreateClient()
|
||||||
|
|
||||||
|
userList, err := client.GetUserList()
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Log(userList)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestReportReportUserTraffic(t *testing.T) {
|
||||||
|
client := CreateClient()
|
||||||
|
userList, err := client.GetUserList()
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
generalUserTraffic := make([]api.UserTraffic, len(*userList))
|
||||||
|
for i, userInfo := range *userList {
|
||||||
|
generalUserTraffic[i] = api.UserTraffic{
|
||||||
|
UID: userInfo.UID,
|
||||||
|
Upload: 114514,
|
||||||
|
Download: 114514,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// client.Debug()
|
||||||
|
err = client.ReportUserTraffic(&generalUserTraffic)
|
||||||
|
if err != nil {
|
||||||
|
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)
|
||||||
|
}
|
@@ -16,7 +16,7 @@ type NodeInfoResponse struct {
|
|||||||
Host string `json:"host"`
|
Host string `json:"host"`
|
||||||
Path string `json:"path"`
|
Path string `json:"path"`
|
||||||
Grpc bool `json:"grpc"`
|
Grpc bool `json:"grpc"`
|
||||||
Sni string `json:sni`
|
Sni string `json:"sni"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// UserResponse is the response of user
|
// UserResponse is the response of user
|
||||||
|
@@ -11,8 +11,9 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/XrayR-project/XrayR/api"
|
|
||||||
"github.com/go-resty/resty/v2"
|
"github.com/go-resty/resty/v2"
|
||||||
|
|
||||||
|
"github.com/XrayR-project/XrayR/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
// APIClient create a api client to the panel.
|
// APIClient create a api client to the panel.
|
||||||
@@ -76,7 +77,7 @@ func readLocalRuleList(path string) (LocalRuleList []api.DetectRule) {
|
|||||||
// open the file
|
// open the file
|
||||||
file, err := os.Open(path)
|
file, err := os.Open(path)
|
||||||
|
|
||||||
//handle errors while opening
|
// handle errors while opening
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Error when opening file: %s", err)
|
log.Printf("Error when opening file: %s", err)
|
||||||
return LocalRuleList
|
return LocalRuleList
|
||||||
@@ -94,7 +95,7 @@ func readLocalRuleList(path string) (LocalRuleList []api.DetectRule) {
|
|||||||
// handle first encountered error while reading
|
// handle first encountered error while reading
|
||||||
if err := fileScanner.Err(); err != nil {
|
if err := fileScanner.Err(); err != nil {
|
||||||
log.Fatalf("Error while reading file: %s", err)
|
log.Fatalf("Error while reading file: %s", err)
|
||||||
return make([]api.DetectRule, 0)
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
file.Close()
|
file.Close()
|
||||||
@@ -130,7 +131,7 @@ func (c *APIClient) parseResponse(res *resty.Response, path string, err error) (
|
|||||||
|
|
||||||
if response.Ret != 200 {
|
if response.Ret != 200 {
|
||||||
res, _ := json.Marshal(&response)
|
res, _ := json.Marshal(&response)
|
||||||
return nil, fmt.Errorf("Ret %s invalid", string(res))
|
return nil, fmt.Errorf("ret %s invalid", string(res))
|
||||||
}
|
}
|
||||||
return response, nil
|
return response, nil
|
||||||
}
|
}
|
||||||
@@ -167,7 +168,7 @@ func (c *APIClient) GetNodeInfo() (nodeInfo *api.NodeInfo, err error) {
|
|||||||
nodeInfoResponse := new(NodeInfoResponse)
|
nodeInfoResponse := new(NodeInfoResponse)
|
||||||
|
|
||||||
if err := json.Unmarshal(response.Data, nodeInfoResponse); err != nil {
|
if err := json.Unmarshal(response.Data, nodeInfoResponse); err != nil {
|
||||||
return nil, fmt.Errorf("Unmarshal %s failed: %s", reflect.TypeOf(nodeInfoResponse), err)
|
return nil, fmt.Errorf("unmarshal %s failed: %s", reflect.TypeOf(nodeInfoResponse), err)
|
||||||
}
|
}
|
||||||
switch c.NodeType {
|
switch c.NodeType {
|
||||||
case "V2ray":
|
case "V2ray":
|
||||||
@@ -177,7 +178,7 @@ func (c *APIClient) GetNodeInfo() (nodeInfo *api.NodeInfo, err error) {
|
|||||||
case "Shadowsocks":
|
case "Shadowsocks":
|
||||||
nodeInfo, err = c.ParseSSNodeResponse(nodeInfoResponse)
|
nodeInfo, err = c.ParseSSNodeResponse(nodeInfoResponse)
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("Unsupported Node type: %s", c.NodeType)
|
return nil, fmt.Errorf("unsupported Node type: %s", c.NodeType)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -219,12 +220,12 @@ func (c *APIClient) GetUserList() (UserList *[]api.UserInfo, err error) {
|
|||||||
|
|
||||||
var userListResponse *[]UserResponse
|
var userListResponse *[]UserResponse
|
||||||
if err := json.Unmarshal(response.Data, &userListResponse); err != nil {
|
if err := json.Unmarshal(response.Data, &userListResponse); err != nil {
|
||||||
return nil, fmt.Errorf("Unmarshal %s failed: %s", reflect.TypeOf(userListResponse), err)
|
return nil, fmt.Errorf("unmarshal %s failed: %s", reflect.TypeOf(userListResponse), err)
|
||||||
}
|
}
|
||||||
userList, err := c.ParseUserListResponse(userListResponse)
|
userList, err := c.ParseUserListResponse(userListResponse)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
res, _ := json.Marshal(userListResponse)
|
res, _ := json.Marshal(userListResponse)
|
||||||
return nil, fmt.Errorf("Parse user list failed: %s", string(res))
|
return nil, fmt.Errorf("parse user list failed: %s", string(res))
|
||||||
}
|
}
|
||||||
return userList, nil
|
return userList, nil
|
||||||
}
|
}
|
||||||
@@ -234,7 +235,7 @@ func (c *APIClient) ReportNodeStatus(nodeStatus *api.NodeStatus) (err error) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//ReportNodeOnlineUsers reports online user ip
|
// ReportNodeOnlineUsers reports online user ip
|
||||||
func (c *APIClient) ReportNodeOnlineUsers(onlineUserList *[]api.OnlineUser) error {
|
func (c *APIClient) ReportNodeOnlineUsers(onlineUserList *[]api.OnlineUser) error {
|
||||||
var nodeType = ""
|
var nodeType = ""
|
||||||
switch c.NodeType {
|
switch c.NodeType {
|
||||||
@@ -338,7 +339,7 @@ func (c *APIClient) GetNodeRule() (*[]api.DetectRule, error) {
|
|||||||
ruleListResponse := new([]RuleItem)
|
ruleListResponse := new([]RuleItem)
|
||||||
|
|
||||||
if err := json.Unmarshal(response.Data, ruleListResponse); err != nil {
|
if err := json.Unmarshal(response.Data, ruleListResponse); err != nil {
|
||||||
return nil, fmt.Errorf("Unmarshal %s failed: %s", reflect.TypeOf(ruleListResponse), err)
|
return nil, fmt.Errorf("unmarshal %s failed: %s", reflect.TypeOf(ruleListResponse), err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, r := range *ruleListResponse {
|
for _, r := range *ruleListResponse {
|
||||||
|
@@ -85,7 +85,7 @@ func TestGetUserList(t *testing.T) {
|
|||||||
func TestReportNodeStatus(t *testing.T) {
|
func TestReportNodeStatus(t *testing.T) {
|
||||||
client := CreateClient()
|
client := CreateClient()
|
||||||
nodeStatus := &api.NodeStatus{
|
nodeStatus := &api.NodeStatus{
|
||||||
1, 1, 1, 256,
|
CPU: 1, Mem: 1, Disk: 1, Uptime: 256,
|
||||||
}
|
}
|
||||||
err := client.ReportNodeStatus(nodeStatus)
|
err := client.ReportNodeStatus(nodeStatus)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -107,7 +107,7 @@ func TestReportReportNodeOnlineUsers(t *testing.T) {
|
|||||||
IP: fmt.Sprintf("1.1.1.%d", i),
|
IP: fmt.Sprintf("1.1.1.%d", i),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//client.Debug()
|
// client.Debug()
|
||||||
err = client.ReportNodeOnlineUsers(&onlineUserList)
|
err = client.ReportNodeOnlineUsers(&onlineUserList)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
@@ -128,7 +128,7 @@ func TestReportReportUserTraffic(t *testing.T) {
|
|||||||
Download: 114514,
|
Download: 114514,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//client.Debug()
|
// client.Debug()
|
||||||
err = client.ReportUserTraffic(&generalUserTraffic)
|
err = client.ReportUserTraffic(&generalUserTraffic)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
@@ -150,8 +150,8 @@ func TestReportIllegal(t *testing.T) {
|
|||||||
client := CreateClient()
|
client := CreateClient()
|
||||||
|
|
||||||
detectResult := []api.DetectResult{
|
detectResult := []api.DetectResult{
|
||||||
api.DetectResult{1, 2},
|
{1, 2},
|
||||||
api.DetectResult{1, 3},
|
{1, 3},
|
||||||
}
|
}
|
||||||
client.Debug()
|
client.Debug()
|
||||||
err := client.ReportIllegal(&detectResult)
|
err := client.ReportIllegal(&detectResult)
|
||||||
|
@@ -49,7 +49,7 @@ type TrojanNodeInfo struct {
|
|||||||
TrojanPort uint32 `json:"trojan_port"`
|
TrojanPort uint32 `json:"trojan_port"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Node status report
|
// NodeStatus Node status report
|
||||||
type NodeStatus struct {
|
type NodeStatus struct {
|
||||||
CPU string `json:"cpu"`
|
CPU string `json:"cpu"`
|
||||||
Mem string `json:"mem"`
|
Mem string `json:"mem"`
|
||||||
@@ -98,7 +98,6 @@ type NodeRuleItem struct {
|
|||||||
Pattern string `json:"pattern"`
|
Pattern string `json:"pattern"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// IllegalReport
|
|
||||||
type IllegalReport struct {
|
type IllegalReport struct {
|
||||||
UID int `json:"uid"`
|
UID int `json:"uid"`
|
||||||
RuleID int `json:"rule_id"`
|
RuleID int `json:"rule_id"`
|
||||||
|
@@ -11,8 +11,9 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/XrayR-project/XrayR/api"
|
|
||||||
"github.com/go-resty/resty/v2"
|
"github.com/go-resty/resty/v2"
|
||||||
|
|
||||||
|
"github.com/XrayR-project/XrayR/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
// APIClient create a api client to the panel.
|
// APIClient create a api client to the panel.
|
||||||
@@ -72,7 +73,7 @@ func readLocalRuleList(path string) (LocalRuleList []api.DetectRule) {
|
|||||||
// open the file
|
// open the file
|
||||||
file, err := os.Open(path)
|
file, err := os.Open(path)
|
||||||
|
|
||||||
//handle errors while opening
|
// handle errors while opening
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Error when opening file: %s", err)
|
log.Printf("Error when opening file: %s", err)
|
||||||
return LocalRuleList
|
return LocalRuleList
|
||||||
@@ -90,7 +91,7 @@ func readLocalRuleList(path string) (LocalRuleList []api.DetectRule) {
|
|||||||
// handle first encountered error while reading
|
// handle first encountered error while reading
|
||||||
if err := fileScanner.Err(); err != nil {
|
if err := fileScanner.Err(); err != nil {
|
||||||
log.Fatalf("Error while reading file: %s", err)
|
log.Fatalf("Error while reading file: %s", err)
|
||||||
return make([]api.DetectRule, 0)
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
file.Close()
|
file.Close()
|
||||||
@@ -134,7 +135,7 @@ func (c *APIClient) parseResponse(res *resty.Response, path string, err error) (
|
|||||||
|
|
||||||
if response.Status != "success" {
|
if response.Status != "success" {
|
||||||
res, _ := json.Marshal(&response)
|
res, _ := json.Marshal(&response)
|
||||||
return nil, fmt.Errorf("Ret %s invalid", string(res))
|
return nil, fmt.Errorf("ret %s invalid", string(res))
|
||||||
}
|
}
|
||||||
return response, nil
|
return response, nil
|
||||||
}
|
}
|
||||||
@@ -150,7 +151,7 @@ func (c *APIClient) GetNodeInfo() (nodeInfo *api.NodeInfo, err error) {
|
|||||||
case "Shadowsocks":
|
case "Shadowsocks":
|
||||||
path = fmt.Sprintf("/api/ss/v1/node/%d", c.NodeID)
|
path = fmt.Sprintf("/api/ss/v1/node/%d", c.NodeID)
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("Unsupported Node type: %s", c.NodeType)
|
return nil, fmt.Errorf("unsupported Node type: %s", c.NodeType)
|
||||||
}
|
}
|
||||||
|
|
||||||
res, err := c.createCommonRequest().
|
res, err := c.createCommonRequest().
|
||||||
@@ -171,7 +172,7 @@ func (c *APIClient) GetNodeInfo() (nodeInfo *api.NodeInfo, err error) {
|
|||||||
case "Shadowsocks":
|
case "Shadowsocks":
|
||||||
nodeInfo, err = c.ParseSSNodeResponse(&response.Data)
|
nodeInfo, err = c.ParseSSNodeResponse(&response.Data)
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("Unsupported Node type: %s", c.NodeType)
|
return nil, fmt.Errorf("unsupported Node type: %s", c.NodeType)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -193,7 +194,7 @@ func (c *APIClient) GetUserList() (UserList *[]api.UserInfo, err error) {
|
|||||||
case "Shadowsocks":
|
case "Shadowsocks":
|
||||||
path = fmt.Sprintf("/api/ss/v1/userList/%d", c.NodeID)
|
path = fmt.Sprintf("/api/ss/v1/userList/%d", c.NodeID)
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("Unsupported Node type: %s", c.NodeType)
|
return nil, fmt.Errorf("unsupported Node type: %s", c.NodeType)
|
||||||
}
|
}
|
||||||
|
|
||||||
res, err := c.createCommonRequest().
|
res, err := c.createCommonRequest().
|
||||||
@@ -214,11 +215,11 @@ func (c *APIClient) GetUserList() (UserList *[]api.UserInfo, err error) {
|
|||||||
case "Shadowsocks":
|
case "Shadowsocks":
|
||||||
userList, err = c.ParseSSUserListResponse(&response.Data)
|
userList, err = c.ParseSSUserListResponse(&response.Data)
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("Unsupported Node type: %s", c.NodeType)
|
return nil, fmt.Errorf("unsupported Node type: %s", c.NodeType)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
res, _ := json.Marshal(response.Data)
|
res, _ := json.Marshal(response.Data)
|
||||||
return nil, fmt.Errorf("Parse user list failed: %s", string(res))
|
return nil, fmt.Errorf("parse user list failed: %s", string(res))
|
||||||
}
|
}
|
||||||
return userList, nil
|
return userList, nil
|
||||||
}
|
}
|
||||||
@@ -234,7 +235,7 @@ func (c *APIClient) ReportNodeStatus(nodeStatus *api.NodeStatus) (err error) {
|
|||||||
case "Shadowsocks":
|
case "Shadowsocks":
|
||||||
path = fmt.Sprintf("/api/ss/v1/nodeStatus/%d", c.NodeID)
|
path = fmt.Sprintf("/api/ss/v1/nodeStatus/%d", c.NodeID)
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("Unsupported Node type: %s", c.NodeType)
|
return fmt.Errorf("unsupported Node type: %s", c.NodeType)
|
||||||
}
|
}
|
||||||
|
|
||||||
systemload := NodeStatus{
|
systemload := NodeStatus{
|
||||||
@@ -258,7 +259,7 @@ func (c *APIClient) ReportNodeStatus(nodeStatus *api.NodeStatus) (err error) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//ReportNodeOnlineUsers reports online user ip
|
// ReportNodeOnlineUsers reports online user ip
|
||||||
func (c *APIClient) ReportNodeOnlineUsers(onlineUserList *[]api.OnlineUser) error {
|
func (c *APIClient) ReportNodeOnlineUsers(onlineUserList *[]api.OnlineUser) error {
|
||||||
|
|
||||||
var path string
|
var path string
|
||||||
@@ -270,7 +271,7 @@ func (c *APIClient) ReportNodeOnlineUsers(onlineUserList *[]api.OnlineUser) erro
|
|||||||
case "Shadowsocks":
|
case "Shadowsocks":
|
||||||
path = fmt.Sprintf("/api/ss/v1/nodeOnline/%d", c.NodeID)
|
path = fmt.Sprintf("/api/ss/v1/nodeOnline/%d", c.NodeID)
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("Unsupported Node type: %s", c.NodeType)
|
return fmt.Errorf("unsupported Node type: %s", c.NodeType)
|
||||||
}
|
}
|
||||||
|
|
||||||
data := make([]NodeOnline, len(*onlineUserList))
|
data := make([]NodeOnline, len(*onlineUserList))
|
||||||
@@ -303,7 +304,7 @@ func (c *APIClient) ReportUserTraffic(userTraffic *[]api.UserTraffic) error {
|
|||||||
case "Shadowsocks":
|
case "Shadowsocks":
|
||||||
path = fmt.Sprintf("/api/ss/v1/userTraffic/%d", c.NodeID)
|
path = fmt.Sprintf("/api/ss/v1/userTraffic/%d", c.NodeID)
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("Unsupported Node type: %s", c.NodeType)
|
return fmt.Errorf("unsupported Node type: %s", c.NodeType)
|
||||||
}
|
}
|
||||||
|
|
||||||
data := make([]UserTraffic, len(*userTraffic))
|
data := make([]UserTraffic, len(*userTraffic))
|
||||||
@@ -338,7 +339,7 @@ func (c *APIClient) GetNodeRule() (*[]api.DetectRule, error) {
|
|||||||
case "Shadowsocks":
|
case "Shadowsocks":
|
||||||
path = fmt.Sprintf("/api/ss/v1/nodeRule/%d", c.NodeID)
|
path = fmt.Sprintf("/api/ss/v1/nodeRule/%d", c.NodeID)
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("Unsupported Node type: %s", c.NodeType)
|
return nil, fmt.Errorf("unsupported Node type: %s", c.NodeType)
|
||||||
}
|
}
|
||||||
|
|
||||||
res, err := c.createCommonRequest().
|
res, err := c.createCommonRequest().
|
||||||
@@ -354,7 +355,7 @@ func (c *APIClient) GetNodeRule() (*[]api.DetectRule, error) {
|
|||||||
ruleListResponse := new(NodeRule)
|
ruleListResponse := new(NodeRule)
|
||||||
|
|
||||||
if err := json.Unmarshal(response.Data, ruleListResponse); err != nil {
|
if err := json.Unmarshal(response.Data, ruleListResponse); err != nil {
|
||||||
return nil, fmt.Errorf("Unmarshal %s failed: %s", reflect.TypeOf(ruleListResponse), err)
|
return nil, fmt.Errorf("unmarshal %s failed: %s", reflect.TypeOf(ruleListResponse), err)
|
||||||
}
|
}
|
||||||
ruleList := c.LocalRuleList
|
ruleList := c.LocalRuleList
|
||||||
// Only support reject rule type
|
// Only support reject rule type
|
||||||
@@ -386,7 +387,7 @@ func (c *APIClient) ReportIllegal(detectResultList *[]api.DetectResult) error {
|
|||||||
case "Shadowsocks":
|
case "Shadowsocks":
|
||||||
path = fmt.Sprintf("/api/ss/v1/trigger/%d", c.NodeID)
|
path = fmt.Sprintf("/api/ss/v1/trigger/%d", c.NodeID)
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("Unsupported Node type: %s", c.NodeType)
|
return fmt.Errorf("unsupported Node type: %s", c.NodeType)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, r := range *detectResultList {
|
for _, r := range *detectResultList {
|
||||||
@@ -421,7 +422,7 @@ func (c *APIClient) ParseV2rayNodeResponse(nodeInfoResponse *json.RawMessage) (*
|
|||||||
|
|
||||||
v2rayNodeInfo := new(V2rayNodeInfo)
|
v2rayNodeInfo := new(V2rayNodeInfo)
|
||||||
if err := json.Unmarshal(*nodeInfoResponse, v2rayNodeInfo); err != nil {
|
if err := json.Unmarshal(*nodeInfoResponse, v2rayNodeInfo); err != nil {
|
||||||
return nil, fmt.Errorf("Unmarshal %s failed: %s", reflect.TypeOf(*nodeInfoResponse), err)
|
return nil, fmt.Errorf("unmarshal %s failed: %s", reflect.TypeOf(*nodeInfoResponse), err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.SpeedLimit > 0 {
|
if c.SpeedLimit > 0 {
|
||||||
@@ -458,7 +459,7 @@ func (c *APIClient) ParseSSNodeResponse(nodeInfoResponse *json.RawMessage) (*api
|
|||||||
var speedlimit uint64 = 0
|
var speedlimit uint64 = 0
|
||||||
shadowsocksNodeInfo := new(ShadowsocksNodeInfo)
|
shadowsocksNodeInfo := new(ShadowsocksNodeInfo)
|
||||||
if err := json.Unmarshal(*nodeInfoResponse, shadowsocksNodeInfo); err != nil {
|
if err := json.Unmarshal(*nodeInfoResponse, shadowsocksNodeInfo); err != nil {
|
||||||
return nil, fmt.Errorf("Unmarshal %s failed: %s", reflect.TypeOf(*nodeInfoResponse), err)
|
return nil, fmt.Errorf("unmarshal %s failed: %s", reflect.TypeOf(*nodeInfoResponse), err)
|
||||||
}
|
}
|
||||||
if c.SpeedLimit > 0 {
|
if c.SpeedLimit > 0 {
|
||||||
speedlimit = uint64((c.SpeedLimit * 1000000) / 8)
|
speedlimit = uint64((c.SpeedLimit * 1000000) / 8)
|
||||||
@@ -495,7 +496,7 @@ func (c *APIClient) ParseTrojanNodeResponse(nodeInfoResponse *json.RawMessage) (
|
|||||||
|
|
||||||
trojanNodeInfo := new(TrojanNodeInfo)
|
trojanNodeInfo := new(TrojanNodeInfo)
|
||||||
if err := json.Unmarshal(*nodeInfoResponse, trojanNodeInfo); err != nil {
|
if err := json.Unmarshal(*nodeInfoResponse, trojanNodeInfo); err != nil {
|
||||||
return nil, fmt.Errorf("Unmarshal %s failed: %s", reflect.TypeOf(*nodeInfoResponse), err)
|
return nil, fmt.Errorf("unmarshal %s failed: %s", reflect.TypeOf(*nodeInfoResponse), err)
|
||||||
}
|
}
|
||||||
if c.SpeedLimit > 0 {
|
if c.SpeedLimit > 0 {
|
||||||
speedlimit = uint64((c.SpeedLimit * 1000000) / 8)
|
speedlimit = uint64((c.SpeedLimit * 1000000) / 8)
|
||||||
@@ -527,7 +528,7 @@ func (c *APIClient) ParseV2rayUserListResponse(userInfoResponse *json.RawMessage
|
|||||||
|
|
||||||
vmessUserList := new([]*VMessUser)
|
vmessUserList := new([]*VMessUser)
|
||||||
if err := json.Unmarshal(*userInfoResponse, vmessUserList); err != nil {
|
if err := json.Unmarshal(*userInfoResponse, vmessUserList); err != nil {
|
||||||
return nil, fmt.Errorf("Unmarshal %s failed: %s", reflect.TypeOf(*userInfoResponse), err)
|
return nil, fmt.Errorf("unmarshal %s failed: %s", reflect.TypeOf(*userInfoResponse), err)
|
||||||
}
|
}
|
||||||
|
|
||||||
userList := make([]api.UserInfo, len(*vmessUserList))
|
userList := make([]api.UserInfo, len(*vmessUserList))
|
||||||
@@ -555,7 +556,7 @@ func (c *APIClient) ParseTrojanUserListResponse(userInfoResponse *json.RawMessag
|
|||||||
|
|
||||||
trojanUserList := new([]*TrojanUser)
|
trojanUserList := new([]*TrojanUser)
|
||||||
if err := json.Unmarshal(*userInfoResponse, trojanUserList); err != nil {
|
if err := json.Unmarshal(*userInfoResponse, trojanUserList); err != nil {
|
||||||
return nil, fmt.Errorf("Unmarshal %s failed: %s", reflect.TypeOf(*userInfoResponse), err)
|
return nil, fmt.Errorf("unmarshal %s failed: %s", reflect.TypeOf(*userInfoResponse), err)
|
||||||
}
|
}
|
||||||
|
|
||||||
userList := make([]api.UserInfo, len(*trojanUserList))
|
userList := make([]api.UserInfo, len(*trojanUserList))
|
||||||
@@ -563,7 +564,7 @@ func (c *APIClient) ParseTrojanUserListResponse(userInfoResponse *json.RawMessag
|
|||||||
if c.SpeedLimit > 0 {
|
if c.SpeedLimit > 0 {
|
||||||
speedlimit = uint64((c.SpeedLimit * 1000000) / 8)
|
speedlimit = uint64((c.SpeedLimit * 1000000) / 8)
|
||||||
} else {
|
} else {
|
||||||
speedlimit = uint64((user.SpeedLimit * 1000000) / 8)
|
speedlimit = (user.SpeedLimit * 1000000) / 8
|
||||||
}
|
}
|
||||||
userList[i] = api.UserInfo{
|
userList[i] = api.UserInfo{
|
||||||
UID: user.UID,
|
UID: user.UID,
|
||||||
@@ -583,7 +584,7 @@ func (c *APIClient) ParseSSUserListResponse(userInfoResponse *json.RawMessage) (
|
|||||||
|
|
||||||
ssUserList := new([]*SSUser)
|
ssUserList := new([]*SSUser)
|
||||||
if err := json.Unmarshal(*userInfoResponse, ssUserList); err != nil {
|
if err := json.Unmarshal(*userInfoResponse, ssUserList); err != nil {
|
||||||
return nil, fmt.Errorf("Unmarshal %s failed: %s", reflect.TypeOf(*userInfoResponse), err)
|
return nil, fmt.Errorf("unmarshal %s failed: %s", reflect.TypeOf(*userInfoResponse), err)
|
||||||
}
|
}
|
||||||
|
|
||||||
userList := make([]api.UserInfo, len(*ssUserList))
|
userList := make([]api.UserInfo, len(*ssUserList))
|
||||||
|
@@ -89,7 +89,7 @@ func TestGetUserList(t *testing.T) {
|
|||||||
func TestReportNodeStatus(t *testing.T) {
|
func TestReportNodeStatus(t *testing.T) {
|
||||||
client := CreateClient()
|
client := CreateClient()
|
||||||
nodeStatus := &api.NodeStatus{
|
nodeStatus := &api.NodeStatus{
|
||||||
1, 1, 1, 256,
|
CPU: 1, Mem: 1, Disk: 1, Uptime: 256,
|
||||||
}
|
}
|
||||||
err := client.ReportNodeStatus(nodeStatus)
|
err := client.ReportNodeStatus(nodeStatus)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -111,7 +111,7 @@ func TestReportReportNodeOnlineUsers(t *testing.T) {
|
|||||||
IP: fmt.Sprintf("1.1.1.%d", i),
|
IP: fmt.Sprintf("1.1.1.%d", i),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//client.Debug()
|
// client.Debug()
|
||||||
err = client.ReportNodeOnlineUsers(&onlineUserList)
|
err = client.ReportNodeOnlineUsers(&onlineUserList)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
@@ -154,8 +154,8 @@ func TestReportIllegal(t *testing.T) {
|
|||||||
client := CreateClient()
|
client := CreateClient()
|
||||||
|
|
||||||
detectResult := []api.DetectResult{
|
detectResult := []api.DetectResult{
|
||||||
api.DetectResult{1, 1},
|
{1, 1},
|
||||||
api.DetectResult{1, 2},
|
{1, 2},
|
||||||
}
|
}
|
||||||
client.Debug()
|
client.Debug()
|
||||||
err := client.ReportIllegal(&detectResult)
|
err := client.ReportIllegal(&detectResult)
|
||||||
|
@@ -13,14 +13,15 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/XrayR-project/XrayR/api"
|
|
||||||
"github.com/go-resty/resty/v2"
|
"github.com/go-resty/resty/v2"
|
||||||
|
|
||||||
|
"github.com/XrayR-project/XrayR/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
firstPortRe = regexp.MustCompile(`(?m)port=(?P<outport>\d+)#?`) // First Port
|
firstPortRe = regexp.MustCompile(`(?m)port=(?P<outport>\d+)#?`) // First Port
|
||||||
secondPortRe = regexp.MustCompile(`(?m)port=\d+#(\d+)`) // Second Port
|
secondPortRe = regexp.MustCompile(`(?m)port=\d+#(\d+)`) // Second Port
|
||||||
hostRe = regexp.MustCompile(`(?m)host=([\w\.]+)\|?`) // Host
|
hostRe = regexp.MustCompile(`(?m)host=([\w.]+)\|?`) // Host
|
||||||
)
|
)
|
||||||
|
|
||||||
// APIClient create a api client to the panel.
|
// APIClient create a api client to the panel.
|
||||||
@@ -89,7 +90,7 @@ func readLocalRuleList(path string) (LocalRuleList []api.DetectRule) {
|
|||||||
// open the file
|
// open the file
|
||||||
file, err := os.Open(path)
|
file, err := os.Open(path)
|
||||||
|
|
||||||
//handle errors while opening
|
// handle errors while opening
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Error when opening file: %s", err)
|
log.Printf("Error when opening file: %s", err)
|
||||||
return LocalRuleList
|
return LocalRuleList
|
||||||
@@ -107,7 +108,7 @@ func readLocalRuleList(path string) (LocalRuleList []api.DetectRule) {
|
|||||||
// handle first encountered error while reading
|
// handle first encountered error while reading
|
||||||
if err := fileScanner.Err(); err != nil {
|
if err := fileScanner.Err(); err != nil {
|
||||||
log.Fatalf("Error while reading file: %s", err)
|
log.Fatalf("Error while reading file: %s", err)
|
||||||
return make([]api.DetectRule, 0)
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
file.Close()
|
file.Close()
|
||||||
@@ -143,7 +144,7 @@ func (c *APIClient) parseResponse(res *resty.Response, path string, err error) (
|
|||||||
|
|
||||||
if response.Ret != 1 {
|
if response.Ret != 1 {
|
||||||
res, _ := json.Marshal(&response)
|
res, _ := json.Marshal(&response)
|
||||||
return nil, fmt.Errorf("Ret %s invalid", string(res))
|
return nil, fmt.Errorf("ret %s invalid", string(res))
|
||||||
}
|
}
|
||||||
return response, nil
|
return response, nil
|
||||||
}
|
}
|
||||||
@@ -164,7 +165,7 @@ func (c *APIClient) GetNodeInfo() (nodeInfo *api.NodeInfo, err error) {
|
|||||||
nodeInfoResponse := new(NodeInfoResponse)
|
nodeInfoResponse := new(NodeInfoResponse)
|
||||||
|
|
||||||
if err := json.Unmarshal(response.Data, nodeInfoResponse); err != nil {
|
if err := json.Unmarshal(response.Data, nodeInfoResponse); err != nil {
|
||||||
return nil, fmt.Errorf("Unmarshal %s failed: %s", reflect.TypeOf(nodeInfoResponse), err)
|
return nil, fmt.Errorf("unmarshal %s failed: %s", reflect.TypeOf(nodeInfoResponse), err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// New sspanel API
|
// New sspanel API
|
||||||
@@ -196,7 +197,7 @@ func (c *APIClient) GetNodeInfo() (nodeInfo *api.NodeInfo, err error) {
|
|||||||
case "Shadowsocks-Plugin":
|
case "Shadowsocks-Plugin":
|
||||||
nodeInfo, err = c.ParseSSPluginNodeResponse(nodeInfoResponse)
|
nodeInfo, err = c.ParseSSPluginNodeResponse(nodeInfoResponse)
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("Unsupported Node type: %s", c.NodeType)
|
return nil, fmt.Errorf("unsupported Node type: %s", c.NodeType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -225,12 +226,12 @@ func (c *APIClient) GetUserList() (UserList *[]api.UserInfo, err error) {
|
|||||||
userListResponse := new([]UserResponse)
|
userListResponse := new([]UserResponse)
|
||||||
|
|
||||||
if err := json.Unmarshal(response.Data, userListResponse); err != nil {
|
if err := json.Unmarshal(response.Data, userListResponse); err != nil {
|
||||||
return nil, fmt.Errorf("Unmarshal %s failed: %s", reflect.TypeOf(userListResponse), err)
|
return nil, fmt.Errorf("unmarshal %s failed: %s", reflect.TypeOf(userListResponse), err)
|
||||||
}
|
}
|
||||||
userList, err := c.ParseUserListResponse(userListResponse)
|
userList, err := c.ParseUserListResponse(userListResponse)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
res, _ := json.Marshal(userListResponse)
|
res, _ := json.Marshal(userListResponse)
|
||||||
return nil, fmt.Errorf("Parse user list failed: %s", string(res))
|
return nil, fmt.Errorf("parse user list failed: %s", string(res))
|
||||||
}
|
}
|
||||||
return userList, nil
|
return userList, nil
|
||||||
}
|
}
|
||||||
@@ -240,7 +241,7 @@ func (c *APIClient) ReportNodeStatus(nodeStatus *api.NodeStatus) (err error) {
|
|||||||
path := fmt.Sprintf("/mod_mu/nodes/%d/info", c.NodeID)
|
path := fmt.Sprintf("/mod_mu/nodes/%d/info", c.NodeID)
|
||||||
systemload := SystemLoad{
|
systemload := SystemLoad{
|
||||||
Uptime: strconv.FormatUint(nodeStatus.Uptime, 10),
|
Uptime: strconv.FormatUint(nodeStatus.Uptime, 10),
|
||||||
Load: fmt.Sprintf("%.2f %.2f %.2f", nodeStatus.CPU/100, nodeStatus.CPU/100, nodeStatus.CPU/100),
|
Load: fmt.Sprintf("%.2f %.2f %.2f", nodeStatus.CPU/100, nodeStatus.Mem/100, nodeStatus.Disk/100),
|
||||||
}
|
}
|
||||||
|
|
||||||
res, err := c.client.R().
|
res, err := c.client.R().
|
||||||
@@ -257,7 +258,7 @@ func (c *APIClient) ReportNodeStatus(nodeStatus *api.NodeStatus) (err error) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//ReportNodeOnlineUsers reports online user ip
|
// ReportNodeOnlineUsers reports online user ip
|
||||||
func (c *APIClient) ReportNodeOnlineUsers(onlineUserList *[]api.OnlineUser) error {
|
func (c *APIClient) ReportNodeOnlineUsers(onlineUserList *[]api.OnlineUser) error {
|
||||||
c.access.Lock()
|
c.access.Lock()
|
||||||
defer c.access.Unlock()
|
defer c.access.Unlock()
|
||||||
@@ -334,7 +335,7 @@ func (c *APIClient) GetNodeRule() (*[]api.DetectRule, error) {
|
|||||||
ruleListResponse := new([]RuleItem)
|
ruleListResponse := new([]RuleItem)
|
||||||
|
|
||||||
if err := json.Unmarshal(response.Data, ruleListResponse); err != nil {
|
if err := json.Unmarshal(response.Data, ruleListResponse); err != nil {
|
||||||
return nil, fmt.Errorf("Unmarshal %s failed: %s", reflect.TypeOf(ruleListResponse), err)
|
return nil, fmt.Errorf("unmarshal %s failed: %s", reflect.TypeOf(ruleListResponse), err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, r := range *ruleListResponse {
|
for _, r := range *ruleListResponse {
|
||||||
@@ -378,9 +379,9 @@ func (c *APIClient) ParseV2rayNodeResponse(nodeInfoResponse *NodeInfoResponse) (
|
|||||||
var header json.RawMessage
|
var header json.RawMessage
|
||||||
var speedlimit uint64 = 0
|
var speedlimit uint64 = 0
|
||||||
if nodeInfoResponse.RawServerString == "" {
|
if nodeInfoResponse.RawServerString == "" {
|
||||||
return nil, fmt.Errorf("No server info in response")
|
return nil, fmt.Errorf("no server info in response")
|
||||||
}
|
}
|
||||||
//nodeInfo.RawServerString = strings.ToLower(nodeInfo.RawServerString)
|
// nodeInfo.RawServerString = strings.ToLower(nodeInfo.RawServerString)
|
||||||
serverConf := strings.Split(nodeInfoResponse.RawServerString, ";")
|
serverConf := strings.Split(nodeInfoResponse.RawServerString, ";")
|
||||||
|
|
||||||
parsedPort, err := strconv.ParseInt(serverConf[1], 10, 32)
|
parsedPort, err := strconv.ParseInt(serverConf[1], 10, 32)
|
||||||
@@ -444,7 +445,7 @@ func (c *APIClient) ParseV2rayNodeResponse(nodeInfoResponse *NodeInfoResponse) (
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
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 fialed: %s", header, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create GeneralNodeInfo
|
// Create GeneralNodeInfo
|
||||||
@@ -487,7 +488,7 @@ func (c *APIClient) ParseSSNodeResponse(nodeInfoResponse *NodeInfoResponse) (*ap
|
|||||||
userListResponse := new([]UserResponse)
|
userListResponse := new([]UserResponse)
|
||||||
|
|
||||||
if err := json.Unmarshal(response.Data, userListResponse); err != nil {
|
if err := json.Unmarshal(response.Data, userListResponse); err != nil {
|
||||||
return nil, fmt.Errorf("Unmarshal %s failed: %s", reflect.TypeOf(userListResponse), err)
|
return nil, fmt.Errorf("unmarshal %s failed: %s", reflect.TypeOf(userListResponse), err)
|
||||||
}
|
}
|
||||||
// Find the multi-user
|
// Find the multi-user
|
||||||
for _, u := range *userListResponse {
|
for _, u := range *userListResponse {
|
||||||
@@ -498,7 +499,7 @@ func (c *APIClient) ParseSSNodeResponse(nodeInfoResponse *NodeInfoResponse) (*ap
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if port == 0 || method == "" {
|
if port == 0 || method == "" {
|
||||||
return nil, fmt.Errorf("Cant find the single port multi user")
|
return nil, fmt.Errorf("cant find the single port multi user")
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.SpeedLimit > 0 {
|
if c.SpeedLimit > 0 {
|
||||||
@@ -603,7 +604,7 @@ func (c *APIClient) ParseTrojanNodeResponse(nodeInfoResponse *NodeInfoResponse)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if nodeInfoResponse.RawServerString == "" {
|
if nodeInfoResponse.RawServerString == "" {
|
||||||
return nil, fmt.Errorf("No server info in response")
|
return nil, fmt.Errorf("no server info in response")
|
||||||
}
|
}
|
||||||
if result := firstPortRe.FindStringSubmatch(nodeInfoResponse.RawServerString); len(result) > 1 {
|
if result := firstPortRe.FindStringSubmatch(nodeInfoResponse.RawServerString); len(result) > 1 {
|
||||||
outsidePort = result[1]
|
outsidePort = result[1]
|
||||||
@@ -678,7 +679,7 @@ func (c *APIClient) ParseUserListResponse(userInfoResponse *[]UserResponse) (*[]
|
|||||||
|
|
||||||
var deviceLimit, localDeviceLimit int = 0, 0
|
var deviceLimit, localDeviceLimit int = 0, 0
|
||||||
var speedlimit uint64 = 0
|
var speedlimit uint64 = 0
|
||||||
userList := []api.UserInfo{}
|
var userList []api.UserInfo
|
||||||
for _, user := range *userInfoResponse {
|
for _, user := range *userInfoResponse {
|
||||||
if c.DeviceLimit > 0 {
|
if c.DeviceLimit > 0 {
|
||||||
deviceLimit = c.DeviceLimit
|
deviceLimit = c.DeviceLimit
|
||||||
|
@@ -83,7 +83,7 @@ func TestGetUserList(t *testing.T) {
|
|||||||
func TestReportNodeStatus(t *testing.T) {
|
func TestReportNodeStatus(t *testing.T) {
|
||||||
client := CreateClient()
|
client := CreateClient()
|
||||||
nodeStatus := &api.NodeStatus{
|
nodeStatus := &api.NodeStatus{
|
||||||
1, 1, 1, 256,
|
CPU: 1, Mem: 1, Disk: 1, Uptime: 256,
|
||||||
}
|
}
|
||||||
err := client.ReportNodeStatus(nodeStatus)
|
err := client.ReportNodeStatus(nodeStatus)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -105,7 +105,7 @@ func TestReportReportNodeOnlineUsers(t *testing.T) {
|
|||||||
IP: fmt.Sprintf("1.1.1.%d", i),
|
IP: fmt.Sprintf("1.1.1.%d", i),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//client.Debug()
|
// client.Debug()
|
||||||
err = client.ReportNodeOnlineUsers(&onlineUserList)
|
err = client.ReportNodeOnlineUsers(&onlineUserList)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
@@ -126,7 +126,7 @@ func TestReportReportUserTraffic(t *testing.T) {
|
|||||||
Download: 114514,
|
Download: 114514,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//client.Debug()
|
// client.Debug()
|
||||||
err = client.ReportUserTraffic(&generalUserTraffic)
|
err = client.ReportUserTraffic(&generalUserTraffic)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
@@ -148,8 +148,8 @@ func TestReportIllegal(t *testing.T) {
|
|||||||
client := CreateClient()
|
client := CreateClient()
|
||||||
|
|
||||||
detectResult := []api.DetectResult{
|
detectResult := []api.DetectResult{
|
||||||
api.DetectResult{1, 2},
|
{1, 2},
|
||||||
api.DetectResult{1, 3},
|
{1, 3},
|
||||||
}
|
}
|
||||||
client.Debug()
|
client.Debug()
|
||||||
err := client.ReportIllegal(&detectResult)
|
err := client.ReportIllegal(&detectResult)
|
||||||
|
@@ -1,7 +1,8 @@
|
|||||||
|
// Deprecated: after 2023.6.1
|
||||||
package v2board
|
package v2board
|
||||||
|
|
||||||
type UserTraffic struct {
|
type UserTraffic struct {
|
||||||
UID int `json:"user_id"`
|
UID int `json:"user_id"`
|
||||||
Upload int64 `json:"u"`
|
Upload int64 `json:"u"`
|
||||||
Download int64 `json:"d"`
|
Download int64 `json:"d"`
|
||||||
}
|
}
|
||||||
|
@@ -12,9 +12,10 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/XrayR-project/XrayR/api"
|
|
||||||
"github.com/bitly/go-simplejson"
|
"github.com/bitly/go-simplejson"
|
||||||
"github.com/go-resty/resty/v2"
|
"github.com/go-resty/resty/v2"
|
||||||
|
|
||||||
|
"github.com/XrayR-project/XrayR/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
// APIClient create an api client to the panel.
|
// APIClient create an api client to the panel.
|
||||||
@@ -81,7 +82,7 @@ func readLocalRuleList(path string) (LocalRuleList []api.DetectRule) {
|
|||||||
// open the file
|
// open the file
|
||||||
file, err := os.Open(path)
|
file, err := os.Open(path)
|
||||||
|
|
||||||
//handle errors while opening
|
// handle errors while opening
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Error when opening file: %s", err)
|
log.Printf("Error when opening file: %s", err)
|
||||||
return LocalRuleList
|
return LocalRuleList
|
||||||
@@ -99,7 +100,7 @@ func readLocalRuleList(path string) (LocalRuleList []api.DetectRule) {
|
|||||||
// handle first encountered error while reading
|
// handle first encountered error while reading
|
||||||
if err := fileScanner.Err(); err != nil {
|
if err := fileScanner.Err(); err != nil {
|
||||||
log.Fatalf("Error while reading file: %s", err)
|
log.Fatalf("Error while reading file: %s", err)
|
||||||
return make([]api.DetectRule, 0)
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
file.Close()
|
file.Close()
|
||||||
@@ -133,7 +134,7 @@ func (c *APIClient) parseResponse(res *resty.Response, path string, err error) (
|
|||||||
}
|
}
|
||||||
rtn, err := simplejson.NewJson(res.Body())
|
rtn, err := simplejson.NewJson(res.Body())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Ret %s invalid", res.String())
|
return nil, fmt.Errorf("ret %s invalid", res.String())
|
||||||
}
|
}
|
||||||
return rtn, nil
|
return rtn, nil
|
||||||
}
|
}
|
||||||
@@ -294,7 +295,7 @@ func (c *APIClient) ReportNodeStatus(nodeStatus *api.NodeStatus) (err error) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//ReportNodeOnlineUsers implements the API interface
|
// ReportNodeOnlineUsers implements the API interface
|
||||||
func (c *APIClient) ReportNodeOnlineUsers(onlineUserList *[]api.OnlineUser) error {
|
func (c *APIClient) ReportNodeOnlineUsers(onlineUserList *[]api.OnlineUser) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -371,7 +372,7 @@ func (c *APIClient) ParseV2rayNodeResponse(nodeInfoResponse *simplejson.Json) (*
|
|||||||
marshalByte, _ := json.Marshal(tmpInboundInfo[0].(map[string]interface{}))
|
marshalByte, _ := json.Marshal(tmpInboundInfo[0].(map[string]interface{}))
|
||||||
inboundInfo, _ = simplejson.NewJson(marshalByte)
|
inboundInfo, _ = simplejson.NewJson(marshalByte)
|
||||||
} else {
|
} else {
|
||||||
return nil, fmt.Errorf("Unable to find inbound(s) in the nodeInfo.")
|
return nil, fmt.Errorf("unable to find inbound(s) in the nodeInfo")
|
||||||
}
|
}
|
||||||
|
|
||||||
port := uint32(inboundInfo.Get("port").MustUint64())
|
port := uint32(inboundInfo.Get("port").MustUint64())
|
||||||
|
@@ -82,7 +82,7 @@ func TestReportReportUserTraffic(t *testing.T) {
|
|||||||
Download: 114514,
|
Download: 114514,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//client.Debug()
|
// client.Debug()
|
||||||
err = client.ReportUserTraffic(&generalUserTraffic)
|
err = client.ReportUserTraffic(&generalUserTraffic)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
|
@@ -12,9 +12,10 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/XrayR-project/XrayR/api"
|
|
||||||
"github.com/bitly/go-simplejson"
|
"github.com/bitly/go-simplejson"
|
||||||
"github.com/go-resty/resty/v2"
|
"github.com/go-resty/resty/v2"
|
||||||
|
|
||||||
|
"github.com/XrayR-project/XrayR/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
// APIClient create an api client to the panel.
|
// APIClient create an api client to the panel.
|
||||||
@@ -80,7 +81,7 @@ func readLocalRuleList(path string) (LocalRuleList []api.DetectRule) {
|
|||||||
// open the file
|
// open the file
|
||||||
file, err := os.Open(path)
|
file, err := os.Open(path)
|
||||||
|
|
||||||
//handle errors while opening
|
// handle errors while opening
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Error when opening file: %s", err)
|
log.Printf("Error when opening file: %s", err)
|
||||||
return LocalRuleList
|
return LocalRuleList
|
||||||
@@ -98,7 +99,7 @@ func readLocalRuleList(path string) (LocalRuleList []api.DetectRule) {
|
|||||||
// handle first encountered error while reading
|
// handle first encountered error while reading
|
||||||
if err := fileScanner.Err(); err != nil {
|
if err := fileScanner.Err(); err != nil {
|
||||||
log.Fatalf("Error while reading file: %s", err)
|
log.Fatalf("Error while reading file: %s", err)
|
||||||
return make([]api.DetectRule, 0)
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
file.Close()
|
file.Close()
|
||||||
@@ -132,7 +133,7 @@ func (c *APIClient) parseResponse(res *resty.Response, path string, err error) (
|
|||||||
}
|
}
|
||||||
rtn, err := simplejson.NewJson(res.Body())
|
rtn, err := simplejson.NewJson(res.Body())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Ret %s invalid", res.String())
|
return nil, fmt.Errorf("ret %s invalid", res.String())
|
||||||
}
|
}
|
||||||
return rtn, nil
|
return rtn, nil
|
||||||
}
|
}
|
||||||
@@ -287,7 +288,7 @@ func (c *APIClient) ReportNodeStatus(nodeStatus *api.NodeStatus) (err error) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//ReportNodeOnlineUsers implements the API interface
|
// ReportNodeOnlineUsers implements the API interface
|
||||||
func (c *APIClient) ReportNodeOnlineUsers(onlineUserList *[]api.OnlineUser) error {
|
func (c *APIClient) ReportNodeOnlineUsers(onlineUserList *[]api.OnlineUser) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@@ -83,7 +83,7 @@ func TestReportReportUserTraffic(t *testing.T) {
|
|||||||
Download: 114514,
|
Download: 114514,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//client.Debug()
|
// client.Debug()
|
||||||
err = client.ReportUserTraffic(&generalUserTraffic)
|
err = client.ReportUserTraffic(&generalUserTraffic)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
|
@@ -9,8 +9,6 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/XrayR-project/XrayR/common/limiter"
|
|
||||||
"github.com/XrayR-project/XrayR/common/rule"
|
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/buf"
|
"github.com/xtls/xray-core/common/buf"
|
||||||
"github.com/xtls/xray-core/common/log"
|
"github.com/xtls/xray-core/common/log"
|
||||||
@@ -22,10 +20,13 @@ import (
|
|||||||
"github.com/xtls/xray-core/features/outbound"
|
"github.com/xtls/xray-core/features/outbound"
|
||||||
"github.com/xtls/xray-core/features/policy"
|
"github.com/xtls/xray-core/features/policy"
|
||||||
"github.com/xtls/xray-core/features/routing"
|
"github.com/xtls/xray-core/features/routing"
|
||||||
routing_session "github.com/xtls/xray-core/features/routing/session"
|
routingSession "github.com/xtls/xray-core/features/routing/session"
|
||||||
"github.com/xtls/xray-core/features/stats"
|
"github.com/xtls/xray-core/features/stats"
|
||||||
"github.com/xtls/xray-core/transport"
|
"github.com/xtls/xray-core/transport"
|
||||||
"github.com/xtls/xray-core/transport/pipe"
|
"github.com/xtls/xray-core/transport/pipe"
|
||||||
|
|
||||||
|
"github.com/XrayR-project/XrayR/common/limiter"
|
||||||
|
"github.com/XrayR-project/XrayR/common/rule"
|
||||||
)
|
)
|
||||||
|
|
||||||
var errSniffingTimeout = newError("timeout on sniffing")
|
var errSniffingTimeout = newError("timeout on sniffing")
|
||||||
@@ -98,7 +99,7 @@ type DefaultDispatcher struct {
|
|||||||
dns dns.Client
|
dns dns.Client
|
||||||
fdns dns.FakeDNSEngine
|
fdns dns.FakeDNSEngine
|
||||||
Limiter *limiter.Limiter
|
Limiter *limiter.Limiter
|
||||||
RuleManager *rule.RuleManager
|
RuleManager *rule.Manager
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@@ -139,7 +140,9 @@ func (*DefaultDispatcher) Start() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Close implements common.Closable.
|
// Close implements common.Closable.
|
||||||
func (*DefaultDispatcher) Close() error { return nil }
|
func (*DefaultDispatcher) Close() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (d *DefaultDispatcher) getLink(ctx context.Context, network net.Network, sniffing session.SniffingRequest) (*transport.Link, *transport.Link, error) {
|
func (d *DefaultDispatcher) getLink(ctx context.Context, network net.Network, sniffing session.SniffingRequest) (*transport.Link, *transport.Link, error) {
|
||||||
downOpt := pipe.OptionsFromContext(ctx)
|
downOpt := pipe.OptionsFromContext(ctx)
|
||||||
@@ -172,7 +175,7 @@ func (d *DefaultDispatcher) getLink(ctx context.Context, network net.Network, sn
|
|||||||
newError("[fakedns client] create a new map").WriteToLog(session.ExportIDToError(ctx))
|
newError("[fakedns client] create a new map").WriteToLog(session.ExportIDToError(ctx))
|
||||||
}
|
}
|
||||||
domain := addr.Domain()
|
domain := addr.Domain()
|
||||||
ips, err := d.dns.LookupIP(domain, dns.IPOption{true, true, false})
|
ips, err := d.dns.LookupIP(domain, dns.IPOption{IPv4Enable: true, IPv6Enable: true})
|
||||||
if err == nil {
|
if err == nil {
|
||||||
for _, ip := range ips {
|
for _, ip := range ips {
|
||||||
ip2domain.Store(ip.String(), domain)
|
ip2domain.Store(ip.String(), domain)
|
||||||
@@ -233,7 +236,7 @@ func (d *DefaultDispatcher) getLink(ctx context.Context, network net.Network, sn
|
|||||||
// Speed Limit and Device Limit
|
// Speed Limit and Device Limit
|
||||||
bucket, ok, reject := d.Limiter.GetUserBucket(sessionInbound.Tag, user.Email, sessionInbound.Source.Address.IP().String())
|
bucket, ok, reject := d.Limiter.GetUserBucket(sessionInbound.Tag, user.Email, sessionInbound.Source.Address.IP().String())
|
||||||
if reject {
|
if reject {
|
||||||
newError("Devices reach the limit: ", user.Email).AtError().WriteToLog()
|
newError("Devices reach the limit: ", user.Email).AtWarning().WriteToLog()
|
||||||
common.Close(outboundLink.Writer)
|
common.Close(outboundLink.Writer)
|
||||||
common.Close(inboundLink.Writer)
|
common.Close(inboundLink.Writer)
|
||||||
common.Interrupt(outboundLink.Reader)
|
common.Interrupt(outboundLink.Reader)
|
||||||
@@ -314,13 +317,13 @@ func (d *DefaultDispatcher) Dispatch(ctx context.Context, destination net.Destin
|
|||||||
}
|
}
|
||||||
|
|
||||||
sniffingRequest := content.SniffingRequest
|
sniffingRequest := content.SniffingRequest
|
||||||
inbound, outbound, err := d.getLink(ctx, destination.Network, sniffingRequest)
|
in, out, err := d.getLink(ctx, destination.Network, sniffingRequest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
switch {
|
switch {
|
||||||
case !sniffingRequest.Enabled:
|
case !sniffingRequest.Enabled:
|
||||||
go d.routedDispatch(ctx, outbound, destination)
|
go d.routedDispatch(ctx, out, destination)
|
||||||
case destination.Network != net.Network_TCP:
|
case destination.Network != net.Network_TCP:
|
||||||
// Only metadata sniff will be used for non tcp connection
|
// Only metadata sniff will be used for non tcp connection
|
||||||
result, err := sniffer(ctx, nil, true)
|
result, err := sniffer(ctx, nil, true)
|
||||||
@@ -337,13 +340,13 @@ func (d *DefaultDispatcher) Dispatch(ctx context.Context, destination net.Destin
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
go d.routedDispatch(ctx, outbound, destination)
|
go d.routedDispatch(ctx, out, destination)
|
||||||
default:
|
default:
|
||||||
go func() {
|
go func() {
|
||||||
cReader := &cachedReader{
|
cReader := &cachedReader{
|
||||||
reader: outbound.Reader.(*pipe.Reader),
|
reader: out.Reader.(*pipe.Reader),
|
||||||
}
|
}
|
||||||
outbound.Reader = cReader
|
out.Reader = cReader
|
||||||
result, err := sniffer(ctx, cReader, sniffingRequest.MetadataOnly)
|
result, err := sniffer(ctx, cReader, sniffingRequest.MetadataOnly)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
content.Protocol = result.Protocol()
|
content.Protocol = result.Protocol()
|
||||||
@@ -358,10 +361,10 @@ func (d *DefaultDispatcher) Dispatch(ctx context.Context, destination net.Destin
|
|||||||
ob.Target = destination
|
ob.Target = destination
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
d.routedDispatch(ctx, outbound, destination)
|
d.routedDispatch(ctx, out, destination)
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
return inbound, nil
|
return in, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DispatchLink implements routing.Dispatcher.
|
// DispatchLink implements routing.Dispatcher.
|
||||||
@@ -501,7 +504,7 @@ func (d *DefaultDispatcher) routedDispatch(ctx context.Context, link *transport.
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
routingLink := routing_session.AsRoutingContext(ctx)
|
routingLink := routingSession.AsRoutingContext(ctx)
|
||||||
inTag := routingLink.GetInboundTag()
|
inTag := routingLink.GetInboundTag()
|
||||||
isPickRoute := 0
|
isPickRoute := 0
|
||||||
if forcedOutboundTag := session.GetForcedOutboundTagFromContext(ctx); forcedOutboundTag != "" {
|
if forcedOutboundTag := session.GetForcedOutboundTagFromContext(ctx); forcedOutboundTag != "" {
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
// Package dispather implement the rate limiter and the onlie device counter
|
// Package mydispatcher Package dispatcher implement the rate limiter and the online device counter
|
||||||
package mydispatcher
|
package mydispatcher
|
||||||
|
|
||||||
//go:generate go run github.com/xtls/xray-core/common/errors/errorgen
|
//go:generate go run github.com/xtls/xray-core/common/errors/errorgen
|
||||||
|
@@ -2,8 +2,6 @@ package mydispatcher
|
|||||||
|
|
||||||
import "github.com/xtls/xray-core/common/errors"
|
import "github.com/xtls/xray-core/common/errors"
|
||||||
|
|
||||||
type errPathObjHolder struct{}
|
|
||||||
|
|
||||||
func newError(values ...interface{}) *errors.Error {
|
func newError(values ...interface{}) *errors.Error {
|
||||||
return errors.New(values...).WithPathObj(errPathObjHolder{})
|
return errors.New(values...)
|
||||||
}
|
}
|
||||||
|
@@ -1,14 +0,0 @@
|
|||||||
package cmd
|
|
||||||
|
|
||||||
import "github.com/urfave/cli"
|
|
||||||
|
|
||||||
// CreateCommands Creates all CLI commands.
|
|
||||||
func CreateCommands() []cli.Command {
|
|
||||||
return []cli.Command{
|
|
||||||
createRun(),
|
|
||||||
createRevoke(),
|
|
||||||
createRenew(),
|
|
||||||
createDNSHelp(),
|
|
||||||
createList(),
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,23 +0,0 @@
|
|||||||
package cmd
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/XrayR-project/XrayR/common/legocmd/log"
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Before(ctx *cli.Context) error {
|
|
||||||
if ctx.GlobalString("path") == "" {
|
|
||||||
log.Panic("Could not determine current working directory. Please pass --path.")
|
|
||||||
}
|
|
||||||
|
|
||||||
err := createNonExistingFolder(ctx.GlobalString("path"))
|
|
||||||
if err != nil {
|
|
||||||
log.Panicf("Could not check/create path: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if ctx.GlobalString("server") == "" {
|
|
||||||
log.Panic("Could not determine current working server. Please pass --server.")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
@@ -1,73 +0,0 @@
|
|||||||
package cmd
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
"text/tabwriter"
|
|
||||||
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
func createDNSHelp() cli.Command {
|
|
||||||
return cli.Command{
|
|
||||||
Name: "dnshelp",
|
|
||||||
Usage: "Shows additional help for the '--dns' global option",
|
|
||||||
Action: dnsHelp,
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "code, c",
|
|
||||||
Usage: fmt.Sprintf("DNS code: %s", allDNSCodes()),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func dnsHelp(ctx *cli.Context) error {
|
|
||||||
code := ctx.String("code")
|
|
||||||
if code == "" {
|
|
||||||
w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
|
|
||||||
ew := &errWriter{w: w}
|
|
||||||
|
|
||||||
ew.writeln(`Credentials for DNS providers must be passed through environment variables.`)
|
|
||||||
ew.writeln()
|
|
||||||
ew.writeln(`To display the documentation for a DNS providers:`)
|
|
||||||
ew.writeln()
|
|
||||||
ew.writeln("\t$ lego dnshelp -c code")
|
|
||||||
ew.writeln()
|
|
||||||
ew.writeln("All DNS codes:")
|
|
||||||
ew.writef("\t%s\n", allDNSCodes())
|
|
||||||
ew.writeln()
|
|
||||||
ew.writeln("More information: https://go-acme.github.io/lego/dns")
|
|
||||||
|
|
||||||
if ew.err != nil {
|
|
||||||
return ew.err
|
|
||||||
}
|
|
||||||
|
|
||||||
return w.Flush()
|
|
||||||
}
|
|
||||||
|
|
||||||
return displayDNSHelp(strings.ToLower(code))
|
|
||||||
}
|
|
||||||
|
|
||||||
type errWriter struct {
|
|
||||||
w io.Writer
|
|
||||||
err error
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ew *errWriter) writeln(a ...interface{}) {
|
|
||||||
if ew.err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
_, ew.err = fmt.Fprintln(ew.w, a...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ew *errWriter) writef(format string, a ...interface{}) {
|
|
||||||
if ew.err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
_, ew.err = fmt.Fprintf(ew.w, format, a...)
|
|
||||||
}
|
|
@@ -1,136 +0,0 @@
|
|||||||
package cmd
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"net/url"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/go-acme/lego/v4/certcrypto"
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
func createList() cli.Command {
|
|
||||||
return cli.Command{
|
|
||||||
Name: "list",
|
|
||||||
Usage: "Display certificates and accounts information.",
|
|
||||||
Action: list,
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "accounts, a",
|
|
||||||
Usage: "Display accounts.",
|
|
||||||
},
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "names, n",
|
|
||||||
Usage: "Display certificate common names only.",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func list(ctx *cli.Context) error {
|
|
||||||
if ctx.Bool("accounts") && !ctx.Bool("names") {
|
|
||||||
if err := listAccount(ctx); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return listCertificates(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
func listCertificates(ctx *cli.Context) error {
|
|
||||||
certsStorage := NewCertificatesStorage(ctx)
|
|
||||||
|
|
||||||
matches, err := filepath.Glob(filepath.Join(certsStorage.GetRootPath(), "*.crt"))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
names := ctx.Bool("names")
|
|
||||||
|
|
||||||
if len(matches) == 0 {
|
|
||||||
if !names {
|
|
||||||
fmt.Println("No certificates found.")
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if !names {
|
|
||||||
fmt.Println("Found the following certs:")
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, filename := range matches {
|
|
||||||
if strings.HasSuffix(filename, ".issuer.crt") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
data, err := ioutil.ReadFile(filename)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
pCert, err := certcrypto.ParsePEMCertificate(data)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if names {
|
|
||||||
fmt.Println(pCert.Subject.CommonName)
|
|
||||||
} else {
|
|
||||||
fmt.Println(" Certificate Name:", pCert.Subject.CommonName)
|
|
||||||
fmt.Println(" Domains:", strings.Join(pCert.DNSNames, ", "))
|
|
||||||
fmt.Println(" Expiry Date:", pCert.NotAfter)
|
|
||||||
fmt.Println(" Certificate Path:", filename)
|
|
||||||
fmt.Println()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func listAccount(ctx *cli.Context) error {
|
|
||||||
// fake email, needed by NewAccountsStorage
|
|
||||||
if err := ctx.GlobalSet("email", "unknown"); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
accountsStorage := NewAccountsStorage(ctx)
|
|
||||||
|
|
||||||
matches, err := filepath.Glob(filepath.Join(accountsStorage.GetRootPath(), "*", "*", "*.json"))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(matches) == 0 {
|
|
||||||
fmt.Println("No accounts found.")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println("Found the following accounts:")
|
|
||||||
for _, filename := range matches {
|
|
||||||
data, err := ioutil.ReadFile(filename)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
var account Account
|
|
||||||
err = json.Unmarshal(data, &account)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
uri, err := url.Parse(account.Registration.URI)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println(" Email:", account.Email)
|
|
||||||
fmt.Println(" Server:", uri.Host)
|
|
||||||
fmt.Println(" Path:", filepath.Dir(filename))
|
|
||||||
fmt.Println()
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
@@ -1,225 +0,0 @@
|
|||||||
package cmd
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto"
|
|
||||||
"crypto/x509"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/XrayR-project/XrayR/common/legocmd/log"
|
|
||||||
"github.com/go-acme/lego/v4/certcrypto"
|
|
||||||
"github.com/go-acme/lego/v4/certificate"
|
|
||||||
"github.com/go-acme/lego/v4/lego"
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
renewEnvAccountEmail = "LEGO_ACCOUNT_EMAIL"
|
|
||||||
renewEnvCertDomain = "LEGO_CERT_DOMAIN"
|
|
||||||
renewEnvCertPath = "LEGO_CERT_PATH"
|
|
||||||
renewEnvCertKeyPath = "LEGO_CERT_KEY_PATH"
|
|
||||||
)
|
|
||||||
|
|
||||||
func createRenew() cli.Command {
|
|
||||||
return cli.Command{
|
|
||||||
Name: "renew",
|
|
||||||
Usage: "Renew a certificate",
|
|
||||||
Action: renew,
|
|
||||||
Before: func(ctx *cli.Context) error {
|
|
||||||
// we require either domains or csr, but not both
|
|
||||||
hasDomains := len(ctx.GlobalStringSlice("domains")) > 0
|
|
||||||
hasCsr := len(ctx.GlobalString("csr")) > 0
|
|
||||||
if hasDomains && hasCsr {
|
|
||||||
log.Panic("Please specify either --domains/-d or --csr/-c, but not both")
|
|
||||||
}
|
|
||||||
if !hasDomains && !hasCsr {
|
|
||||||
log.Panic("Please specify --domains/-d (or --csr/-c if you already have a CSR)")
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
cli.IntFlag{
|
|
||||||
Name: "days",
|
|
||||||
Value: 30,
|
|
||||||
Usage: "The number of days left on a certificate to renew it.",
|
|
||||||
},
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "reuse-key",
|
|
||||||
Usage: "Used to indicate you want to reuse your current private key for the new certificate.",
|
|
||||||
},
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "no-bundle",
|
|
||||||
Usage: "Do not create a certificate bundle by adding the issuers certificate to the new certificate.",
|
|
||||||
},
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "must-staple",
|
|
||||||
Usage: "Include the OCSP must staple TLS extension in the CSR and generated certificate. Only works if the CSR is generated by lego.",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "renew-hook",
|
|
||||||
Usage: "Define a hook. The hook is executed only when the certificates are effectively renewed.",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "preferred-chain",
|
|
||||||
Usage: "If the CA offers multiple certificate chains, prefer the chain with an issuer matching this Subject Common Name. If no match, the default offered chain will be used.",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func renew(ctx *cli.Context) error {
|
|
||||||
account, client := setup(ctx, NewAccountsStorage(ctx))
|
|
||||||
setupChallenges(ctx, client)
|
|
||||||
|
|
||||||
if account.Registration == nil {
|
|
||||||
log.Panicf("Account %s is not registered. Use 'run' to register a new account.\n", account.Email)
|
|
||||||
}
|
|
||||||
|
|
||||||
certsStorage := NewCertificatesStorage(ctx)
|
|
||||||
|
|
||||||
bundle := !ctx.Bool("no-bundle")
|
|
||||||
|
|
||||||
meta := map[string]string{renewEnvAccountEmail: account.Email}
|
|
||||||
|
|
||||||
// CSR
|
|
||||||
if ctx.GlobalIsSet("csr") {
|
|
||||||
return renewForCSR(ctx, client, certsStorage, bundle, meta)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Domains
|
|
||||||
return renewForDomains(ctx, client, certsStorage, bundle, meta)
|
|
||||||
}
|
|
||||||
|
|
||||||
func renewForDomains(ctx *cli.Context, client *lego.Client, certsStorage *CertificatesStorage, bundle bool, meta map[string]string) error {
|
|
||||||
domains := ctx.GlobalStringSlice("domains")
|
|
||||||
domain := domains[0]
|
|
||||||
|
|
||||||
// load the cert resource from files.
|
|
||||||
// We store the certificate, private key and metadata in different files
|
|
||||||
// as web servers would not be able to work with a combined file.
|
|
||||||
certificates, err := certsStorage.ReadCertificate(domain, ".crt")
|
|
||||||
if err != nil {
|
|
||||||
log.Panicf("Error while loading the certificate for domain %s\n\t%v", domain, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
cert := certificates[0]
|
|
||||||
|
|
||||||
if !needRenewal(cert, domain, ctx.Int("days")) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is just meant to be informal for the user.
|
|
||||||
timeLeft := cert.NotAfter.Sub(time.Now().UTC())
|
|
||||||
log.Infof("[%s] acme: Trying renewal with %d hours remaining", domain, int(timeLeft.Hours()))
|
|
||||||
|
|
||||||
certDomains := certcrypto.ExtractDomains(cert)
|
|
||||||
|
|
||||||
var privateKey crypto.PrivateKey
|
|
||||||
if ctx.Bool("reuse-key") {
|
|
||||||
keyBytes, errR := certsStorage.ReadFile(domain, ".key")
|
|
||||||
if errR != nil {
|
|
||||||
log.Panicf("Error while loading the private key for domain %s\n\t%v", domain, errR)
|
|
||||||
}
|
|
||||||
|
|
||||||
privateKey, errR = certcrypto.ParsePEMPrivateKey(keyBytes)
|
|
||||||
if errR != nil {
|
|
||||||
return errR
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
request := certificate.ObtainRequest{
|
|
||||||
Domains: merge(certDomains, domains),
|
|
||||||
Bundle: bundle,
|
|
||||||
PrivateKey: privateKey,
|
|
||||||
MustStaple: ctx.Bool("must-staple"),
|
|
||||||
PreferredChain: ctx.String("preferred-chain"),
|
|
||||||
}
|
|
||||||
certRes, err := client.Certificate.Obtain(request)
|
|
||||||
if err != nil {
|
|
||||||
log.Panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
certsStorage.SaveResource(certRes)
|
|
||||||
|
|
||||||
meta[renewEnvCertDomain] = domain
|
|
||||||
meta[renewEnvCertPath] = certsStorage.GetFileName(domain, ".crt")
|
|
||||||
meta[renewEnvCertKeyPath] = certsStorage.GetFileName(domain, ".key")
|
|
||||||
|
|
||||||
return launchHook(ctx.String("renew-hook"), meta)
|
|
||||||
}
|
|
||||||
|
|
||||||
func renewForCSR(ctx *cli.Context, client *lego.Client, certsStorage *CertificatesStorage, bundle bool, meta map[string]string) error {
|
|
||||||
csr, err := readCSRFile(ctx.GlobalString("csr"))
|
|
||||||
if err != nil {
|
|
||||||
log.Panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
domain := csr.Subject.CommonName
|
|
||||||
|
|
||||||
// load the cert resource from files.
|
|
||||||
// We store the certificate, private key and metadata in different files
|
|
||||||
// as web servers would not be able to work with a combined file.
|
|
||||||
certificates, err := certsStorage.ReadCertificate(domain, ".crt")
|
|
||||||
if err != nil {
|
|
||||||
log.Panicf("Error while loading the certificate for domain %s\n\t%v", domain, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
cert := certificates[0]
|
|
||||||
|
|
||||||
if !needRenewal(cert, domain, ctx.Int("days")) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is just meant to be informal for the user.
|
|
||||||
timeLeft := cert.NotAfter.Sub(time.Now().UTC())
|
|
||||||
log.Infof("[%s] acme: Trying renewal with %d hours remaining", domain, int(timeLeft.Hours()))
|
|
||||||
|
|
||||||
certRes, err := client.Certificate.ObtainForCSR(certificate.ObtainForCSRRequest{
|
|
||||||
CSR: csr,
|
|
||||||
Bundle: bundle,
|
|
||||||
PreferredChain: ctx.String("preferred-chain"),
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
log.Panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
certsStorage.SaveResource(certRes)
|
|
||||||
|
|
||||||
meta[renewEnvCertDomain] = domain
|
|
||||||
meta[renewEnvCertPath] = certsStorage.GetFileName(domain, ".crt")
|
|
||||||
meta[renewEnvCertKeyPath] = certsStorage.GetFileName(domain, ".key")
|
|
||||||
|
|
||||||
return launchHook(ctx.String("renew-hook"), meta)
|
|
||||||
}
|
|
||||||
|
|
||||||
func needRenewal(x509Cert *x509.Certificate, domain string, days int) bool {
|
|
||||||
if x509Cert.IsCA {
|
|
||||||
log.Panicf("[%s] Certificate bundle starts with a CA certificate", domain)
|
|
||||||
}
|
|
||||||
|
|
||||||
if days >= 0 {
|
|
||||||
notAfter := int(time.Until(x509Cert.NotAfter).Hours() / 24.0)
|
|
||||||
if notAfter > days {
|
|
||||||
log.Printf("[%s] The certificate expires in %d days, the number of days defined to perform the renewal is %d: no renewal.",
|
|
||||||
domain, notAfter, days)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func merge(prevDomains, nextDomains []string) []string {
|
|
||||||
for _, next := range nextDomains {
|
|
||||||
var found bool
|
|
||||||
for _, prev := range prevDomains {
|
|
||||||
if prev == next {
|
|
||||||
found = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !found {
|
|
||||||
prevDomains = append(prevDomains, next)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return prevDomains
|
|
||||||
}
|
|
@@ -1,62 +0,0 @@
|
|||||||
package cmd
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/XrayR-project/XrayR/common/legocmd/log"
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
func createRevoke() cli.Command {
|
|
||||||
return cli.Command{
|
|
||||||
Name: "revoke",
|
|
||||||
Usage: "Revoke a certificate",
|
|
||||||
Action: revoke,
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "keep, k",
|
|
||||||
Usage: "Keep the certificates after the revocation instead of archiving them.",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func revoke(ctx *cli.Context) error {
|
|
||||||
acc, client := setup(ctx, NewAccountsStorage(ctx))
|
|
||||||
|
|
||||||
if acc.Registration == nil {
|
|
||||||
log.Panicf("Account %s is not registered. Use 'run' to register a new account.\n", acc.Email)
|
|
||||||
}
|
|
||||||
|
|
||||||
certsStorage := NewCertificatesStorage(ctx)
|
|
||||||
certsStorage.CreateRootFolder()
|
|
||||||
|
|
||||||
for _, domain := range ctx.GlobalStringSlice("domains") {
|
|
||||||
log.Printf("Trying to revoke certificate for domain %s", domain)
|
|
||||||
|
|
||||||
certBytes, err := certsStorage.ReadFile(domain, ".crt")
|
|
||||||
if err != nil {
|
|
||||||
log.Panicf("Error while revoking the certificate for domain %s\n\t%v", domain, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = client.Certificate.Revoke(certBytes)
|
|
||||||
if err != nil {
|
|
||||||
log.Panicf("Error while revoking the certificate for domain %s\n\t%v", domain, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Println("Certificate was revoked.")
|
|
||||||
|
|
||||||
if ctx.Bool("keep") {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
certsStorage.CreateArchiveFolder()
|
|
||||||
|
|
||||||
err = certsStorage.MoveToArchive(domain)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Println("Certificate was archived for domain:", domain)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
@@ -1,186 +0,0 @@
|
|||||||
package cmd
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/XrayR-project/XrayR/common/legocmd/log"
|
|
||||||
"github.com/go-acme/lego/v4/certificate"
|
|
||||||
"github.com/go-acme/lego/v4/lego"
|
|
||||||
"github.com/go-acme/lego/v4/registration"
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
func createRun() cli.Command {
|
|
||||||
return cli.Command{
|
|
||||||
Name: "run",
|
|
||||||
Usage: "Register an account, then create and install a certificate",
|
|
||||||
Before: func(ctx *cli.Context) error {
|
|
||||||
// we require either domains or csr, but not both
|
|
||||||
hasDomains := len(ctx.GlobalStringSlice("domains")) > 0
|
|
||||||
hasCsr := len(ctx.GlobalString("csr")) > 0
|
|
||||||
if hasDomains && hasCsr {
|
|
||||||
log.Panic("Please specify either --domains/-d or --csr/-c, but not both")
|
|
||||||
}
|
|
||||||
if !hasDomains && !hasCsr {
|
|
||||||
log.Panic("Please specify --domains/-d (or --csr/-c if you already have a CSR)")
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
Action: run,
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "no-bundle",
|
|
||||||
Usage: "Do not create a certificate bundle by adding the issuers certificate to the new certificate.",
|
|
||||||
},
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "must-staple",
|
|
||||||
Usage: "Include the OCSP must staple TLS extension in the CSR and generated certificate. Only works if the CSR is generated by lego.",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "run-hook",
|
|
||||||
Usage: "Define a hook. The hook is executed when the certificates are effectively created.",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "preferred-chain",
|
|
||||||
Usage: "If the CA offers multiple certificate chains, prefer the chain with an issuer matching this Subject Common Name. If no match, the default offered chain will be used.",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const rootPathWarningMessage = `!!!! HEADS UP !!!!
|
|
||||||
|
|
||||||
Your account credentials have been saved in your Let's Encrypt
|
|
||||||
configuration directory at "%s".
|
|
||||||
|
|
||||||
You should make a secure backup of this folder now. This
|
|
||||||
configuration directory will also contain certificates and
|
|
||||||
private keys obtained from Let's Encrypt so making regular
|
|
||||||
backups of this folder is ideal.
|
|
||||||
`
|
|
||||||
|
|
||||||
func run(ctx *cli.Context) error {
|
|
||||||
accountsStorage := NewAccountsStorage(ctx)
|
|
||||||
|
|
||||||
account, client := setup(ctx, accountsStorage)
|
|
||||||
setupChallenges(ctx, client)
|
|
||||||
|
|
||||||
if account.Registration == nil {
|
|
||||||
reg, err := register(ctx, client)
|
|
||||||
if err != nil {
|
|
||||||
log.Panicf("Could not complete registration\n\t%v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
account.Registration = reg
|
|
||||||
if err = accountsStorage.Save(account); err != nil {
|
|
||||||
log.Panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf(rootPathWarningMessage, accountsStorage.GetRootPath())
|
|
||||||
}
|
|
||||||
|
|
||||||
certsStorage := NewCertificatesStorage(ctx)
|
|
||||||
certsStorage.CreateRootFolder()
|
|
||||||
|
|
||||||
cert, err := obtainCertificate(ctx, client)
|
|
||||||
if err != nil {
|
|
||||||
// Make sure to return a non-zero exit code if ObtainSANCertificate returned at least one error.
|
|
||||||
// Due to us not returning partial certificate we can just exit here instead of at the end.
|
|
||||||
log.Panicf("Could not obtain certificates:\n\t%v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
certsStorage.SaveResource(cert)
|
|
||||||
|
|
||||||
meta := map[string]string{
|
|
||||||
renewEnvAccountEmail: account.Email,
|
|
||||||
renewEnvCertDomain: cert.Domain,
|
|
||||||
renewEnvCertPath: certsStorage.GetFileName(cert.Domain, ".crt"),
|
|
||||||
renewEnvCertKeyPath: certsStorage.GetFileName(cert.Domain, ".key"),
|
|
||||||
}
|
|
||||||
|
|
||||||
return launchHook(ctx.String("run-hook"), meta)
|
|
||||||
}
|
|
||||||
|
|
||||||
func handleTOS(ctx *cli.Context, client *lego.Client) bool {
|
|
||||||
// Check for a global accept override
|
|
||||||
if ctx.GlobalBool("accept-tos") {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
reader := bufio.NewReader(os.Stdin)
|
|
||||||
log.Printf("Please review the TOS at %s", client.GetToSURL())
|
|
||||||
|
|
||||||
for {
|
|
||||||
fmt.Println("Do you accept the TOS? Y/n")
|
|
||||||
text, err := reader.ReadString('\n')
|
|
||||||
if err != nil {
|
|
||||||
log.Panicf("Could not read from console: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
text = strings.Trim(text, "\r\n")
|
|
||||||
switch text {
|
|
||||||
case "", "y", "Y":
|
|
||||||
return true
|
|
||||||
case "n", "N":
|
|
||||||
return false
|
|
||||||
default:
|
|
||||||
fmt.Println("Your input was invalid. Please answer with one of Y/y, n/N or by pressing enter.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func register(ctx *cli.Context, client *lego.Client) (*registration.Resource, error) {
|
|
||||||
accepted := handleTOS(ctx, client)
|
|
||||||
if !accepted {
|
|
||||||
log.Panic("You did not accept the TOS. Unable to proceed.")
|
|
||||||
}
|
|
||||||
|
|
||||||
if ctx.GlobalBool("eab") {
|
|
||||||
kid := ctx.GlobalString("kid")
|
|
||||||
hmacEncoded := ctx.GlobalString("hmac")
|
|
||||||
|
|
||||||
if kid == "" || hmacEncoded == "" {
|
|
||||||
log.Panicf("Requires arguments --kid and --hmac.")
|
|
||||||
}
|
|
||||||
|
|
||||||
return client.Registration.RegisterWithExternalAccountBinding(registration.RegisterEABOptions{
|
|
||||||
TermsOfServiceAgreed: accepted,
|
|
||||||
Kid: kid,
|
|
||||||
HmacEncoded: hmacEncoded,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return client.Registration.Register(registration.RegisterOptions{TermsOfServiceAgreed: true})
|
|
||||||
}
|
|
||||||
|
|
||||||
func obtainCertificate(ctx *cli.Context, client *lego.Client) (*certificate.Resource, error) {
|
|
||||||
bundle := !ctx.Bool("no-bundle")
|
|
||||||
|
|
||||||
domains := ctx.GlobalStringSlice("domains")
|
|
||||||
if len(domains) > 0 {
|
|
||||||
// obtain a certificate, generating a new private key
|
|
||||||
request := certificate.ObtainRequest{
|
|
||||||
Domains: domains,
|
|
||||||
Bundle: bundle,
|
|
||||||
MustStaple: ctx.Bool("must-staple"),
|
|
||||||
PreferredChain: ctx.String("preferred-chain"),
|
|
||||||
}
|
|
||||||
return client.Certificate.Obtain(request)
|
|
||||||
}
|
|
||||||
|
|
||||||
// read the CSR
|
|
||||||
csr, err := readCSRFile(ctx.GlobalString("csr"))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// obtain a certificate for this CSR
|
|
||||||
return client.Certificate.ObtainForCSR(certificate.ObtainForCSRRequest{
|
|
||||||
CSR: csr,
|
|
||||||
Bundle: bundle,
|
|
||||||
PreferredChain: ctx.String("preferred-chain"),
|
|
||||||
})
|
|
||||||
}
|
|
@@ -1,120 +0,0 @@
|
|||||||
package cmd
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/go-acme/lego/v4/lego"
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
func CreateFlags(defaultPath string) []cli.Flag {
|
|
||||||
return []cli.Flag{
|
|
||||||
cli.StringSliceFlag{
|
|
||||||
Name: "domains, d",
|
|
||||||
Usage: "Add a domain to the process. Can be specified multiple times.",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "server, s",
|
|
||||||
Usage: "CA hostname (and optionally :port). The server certificate must be trusted in order to avoid further modifications to the client.",
|
|
||||||
Value: lego.LEDirectoryProduction,
|
|
||||||
},
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "accept-tos, a",
|
|
||||||
Usage: "By setting this flag to true you indicate that you accept the current Let's Encrypt terms of service.",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "email, m",
|
|
||||||
Usage: "Email used for registration and recovery contact.",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "csr, c",
|
|
||||||
Usage: "Certificate signing request filename, if an external CSR is to be used.",
|
|
||||||
},
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "eab",
|
|
||||||
Usage: "Use External Account Binding for account registration. Requires --kid and --hmac.",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "kid",
|
|
||||||
Usage: "Key identifier from External CA. Used for External Account Binding.",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "hmac",
|
|
||||||
Usage: "MAC key from External CA. Should be in Base64 URL Encoding without padding format. Used for External Account Binding.",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "key-type, k",
|
|
||||||
Value: "ec256",
|
|
||||||
Usage: "Key type to use for private keys. Supported: rsa2048, rsa4096, rsa8192, ec256, ec384.",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "filename",
|
|
||||||
Usage: "(deprecated) Filename of the generated certificate.",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "path",
|
|
||||||
EnvVar: "LEGO_PATH",
|
|
||||||
Usage: "Directory to use for storing the data.",
|
|
||||||
Value: defaultPath,
|
|
||||||
},
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "http",
|
|
||||||
Usage: "Use the HTTP challenge to solve challenges. Can be mixed with other types of challenges.",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "http.port",
|
|
||||||
Usage: "Set the port and interface to use for HTTP based challenges to listen on.Supported: interface:port or :port.",
|
|
||||||
Value: ":80",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "http.proxy-header",
|
|
||||||
Usage: "Validate against this HTTP header when solving HTTP based challenges behind a reverse proxy.",
|
|
||||||
Value: "Host",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "http.webroot",
|
|
||||||
Usage: "Set the webroot folder to use for HTTP based challenges to write directly in a file in .well-known/acme-challenge. This disables the built-in server and expects the given directory to be publicly served with access to .well-known/acme-challenge",
|
|
||||||
},
|
|
||||||
cli.StringSliceFlag{
|
|
||||||
Name: "http.memcached-host",
|
|
||||||
Usage: "Set the memcached host(s) to use for HTTP based challenges. Challenges will be written to all specified hosts.",
|
|
||||||
},
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "tls",
|
|
||||||
Usage: "Use the TLS challenge to solve challenges. Can be mixed with other types of challenges.",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "tls.port",
|
|
||||||
Usage: "Set the port and interface to use for TLS based challenges to listen on. Supported: interface:port or :port.",
|
|
||||||
Value: ":443",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "dns",
|
|
||||||
Usage: "Solve a DNS challenge using the specified provider. Can be mixed with other types of challenges. Run 'lego dnshelp' for help on usage.",
|
|
||||||
},
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "dns.disable-cp",
|
|
||||||
Usage: "By setting this flag to true, disables the need to wait the propagation of the TXT record to all authoritative name servers.",
|
|
||||||
},
|
|
||||||
cli.StringSliceFlag{
|
|
||||||
Name: "dns.resolvers",
|
|
||||||
Usage: "Set the resolvers to use for performing recursive DNS queries. Supported: host:port. The default is to use the system resolvers, or Google's DNS resolvers if the system's cannot be determined.",
|
|
||||||
},
|
|
||||||
cli.IntFlag{
|
|
||||||
Name: "http-timeout",
|
|
||||||
Usage: "Set the HTTP timeout value to a specific value in seconds.",
|
|
||||||
},
|
|
||||||
cli.IntFlag{
|
|
||||||
Name: "dns-timeout",
|
|
||||||
Usage: "Set the DNS timeout value to a specific value in seconds. Used only when performing authoritative name servers queries.",
|
|
||||||
Value: 10,
|
|
||||||
},
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "pem",
|
|
||||||
Usage: "Generate a .pem file by concatenating the .key and .crt files together.",
|
|
||||||
},
|
|
||||||
cli.IntFlag{
|
|
||||||
Name: "cert.timeout",
|
|
||||||
Usage: "Set the certificate timeout value to a specific value in seconds. Only used when obtaining certificates.",
|
|
||||||
Value: 30,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,47 +0,0 @@
|
|||||||
package cmd
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
func launchHook(hook string, meta map[string]string) error {
|
|
||||||
if hook == "" {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
ctxCmd, cancel := context.WithTimeout(context.Background(), 120*time.Second)
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
parts := strings.Fields(hook)
|
|
||||||
|
|
||||||
cmdCtx := exec.CommandContext(ctxCmd, parts[0], parts[1:]...)
|
|
||||||
cmdCtx.Env = append(os.Environ(), metaToEnv(meta)...)
|
|
||||||
|
|
||||||
output, err := cmdCtx.CombinedOutput()
|
|
||||||
|
|
||||||
if len(output) > 0 {
|
|
||||||
fmt.Println(string(output))
|
|
||||||
}
|
|
||||||
|
|
||||||
if errors.Is(ctxCmd.Err(), context.DeadlineExceeded) {
|
|
||||||
return errors.New("hook timed out")
|
|
||||||
}
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func metaToEnv(meta map[string]string) []string {
|
|
||||||
var envs []string
|
|
||||||
|
|
||||||
for k, v := range meta {
|
|
||||||
envs = append(envs, k+"="+v)
|
|
||||||
}
|
|
||||||
|
|
||||||
return envs
|
|
||||||
}
|
|
@@ -1,129 +0,0 @@
|
|||||||
package cmd
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/x509"
|
|
||||||
"encoding/pem"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/XrayR-project/XrayR/common/legocmd/log"
|
|
||||||
"github.com/go-acme/lego/v4/certcrypto"
|
|
||||||
"github.com/go-acme/lego/v4/lego"
|
|
||||||
"github.com/go-acme/lego/v4/registration"
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
const filePerm os.FileMode = 0o600
|
|
||||||
|
|
||||||
func setup(ctx *cli.Context, accountsStorage *AccountsStorage) (*Account, *lego.Client) {
|
|
||||||
keyType := getKeyType(ctx)
|
|
||||||
privateKey := accountsStorage.GetPrivateKey(keyType)
|
|
||||||
|
|
||||||
var account *Account
|
|
||||||
if accountsStorage.ExistsAccountFilePath() {
|
|
||||||
account = accountsStorage.LoadAccount(privateKey)
|
|
||||||
} else {
|
|
||||||
account = &Account{Email: accountsStorage.GetUserID(), key: privateKey}
|
|
||||||
}
|
|
||||||
|
|
||||||
client := newClient(ctx, account, keyType)
|
|
||||||
|
|
||||||
return account, client
|
|
||||||
}
|
|
||||||
|
|
||||||
func newClient(ctx *cli.Context, acc registration.User, keyType certcrypto.KeyType) *lego.Client {
|
|
||||||
config := lego.NewConfig(acc)
|
|
||||||
config.CADirURL = ctx.GlobalString("server")
|
|
||||||
|
|
||||||
config.Certificate = lego.CertificateConfig{
|
|
||||||
KeyType: keyType,
|
|
||||||
Timeout: time.Duration(ctx.GlobalInt("cert.timeout")) * time.Second,
|
|
||||||
}
|
|
||||||
config.UserAgent = fmt.Sprintf("lego-cli/%s", ctx.App.Version)
|
|
||||||
|
|
||||||
if ctx.GlobalIsSet("http-timeout") {
|
|
||||||
config.HTTPClient.Timeout = time.Duration(ctx.GlobalInt("http-timeout")) * time.Second
|
|
||||||
}
|
|
||||||
|
|
||||||
client, err := lego.NewClient(config)
|
|
||||||
if err != nil {
|
|
||||||
log.Panicf("Could not create client: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if client.GetExternalAccountRequired() && !ctx.GlobalIsSet("eab") {
|
|
||||||
log.Panic("Server requires External Account Binding. Use --eab with --kid and --hmac.")
|
|
||||||
}
|
|
||||||
|
|
||||||
return client
|
|
||||||
}
|
|
||||||
|
|
||||||
// getKeyType the type from which private keys should be generated.
|
|
||||||
func getKeyType(ctx *cli.Context) certcrypto.KeyType {
|
|
||||||
keyType := ctx.GlobalString("key-type")
|
|
||||||
switch strings.ToUpper(keyType) {
|
|
||||||
case "RSA2048":
|
|
||||||
return certcrypto.RSA2048
|
|
||||||
case "RSA4096":
|
|
||||||
return certcrypto.RSA4096
|
|
||||||
case "RSA8192":
|
|
||||||
return certcrypto.RSA8192
|
|
||||||
case "EC256":
|
|
||||||
return certcrypto.EC256
|
|
||||||
case "EC384":
|
|
||||||
return certcrypto.EC384
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Panicf("Unsupported KeyType: %s", keyType)
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func getEmail(ctx *cli.Context) string {
|
|
||||||
email := ctx.GlobalString("email")
|
|
||||||
if email == "" {
|
|
||||||
log.Panic("You have to pass an account (email address) to the program using --email or -m")
|
|
||||||
}
|
|
||||||
return email
|
|
||||||
}
|
|
||||||
|
|
||||||
func createNonExistingFolder(path string) error {
|
|
||||||
if _, err := os.Stat(path); os.IsNotExist(err) {
|
|
||||||
return os.MkdirAll(path, 0o700)
|
|
||||||
} else if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func readCSRFile(filename string) (*x509.CertificateRequest, error) {
|
|
||||||
bytes, err := ioutil.ReadFile(filename)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
raw := bytes
|
|
||||||
|
|
||||||
// see if we can find a PEM-encoded CSR
|
|
||||||
var p *pem.Block
|
|
||||||
rest := bytes
|
|
||||||
for {
|
|
||||||
// decode a PEM block
|
|
||||||
p, rest = pem.Decode(rest)
|
|
||||||
|
|
||||||
// did we fail?
|
|
||||||
if p == nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
// did we get a CSR?
|
|
||||||
if p.Type == "CERTIFICATE REQUEST" {
|
|
||||||
raw = p.Bytes
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// no PEM-encoded CSR
|
|
||||||
// assume we were given a DER-encoded ASN.1 CSR
|
|
||||||
// (if this assumption is wrong, parsing these bytes will fail)
|
|
||||||
return x509.ParseCertificateRequest(raw)
|
|
||||||
}
|
|
@@ -1,126 +0,0 @@
|
|||||||
package cmd
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/XrayR-project/XrayR/common/legocmd/log"
|
|
||||||
"github.com/go-acme/lego/v4/challenge"
|
|
||||||
"github.com/go-acme/lego/v4/challenge/dns01"
|
|
||||||
"github.com/go-acme/lego/v4/challenge/http01"
|
|
||||||
"github.com/go-acme/lego/v4/challenge/tlsalpn01"
|
|
||||||
"github.com/go-acme/lego/v4/lego"
|
|
||||||
"github.com/go-acme/lego/v4/providers/dns"
|
|
||||||
"github.com/go-acme/lego/v4/providers/http/memcached"
|
|
||||||
"github.com/go-acme/lego/v4/providers/http/webroot"
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
func setupChallenges(ctx *cli.Context, client *lego.Client) {
|
|
||||||
if !ctx.GlobalBool("http") && !ctx.GlobalBool("tls") && !ctx.GlobalIsSet("dns") {
|
|
||||||
log.Panic("No challenge selected. You must specify at least one challenge: `--http`, `--tls`, `--dns`.")
|
|
||||||
}
|
|
||||||
|
|
||||||
if ctx.GlobalBool("http") {
|
|
||||||
err := client.Challenge.SetHTTP01Provider(setupHTTPProvider(ctx))
|
|
||||||
if err != nil {
|
|
||||||
log.Panic(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ctx.GlobalBool("tls") {
|
|
||||||
err := client.Challenge.SetTLSALPN01Provider(setupTLSProvider(ctx))
|
|
||||||
if err != nil {
|
|
||||||
log.Panic(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ctx.GlobalIsSet("dns") {
|
|
||||||
setupDNS(ctx, client)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func setupHTTPProvider(ctx *cli.Context) challenge.Provider {
|
|
||||||
switch {
|
|
||||||
case ctx.GlobalIsSet("http.webroot"):
|
|
||||||
ps, err := webroot.NewHTTPProvider(ctx.GlobalString("http.webroot"))
|
|
||||||
if err != nil {
|
|
||||||
log.Panic(err)
|
|
||||||
}
|
|
||||||
return ps
|
|
||||||
case ctx.GlobalIsSet("http.memcached-host"):
|
|
||||||
ps, err := memcached.NewMemcachedProvider(ctx.GlobalStringSlice("http.memcached-host"))
|
|
||||||
if err != nil {
|
|
||||||
log.Panic(err)
|
|
||||||
}
|
|
||||||
return ps
|
|
||||||
case ctx.GlobalIsSet("http.port"):
|
|
||||||
iface := ctx.GlobalString("http.port")
|
|
||||||
if !strings.Contains(iface, ":") {
|
|
||||||
log.Panicf("The --http switch only accepts interface:port or :port for its argument.")
|
|
||||||
}
|
|
||||||
|
|
||||||
host, port, err := net.SplitHostPort(iface)
|
|
||||||
if err != nil {
|
|
||||||
log.Panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
srv := http01.NewProviderServer(host, port)
|
|
||||||
if header := ctx.GlobalString("http.proxy-header"); header != "" {
|
|
||||||
srv.SetProxyHeader(header)
|
|
||||||
}
|
|
||||||
return srv
|
|
||||||
case ctx.GlobalBool("http"):
|
|
||||||
srv := http01.NewProviderServer("", "")
|
|
||||||
if header := ctx.GlobalString("http.proxy-header"); header != "" {
|
|
||||||
srv.SetProxyHeader(header)
|
|
||||||
}
|
|
||||||
return srv
|
|
||||||
default:
|
|
||||||
log.Panic("Invalid HTTP challenge options.")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func setupTLSProvider(ctx *cli.Context) challenge.Provider {
|
|
||||||
switch {
|
|
||||||
case ctx.GlobalIsSet("tls.port"):
|
|
||||||
iface := ctx.GlobalString("tls.port")
|
|
||||||
if !strings.Contains(iface, ":") {
|
|
||||||
log.Panicf("The --tls switch only accepts interface:port or :port for its argument.")
|
|
||||||
}
|
|
||||||
|
|
||||||
host, port, err := net.SplitHostPort(iface)
|
|
||||||
if err != nil {
|
|
||||||
log.Panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return tlsalpn01.NewProviderServer(host, port)
|
|
||||||
case ctx.GlobalBool("tls"):
|
|
||||||
return tlsalpn01.NewProviderServer("", "")
|
|
||||||
default:
|
|
||||||
log.Panic("Invalid HTTP challenge options.")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func setupDNS(ctx *cli.Context, client *lego.Client) {
|
|
||||||
provider, err := dns.NewDNSChallengeProviderByName(ctx.GlobalString("dns"))
|
|
||||||
if err != nil {
|
|
||||||
log.Panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
servers := ctx.GlobalStringSlice("dns.resolvers")
|
|
||||||
err = client.Challenge.SetDNS01Provider(provider,
|
|
||||||
dns01.CondOption(len(servers) > 0,
|
|
||||||
dns01.AddRecursiveNameservers(dns01.ParseNameservers(ctx.GlobalStringSlice("dns.resolvers")))),
|
|
||||||
dns01.CondOption(ctx.GlobalBool("dns.disable-cp"),
|
|
||||||
dns01.DisableCompletePropagationRequirement()),
|
|
||||||
dns01.CondOption(ctx.GlobalIsSet("dns-timeout"),
|
|
||||||
dns01.AddDNSTimeout(time.Duration(ctx.GlobalInt("dns-timeout"))*time.Second)),
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
log.Panic(err)
|
|
||||||
}
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
@@ -1,189 +0,0 @@
|
|||||||
// Let's Encrypt client to go!
|
|
||||||
// CLI application for generating Let's Encrypt certificates using the ACME package.
|
|
||||||
package legocmd
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"path"
|
|
||||||
"path/filepath"
|
|
||||||
"runtime"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/XrayR-project/XrayR/common/legocmd/cmd"
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
var version = "dev"
|
|
||||||
var defaultPath string
|
|
||||||
|
|
||||||
type LegoCMD struct {
|
|
||||||
cmdClient *cli.App
|
|
||||||
}
|
|
||||||
|
|
||||||
func New() (*LegoCMD, error) {
|
|
||||||
app := cli.NewApp()
|
|
||||||
app.Name = "lego"
|
|
||||||
app.HelpName = "lego"
|
|
||||||
app.Usage = "Let's Encrypt client written in Go"
|
|
||||||
app.EnableBashCompletion = true
|
|
||||||
|
|
||||||
app.Version = version
|
|
||||||
cli.VersionPrinter = func(c *cli.Context) {
|
|
||||||
fmt.Printf("lego version %s %s/%s\n", c.App.Version, runtime.GOOS, runtime.GOARCH)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set default path to configPath/cert
|
|
||||||
var path string = ""
|
|
||||||
configPath := os.Getenv("XRAY_LOCATION_CONFIG")
|
|
||||||
if configPath != "" {
|
|
||||||
path = configPath
|
|
||||||
} else if cwd, err := os.Getwd(); err == nil {
|
|
||||||
path = cwd
|
|
||||||
} else {
|
|
||||||
path = "."
|
|
||||||
}
|
|
||||||
|
|
||||||
defaultPath = filepath.Join(path, "cert")
|
|
||||||
|
|
||||||
app.Flags = cmd.CreateFlags(defaultPath)
|
|
||||||
|
|
||||||
app.Before = cmd.Before
|
|
||||||
|
|
||||||
app.Commands = cmd.CreateCommands()
|
|
||||||
|
|
||||||
lego := &LegoCMD{
|
|
||||||
cmdClient: app,
|
|
||||||
}
|
|
||||||
|
|
||||||
return lego, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DNSCert cert a domain using DNS API
|
|
||||||
func (l *LegoCMD) DNSCert(domain, email, provider string, DNSEnv map[string]string) (CertPath string, KeyPath string, err error) {
|
|
||||||
defer func() (string, string, error) {
|
|
||||||
// Handle any error
|
|
||||||
if r := recover(); r != nil {
|
|
||||||
switch x := r.(type) {
|
|
||||||
case string:
|
|
||||||
err = errors.New(x)
|
|
||||||
case error:
|
|
||||||
err = x
|
|
||||||
default:
|
|
||||||
err = errors.New("unknow panic")
|
|
||||||
}
|
|
||||||
return "", "", err
|
|
||||||
}
|
|
||||||
return CertPath, KeyPath, nil
|
|
||||||
}()
|
|
||||||
// Set Env for DNS configuration
|
|
||||||
for key, value := range DNSEnv {
|
|
||||||
os.Setenv(strings.ToUpper(key), value)
|
|
||||||
}
|
|
||||||
// First check if the certificate exists
|
|
||||||
CertPath, KeyPath, err = checkCertfile(domain)
|
|
||||||
if err == nil {
|
|
||||||
return CertPath, KeyPath, err
|
|
||||||
}
|
|
||||||
|
|
||||||
argstring := fmt.Sprintf("lego -a -d %s -m %s --dns %s run", domain, email, provider)
|
|
||||||
err = l.cmdClient.Run(strings.Split(argstring, " "))
|
|
||||||
if err != nil {
|
|
||||||
return "", "", err
|
|
||||||
}
|
|
||||||
CertPath, KeyPath, err = checkCertfile(domain)
|
|
||||||
if err != nil {
|
|
||||||
return "", "", err
|
|
||||||
}
|
|
||||||
return CertPath, KeyPath, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// HTTPCert cert a domain using http methods
|
|
||||||
func (l *LegoCMD) HTTPCert(domain, email string) (CertPath string, KeyPath string, err error) {
|
|
||||||
defer func() (string, string, error) {
|
|
||||||
// Handle any error
|
|
||||||
if r := recover(); r != nil {
|
|
||||||
switch x := r.(type) {
|
|
||||||
case string:
|
|
||||||
err = errors.New(x)
|
|
||||||
case error:
|
|
||||||
err = x
|
|
||||||
default:
|
|
||||||
err = errors.New("unknow panic")
|
|
||||||
}
|
|
||||||
return "", "", err
|
|
||||||
}
|
|
||||||
return CertPath, KeyPath, nil
|
|
||||||
}()
|
|
||||||
// First check if the certificate exists
|
|
||||||
CertPath, KeyPath, err = checkCertfile(domain)
|
|
||||||
if err == nil {
|
|
||||||
return CertPath, KeyPath, err
|
|
||||||
}
|
|
||||||
argstring := fmt.Sprintf("lego -a -d %s -m %s --http run", domain, email)
|
|
||||||
err = l.cmdClient.Run(strings.Split(argstring, " "))
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return "", "", err
|
|
||||||
}
|
|
||||||
CertPath, KeyPath, err = checkCertfile(domain)
|
|
||||||
if err != nil {
|
|
||||||
return "", "", err
|
|
||||||
}
|
|
||||||
return CertPath, KeyPath, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
//RenewCert renew a domain cert
|
|
||||||
func (l *LegoCMD) RenewCert(domain, email, certMode, provider string, DNSEnv map[string]string) (CertPath string, KeyPath string, err error) {
|
|
||||||
var argstring string
|
|
||||||
defer func() (string, string, error) {
|
|
||||||
// Handle any error
|
|
||||||
if r := recover(); r != nil {
|
|
||||||
switch x := r.(type) {
|
|
||||||
case string:
|
|
||||||
err = errors.New(x)
|
|
||||||
case error:
|
|
||||||
err = x
|
|
||||||
default:
|
|
||||||
err = errors.New("unknow panic")
|
|
||||||
}
|
|
||||||
return "", "", err
|
|
||||||
}
|
|
||||||
return CertPath, KeyPath, nil
|
|
||||||
}()
|
|
||||||
if certMode == "http" {
|
|
||||||
argstring = fmt.Sprintf("lego -a -d %s -m %s --http renew --days 30", domain, email)
|
|
||||||
} else if certMode == "dns" {
|
|
||||||
// Set Env for DNS configuration
|
|
||||||
for key, value := range DNSEnv {
|
|
||||||
os.Setenv(key, value)
|
|
||||||
}
|
|
||||||
argstring = fmt.Sprintf("lego -a -d %s -m %s --dns %s renew --days 30", domain, email, provider)
|
|
||||||
} else {
|
|
||||||
return "", "", fmt.Errorf("Unsupport cert mode: %s", certMode)
|
|
||||||
}
|
|
||||||
err = l.cmdClient.Run(strings.Split(argstring, " "))
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return "", "", err
|
|
||||||
}
|
|
||||||
CertPath, KeyPath, err = checkCertfile(domain)
|
|
||||||
if err != nil {
|
|
||||||
return "", "", err
|
|
||||||
}
|
|
||||||
return CertPath, KeyPath, nil
|
|
||||||
}
|
|
||||||
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))
|
|
||||||
if _, err := os.Stat(keyPath); os.IsNotExist(err) {
|
|
||||||
return "", "", fmt.Errorf("Cert key failed: %s", domain)
|
|
||||||
}
|
|
||||||
if _, err := os.Stat(certPath); os.IsNotExist(err) {
|
|
||||||
return "", "", fmt.Errorf("Cert cert failed: %s", domain)
|
|
||||||
}
|
|
||||||
absKeyPath, _ := filepath.Abs(keyPath)
|
|
||||||
absCertPath, _ := filepath.Abs(certPath)
|
|
||||||
return absCertPath, absKeyPath, nil
|
|
||||||
}
|
|
@@ -1,82 +0,0 @@
|
|||||||
package legocmd_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/XrayR-project/XrayR/common/legocmd"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestLegoClient(t *testing.T) {
|
|
||||||
_, err := legocmd.New()
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestLegoDNSCert(t *testing.T) {
|
|
||||||
lego, err := legocmd.New()
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
var (
|
|
||||||
domain string = "node1.test.com"
|
|
||||||
email string = "test@gmail.com"
|
|
||||||
provider string = "alidns"
|
|
||||||
DNSEnv map[string]string
|
|
||||||
)
|
|
||||||
DNSEnv = make(map[string]string)
|
|
||||||
DNSEnv["ALICLOUD_ACCESS_KEY"] = "aaa"
|
|
||||||
DNSEnv["ALICLOUD_SECRET_KEY"] = "bbb"
|
|
||||||
certPath, keyPath, err := lego.DNSCert(domain, email, provider, DNSEnv)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
t.Log(certPath)
|
|
||||||
t.Log(keyPath)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestLegoHTTPCert(t *testing.T) {
|
|
||||||
lego, err := legocmd.New()
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
var (
|
|
||||||
domain string = "node1.test.com"
|
|
||||||
email string = "test@gmail.com"
|
|
||||||
)
|
|
||||||
certPath, keyPath, err := lego.HTTPCert(domain, email)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
t.Log(certPath)
|
|
||||||
t.Log(keyPath)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestLegoRenewCert(t *testing.T) {
|
|
||||||
lego, err := legocmd.New()
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
var (
|
|
||||||
domain string = "node1.test.com"
|
|
||||||
email string = "test@gmail.com"
|
|
||||||
provider string = "alidns"
|
|
||||||
DNSEnv map[string]string
|
|
||||||
)
|
|
||||||
DNSEnv = make(map[string]string)
|
|
||||||
DNSEnv["ALICLOUD_ACCESS_KEY"] = "aaa"
|
|
||||||
DNSEnv["ALICLOUD_SECRET_KEY"] = "bbb"
|
|
||||||
certPath, keyPath, err := lego.RenewCert(domain, email, "dns", provider, DNSEnv)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
t.Log(certPath)
|
|
||||||
t.Log(keyPath)
|
|
||||||
|
|
||||||
certPath, keyPath, err = lego.RenewCert(domain, email, "http", provider, DNSEnv)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
t.Log(certPath)
|
|
||||||
t.Log(keyPath)
|
|
||||||
}
|
|
@@ -1,60 +0,0 @@
|
|||||||
package log
|
|
||||||
|
|
||||||
import (
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Logger is an optional custom logger.
|
|
||||||
var Logger StdLogger = log.New(os.Stdout, "", log.LstdFlags)
|
|
||||||
|
|
||||||
// StdLogger interface for Standard Logger.
|
|
||||||
type StdLogger interface {
|
|
||||||
Panic(args ...interface{})
|
|
||||||
Fatalln(args ...interface{})
|
|
||||||
Panicf(format string, args ...interface{})
|
|
||||||
Print(args ...interface{})
|
|
||||||
Println(args ...interface{})
|
|
||||||
Printf(format string, args ...interface{})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Panic writes a log entry.
|
|
||||||
// It uses Logger if not nil, otherwise it uses the default log.Logger.
|
|
||||||
func Panic(args ...interface{}) {
|
|
||||||
Logger.Panic(args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Panicf writes a log entry.
|
|
||||||
// It uses Logger if not nil, otherwise it uses the default log.Logger.
|
|
||||||
func Panicf(format string, args ...interface{}) {
|
|
||||||
Logger.Panicf(format, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Print writes a log entry.
|
|
||||||
// It uses Logger if not nil, otherwise it uses the default log.Logger.
|
|
||||||
func Print(args ...interface{}) {
|
|
||||||
Logger.Print(args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Println writes a log entry.
|
|
||||||
// It uses Logger if not nil, otherwise it uses the default log.Logger.
|
|
||||||
func Println(args ...interface{}) {
|
|
||||||
Logger.Println(args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Printf writes a log entry.
|
|
||||||
// It uses Logger if not nil, otherwise it uses the default log.Logger.
|
|
||||||
func Printf(format string, args ...interface{}) {
|
|
||||||
Logger.Printf(format, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Warnf writes a log entry.
|
|
||||||
func Warnf(format string, args ...interface{}) {
|
|
||||||
Printf("[WARN] "+format, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Infof writes a log entry.
|
|
||||||
func Infof(format string, args ...interface{}) {
|
|
||||||
Printf("[INFO] "+format, args...)
|
|
||||||
}
|
|
||||||
|
|
@@ -2,8 +2,6 @@ package limiter
|
|||||||
|
|
||||||
import "github.com/xtls/xray-core/common/errors"
|
import "github.com/xtls/xray-core/common/errors"
|
||||||
|
|
||||||
type errPathObjHolder struct{}
|
|
||||||
|
|
||||||
func newError(values ...interface{}) *errors.Error {
|
func newError(values ...interface{}) *errors.Error {
|
||||||
return errors.New(values...).WithPathObj(errPathObjHolder{})
|
return errors.New(values...)
|
||||||
}
|
}
|
||||||
|
@@ -1,12 +1,24 @@
|
|||||||
// Package limiter is to control the links that go into the dispather
|
// Package limiter is to control the links that go into the dispatcher
|
||||||
package limiter
|
package limiter
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/eko/gocache/lib/v4/cache"
|
||||||
|
"github.com/eko/gocache/lib/v4/marshaler"
|
||||||
|
"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"
|
||||||
|
"golang.org/x/time/rate"
|
||||||
|
|
||||||
"github.com/XrayR-project/XrayR/api"
|
"github.com/XrayR-project/XrayR/api"
|
||||||
"golang.org/x/time/rate"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type UserInfo struct {
|
type UserInfo struct {
|
||||||
@@ -20,7 +32,11 @@ type InboundInfo struct {
|
|||||||
NodeSpeedLimit uint64
|
NodeSpeedLimit uint64
|
||||||
UserInfo *sync.Map // Key: Email value: UserInfo
|
UserInfo *sync.Map // Key: Email value: UserInfo
|
||||||
BucketHub *sync.Map // key: Email, value: *rate.Limiter
|
BucketHub *sync.Map // key: Email, value: *rate.Limiter
|
||||||
UserOnlineIP *sync.Map // Key: Email Value: *sync.Map: Key: IP, Value: UID
|
UserOnlineIP *sync.Map // Key: Email, value: {Key: IP, value: UID}
|
||||||
|
GlobalLimit struct {
|
||||||
|
config *GlobalDeviceLimitConfig
|
||||||
|
globalOnlineIP *marshaler.Marshaler
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type Limiter struct {
|
type Limiter struct {
|
||||||
@@ -33,13 +49,37 @@ func New() *Limiter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *Limiter) AddInboundLimiter(tag string, nodeSpeedLimit uint64, userList *[]api.UserInfo) error {
|
func (l *Limiter) AddInboundLimiter(tag string, nodeSpeedLimit uint64, userList *[]api.UserInfo, globalLimit *GlobalDeviceLimitConfig) error {
|
||||||
inboundInfo := &InboundInfo{
|
inboundInfo := &InboundInfo{
|
||||||
Tag: tag,
|
Tag: tag,
|
||||||
NodeSpeedLimit: nodeSpeedLimit,
|
NodeSpeedLimit: nodeSpeedLimit,
|
||||||
BucketHub: new(sync.Map),
|
BucketHub: new(sync.Map),
|
||||||
UserOnlineIP: new(sync.Map),
|
UserOnlineIP: new(sync.Map),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if globalLimit != nil && globalLimit.Enable {
|
||||||
|
inboundInfo.GlobalLimit.config = globalLimit
|
||||||
|
|
||||||
|
// init local store
|
||||||
|
gs := goCacheStore.NewGoCache(goCache.New(time.Duration(globalLimit.Expiry)*time.Second, 1*time.Minute))
|
||||||
|
|
||||||
|
// init redis store
|
||||||
|
rs := redisStore.NewRedis(redis.NewClient(
|
||||||
|
&redis.Options{
|
||||||
|
Addr: globalLimit.RedisAddr,
|
||||||
|
Password: globalLimit.RedisPassword,
|
||||||
|
DB: globalLimit.RedisDB,
|
||||||
|
}),
|
||||||
|
store.WithExpiration(time.Duration(globalLimit.Expiry)*time.Second))
|
||||||
|
|
||||||
|
// init chained cache. First use local go-cache, if go-cache is nil, then use redis cache
|
||||||
|
cacheManager := cache.NewChain[any](
|
||||||
|
cache.New[any](gs), // go-cache is priority
|
||||||
|
cache.New[any](rs),
|
||||||
|
)
|
||||||
|
inboundInfo.GlobalLimit.globalOnlineIP = marshaler.New(cacheManager)
|
||||||
|
}
|
||||||
|
|
||||||
userMap := new(sync.Map)
|
userMap := new(sync.Map)
|
||||||
for _, u := range *userList {
|
for _, u := range *userList {
|
||||||
userMap.Store(fmt.Sprintf("%s|%s|%d", tag, u.Email, u.UID), UserInfo{
|
userMap.Store(fmt.Sprintf("%s|%s|%d", tag, u.Email, u.UID), UserInfo{
|
||||||
@@ -54,7 +94,6 @@ func (l *Limiter) AddInboundLimiter(tag string, nodeSpeedLimit uint64, userList
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (l *Limiter) UpdateInboundLimiter(tag string, updatedUserList *[]api.UserInfo) error {
|
func (l *Limiter) UpdateInboundLimiter(tag string, updatedUserList *[]api.UserInfo) error {
|
||||||
|
|
||||||
if value, ok := l.InboundInfo.Load(tag); ok {
|
if value, ok := l.InboundInfo.Load(tag); ok {
|
||||||
inboundInfo := value.(*InboundInfo)
|
inboundInfo := value.(*InboundInfo)
|
||||||
// Update User info
|
// Update User info
|
||||||
@@ -88,7 +127,8 @@ func (l *Limiter) DeleteInboundLimiter(tag string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (l *Limiter) GetOnlineDevice(tag string) (*[]api.OnlineUser, error) {
|
func (l *Limiter) GetOnlineDevice(tag string) (*[]api.OnlineUser, error) {
|
||||||
onlineUser := make([]api.OnlineUser, 0)
|
var onlineUser []api.OnlineUser
|
||||||
|
|
||||||
if value, ok := l.InboundInfo.Load(tag); ok {
|
if value, ok := l.InboundInfo.Load(tag); ok {
|
||||||
inboundInfo := value.(*InboundInfo)
|
inboundInfo := value.(*InboundInfo)
|
||||||
// Clear Speed Limiter bucket for users who are not online
|
// Clear Speed Limiter bucket for users who are not online
|
||||||
@@ -100,43 +140,48 @@ func (l *Limiter) GetOnlineDevice(tag string) (*[]api.OnlineUser, error) {
|
|||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
inboundInfo.UserOnlineIP.Range(func(key, value interface{}) bool {
|
inboundInfo.UserOnlineIP.Range(func(key, value interface{}) bool {
|
||||||
|
email := key.(string)
|
||||||
ipMap := value.(*sync.Map)
|
ipMap := value.(*sync.Map)
|
||||||
ipMap.Range(func(key, value interface{}) bool {
|
ipMap.Range(func(key, value interface{}) bool {
|
||||||
ip := key.(string)
|
|
||||||
uid := value.(int)
|
uid := value.(int)
|
||||||
|
ip := key.(string)
|
||||||
onlineUser = append(onlineUser, api.OnlineUser{UID: uid, IP: ip})
|
onlineUser = append(onlineUser, api.OnlineUser{UID: uid, IP: ip})
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
email := key.(string)
|
|
||||||
inboundInfo.UserOnlineIP.Delete(email) // Reset online device
|
inboundInfo.UserOnlineIP.Delete(email) // Reset online device
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
return nil, fmt.Errorf("no such inbound in limiter: %s", tag)
|
return nil, fmt.Errorf("no such inbound in limiter: %s", tag)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &onlineUser, nil
|
return &onlineUser, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *Limiter) GetUserBucket(tag string, email string, ip string) (limiter *rate.Limiter, SpeedLimit bool, Reject bool) {
|
func (l *Limiter) GetUserBucket(tag string, email string, ip string) (limiter *rate.Limiter, SpeedLimit bool, Reject bool) {
|
||||||
if value, ok := l.InboundInfo.Load(tag); ok {
|
if value, ok := l.InboundInfo.Load(tag); ok {
|
||||||
|
var (
|
||||||
|
userLimit uint64 = 0
|
||||||
|
deviceLimit, uid int
|
||||||
|
)
|
||||||
|
|
||||||
inboundInfo := value.(*InboundInfo)
|
inboundInfo := value.(*InboundInfo)
|
||||||
nodeLimit := inboundInfo.NodeSpeedLimit
|
nodeLimit := inboundInfo.NodeSpeedLimit
|
||||||
var userLimit uint64 = 0
|
|
||||||
var deviceLimit int = 0
|
|
||||||
var uid int = 0
|
|
||||||
if v, ok := inboundInfo.UserInfo.Load(email); ok {
|
if v, ok := inboundInfo.UserInfo.Load(email); ok {
|
||||||
u := v.(UserInfo)
|
u := v.(UserInfo)
|
||||||
uid = u.UID
|
uid = u.UID
|
||||||
userLimit = u.SpeedLimit
|
userLimit = u.SpeedLimit
|
||||||
deviceLimit = u.DeviceLimit
|
deviceLimit = u.DeviceLimit
|
||||||
}
|
}
|
||||||
// Report online device
|
|
||||||
|
// Local device limit
|
||||||
ipMap := new(sync.Map)
|
ipMap := new(sync.Map)
|
||||||
ipMap.Store(ip, uid)
|
ipMap.Store(ip, uid)
|
||||||
// If any device is online
|
// If any device is online
|
||||||
if v, ok := inboundInfo.UserOnlineIP.LoadOrStore(email, ipMap); ok {
|
if v, ok := inboundInfo.UserOnlineIP.LoadOrStore(email, ipMap); ok {
|
||||||
ipMap := v.(*sync.Map)
|
ipMap := v.(*sync.Map)
|
||||||
// If this ip is a new device
|
// If this is a new ip
|
||||||
if _, ok := ipMap.LoadOrStore(ip, uid); !ok {
|
if _, ok := ipMap.LoadOrStore(ip, uid); !ok {
|
||||||
counter := 0
|
counter := 0
|
||||||
ipMap.Range(func(key, value interface{}) bool {
|
ipMap.Range(func(key, value interface{}) bool {
|
||||||
@@ -149,7 +194,16 @@ func (l *Limiter) GetUserBucket(tag string, email string, ip string) (limiter *r
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
limit := determineRate(nodeLimit, userLimit) // If need the Speed limit
|
|
||||||
|
// GlobalLimit
|
||||||
|
if inboundInfo.GlobalLimit.config != nil && inboundInfo.GlobalLimit.config.Enable {
|
||||||
|
if reject := globalLimit(inboundInfo, email, uid, ip, deviceLimit); reject {
|
||||||
|
return nil, false, true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Speed limit
|
||||||
|
limit := determineRate(nodeLimit, userLimit) // Determine the speed limit rate
|
||||||
if limit > 0 {
|
if limit > 0 {
|
||||||
limiter := rate.NewLimiter(rate.Limit(limit), int(limit)) // Byte/s
|
limiter := rate.NewLimiter(rate.Limit(limit), int(limit)) // Byte/s
|
||||||
if v, ok := inboundInfo.BucketHub.LoadOrStore(email, limiter); ok {
|
if v, ok := inboundInfo.BucketHub.LoadOrStore(email, limiter); ok {
|
||||||
@@ -167,6 +221,51 @@ func (l *Limiter) GetUserBucket(tag string, email string, ip string) (limiter *r
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Global device limit
|
||||||
|
func globalLimit(inboundInfo *InboundInfo, email string, uid int, ip string, deviceLimit int) bool {
|
||||||
|
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(inboundInfo.GlobalLimit.config.Timeout)*time.Second)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
// reformat email for unique key
|
||||||
|
uniqueKey := strings.Replace(email, inboundInfo.Tag, strconv.Itoa(deviceLimit), 1)
|
||||||
|
|
||||||
|
v, err := inboundInfo.GlobalLimit.globalOnlineIP.Get(ctx, uniqueKey, new(map[string]int))
|
||||||
|
if err != nil {
|
||||||
|
if _, ok := err.(*store.NotFound); ok {
|
||||||
|
// If the email is a new device
|
||||||
|
go pushIP(inboundInfo, uniqueKey, &map[string]int{ip: uid})
|
||||||
|
} else {
|
||||||
|
newError("cache service").Base(err).AtError().WriteToLog()
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
ipMap := v.(*map[string]int)
|
||||||
|
// Reject device reach limit directly
|
||||||
|
if deviceLimit > 0 && len(*ipMap) > deviceLimit {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the ip is not in cache
|
||||||
|
if _, ok := (*ipMap)[ip]; !ok {
|
||||||
|
(*ipMap)[ip] = uid
|
||||||
|
go pushIP(inboundInfo, email, ipMap)
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// push the ip to cache
|
||||||
|
func pushIP(inboundInfo *InboundInfo, email string, ipMap *map[string]int) {
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(inboundInfo.GlobalLimit.config.Timeout)*time.Second)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
if err := inboundInfo.GlobalLimit.globalOnlineIP.Set(ctx, email, ipMap); err != nil {
|
||||||
|
newError("cache service").Base(err).AtError().WriteToLog()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// determineRate returns the minimum non-zero rate
|
// determineRate returns the minimum non-zero rate
|
||||||
func determineRate(nodeLimit, userLimit uint64) (limit uint64) {
|
func determineRate(nodeLimit, userLimit uint64) (limit uint64) {
|
||||||
if nodeLimit == 0 || userLimit == 0 {
|
if nodeLimit == 0 || userLimit == 0 {
|
||||||
|
10
common/limiter/model.go
Normal file
10
common/limiter/model.go
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
package limiter
|
||||||
|
|
||||||
|
type GlobalDeviceLimitConfig struct {
|
||||||
|
Enable bool `mapstructure:"Enable"`
|
||||||
|
RedisAddr string `mapstructure:"RedisAddr"` // host:port
|
||||||
|
RedisPassword string `mapstructure:"RedisPassword"`
|
||||||
|
RedisDB int `mapstructure:"RedisDB"`
|
||||||
|
Timeout int `mapstructure:"Timeout"`
|
||||||
|
Expiry int `mapstructure:"Expiry"` // second
|
||||||
|
}
|
@@ -1,9 +1,8 @@
|
|||||||
package limiter
|
package limiter
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
|
||||||
|
|
||||||
"context"
|
"context"
|
||||||
|
"io"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/buf"
|
"github.com/xtls/xray-core/common/buf"
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
package cmd
|
package mylego
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto"
|
"crypto"
|
@@ -1,4 +1,4 @@
|
|||||||
package cmd
|
package mylego
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto"
|
"crypto"
|
||||||
@@ -6,18 +6,16 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"encoding/pem"
|
"encoding/pem"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"log"
|
||||||
"io/ioutil"
|
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/XrayR-project/XrayR/common/legocmd/log"
|
|
||||||
"github.com/go-acme/lego/v4/certcrypto"
|
"github.com/go-acme/lego/v4/certcrypto"
|
||||||
"github.com/go-acme/lego/v4/lego"
|
"github.com/go-acme/lego/v4/lego"
|
||||||
"github.com/go-acme/lego/v4/registration"
|
"github.com/go-acme/lego/v4/registration"
|
||||||
"github.com/urfave/cli"
|
"golang.org/x/crypto/acme"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -30,56 +28,53 @@ const (
|
|||||||
//
|
//
|
||||||
// rootPath:
|
// rootPath:
|
||||||
//
|
//
|
||||||
// ./.lego/accounts/
|
// ./.lego/accounts/
|
||||||
// │ └── root accounts directory
|
// │ └── root accounts directory
|
||||||
// └── "path" option
|
// └── "path" option
|
||||||
//
|
//
|
||||||
// rootUserPath:
|
// rootUserPath:
|
||||||
//
|
//
|
||||||
// ./.lego/accounts/localhost_14000/hubert@hubert.com/
|
// ./.lego/accounts/localhost_14000/hubert@hubert.com/
|
||||||
// │ │ │ └── userID ("email" option)
|
// │ │ │ └── userID ("email" option)
|
||||||
// │ │ └── CA server ("server" option)
|
// │ │ └── CA server ("server" option)
|
||||||
// │ └── root accounts directory
|
// │ └── root accounts directory
|
||||||
// └── "path" option
|
// └── "path" option
|
||||||
//
|
//
|
||||||
// keysPath:
|
// keysPath:
|
||||||
//
|
//
|
||||||
// ./.lego/accounts/localhost_14000/hubert@hubert.com/keys/
|
// ./.lego/accounts/localhost_14000/hubert@hubert.com/keys/
|
||||||
// │ │ │ │ └── root keys directory
|
// │ │ │ │ └── root keys directory
|
||||||
// │ │ │ └── userID ("email" option)
|
// │ │ │ └── userID ("email" option)
|
||||||
// │ │ └── CA server ("server" option)
|
// │ │ └── CA server ("server" option)
|
||||||
// │ └── root accounts directory
|
// │ └── root accounts directory
|
||||||
// └── "path" option
|
// └── "path" option
|
||||||
//
|
//
|
||||||
// accountFilePath:
|
// accountFilePath:
|
||||||
//
|
//
|
||||||
// ./.lego/accounts/localhost_14000/hubert@hubert.com/account.json
|
// ./.lego/accounts/localhost_14000/hubert@hubert.com/account.json
|
||||||
// │ │ │ │ └── account file
|
// │ │ │ │ └── account file
|
||||||
// │ │ │ └── userID ("email" option)
|
// │ │ │ └── userID ("email" option)
|
||||||
// │ │ └── CA server ("server" option)
|
// │ │ └── CA server ("server" option)
|
||||||
// │ └── root accounts directory
|
// │ └── root accounts directory
|
||||||
// └── "path" option
|
// └── "path" option
|
||||||
//
|
|
||||||
type AccountsStorage struct {
|
type AccountsStorage struct {
|
||||||
userID string
|
userID string
|
||||||
rootPath string
|
rootPath string
|
||||||
rootUserPath string
|
rootUserPath string
|
||||||
keysPath string
|
keysPath string
|
||||||
accountFilePath string
|
accountFilePath string
|
||||||
ctx *cli.Context
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewAccountsStorage Creates a new AccountsStorage.
|
// NewAccountsStorage Creates a new AccountsStorage.
|
||||||
func NewAccountsStorage(ctx *cli.Context) *AccountsStorage {
|
func NewAccountsStorage(l *LegoCMD) *AccountsStorage {
|
||||||
// TODO: move to account struct? Currently MUST pass email.
|
email := l.C.Email
|
||||||
email := getEmail(ctx)
|
|
||||||
|
|
||||||
serverURL, err := url.Parse(ctx.GlobalString("server"))
|
serverURL, err := url.Parse(acme.LetsEncryptURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Panic(err)
|
log.Panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
rootPath := filepath.Join(ctx.GlobalString("path"), baseAccountsRootFolderName)
|
rootPath := filepath.Join(l.path, baseAccountsRootFolderName)
|
||||||
serverPath := strings.NewReplacer(":", "_", "/", string(os.PathSeparator)).Replace(serverURL.Host)
|
serverPath := strings.NewReplacer(":", "_", "/", string(os.PathSeparator)).Replace(serverURL.Host)
|
||||||
accountsPath := filepath.Join(rootPath, serverPath)
|
accountsPath := filepath.Join(rootPath, serverPath)
|
||||||
rootUserPath := filepath.Join(accountsPath, email)
|
rootUserPath := filepath.Join(accountsPath, email)
|
||||||
@@ -90,7 +85,6 @@ func NewAccountsStorage(ctx *cli.Context) *AccountsStorage {
|
|||||||
rootUserPath: rootUserPath,
|
rootUserPath: rootUserPath,
|
||||||
keysPath: filepath.Join(rootUserPath, baseKeysFolderName),
|
keysPath: filepath.Join(rootUserPath, baseKeysFolderName),
|
||||||
accountFilePath: filepath.Join(rootUserPath, accountFileName),
|
accountFilePath: filepath.Join(rootUserPath, accountFileName),
|
||||||
ctx: ctx,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,11 +116,11 @@ func (s *AccountsStorage) Save(account *Account) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return ioutil.WriteFile(s.accountFilePath, jsonBytes, filePerm)
|
return os.WriteFile(s.accountFilePath, jsonBytes, filePerm)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *AccountsStorage) LoadAccount(privateKey crypto.PrivateKey) *Account {
|
func (s *AccountsStorage) LoadAccount(privateKey crypto.PrivateKey) *Account {
|
||||||
fileBytes, err := ioutil.ReadFile(s.accountFilePath)
|
fileBytes, err := os.ReadFile(s.accountFilePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Panicf("Could not load file for account %s: %v", s.userID, err)
|
log.Panicf("Could not load file for account %s: %v", s.userID, err)
|
||||||
}
|
}
|
||||||
@@ -140,7 +134,7 @@ func (s *AccountsStorage) LoadAccount(privateKey crypto.PrivateKey) *Account {
|
|||||||
account.key = privateKey
|
account.key = privateKey
|
||||||
|
|
||||||
if account.Registration == nil || account.Registration.Body.Status == "" {
|
if account.Registration == nil || account.Registration.Body.Status == "" {
|
||||||
reg, err := tryRecoverRegistration(s.ctx, privateKey)
|
reg, err := tryRecoverRegistration(privateKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Panicf("Could not load account for %s. Registration is nil: %#v", s.userID, err)
|
log.Panicf("Could not load account for %s. Registration is nil: %#v", s.userID, err)
|
||||||
}
|
}
|
||||||
@@ -207,7 +201,7 @@ func generatePrivateKey(file string, keyType certcrypto.KeyType) (crypto.Private
|
|||||||
}
|
}
|
||||||
|
|
||||||
func loadPrivateKey(file string) (crypto.PrivateKey, error) {
|
func loadPrivateKey(file string) (crypto.PrivateKey, error) {
|
||||||
keyBytes, err := ioutil.ReadFile(file)
|
keyBytes, err := os.ReadFile(file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -224,11 +218,11 @@ func loadPrivateKey(file string) (crypto.PrivateKey, error) {
|
|||||||
return nil, errors.New("unknown private key type")
|
return nil, errors.New("unknown private key type")
|
||||||
}
|
}
|
||||||
|
|
||||||
func tryRecoverRegistration(ctx *cli.Context, privateKey crypto.PrivateKey) (*registration.Resource, error) {
|
func tryRecoverRegistration(privateKey crypto.PrivateKey) (*registration.Resource, error) {
|
||||||
// couldn't load account but got a key. Try to look the account up.
|
// couldn't load account but got a key. Try to look the account up.
|
||||||
config := lego.NewConfig(&Account{key: privateKey})
|
config := lego.NewConfig(&Account{key: privateKey})
|
||||||
config.CADirURL = ctx.GlobalString("server")
|
config.CADirURL = acme.LetsEncryptURL
|
||||||
config.UserAgent = fmt.Sprintf("lego-cli/%s", ctx.App.Version)
|
config.UserAgent = "lego-cli/dev"
|
||||||
|
|
||||||
client, err := lego.NewClient(config)
|
client, err := lego.NewClient(config)
|
||||||
if err != nil {
|
if err != nil {
|
@@ -1,56 +1,45 @@
|
|||||||
package cmd
|
package mylego
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"io/ioutil"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/XrayR-project/XrayR/common/legocmd/log"
|
|
||||||
"github.com/go-acme/lego/v4/certcrypto"
|
"github.com/go-acme/lego/v4/certcrypto"
|
||||||
"github.com/go-acme/lego/v4/certificate"
|
"github.com/go-acme/lego/v4/certificate"
|
||||||
"github.com/urfave/cli"
|
|
||||||
"golang.org/x/net/idna"
|
"golang.org/x/net/idna"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
baseCertificatesFolderName = "certificates"
|
baseCertificatesFolderName = "certificates"
|
||||||
baseArchivesFolderName = "archives"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// CertificatesStorage a certificates storage.
|
// CertificatesStorage a certificates' storage.
|
||||||
//
|
//
|
||||||
// rootPath:
|
// rootPath:
|
||||||
//
|
//
|
||||||
// ./.lego/certificates/
|
// ./.lego/certificates/
|
||||||
// │ └── root certificates directory
|
// │ └── root certificates directory
|
||||||
// └── "path" option
|
// └── "path" option
|
||||||
//
|
//
|
||||||
// archivePath:
|
// archivePath:
|
||||||
//
|
//
|
||||||
// ./.lego/archives/
|
// ./.lego/archives/
|
||||||
// │ └── archived certificates directory
|
// │ └── archived certificates directory
|
||||||
// └── "path" option
|
// └── "path" option
|
||||||
//
|
|
||||||
type CertificatesStorage struct {
|
type CertificatesStorage struct {
|
||||||
rootPath string
|
rootPath string
|
||||||
archivePath string
|
pem bool
|
||||||
pem bool
|
|
||||||
filename string // Deprecated
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewCertificatesStorage create a new certificates storage.
|
// NewCertificatesStorage create a new certificates storage.
|
||||||
func NewCertificatesStorage(ctx *cli.Context) *CertificatesStorage {
|
func NewCertificatesStorage(path string) *CertificatesStorage {
|
||||||
return &CertificatesStorage{
|
return &CertificatesStorage{
|
||||||
rootPath: filepath.Join(ctx.GlobalString("path"), baseCertificatesFolderName),
|
rootPath: filepath.Join(path, baseCertificatesFolderName),
|
||||||
archivePath: filepath.Join(ctx.GlobalString("path"), baseArchivesFolderName),
|
|
||||||
pem: ctx.GlobalBool("pem"),
|
|
||||||
filename: ctx.GlobalString("filename"),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,13 +50,6 @@ func (s *CertificatesStorage) CreateRootFolder() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *CertificatesStorage) CreateArchiveFolder() {
|
|
||||||
err := createNonExistingFolder(s.archivePath)
|
|
||||||
if err != nil {
|
|
||||||
log.Panicf("Could not check/create path: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *CertificatesStorage) GetRootPath() string {
|
func (s *CertificatesStorage) GetRootPath() string {
|
||||||
return s.rootPath
|
return s.rootPath
|
||||||
}
|
}
|
||||||
@@ -144,7 +126,7 @@ func (s *CertificatesStorage) ExistsFile(domain, extension string) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *CertificatesStorage) ReadFile(domain, extension string) ([]byte, error) {
|
func (s *CertificatesStorage) ReadFile(domain, extension string) ([]byte, error) {
|
||||||
return ioutil.ReadFile(s.GetFileName(domain, extension))
|
return os.ReadFile(s.GetFileName(domain, extension))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *CertificatesStorage) GetFileName(domain, extension string) string {
|
func (s *CertificatesStorage) GetFileName(domain, extension string) string {
|
||||||
@@ -163,36 +145,11 @@ func (s *CertificatesStorage) ReadCertificate(domain, extension string) ([]*x509
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *CertificatesStorage) WriteFile(domain, extension string, data []byte) error {
|
func (s *CertificatesStorage) WriteFile(domain, extension string, data []byte) error {
|
||||||
var baseFileName string
|
var baseFileName = sanitizedDomain(domain)
|
||||||
if s.filename != "" {
|
|
||||||
baseFileName = s.filename
|
|
||||||
} else {
|
|
||||||
baseFileName = sanitizedDomain(domain)
|
|
||||||
}
|
|
||||||
|
|
||||||
filePath := filepath.Join(s.rootPath, baseFileName+extension)
|
filePath := filepath.Join(s.rootPath, baseFileName+extension)
|
||||||
|
|
||||||
return ioutil.WriteFile(filePath, data, filePerm)
|
return os.WriteFile(filePath, data, filePerm)
|
||||||
}
|
|
||||||
|
|
||||||
func (s *CertificatesStorage) MoveToArchive(domain string) error {
|
|
||||||
matches, err := filepath.Glob(filepath.Join(s.rootPath, sanitizedDomain(domain)+".*"))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, oldFile := range matches {
|
|
||||||
date := strconv.FormatInt(time.Now().Unix(), 10)
|
|
||||||
filename := date + "." + filepath.Base(oldFile)
|
|
||||||
newFile := filepath.Join(s.archivePath, filename)
|
|
||||||
|
|
||||||
err = os.Rename(oldFile, newFile)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// sanitizedDomain Make sure no funny chars are in the cert names (like wildcards ;)).
|
// sanitizedDomain Make sure no funny chars are in the cert names (like wildcards ;)).
|
87
common/mylego/lego_test.go
Normal file
87
common/mylego/lego_test.go
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
package mylego_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/XrayR-project/XrayR/common/mylego"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestLegoClient(t *testing.T) {
|
||||||
|
_, err := mylego.New(&mylego.CertConfig{})
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLegoDNSCert(t *testing.T) {
|
||||||
|
lego, err := mylego.New(&mylego.CertConfig{
|
||||||
|
CertDomain: "node1.test.com",
|
||||||
|
Provider: "alidns",
|
||||||
|
Email: "test@gmail.com",
|
||||||
|
DNSEnv: map[string]string{
|
||||||
|
"ALICLOUD_ACCESS_KEY": "aaa",
|
||||||
|
"ALICLOUD_SECRET_KEY": "bbb",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
certPath, keyPath, err := lego.DNSCert()
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
t.Log(certPath)
|
||||||
|
t.Log(keyPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLegoHTTPCert(t *testing.T) {
|
||||||
|
lego, err := mylego.New(&mylego.CertConfig{
|
||||||
|
CertMode: "http",
|
||||||
|
CertDomain: "node1.test.com",
|
||||||
|
Email: "test@gmail.com",
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
certPath, keyPath, err := lego.HTTPCert()
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
t.Log(certPath)
|
||||||
|
t.Log(keyPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLegoRenewCert(t *testing.T) {
|
||||||
|
lego, err := mylego.New(&mylego.CertConfig{
|
||||||
|
CertDomain: "node1.test.com",
|
||||||
|
Email: "test@gmail.com",
|
||||||
|
Provider: "alidns",
|
||||||
|
DNSEnv: map[string]string{
|
||||||
|
"ALICLOUD_ACCESS_KEY": "aaa",
|
||||||
|
"ALICLOUD_SECRET_KEY": "bbb",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
lego.C.CertMode = "http"
|
||||||
|
certPath, keyPath, ok, err := lego.RenewCert()
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
t.Log(certPath)
|
||||||
|
t.Log(keyPath)
|
||||||
|
t.Log(ok)
|
||||||
|
|
||||||
|
lego.C.CertMode = "dns"
|
||||||
|
certPath, keyPath, ok, err = lego.RenewCert()
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
t.Log(certPath)
|
||||||
|
t.Log(keyPath)
|
||||||
|
t.Log(ok)
|
||||||
|
}
|
17
common/mylego/model.go
Normal file
17
common/mylego/model.go
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
package mylego
|
||||||
|
|
||||||
|
type CertConfig struct {
|
||||||
|
CertMode string `mapstructure:"CertMode"` // none, file, http, dns
|
||||||
|
CertDomain string `mapstructure:"CertDomain"`
|
||||||
|
CertFile string `mapstructure:"CertFile"`
|
||||||
|
KeyFile string `mapstructure:"KeyFile"`
|
||||||
|
Provider string `mapstructure:"Provider"` // alidns, cloudflare, gandi, godaddy....
|
||||||
|
Email string `mapstructure:"Email"`
|
||||||
|
DNSEnv map[string]string `mapstructure:"DNSEnv"`
|
||||||
|
RejectUnknownSni bool `mapstructure:"RejectUnknownSni"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type LegoCMD struct {
|
||||||
|
C *CertConfig
|
||||||
|
path string
|
||||||
|
}
|
163
common/mylego/mylego.go
Normal file
163
common/mylego/mylego.go
Normal file
@@ -0,0 +1,163 @@
|
|||||||
|
package mylego
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
var defaultPath string
|
||||||
|
|
||||||
|
func New(certConf *CertConfig) (*LegoCMD, error) {
|
||||||
|
// Set default path to configPath/cert
|
||||||
|
var p = ""
|
||||||
|
configPath := os.Getenv("XRAY_LOCATION_CONFIG")
|
||||||
|
if configPath != "" {
|
||||||
|
p = configPath
|
||||||
|
} else if cwd, err := os.Getwd(); err == nil {
|
||||||
|
p = cwd
|
||||||
|
} else {
|
||||||
|
p = "."
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultPath = filepath.Join(p, "cert")
|
||||||
|
lego := &LegoCMD{
|
||||||
|
C: certConf,
|
||||||
|
path: defaultPath,
|
||||||
|
}
|
||||||
|
|
||||||
|
return lego, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *LegoCMD) getPath() string {
|
||||||
|
return l.path
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *LegoCMD) getCertConfig() *CertConfig {
|
||||||
|
return l.C
|
||||||
|
}
|
||||||
|
|
||||||
|
// DNSCert cert a domain using DNS API
|
||||||
|
func (l *LegoCMD) DNSCert() (CertPath string, KeyPath string, err error) {
|
||||||
|
defer func() (string, string, error) {
|
||||||
|
// Handle any error
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
switch x := r.(type) {
|
||||||
|
case string:
|
||||||
|
err = errors.New(x)
|
||||||
|
case error:
|
||||||
|
err = x
|
||||||
|
default:
|
||||||
|
err = errors.New("unknown panic")
|
||||||
|
}
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
return CertPath, KeyPath, nil
|
||||||
|
}()
|
||||||
|
|
||||||
|
// Set Env for DNS configuration
|
||||||
|
for key, value := range l.C.DNSEnv {
|
||||||
|
os.Setenv(strings.ToUpper(key), value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// First check if the certificate exists
|
||||||
|
CertPath, KeyPath, err = checkCertFile(l.C.CertDomain)
|
||||||
|
if err == nil {
|
||||||
|
return CertPath, KeyPath, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = l.Run()
|
||||||
|
if err != nil {
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
CertPath, KeyPath, err = checkCertFile(l.C.CertDomain)
|
||||||
|
if err != nil {
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
return CertPath, KeyPath, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// HTTPCert cert a domain using http methods
|
||||||
|
func (l *LegoCMD) HTTPCert() (CertPath string, KeyPath string, err error) {
|
||||||
|
defer func() (string, string, error) {
|
||||||
|
// Handle any error
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
switch x := r.(type) {
|
||||||
|
case string:
|
||||||
|
err = errors.New(x)
|
||||||
|
case error:
|
||||||
|
err = x
|
||||||
|
default:
|
||||||
|
err = errors.New("unknown panic")
|
||||||
|
}
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
return CertPath, KeyPath, nil
|
||||||
|
}()
|
||||||
|
|
||||||
|
// First check if the certificate exists
|
||||||
|
CertPath, KeyPath, err = checkCertFile(l.C.CertDomain)
|
||||||
|
if err == nil {
|
||||||
|
return CertPath, KeyPath, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = l.Run()
|
||||||
|
if err != nil {
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
CertPath, KeyPath, err = checkCertFile(l.C.CertDomain)
|
||||||
|
if err != nil {
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return CertPath, KeyPath, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// RenewCert renew a domain cert
|
||||||
|
func (l *LegoCMD) RenewCert() (CertPath string, KeyPath string, ok bool, err error) {
|
||||||
|
defer func() (string, string, bool, error) {
|
||||||
|
// Handle any error
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
switch x := r.(type) {
|
||||||
|
case string:
|
||||||
|
err = errors.New(x)
|
||||||
|
case error:
|
||||||
|
err = x
|
||||||
|
default:
|
||||||
|
err = errors.New("unknown panic")
|
||||||
|
}
|
||||||
|
return "", "", false, err
|
||||||
|
}
|
||||||
|
return CertPath, KeyPath, ok, nil
|
||||||
|
}()
|
||||||
|
|
||||||
|
ok, err = l.Renew()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
CertPath, KeyPath, err = checkCertFile(l.C.CertDomain)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
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))
|
||||||
|
if _, err := os.Stat(keyPath); os.IsNotExist(err) {
|
||||||
|
return "", "", fmt.Errorf("cert key failed: %s", domain)
|
||||||
|
}
|
||||||
|
if _, err := os.Stat(certPath); os.IsNotExist(err) {
|
||||||
|
return "", "", fmt.Errorf("cert cert failed: %s", domain)
|
||||||
|
}
|
||||||
|
absKeyPath, _ := filepath.Abs(keyPath)
|
||||||
|
absCertPath, _ := filepath.Abs(certPath)
|
||||||
|
return absCertPath, absKeyPath, nil
|
||||||
|
}
|
77
common/mylego/renew.go
Normal file
77
common/mylego/renew.go
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
package mylego
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto"
|
||||||
|
"crypto/x509"
|
||||||
|
"log"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/go-acme/lego/v4/certcrypto"
|
||||||
|
"github.com/go-acme/lego/v4/certificate"
|
||||||
|
"github.com/go-acme/lego/v4/lego"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (l *LegoCMD) Renew() (bool, error) {
|
||||||
|
account, client := setup(NewAccountsStorage(l))
|
||||||
|
setupChallenges(l, client)
|
||||||
|
|
||||||
|
if account.Registration == nil {
|
||||||
|
log.Panicf("Account %s is not registered. Use 'run' to register a new account.\n", account.Email)
|
||||||
|
}
|
||||||
|
|
||||||
|
return renewForDomains(l.C.CertDomain, client, NewCertificatesStorage(l.path))
|
||||||
|
}
|
||||||
|
|
||||||
|
func renewForDomains(domain string, client *lego.Client, certsStorage *CertificatesStorage) (bool, error) {
|
||||||
|
// load the cert resource from files.
|
||||||
|
// We store the certificate, private key and metadata in different files
|
||||||
|
// as web servers would not be able to work with a combined file.
|
||||||
|
certificates, err := certsStorage.ReadCertificate(domain, ".crt")
|
||||||
|
if err != nil {
|
||||||
|
log.Panicf("Error while loading the certificate for domain %s\n\t%v", domain, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
cert := certificates[0]
|
||||||
|
|
||||||
|
if !needRenewal(cert, domain, 30) {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is just meant to be informal for the user.
|
||||||
|
timeLeft := cert.NotAfter.Sub(time.Now().UTC())
|
||||||
|
log.Printf("[%s] acme: Trying renewal with %d hours remaining", domain, int(timeLeft.Hours()))
|
||||||
|
|
||||||
|
certDomains := certcrypto.ExtractDomains(cert)
|
||||||
|
|
||||||
|
var privateKey crypto.PrivateKey
|
||||||
|
request := certificate.ObtainRequest{
|
||||||
|
Domains: certDomains,
|
||||||
|
Bundle: true,
|
||||||
|
PrivateKey: privateKey,
|
||||||
|
}
|
||||||
|
certRes, err := client.Certificate.Obtain(request)
|
||||||
|
if err != nil {
|
||||||
|
log.Panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
certsStorage.SaveResource(certRes)
|
||||||
|
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func needRenewal(x509Cert *x509.Certificate, domain string, days int) bool {
|
||||||
|
if x509Cert.IsCA {
|
||||||
|
log.Panicf("[%s] Certificate bundle starts with a CA certificate", domain)
|
||||||
|
}
|
||||||
|
|
||||||
|
if days >= 0 {
|
||||||
|
notAfter := int(time.Until(x509Cert.NotAfter).Hours() / 24.0)
|
||||||
|
if notAfter > days {
|
||||||
|
log.Printf("[%s] The certificate expires in %d days, the number of days defined to perform the renewal is %d: no renewal.",
|
||||||
|
domain, notAfter, days)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
@@ -1,4 +1,4 @@
|
|||||||
package cmd
|
package mylego
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
@@ -116,3 +116,19 @@ func Test_needRenewal(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func merge(prevDomains, nextDomains []string) []string {
|
||||||
|
for _, next := range nextDomains {
|
||||||
|
var found bool
|
||||||
|
for _, prev := range prevDomains {
|
||||||
|
if prev == next {
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
prevDomains = append(prevDomains, next)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return prevDomains
|
||||||
|
}
|
68
common/mylego/run.go
Normal file
68
common/mylego/run.go
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
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"
|
||||||
|
)
|
||||||
|
|
||||||
|
const rootPathWarningMessage = `!!!! HEADS UP !!!!
|
||||||
|
|
||||||
|
Your account credentials have been saved in your Let's Encrypt
|
||||||
|
configuration directory at "%s".
|
||||||
|
|
||||||
|
You should make a secure backup of this folder now. This
|
||||||
|
configuration directory will also contain certificates and
|
||||||
|
private keys obtained from Let's Encrypt so making regular
|
||||||
|
backups of this folder is ideal.
|
||||||
|
`
|
||||||
|
|
||||||
|
func (l *LegoCMD) Run() error {
|
||||||
|
accountsStorage := NewAccountsStorage(l)
|
||||||
|
|
||||||
|
account, client := setup(accountsStorage)
|
||||||
|
setupChallenges(l, client)
|
||||||
|
|
||||||
|
if account.Registration == nil {
|
||||||
|
reg, err := client.Registration.Register(registration.RegisterOptions{TermsOfServiceAgreed: true})
|
||||||
|
if err != nil {
|
||||||
|
log.Panicf("Could not complete registration\n\t%v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
account.Registration = reg
|
||||||
|
if err = accountsStorage.Save(account); err != nil {
|
||||||
|
log.Panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf(rootPathWarningMessage, accountsStorage.GetRootPath())
|
||||||
|
}
|
||||||
|
|
||||||
|
certsStorage := NewCertificatesStorage(l.path)
|
||||||
|
certsStorage.CreateRootFolder()
|
||||||
|
|
||||||
|
cert, err := obtainCertificate([]string{l.C.CertDomain}, client)
|
||||||
|
if err != nil {
|
||||||
|
// Make sure to return a non-zero exit code if ObtainSANCertificate returned at least one error.
|
||||||
|
// Due to us not returning partial certificate we can just exit here instead of at the end.
|
||||||
|
log.Panicf("Could not obtain certificates:\n\t%v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
certsStorage.SaveResource(cert)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func obtainCertificate(domains []string, client *lego.Client) (*certificate.Resource, error) {
|
||||||
|
if len(domains) > 0 {
|
||||||
|
// obtain a certificate, generating a new private key
|
||||||
|
request := certificate.ObtainRequest{
|
||||||
|
Domains: domains,
|
||||||
|
Bundle: true,
|
||||||
|
}
|
||||||
|
return client.Certificate.Obtain(request)
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("not a valid domain")
|
||||||
|
}
|
95
common/mylego/setup.go
Normal file
95
common/mylego/setup.go
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
package mylego
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/go-acme/lego/v4/certcrypto"
|
||||||
|
"github.com/go-acme/lego/v4/challenge/dns01"
|
||||||
|
"github.com/go-acme/lego/v4/challenge/http01"
|
||||||
|
"github.com/go-acme/lego/v4/challenge/tlsalpn01"
|
||||||
|
"github.com/go-acme/lego/v4/lego"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns"
|
||||||
|
"github.com/go-acme/lego/v4/registration"
|
||||||
|
"golang.org/x/crypto/acme"
|
||||||
|
)
|
||||||
|
|
||||||
|
const filePerm os.FileMode = 0o600
|
||||||
|
|
||||||
|
func setup(accountsStorage *AccountsStorage) (*Account, *lego.Client) {
|
||||||
|
keyType := certcrypto.EC256
|
||||||
|
privateKey := accountsStorage.GetPrivateKey(keyType)
|
||||||
|
|
||||||
|
var account *Account
|
||||||
|
if accountsStorage.ExistsAccountFilePath() {
|
||||||
|
account = accountsStorage.LoadAccount(privateKey)
|
||||||
|
} else {
|
||||||
|
account = &Account{Email: accountsStorage.GetUserID(), key: privateKey}
|
||||||
|
}
|
||||||
|
|
||||||
|
client := newClient(account, keyType)
|
||||||
|
|
||||||
|
return account, client
|
||||||
|
}
|
||||||
|
|
||||||
|
func newClient(acc registration.User, keyType certcrypto.KeyType) *lego.Client {
|
||||||
|
config := lego.NewConfig(acc)
|
||||||
|
config.CADirURL = acme.LetsEncryptURL
|
||||||
|
|
||||||
|
config.Certificate = lego.CertificateConfig{
|
||||||
|
KeyType: keyType,
|
||||||
|
Timeout: 30 * time.Second,
|
||||||
|
}
|
||||||
|
config.UserAgent = "lego-cli/dev"
|
||||||
|
|
||||||
|
client, err := lego.NewClient(config)
|
||||||
|
if err != nil {
|
||||||
|
log.Panicf("Could not create client: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return client
|
||||||
|
}
|
||||||
|
|
||||||
|
func createNonExistingFolder(path string) error {
|
||||||
|
if _, err := os.Stat(path); os.IsNotExist(err) {
|
||||||
|
return os.MkdirAll(path, 0o700)
|
||||||
|
} else if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func setupChallenges(l *LegoCMD, client *lego.Client) {
|
||||||
|
switch l.C.CertMode {
|
||||||
|
case "http":
|
||||||
|
err := client.Challenge.SetHTTP01Provider(http01.NewProviderServer("", ""))
|
||||||
|
if err != nil {
|
||||||
|
log.Panic(err)
|
||||||
|
}
|
||||||
|
case "tls":
|
||||||
|
err := client.Challenge.SetTLSALPN01Provider(tlsalpn01.NewProviderServer("", ""))
|
||||||
|
if err != nil {
|
||||||
|
log.Panic(err)
|
||||||
|
}
|
||||||
|
case "dns":
|
||||||
|
setupDNS(l.C.Provider, client)
|
||||||
|
default:
|
||||||
|
log.Panic("No challenge selected. You must specify at least one challenge: `http`, `tls`, `dns`.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func setupDNS(p string, client *lego.Client) {
|
||||||
|
provider, err := dns.NewDNSChallengeProviderByName(p)
|
||||||
|
if err != nil {
|
||||||
|
log.Panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = client.Challenge.SetDNS01Provider(
|
||||||
|
provider,
|
||||||
|
dns01.CondOption(true, dns01.AddDNSTimeout(10*time.Second)),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
log.Panic(err)
|
||||||
|
}
|
||||||
|
}
|
@@ -2,8 +2,6 @@ package rule
|
|||||||
|
|
||||||
import "github.com/xtls/xray-core/common/errors"
|
import "github.com/xtls/xray-core/common/errors"
|
||||||
|
|
||||||
type errPathObjHolder struct{}
|
|
||||||
|
|
||||||
func newError(values ...interface{}) *errors.Error {
|
func newError(values ...interface{}) *errors.Error {
|
||||||
return errors.New(values...).WithPathObj(errPathObjHolder{})
|
return errors.New(values...)
|
||||||
}
|
}
|
||||||
|
@@ -8,23 +8,24 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/XrayR-project/XrayR/api"
|
|
||||||
mapset "github.com/deckarep/golang-set"
|
mapset "github.com/deckarep/golang-set"
|
||||||
|
|
||||||
|
"github.com/XrayR-project/XrayR/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
type RuleManager struct {
|
type Manager struct {
|
||||||
InboundRule *sync.Map // Key: Tag, Value: []api.DetectRule
|
InboundRule *sync.Map // Key: Tag, Value: []api.DetectRule
|
||||||
InboundDetectResult *sync.Map // key: Tag, Value: mapset.NewSet []api.DetectResult
|
InboundDetectResult *sync.Map // key: Tag, Value: mapset.NewSet []api.DetectResult
|
||||||
}
|
}
|
||||||
|
|
||||||
func New() *RuleManager {
|
func New() *Manager {
|
||||||
return &RuleManager{
|
return &Manager{
|
||||||
InboundRule: new(sync.Map),
|
InboundRule: new(sync.Map),
|
||||||
InboundDetectResult: new(sync.Map),
|
InboundDetectResult: new(sync.Map),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *RuleManager) UpdateRule(tag string, newRuleList []api.DetectRule) error {
|
func (r *Manager) UpdateRule(tag string, newRuleList []api.DetectRule) error {
|
||||||
if value, ok := r.InboundRule.LoadOrStore(tag, newRuleList); ok {
|
if value, ok := r.InboundRule.LoadOrStore(tag, newRuleList); ok {
|
||||||
oldRuleList := value.([]api.DetectRule)
|
oldRuleList := value.([]api.DetectRule)
|
||||||
if !reflect.DeepEqual(oldRuleList, newRuleList) {
|
if !reflect.DeepEqual(oldRuleList, newRuleList) {
|
||||||
@@ -34,7 +35,7 @@ func (r *RuleManager) UpdateRule(tag string, newRuleList []api.DetectRule) error
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *RuleManager) GetDetectResult(tag string) (*[]api.DetectResult, error) {
|
func (r *Manager) GetDetectResult(tag string) (*[]api.DetectResult, error) {
|
||||||
detectResult := make([]api.DetectResult, 0)
|
detectResult := make([]api.DetectResult, 0)
|
||||||
if value, ok := r.InboundDetectResult.LoadAndDelete(tag); ok {
|
if value, ok := r.InboundDetectResult.LoadAndDelete(tag); ok {
|
||||||
resultSet := value.(mapset.Set)
|
resultSet := value.(mapset.Set)
|
||||||
@@ -46,9 +47,9 @@ func (r *RuleManager) GetDetectResult(tag string) (*[]api.DetectResult, error) {
|
|||||||
return &detectResult, nil
|
return &detectResult, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *RuleManager) Detect(tag string, destination string, email string) (reject bool) {
|
func (r *Manager) Detect(tag string, destination string, email string) (reject bool) {
|
||||||
reject = false
|
reject = false
|
||||||
var hitRuleID int = -1
|
var hitRuleID = -1
|
||||||
// If we have some rule for this inbound
|
// If we have some rule for this inbound
|
||||||
if value, ok := r.InboundRule.Load(tag); ok {
|
if value, ok := r.InboundRule.Load(tag); ok {
|
||||||
ruleList := value.([]api.DetectRule)
|
ruleList := value.([]api.DetectRule)
|
||||||
|
@@ -13,7 +13,7 @@ import (
|
|||||||
// GetSystemInfo get the system info of a given periodic
|
// GetSystemInfo get the system info of a given periodic
|
||||||
func GetSystemInfo() (Cpu float64, Mem float64, Disk float64, Uptime uint64, err error) {
|
func GetSystemInfo() (Cpu float64, Mem float64, Disk float64, Uptime uint64, err error) {
|
||||||
|
|
||||||
error_string := ""
|
errorString := ""
|
||||||
|
|
||||||
cpuPercent, err := cpu.Percent(0, false)
|
cpuPercent, err := cpu.Percent(0, false)
|
||||||
// Check if cpuPercent is empty
|
// Check if cpuPercent is empty
|
||||||
@@ -21,32 +21,32 @@ func GetSystemInfo() (Cpu float64, Mem float64, Disk float64, Uptime uint64, err
|
|||||||
Cpu = cpuPercent[0]
|
Cpu = cpuPercent[0]
|
||||||
} else {
|
} else {
|
||||||
Cpu = 0
|
Cpu = 0
|
||||||
error_string += fmt.Sprintf("get cpu usage failed: %s ", err)
|
errorString += fmt.Sprintf("get cpu usage failed: %s ", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
memUsage, err := mem.VirtualMemory()
|
memUsage, err := mem.VirtualMemory()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
error_string += fmt.Sprintf("get mem usage failed: %s ", err)
|
errorString += fmt.Sprintf("get mem usage failed: %s ", err)
|
||||||
} else {
|
} else {
|
||||||
Mem = memUsage.UsedPercent
|
Mem = memUsage.UsedPercent
|
||||||
}
|
}
|
||||||
|
|
||||||
diskUsage, err := disk.Usage("/")
|
diskUsage, err := disk.Usage("/")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
error_string += fmt.Sprintf("get disk usage failed: %s ", err)
|
errorString += fmt.Sprintf("get disk usage failed: %s ", err)
|
||||||
} else {
|
} else {
|
||||||
Disk = diskUsage.UsedPercent
|
Disk = diskUsage.UsedPercent
|
||||||
}
|
}
|
||||||
|
|
||||||
uptime, err := host.Uptime()
|
uptime, err := host.Uptime()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
error_string += fmt.Sprintf("get uptime failed: %s ", err)
|
errorString += fmt.Sprintf("get uptime failed: %s ", err)
|
||||||
} else {
|
} else {
|
||||||
Uptime = uptime
|
Uptime = uptime
|
||||||
}
|
}
|
||||||
|
|
||||||
if error_string != "" {
|
if errorString != "" {
|
||||||
err = fmt.Errorf(error_string)
|
err = fmt.Errorf(errorString)
|
||||||
}
|
}
|
||||||
|
|
||||||
return Cpu, Mem, Disk, Uptime, err
|
return Cpu, Mem, Disk, Uptime, err
|
||||||
|
94
go.mod
94
go.mod
@@ -5,23 +5,31 @@ go 1.19
|
|||||||
require (
|
require (
|
||||||
github.com/bitly/go-simplejson v0.5.0
|
github.com/bitly/go-simplejson v0.5.0
|
||||||
github.com/deckarep/golang-set v1.8.0
|
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/fsnotify/fsnotify v1.6.0
|
||||||
github.com/go-acme/lego/v4 v4.9.0
|
github.com/go-acme/lego/v4 v4.9.1
|
||||||
|
github.com/go-redis/redis/v8 v8.11.5
|
||||||
github.com/go-resty/resty/v2 v2.7.0
|
github.com/go-resty/resty/v2 v2.7.0
|
||||||
github.com/imdario/mergo v0.3.13
|
github.com/imdario/mergo v0.3.13
|
||||||
|
github.com/patrickmn/go-cache v2.1.0+incompatible
|
||||||
github.com/r3labs/diff/v2 v2.15.1
|
github.com/r3labs/diff/v2 v2.15.1
|
||||||
github.com/shirou/gopsutil/v3 v3.22.9
|
github.com/sagernet/sing v0.1.0
|
||||||
github.com/spf13/viper v1.13.0
|
github.com/sagernet/sing-shadowsocks v0.1.0
|
||||||
github.com/stretchr/testify v1.8.0
|
github.com/shirou/gopsutil/v3 v3.22.11
|
||||||
github.com/urfave/cli v1.22.10
|
github.com/spf13/viper v1.14.0
|
||||||
github.com/xtls/xray-core v1.6.0
|
github.com/stretchr/testify v1.8.1
|
||||||
golang.org/x/net v0.0.0-20220909164309-bea034e7d591
|
github.com/xtls/xray-core v1.6.5
|
||||||
golang.org/x/time v0.0.0-20220224211638-0e9765cccd65
|
golang.org/x/crypto v0.4.0
|
||||||
|
golang.org/x/net v0.4.0
|
||||||
|
golang.org/x/time v0.3.0
|
||||||
google.golang.org/protobuf v1.28.1
|
google.golang.org/protobuf v1.28.1
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
cloud.google.com/go/compute v1.7.0 // indirect
|
cloud.google.com/go/compute v1.12.1 // indirect
|
||||||
|
cloud.google.com/go/compute/metadata v0.2.1 // indirect
|
||||||
github.com/Azure/azure-sdk-for-go v32.4.0+incompatible // indirect
|
github.com/Azure/azure-sdk-for-go v32.4.0+incompatible // indirect
|
||||||
github.com/Azure/go-autorest v14.2.0+incompatible // 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 v0.11.24 // indirect
|
||||||
@@ -39,16 +47,18 @@ require (
|
|||||||
github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129 // indirect
|
github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129 // indirect
|
||||||
github.com/andybalholm/brotli v1.0.4 // indirect
|
github.com/andybalholm/brotli v1.0.4 // indirect
|
||||||
github.com/aws/aws-sdk-go v1.39.0 // indirect
|
github.com/aws/aws-sdk-go v1.39.0 // indirect
|
||||||
|
github.com/beorn7/perks v1.0.1 // indirect
|
||||||
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect
|
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect
|
||||||
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc // indirect
|
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc // indirect
|
||||||
github.com/cenkalti/backoff/v4 v4.1.3 // 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/civo/civogo v0.3.11 // indirect
|
||||||
github.com/cloudflare/cloudflare-go v0.49.0 // indirect
|
github.com/cloudflare/cloudflare-go v0.49.0 // indirect
|
||||||
github.com/cpu/goacmedns v0.1.1 // indirect
|
github.com/cpu/goacmedns v0.1.1 // indirect
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
|
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/deepmap/oapi-codegen v1.9.1 // indirect
|
github.com/deepmap/oapi-codegen v1.9.1 // indirect
|
||||||
github.com/dgryski/go-metro v0.0.0-20211217172704-adc40b04c140 // 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/dimchansky/utfbom v1.1.1 // indirect
|
||||||
github.com/dnsimple/dnsimple-go v0.71.1 // indirect
|
github.com/dnsimple/dnsimple-go v0.71.1 // indirect
|
||||||
github.com/exoscale/egoscale v0.90.0 // indirect
|
github.com/exoscale/egoscale v0.90.0 // indirect
|
||||||
@@ -62,10 +72,12 @@ require (
|
|||||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||||
github.com/golang/mock v1.6.0 // indirect
|
github.com/golang/mock v1.6.0 // indirect
|
||||||
github.com/golang/protobuf v1.5.2 // indirect
|
github.com/golang/protobuf v1.5.2 // indirect
|
||||||
|
github.com/google/btree v1.1.2 // indirect
|
||||||
github.com/google/go-querystring v1.1.0 // indirect
|
github.com/google/go-querystring v1.1.0 // indirect
|
||||||
|
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 // indirect
|
||||||
github.com/google/uuid v1.3.0 // indirect
|
github.com/google/uuid v1.3.0 // indirect
|
||||||
github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa // indirect
|
github.com/googleapis/enterprise-certificate-proxy v0.2.0 // indirect
|
||||||
github.com/googleapis/gax-go/v2 v2.4.0 // indirect
|
github.com/googleapis/gax-go/v2 v2.6.0 // indirect
|
||||||
github.com/gophercloud/gophercloud v1.0.0 // indirect
|
github.com/gophercloud/gophercloud v1.0.0 // indirect
|
||||||
github.com/gophercloud/utils v0.0.0-20210216074907-f6de111f2eae // indirect
|
github.com/gophercloud/utils v0.0.0-20210216074907-f6de111f2eae // indirect
|
||||||
github.com/gorilla/websocket v1.5.0 // indirect
|
github.com/gorilla/websocket v1.5.0 // indirect
|
||||||
@@ -79,8 +91,8 @@ require (
|
|||||||
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||||
github.com/json-iterator/go v1.1.12 // indirect
|
github.com/json-iterator/go v1.1.12 // indirect
|
||||||
github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213 // indirect
|
github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213 // indirect
|
||||||
github.com/klauspost/compress v1.15.10 // indirect
|
github.com/klauspost/compress v1.15.12 // indirect
|
||||||
github.com/klauspost/cpuid/v2 v2.1.1 // indirect
|
github.com/klauspost/cpuid/v2 v2.2.1 // indirect
|
||||||
github.com/kolo/xmlrpc v0.0.0-20200310150728-e0350524596b // indirect
|
github.com/kolo/xmlrpc v0.0.0-20200310150728-e0350524596b // indirect
|
||||||
github.com/labbsr0x/bindman-dns-webhook v1.0.2 // indirect
|
github.com/labbsr0x/bindman-dns-webhook v1.0.2 // indirect
|
||||||
github.com/labbsr0x/goh v1.0.1 // indirect
|
github.com/labbsr0x/goh v1.0.1 // indirect
|
||||||
@@ -88,12 +100,13 @@ require (
|
|||||||
github.com/liquidweb/go-lwApi v0.0.5 // indirect
|
github.com/liquidweb/go-lwApi v0.0.5 // indirect
|
||||||
github.com/liquidweb/liquidweb-cli v0.6.9 // indirect
|
github.com/liquidweb/liquidweb-cli v0.6.9 // indirect
|
||||||
github.com/liquidweb/liquidweb-go v1.6.3 // indirect
|
github.com/liquidweb/liquidweb-go v1.6.3 // indirect
|
||||||
github.com/lucas-clemente/quic-go v0.29.0 // indirect
|
github.com/lucas-clemente/quic-go v0.31.0 // indirect
|
||||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
|
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
|
||||||
github.com/magiconair/properties v1.8.6 // indirect
|
github.com/magiconair/properties v1.8.6 // indirect
|
||||||
github.com/marten-seemann/qtls-go1-18 v0.1.2 // indirect
|
github.com/marten-seemann/qtls-go1-18 v0.1.3 // indirect
|
||||||
github.com/marten-seemann/qtls-go1-19 v0.1.0 // indirect
|
github.com/marten-seemann/qtls-go1-19 v0.1.1 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.16 // 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/miekg/dns v1.1.50 // indirect
|
||||||
github.com/mimuret/golang-iij-dpf v0.7.1 // indirect
|
github.com/mimuret/golang-iij-dpf v0.7.1 // indirect
|
||||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||||
@@ -108,11 +121,9 @@ require (
|
|||||||
github.com/nrdcg/goinwx v0.8.1 // indirect
|
github.com/nrdcg/goinwx v0.8.1 // indirect
|
||||||
github.com/nrdcg/namesilo v0.2.1 // indirect
|
github.com/nrdcg/namesilo v0.2.1 // indirect
|
||||||
github.com/nrdcg/porkbun v0.1.1 // indirect
|
github.com/nrdcg/porkbun v0.1.1 // indirect
|
||||||
github.com/nxadm/tail v1.4.8 // indirect
|
github.com/onsi/ginkgo/v2 v2.5.1 // indirect
|
||||||
github.com/onsi/ginkgo v1.16.5 // indirect
|
|
||||||
github.com/oracle/oci-go-sdk v24.3.0+incompatible // 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.1.0 // indirect
|
||||||
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
|
|
||||||
github.com/pelletier/go-toml v1.9.5 // indirect
|
github.com/pelletier/go-toml v1.9.5 // indirect
|
||||||
github.com/pelletier/go-toml/v2 v2.0.5 // indirect
|
github.com/pelletier/go-toml/v2 v2.0.5 // indirect
|
||||||
github.com/pires/go-proxyproto v0.6.2 // indirect
|
github.com/pires/go-proxyproto v0.6.2 // indirect
|
||||||
@@ -120,32 +131,33 @@ require (
|
|||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
|
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
|
||||||
github.com/pquerna/otp v1.3.0 // indirect
|
github.com/pquerna/otp v1.3.0 // indirect
|
||||||
github.com/rainycape/memcache v0.0.0-20150622160815-1031fa0ce2f2 // indirect
|
github.com/prometheus/client_golang v1.14.0 // indirect
|
||||||
github.com/refraction-networking/utls v1.1.2 // 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/refraction-networking/utls v1.2.0 // indirect
|
||||||
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 // indirect
|
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 // indirect
|
||||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
|
||||||
github.com/sacloud/api-client-go v0.2.1 // indirect
|
github.com/sacloud/api-client-go v0.2.1 // indirect
|
||||||
github.com/sacloud/go-http v0.1.2 // indirect
|
github.com/sacloud/go-http v0.1.2 // indirect
|
||||||
github.com/sacloud/iaas-api-go v1.3.2 // indirect
|
github.com/sacloud/iaas-api-go v1.3.2 // indirect
|
||||||
github.com/sacloud/packages-go v0.0.5 // indirect
|
github.com/sacloud/packages-go v0.0.5 // indirect
|
||||||
github.com/sagernet/sing v0.0.0-20220801112236-1bb95f9661fc // indirect
|
github.com/sagernet/wireguard-go v0.0.0-20221116151939-c99467f53f2c // indirect
|
||||||
github.com/sagernet/sing-shadowsocks v0.0.0-20220801112336-a91eacdd01e1 // indirect
|
|
||||||
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.9 // 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/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb // indirect
|
||||||
github.com/sirupsen/logrus v1.8.1 // indirect
|
github.com/sirupsen/logrus v1.8.1 // indirect
|
||||||
github.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9 // 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.0.6 // indirect
|
||||||
github.com/softlayer/xmlrpc v0.0.0-20200409220501-5f089df7cb7e // indirect
|
github.com/softlayer/xmlrpc v0.0.0-20200409220501-5f089df7cb7e // indirect
|
||||||
github.com/spf13/afero v1.8.2 // indirect
|
github.com/spf13/afero v1.9.2 // indirect
|
||||||
github.com/spf13/cast v1.5.0 // indirect
|
github.com/spf13/cast v1.5.0 // indirect
|
||||||
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
||||||
github.com/spf13/pflag v1.0.5 // indirect
|
github.com/spf13/pflag v1.0.5 // indirect
|
||||||
github.com/stretchr/objx v0.4.0 // indirect
|
github.com/stretchr/objx v0.5.0 // indirect
|
||||||
github.com/subosito/gotenv v1.4.1 // indirect
|
github.com/subosito/gotenv v1.4.1 // indirect
|
||||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.490 // 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/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.490 // indirect
|
||||||
github.com/tklauser/go-sysconf v0.3.10 // indirect
|
github.com/tklauser/go-sysconf v0.3.11 // indirect
|
||||||
github.com/tklauser/numcpus v0.4.0 // indirect
|
github.com/tklauser/numcpus v0.6.0 // indirect
|
||||||
github.com/transip/gotransip/v6 v6.17.0 // indirect
|
github.com/transip/gotransip/v6 v6.17.0 // indirect
|
||||||
github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e // indirect
|
github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e // indirect
|
||||||
github.com/vinyldns/go-vinyldns v0.9.16 // indirect
|
github.com/vinyldns/go-vinyldns v0.9.16 // indirect
|
||||||
@@ -156,24 +168,24 @@ require (
|
|||||||
github.com/yandex-cloud/go-sdk v0.0.0-20220805164847-cf028e604997 // indirect
|
github.com/yandex-cloud/go-sdk v0.0.0-20220805164847-cf028e604997 // indirect
|
||||||
github.com/yusufpapurcu/wmi v1.2.2 // indirect
|
github.com/yusufpapurcu/wmi v1.2.2 // indirect
|
||||||
go.opencensus.io v0.23.0 // indirect
|
go.opencensus.io v0.23.0 // indirect
|
||||||
go.starlark.net v0.0.0-20220817180228-f738f5508c12 // indirect
|
go.starlark.net v0.0.0-20221028183056-acb66ad56dd2 // indirect
|
||||||
|
go.uber.org/atomic v1.10.0 // indirect
|
||||||
go.uber.org/ratelimit v0.2.0 // indirect
|
go.uber.org/ratelimit v0.2.0 // indirect
|
||||||
golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90 // indirect
|
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db // indirect
|
||||||
golang.org/x/exp v0.0.0-20220916125017-b168a2c6b86b // indirect
|
golang.org/x/mod v0.7.0 // indirect
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
|
golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783 // indirect
|
||||||
golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1 // indirect
|
golang.org/x/sys v0.3.0 // indirect
|
||||||
golang.org/x/sys v0.0.0-20220915200043-7b5979e65e41 // indirect
|
golang.org/x/text v0.5.0 // indirect
|
||||||
golang.org/x/text v0.3.7 // indirect
|
golang.org/x/tools v0.3.0 // indirect
|
||||||
golang.org/x/tools v0.1.12 // indirect
|
google.golang.org/api v0.102.0 // indirect
|
||||||
google.golang.org/api v0.84.0 // indirect
|
|
||||||
google.golang.org/appengine v1.6.7 // indirect
|
google.golang.org/appengine v1.6.7 // indirect
|
||||||
google.golang.org/genproto v0.0.0-20220916172020-2692e8806bfa // indirect
|
google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6 // indirect
|
||||||
google.golang.org/grpc v1.49.0 // indirect
|
google.golang.org/grpc v1.51.0 // indirect
|
||||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||||
gopkg.in/ns1/ns1-go.v2 v2.6.5 // indirect
|
gopkg.in/ns1/ns1-go.v2 v2.6.5 // indirect
|
||||||
gopkg.in/square/go-jose.v2 v2.6.0 // indirect
|
gopkg.in/square/go-jose.v2 v2.6.0 // indirect
|
||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
|
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // 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
|
lukechampine.com/blake3 v1.1.7 // indirect
|
||||||
)
|
)
|
||||||
|
389
go.sum
389
go.sum
@@ -19,36 +19,21 @@ cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHOb
|
|||||||
cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI=
|
cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI=
|
||||||
cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk=
|
cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk=
|
||||||
cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY=
|
cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY=
|
||||||
cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg=
|
cloud.google.com/go v0.105.0 h1:DNtEKRBAAzeS4KyIory52wWHuClNaXJ5x1F7xa4q+5Y=
|
||||||
cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8=
|
|
||||||
cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0=
|
|
||||||
cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY=
|
|
||||||
cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM=
|
|
||||||
cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY=
|
|
||||||
cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ=
|
|
||||||
cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI=
|
|
||||||
cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4=
|
|
||||||
cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc=
|
|
||||||
cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA=
|
|
||||||
cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A=
|
|
||||||
cloud.google.com/go v0.102.0/go.mod h1:oWcCzKlqJ5zgHQt9YsaeTY9KzIvjyy0ArmiBUgpQ+nc=
|
|
||||||
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
|
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
|
||||||
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
|
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
|
||||||
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
|
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
|
||||||
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
|
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
|
||||||
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
|
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
|
||||||
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
|
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
|
||||||
cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow=
|
cloud.google.com/go/compute v1.12.1 h1:gKVJMEyqV5c/UnpzjjQbo3Rjvvqpr9B1DFSbJC4OXr0=
|
||||||
cloud.google.com/go/compute v1.3.0/go.mod h1:cCZiE1NHEtai4wiufUhW8I8S1JKkAnhnQJWM7YD99wM=
|
cloud.google.com/go/compute v1.12.1/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x/6PIIOocU=
|
||||||
cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6mkzQJeu0M=
|
cloud.google.com/go/compute/metadata v0.2.1 h1:efOwf5ymceDhK6PKMnnrTHP4pppY5L22mle96M1yP48=
|
||||||
cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz/FMzPu0s=
|
cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM=
|
||||||
cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU=
|
|
||||||
cloud.google.com/go/compute v1.7.0 h1:v/k9Eueb8aAJ0vZuxKMrgm6kPhCLZU9HxFU+AFDs9Uk=
|
|
||||||
cloud.google.com/go/compute v1.7.0/go.mod h1:435lt8av5oL9P3fv1OEzSbSUe+ybHXGMPQHHZWZxy9U=
|
|
||||||
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
|
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
|
||||||
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
|
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
|
||||||
cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
|
cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
|
||||||
cloud.google.com/go/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp4bnY=
|
cloud.google.com/go/longrunning v0.3.0 h1:NjljC+FYPV3uh5/OwWT6pVU+doBqMg2x/rZlE+CamDs=
|
||||||
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
|
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
|
||||||
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
|
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
|
||||||
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
|
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
|
||||||
@@ -59,7 +44,6 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl
|
|||||||
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
|
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
|
||||||
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
|
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
|
||||||
cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo=
|
cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo=
|
||||||
cloud.google.com/go/storage v1.22.1/go.mod h1:S8N1cAStu7BOeFfE8KAQzmyyLkK8p/vmRq6kuBTW58Y=
|
|
||||||
dmitri.shuralyov.com/app/changes v0.0.0-20180602232624-0a106ad413e3/go.mod h1:Yl+fi1br7+Rr3LqpNJf1/uxUdtRUV+Tnj0o93V2B9MU=
|
dmitri.shuralyov.com/app/changes v0.0.0-20180602232624-0a106ad413e3/go.mod h1:Yl+fi1br7+Rr3LqpNJf1/uxUdtRUV+Tnj0o93V2B9MU=
|
||||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||||
dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBrvjyP0v+ecvNYvCpyZgu5/xkfAUhi6wJj28eUfSU=
|
dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBrvjyP0v+ecvNYvCpyZgu5/xkfAUhi6wJj28eUfSU=
|
||||||
@@ -98,7 +82,10 @@ github.com/OpenDNS/vegadns2client v0.0.0-20180418235048-a3fa4a771d87/go.mod h1:i
|
|||||||
github.com/akamai/AkamaiOPEN-edgegrid-golang v1.2.1 h1:5BIsppVPdWJA29Yb5cYawQYeh5geN413WxAgBZvEtdA=
|
github.com/akamai/AkamaiOPEN-edgegrid-golang v1.2.1 h1:5BIsppVPdWJA29Yb5cYawQYeh5geN413WxAgBZvEtdA=
|
||||||
github.com/akamai/AkamaiOPEN-edgegrid-golang v1.2.1/go.mod h1:kX6YddBkXqqywAe8c9LyvgTCyFuZCTMF4cRPQhc3Fy8=
|
github.com/akamai/AkamaiOPEN-edgegrid-golang v1.2.1/go.mod h1:kX6YddBkXqqywAe8c9LyvgTCyFuZCTMF4cRPQhc3Fy8=
|
||||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||||
|
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||||
|
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||||
|
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
|
||||||
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1755 h1:J45/QHgrzUdqe/Vco/Vxk0wRvdS2nKUxmf/zLgvfass=
|
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1755 h1:J45/QHgrzUdqe/Vco/Vxk0wRvdS2nKUxmf/zLgvfass=
|
||||||
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1755/go.mod h1:RcDobYh8k5VP6TNybz9m++gL3ijVI5wueVr0EM10VsU=
|
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1755/go.mod h1:RcDobYh8k5VP6TNybz9m++gL3ijVI5wueVr0EM10VsU=
|
||||||
github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129 h1:MzBOUgng9orim59UnfUTLRjMpd09C5uEVQ6RPGeCaVI=
|
github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129 h1:MzBOUgng9orim59UnfUTLRjMpd09C5uEVQ6RPGeCaVI=
|
||||||
@@ -114,6 +101,7 @@ github.com/aws/aws-sdk-go v1.39.0 h1:74BBwkEmiqBbi2CGflEh34l0YNtIibTjZsibGarkNjo
|
|||||||
github.com/aws/aws-sdk-go v1.39.0/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
|
github.com/aws/aws-sdk-go v1.39.0/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
|
||||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||||
|
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||||
github.com/bitly/go-simplejson v0.5.0 h1:6IH+V8/tVMab511d5bn4M7EwGXZf9Hj6i2xSwkNEM+Y=
|
github.com/bitly/go-simplejson v0.5.0 h1:6IH+V8/tVMab511d5bn4M7EwGXZf9Hj6i2xSwkNEM+Y=
|
||||||
@@ -132,6 +120,9 @@ github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInq
|
|||||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
|
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
|
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
|
||||||
|
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||||
@@ -143,12 +134,8 @@ github.com/cloudflare/cloudflare-go v0.49.0/go.mod h1:h0QgcIZ3qEXwFiwfBO8sQxjVdY
|
|||||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||||
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||||
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||||
github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
|
|
||||||
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||||
github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||||
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
|
||||||
github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
|
||||||
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
|
||||||
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
||||||
github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||||
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||||
@@ -157,10 +144,7 @@ github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7
|
|||||||
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||||
github.com/cpu/goacmedns v0.1.1 h1:DM3H2NiN2oam7QljgGY5ygy4yDXhK5Z4JUnqaugs2C4=
|
github.com/cpu/goacmedns v0.1.1 h1:DM3H2NiN2oam7QljgGY5ygy4yDXhK5Z4JUnqaugs2C4=
|
||||||
github.com/cpu/goacmedns v0.1.1/go.mod h1:MuaouqEhPAHxsbqjgnck5zeghuwBP1dLnPoobeGqugQ=
|
github.com/cpu/goacmedns v0.1.1/go.mod h1:MuaouqEhPAHxsbqjgnck5zeghuwBP1dLnPoobeGqugQ=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
|
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
|
||||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||||
github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4=
|
github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
@@ -176,21 +160,27 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZm
|
|||||||
github.com/dgryski/go-metro v0.0.0-20200812162917-85c65e2d0165/go.mod h1:c9O8+fpSOX1DM8cPNSkX/qsBWdkD4yd2dpciOWQjpBw=
|
github.com/dgryski/go-metro v0.0.0-20200812162917-85c65e2d0165/go.mod h1:c9O8+fpSOX1DM8cPNSkX/qsBWdkD4yd2dpciOWQjpBw=
|
||||||
github.com/dgryski/go-metro v0.0.0-20211217172704-adc40b04c140 h1:y7y0Oa6UawqTFPCDw9JG6pdKt4F9pAhHv0B7FMGaGD0=
|
github.com/dgryski/go-metro v0.0.0-20211217172704-adc40b04c140 h1:y7y0Oa6UawqTFPCDw9JG6pdKt4F9pAhHv0B7FMGaGD0=
|
||||||
github.com/dgryski/go-metro v0.0.0-20211217172704-adc40b04c140/go.mod h1:c9O8+fpSOX1DM8cPNSkX/qsBWdkD4yd2dpciOWQjpBw=
|
github.com/dgryski/go-metro v0.0.0-20211217172704-adc40b04c140/go.mod h1:c9O8+fpSOX1DM8cPNSkX/qsBWdkD4yd2dpciOWQjpBw=
|
||||||
|
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
|
||||||
|
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
||||||
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
||||||
github.com/dimchansky/utfbom v1.1.1 h1:vV6w1AhK4VMnhBno/TPVCoK9U/LP0PkLCS9tbxHdi/U=
|
github.com/dimchansky/utfbom v1.1.1 h1:vV6w1AhK4VMnhBno/TPVCoK9U/LP0PkLCS9tbxHdi/U=
|
||||||
github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE=
|
github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE=
|
||||||
github.com/dnsimple/dnsimple-go v0.71.1 h1:1hGoBA3CIjpjZj5DM3081xfxr4e2jYmYnkO2VuBF8Qc=
|
github.com/dnsimple/dnsimple-go v0.71.1 h1:1hGoBA3CIjpjZj5DM3081xfxr4e2jYmYnkO2VuBF8Qc=
|
||||||
github.com/dnsimple/dnsimple-go v0.71.1/go.mod h1:F9WHww9cC76hrnwGFfAfrqdW99j3MOYasQcIwTS/aUk=
|
github.com/dnsimple/dnsimple-go v0.71.1/go.mod h1:F9WHww9cC76hrnwGFfAfrqdW99j3MOYasQcIwTS/aUk=
|
||||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||||
|
github.com/eko/gocache/lib/v4 v4.1.2 h1:cX54GhJJsfc5jvCEaPW8595h9Pq6bbNfkv0o/669Tw4=
|
||||||
|
github.com/eko/gocache/lib/v4 v4.1.2/go.mod h1:FqyrANKct257VFHVVs11m6V2syGobOmHycQCyRSMwu0=
|
||||||
|
github.com/eko/gocache/store/go_cache/v4 v4.1.2 h1:tRp+DQ8HOKGgCySXp1HFgeYC8+LyAyV+j9xig6IYz2A=
|
||||||
|
github.com/eko/gocache/store/go_cache/v4 v4.1.2/go.mod h1:aSHMK36ERJXhVvwXS+ulWZWuuqGoiSf54Z3zwIjHeT8=
|
||||||
|
github.com/eko/gocache/store/redis/v4 v4.1.2 h1:PtpjQu8Q698kpC3H06As5As15s+hJofV8NtkddVX5aQ=
|
||||||
|
github.com/eko/gocache/store/redis/v4 v4.1.2/go.mod h1:P2HeqvNwqkdwajYro+qwBWquhdYpN0LgfH2rJ3jK7yg=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
|
github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
|
||||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
|
github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
|
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
|
||||||
github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE=
|
|
||||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||||
github.com/exoscale/egoscale v0.90.0 h1:DZBXVU3iHqu5Ju5lQ5jWVlPo0IpI98SUo8Aa1UQVrmo=
|
github.com/exoscale/egoscale v0.90.0 h1:DZBXVU3iHqu5Ju5lQ5jWVlPo0IpI98SUo8Aa1UQVrmo=
|
||||||
github.com/exoscale/egoscale v0.90.0/go.mod h1:wyXE5zrnFynMXA0jMhwQqSe24CfUhmBk2WI5wFZcq6Y=
|
github.com/exoscale/egoscale v0.90.0/go.mod h1:wyXE5zrnFynMXA0jMhwQqSe24CfUhmBk2WI5wFZcq6Y=
|
||||||
@@ -214,8 +204,8 @@ github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32/go.mod h1:GIjDIg/heH
|
|||||||
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||||
github.com/gin-gonic/gin v1.7.4/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY=
|
github.com/gin-gonic/gin v1.7.4/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY=
|
||||||
github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
|
github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
|
||||||
github.com/go-acme/lego/v4 v4.9.0 h1:8Hjj44IqRS7cigshMyFQ+0pIZvwgkG/+9A0UnNh7G8A=
|
github.com/go-acme/lego/v4 v4.9.1 h1:n9Z5MQwANeGSQKlVE3bEh9SDvAySK9oVYOKCGCESqQE=
|
||||||
github.com/go-acme/lego/v4 v4.9.0/go.mod h1:g3JRUyWS3L/VObpp4bCxzJftKyf/Wba8QrSSnoiqjg4=
|
github.com/go-acme/lego/v4 v4.9.1/go.mod h1:g3JRUyWS3L/VObpp4bCxzJftKyf/Wba8QrSSnoiqjg4=
|
||||||
github.com/go-chi/chi/v5 v5.0.0/go.mod h1:BBug9lr0cqtdAhsu6R4AAdvufI0/XBzAQSsUqJpoZOs=
|
github.com/go-chi/chi/v5 v5.0.0/go.mod h1:BBug9lr0cqtdAhsu6R4AAdvufI0/XBzAQSsUqJpoZOs=
|
||||||
github.com/go-cmd/cmd v1.0.5/go.mod h1:y8q8qlK5wQibcw63djSl/ntiHUHXHGdCkPk0j4QeW4s=
|
github.com/go-cmd/cmd v1.0.5/go.mod h1:y8q8qlK5wQibcw63djSl/ntiHUHXHGdCkPk0j4QeW4s=
|
||||||
github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w=
|
github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w=
|
||||||
@@ -224,8 +214,14 @@ github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9
|
|||||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||||
|
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||||
|
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
|
||||||
|
github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0=
|
||||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||||
|
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
|
||||||
|
github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
|
||||||
|
github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=
|
||||||
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
|
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
|
||||||
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||||
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
||||||
@@ -237,6 +233,8 @@ github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+
|
|||||||
github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=
|
github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=
|
||||||
github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
|
github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
|
||||||
github.com/go-playground/validator/v10 v10.9.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos=
|
github.com/go-playground/validator/v10 v10.9.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos=
|
||||||
|
github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
|
||||||
|
github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
|
||||||
github.com/go-resty/resty/v2 v2.7.0 h1:me+K9p3uhSmXtrBZ4k9jcEAfJmuC8IivWHwaLZwPrFY=
|
github.com/go-resty/resty/v2 v2.7.0 h1:me+K9p3uhSmXtrBZ4k9jcEAfJmuC8IivWHwaLZwPrFY=
|
||||||
github.com/go-resty/resty/v2 v2.7.0/go.mod h1:9PWDzw47qPphMRFfhsyk0NnSgvluHcljSMVIq3w7q0I=
|
github.com/go-resty/resty/v2 v2.7.0/go.mod h1:9PWDzw47qPphMRFfhsyk0NnSgvluHcljSMVIq3w7q0I=
|
||||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||||
@@ -268,7 +266,6 @@ github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt
|
|||||||
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||||
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||||
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
|
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
|
||||||
github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8=
|
|
||||||
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
|
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
|
||||||
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
|
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
|
||||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
@@ -286,13 +283,13 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD
|
|||||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||||
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||||
github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM=
|
|
||||||
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
||||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||||
github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
|
||||||
github.com/golangci/lint-1 v0.0.0-20181222135242-d2cdd8c08219/go.mod h1:/X8TswGSh1pIozq4ZwCfxS0WA5JGXguxk94ar/4c87Y=
|
github.com/golangci/lint-1 v0.0.0-20181222135242-d2cdd8c08219/go.mod h1:/X8TswGSh1pIozq4ZwCfxS0WA5JGXguxk94ar/4c87Y=
|
||||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||||
|
github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU=
|
||||||
|
github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
|
||||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
@@ -306,7 +303,6 @@ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
|||||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
|
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
|
||||||
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
|
||||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
|
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
|
||||||
@@ -318,7 +314,6 @@ github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/
|
|||||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||||
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||||
github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||||
github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk=
|
|
||||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||||
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||||
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||||
@@ -329,30 +324,22 @@ github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hf
|
|||||||
github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||||
github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||||
github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||||
github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
|
||||||
github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
|
||||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||||
github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ=
|
||||||
github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo=
|
||||||
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
|
||||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa h1:7MYGT2XEMam7Mtzv1yDUYXANedWvwk3HKkR3MyGowy8=
|
github.com/googleapis/enterprise-certificate-proxy v0.2.0 h1:y8Yozv7SZtlU//QXbezB6QkpuE6jMD2/gfzk4AftXjs=
|
||||||
github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8=
|
github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg=
|
||||||
github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
|
github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
|
||||||
github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg=
|
github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg=
|
||||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||||
github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0=
|
github.com/googleapis/gax-go/v2 v2.6.0 h1:SXk3ABtQYDT/OH8jAyvEOQ58mgawq5C4o/4/89qN2ZU=
|
||||||
github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM=
|
github.com/googleapis/gax-go/v2 v2.6.0/go.mod h1:1mjbznJAPHFpesgE5ucqfYEscaz5kMdcIDwU/6+DDoY=
|
||||||
github.com/googleapis/gax-go/v2 v2.2.0/go.mod h1:as02EH8zWkzwUoLbBaFeQ+arQaj/OthfcblKl4IGNaM=
|
|
||||||
github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99EXz9pXxye9YM=
|
|
||||||
github.com/googleapis/gax-go/v2 v2.4.0 h1:dS9eYAjhrE2RjmzYw2XAPvcXfmcQLtFEQWn0CR82awk=
|
|
||||||
github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c=
|
|
||||||
github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4=
|
|
||||||
github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
|
github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
|
||||||
github.com/gophercloud/gophercloud v0.15.1-0.20210202035223-633d73521055/go.mod h1:wRtmUelyIIv3CSSDI47aUwbs075O6i+LY+pXsKCBsb4=
|
github.com/gophercloud/gophercloud v0.15.1-0.20210202035223-633d73521055/go.mod h1:wRtmUelyIIv3CSSDI47aUwbs075O6i+LY+pXsKCBsb4=
|
||||||
github.com/gophercloud/gophercloud v1.0.0 h1:9nTGx0jizmHxDobe4mck89FyQHVyA3CaXLIUSGJjP9k=
|
github.com/gophercloud/gophercloud v1.0.0 h1:9nTGx0jizmHxDobe4mck89FyQHVyA3CaXLIUSGJjP9k=
|
||||||
@@ -425,35 +412,39 @@ github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHW
|
|||||||
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
|
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
|
||||||
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
|
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
|
||||||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||||
|
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
|
||||||
github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||||
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||||
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||||
|
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||||
|
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||||
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
|
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
|
||||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||||
|
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
|
||||||
github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213 h1:qGQQKEcAR99REcMpsXCp3lJ03zYT1PkRd3kQGPn9GVg=
|
github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213 h1:qGQQKEcAR99REcMpsXCp3lJ03zYT1PkRd3kQGPn9GVg=
|
||||||
github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213/go.mod h1:vNUNkEQ1e29fT/6vq2aBdFsgNPmy8qMdSay1npru+Sw=
|
github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213/go.mod h1:vNUNkEQ1e29fT/6vq2aBdFsgNPmy8qMdSay1npru+Sw=
|
||||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||||
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
github.com/klauspost/compress v1.15.12 h1:YClS/PImqYbn+UILDnqxQCZ3RehC9N318SU3kElDUEM=
|
||||||
github.com/klauspost/compress v1.15.10 h1:Ai8UzuomSCDw90e1qNMtb15msBXsNpH6gzkkENQNcJo=
|
github.com/klauspost/compress v1.15.12/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM=
|
||||||
github.com/klauspost/compress v1.15.10/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM=
|
|
||||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||||
github.com/klauspost/cpuid/v2 v2.1.1 h1:t0wUqjowdm8ezddV5k0tLWVklVuvLJpoHeb4WBdydm0=
|
github.com/klauspost/cpuid/v2 v2.2.1 h1:U33DW0aiEj633gHYw3LoDNfkDiYnE5Q8M/TKJn2f2jI=
|
||||||
github.com/klauspost/cpuid/v2 v2.1.1/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
|
github.com/klauspost/cpuid/v2 v2.2.1/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
|
||||||
github.com/kolo/xmlrpc v0.0.0-20200310150728-e0350524596b h1:DzHy0GlWeF0KAglaTMY7Q+khIFoG8toHP+wLFBVBQJc=
|
github.com/kolo/xmlrpc v0.0.0-20200310150728-e0350524596b h1:DzHy0GlWeF0KAglaTMY7Q+khIFoG8toHP+wLFBVBQJc=
|
||||||
github.com/kolo/xmlrpc v0.0.0-20200310150728-e0350524596b/go.mod h1:o03bZfuBwAXHetKXuInt4S7omeXUu62/A845kiycsSQ=
|
github.com/kolo/xmlrpc v0.0.0-20200310150728-e0350524596b/go.mod h1:o03bZfuBwAXHetKXuInt4S7omeXUu62/A845kiycsSQ=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
|
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
||||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||||
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
|
|
||||||
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
|
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
|
||||||
|
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
@@ -483,8 +474,8 @@ github.com/liquidweb/liquidweb-cli v0.6.9 h1:acbIvdRauiwbxIsOCEMXGwF75aSJDbDiyAW
|
|||||||
github.com/liquidweb/liquidweb-cli v0.6.9/go.mod h1:cE1uvQ+x24NGUL75D0QagOFCG8Wdvmwu8aL9TLmA/eQ=
|
github.com/liquidweb/liquidweb-cli v0.6.9/go.mod h1:cE1uvQ+x24NGUL75D0QagOFCG8Wdvmwu8aL9TLmA/eQ=
|
||||||
github.com/liquidweb/liquidweb-go v1.6.3 h1:NVHvcnX3eb3BltiIoA+gLYn15nOpkYkdizOEYGSKrk4=
|
github.com/liquidweb/liquidweb-go v1.6.3 h1:NVHvcnX3eb3BltiIoA+gLYn15nOpkYkdizOEYGSKrk4=
|
||||||
github.com/liquidweb/liquidweb-go v1.6.3/go.mod h1:SuXXp+thr28LnjEw18AYtWwIbWMHSUiajPQs8T9c/Rc=
|
github.com/liquidweb/liquidweb-go v1.6.3/go.mod h1:SuXXp+thr28LnjEw18AYtWwIbWMHSUiajPQs8T9c/Rc=
|
||||||
github.com/lucas-clemente/quic-go v0.29.0 h1:Vw0mGTfmWqGzh4jx/kMymsIkFK6rErFVmg+t9RLrnZE=
|
github.com/lucas-clemente/quic-go v0.31.0 h1:MfNp3fk0wjWRajw6quMFA3ap1AVtlU+2mtwmbVogB2M=
|
||||||
github.com/lucas-clemente/quic-go v0.29.0/go.mod h1:CTcNfLYJS2UuRNB+zcNlgvkjBhxX6Hm3WUxxAQx2mgE=
|
github.com/lucas-clemente/quic-go v0.31.0/go.mod h1:0wFbizLgYzqHqtlyxyCaJKlE7bYgE6JQ+54TLd/Dq2g=
|
||||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
|
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
|
||||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
|
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
|
||||||
github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
|
github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
|
||||||
@@ -495,10 +486,10 @@ github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPK
|
|||||||
github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||||
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||||
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||||
github.com/marten-seemann/qtls-go1-18 v0.1.2 h1:JH6jmzbduz0ITVQ7ShevK10Av5+jBEKAHMntXmIV7kM=
|
github.com/marten-seemann/qtls-go1-18 v0.1.3 h1:R4H2Ks8P6pAtUagjFty2p7BVHn3XiwDAl7TTQf5h7TI=
|
||||||
github.com/marten-seemann/qtls-go1-18 v0.1.2/go.mod h1:mJttiymBAByA49mhlNZZGrH5u1uXYZJ+RW28Py7f4m4=
|
github.com/marten-seemann/qtls-go1-18 v0.1.3/go.mod h1:mJttiymBAByA49mhlNZZGrH5u1uXYZJ+RW28Py7f4m4=
|
||||||
github.com/marten-seemann/qtls-go1-19 v0.1.0 h1:rLFKD/9mp/uq1SYGYuVZhm83wkmU95pK5df3GufyYYU=
|
github.com/marten-seemann/qtls-go1-19 v0.1.1 h1:mnbxeq3oEyQxQXwI4ReCgW9DPoPR94sNlqWoDZnjRIE=
|
||||||
github.com/marten-seemann/qtls-go1-19 v0.1.0/go.mod h1:5HTDWtVudo/WFsHKRNuOhWlbdjrfs5JHrYb0wIJqGpI=
|
github.com/marten-seemann/qtls-go1-19 v0.1.1/go.mod h1:5HTDWtVudo/WFsHKRNuOhWlbdjrfs5JHrYb0wIJqGpI=
|
||||||
github.com/matryer/moq v0.0.0-20190312154309-6cfb0558e1bd/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ=
|
github.com/matryer/moq v0.0.0-20190312154309-6cfb0558e1bd/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ=
|
||||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||||
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||||
@@ -516,6 +507,7 @@ github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/
|
|||||||
github.com/mattn/go-runewidth v0.0.6/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
github.com/mattn/go-runewidth v0.0.6/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||||
github.com/mattn/go-tty v0.0.3/go.mod h1:ihxohKRERHTVzN+aSVRwACLCeqIoZAWpoICkkvrWyR0=
|
github.com/mattn/go-tty v0.0.3/go.mod h1:ihxohKRERHTVzN+aSVRwACLCeqIoZAWpoICkkvrWyR0=
|
||||||
|
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||||
github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4=
|
github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4=
|
||||||
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||||
@@ -545,6 +537,7 @@ github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3Rllmb
|
|||||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||||
|
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||||
github.com/namedotcom/go v0.0.0-20180403034216-08470befbe04 h1:o6uBwrhM5C8Ll3MAAxrQxRHEu7FkapwTuI2WmL1rw4g=
|
github.com/namedotcom/go v0.0.0-20180403034216-08470befbe04 h1:o6uBwrhM5C8Ll3MAAxrQxRHEu7FkapwTuI2WmL1rw4g=
|
||||||
github.com/namedotcom/go v0.0.0-20180403034216-08470befbe04/go.mod h1:5sN+Lt1CaY4wsPvgQH/jsuJi4XO2ssZbdsIizr4CVC8=
|
github.com/namedotcom/go v0.0.0-20180403034216-08470befbe04/go.mod h1:5sN+Lt1CaY4wsPvgQH/jsuJi4XO2ssZbdsIizr4CVC8=
|
||||||
github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms=
|
github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms=
|
||||||
@@ -573,15 +566,16 @@ github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W
|
|||||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
||||||
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
|
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
|
||||||
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
|
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
|
||||||
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
|
|
||||||
github.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
|
github.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
|
||||||
github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
|
github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
|
||||||
|
github.com/onsi/ginkgo/v2 v2.5.1 h1:auzK7OI497k6x4OvWq+TKAcpcSAlod0doAH72oIN0Jw=
|
||||||
|
github.com/onsi/ginkgo/v2 v2.5.1/go.mod h1:63DOGlLAH8+REH8jUGdL3YpCpu7JODesutUjdENfUAc=
|
||||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||||
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
|
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
|
||||||
github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs=
|
github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs=
|
||||||
github.com/onsi/gomega v1.19.0 h1:4ieX6qQjPP/BfC3mpsAtIGGlxTWPeA3Inl/7DtXw1tw=
|
|
||||||
github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro=
|
github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro=
|
||||||
|
github.com/onsi/gomega v1.24.0 h1:+0glovB9Jd6z3VR+ScSwQqXVTIfJcGA9UBM8yzQxhqg=
|
||||||
github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
|
github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
|
||||||
github.com/oracle/oci-go-sdk v24.3.0+incompatible h1:x4mcfb4agelf1O4/1/auGlZ1lr97jXRSSN5MxTgG/zU=
|
github.com/oracle/oci-go-sdk v24.3.0+incompatible h1:x4mcfb4agelf1O4/1/auGlZ1lr97jXRSSN5MxTgG/zU=
|
||||||
github.com/oracle/oci-go-sdk v24.3.0+incompatible/go.mod h1:VQb79nF8Z2cwLkLS35ukwStZIg5F66tcBccjip/j888=
|
github.com/oracle/oci-go-sdk v24.3.0+incompatible/go.mod h1:VQb79nF8Z2cwLkLS35ukwStZIg5F66tcBccjip/j888=
|
||||||
@@ -618,26 +612,42 @@ github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXP
|
|||||||
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
|
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
|
||||||
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
||||||
github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g=
|
github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g=
|
||||||
|
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
|
||||||
|
github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
|
||||||
|
github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
|
||||||
|
github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw=
|
||||||
|
github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y=
|
||||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
|
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
|
github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4=
|
||||||
|
github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w=
|
||||||
github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||||
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||||
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||||
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||||
github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc=
|
github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc=
|
||||||
|
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
|
||||||
|
github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
|
||||||
|
github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
|
||||||
|
github.com/prometheus/common v0.37.0 h1:ccBbHCgIiT9uSoFY0vX8H3zsNR5eLt17/RQLUvn8pXE=
|
||||||
|
github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA=
|
||||||
github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||||
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||||
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||||
github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
|
github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
|
||||||
|
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
||||||
|
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
||||||
|
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
||||||
|
github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo=
|
||||||
|
github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4=
|
||||||
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||||
github.com/r3labs/diff/v2 v2.15.1 h1:EOrVqPUzi+njlumoqJwiS/TgGgmZo83619FNDB9xQUg=
|
github.com/r3labs/diff/v2 v2.15.1 h1:EOrVqPUzi+njlumoqJwiS/TgGgmZo83619FNDB9xQUg=
|
||||||
github.com/r3labs/diff/v2 v2.15.1/go.mod h1:I8noH9Fc2fjSaMxqF3G2lhDdC0b+JXCfyx85tWFM9kc=
|
github.com/r3labs/diff/v2 v2.15.1/go.mod h1:I8noH9Fc2fjSaMxqF3G2lhDdC0b+JXCfyx85tWFM9kc=
|
||||||
github.com/rainycape/memcache v0.0.0-20150622160815-1031fa0ce2f2 h1:dq90+d51/hQRaHEqRAsQ1rE/pC1GUS4sc2rCbbFsAIY=
|
github.com/refraction-networking/utls v1.2.0 h1:U5f8wkij2NVinfLuJdFP3gCMwIHs+EzvhxmYdXgiapo=
|
||||||
github.com/rainycape/memcache v0.0.0-20150622160815-1031fa0ce2f2/go.mod h1:7tZKcyumwBO6qip7RNQ5r77yrssm9bfCowcLEBcU5IA=
|
github.com/refraction-networking/utls v1.2.0/go.mod h1:NPq+cVqzH7D1BeOkmOcb5O/8iVewAsiVt2x1/eO0hgQ=
|
||||||
github.com/refraction-networking/utls v1.1.2 h1:a7GQauRt72VG+wtNm0lnrAaCGlyX47gEi1++dSsDBpw=
|
|
||||||
github.com/refraction-networking/utls v1.1.2/go.mod h1:+D89TUtA8+NKVFj1IXWr0p3tSdX1+SqUB7rL0QnGqyg=
|
|
||||||
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 h1:f/FNXud6gA3MNr8meMVVGxhp+QBTqY91tM8HjEuMjGg=
|
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 h1:f/FNXud6gA3MNr8meMVVGxhp+QBTqY91tM8HjEuMjGg=
|
||||||
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3/go.mod h1:HgjTstvQsPGkxUsCd2KWxErBblirPizecHcpD3ffK+s=
|
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3/go.mod h1:HgjTstvQsPGkxUsCd2KWxErBblirPizecHcpD3ffK+s=
|
||||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||||
@@ -648,8 +658,6 @@ github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6po
|
|||||||
github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg=
|
github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg=
|
||||||
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
||||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
|
||||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
|
||||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||||
github.com/sacloud/api-client-go v0.2.1 h1:jl02ZG6cM+mcH4eDYg0cxCFFuTOVTOjUCLYL4UbP09U=
|
github.com/sacloud/api-client-go v0.2.1 h1:jl02ZG6cM+mcH4eDYg0cxCFFuTOVTOjUCLYL4UbP09U=
|
||||||
github.com/sacloud/api-client-go v0.2.1/go.mod h1:8fmYy5OpT3W8ltV5ZxF8evultNwKpduGN4YKmU9Af7w=
|
github.com/sacloud/api-client-go v0.2.1/go.mod h1:8fmYy5OpT3W8ltV5ZxF8evultNwKpduGN4YKmU9Af7w=
|
||||||
@@ -659,18 +667,20 @@ github.com/sacloud/iaas-api-go v1.3.2 h1:03obrdVdv/bGHK9p6CV7Uzg+ot2gLsddUMevm9D
|
|||||||
github.com/sacloud/iaas-api-go v1.3.2/go.mod h1:CoqpRYBG2NRB5xfqTfZNyh2lVLKyLkE/HV9ISqmbhGc=
|
github.com/sacloud/iaas-api-go v1.3.2/go.mod h1:CoqpRYBG2NRB5xfqTfZNyh2lVLKyLkE/HV9ISqmbhGc=
|
||||||
github.com/sacloud/packages-go v0.0.5 h1:NXTQNyyp/3ugM4CANtLBJLejFESzfWu4GPUURN4NJrA=
|
github.com/sacloud/packages-go v0.0.5 h1:NXTQNyyp/3ugM4CANtLBJLejFESzfWu4GPUURN4NJrA=
|
||||||
github.com/sacloud/packages-go v0.0.5/go.mod h1:XWMBSNHT9YKY3lCh6yJsx1o1RRQQGpuhNqJA6bSHdD4=
|
github.com/sacloud/packages-go v0.0.5/go.mod h1:XWMBSNHT9YKY3lCh6yJsx1o1RRQQGpuhNqJA6bSHdD4=
|
||||||
github.com/sagernet/sing v0.0.0-20220801112236-1bb95f9661fc h1:x7H64IiqyrpxPWl/KrWkknzEK4GmpqgfZeVKFVw6E/M=
|
github.com/sagernet/sing v0.1.0 h1:FGmaP2BVPYO2IyC/3R1DaQa/zr+kOKHRgWqrmOF+Gu8=
|
||||||
github.com/sagernet/sing v0.0.0-20220801112236-1bb95f9661fc/go.mod h1:GbtQfZSpmtD3cXeD1qX2LCMwY8dH+bnnInDTqd92IsM=
|
github.com/sagernet/sing v0.1.0/go.mod h1:zvgDYKI+vCAW9RyfyrKTgleI+DOa8lzHMPC7VZo3OL4=
|
||||||
github.com/sagernet/sing-shadowsocks v0.0.0-20220801112336-a91eacdd01e1 h1:RYvOc69eSNMN0dwVugrDts41Nn7Ar/C/n/fvytvFcp4=
|
github.com/sagernet/sing-shadowsocks v0.1.0 h1:cDmmOkA11fzVdhyCZQEeI3ozQz+59rj8+rqPb91xux4=
|
||||||
github.com/sagernet/sing-shadowsocks v0.0.0-20220801112336-a91eacdd01e1/go.mod h1:NqZjiXszgVCMQ4gVDa2V+drhS8NMfGqUqDF86EacEFc=
|
github.com/sagernet/sing-shadowsocks v0.1.0/go.mod h1:O5LtOs8Ivw686FqLpO0Zu+A0ROVE15VeqEK3yDRRAms=
|
||||||
|
github.com/sagernet/wireguard-go v0.0.0-20221116151939-c99467f53f2c h1:vK2wyt9aWYHHvNLWniwijBu/n4pySypiKRhN32u/JGo=
|
||||||
|
github.com/sagernet/wireguard-go v0.0.0-20221116151939-c99467f53f2c/go.mod h1:euOmN6O5kk9dQmgSS8Df4psAl3TCjxOz0NW60EWkSaI=
|
||||||
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.9 h1:0roa6gXKgyta64uqh52AQG3wzZXH21unn+ltzQSXML0=
|
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.9 h1:0roa6gXKgyta64uqh52AQG3wzZXH21unn+ltzQSXML0=
|
||||||
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.9/go.mod h1:fCa7OJZ/9DRTnOKmxvT6pn+LPWUptQAmHF/SBJUGEcg=
|
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.9/go.mod h1:fCa7OJZ/9DRTnOKmxvT6pn+LPWUptQAmHF/SBJUGEcg=
|
||||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||||
github.com/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb h1:XfLJSPIOUX+osiMraVgIrMR27uMXnRJWGm1+GL8/63U=
|
github.com/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb h1:XfLJSPIOUX+osiMraVgIrMR27uMXnRJWGm1+GL8/63U=
|
||||||
github.com/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb/go.mod h1:bR6DqgcAl1zTcOX8/pE2Qkj9XO00eCNqmKb7lXP8EAg=
|
github.com/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb/go.mod h1:bR6DqgcAl1zTcOX8/pE2Qkj9XO00eCNqmKb7lXP8EAg=
|
||||||
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||||
github.com/shirou/gopsutil/v3 v3.22.9 h1:yibtJhIVEMcdw+tCTbOPiF1VcsuDeTE4utJ8Dm4c5eA=
|
github.com/shirou/gopsutil/v3 v3.22.11 h1:kxsPKS+Eeo+VnEQ2XCaGJepeP6KY53QoRTETx3+1ndM=
|
||||||
github.com/shirou/gopsutil/v3 v3.22.9/go.mod h1:bBYl1kjgEJpWpxeHmLI+dVHWtyAwfcmSBLDsp2TNT8A=
|
github.com/shirou/gopsutil/v3 v3.22.11/go.mod h1:xl0EeL4vXJ+hQMAGN8B9VFpxukEMA0XdevQOe5MZ1oY=
|
||||||
github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY=
|
github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY=
|
||||||
github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM=
|
github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM=
|
||||||
github.com/shurcooL/github_flavored_markdown v0.0.0-20181002035957-2122de532470/go.mod h1:2dOwnU2uBioM+SGy2aZoq1f/Sd1l9OkAeAUvjSyvgU0=
|
github.com/shurcooL/github_flavored_markdown v0.0.0-20181002035957-2122de532470/go.mod h1:2dOwnU2uBioM+SGy2aZoq1f/Sd1l9OkAeAUvjSyvgU0=
|
||||||
@@ -696,6 +706,7 @@ github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYED
|
|||||||
github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw=
|
github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw=
|
||||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||||
|
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
||||||
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
|
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
|
||||||
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||||
@@ -714,8 +725,8 @@ github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod
|
|||||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||||
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||||
github.com/spf13/afero v1.4.1/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
|
github.com/spf13/afero v1.4.1/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
|
||||||
github.com/spf13/afero v1.8.2 h1:xehSyVa0YnHWsJ49JFljMpg1HX19V6NDZ1fkm1Xznbo=
|
github.com/spf13/afero v1.9.2 h1:j49Hj62F0n+DaZ1dDCvhABaPNSGNkt32oRFxI33IEMw=
|
||||||
github.com/spf13/afero v1.8.2/go.mod h1:CtAatgMJh6bJEIs48Ay/FOnkljP3WeGUG0MC1RfAqwo=
|
github.com/spf13/afero v1.9.2/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y=
|
||||||
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||||
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||||
github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w=
|
github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w=
|
||||||
@@ -729,12 +740,13 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
|||||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||||
github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
|
github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
|
||||||
github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
|
github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
|
||||||
github.com/spf13/viper v1.13.0 h1:BWSJ/M+f+3nmdz9bxB+bWX28kkALN2ok11D0rSo8EJU=
|
github.com/spf13/viper v1.14.0 h1:Rg7d3Lo706X9tHsJMUjdiwMpHB7W8WnSVOssIY+JElU=
|
||||||
github.com/spf13/viper v1.13.0/go.mod h1:Icm2xNL3/8uyh/wFuB1jI7TiTNKp8632Nwegu+zgdYw=
|
github.com/spf13/viper v1.14.0/go.mod h1:WT//axPky3FdvXHzGw33dNdXXXfFQqmEalje+egj8As=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4=
|
|
||||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||||
|
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
|
||||||
|
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
@@ -742,8 +754,9 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5
|
|||||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
|
|
||||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
|
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
|
||||||
|
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||||
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
||||||
github.com/subosito/gotenv v1.4.1 h1:jyEFiXpy21Wm81FBN71l9VoMMV8H8jG+qIK3GCpY6Qs=
|
github.com/subosito/gotenv v1.4.1 h1:jyEFiXpy21Wm81FBN71l9VoMMV8H8jG+qIK3GCpY6Qs=
|
||||||
github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0=
|
github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0=
|
||||||
@@ -752,10 +765,10 @@ github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.490 h1:mmz2
|
|||||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.490/go.mod h1:7sCQWVkxcsR38nffDW057DRGk8mUjK1Ing/EFOK8s8Y=
|
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.490/go.mod h1:7sCQWVkxcsR38nffDW057DRGk8mUjK1Ing/EFOK8s8Y=
|
||||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.490 h1:g9SWTaTy/rEuhMErC2jWq9Qt5ci+jBYSvXnJsLq4adg=
|
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.490 h1:g9SWTaTy/rEuhMErC2jWq9Qt5ci+jBYSvXnJsLq4adg=
|
||||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.490/go.mod h1:l9q4vc1QiawUB1m3RU+87yLvrrxe54jc0w/kEl4DbSQ=
|
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.490/go.mod h1:l9q4vc1QiawUB1m3RU+87yLvrrxe54jc0w/kEl4DbSQ=
|
||||||
github.com/tklauser/go-sysconf v0.3.10 h1:IJ1AZGZRWbY8T5Vfk04D9WOA5WSejdflXxP03OUqALw=
|
github.com/tklauser/go-sysconf v0.3.11 h1:89WgdJhk5SNwJfu+GKyYveZ4IaJ7xAkecBo+KdJV0CM=
|
||||||
github.com/tklauser/go-sysconf v0.3.10/go.mod h1:C8XykCvCb+Gn0oNCWPIlcb0RuglQTYaQ2hGm7jmxEFk=
|
github.com/tklauser/go-sysconf v0.3.11/go.mod h1:GqXfhXY3kiPa0nAXPDIQIWzJbMCB7AmcWpGR8lSZfqI=
|
||||||
github.com/tklauser/numcpus v0.4.0 h1:E53Dm1HjH1/R2/aoCtXtPgzmElmn51aOkhCFSuZq//o=
|
github.com/tklauser/numcpus v0.6.0 h1:kebhY2Qt+3U6RNK7UqpYNA+tJ23IBEGKkB7JQBfDYms=
|
||||||
github.com/tklauser/numcpus v0.4.0/go.mod h1:1+UI3pD8NW14VMwdgJNJ1ESk2UnwhAnz5hMwiKKqXCQ=
|
github.com/tklauser/numcpus v0.6.0/go.mod h1:FEZLMke0lhOUG6w2JadTzp0a+Nl8PF/GFkQ5UVIcaL4=
|
||||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||||
github.com/transip/gotransip/v6 v6.17.0 h1:2RCyqYqz5+Ej8z96EyE4sf6tQrrfEBaFDO0LliSl6+8=
|
github.com/transip/gotransip/v6 v6.17.0 h1:2RCyqYqz5+Ej8z96EyE4sf6tQrrfEBaFDO0LliSl6+8=
|
||||||
github.com/transip/gotransip/v6 v6.17.0/go.mod h1:pQZ36hWWRahCUXkFWlx9Hs711gLd8J4qdgLdRzmtY+g=
|
github.com/transip/gotransip/v6 v6.17.0/go.mod h1:pQZ36hWWRahCUXkFWlx9Hs711gLd8J4qdgLdRzmtY+g=
|
||||||
@@ -763,8 +776,6 @@ github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVM
|
|||||||
github.com/ugorji/go v1.2.6/go.mod h1:anCg0y61KIhDlPZmnH+so+RQbysYVyDko0IMgJv0Nn0=
|
github.com/ugorji/go v1.2.6/go.mod h1:anCg0y61KIhDlPZmnH+so+RQbysYVyDko0IMgJv0Nn0=
|
||||||
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
|
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
|
||||||
github.com/ugorji/go/codec v1.2.6/go.mod h1:V6TCNZ4PHqoHGFZuSG1W8nrCzzdgA2DozYxWFFpvxTw=
|
github.com/ugorji/go/codec v1.2.6/go.mod h1:V6TCNZ4PHqoHGFZuSG1W8nrCzzdgA2DozYxWFFpvxTw=
|
||||||
github.com/urfave/cli v1.22.10 h1:p8Fspmz3iTctJstry1PYS3HVdllxnEzTEsgIgtxTrCk=
|
|
||||||
github.com/urfave/cli v1.22.10/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
|
||||||
github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e h1:5QefA066A1tF8gHIiADmOVOV5LS43gt3ONnlEl3xkwI=
|
github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e h1:5QefA066A1tF8gHIiADmOVOV5LS43gt3ONnlEl3xkwI=
|
||||||
github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e/go.mod h1:5t19P9LBIrNamL6AcMQOncg/r10y3Pc01AbHeMhwlpU=
|
github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e/go.mod h1:5t19P9LBIrNamL6AcMQOncg/r10y3Pc01AbHeMhwlpU=
|
||||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||||
@@ -783,8 +794,8 @@ github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQ
|
|||||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||||
github.com/xtls/go v0.0.0-20220914232946-0441cf4cf837 h1:AHhUwwFJGl27E46OpdJHplZkK09m7aETNBNzhT6t15M=
|
github.com/xtls/go v0.0.0-20220914232946-0441cf4cf837 h1:AHhUwwFJGl27E46OpdJHplZkK09m7aETNBNzhT6t15M=
|
||||||
github.com/xtls/go v0.0.0-20220914232946-0441cf4cf837/go.mod h1:YJTRELIWrGxR1s8xcEBgxcxBfwQfMGjdvNLTjN9XFgY=
|
github.com/xtls/go v0.0.0-20220914232946-0441cf4cf837/go.mod h1:YJTRELIWrGxR1s8xcEBgxcxBfwQfMGjdvNLTjN9XFgY=
|
||||||
github.com/xtls/xray-core v1.6.0 h1:5kqFV/BbMb0vn3ymyRIxtnJbS7ctb0Fgb7P3slaYdzI=
|
github.com/xtls/xray-core v1.6.5 h1:orN/xTYAtEz6UyF7OMKliYOBNAfYLuZDIKzcKgzRS2w=
|
||||||
github.com/xtls/xray-core v1.6.0/go.mod h1:wLbZAk/dz5JEnsMZ3QeGTeKyOB50ZqKYKPGRnv0MrWI=
|
github.com/xtls/xray-core v1.6.5/go.mod h1:zim9x2y26FB2qD19HyvcLvwtOy8nw+Fa9g8bCEUwaNw=
|
||||||
github.com/yandex-cloud/go-genproto v0.0.0-20220805142335-27b56ddae16f h1:cG+ehPRJSlqljSufLf1KXeXpUd1dLNjnzA18mZcB/O0=
|
github.com/yandex-cloud/go-genproto v0.0.0-20220805142335-27b56ddae16f h1:cG+ehPRJSlqljSufLf1KXeXpUd1dLNjnzA18mZcB/O0=
|
||||||
github.com/yandex-cloud/go-genproto v0.0.0-20220805142335-27b56ddae16f/go.mod h1:HEUYX/p8966tMUHHT+TsS0hF/Ca/NYwqprC5WXSDMfE=
|
github.com/yandex-cloud/go-genproto v0.0.0-20220805142335-27b56ddae16f/go.mod h1:HEUYX/p8966tMUHHT+TsS0hF/Ca/NYwqprC5WXSDMfE=
|
||||||
github.com/yandex-cloud/go-sdk v0.0.0-20220805164847-cf028e604997 h1:2wzke3JH7OtN20WsNDZx2VH/TCmsbqtDEbXzjF+i05E=
|
github.com/yandex-cloud/go-sdk v0.0.0-20220805164847-cf028e604997 h1:2wzke3JH7OtN20WsNDZx2VH/TCmsbqtDEbXzjF+i05E=
|
||||||
@@ -807,11 +818,12 @@ go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
|
|||||||
go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M=
|
go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M=
|
||||||
go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
|
go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
|
||||||
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
|
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
|
||||||
go.starlark.net v0.0.0-20220817180228-f738f5508c12 h1:xOBJXWGEDwU5xSDxH6macxO11Us0AH2fTa9rmsbbF7g=
|
go.starlark.net v0.0.0-20221028183056-acb66ad56dd2 h1:5/KzhcSqd4UgY51l17r7C5g/JiE6DRw1Vq7VJfQHuMc=
|
||||||
go.starlark.net v0.0.0-20220817180228-f738f5508c12/go.mod h1:VZcBMdr3cT3PnBoWunTabuSEXwVAH+ZJ5zxfs3AdASk=
|
go.starlark.net v0.0.0-20221028183056-acb66ad56dd2/go.mod h1:kIVgS18CjmEC3PqMd5kaJSGEifyV/CeB9x506ZJ1Vbk=
|
||||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||||
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
|
|
||||||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||||
|
go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ=
|
||||||
|
go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
|
||||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||||
go.uber.org/ratelimit v0.2.0 h1:UQE2Bgi7p2B85uP5dC2bbRtig0C+OeNRnNEafLjsLPA=
|
go.uber.org/ratelimit v0.2.0 h1:UQE2Bgi7p2B85uP5dC2bbRtig0C+OeNRnNEafLjsLPA=
|
||||||
go.uber.org/ratelimit v0.2.0/go.mod h1:YYBV4e4naJvhpitQrWJu1vCpgB7CboMe0qhltKt6mUg=
|
go.uber.org/ratelimit v0.2.0/go.mod h1:YYBV4e4naJvhpitQrWJu1vCpgB7CboMe0qhltKt6mUg=
|
||||||
@@ -838,8 +850,8 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y
|
|||||||
golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.0.0-20211202192323-5770296d904e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
golang.org/x/crypto v0.0.0-20211202192323-5770296d904e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90 h1:Y/gsMcFOcR+6S6f3YeMKl5g+dZMEWqcz5Czj/GWYbkM=
|
golang.org/x/crypto v0.4.0 h1:UVQgzMY87xqpKNgb+kDsll2Igd33HszWHFLmpaRMq/8=
|
||||||
golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
golang.org/x/crypto v0.4.0/go.mod h1:3quD/ATkf6oY+rnes5c3ExXTbLc8mueNue5/DoinL80=
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||||
@@ -850,8 +862,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
|
|||||||
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||||
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
|
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
|
||||||
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
||||||
golang.org/x/exp v0.0.0-20220916125017-b168a2c6b86b h1:SCE/18RnFsLrjydh/R/s5EVvHoZprqEQUuoxK8q2Pc4=
|
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db h1:D/cFflL63o2KSLJIwjlcIt8PR064j/xsmdEJL/YvY/o=
|
||||||
golang.org/x/exp v0.0.0-20220916125017-b168a2c6b86b/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE=
|
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
|
||||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||||
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
@@ -866,7 +878,6 @@ golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRu
|
|||||||
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||||
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||||
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
|
||||||
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
||||||
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
||||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||||
@@ -878,8 +889,8 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
|||||||
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
|
golang.org/x/mod v0.7.0 h1:LapD9S96VoQRhi/GrNTqeBJFrUjs5UHCAtTlgwA5oZA=
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
@@ -921,25 +932,18 @@ golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwY
|
|||||||
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
|
|
||||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||||
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
|
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
|
||||||
golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20210913180222-943fd674d43e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20210913180222-943fd674d43e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20211029224645-99673261e6eb/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20211029224645-99673261e6eb/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20211111160137-58aab5ef257a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
|
||||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||||
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||||
golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
golang.org/x/net v0.4.0 h1:Q5QPcMlvfxFTAPV0+07Xz/MpK9NTXu2VDUuy0FeMfaU=
|
||||||
golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
|
||||||
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
|
||||||
golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
|
||||||
golang.org/x/net v0.0.0-20220909164309-bea034e7d591 h1:D0B/7al0LLrVC8aWF4+oxpv/m8bc7ViFfVS8/gXGdqI=
|
|
||||||
golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
|
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
@@ -951,19 +955,10 @@ golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ
|
|||||||
golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||||
golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||||
golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||||
golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
|
||||||
golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
|
||||||
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||||
golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
|
||||||
golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
|
||||||
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
|
||||||
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
|
||||||
golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
|
golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
|
||||||
golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
|
golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783 h1:nt+Q6cXKz4MosCSpnbMtqiQ8Oz0pxTef2B4Vca2lvfk=
|
||||||
golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
|
golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg=
|
||||||
golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE=
|
|
||||||
golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1 h1:lxqLZaMad/dJHMFZH0NiNpiEZI/nhgWhe4wgzpE+MuA=
|
|
||||||
golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg=
|
|
||||||
golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw=
|
golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw=
|
||||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
@@ -976,8 +971,7 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ
|
|||||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
|
||||||
golang.org/x/sync v0.0.0-20220907140024-f12130a52804 h1:0SH2R3f1b1VmIMG7BXbEZCBUu2dKmHschSmjqGUrW8A=
|
|
||||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
@@ -1007,6 +1001,7 @@ golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
@@ -1020,6 +1015,8 @@ golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
@@ -1032,46 +1029,33 @@ golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220915200043-7b5979e65e41 h1:ohgcoMbSofXygzo6AD2I1kz3BFmW1QArPYTtwEM3UXc=
|
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220915200043-7b5979e65e41/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ=
|
||||||
|
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
|
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
|
golang.org/x/term v0.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
|
golang.org/x/term v0.3.0 h1:qoo4akIqOcDME5bhc/NgxUdovd6BSS2uMsVjB56q1xI=
|
||||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
@@ -1080,16 +1064,17 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
|||||||
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
|
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
|
golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM=
|
||||||
|
golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 h1:M73Iuj3xbbb9Uk1DYhzydthsj6oOd6l9bpuFcNoUvTs=
|
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
|
||||||
golang.org/x/time v0.0.0-20220224211638-0e9765cccd65/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
@@ -1147,21 +1132,14 @@ golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4f
|
|||||||
golang.org/x/tools v0.0.0-20210114065538-d78b04bdf963/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
golang.org/x/tools v0.0.0-20210114065538-d78b04bdf963/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
||||||
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||||
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
|
||||||
golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
|
||||||
golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
|
||||||
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
|
||||||
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||||
golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
|
golang.org/x/tools v0.3.0 h1:SrNbZl6ECOS1qFzgTdQfWXZM9XBkiA6tkFrH9YSTPHM=
|
||||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk=
|
||||||
golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
|
|
||||||
golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f h1:uF6paiQQebLeSXkrTqHqz0MXhXXS1KgF41eUdBNvxK0=
|
|
||||||
golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
|
|
||||||
google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
|
google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
|
||||||
google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
|
google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
|
||||||
google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y=
|
google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y=
|
||||||
@@ -1184,27 +1162,8 @@ google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz513
|
|||||||
google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
|
google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
|
||||||
google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE=
|
google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE=
|
||||||
google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
|
google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
|
||||||
google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU=
|
google.golang.org/api v0.102.0 h1:JxJl2qQ85fRMPNvlZY/enexbxpCjLwGhZUtgfGeQ51I=
|
||||||
google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94=
|
google.golang.org/api v0.102.0/go.mod h1:3VFl6/fzoA+qNuS1N1/VfXY4LjoXN/wzeIp7TweWwGo=
|
||||||
google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo=
|
|
||||||
google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4=
|
|
||||||
google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw=
|
|
||||||
google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU=
|
|
||||||
google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k=
|
|
||||||
google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE=
|
|
||||||
google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE=
|
|
||||||
google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI=
|
|
||||||
google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I=
|
|
||||||
google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo=
|
|
||||||
google.golang.org/api v0.67.0/go.mod h1:ShHKP8E60yPsKNw/w8w+VYaj9H6buA5UqDp8dhbQZ6g=
|
|
||||||
google.golang.org/api v0.70.0/go.mod h1:Bs4ZM2HGifEvXwd50TtW70ovgJffJYw2oRCOFU/SkfA=
|
|
||||||
google.golang.org/api v0.71.0/go.mod h1:4PyU6e6JogV1f9eA4voyrTY2batOLdgZ5qZ5HOCc4j8=
|
|
||||||
google.golang.org/api v0.74.0/go.mod h1:ZpfMZOVRMywNyvJFeqL9HRWBgAuRfSjJFpe9QtRRyDs=
|
|
||||||
google.golang.org/api v0.75.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA=
|
|
||||||
google.golang.org/api v0.78.0/go.mod h1:1Sg78yoMLOhlQTeF+ARBoytAcH1NNyyl390YMy6rKmw=
|
|
||||||
google.golang.org/api v0.80.0/go.mod h1:xY3nI94gbvBrE0J6NHXhxOmW97HG7Khjkku6AFB3Hyg=
|
|
||||||
google.golang.org/api v0.84.0 h1:NMB9J4cCxs9xEm+1Z9QiO3eFvn7EnQj3Eo3hN6ugVlg=
|
|
||||||
google.golang.org/api v0.84.0/go.mod h1:NTsGnUFJMYROtiquksZHBWtHfeMC7iYthki7Eq3pa8o=
|
|
||||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||||
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
@@ -1255,53 +1214,10 @@ google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6D
|
|||||||
google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
|
||||||
google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
|
||||||
google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
|
||||||
google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
|
||||||
google.golang.org/genproto v0.0.0-20210329143202-679c6ae281ee/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A=
|
|
||||||
google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A=
|
|
||||||
google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A=
|
|
||||||
google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
|
|
||||||
google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
|
|
||||||
google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
|
|
||||||
google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24=
|
|
||||||
google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k=
|
|
||||||
google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k=
|
|
||||||
google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=
|
|
||||||
google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=
|
|
||||||
google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w=
|
|
||||||
google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
|
|
||||||
google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
|
|
||||||
google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
|
|
||||||
google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
|
|
||||||
google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
|
|
||||||
google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
|
||||||
google.golang.org/genproto v0.0.0-20211021150943-2b146023228c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
google.golang.org/genproto v0.0.0-20211021150943-2b146023228c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||||
google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6 h1:a2S6M0+660BgMNl++4JPlcAO/CjkqYItDEZwkoDQK7c=
|
||||||
google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg=
|
||||||
google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
|
||||||
google.golang.org/genproto v0.0.0-20211221195035-429b39de9b1c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
|
||||||
google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
|
||||||
google.golang.org/genproto v0.0.0-20220207164111-0872dc986b00/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
|
||||||
google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
|
|
||||||
google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
|
|
||||||
google.golang.org/genproto v0.0.0-20220304144024-325a89244dc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
|
|
||||||
google.golang.org/genproto v0.0.0-20220310185008-1973136f34c6/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
|
|
||||||
google.golang.org/genproto v0.0.0-20220324131243-acbaeb5b85eb/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E=
|
|
||||||
google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
|
|
||||||
google.golang.org/genproto v0.0.0-20220413183235-5e96e2839df9/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
|
|
||||||
google.golang.org/genproto v0.0.0-20220414192740-2d67ff6cf2b4/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
|
|
||||||
google.golang.org/genproto v0.0.0-20220421151946-72621c1f0bd3/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
|
|
||||||
google.golang.org/genproto v0.0.0-20220429170224-98d788798c3e/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
|
|
||||||
google.golang.org/genproto v0.0.0-20220505152158-f39f71e6c8f3/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
|
|
||||||
google.golang.org/genproto v0.0.0-20220518221133-4f43b3371335/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
|
|
||||||
google.golang.org/genproto v0.0.0-20220523171625-347a074981d8/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
|
|
||||||
google.golang.org/genproto v0.0.0-20220608133413-ed9918b62aac/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA=
|
|
||||||
google.golang.org/genproto v0.0.0-20220616135557-88e70c0c3a90/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA=
|
|
||||||
google.golang.org/genproto v0.0.0-20220916172020-2692e8806bfa h1:VWkrxnAx2C2hirAP+W5ADU7e/+93Yhk//ioKd2XFyDI=
|
|
||||||
google.golang.org/genproto v0.0.0-20220916172020-2692e8806bfa/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo=
|
|
||||||
google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||||
google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
|
google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
|
||||||
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
||||||
@@ -1323,23 +1239,10 @@ google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv
|
|||||||
google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
|
google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
|
||||||
google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||||
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||||
google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
|
||||||
google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
|
|
||||||
google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
|
|
||||||
google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
|
|
||||||
google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
|
|
||||||
google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
|
|
||||||
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
|
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
|
||||||
google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
|
|
||||||
google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k=
|
google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k=
|
||||||
google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
|
google.golang.org/grpc v1.51.0 h1:E1eGv1FTqoLIdnBCZufiSHgKjlqG6fKFf6pPWtMTh8U=
|
||||||
google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ=
|
google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww=
|
||||||
google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
|
|
||||||
google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
|
|
||||||
google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
|
|
||||||
google.golang.org/grpc v1.49.0 h1:WTLtQzmQori5FUH25Pq4WT22oCsv8USpQ+F6rqtsmxw=
|
|
||||||
google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI=
|
|
||||||
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
|
|
||||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||||
@@ -1353,7 +1256,6 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba
|
|||||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||||
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||||
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
|
||||||
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
|
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
|
||||||
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||||
@@ -1387,6 +1289,7 @@ gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||||
@@ -1398,6 +1301,8 @@ gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
|||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o=
|
grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o=
|
||||||
|
gvisor.dev/gvisor v0.0.0-20220901235040-6ca97ef2ce1c h1:m5lcgWnL3OElQNVyp3qcncItJ2c0sQlSGjYK2+nJTA4=
|
||||||
|
gvisor.dev/gvisor v0.0.0-20220901235040-6ca97ef2ce1c/go.mod h1:TIvkJD0sxe8pIob3p6T8IzxXunlp6yfgktvTNp+DGNM=
|
||||||
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
|
@@ -6,15 +6,15 @@ DnsConfigPath: # /etc/XrayR/dns.json # Path to dns config, check https://xtls.gi
|
|||||||
RouteConfigPath: # /etc/XrayR/route.json # Path to route config, check https://xtls.github.io/config/routing.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
|
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
|
OutboundConfigPath: # /etc/XrayR/custom_outbound.json # Path to custom outbound config, check https://xtls.github.io/config/outbound.html for help
|
||||||
ConnetionConfig:
|
ConnectionConfig:
|
||||||
Handshake: 4 # Handshake time limit, Second
|
Handshake: 4 # Handshake time limit, Second
|
||||||
ConnIdle: 30 # Connection idle time limit, Second
|
ConnIdle: 30 # Connection idle time limit, Second
|
||||||
UplinkOnly: 2 # Time limit when the connection downstream is closed, 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
|
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
|
BufferSize: 64 # The internal cache size of each connection, kB
|
||||||
Nodes:
|
Nodes:
|
||||||
-
|
-
|
||||||
PanelType: "SSpanel" # Panel type: SSpanel, V2board, PMpanel, Proxypanel, V2RaySocks
|
PanelType: "SSpanel" # Panel type: SSpanel, V2board, NewV2board, PMpanel, Proxypanel, V2RaySocks
|
||||||
ApiConfig:
|
ApiConfig:
|
||||||
ApiHost: "http://127.0.0.1:667"
|
ApiHost: "http://127.0.0.1:667"
|
||||||
ApiKey: "123"
|
ApiKey: "123"
|
||||||
@@ -33,12 +33,19 @@ Nodes:
|
|||||||
EnableDNS: false # Use custom DNS config, Please ensure that you set the dns.json well
|
EnableDNS: false # Use custom DNS config, Please ensure that you set the dns.json well
|
||||||
DNSType: AsIs # AsIs, UseIP, UseIPv4, UseIPv6, DNS strategy
|
DNSType: AsIs # AsIs, UseIP, UseIPv4, UseIPv6, DNS strategy
|
||||||
EnableProxyProtocol: false # Only works for WebSocket and TCP
|
EnableProxyProtocol: false # Only works for WebSocket and TCP
|
||||||
EnableFallback: false # Only support for Trojan and Vless
|
|
||||||
AutoSpeedLimitConfig:
|
AutoSpeedLimitConfig:
|
||||||
Limit: 0 # Warned speed. Set to 0 to disable AutoSpeedLimit (mbps)
|
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.
|
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)
|
LimitSpeed: 0 # The speedlimit of a limited user (unit: mbps)
|
||||||
LimitDuration: 0 # How many minutes will the limiting last (unit: minute)
|
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
|
FallBackConfigs: # Support multiple fallbacks
|
||||||
-
|
-
|
||||||
SNI: # TLS SNI(Server Name Indication), Empty for any
|
SNI: # TLS SNI(Server Name Indication), Empty for any
|
||||||
@@ -47,7 +54,7 @@ Nodes:
|
|||||||
Dest: 80 # Required, Destination of fallback, check https://xtls.github.io/config/features/fallback.html for details.
|
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
|
ProxyProtocolVer: 0 # Send PROXY protocol version, 0 for dsable
|
||||||
CertConfig:
|
CertConfig:
|
||||||
CertMode: dns # Option about how to get certificate: none, file, http, dns. Choose "none" will forcedly disable the tls config.
|
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
|
CertDomain: "node1.test.com" # Domain to cert
|
||||||
CertFile: /etc/XrayR/cert/node1.test.com.cert # Provided if the CertMode is file
|
CertFile: /etc/XrayR/cert/node1.test.com.cert # Provided if the CertMode is file
|
||||||
KeyFile: /etc/XrayR/cert/node1.test.com.key
|
KeyFile: /etc/XrayR/cert/node1.test.com.key
|
||||||
@@ -57,7 +64,7 @@ Nodes:
|
|||||||
ALICLOUD_ACCESS_KEY: aaa
|
ALICLOUD_ACCESS_KEY: aaa
|
||||||
ALICLOUD_SECRET_KEY: bbb
|
ALICLOUD_SECRET_KEY: bbb
|
||||||
# -
|
# -
|
||||||
# PanelType: "V2board" # Panel type: SSpanel, V2board
|
# PanelType: "NewV2board" # Panel type: SSpanel, V2board, NewV2board, PMpanel, Proxypanel, V2RaySocks
|
||||||
# ApiConfig:
|
# ApiConfig:
|
||||||
# ApiHost: "http://127.0.0.1:668"
|
# ApiHost: "http://127.0.0.1:668"
|
||||||
# ApiKey: "123"
|
# ApiKey: "123"
|
||||||
@@ -82,4 +89,3 @@ Nodes:
|
|||||||
# DNSEnv: # DNS ENV option used by DNS provider
|
# DNSEnv: # DNS ENV option used by DNS provider
|
||||||
# ALICLOUD_ACCESS_KEY: aaa
|
# ALICLOUD_ACCESS_KEY: aaa
|
||||||
# ALICLOUD_SECRET_KEY: bbb
|
# ALICLOUD_SECRET_KEY: bbb
|
||||||
|
|
||||||
|
@@ -1,19 +1,19 @@
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
"listen": "0.0.0.0",
|
"listen": "0.0.0.0",
|
||||||
"port": 1234,
|
"port": 1234,
|
||||||
"protocol": "socks",
|
"protocol": "socks",
|
||||||
"settings": {
|
"settings": {
|
||||||
"auth": "noauth",
|
"auth": "noauth",
|
||||||
"accounts": [
|
"accounts": [
|
||||||
{
|
{
|
||||||
"user": "my-username",
|
"user": "my-username",
|
||||||
"pass": "my-password"
|
"pass": "my-password"
|
||||||
}
|
|
||||||
],
|
|
||||||
"udp": false,
|
|
||||||
"ip": "127.0.0.1",
|
|
||||||
"userLevel": 0
|
|
||||||
}
|
}
|
||||||
|
],
|
||||||
|
"udp": false,
|
||||||
|
"ip": "127.0.0.1",
|
||||||
|
"userLevel": 0
|
||||||
}
|
}
|
||||||
|
}
|
||||||
]
|
]
|
@@ -1,28 +1,30 @@
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
"tag": "IPv4_out",
|
"tag": "IPv4_out",
|
||||||
"protocol": "freedom",
|
"protocol": "freedom",
|
||||||
"settings": {}
|
"settings": {}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"tag": "IPv6_out",
|
"tag": "IPv6_out",
|
||||||
"protocol": "freedom",
|
"protocol": "freedom",
|
||||||
"settings": {
|
"settings": {
|
||||||
"domainStrategy": "UseIPv6"
|
"domainStrategy": "UseIPv6"
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tag": "socks5-warp",
|
|
||||||
"protocol": "socks",
|
|
||||||
"settings": {
|
|
||||||
"servers": [{
|
|
||||||
"address": "127.0.0.1",
|
|
||||||
"port": 1080
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"protocol": "blackhole",
|
|
||||||
"tag": "block"
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tag": "socks5-warp",
|
||||||
|
"protocol": "socks",
|
||||||
|
"settings": {
|
||||||
|
"servers": [
|
||||||
|
{
|
||||||
|
"address": "127.0.0.1",
|
||||||
|
"port": 1080
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"protocol": "blackhole",
|
||||||
|
"tag": "block"
|
||||||
|
}
|
||||||
]
|
]
|
@@ -3,11 +3,12 @@ package all
|
|||||||
import (
|
import (
|
||||||
// The following are necessary as they register handlers in their init functions.
|
// The following are necessary as they register handlers in their init functions.
|
||||||
|
|
||||||
|
_ "github.com/xtls/xray-core/app/proxyman/inbound"
|
||||||
|
_ "github.com/xtls/xray-core/app/proxyman/outbound"
|
||||||
|
|
||||||
// Required features. Can't remove unless there is replacements.
|
// Required features. Can't remove unless there is replacements.
|
||||||
// _ "github.com/xtls/xray-core/app/dispatcher"
|
// _ "github.com/xtls/xray-core/app/dispatcher"
|
||||||
_ "github.com/XrayR-project/XrayR/app/mydispatcher"
|
_ "github.com/XrayR-project/XrayR/app/mydispatcher"
|
||||||
_ "github.com/xtls/xray-core/app/proxyman/inbound"
|
|
||||||
_ "github.com/xtls/xray-core/app/proxyman/outbound"
|
|
||||||
|
|
||||||
// Default commander and all its services. This is an optional feature.
|
// Default commander and all its services. This is an optional feature.
|
||||||
_ "github.com/xtls/xray-core/app/commander"
|
_ "github.com/xtls/xray-core/app/commander"
|
||||||
|
@@ -1,8 +1,8 @@
|
|||||||
{
|
{
|
||||||
"servers": [
|
"servers": [
|
||||||
"1.1.1.1",
|
"1.1.1.1",
|
||||||
"8.8.8.8",
|
"8.8.8.8",
|
||||||
"localhost"
|
"localhost"
|
||||||
],
|
],
|
||||||
"tag": "dns_inbound"
|
"tag": "dns_inbound"
|
||||||
}
|
}
|
11
main/main.go
11
main/main.go
@@ -12,9 +12,10 @@ import (
|
|||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/XrayR-project/XrayR/panel"
|
|
||||||
"github.com/fsnotify/fsnotify"
|
"github.com/fsnotify/fsnotify"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
|
|
||||||
|
"github.com/XrayR-project/XrayR/panel"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -23,7 +24,7 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
version = "0.8.5"
|
version = "0.8.7"
|
||||||
codename = "XrayR"
|
codename = "XrayR"
|
||||||
intro = "A Xray backend that supports many panels"
|
intro = "A Xray backend that supports many panels"
|
||||||
)
|
)
|
||||||
@@ -74,7 +75,7 @@ func main() {
|
|||||||
config := getConfig()
|
config := getConfig()
|
||||||
panelConfig := &panel.Config{}
|
panelConfig := &panel.Config{}
|
||||||
if err := config.Unmarshal(panelConfig); err != nil {
|
if err := config.Unmarshal(panelConfig); err != nil {
|
||||||
log.Panicf("Parse config file %s failed: %s \n", configFile, err)
|
log.Panicf("Parse config file %v failed: %s \n", configFile, err)
|
||||||
}
|
}
|
||||||
p := panel.New(panelConfig)
|
p := panel.New(panelConfig)
|
||||||
lastTime := time.Now()
|
lastTime := time.Now()
|
||||||
@@ -87,7 +88,7 @@ func main() {
|
|||||||
// Delete old instance and trigger GC
|
// Delete old instance and trigger GC
|
||||||
runtime.GC()
|
runtime.GC()
|
||||||
if err := config.Unmarshal(panelConfig); err != nil {
|
if err := config.Unmarshal(panelConfig); err != nil {
|
||||||
log.Panicf("Parse config file %s failed: %s \n", configFile, err)
|
log.Panicf("Parse config file %v failed: %s \n", configFile, err)
|
||||||
}
|
}
|
||||||
p.Start()
|
p.Start()
|
||||||
lastTime = time.Now()
|
lastTime = time.Now()
|
||||||
@@ -96,7 +97,7 @@ func main() {
|
|||||||
p.Start()
|
p.Start()
|
||||||
defer p.Close()
|
defer p.Close()
|
||||||
|
|
||||||
//Explicitly triggering GC to remove garbage from config loading.
|
// Explicitly triggering GC to remove garbage from config loading.
|
||||||
runtime.GC()
|
runtime.GC()
|
||||||
// Running backend
|
// Running backend
|
||||||
{
|
{
|
||||||
|
@@ -1,36 +1,36 @@
|
|||||||
{
|
{
|
||||||
"domainStrategy": "IPOnDemand",
|
"domainStrategy": "IPOnDemand",
|
||||||
"rules": [
|
"rules": [
|
||||||
{
|
{
|
||||||
"type": "field",
|
"type": "field",
|
||||||
"outboundTag": "block",
|
"outboundTag": "block",
|
||||||
"ip": [
|
"ip": [
|
||||||
"geoip:private"
|
"geoip:private"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "field",
|
"type": "field",
|
||||||
"outboundTag": "block",
|
"outboundTag": "block",
|
||||||
"protocol": [
|
"protocol": [
|
||||||
"bittorrent"
|
"bittorrent"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "field",
|
"type": "field",
|
||||||
"outboundTag": "socks5-warp",
|
"outboundTag": "socks5-warp",
|
||||||
"domain": []
|
"domain": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "field",
|
"type": "field",
|
||||||
"outboundTag": "IPv6_out",
|
"outboundTag": "IPv6_out",
|
||||||
"domain": [
|
"domain": [
|
||||||
"geosite:netflix"
|
"geosite:netflix"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "field",
|
"type": "field",
|
||||||
"outboundTag": "IPv4_out",
|
"outboundTag": "IPv4_out",
|
||||||
"network": "udp,tcp"
|
"network": "udp,tcp"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
@@ -6,13 +6,13 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
LogConfig *LogConfig `mapstructure:"Log"`
|
LogConfig *LogConfig `mapstructure:"Log"`
|
||||||
DnsConfigPath string `mapstructure:"DnsConfigPath"`
|
DnsConfigPath string `mapstructure:"DnsConfigPath"`
|
||||||
InboundConfigPath string `mapstructure:"InboundConfigPath"`
|
InboundConfigPath string `mapstructure:"InboundConfigPath"`
|
||||||
OutboundConfigPath string `mapstructure:"OutboundConfigPath"`
|
OutboundConfigPath string `mapstructure:"OutboundConfigPath"`
|
||||||
RouteConfigPath string `mapstructure:"RouteConfigPath"`
|
RouteConfigPath string `mapstructure:"RouteConfigPath"`
|
||||||
ConnetionConfig *ConnetionConfig `mapstructure:"ConnetionConfig"`
|
ConnectionConfig *ConnectionConfig `mapstructure:"ConnectionConfig"`
|
||||||
NodesConfig []*NodesConfig `mapstructure:"Nodes"`
|
NodesConfig []*NodesConfig `mapstructure:"Nodes"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type NodesConfig struct {
|
type NodesConfig struct {
|
||||||
@@ -27,7 +27,7 @@ type LogConfig struct {
|
|||||||
ErrorPath string `mapstructure:"ErrorPath"`
|
ErrorPath string `mapstructure:"ErrorPath"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ConnetionConfig struct {
|
type ConnectionConfig struct {
|
||||||
Handshake uint32 `mapstructure:"handshake"`
|
Handshake uint32 `mapstructure:"handshake"`
|
||||||
ConnIdle uint32 `mapstructure:"connIdle"`
|
ConnIdle uint32 `mapstructure:"connIdle"`
|
||||||
UplinkOnly uint32 `mapstructure:"uplinkOnly"`
|
UplinkOnly uint32 `mapstructure:"uplinkOnly"`
|
||||||
|
@@ -10,8 +10,8 @@ func getDefaultLogConfig() *LogConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getDefaultConnetionConfig() *ConnetionConfig {
|
func getDefaultConnectionConfig() *ConnectionConfig {
|
||||||
return &ConnetionConfig{
|
return &ConnectionConfig{
|
||||||
Handshake: 4,
|
Handshake: 4,
|
||||||
ConnIdle: 30,
|
ConnIdle: 30,
|
||||||
UplinkOnly: 2,
|
UplinkOnly: 2,
|
||||||
|
@@ -2,12 +2,21 @@ package panel
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
io "io/ioutil"
|
|
||||||
"log"
|
"log"
|
||||||
|
"os"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/XrayR-project/XrayR/api/newV2board"
|
||||||
"github.com/XrayR-project/XrayR/app/mydispatcher"
|
"github.com/XrayR-project/XrayR/app/mydispatcher"
|
||||||
|
|
||||||
|
"github.com/imdario/mergo"
|
||||||
|
"github.com/r3labs/diff/v2"
|
||||||
|
"github.com/xtls/xray-core/app/proxyman"
|
||||||
|
"github.com/xtls/xray-core/app/stats"
|
||||||
|
"github.com/xtls/xray-core/common/serial"
|
||||||
|
"github.com/xtls/xray-core/core"
|
||||||
|
"github.com/xtls/xray-core/infra/conf"
|
||||||
|
|
||||||
"github.com/XrayR-project/XrayR/api"
|
"github.com/XrayR-project/XrayR/api"
|
||||||
"github.com/XrayR-project/XrayR/api/pmpanel"
|
"github.com/XrayR-project/XrayR/api/pmpanel"
|
||||||
"github.com/XrayR-project/XrayR/api/proxypanel"
|
"github.com/XrayR-project/XrayR/api/proxypanel"
|
||||||
@@ -17,13 +26,6 @@ import (
|
|||||||
_ "github.com/XrayR-project/XrayR/main/distro/all"
|
_ "github.com/XrayR-project/XrayR/main/distro/all"
|
||||||
"github.com/XrayR-project/XrayR/service"
|
"github.com/XrayR-project/XrayR/service"
|
||||||
"github.com/XrayR-project/XrayR/service/controller"
|
"github.com/XrayR-project/XrayR/service/controller"
|
||||||
"github.com/imdario/mergo"
|
|
||||||
"github.com/r3labs/diff/v2"
|
|
||||||
"github.com/xtls/xray-core/app/proxyman"
|
|
||||||
"github.com/xtls/xray-core/app/stats"
|
|
||||||
"github.com/xtls/xray-core/common/serial"
|
|
||||||
"github.com/xtls/xray-core/core"
|
|
||||||
"github.com/xtls/xray-core/infra/conf"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Panel Structure
|
// Panel Structure
|
||||||
@@ -56,7 +58,7 @@ func (p *Panel) loadCore(panelConfig *Config) *core.Instance {
|
|||||||
// DNS config
|
// DNS config
|
||||||
coreDnsConfig := &conf.DNSConfig{}
|
coreDnsConfig := &conf.DNSConfig{}
|
||||||
if panelConfig.DnsConfigPath != "" {
|
if panelConfig.DnsConfigPath != "" {
|
||||||
if data, err := io.ReadFile(panelConfig.DnsConfigPath); err != nil {
|
if data, err := os.ReadFile(panelConfig.DnsConfigPath); err != nil {
|
||||||
log.Panicf("Failed to read DNS config file at: %s", panelConfig.DnsConfigPath)
|
log.Panicf("Failed to read DNS config file at: %s", panelConfig.DnsConfigPath)
|
||||||
} else {
|
} else {
|
||||||
if err = json.Unmarshal(data, coreDnsConfig); err != nil {
|
if err = json.Unmarshal(data, coreDnsConfig); err != nil {
|
||||||
@@ -71,7 +73,7 @@ func (p *Panel) loadCore(panelConfig *Config) *core.Instance {
|
|||||||
// Routing config
|
// Routing config
|
||||||
coreRouterConfig := &conf.RouterConfig{}
|
coreRouterConfig := &conf.RouterConfig{}
|
||||||
if panelConfig.RouteConfigPath != "" {
|
if panelConfig.RouteConfigPath != "" {
|
||||||
if data, err := io.ReadFile(panelConfig.RouteConfigPath); err != nil {
|
if data, err := os.ReadFile(panelConfig.RouteConfigPath); err != nil {
|
||||||
log.Panicf("Failed to read Routing config file at: %s", panelConfig.RouteConfigPath)
|
log.Panicf("Failed to read Routing config file at: %s", panelConfig.RouteConfigPath)
|
||||||
} else {
|
} else {
|
||||||
if err = json.Unmarshal(data, coreRouterConfig); err != nil {
|
if err = json.Unmarshal(data, coreRouterConfig); err != nil {
|
||||||
@@ -84,9 +86,9 @@ func (p *Panel) loadCore(panelConfig *Config) *core.Instance {
|
|||||||
log.Panicf("Failed to understand Routing config Please check: https://xtls.github.io/config/routing.html for help: %s", err)
|
log.Panicf("Failed to understand Routing config Please check: https://xtls.github.io/config/routing.html for help: %s", err)
|
||||||
}
|
}
|
||||||
// Custom Inbound config
|
// Custom Inbound config
|
||||||
coreCustomInboundConfig := []conf.InboundDetourConfig{}
|
var coreCustomInboundConfig []conf.InboundDetourConfig
|
||||||
if panelConfig.InboundConfigPath != "" {
|
if panelConfig.InboundConfigPath != "" {
|
||||||
if data, err := io.ReadFile(panelConfig.InboundConfigPath); err != nil {
|
if data, err := os.ReadFile(panelConfig.InboundConfigPath); err != nil {
|
||||||
log.Panicf("Failed to read Custom Inbound config file at: %s", panelConfig.OutboundConfigPath)
|
log.Panicf("Failed to read Custom Inbound config file at: %s", panelConfig.OutboundConfigPath)
|
||||||
} else {
|
} else {
|
||||||
if err = json.Unmarshal(data, &coreCustomInboundConfig); err != nil {
|
if err = json.Unmarshal(data, &coreCustomInboundConfig); err != nil {
|
||||||
@@ -94,7 +96,7 @@ func (p *Panel) loadCore(panelConfig *Config) *core.Instance {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
inBoundConfig := []*core.InboundHandlerConfig{}
|
var inBoundConfig []*core.InboundHandlerConfig
|
||||||
for _, config := range coreCustomInboundConfig {
|
for _, config := range coreCustomInboundConfig {
|
||||||
oc, err := config.Build()
|
oc, err := config.Build()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -103,9 +105,9 @@ func (p *Panel) loadCore(panelConfig *Config) *core.Instance {
|
|||||||
inBoundConfig = append(inBoundConfig, oc)
|
inBoundConfig = append(inBoundConfig, oc)
|
||||||
}
|
}
|
||||||
// Custom Outbound config
|
// Custom Outbound config
|
||||||
coreCustomOutboundConfig := []conf.OutboundDetourConfig{}
|
var coreCustomOutboundConfig []conf.OutboundDetourConfig
|
||||||
if panelConfig.OutboundConfigPath != "" {
|
if panelConfig.OutboundConfigPath != "" {
|
||||||
if data, err := io.ReadFile(panelConfig.OutboundConfigPath); err != nil {
|
if data, err := os.ReadFile(panelConfig.OutboundConfigPath); err != nil {
|
||||||
log.Panicf("Failed to read Custom Outbound config file at: %s", panelConfig.OutboundConfigPath)
|
log.Panicf("Failed to read Custom Outbound config file at: %s", panelConfig.OutboundConfigPath)
|
||||||
} else {
|
} else {
|
||||||
if err = json.Unmarshal(data, &coreCustomOutboundConfig); err != nil {
|
if err = json.Unmarshal(data, &coreCustomOutboundConfig); err != nil {
|
||||||
@@ -113,7 +115,7 @@ func (p *Panel) loadCore(panelConfig *Config) *core.Instance {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
outBoundConfig := []*core.OutboundHandlerConfig{}
|
var outBoundConfig []*core.OutboundHandlerConfig
|
||||||
for _, config := range coreCustomOutboundConfig {
|
for _, config := range coreCustomOutboundConfig {
|
||||||
oc, err := config.Build()
|
oc, err := config.Build()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -122,7 +124,7 @@ func (p *Panel) loadCore(panelConfig *Config) *core.Instance {
|
|||||||
outBoundConfig = append(outBoundConfig, oc)
|
outBoundConfig = append(outBoundConfig, oc)
|
||||||
}
|
}
|
||||||
// Policy config
|
// Policy config
|
||||||
levelPolicyConfig := parseConnectionConfig(panelConfig.ConnetionConfig)
|
levelPolicyConfig := parseConnectionConfig(panelConfig.ConnectionConfig)
|
||||||
corePolicyConfig := &conf.PolicyConfig{}
|
corePolicyConfig := &conf.PolicyConfig{}
|
||||||
corePolicyConfig.Levels = map[uint32]*conf.Policy{0: levelPolicyConfig}
|
corePolicyConfig.Levels = map[uint32]*conf.Policy{0: levelPolicyConfig}
|
||||||
policyConfig, _ := corePolicyConfig.Build()
|
policyConfig, _ := corePolicyConfig.Build()
|
||||||
@@ -150,7 +152,7 @@ func (p *Panel) loadCore(panelConfig *Config) *core.Instance {
|
|||||||
return server
|
return server
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start Start the panel
|
// Start the panel
|
||||||
func (p *Panel) Start() {
|
func (p *Panel) Start() {
|
||||||
p.access.Lock()
|
p.access.Lock()
|
||||||
defer p.access.Unlock()
|
defer p.access.Unlock()
|
||||||
@@ -161,14 +163,18 @@ func (p *Panel) Start() {
|
|||||||
log.Panicf("Failed to start instance: %s", err)
|
log.Panicf("Failed to start instance: %s", err)
|
||||||
}
|
}
|
||||||
p.Server = server
|
p.Server = server
|
||||||
|
|
||||||
// Load Nodes config
|
// Load Nodes config
|
||||||
for _, nodeConfig := range p.panelConfig.NodesConfig {
|
for _, nodeConfig := range p.panelConfig.NodesConfig {
|
||||||
var apiClient api.API
|
var apiClient api.API
|
||||||
switch nodeConfig.PanelType {
|
switch nodeConfig.PanelType {
|
||||||
case "SSpanel":
|
case "SSpanel":
|
||||||
apiClient = sspanel.New(nodeConfig.ApiConfig)
|
apiClient = sspanel.New(nodeConfig.ApiConfig)
|
||||||
|
// todo Deprecated after 2023.6.1
|
||||||
case "V2board":
|
case "V2board":
|
||||||
apiClient = v2board.New(nodeConfig.ApiConfig)
|
apiClient = v2board.New(nodeConfig.ApiConfig)
|
||||||
|
case "NewV2board":
|
||||||
|
apiClient = newV2board.New(nodeConfig.ApiConfig)
|
||||||
case "PMpanel":
|
case "PMpanel":
|
||||||
apiClient = pmpanel.New(nodeConfig.ApiConfig)
|
apiClient = pmpanel.New(nodeConfig.ApiConfig)
|
||||||
case "Proxypanel":
|
case "Proxypanel":
|
||||||
@@ -202,7 +208,7 @@ func (p *Panel) Start() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close Close the panel
|
// Close the panel
|
||||||
func (p *Panel) Close() {
|
func (p *Panel) Close() {
|
||||||
p.access.Lock()
|
p.access.Lock()
|
||||||
defer p.access.Unlock()
|
defer p.access.Unlock()
|
||||||
@@ -218,21 +224,21 @@ func (p *Panel) Close() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseConnectionConfig(c *ConnetionConfig) (policy *conf.Policy) {
|
func parseConnectionConfig(c *ConnectionConfig) (policy *conf.Policy) {
|
||||||
connetionConfig := getDefaultConnetionConfig()
|
connectionConfig := getDefaultConnectionConfig()
|
||||||
if c != nil {
|
if c != nil {
|
||||||
if _, err := diff.Merge(connetionConfig, c, connetionConfig); err != nil {
|
if _, err := diff.Merge(connectionConfig, c, connectionConfig); err != nil {
|
||||||
log.Panicf("Read ConnetionConfig failed: %s", err)
|
log.Panicf("Read ConnectionConfig failed: %s", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
policy = &conf.Policy{
|
policy = &conf.Policy{
|
||||||
StatsUserUplink: true,
|
StatsUserUplink: true,
|
||||||
StatsUserDownlink: true,
|
StatsUserDownlink: true,
|
||||||
Handshake: &connetionConfig.Handshake,
|
Handshake: &connectionConfig.Handshake,
|
||||||
ConnectionIdle: &connetionConfig.ConnIdle,
|
ConnectionIdle: &connectionConfig.ConnIdle,
|
||||||
UplinkOnly: &connetionConfig.UplinkOnly,
|
UplinkOnly: &connectionConfig.UplinkOnly,
|
||||||
DownlinkOnly: &connetionConfig.DownlinkOnly,
|
DownlinkOnly: &connectionConfig.DownlinkOnly,
|
||||||
BufferSize: &connetionConfig.BufferSize,
|
BufferSize: &connectionConfig.BufferSize,
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
|
@@ -1,20 +1,26 @@
|
|||||||
package controller
|
package controller
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/XrayR-project/XrayR/common/limiter"
|
||||||
|
"github.com/XrayR-project/XrayR/common/mylego"
|
||||||
|
)
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
ListenIP string `mapstructure:"ListenIP"`
|
ListenIP string `mapstructure:"ListenIP"`
|
||||||
SendIP string `mapstructure:"SendIP"`
|
SendIP string `mapstructure:"SendIP"`
|
||||||
UpdatePeriodic int `mapstructure:"UpdatePeriodic"`
|
UpdatePeriodic int `mapstructure:"UpdatePeriodic"`
|
||||||
CertConfig *CertConfig `mapstructure:"CertConfig"`
|
CertConfig *mylego.CertConfig `mapstructure:"CertConfig"`
|
||||||
EnableDNS bool `mapstructure:"EnableDNS"`
|
EnableDNS bool `mapstructure:"EnableDNS"`
|
||||||
DNSType string `mapstructure:"DNSType"`
|
DNSType string `mapstructure:"DNSType"`
|
||||||
DisableUploadTraffic bool `mapstructure:"DisableUploadTraffic"`
|
DisableUploadTraffic bool `mapstructure:"DisableUploadTraffic"`
|
||||||
DisableGetRule bool `mapstructure:"DisableGetRule"`
|
DisableGetRule bool `mapstructure:"DisableGetRule"`
|
||||||
EnableProxyProtocol bool `mapstructure:"EnableProxyProtocol"`
|
EnableProxyProtocol bool `mapstructure:"EnableProxyProtocol"`
|
||||||
EnableFallback bool `mapstructure:"EnableFallback"`
|
EnableFallback bool `mapstructure:"EnableFallback"`
|
||||||
DisableIVCheck bool `mapstructure:"DisableIVCheck"`
|
DisableIVCheck bool `mapstructure:"DisableIVCheck"`
|
||||||
DisableSniffing bool `mapstructure:"DisableSniffing"`
|
DisableSniffing bool `mapstructure:"DisableSniffing"`
|
||||||
AutoSpeedLimitConfig *AutoSpeedLimitConfig `mapstructure:"AutoSpeedLimitConfig"`
|
AutoSpeedLimitConfig *AutoSpeedLimitConfig `mapstructure:"AutoSpeedLimitConfig"`
|
||||||
FallBackConfigs []*FallBackConfig `mapstructure:"FallBackConfigs"`
|
GlobalDeviceLimitConfig *limiter.GlobalDeviceLimitConfig `mapstructure:"GlobalDeviceLimitConfig"`
|
||||||
|
FallBackConfigs []*FallBackConfig `mapstructure:"FallBackConfigs"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type AutoSpeedLimitConfig struct {
|
type AutoSpeedLimitConfig struct {
|
||||||
@@ -24,17 +30,6 @@ type AutoSpeedLimitConfig struct {
|
|||||||
LimitDuration int `mapstructure:"LimitDuration"` // minute
|
LimitDuration int `mapstructure:"LimitDuration"` // minute
|
||||||
}
|
}
|
||||||
|
|
||||||
type CertConfig struct {
|
|
||||||
CertMode string `mapstructure:"CertMode"` // none, file, http, dns
|
|
||||||
RejectUnknownSni bool `mapstructure:"RejectUnknownSni"`
|
|
||||||
CertDomain string `mapstructure:"CertDomain"`
|
|
||||||
CertFile string `mapstructure:"CertFile"`
|
|
||||||
KeyFile string `mapstructure:"KeyFile"`
|
|
||||||
Provider string `mapstructure:"Provider"` // alidns, cloudflare, gandi, godaddy....
|
|
||||||
Email string `mapstructure:"Email"`
|
|
||||||
DNSEnv map[string]string `mapstructure:"DNSEnv"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type FallBackConfig struct {
|
type FallBackConfig struct {
|
||||||
SNI string `mapstructure:"SNI"`
|
SNI string `mapstructure:"SNI"`
|
||||||
Alpn string `mapstructure:"Alpn"`
|
Alpn string `mapstructure:"Alpn"`
|
||||||
|
@@ -4,22 +4,24 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/XrayR-project/XrayR/api"
|
|
||||||
"github.com/xtls/xray-core/common/protocol"
|
"github.com/xtls/xray-core/common/protocol"
|
||||||
"github.com/xtls/xray-core/core"
|
"github.com/xtls/xray-core/core"
|
||||||
"github.com/xtls/xray-core/features/inbound"
|
"github.com/xtls/xray-core/features/inbound"
|
||||||
"github.com/xtls/xray-core/features/outbound"
|
"github.com/xtls/xray-core/features/outbound"
|
||||||
"github.com/xtls/xray-core/features/stats"
|
"github.com/xtls/xray-core/features/stats"
|
||||||
"github.com/xtls/xray-core/proxy"
|
"github.com/xtls/xray-core/proxy"
|
||||||
|
|
||||||
|
"github.com/XrayR-project/XrayR/api"
|
||||||
|
"github.com/XrayR-project/XrayR/common/limiter"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c *Controller) removeInbound(tag string) error {
|
func (c *Controller) removeInbound(tag string) error {
|
||||||
err := c.ihm.RemoveHandler(context.Background(), tag)
|
err := c.ibm.RemoveHandler(context.Background(), tag)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Controller) removeOutbound(tag string) error {
|
func (c *Controller) removeOutbound(tag string) error {
|
||||||
err := c.ohm.RemoveHandler(context.Background(), tag)
|
err := c.obm.RemoveHandler(context.Background(), tag)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -32,7 +34,7 @@ func (c *Controller) addInbound(config *core.InboundHandlerConfig) error {
|
|||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("not an InboundHandler: %s", err)
|
return fmt.Errorf("not an InboundHandler: %s", err)
|
||||||
}
|
}
|
||||||
if err := c.ihm.AddHandler(context.Background(), handler); err != nil {
|
if err := c.ibm.AddHandler(context.Background(), handler); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@@ -47,16 +49,16 @@ func (c *Controller) addOutbound(config *core.OutboundHandlerConfig) error {
|
|||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("not an InboundHandler: %s", err)
|
return fmt.Errorf("not an InboundHandler: %s", err)
|
||||||
}
|
}
|
||||||
if err := c.ohm.AddHandler(context.Background(), handler); err != nil {
|
if err := c.obm.AddHandler(context.Background(), handler); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Controller) addUsers(users []*protocol.User, tag string) error {
|
func (c *Controller) addUsers(users []*protocol.User, tag string) error {
|
||||||
handler, err := c.ihm.GetHandler(context.Background(), tag)
|
handler, err := c.ibm.GetHandler(context.Background(), tag)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("No such inbound tag: %s", err)
|
return fmt.Errorf("no such inbound tag: %s", err)
|
||||||
}
|
}
|
||||||
inboundInstance, ok := handler.(proxy.GetInbound)
|
inboundInstance, ok := handler.(proxy.GetInbound)
|
||||||
if !ok {
|
if !ok {
|
||||||
@@ -81,9 +83,9 @@ func (c *Controller) addUsers(users []*protocol.User, tag string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Controller) removeUsers(users []string, tag string) error {
|
func (c *Controller) removeUsers(users []string, tag string) error {
|
||||||
handler, err := c.ihm.GetHandler(context.Background(), tag)
|
handler, err := c.ibm.GetHandler(context.Background(), tag)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("No such inbound tag: %s", err)
|
return fmt.Errorf("no such inbound tag: %s", err)
|
||||||
}
|
}
|
||||||
inboundInstance, ok := handler.(proxy.GetInbound)
|
inboundInstance, ok := handler.(proxy.GetInbound)
|
||||||
if !ok {
|
if !ok {
|
||||||
@@ -130,8 +132,8 @@ func (c *Controller) resetTraffic(upCounterList *[]stats.Counter, downCounterLis
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Controller) AddInboundLimiter(tag string, nodeSpeedLimit uint64, userList *[]api.UserInfo) error {
|
func (c *Controller) AddInboundLimiter(tag string, nodeSpeedLimit uint64, userList *[]api.UserInfo, globalDeviceLimitConfig *limiter.GlobalDeviceLimitConfig) error {
|
||||||
err := c.dispatcher.Limiter.AddInboundLimiter(tag, nodeSpeedLimit, userList)
|
err := c.dispatcher.Limiter.AddInboundLimiter(tag, nodeSpeedLimit, userList, globalDeviceLimitConfig)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -6,10 +6,6 @@ import (
|
|||||||
"reflect"
|
"reflect"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/XrayR-project/XrayR/api"
|
|
||||||
"github.com/XrayR-project/XrayR/app/mydispatcher"
|
|
||||||
"github.com/XrayR-project/XrayR/common/legocmd"
|
|
||||||
"github.com/XrayR-project/XrayR/common/serverstatus"
|
|
||||||
"github.com/xtls/xray-core/common/protocol"
|
"github.com/xtls/xray-core/common/protocol"
|
||||||
"github.com/xtls/xray-core/common/task"
|
"github.com/xtls/xray-core/common/task"
|
||||||
"github.com/xtls/xray-core/core"
|
"github.com/xtls/xray-core/core"
|
||||||
@@ -17,6 +13,11 @@ import (
|
|||||||
"github.com/xtls/xray-core/features/outbound"
|
"github.com/xtls/xray-core/features/outbound"
|
||||||
"github.com/xtls/xray-core/features/routing"
|
"github.com/xtls/xray-core/features/routing"
|
||||||
"github.com/xtls/xray-core/features/stats"
|
"github.com/xtls/xray-core/features/stats"
|
||||||
|
|
||||||
|
"github.com/XrayR-project/XrayR/api"
|
||||||
|
"github.com/XrayR-project/XrayR/app/mydispatcher"
|
||||||
|
"github.com/XrayR-project/XrayR/common/mylego"
|
||||||
|
"github.com/XrayR-project/XrayR/common/serverstatus"
|
||||||
)
|
)
|
||||||
|
|
||||||
type LimitInfo struct {
|
type LimitInfo struct {
|
||||||
@@ -26,22 +27,27 @@ type LimitInfo struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Controller struct {
|
type Controller struct {
|
||||||
server *core.Instance
|
server *core.Instance
|
||||||
config *Config
|
config *Config
|
||||||
clientInfo api.ClientInfo
|
clientInfo api.ClientInfo
|
||||||
apiClient api.API
|
apiClient api.API
|
||||||
nodeInfo *api.NodeInfo
|
nodeInfo *api.NodeInfo
|
||||||
Tag string
|
Tag string
|
||||||
userList *[]api.UserInfo
|
userList *[]api.UserInfo
|
||||||
nodeInfoMonitorPeriodic *task.Periodic
|
tasks []periodicTask
|
||||||
userReportPeriodic *task.Periodic
|
limitedUsers map[api.UserInfo]LimitInfo
|
||||||
limitedUsers map[api.UserInfo]LimitInfo
|
warnedUsers map[api.UserInfo]int
|
||||||
warnedUsers map[api.UserInfo]int
|
panelType string
|
||||||
panelType string
|
ibm inbound.Manager
|
||||||
ihm inbound.Manager
|
obm outbound.Manager
|
||||||
ohm outbound.Manager
|
stm stats.Manager
|
||||||
stm stats.Manager
|
dispatcher *mydispatcher.DefaultDispatcher
|
||||||
dispatcher *mydispatcher.DefaultDispatcher
|
startAt time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
type periodicTask struct {
|
||||||
|
tag string
|
||||||
|
*task.Periodic
|
||||||
}
|
}
|
||||||
|
|
||||||
// New return a Controller service with default parameters.
|
// New return a Controller service with default parameters.
|
||||||
@@ -51,11 +57,13 @@ func New(server *core.Instance, api api.API, config *Config, panelType string) *
|
|||||||
config: config,
|
config: config,
|
||||||
apiClient: api,
|
apiClient: api,
|
||||||
panelType: panelType,
|
panelType: panelType,
|
||||||
ihm: server.GetFeature(inbound.ManagerType()).(inbound.Manager),
|
ibm: server.GetFeature(inbound.ManagerType()).(inbound.Manager),
|
||||||
ohm: server.GetFeature(outbound.ManagerType()).(outbound.Manager),
|
obm: server.GetFeature(outbound.ManagerType()).(outbound.Manager),
|
||||||
stm: server.GetFeature(stats.ManagerType()).(stats.Manager),
|
stm: server.GetFeature(stats.ManagerType()).(stats.Manager),
|
||||||
dispatcher: server.GetFeature(routing.DispatcherType()).(*mydispatcher.DefaultDispatcher),
|
dispatcher: server.GetFeature(routing.DispatcherType()).(*mydispatcher.DefaultDispatcher),
|
||||||
|
startAt: time.Now(),
|
||||||
}
|
}
|
||||||
|
|
||||||
return controller
|
return controller
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,17 +89,19 @@ func (c *Controller) Start() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// sync controller userList
|
||||||
|
c.userList = userInfo
|
||||||
|
|
||||||
err = c.addNewUser(userInfo, newNodeInfo)
|
err = c.addNewUser(userInfo, newNodeInfo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
//sync controller userList
|
|
||||||
c.userList = userInfo
|
|
||||||
|
|
||||||
// Add Limiter
|
// Add Limiter
|
||||||
if err := c.AddInboundLimiter(c.Tag, newNodeInfo.SpeedLimit, userInfo); err != nil {
|
if err := c.AddInboundLimiter(c.Tag, newNodeInfo.SpeedLimit, userInfo, c.config.GlobalDeviceLimitConfig); err != nil {
|
||||||
log.Print(err)
|
log.Print(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add Rule Manager
|
// Add Rule Manager
|
||||||
if !c.config.DisableGetRule {
|
if !c.config.DisableGetRule {
|
||||||
if ruleList, err := c.apiClient.GetNodeRule(); err != nil {
|
if ruleList, err := c.apiClient.GetNodeRule(); err != nil {
|
||||||
@@ -102,14 +112,8 @@ func (c *Controller) Start() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
c.nodeInfoMonitorPeriodic = &task.Periodic{
|
|
||||||
Interval: time.Duration(c.config.UpdatePeriodic) * time.Second,
|
// Init AutoSpeedLimitConfig
|
||||||
Execute: c.nodeInfoMonitor,
|
|
||||||
}
|
|
||||||
c.userReportPeriodic = &task.Periodic{
|
|
||||||
Interval: time.Duration(c.config.UpdatePeriodic) * time.Second,
|
|
||||||
Execute: c.userInfoMonitor,
|
|
||||||
}
|
|
||||||
if c.config.AutoSpeedLimitConfig == nil {
|
if c.config.AutoSpeedLimitConfig == nil {
|
||||||
c.config.AutoSpeedLimitConfig = &AutoSpeedLimitConfig{0, 0, 0, 0}
|
c.config.AutoSpeedLimitConfig = &AutoSpeedLimitConfig{0, 0, 0, 0}
|
||||||
}
|
}
|
||||||
@@ -117,41 +121,61 @@ func (c *Controller) Start() error {
|
|||||||
c.limitedUsers = make(map[api.UserInfo]LimitInfo)
|
c.limitedUsers = make(map[api.UserInfo]LimitInfo)
|
||||||
c.warnedUsers = make(map[api.UserInfo]int)
|
c.warnedUsers = make(map[api.UserInfo]int)
|
||||||
}
|
}
|
||||||
log.Printf("[%s: %d] Start monitor node status", c.nodeInfo.NodeType, c.nodeInfo.NodeID)
|
|
||||||
// delay to start nodeInfoMonitor
|
|
||||||
go func() {
|
|
||||||
time.Sleep(time.Duration(c.config.UpdatePeriodic) * time.Second)
|
|
||||||
_ = c.nodeInfoMonitorPeriodic.Start()
|
|
||||||
}()
|
|
||||||
|
|
||||||
log.Printf("[%s: %d] Start report node status", c.nodeInfo.NodeType, c.nodeInfo.NodeID)
|
// Add periodic tasks
|
||||||
// delay to start userReport
|
c.tasks = append(c.tasks,
|
||||||
go func() {
|
periodicTask{
|
||||||
time.Sleep(time.Duration(c.config.UpdatePeriodic) * time.Second)
|
tag: "node monitor",
|
||||||
_ = c.userReportPeriodic.Start()
|
Periodic: &task.Periodic{
|
||||||
}()
|
Interval: time.Duration(c.config.UpdatePeriodic) * time.Second,
|
||||||
|
Execute: c.nodeInfoMonitor,
|
||||||
|
}},
|
||||||
|
periodicTask{
|
||||||
|
tag: "user monitor",
|
||||||
|
Periodic: &task.Periodic{
|
||||||
|
Interval: time.Duration(c.config.UpdatePeriodic) * time.Second,
|
||||||
|
Execute: c.userInfoMonitor,
|
||||||
|
}},
|
||||||
|
)
|
||||||
|
|
||||||
|
// Check cert service in need
|
||||||
|
if c.nodeInfo.EnableTLS {
|
||||||
|
c.tasks = append(c.tasks, periodicTask{
|
||||||
|
tag: "cert monitor",
|
||||||
|
Periodic: &task.Periodic{
|
||||||
|
Interval: time.Duration(c.config.UpdatePeriodic) * time.Second * 60,
|
||||||
|
Execute: c.certMonitor,
|
||||||
|
}})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start periodic tasks
|
||||||
|
for i := range c.tasks {
|
||||||
|
log.Printf("%s Start %s periodic task", c.logPrefix(), c.tasks[i].tag)
|
||||||
|
go c.tasks[i].Start()
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close implement the Close() function of the service interface
|
// Close implement the Close() function of the service interface
|
||||||
func (c *Controller) Close() error {
|
func (c *Controller) Close() error {
|
||||||
if c.nodeInfoMonitorPeriodic != nil {
|
for i := range c.tasks {
|
||||||
err := c.nodeInfoMonitorPeriodic.Close()
|
if c.tasks[i].Periodic != nil {
|
||||||
if err != nil {
|
if err := c.tasks[i].Periodic.Close(); err != nil {
|
||||||
log.Panicf("node info periodic close failed: %s", err)
|
log.Panicf("%s %s periodic task close failed: %s", c.logPrefix(), c.tasks[i].tag, err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.nodeInfoMonitorPeriodic != nil {
|
|
||||||
err := c.userReportPeriodic.Close()
|
|
||||||
if err != nil {
|
|
||||||
log.Panicf("user report periodic close failed: %s", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Controller) nodeInfoMonitor() (err error) {
|
func (c *Controller) nodeInfoMonitor() (err error) {
|
||||||
|
// delay to start
|
||||||
|
if time.Since(c.startAt) < time.Duration(c.config.UpdatePeriodic)*time.Second {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// First fetch Node Info
|
// First fetch Node Info
|
||||||
newNodeInfo, err := c.apiClient.GetNodeInfo()
|
newNodeInfo, err := c.apiClient.GetNodeInfo()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -160,18 +184,24 @@ func (c *Controller) nodeInfoMonitor() (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Update User
|
// Update User
|
||||||
|
var usersChanged = true
|
||||||
newUserInfo, err := c.apiClient.GetUserList()
|
newUserInfo, err := c.apiClient.GetUserList()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Print(err)
|
if err.Error() == "users no change" {
|
||||||
return nil
|
usersChanged = false
|
||||||
|
newUserInfo = c.userList
|
||||||
|
} else {
|
||||||
|
log.Print(err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var nodeInfoChanged = false
|
var nodeInfoChanged = false
|
||||||
// If nodeInfo changed
|
// If nodeInfo changed
|
||||||
if !reflect.DeepEqual(c.nodeInfo, newNodeInfo) {
|
if !reflect.DeepEqual(c.nodeInfo, newNodeInfo) {
|
||||||
// Remove old tag
|
// Remove old tag
|
||||||
oldtag := c.Tag
|
oldTag := c.Tag
|
||||||
err := c.removeOldTag(oldtag)
|
err := c.removeOldTag(oldTag)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Print(err)
|
log.Print(err)
|
||||||
return nil
|
return nil
|
||||||
@@ -193,7 +223,7 @@ func (c *Controller) nodeInfoMonitor() (err error) {
|
|||||||
}
|
}
|
||||||
nodeInfoChanged = true
|
nodeInfoChanged = true
|
||||||
// Remove Old limiter
|
// Remove Old limiter
|
||||||
if err = c.DeleteInboundLimiter(oldtag); err != nil {
|
if err = c.DeleteInboundLimiter(oldTag); err != nil {
|
||||||
log.Print(err)
|
log.Print(err)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -210,64 +240,55 @@ func (c *Controller) nodeInfoMonitor() (err error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check Cert
|
|
||||||
if c.nodeInfo.EnableTLS && (c.config.CertConfig.CertMode == "dns" || c.config.CertConfig.CertMode == "http") {
|
|
||||||
lego, err := legocmd.New()
|
|
||||||
if err != nil {
|
|
||||||
log.Print(err)
|
|
||||||
}
|
|
||||||
// Xray-core supports the OcspStapling certification hot renew
|
|
||||||
_, _, err = lego.RenewCert(c.config.CertConfig.CertDomain, c.config.CertConfig.Email, c.config.CertConfig.CertMode, c.config.CertConfig.Provider, c.config.CertConfig.DNSEnv)
|
|
||||||
if err != nil {
|
|
||||||
log.Print(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if nodeInfoChanged {
|
if nodeInfoChanged {
|
||||||
err = c.addNewUser(newUserInfo, newNodeInfo)
|
err = c.addNewUser(newUserInfo, newNodeInfo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Print(err)
|
log.Print(err)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add Limiter
|
// Add Limiter
|
||||||
if err := c.AddInboundLimiter(c.Tag, newNodeInfo.SpeedLimit, newUserInfo); err != nil {
|
if err := c.AddInboundLimiter(c.Tag, newNodeInfo.SpeedLimit, newUserInfo, c.config.GlobalDeviceLimitConfig); err != nil {
|
||||||
log.Print(err)
|
log.Print(err)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
deleted, added := compareUserList(c.userList, newUserInfo)
|
var deleted, added []api.UserInfo
|
||||||
if len(deleted) > 0 {
|
if usersChanged {
|
||||||
deletedEmail := make([]string, len(deleted))
|
deleted, added = compareUserList(c.userList, newUserInfo)
|
||||||
for i, u := range deleted {
|
if len(deleted) > 0 {
|
||||||
deletedEmail[i] = fmt.Sprintf("%s|%s|%d", c.Tag, u.Email, u.UID)
|
deletedEmail := make([]string, len(deleted))
|
||||||
|
for i, u := range deleted {
|
||||||
|
deletedEmail[i] = fmt.Sprintf("%s|%s|%d", c.Tag, u.Email, u.UID)
|
||||||
|
}
|
||||||
|
err := c.removeUsers(deletedEmail, c.Tag)
|
||||||
|
if err != nil {
|
||||||
|
log.Print(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
err := c.removeUsers(deletedEmail, c.Tag)
|
if len(added) > 0 {
|
||||||
if err != nil {
|
err = c.addNewUser(&added, c.nodeInfo)
|
||||||
log.Print(err)
|
if err != nil {
|
||||||
|
log.Print(err)
|
||||||
|
}
|
||||||
|
// Update Limiter
|
||||||
|
if err := c.UpdateInboundLimiter(c.Tag, &added); err != nil {
|
||||||
|
log.Print(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(added) > 0 {
|
log.Printf("%s %d user deleted, %d user added", c.logPrefix(), len(deleted), len(added))
|
||||||
err = c.addNewUser(&added, c.nodeInfo)
|
|
||||||
if err != nil {
|
|
||||||
log.Print(err)
|
|
||||||
}
|
|
||||||
// Update Limiter
|
|
||||||
if err := c.UpdateInboundLimiter(c.Tag, &added); err != nil {
|
|
||||||
log.Print(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
log.Printf("[%s: %d] %d user deleted, %d user added", c.nodeInfo.NodeType, c.nodeInfo.NodeID, len(deleted), len(added))
|
|
||||||
}
|
}
|
||||||
c.userList = newUserInfo
|
c.userList = newUserInfo
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Controller) removeOldTag(oldtag string) (err error) {
|
func (c *Controller) removeOldTag(oldTag string) (err error) {
|
||||||
err = c.removeInbound(oldtag)
|
err = c.removeInbound(oldTag)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = c.removeOutbound(oldtag)
|
err = c.removeOutbound(oldTag)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -303,7 +324,7 @@ func (c *Controller) addNewTag(newNodeInfo *api.NodeInfo) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Controller) addInboundForSSPlugin(newNodeInfo api.NodeInfo) (err error) {
|
func (c *Controller) addInboundForSSPlugin(newNodeInfo api.NodeInfo) (err error) {
|
||||||
// Shadowsocks-Plugin require a seaperate inbound for other TransportProtocol likes: ws, grpc
|
// Shadowsocks-Plugin require a separate inbound for other TransportProtocol likes: ws, grpc
|
||||||
fakeNodeInfo := newNodeInfo
|
fakeNodeInfo := newNodeInfo
|
||||||
fakeNodeInfo.TransportProtocol = "tcp"
|
fakeNodeInfo.TransportProtocol = "tcp"
|
||||||
fakeNodeInfo.EnableTLS = false
|
fakeNodeInfo.EnableTLS = false
|
||||||
@@ -356,7 +377,8 @@ func (c *Controller) addInboundForSSPlugin(newNodeInfo api.NodeInfo) (err error)
|
|||||||
|
|
||||||
func (c *Controller) addNewUser(userInfo *[]api.UserInfo, nodeInfo *api.NodeInfo) (err error) {
|
func (c *Controller) addNewUser(userInfo *[]api.UserInfo, nodeInfo *api.NodeInfo) (err error) {
|
||||||
users := make([]*protocol.User, 0)
|
users := make([]*protocol.User, 0)
|
||||||
if nodeInfo.NodeType == "V2ray" {
|
switch nodeInfo.NodeType {
|
||||||
|
case "V2ray":
|
||||||
if nodeInfo.EnableVless {
|
if nodeInfo.EnableVless {
|
||||||
users = c.buildVlessUser(userInfo)
|
users = c.buildVlessUser(userInfo)
|
||||||
} else {
|
} else {
|
||||||
@@ -369,51 +391,52 @@ func (c *Controller) addNewUser(userInfo *[]api.UserInfo, nodeInfo *api.NodeInfo
|
|||||||
}
|
}
|
||||||
users = c.buildVmessUser(userInfo, alterID)
|
users = c.buildVmessUser(userInfo, alterID)
|
||||||
}
|
}
|
||||||
} else if nodeInfo.NodeType == "Trojan" {
|
case "Trojan":
|
||||||
users = c.buildTrojanUser(userInfo)
|
users = c.buildTrojanUser(userInfo)
|
||||||
} else if nodeInfo.NodeType == "Shadowsocks" {
|
case "Shadowsocks":
|
||||||
users = c.buildSSUser(userInfo, nodeInfo.CypherMethod)
|
users = c.buildSSUser(userInfo, nodeInfo.CypherMethod)
|
||||||
} else if nodeInfo.NodeType == "Shadowsocks-Plugin" {
|
case "Shadowsocks-Plugin":
|
||||||
users = c.buildSSPluginUser(userInfo)
|
users = c.buildSSPluginUser(userInfo)
|
||||||
} else {
|
default:
|
||||||
return fmt.Errorf("unsupported node type: %s", nodeInfo.NodeType)
|
return fmt.Errorf("unsupported node type: %s", nodeInfo.NodeType)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = c.addUsers(users, c.Tag)
|
err = c.addUsers(users, c.Tag)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
log.Printf("[%s: %d] Added %d new users", c.nodeInfo.NodeType, c.nodeInfo.NodeID, len(*userInfo))
|
log.Printf("%s Added %d new users", c.logPrefix(), len(*userInfo))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func compareUserList(old, new *[]api.UserInfo) (deleted, added []api.UserInfo) {
|
func compareUserList(old, new *[]api.UserInfo) (deleted, added []api.UserInfo) {
|
||||||
msrc := make(map[api.UserInfo]byte) //按源数组建索引
|
mSrc := make(map[api.UserInfo]byte) // 按源数组建索引
|
||||||
mall := make(map[api.UserInfo]byte) //源+目所有元素建索引
|
mAll := make(map[api.UserInfo]byte) // 源+目所有元素建索引
|
||||||
|
|
||||||
var set []api.UserInfo //交集
|
var set []api.UserInfo // 交集
|
||||||
|
|
||||||
//1.源数组建立map
|
// 1.源数组建立map
|
||||||
for _, v := range *old {
|
for _, v := range *old {
|
||||||
msrc[v] = 0
|
mSrc[v] = 0
|
||||||
mall[v] = 0
|
mAll[v] = 0
|
||||||
}
|
}
|
||||||
//2.目数组中,存不进去,即重复元素,所有存不进去的集合就是并集
|
// 2.目数组中,存不进去,即重复元素,所有存不进去的集合就是并集
|
||||||
for _, v := range *new {
|
for _, v := range *new {
|
||||||
l := len(mall)
|
l := len(mAll)
|
||||||
mall[v] = 1
|
mAll[v] = 1
|
||||||
if l != len(mall) { //长度变化,即可以存
|
if l != len(mAll) { // 长度变化,即可以存
|
||||||
l = len(mall)
|
l = len(mAll)
|
||||||
} else { //存不了,进并集
|
} else { // 存不了,进并集
|
||||||
set = append(set, v)
|
set = append(set, v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//3.遍历交集,在并集中找,找到就从并集中删,删完后就是补集(即并-交=所有变化的元素)
|
// 3.遍历交集,在并集中找,找到就从并集中删,删完后就是补集(即并-交=所有变化的元素)
|
||||||
for _, v := range set {
|
for _, v := range set {
|
||||||
delete(mall, v)
|
delete(mAll, v)
|
||||||
}
|
}
|
||||||
//4.此时,mall是补集,所有元素去源中找,找到就是删除的,找不到的必定能在目数组中找到,即新加的
|
// 4.此时,mall是补集,所有元素去源中找,找到就是删除的,找不到的必定能在目数组中找到,即新加的
|
||||||
for v := range mall {
|
for v := range mAll {
|
||||||
_, exist := msrc[v]
|
_, exist := mSrc[v]
|
||||||
if exist {
|
if exist {
|
||||||
deleted = append(deleted, v)
|
deleted = append(deleted, v)
|
||||||
} else {
|
} else {
|
||||||
@@ -436,6 +459,11 @@ func limitUser(c *Controller, user api.UserInfo, silentUsers *[]api.UserInfo) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Controller) userInfoMonitor() (err error) {
|
func (c *Controller) userInfoMonitor() (err error) {
|
||||||
|
// delay to start
|
||||||
|
if time.Since(c.startAt) < time.Duration(c.config.UpdatePeriodic)*time.Second {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// Get server status
|
// Get server status
|
||||||
CPU, Mem, Disk, Uptime, err := serverstatus.GetSystemInfo()
|
CPU, Mem, Disk, Uptime, err := serverstatus.GetSystemInfo()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -453,7 +481,7 @@ func (c *Controller) userInfoMonitor() (err error) {
|
|||||||
}
|
}
|
||||||
// Unlock users
|
// Unlock users
|
||||||
if c.config.AutoSpeedLimitConfig.Limit > 0 && len(c.limitedUsers) > 0 {
|
if c.config.AutoSpeedLimitConfig.Limit > 0 && len(c.limitedUsers) > 0 {
|
||||||
log.Printf("Limited users:")
|
log.Printf("%s Limited users:", c.logPrefix())
|
||||||
toReleaseUsers := make([]api.UserInfo, 0)
|
toReleaseUsers := make([]api.UserInfo, 0)
|
||||||
for user, limitInfo := range c.limitedUsers {
|
for user, limitInfo := range c.limitedUsers {
|
||||||
if time.Now().Unix() > limitInfo.end {
|
if time.Now().Unix() > limitInfo.end {
|
||||||
@@ -541,9 +569,10 @@ func (c *Controller) userInfoMonitor() (err error) {
|
|||||||
if err = c.apiClient.ReportNodeOnlineUsers(onlineDevice); err != nil {
|
if err = c.apiClient.ReportNodeOnlineUsers(onlineDevice); err != nil {
|
||||||
log.Print(err)
|
log.Print(err)
|
||||||
} else {
|
} else {
|
||||||
log.Printf("[%s: %d] Report %d online users", c.nodeInfo.NodeType, c.nodeInfo.NodeID, len(*onlineDevice))
|
log.Printf("%s Report %d online users", c.logPrefix(), len(*onlineDevice))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Report Illegal user
|
// Report Illegal user
|
||||||
if detectResult, err := c.GetDetectResult(c.Tag); err != nil {
|
if detectResult, err := c.GetDetectResult(c.Tag); err != nil {
|
||||||
log.Print(err)
|
log.Print(err)
|
||||||
@@ -551,7 +580,7 @@ func (c *Controller) userInfoMonitor() (err error) {
|
|||||||
if err = c.apiClient.ReportIllegal(detectResult); err != nil {
|
if err = c.apiClient.ReportIllegal(detectResult); err != nil {
|
||||||
log.Print(err)
|
log.Print(err)
|
||||||
} else {
|
} else {
|
||||||
log.Printf("[%s: %d] Report %d illegal behaviors", c.nodeInfo.NodeType, c.nodeInfo.NodeID, len(*detectResult))
|
log.Printf("%s Report %d illegal behaviors", c.logPrefix(), len(*detectResult))
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -561,3 +590,26 @@ func (c *Controller) userInfoMonitor() (err error) {
|
|||||||
func (c *Controller) buildNodeTag() string {
|
func (c *Controller) buildNodeTag() string {
|
||||||
return fmt.Sprintf("%s_%s_%d", c.nodeInfo.NodeType, c.config.ListenIP, c.nodeInfo.Port)
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check Cert
|
||||||
|
func (c *Controller) certMonitor() error {
|
||||||
|
if c.nodeInfo.EnableTLS {
|
||||||
|
switch c.config.CertConfig.CertMode {
|
||||||
|
case "dns", "http", "tls":
|
||||||
|
lego, err := mylego.New(c.config.CertConfig)
|
||||||
|
if err != nil {
|
||||||
|
log.Print(err)
|
||||||
|
}
|
||||||
|
// Xray-core supports the OcspStapling certification hot renew
|
||||||
|
_, _, _, err = lego.RenewCert()
|
||||||
|
if err != nil {
|
||||||
|
log.Print(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@@ -8,12 +8,14 @@ import (
|
|||||||
"syscall"
|
"syscall"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/XrayR-project/XrayR/api"
|
|
||||||
"github.com/XrayR-project/XrayR/api/sspanel"
|
|
||||||
_ "github.com/XrayR-project/XrayR/main/distro/all"
|
|
||||||
. "github.com/XrayR-project/XrayR/service/controller"
|
|
||||||
"github.com/xtls/xray-core/core"
|
"github.com/xtls/xray-core/core"
|
||||||
"github.com/xtls/xray-core/infra/conf"
|
"github.com/xtls/xray-core/infra/conf"
|
||||||
|
|
||||||
|
"github.com/XrayR-project/XrayR/api"
|
||||||
|
"github.com/XrayR-project/XrayR/api/sspanel"
|
||||||
|
"github.com/XrayR-project/XrayR/common/mylego"
|
||||||
|
_ "github.com/XrayR-project/XrayR/main/distro/all"
|
||||||
|
. "github.com/XrayR-project/XrayR/service/controller"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestController(t *testing.T) {
|
func TestController(t *testing.T) {
|
||||||
@@ -22,7 +24,7 @@ func TestController(t *testing.T) {
|
|||||||
LogConfig: &conf.LogConfig{LogLevel: "debug"},
|
LogConfig: &conf.LogConfig{LogLevel: "debug"},
|
||||||
}
|
}
|
||||||
policyConfig := &conf.PolicyConfig{}
|
policyConfig := &conf.PolicyConfig{}
|
||||||
policyConfig.Levels = map[uint32]*conf.Policy{0: &conf.Policy{
|
policyConfig.Levels = map[uint32]*conf.Policy{0: {
|
||||||
StatsUserUplink: true,
|
StatsUserUplink: true,
|
||||||
StatsUserDownlink: true,
|
StatsUserDownlink: true,
|
||||||
}}
|
}}
|
||||||
@@ -45,13 +47,13 @@ func TestController(t *testing.T) {
|
|||||||
if err = server.Start(); err != nil {
|
if err = server.Start(); err != nil {
|
||||||
t.Errorf("Failed to start instance: %s", err)
|
t.Errorf("Failed to start instance: %s", err)
|
||||||
}
|
}
|
||||||
certConfig := &CertConfig{
|
certConfig := &mylego.CertConfig{
|
||||||
CertMode: "http",
|
CertMode: "http",
|
||||||
CertDomain: "test.ss.tk",
|
CertDomain: "test.ss.tk",
|
||||||
Provider: "alidns",
|
Provider: "alidns",
|
||||||
Email: "ss@ss.com",
|
Email: "ss@ss.com",
|
||||||
}
|
}
|
||||||
controlerconfig := &Config{
|
controlerConfig := &Config{
|
||||||
UpdatePeriodic: 5,
|
UpdatePeriodic: 5,
|
||||||
CertConfig: certConfig,
|
CertConfig: certConfig,
|
||||||
}
|
}
|
||||||
@@ -61,14 +63,14 @@ func TestController(t *testing.T) {
|
|||||||
NodeID: 41,
|
NodeID: 41,
|
||||||
NodeType: "V2ray",
|
NodeType: "V2ray",
|
||||||
}
|
}
|
||||||
apiclient := sspanel.New(apiConfig)
|
apiClient := sspanel.New(apiConfig)
|
||||||
c := New(server, apiclient, controlerconfig, "SSpanel")
|
c := New(server, apiClient, controlerConfig, "SSpanel")
|
||||||
fmt.Println("Sleep 1s")
|
fmt.Println("Sleep 1s")
|
||||||
err = c.Start()
|
err = c.Start()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
//Explicitly triggering GC to remove garbage from config loading.
|
// Explicitly triggering GC to remove garbage from config loading.
|
||||||
runtime.GC()
|
runtime.GC()
|
||||||
|
|
||||||
{
|
{
|
||||||
|
7
service/controller/errors.generated.go
Normal file
7
service/controller/errors.generated.go
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
package controller
|
||||||
|
|
||||||
|
import "github.com/xtls/xray-core/common/errors"
|
||||||
|
|
||||||
|
func newError(values ...interface{}) *errors.Error {
|
||||||
|
return errors.New(values...)
|
||||||
|
}
|
@@ -1,28 +1,34 @@
|
|||||||
//Package generate the InbounderConfig used by add inbound
|
// Package controller Package generate the InboundConfig used by add inbound
|
||||||
package controller
|
package controller
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/rand"
|
||||||
|
"encoding/base64"
|
||||||
|
"encoding/hex"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/XrayR-project/XrayR/api"
|
"github.com/sagernet/sing-shadowsocks/shadowaead_2022"
|
||||||
"github.com/XrayR-project/XrayR/common/legocmd"
|
C "github.com/sagernet/sing/common"
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
"github.com/xtls/xray-core/common/uuid"
|
|
||||||
"github.com/xtls/xray-core/core"
|
"github.com/xtls/xray-core/core"
|
||||||
"github.com/xtls/xray-core/infra/conf"
|
"github.com/xtls/xray-core/infra/conf"
|
||||||
|
|
||||||
|
"github.com/XrayR-project/XrayR/api"
|
||||||
|
"github.com/XrayR-project/XrayR/common/mylego"
|
||||||
)
|
)
|
||||||
|
|
||||||
//InboundBuilder build Inbound config for different protocol
|
// InboundBuilder build Inbound config for different protocol
|
||||||
func InboundBuilder(config *Config, nodeInfo *api.NodeInfo, tag string) (*core.InboundHandlerConfig, error) {
|
func InboundBuilder(config *Config, nodeInfo *api.NodeInfo, tag string) (*core.InboundHandlerConfig, error) {
|
||||||
inboundDetourConfig := &conf.InboundDetourConfig{}
|
inboundDetourConfig := &conf.InboundDetourConfig{}
|
||||||
// Build Listen IP address
|
// Build Listen IP address
|
||||||
if nodeInfo.NodeType == "Shadowsocks-Plugin" {
|
if nodeInfo.NodeType == "Shadowsocks-Plugin" {
|
||||||
// Shdowsocks listen in 127.0.0.1 for safety
|
// Shdowsocks listen in 127.0.0.1 for safety
|
||||||
inboundDetourConfig.ListenOn = &conf.Address{net.ParseAddress("127.0.0.1")}
|
inboundDetourConfig.ListenOn = &conf.Address{Address: net.ParseAddress("127.0.0.1")}
|
||||||
} else if config.ListenIP != "" {
|
} else if config.ListenIP != "" {
|
||||||
ipAddress := net.ParseAddress(config.ListenIP)
|
ipAddress := net.ParseAddress(config.ListenIP)
|
||||||
inboundDetourConfig.ListenOn = &conf.Address{ipAddress}
|
inboundDetourConfig.ListenOn = &conf.Address{Address: ipAddress}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build Port
|
// Build Port
|
||||||
@@ -48,9 +54,10 @@ func InboundBuilder(config *Config, nodeInfo *api.NodeInfo, tag string) (*core.I
|
|||||||
setting json.RawMessage
|
setting json.RawMessage
|
||||||
)
|
)
|
||||||
|
|
||||||
var proxySetting interface{}
|
var proxySetting any
|
||||||
// Build Protocol and Protocol setting
|
// Build Protocol and Protocol setting
|
||||||
if nodeInfo.NodeType == "V2ray" {
|
switch nodeInfo.NodeType {
|
||||||
|
case "V2ray":
|
||||||
if nodeInfo.EnableVless {
|
if nodeInfo.EnableVless {
|
||||||
protocol = "vless"
|
protocol = "vless"
|
||||||
// Enable fallback
|
// Enable fallback
|
||||||
@@ -73,7 +80,7 @@ func InboundBuilder(config *Config, nodeInfo *api.NodeInfo, tag string) (*core.I
|
|||||||
protocol = "vmess"
|
protocol = "vmess"
|
||||||
proxySetting = &conf.VMessInboundConfig{}
|
proxySetting = &conf.VMessInboundConfig{}
|
||||||
}
|
}
|
||||||
} else if nodeInfo.NodeType == "Trojan" {
|
case "Trojan":
|
||||||
protocol = "trojan"
|
protocol = "trojan"
|
||||||
// Enable fallback
|
// Enable fallback
|
||||||
if config.EnableFallback {
|
if config.EnableFallback {
|
||||||
@@ -88,23 +95,36 @@ func InboundBuilder(config *Config, nodeInfo *api.NodeInfo, tag string) (*core.I
|
|||||||
} else {
|
} else {
|
||||||
proxySetting = &conf.TrojanServerConfig{}
|
proxySetting = &conf.TrojanServerConfig{}
|
||||||
}
|
}
|
||||||
} else if nodeInfo.NodeType == "Shadowsocks" || nodeInfo.NodeType == "Shadowsocks-Plugin" {
|
case "Shadowsocks", "Shadowsocks-Plugin":
|
||||||
protocol = "shadowsocks"
|
protocol = "shadowsocks"
|
||||||
proxySetting = &conf.ShadowsocksServerConfig{}
|
cipher := strings.ToLower(nodeInfo.CypherMethod)
|
||||||
randomPasswd := uuid.New()
|
|
||||||
defaultSSuser := &conf.ShadowsocksUserConfig{
|
proxySetting = &conf.ShadowsocksServerConfig{
|
||||||
Cipher: "aes-128-gcm",
|
Cipher: cipher,
|
||||||
Password: randomPasswd.String(),
|
Password: nodeInfo.ServerKey, // shadowsocks2022 shareKey
|
||||||
}
|
}
|
||||||
|
|
||||||
proxySetting, _ := proxySetting.(*conf.ShadowsocksServerConfig)
|
proxySetting, _ := proxySetting.(*conf.ShadowsocksServerConfig)
|
||||||
proxySetting.Users = append(proxySetting.Users, defaultSSuser)
|
// shadowsocks must have a random password
|
||||||
|
// shadowsocks2022's password == user PSK, thus should a length of string >= 32 and base64 encoder
|
||||||
|
b := make([]byte, 32)
|
||||||
|
rand.Read(b)
|
||||||
|
randPasswd := hex.EncodeToString(b)
|
||||||
|
if C.Contains(shadowaead_2022.List, cipher) {
|
||||||
|
proxySetting.Users = append(proxySetting.Users, &conf.ShadowsocksUserConfig{
|
||||||
|
Password: base64.StdEncoding.EncodeToString(b),
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
proxySetting.Password = randPasswd
|
||||||
|
}
|
||||||
|
|
||||||
proxySetting.NetworkList = &conf.NetworkList{"tcp", "udp"}
|
proxySetting.NetworkList = &conf.NetworkList{"tcp", "udp"}
|
||||||
proxySetting.IVCheck = true
|
proxySetting.IVCheck = true
|
||||||
if config.DisableIVCheck {
|
if config.DisableIVCheck {
|
||||||
proxySetting.IVCheck = false
|
proxySetting.IVCheck = false
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if nodeInfo.NodeType == "dokodemo-door" {
|
case "dokodemo-door":
|
||||||
protocol = "dokodemo-door"
|
protocol = "dokodemo-door"
|
||||||
proxySetting = struct {
|
proxySetting = struct {
|
||||||
Host string `json:"address"`
|
Host string `json:"address"`
|
||||||
@@ -113,14 +133,16 @@ func InboundBuilder(config *Config, nodeInfo *api.NodeInfo, tag string) (*core.I
|
|||||||
Host: "v1.mux.cool",
|
Host: "v1.mux.cool",
|
||||||
NetworkList: []string{"tcp", "udp"},
|
NetworkList: []string{"tcp", "udp"},
|
||||||
}
|
}
|
||||||
} else {
|
default:
|
||||||
return nil, fmt.Errorf("Unsupported node type: %s, Only support: V2ray, Trojan, Shadowsocks, and Shadowsocks-Plugin", nodeInfo.NodeType)
|
return nil, fmt.Errorf("unsupported node type: %s, Only support: V2ray, Trojan, Shadowsocks, and Shadowsocks-Plugin", nodeInfo.NodeType)
|
||||||
}
|
}
|
||||||
|
|
||||||
setting, err := json.Marshal(proxySetting)
|
setting, err := json.Marshal(proxySetting)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Marshal proxy %s config fialed: %s", nodeInfo.NodeType, err)
|
return nil, fmt.Errorf("marshal proxy %s config fialed: %s", nodeInfo.NodeType, err)
|
||||||
}
|
}
|
||||||
|
inboundDetourConfig.Protocol = protocol
|
||||||
|
inboundDetourConfig.Settings = &setting
|
||||||
|
|
||||||
// Build streamSettings
|
// Build streamSettings
|
||||||
streamSetting = new(conf.StreamConfig)
|
streamSetting = new(conf.StreamConfig)
|
||||||
@@ -129,13 +151,15 @@ func InboundBuilder(config *Config, nodeInfo *api.NodeInfo, tag string) (*core.I
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("convert TransportProtocol failed: %s", err)
|
return nil, fmt.Errorf("convert TransportProtocol failed: %s", err)
|
||||||
}
|
}
|
||||||
if networkType == "tcp" {
|
|
||||||
|
switch networkType {
|
||||||
|
case "tcp":
|
||||||
tcpSetting := &conf.TCPConfig{
|
tcpSetting := &conf.TCPConfig{
|
||||||
AcceptProxyProtocol: config.EnableProxyProtocol,
|
AcceptProxyProtocol: config.EnableProxyProtocol,
|
||||||
HeaderConfig: nodeInfo.Header,
|
HeaderConfig: nodeInfo.Header,
|
||||||
}
|
}
|
||||||
streamSetting.TCPSettings = tcpSetting
|
streamSetting.TCPSettings = tcpSetting
|
||||||
} else if networkType == "websocket" {
|
case "websocket":
|
||||||
headers := make(map[string]string)
|
headers := make(map[string]string)
|
||||||
headers["Host"] = nodeInfo.Host
|
headers["Host"] = nodeInfo.Host
|
||||||
wsSettings := &conf.WebSocketConfig{
|
wsSettings := &conf.WebSocketConfig{
|
||||||
@@ -144,14 +168,14 @@ func InboundBuilder(config *Config, nodeInfo *api.NodeInfo, tag string) (*core.I
|
|||||||
Headers: headers,
|
Headers: headers,
|
||||||
}
|
}
|
||||||
streamSetting.WSSettings = wsSettings
|
streamSetting.WSSettings = wsSettings
|
||||||
} else if networkType == "http" {
|
case "http":
|
||||||
hosts := conf.StringList{nodeInfo.Host}
|
hosts := conf.StringList{nodeInfo.Host}
|
||||||
httpSettings := &conf.HTTPConfig{
|
httpSettings := &conf.HTTPConfig{
|
||||||
Host: &hosts,
|
Host: &hosts,
|
||||||
Path: nodeInfo.Path,
|
Path: nodeInfo.Path,
|
||||||
}
|
}
|
||||||
streamSetting.HTTPSettings = httpSettings
|
streamSetting.HTTPSettings = httpSettings
|
||||||
} else if networkType == "grpc" {
|
case "grpc":
|
||||||
grpcSettings := &conf.GRPCConfig{
|
grpcSettings := &conf.GRPCConfig{
|
||||||
ServiceName: nodeInfo.ServiceName,
|
ServiceName: nodeInfo.ServiceName,
|
||||||
}
|
}
|
||||||
@@ -159,6 +183,7 @@ func InboundBuilder(config *Config, nodeInfo *api.NodeInfo, tag string) (*core.I
|
|||||||
}
|
}
|
||||||
|
|
||||||
streamSetting.Network = &transportProtocol
|
streamSetting.Network = &transportProtocol
|
||||||
|
|
||||||
// Build TLS and XTLS settings
|
// Build TLS and XTLS settings
|
||||||
if nodeInfo.EnableTLS && config.CertConfig.CertMode != "none" {
|
if nodeInfo.EnableTLS && config.CertConfig.CertMode != "none" {
|
||||||
streamSetting.Security = nodeInfo.TLSType
|
streamSetting.Security = nodeInfo.TLSType
|
||||||
@@ -181,6 +206,7 @@ func InboundBuilder(config *Config, nodeInfo *api.NodeInfo, tag string) (*core.I
|
|||||||
streamSetting.XTLSSettings = xtlsSettings
|
streamSetting.XTLSSettings = xtlsSettings
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Support ProxyProtocol for any transport protocol
|
// Support ProxyProtocol for any transport protocol
|
||||||
if networkType != "tcp" && networkType != "ws" && config.EnableProxyProtocol {
|
if networkType != "tcp" && networkType != "ws" && config.EnableProxyProtocol {
|
||||||
sockoptConfig := &conf.SocketConfig{
|
sockoptConfig := &conf.SocketConfig{
|
||||||
@@ -188,60 +214,59 @@ func InboundBuilder(config *Config, nodeInfo *api.NodeInfo, tag string) (*core.I
|
|||||||
}
|
}
|
||||||
streamSetting.SocketSettings = sockoptConfig
|
streamSetting.SocketSettings = sockoptConfig
|
||||||
}
|
}
|
||||||
inboundDetourConfig.Protocol = protocol
|
|
||||||
inboundDetourConfig.StreamSetting = streamSetting
|
inboundDetourConfig.StreamSetting = streamSetting
|
||||||
inboundDetourConfig.Settings = &setting
|
|
||||||
|
|
||||||
return inboundDetourConfig.Build()
|
return inboundDetourConfig.Build()
|
||||||
}
|
}
|
||||||
|
|
||||||
func getCertFile(certConfig *CertConfig) (certFile string, keyFile string, err error) {
|
func getCertFile(certConfig *mylego.CertConfig) (certFile string, keyFile string, err error) {
|
||||||
if certConfig.CertMode == "file" {
|
switch certConfig.CertMode {
|
||||||
|
case "file":
|
||||||
if certConfig.CertFile == "" || certConfig.KeyFile == "" {
|
if certConfig.CertFile == "" || certConfig.KeyFile == "" {
|
||||||
return "", "", fmt.Errorf("Cert file path or key file path not exist")
|
return "", "", fmt.Errorf("cert file path or key file path not exist")
|
||||||
}
|
}
|
||||||
return certConfig.CertFile, certConfig.KeyFile, nil
|
return certConfig.CertFile, certConfig.KeyFile, nil
|
||||||
} else if certConfig.CertMode == "dns" {
|
case "dns":
|
||||||
lego, err := legocmd.New()
|
lego, err := mylego.New(certConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", err
|
return "", "", err
|
||||||
}
|
}
|
||||||
certPath, keyPath, err := lego.DNSCert(certConfig.CertDomain, certConfig.Email, certConfig.Provider, certConfig.DNSEnv)
|
certPath, keyPath, err := lego.DNSCert()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", err
|
return "", "", err
|
||||||
}
|
}
|
||||||
return certPath, keyPath, err
|
return certPath, keyPath, err
|
||||||
} else if certConfig.CertMode == "http" {
|
case "http", "tls":
|
||||||
lego, err := legocmd.New()
|
lego, err := mylego.New(certConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", err
|
return "", "", err
|
||||||
}
|
}
|
||||||
certPath, keyPath, err := lego.HTTPCert(certConfig.CertDomain, certConfig.Email)
|
certPath, keyPath, err := lego.HTTPCert()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", err
|
return "", "", err
|
||||||
}
|
}
|
||||||
return certPath, keyPath, err
|
return certPath, keyPath, err
|
||||||
|
default:
|
||||||
|
return "", "", fmt.Errorf("unsupported certmode: %s", certConfig.CertMode)
|
||||||
}
|
}
|
||||||
|
|
||||||
return "", "", fmt.Errorf("Unsupported certmode: %s", certConfig.CertMode)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildVlessFallbacks(fallbackConfigs []*FallBackConfig) ([]*conf.VLessInboundFallback, error) {
|
func buildVlessFallbacks(fallbackConfigs []*FallBackConfig) ([]*conf.VLessInboundFallback, error) {
|
||||||
if fallbackConfigs == nil {
|
if fallbackConfigs == nil {
|
||||||
return nil, fmt.Errorf("You must provide FallBackConfigs")
|
return nil, fmt.Errorf("you must provide FallBackConfigs")
|
||||||
}
|
}
|
||||||
|
|
||||||
vlessFallBacks := make([]*conf.VLessInboundFallback, len(fallbackConfigs))
|
vlessFallBacks := make([]*conf.VLessInboundFallback, len(fallbackConfigs))
|
||||||
for i, c := range fallbackConfigs {
|
for i, c := range fallbackConfigs {
|
||||||
|
|
||||||
if c.Dest == "" {
|
if c.Dest == "" {
|
||||||
return nil, fmt.Errorf("Dest is required for fallback fialed")
|
return nil, fmt.Errorf("dest is required for fallback fialed")
|
||||||
}
|
}
|
||||||
|
|
||||||
var dest json.RawMessage
|
var dest json.RawMessage
|
||||||
dest, err := json.Marshal(c.Dest)
|
dest, err := json.Marshal(c.Dest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Marshal dest %s config fialed: %s", dest, err)
|
return nil, fmt.Errorf("marshal dest %s config fialed: %s", dest, err)
|
||||||
}
|
}
|
||||||
vlessFallBacks[i] = &conf.VLessInboundFallback{
|
vlessFallBacks[i] = &conf.VLessInboundFallback{
|
||||||
Name: c.SNI,
|
Name: c.SNI,
|
||||||
@@ -256,20 +281,20 @@ func buildVlessFallbacks(fallbackConfigs []*FallBackConfig) ([]*conf.VLessInboun
|
|||||||
|
|
||||||
func buildTrojanFallbacks(fallbackConfigs []*FallBackConfig) ([]*conf.TrojanInboundFallback, error) {
|
func buildTrojanFallbacks(fallbackConfigs []*FallBackConfig) ([]*conf.TrojanInboundFallback, error) {
|
||||||
if fallbackConfigs == nil {
|
if fallbackConfigs == nil {
|
||||||
return nil, fmt.Errorf("You must provide FallBackConfigs")
|
return nil, fmt.Errorf("you must provide FallBackConfigs")
|
||||||
}
|
}
|
||||||
|
|
||||||
trojanFallBacks := make([]*conf.TrojanInboundFallback, len(fallbackConfigs))
|
trojanFallBacks := make([]*conf.TrojanInboundFallback, len(fallbackConfigs))
|
||||||
for i, c := range fallbackConfigs {
|
for i, c := range fallbackConfigs {
|
||||||
|
|
||||||
if c.Dest == "" {
|
if c.Dest == "" {
|
||||||
return nil, fmt.Errorf("Dest is required for fallback fialed")
|
return nil, fmt.Errorf("dest is required for fallback fialed")
|
||||||
}
|
}
|
||||||
|
|
||||||
var dest json.RawMessage
|
var dest json.RawMessage
|
||||||
dest, err := json.Marshal(c.Dest)
|
dest, err := json.Marshal(c.Dest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Marshal dest %s config fialed: %s", dest, err)
|
return nil, fmt.Errorf("marshal dest %s config fialed: %s", dest, err)
|
||||||
}
|
}
|
||||||
trojanFallBacks[i] = &conf.TrojanInboundFallback{
|
trojanFallBacks[i] = &conf.TrojanInboundFallback{
|
||||||
Name: c.SNI,
|
Name: c.SNI,
|
||||||
|
@@ -4,6 +4,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/XrayR-project/XrayR/api"
|
"github.com/XrayR-project/XrayR/api"
|
||||||
|
"github.com/XrayR-project/XrayR/common/mylego"
|
||||||
. "github.com/XrayR-project/XrayR/service/controller"
|
. "github.com/XrayR-project/XrayR/service/controller"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -20,7 +21,7 @@ func TestBuildV2ray(t *testing.T) {
|
|||||||
EnableTLS: false,
|
EnableTLS: false,
|
||||||
TLSType: "tls",
|
TLSType: "tls",
|
||||||
}
|
}
|
||||||
certConfig := &CertConfig{
|
certConfig := &mylego.CertConfig{
|
||||||
CertMode: "http",
|
CertMode: "http",
|
||||||
CertDomain: "test.test.tk",
|
CertDomain: "test.test.tk",
|
||||||
Provider: "alidns",
|
Provider: "alidns",
|
||||||
@@ -51,7 +52,7 @@ func TestBuildTrojan(t *testing.T) {
|
|||||||
DNSEnv := make(map[string]string)
|
DNSEnv := make(map[string]string)
|
||||||
DNSEnv["ALICLOUD_ACCESS_KEY"] = "aaa"
|
DNSEnv["ALICLOUD_ACCESS_KEY"] = "aaa"
|
||||||
DNSEnv["ALICLOUD_SECRET_KEY"] = "bbb"
|
DNSEnv["ALICLOUD_SECRET_KEY"] = "bbb"
|
||||||
certConfig := &CertConfig{
|
certConfig := &mylego.CertConfig{
|
||||||
CertMode: "dns",
|
CertMode: "dns",
|
||||||
CertDomain: "trojan.test.tk",
|
CertDomain: "trojan.test.tk",
|
||||||
Provider: "alidns",
|
Provider: "alidns",
|
||||||
@@ -83,7 +84,7 @@ func TestBuildSS(t *testing.T) {
|
|||||||
DNSEnv := make(map[string]string)
|
DNSEnv := make(map[string]string)
|
||||||
DNSEnv["ALICLOUD_ACCESS_KEY"] = "aaa"
|
DNSEnv["ALICLOUD_ACCESS_KEY"] = "aaa"
|
||||||
DNSEnv["ALICLOUD_SECRET_KEY"] = "bbb"
|
DNSEnv["ALICLOUD_SECRET_KEY"] = "bbb"
|
||||||
certConfig := &CertConfig{
|
certConfig := &mylego.CertConfig{
|
||||||
CertMode: "dns",
|
CertMode: "dns",
|
||||||
CertDomain: "trojan.test.tk",
|
CertDomain: "trojan.test.tk",
|
||||||
Provider: "alidns",
|
Provider: "alidns",
|
||||||
|
@@ -4,13 +4,14 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/XrayR-project/XrayR/api"
|
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
"github.com/xtls/xray-core/core"
|
"github.com/xtls/xray-core/core"
|
||||||
"github.com/xtls/xray-core/infra/conf"
|
"github.com/xtls/xray-core/infra/conf"
|
||||||
|
|
||||||
|
"github.com/XrayR-project/XrayR/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
//OutboundBuilder build freedom outbund config for addoutbound
|
// OutboundBuilder build freedom outbound config for addOutbound
|
||||||
func OutboundBuilder(config *Config, nodeInfo *api.NodeInfo, tag string) (*core.OutboundHandlerConfig, error) {
|
func OutboundBuilder(config *Config, nodeInfo *api.NodeInfo, tag string) (*core.OutboundHandlerConfig, error) {
|
||||||
outboundDetourConfig := &conf.OutboundDetourConfig{}
|
outboundDetourConfig := &conf.OutboundDetourConfig{}
|
||||||
outboundDetourConfig.Protocol = "freedom"
|
outboundDetourConfig.Protocol = "freedom"
|
||||||
@@ -19,11 +20,11 @@ func OutboundBuilder(config *Config, nodeInfo *api.NodeInfo, tag string) (*core.
|
|||||||
// Build Send IP address
|
// Build Send IP address
|
||||||
if config.SendIP != "" {
|
if config.SendIP != "" {
|
||||||
ipAddress := net.ParseAddress(config.SendIP)
|
ipAddress := net.ParseAddress(config.SendIP)
|
||||||
outboundDetourConfig.SendThrough = &conf.Address{ipAddress}
|
outboundDetourConfig.SendThrough = &conf.Address{Address: ipAddress}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Freedom Protocol setting
|
// Freedom Protocol setting
|
||||||
var domainStrategy string = "Asis"
|
var domainStrategy = "Asis"
|
||||||
if config.EnableDNS {
|
if config.EnableDNS {
|
||||||
if config.DNSType != "" {
|
if config.DNSType != "" {
|
||||||
domainStrategy = config.DNSType
|
domainStrategy = config.DNSType
|
||||||
@@ -41,7 +42,7 @@ func OutboundBuilder(config *Config, nodeInfo *api.NodeInfo, tag string) (*core.
|
|||||||
var setting json.RawMessage
|
var setting json.RawMessage
|
||||||
setting, err := json.Marshal(proxySetting)
|
setting, err := json.Marshal(proxySetting)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Marshal proxy %s config fialed: %s", nodeInfo.NodeType, err)
|
return nil, fmt.Errorf("marshal proxy %s config fialed: %s", nodeInfo.NodeType, err)
|
||||||
}
|
}
|
||||||
outboundDetourConfig.Settings = &setting
|
outboundDetourConfig.Settings = &setting
|
||||||
return outboundDetourConfig.Build()
|
return outboundDetourConfig.Build()
|
||||||
|
@@ -1,19 +1,29 @@
|
|||||||
package controller
|
package controller
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/base64"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/XrayR-project/XrayR/api"
|
"github.com/sagernet/sing-shadowsocks/shadowaead_2022"
|
||||||
|
C "github.com/sagernet/sing/common"
|
||||||
"github.com/xtls/xray-core/common/protocol"
|
"github.com/xtls/xray-core/common/protocol"
|
||||||
"github.com/xtls/xray-core/common/serial"
|
"github.com/xtls/xray-core/common/serial"
|
||||||
"github.com/xtls/xray-core/infra/conf"
|
"github.com/xtls/xray-core/infra/conf"
|
||||||
"github.com/xtls/xray-core/proxy/shadowsocks"
|
"github.com/xtls/xray-core/proxy/shadowsocks"
|
||||||
|
"github.com/xtls/xray-core/proxy/shadowsocks_2022"
|
||||||
"github.com/xtls/xray-core/proxy/trojan"
|
"github.com/xtls/xray-core/proxy/trojan"
|
||||||
"github.com/xtls/xray-core/proxy/vless"
|
"github.com/xtls/xray-core/proxy/vless"
|
||||||
|
|
||||||
|
"github.com/XrayR-project/XrayR/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
var AEADMethod = []shadowsocks.CipherType{shadowsocks.CipherType_AES_128_GCM, shadowsocks.CipherType_AES_256_GCM, shadowsocks.CipherType_CHACHA20_POLY1305, shadowsocks.CipherType_XCHACHA20_POLY1305}
|
var AEADMethod = map[shadowsocks.CipherType]uint8{
|
||||||
|
shadowsocks.CipherType_AES_128_GCM: 0,
|
||||||
|
shadowsocks.CipherType_AES_256_GCM: 0,
|
||||||
|
shadowsocks.CipherType_CHACHA20_POLY1305: 0,
|
||||||
|
shadowsocks.CipherType_XCHACHA20_POLY1305: 0,
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Controller) buildVmessUser(userInfo *[]api.UserInfo, serverAlterID uint16) (users []*protocol.User) {
|
func (c *Controller) buildVmessUser(userInfo *[]api.UserInfo, serverAlterID uint16) (users []*protocol.User) {
|
||||||
users = make([]*protocol.User, len(*userInfo))
|
users = make([]*protocol.User, len(*userInfo))
|
||||||
@@ -65,43 +75,65 @@ func (c *Controller) buildTrojanUser(userInfo *[]api.UserInfo) (users []*protoco
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Controller) buildSSUser(userInfo *[]api.UserInfo, method string) (users []*protocol.User) {
|
func (c *Controller) buildSSUser(userInfo *[]api.UserInfo, method string) (users []*protocol.User) {
|
||||||
users = make([]*protocol.User, 0)
|
users = make([]*protocol.User, len(*userInfo))
|
||||||
|
|
||||||
cypherMethod := cipherFromString(method)
|
for i, user := range *userInfo {
|
||||||
for _, user := range *userInfo {
|
// // shadowsocks2022 Key = openssl rand -base64 32 and multi users needn't cipher method
|
||||||
ssAccount := &shadowsocks.Account{
|
if C.Contains(shadowaead_2022.List, strings.ToLower(method)) {
|
||||||
Password: user.Passwd,
|
e := c.buildUserTag(&user)
|
||||||
CipherType: cypherMethod,
|
users[i] = &protocol.User{
|
||||||
|
Level: 0,
|
||||||
|
Email: e,
|
||||||
|
Account: serial.ToTypedMessage(&shadowsocks_2022.User{
|
||||||
|
Key: base64.StdEncoding.EncodeToString([]byte(user.Passwd)),
|
||||||
|
Email: e,
|
||||||
|
Level: 0,
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
users[i] = &protocol.User{
|
||||||
|
Level: 0,
|
||||||
|
Email: c.buildUserTag(&user),
|
||||||
|
Account: serial.ToTypedMessage(&shadowsocks.Account{
|
||||||
|
Password: user.Passwd,
|
||||||
|
CipherType: cipherFromString(method),
|
||||||
|
}),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
users = append(users, &protocol.User{
|
|
||||||
Level: 0,
|
|
||||||
Email: c.buildUserTag(&user),
|
|
||||||
Account: serial.ToTypedMessage(ssAccount),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
return users
|
return users
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Controller) buildSSPluginUser(userInfo *[]api.UserInfo) (users []*protocol.User) {
|
func (c *Controller) buildSSPluginUser(userInfo *[]api.UserInfo) (users []*protocol.User) {
|
||||||
users = make([]*protocol.User, 0)
|
users = make([]*protocol.User, len(*userInfo))
|
||||||
|
|
||||||
for _, user := range *userInfo {
|
for i, user := range *userInfo {
|
||||||
// Check if the cypher method is AEAD
|
// shadowsocks2022 Key = openssl rand -base64 32 and multi users needn't cipher method
|
||||||
cypherMethod := cipherFromString(user.Method)
|
if C.Contains(shadowaead_2022.List, strings.ToLower(user.Method)) {
|
||||||
for _, aeadMethod := range AEADMethod {
|
e := c.buildUserTag(&user)
|
||||||
if aeadMethod == cypherMethod {
|
users[i] = &protocol.User{
|
||||||
ssAccount := &shadowsocks.Account{
|
Level: 0,
|
||||||
Password: user.Passwd,
|
Email: e,
|
||||||
CipherType: cypherMethod,
|
Account: serial.ToTypedMessage(&shadowsocks_2022.User{
|
||||||
|
Key: base64.StdEncoding.EncodeToString([]byte(user.Passwd)),
|
||||||
|
Email: e,
|
||||||
|
Level: 0,
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Check if the cypher method is AEAD
|
||||||
|
cypherMethod := cipherFromString(user.Method)
|
||||||
|
if _, ok := AEADMethod[cypherMethod]; ok {
|
||||||
|
users[i] = &protocol.User{
|
||||||
|
Level: 0,
|
||||||
|
Email: c.buildUserTag(&user),
|
||||||
|
Account: serial.ToTypedMessage(&shadowsocks.Account{
|
||||||
|
Password: user.Passwd,
|
||||||
|
CipherType: cypherMethod,
|
||||||
|
}),
|
||||||
}
|
}
|
||||||
users = append(users, &protocol.User{
|
|
||||||
Level: 0,
|
|
||||||
Email: c.buildUserTag(&user),
|
|
||||||
Account: serial.ToTypedMessage(ssAccount),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return users
|
return users
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
// Package service contains all the services used by XrayR
|
// Package service contains all the services used by XrayR
|
||||||
// To implement an service, one needs to implement the interface below.
|
// To implement a service, one needs to implement the interface below.
|
||||||
package service
|
package service
|
||||||
|
|
||||||
// Service is the interface of all the services running in the panel
|
// Service is the interface of all the services running in the panel
|
||||||
|
Reference in New Issue
Block a user