Showing preview only (972K chars total). Download the full file or copy to clipboard to get everything.
Repository: cedar2025/hysteria
Branch: master
Commit: 6f4f1d3e9916
Files: 211
Total size: 909.8 KB
Directory structure:
gitextract_5rjruq7m/
├── .github/
│ ├── FUNDING.yml
│ ├── ISSUE_TEMPLATE/
│ │ ├── bug_report.md
│ │ ├── bug_report.zh.md
│ │ ├── feature_request.md
│ │ └── feature_request.zh.md
│ ├── dependabot.yml
│ └── workflows/
│ ├── autotag.yaml
│ ├── docker.yml
│ ├── master.yml
│ ├── release.yml
│ └── scripts.yml
├── .gitignore
├── CHANGELOG.md
├── Dockerfile
├── LICENSE.md
├── PROTOCOL.md
├── README.md
├── app/
│ ├── cmd/
│ │ ├── client.go
│ │ ├── client_test.go
│ │ ├── client_test.yaml
│ │ ├── errors.go
│ │ ├── ping.go
│ │ ├── root.go
│ │ ├── server.go
│ │ ├── server_test.go
│ │ ├── server_test.yaml
│ │ ├── share.go
│ │ ├── speedtest.go
│ │ ├── update.go
│ │ └── version.go
│ ├── go.mod
│ ├── go.sum
│ ├── internal/
│ │ ├── forwarding/
│ │ │ ├── tcp.go
│ │ │ ├── tcp_test.go
│ │ │ ├── udp.go
│ │ │ └── udp_test.go
│ │ ├── http/
│ │ │ ├── server.go
│ │ │ ├── server_test.go
│ │ │ ├── server_test.py
│ │ │ ├── test.crt
│ │ │ └── test.key
│ │ ├── proxymux/
│ │ │ ├── .mockery.yaml
│ │ │ ├── internal/
│ │ │ │ └── mocks/
│ │ │ │ ├── mock_Conn.go
│ │ │ │ └── mock_Listener.go
│ │ │ ├── manager.go
│ │ │ ├── manager_test.go
│ │ │ ├── mux.go
│ │ │ └── mux_test.go
│ │ ├── redirect/
│ │ │ ├── getsockopt_linux.go
│ │ │ ├── getsockopt_linux_386.go
│ │ │ ├── syscall_socketcall_linux_386.s
│ │ │ ├── tcp_linux.go
│ │ │ └── tcp_others.go
│ │ ├── sockopts/
│ │ │ ├── fd_control_unix_socket_test.py
│ │ │ ├── sockopts.go
│ │ │ ├── sockopts_linux.go
│ │ │ └── sockopts_linux_test.go
│ │ ├── socks5/
│ │ │ ├── server.go
│ │ │ ├── server_test.go
│ │ │ └── server_test.py
│ │ ├── tproxy/
│ │ │ ├── tcp_linux.go
│ │ │ ├── tcp_others.go
│ │ │ ├── udp_linux.go
│ │ │ └── udp_others.go
│ │ ├── tun/
│ │ │ ├── log.go
│ │ │ └── server.go
│ │ ├── url/
│ │ │ ├── url.go
│ │ │ └── url_test.go
│ │ ├── utils/
│ │ │ ├── bpsconv.go
│ │ │ ├── bpsconv_test.go
│ │ │ ├── certloader.go
│ │ │ ├── certloader_test.go
│ │ │ ├── certloader_test_gencert.py
│ │ │ ├── certloader_test_tlsclient.py
│ │ │ ├── geoloader.go
│ │ │ ├── qr.go
│ │ │ ├── testcerts/
│ │ │ │ └── .gitignore
│ │ │ └── update.go
│ │ └── utils_test/
│ │ └── mock.go
│ ├── main.go
│ ├── misc/
│ │ └── socks5_test.py
│ └── pprof.go
├── core/
│ ├── client/
│ │ ├── .mockery.yaml
│ │ ├── client.go
│ │ ├── config.go
│ │ ├── mock_udpIO.go
│ │ ├── reconnect.go
│ │ ├── udp.go
│ │ └── udp_test.go
│ ├── errors/
│ │ └── errors.go
│ ├── go.mod
│ ├── go.sum
│ ├── internal/
│ │ ├── congestion/
│ │ │ ├── bbr/
│ │ │ │ ├── bandwidth.go
│ │ │ │ ├── bandwidth_sampler.go
│ │ │ │ ├── bbr_sender.go
│ │ │ │ ├── clock.go
│ │ │ │ ├── packet_number_indexed_queue.go
│ │ │ │ ├── ringbuffer.go
│ │ │ │ └── windowed_filter.go
│ │ │ ├── brutal/
│ │ │ │ └── brutal.go
│ │ │ ├── common/
│ │ │ │ └── pacer.go
│ │ │ └── utils.go
│ │ ├── frag/
│ │ │ ├── frag.go
│ │ │ └── frag_test.go
│ │ ├── integration_tests/
│ │ │ ├── .mockery.yaml
│ │ │ ├── close_test.go
│ │ │ ├── hook_test.go
│ │ │ ├── masq_test.go
│ │ │ ├── mocks/
│ │ │ │ ├── mock_Authenticator.go
│ │ │ │ ├── mock_Conn.go
│ │ │ │ ├── mock_EventLogger.go
│ │ │ │ ├── mock_Outbound.go
│ │ │ │ ├── mock_RequestHook.go
│ │ │ │ ├── mock_TrafficLogger.go
│ │ │ │ └── mock_UDPConn.go
│ │ │ ├── smoke_test.go
│ │ │ ├── stress_test.go
│ │ │ ├── test.crt
│ │ │ ├── test.key
│ │ │ ├── trafficlogger_test.go
│ │ │ └── utils_test.go
│ │ ├── pmtud/
│ │ │ ├── avail.go
│ │ │ └── unavail.go
│ │ ├── protocol/
│ │ │ ├── http.go
│ │ │ ├── padding.go
│ │ │ ├── proxy.go
│ │ │ └── proxy_test.go
│ │ └── utils/
│ │ ├── atomic.go
│ │ └── qstream.go
│ └── server/
│ ├── .mockery.yaml
│ ├── config.go
│ ├── copy.go
│ ├── mock_UDPConn.go
│ ├── mock_udpEventLogger.go
│ ├── mock_udpIO.go
│ ├── server.go
│ ├── udp.go
│ └── udp_test.go
├── entrypoint
├── extras/
│ ├── auth/
│ │ ├── command.go
│ │ ├── http.go
│ │ ├── http_test.go
│ │ ├── http_test.py
│ │ ├── password.go
│ │ ├── password_test.go
│ │ ├── userpass.go
│ │ ├── userpass_test.go
│ │ └── v2board.go
│ ├── correctnet/
│ │ └── correctnet.go
│ ├── go.mod
│ ├── go.sum
│ ├── masq/
│ │ └── server.go
│ ├── obfs/
│ │ ├── conn.go
│ │ ├── salamander.go
│ │ └── salamander_test.go
│ ├── outbounds/
│ │ ├── .mockery.yaml
│ │ ├── acl/
│ │ │ ├── compile.go
│ │ │ ├── compile_test.go
│ │ │ ├── matchers.go
│ │ │ ├── matchers_test.go
│ │ │ ├── matchers_v2geo.go
│ │ │ ├── matchers_v2geo_test.go
│ │ │ ├── parse.go
│ │ │ ├── parse_test.go
│ │ │ └── v2geo/
│ │ │ ├── load.go
│ │ │ ├── load_test.go
│ │ │ ├── v2geo.pb.go
│ │ │ └── v2geo.proto
│ │ ├── acl.go
│ │ ├── acl_test.go
│ │ ├── dns_https.go
│ │ ├── dns_standard.go
│ │ ├── dns_system.go
│ │ ├── interface.go
│ │ ├── interface_test.go
│ │ ├── mock_PluggableOutbound.go
│ │ ├── mock_UDPConn.go
│ │ ├── ob_direct.go
│ │ ├── ob_direct_linux.go
│ │ ├── ob_direct_others.go
│ │ ├── ob_http.go
│ │ ├── ob_socks5.go
│ │ ├── speedtest/
│ │ │ ├── client.go
│ │ │ ├── protocol.go
│ │ │ ├── protocol_test.go
│ │ │ └── server.go
│ │ ├── speedtest.go
│ │ ├── utils.go
│ │ └── utils_test.go
│ ├── sniff/
│ │ ├── .mockery.yaml
│ │ ├── internal/
│ │ │ └── quic/
│ │ │ ├── LICENSE
│ │ │ ├── README.md
│ │ │ ├── header.go
│ │ │ ├── packet_protector.go
│ │ │ ├── packet_protector_test.go
│ │ │ ├── payload.go
│ │ │ └── quic.go
│ │ ├── mock_Stream.go
│ │ ├── sniff.go
│ │ └── sniff_test.go
│ ├── trafficlogger/
│ │ └── http.go
│ ├── transport/
│ │ └── udphop/
│ │ ├── addr.go
│ │ └── conn.go
│ └── utils/
│ ├── portunion.go
│ └── portunion_test.go
├── go.work.sum
├── hyperbole.py
├── platforms.txt
├── requirements.txt
└── scripts/
├── _redirects
└── install_server.sh
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/FUNDING.yml
================================================
custom: [ 'https://v2.hysteria.network/docs/Donation/' ]
================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.md
================================================
---
name: Bug report
about: Report anything you think is a bug and needs to be fixed.
title: ''
labels: bug
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior.
**Expected behavior**
A clear and concise description of what you expected to happen.
**Logs**
Attach logs from the client/server when the error occurs.
**Device and Operating System**
What are you using it on.
**Additional context**
Add any other context about the problem here.
================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.zh.md
================================================
---
name: Bug 反馈
about: 反馈任何你认为是 bug 需要修复的问题。
title: ''
labels: bug
assignees: ''
---
**描述问题**
请尽量清晰精准地描述你遇到的问题。
**如何复现**
复现问题的步骤。
**预期行为**
你认为修复后的行为应该是怎样的。
**日志**
附上客户端/服务器端在错误发生前后的日志。
**设备和操作系统**
你在用什么设备和操作系统。
**额外信息**
其他你认为有助于解决问题的信息。
================================================
FILE: .github/ISSUE_TEMPLATE/feature_request.md
================================================
---
name: Feature request
about: Suggest an idea for this project.
title: ''
labels: enhancement
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.
================================================
FILE: .github/ISSUE_TEMPLATE/feature_request.zh.md
================================================
---
name: 功能请求
about: 为这个项目提出改进意见。
title: ''
labels: enhancement
assignees: ''
---
**你的功能请求是否与某个问题有关?**
请尽量清晰精准地描述你遇到的问题。例如:我家运营商限制 UDP 协议速度,导致 Hysteria 很慢,希望增加 FakeTCP 支持。
**描述你希望的解决方案**
请尽量清晰精准地描述你希望的解决方案。
**有没有其他替代方案**
请尽量清晰精准地描述你认为可能的替代方案。
**额外信息**
其他你认为有助于开发者了解你需求的信息。
================================================
FILE: .github/dependabot.yml
================================================
version: 2
updates:
- package-ecosystem: "gomod"
directory: "/"
schedule:
interval: "daily"
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "daily"
================================================
FILE: .github/workflows/autotag.yaml
================================================
name: "Create release tags for nested modules"
on:
push:
tags:
- app/v*.*.*
permissions:
contents: write
jobs:
tag:
name: "Create tags"
runs-on: ubuntu-latest
steps:
- name: "Extract tagbase"
id: extract_tagbase
uses: actions/github-script@v7
with:
script: |
const ref = context.ref;
core.info(`context.ref: ${ref}`);
const refPrefix = 'refs/tags/app/';
if (!ref.startsWith(refPrefix)) {
core.setFailed(`context.ref does not start with ${refPrefix}: ${ref}`);
return;
}
const tagbase = ref.slice(refPrefix.length);
core.info(`tagbase: ${tagbase}`);
core.setOutput('tagbase', tagbase);
- name: "Tagging core/*"
uses: actions/github-script@v7
env:
INPUT_TAGPREFIX: "core/"
INPUT_TAGBASE: ${{ steps.extract_tagbase.outputs.tagbase }}
with:
script: |
const tagbase = core.getInput('tagbase', { required: true });
const tagprefix = core.getInput('tagprefix', { required: true });
const refname = `tags/${tagprefix}${tagbase}`;
core.info(`creating ref ${refname}`);
try {
await github.rest.git.createRef({
owner: context.repo.owner,
repo: context.repo.repo,
ref: `refs/${refname}`,
sha: context.sha
});
core.info(`created ref ${refname}`);
return;
} catch (error) {
core.info(`failed to create ref ${refname}: ${error}`);
}
core.info(`updating ref ${refname}`)
try {
await github.rest.git.updateRef({
owner: context.repo.owner,
repo: context.repo.repo,
ref: refname,
sha: context.sha
});
core.info(`updated ref ${refname}`);
return;
} catch (error) {
core.setFailed(`failed to update ref ${refname}: ${error}`);
}
- name: "Tagging extras/*"
uses: actions/github-script@v7
env:
INPUT_TAGPREFIX: "extras/"
INPUT_TAGBASE: ${{ steps.extract_tagbase.outputs.tagbase }}
with:
script: |
const tagbase = core.getInput('tagbase', { required: true });
const tagprefix = core.getInput('tagprefix', { required: true });
const refname = `tags/${tagprefix}${tagbase}`;
core.info(`creating ref ${refname}`);
try {
await github.rest.git.createRef({
owner: context.repo.owner,
repo: context.repo.repo,
ref: `refs/${refname}`,
sha: context.sha
});
core.info(`created ref ${refname}`);
return;
} catch (error) {
core.info(`failed to create ref ${refname}: ${error}`);
}
core.info(`updating ref ${refname}`)
try {
await github.rest.git.updateRef({
owner: context.repo.owner,
repo: context.repo.repo,
ref: refname,
sha: context.sha
});
core.info(`updated ref ${refname}`);
return;
} catch (error) {
core.setFailed(`failed to update ref ${refname}: ${error}`);
}
================================================
FILE: .github/workflows/docker.yml
================================================
name: Docker
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
on:
push:
branches: [ "master" ]
# Publish semver tags as releases.
tags: [ 'v*.*.*' ]
env:
# Use docker.io for Docker Hub if empty
REGISTRY: ghcr.io
# github.repository as <account>/<repo>
IMAGE_NAME: ${{ github.repository }}
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
# This is used to complete the identity challenge
# with sigstore/fulcio when running outside of PRs.
id-token: write
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Install cosign
uses: sigstore/cosign-installer@v3.4.0
with:
cosign-release: 'v2.2.2'
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3.2.0
# Login against a Docker registry except on PR
# https://github.com/docker/login-action
- name: Log into registry ${{ env.REGISTRY }}
uses: docker/login-action@v3.1.0
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract Docker metadata
id: meta
uses: docker/metadata-action@v5.5.1
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
- name: Get version
id: get_version
run: echo "version=$(git describe --tags --always)" >> $GITHUB_OUTPUT
- name: Build and push Docker image
id: build-and-push
uses: docker/build-push-action@v5.3.0
with:
context: .
push: true
platforms: linux/amd64,linux/arm64
tags: |
${{ env.REGISTRY }}/${{ github.repository_owner }}/hysteria
${{ env.REGISTRY }}/${{ github.repository_owner }}/hysteria:latest
${{ env.REGISTRY }}/${{ github.repository_owner }}/hysteria:${{ steps.get_version.outputs.version }}
# Sign the resulting Docker image digest except on PRs.
# This will only write to the public Rekor transparency log when the Docker
# repository is public to avoid leaking data. If you would like to publish
# transparency data even for private images, pass --force to cosign below.
# https://github.com/sigstore/cosign
- name: Sign the published Docker image
env:
# https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions#using-an-intermediate-environment-variable
TAGS: ${{ steps.meta.outputs.tags }}
DIGEST: ${{ steps.build-and-push.outputs.digest }}
# This step uses the identity token to provision an ephemeral certificate
# against the sigstore community Fulcio instance.
run: echo "${TAGS}" | xargs -I {} cosign sign --yes {}@${DIGEST}
================================================
FILE: .github/workflows/master.yml
================================================
name: "Build master branch"
on:
push:
branches:
- master
jobs:
build:
name: Build
runs-on: ubuntu-latest
env:
ACTIONS_ALLOW_UNSECURE_COMMANDS: true
steps:
- name: Check out
uses: actions/checkout@v4
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: "1.23"
- name: Setup Python # This is for the build script
uses: actions/setup-python@v5
with:
python-version: "3.11"
- uses: nttld/setup-ndk@v1
id: setup-ndk
with:
ndk-version: r26b
add-to-path: false
- name: Run build script
env:
ANDROID_NDK_HOME: ${{ steps.setup-ndk.outputs.ndk-path }}
run: |
export HY_APP_PLATFORMS=$(sed 's/\r$//' platforms.txt | awk '!/^#/ && !/^$/' | paste -sd ",")
python hyperbole.py build -r
- name: Generate hashes
run: |
for file in build/*; do
sha256sum $file >> build/hashes.txt
done
- name: Archive
uses: actions/upload-artifact@v4
with:
name: hysteria-master-${{ github.sha }}
path: build
================================================
FILE: .github/workflows/release.yml
================================================
name: "Build release"
on:
push:
tags:
- app/v*.*.*
jobs:
build:
name: Build
runs-on: ubuntu-latest
env:
ACTIONS_ALLOW_UNSECURE_COMMANDS: true
steps:
- name: Check out
uses: actions/checkout@v4
- name: Get version
id: get_version
run: echo "version=$(git describe --tags --always --match 'app/v*' | sed -n 's|app/\([^/-]*\)\(-.*\)\{0,1\}|\1|p')" >> $GITHUB_OUTPUT
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: "1.23"
- name: Setup Python # This is for the build script
uses: actions/setup-python@v5
with:
python-version: "3.11"
- uses: nttld/setup-ndk@v1
id: setup-ndk
with:
ndk-version: r26b
add-to-path: false
- name: Run build script
env:
ANDROID_NDK_HOME: ${{ steps.setup-ndk.outputs.ndk-path }}
run: |
export HY_APP_PLATFORMS=$(sed 's/\r$//' platforms.txt | awk '!/^#/ && !/^$/' | paste -sd ",")
python hyperbole.py build -r
- name: Generate hashes
run: |
for file in build/*; do
sha256sum $file >> build/hashes.txt
done
- name: Upload GitHub
uses: softprops/action-gh-release@v2
with:
files: build/*
- name: Upload CF bucket
uses: shallwefootball/upload-s3-action@v1.3.3
with:
aws_key_id: ${{ secrets.CF_KEY_ID }}
aws_secret_access_key: ${{ secrets.CF_KEY }}
aws_bucket: "hydownload"
endpoint: "https://bea223c61d5a41250d127bd67f51dfec.r2.cloudflarestorage.com/"
source_dir: "build"
destination_dir: "app/${{ steps.get_version.outputs.version }}"
- name: Publish to API
run: |
export HY_API_POST_KEY=${{ secrets.HY2_API_POST_KEY }}
pip install requests
python hyperbole.py publish
================================================
FILE: .github/workflows/scripts.yml
================================================
name: "Publish scripts"
on:
push:
branches:
- master
paths:
- scripts/**
jobs:
publish:
runs-on: ubuntu-latest
permissions:
contents: read
deployments: write
name: Publish scripts to Cloudflare Pages
steps:
- name: Check out
uses: actions/checkout@v4
- name: Publish to Cloudflare Pages
uses: cloudflare/pages-action@v1
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
projectName: hy2scripts
directory: scripts
gitHubToken: ${{ secrets.GITHUB_TOKEN }}
branch: main
================================================
FILE: .gitignore
================================================
# Created by https://www.toptal.com/developers/gitignore/api/goland+all,intellij+all,go,windows,linux,macos,python,pycharm+all
# Edit at https://www.toptal.com/developers/gitignore?templates=goland+all,intellij+all,go,windows,linux,macos,python,pycharm+all
### Go ###
# If you prefer the allow list template instead of the deny list, see community template:
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
#
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
# Test binary, built with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
# Dependency directories (remove the comment below to include it)
# vendor/
# Go workspace file
go.work
### GoLand+all ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf
# AWS User-specific
.idea/**/aws.xml
# Generated files
.idea/**/contentModel.xml
# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml
# Gradle
.idea/**/gradle.xml
.idea/**/libraries
# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
# .idea/artifacts
# .idea/compiler.xml
# .idea/jarRepositories.xml
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# *.iml
# *.ipr
# CMake
cmake-build-*/
# Mongo Explorer plugin
.idea/**/mongoSettings.xml
# File-based project format
*.iws
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# SonarLint plugin
.idea/sonarlint/
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
# Editor-based Rest Client
.idea/httpRequests
# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser
### GoLand+all Patch ###
# Ignore everything but code style settings and run configurations
# that are supposed to be shared within teams.
.idea/*
!.idea/codeStyles
!.idea/runConfigurations
### Intellij+all ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff
# AWS User-specific
# Generated files
# Sensitive or high-churn files
# Gradle
# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
# .idea/artifacts
# .idea/compiler.xml
# .idea/jarRepositories.xml
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# *.iml
# *.ipr
# CMake
# Mongo Explorer plugin
# File-based project format
# IntelliJ
# mpeltonen/sbt-idea plugin
# JIRA plugin
# Cursive Clojure plugin
# SonarLint plugin
# Crashlytics plugin (for Android Studio and IntelliJ)
# Editor-based Rest Client
# Android studio 3.1+ serialized cache file
### Intellij+all Patch ###
# Ignore everything but code style settings and run configurations
# that are supposed to be shared within teams.
### Linux ###
*~
# temporary files which can be created if a process still has a handle open of a deleted file
.fuse_hidden*
# KDE directory preferences
.directory
# Linux trash folder which might appear on any partition or disk
.Trash-*
# .nfs files are created when an open file is removed but is still being accessed
.nfs*
### macOS ###
# General
.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
### macOS Patch ###
# iCloud generated files
*.icloud
### PyCharm+all ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff
# AWS User-specific
# Generated files
# Sensitive or high-churn files
# Gradle
# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
# .idea/artifacts
# .idea/compiler.xml
# .idea/jarRepositories.xml
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# *.iml
# *.ipr
# CMake
# Mongo Explorer plugin
# File-based project format
# IntelliJ
# mpeltonen/sbt-idea plugin
# JIRA plugin
# Cursive Clojure plugin
# SonarLint plugin
# Crashlytics plugin (for Android Studio and IntelliJ)
# Editor-based Rest Client
# Android studio 3.1+ serialized cache file
### PyCharm+all Patch ###
# Ignore everything but code style settings and run configurations
# that are supposed to be shared within teams.
### Python ###
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock
# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm.fming.dev/#use-with-ide
.pdm.toml
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
# PyCharm
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
### Python Patch ###
# Poetry local configuration file - https://python-poetry.org/docs/configuration/#local-configuration
poetry.toml
# ruff
.ruff_cache/
# LSP config files
pyrightconfig.json
### Windows ###
# Windows thumbnail cache files
Thumbs.db
Thumbs.db:encryptable
ehthumbs.db
ehthumbs_vista.db
# Dump file
*.stackdump
# Folder config file
[Dd]esktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msix
*.msm
*.msp
# Windows shortcuts
*.lnk
# End of https://www.toptal.com/developers/gitignore/api/goland+all,intellij+all,go,windows,linux,macos,python,pycharm+all
================================================
FILE: CHANGELOG.md
================================================
# Changelog
https://v2.hysteria.network/docs/Changelog/
================================================
FILE: Dockerfile
================================================
FROM golang:1-alpine AS builder
# GOPROXY is disabled by default, use:
# docker build --build-arg GOPROXY="https://goproxy.io" ...
# to enable GOPROXY.
ARG GOPROXY=""
ENV GOPROXY ${GOPROXY}
COPY . /go/src/github.com/apernet/hysteria
WORKDIR /go/src/github.com/apernet/hysteria
RUN set -ex \
&& apk add git build-base bash python3 \
&& python hyperbole.py build -r \
&& mv ./build/hysteria-* /go/bin/hysteria
# multi-stage builds to create the final image
FROM alpine AS dist
# set up nsswitch.conf for Go's "netgo" implementation
# - https://github.com/golang/go/blob/go1.9.1/src/net/conf.go#L194-L275
# - docker run --rm debian:stretch grep '^hosts:' /etc/nsswitch.conf
RUN if [ ! -e /etc/nsswitch.conf ]; then echo 'hosts: files dns' > /etc/nsswitch.conf; fi
# bash is used for debugging, tzdata is used to add timezone information.
# Install ca-certificates to ensure no CA certificate errors.
#
# Do not try to add the "--no-cache" option when there are multiple "apk"
# commands, this will cause the build process to become very slow.
COPY ./entrypoint /usr/local/bin/entrypoint
RUN set -ex \
&& apk upgrade \
&& apk add bash tzdata ca-certificates \
&& rm -rf /var/cache/apk/* \
&& chmod +x /usr/local/bin/entrypoint
COPY --from=builder /go/bin/hysteria /usr/local/bin/hysteria
CMD ["entrypoint"]
================================================
FILE: LICENSE.md
================================================
Copyright 2023 Toby
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
================================================
FILE: PROTOCOL.md
================================================
# Hysteria 2 Protocol Specification
Hysteria is a TCP & UDP proxy based on QUIC, designed for speed, security and censorship resistance. This document describes the protocol used by Hysteria starting with version 2.0.0, sometimes internally referred to as the "v4" protocol. From here on, we will call it "the protocol" or "the Hysteria protocol".
## Requirements Language
The keywords "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC 2119](https://tools.ietf.org/html/rfc2119).
## Underlying Protocol & Wire Format
The Hysteria protocol MUST be implemented on top of the standard QUIC transport protocol [RFC 9000](https://datatracker.ietf.org/doc/html/rfc9000) with [Unreliable Datagram Extension](https://datatracker.ietf.org/doc/rfc9221/).
All multibyte numbers use Big Endian format.
All variable-length integers ("varints") are encoded/decoded as defined in QUIC (RFC 9000).
## Authentication & HTTP/3 masquerading
One of the key features of the Hysteria protocol is that to a third party without proper authentication credentials (whether it's a middleman or an active prober), a Hysteria proxy server behaves just like a standard HTTP/3 web server. Additionally, the encrypted traffic between the client and the server appears indistinguishable from normal HTTP/3 traffic.
Therefore, a Hysteria server MUST implement an HTTP/3 server (as defined by [RFC 9114](https://datatracker.ietf.org/doc/rfc9114/)) and handle HTTP requests as any standard web server would. To prevent active probers from detecting common response patterns in Hysteria servers, implementations SHOULD advise users to either host actual content or set it up as a reverse proxy for other sites.
An actual Hysteria client, upon connection, MUST send the following HTTP/3 request to the server:
```
:method: POST
:path: /auth
:host: hysteria
Hysteria-Auth: [string]
Hysteria-CC-RX: [uint]
Hysteria-Padding: [string]
```
`Hysteria-Auth`: Authentication credentials.
`Hysteria-CC-RX`: Client's maximum receive rate in bytes per second. A value of 0 indicates unknown.
`Hysteria-Padding`: A random padding string of variable length.
The Hysteria server MUST identify this special request, and, instead of attempting to serve content or forwarding it to an upstream site, it MUST authenticate the client using the provided information. If authentication is successful, the server MUST send the following response (HTTP status code 233):
```
:status: 233 HyOK
Hysteria-UDP: [true/false]
Hysteria-CC-RX: [uint/"auto"]
Hysteria-Padding: [string]
```
`Hysteria-UDP`: Whether the server supports UDP relay.
`Hysteria-CC-RX`: Server's maximum receive rate in bytes per second. A value of 0 indicates unlimited; "auto" indicates the server refuses to provide a value and ask the client to use congestion control to determine the rate on its own.
`Hysteria-Padding`: A random padding string of variable length.
See the Congestion Control section for more information on how to use the `Hysteria-CC-RX` values.
`Hysteria-Padding` is optional and is only intended to obfuscate the request/response pattern. It SHOULD be ignored by both sides.
If authentication fails, the server MUST either act like a standard web server that does not understand the request, or in the case of being a reverse proxy, forward the request to the upstream site and return the response to the client.
The client MUST check the status code to determine if the authentication was successful. If the status code is anything other than 233, the client MUST consider authentication to have failed and disconnect from the server.
After (and only after) a client passes authentication, the server MUST consider this QUIC connection to be a Hysteria proxy connection. It MUST then start processing proxy requests from the client as described in the next section.
## Proxy Requests
### TCP
For each TCP connection, the client MUST create a new QUIC bidirectional stream and send the following TCPRequest message:
```
[varint] 0x401 (TCPRequest ID)
[varint] Address length
[bytes] Address string (host:port)
[varint] Padding length
[bytes] Random padding
```
The server MUST respond with a TCPResponse message:
```
[uint8] Status (0x00 = OK, 0x01 = Error)
[varint] Message length
[bytes] Message string
[varint] Padding length
[bytes] Random padding
```
If the status is OK, the server MUST then begin forwarding data between the client and the specified TCP address until either side closes the connection. If the status is Error, the server MUST close the QUIC stream.
### UDP
UDP packets MUST be encapsulated in the following UDPMessage format and sent over QUIC's unreliable datagram (for both client-to-server and server-to-client):
```
[uint32] Session ID
[uint16] Packet ID
[uint8] Fragment ID
[uint8] Fragment count
[varint] Address length
[bytes] Address string (host:port)
[bytes] Payload
```
The client MUST use a unique Session ID for each UDP session. The server SHOULD assign a unique UDP port to each Session ID, unless it has another mechanism to differentiate packets from different sessions (e.g., symmetric NAT, varying outbound IP addresses, etc.).
The protocol does not provide an explicit way to close a UDP session. While a client can retain and reuse a Session ID indefinitely, the server SHOULD release and reassign the port associated with the Session ID after a period of inactivity or some other criteria. If the client sends a UDP packet to a Session ID that is no longer recognized by the server, the server MUST treat it as a new session and assign a new port.
If a server does not support UDP relay, it SHOULD silently discard all UDP messages received from the client.
#### Fragmentation
Due to the limit imposed by QUIC's unreliable datagram channel, any UDP packet that exceeds QUIC's maximum datagram size MUST either be fragmented or discarded.
For fragmented packets, each fragment MUST carry the same unique Packet ID. The Fragment ID, starting from 0, indicates the index out of the total Fragment Count. Both the server and client MUST wait for all fragments of a fragmented packet to arrive before processing them. If one or more fragments of a packet are lost, the entire packet MUST be discarded.
For packets that are not fragmented, the Fragment Count MUST be set to 1. In this case, the values of Packet ID and Fragment ID are irrelevant.
## Congestion Control
A unique feature of Hysteria is the ability to set the tx/rx (upload/download) rate on the client side. During authentication, the client sends its rx rate to the server via the `Hysteria-CC-RX` header. The server can use this to determine its transmission rate to the client, and vice versa by returning its rx rate to the client through the same header.
Three special cases are:
- If the client sends 0, it doesn't know its own rx rate. The server MUST use a congestion control algorithm (e.g., BBR, Cubic) to adjust its transmission rate.
- If the server responds with 0, it has no bandwidth limit. The client MAY transmit at any rate it wants.
- If the server responds with "auto", it chooses not to specify a rate. The client MUST use a congestion control algorithm to adjust its transmission rate.
## "Salamander" Obfuscation
The Hysteria protocol supports an optional obfuscation layer codenamed "Salamander".
"Salamander" encapsulates all QUIC packets in the following format:
```
[8 bytes] Salt
[bytes] Payload
```
For each QUIC packet, the obfuscator MUST calculate the BLAKE2b-256 hash of a randomly generated 8-byte salt appended to a user-provided pre-shared key.
```
hash = BLAKE2b-256(key + salt)
```
The hash is then used to obfuscate the payload using the following algorithm:
```
for i in range(0, len(payload)):
payload[i] ^= hash[i % 32]
```
The deobfuscator MUST use the same algorithms to calculate the salted hash and deobfuscate the payload. Any invalid packet MUST be discarded.
================================================
FILE: README.md
================================================
# 
# 支持对接V2board面板的Hysteria2后端
### 项目说明
本项目基于hysteria官方内核二次开发,添加了从v2b获取节点信息、用户鉴权信息与上报用户流量的功能。
性能方面已经由hysteria2内核作者亲自指导优化过了。
### TG交流群
欢迎加入交流群 [点击加入](https://t.me/+DcRt8AB2VbI2Yzc1)
### 示例配置
```
v2board:
apiHost: https://面板地址
apiKey: 面板节点密钥
nodeID: 节点ID
tls:
type: tls
cert: /etc/hysteria/tls.crt
key: /etc/hysteria/tls.key
auth:
type: v2board
trafficStats:
listen: 127.0.0.1:7653
acl:
inline:
- reject(10.0.0.0/8)
- reject(172.16.0.0/12)
- reject(192.168.0.0/16)
- reject(127.0.0.0/8)
- reject(fc00::/7)
```
> 其他配置完全与hysteria文档的一致,可以查看hysteria2官方文档 [点击查看](https://hysteria.network/zh/docs/getting-started/Installation/)
### 快速启动
```
docker run -itd --restart=always --network=host \
-e apiHost=https://example.com \
-e apiKey=xxxxxxxxxxxxxxxxxxxxx \
-e domain=hy2.example.com \
-e nodeID=1 \
ghcr.io/cedar2025/hysteria:latest
```
### docker 仓库
```
docker pull ghcr.io/cedar2025/hysteria:latest
```
================================================
FILE: app/cmd/client.go
================================================
package cmd
import (
"crypto/sha256"
"crypto/x509"
"encoding/hex"
"errors"
"fmt"
"net"
"net/netip"
"os"
"os/signal"
"runtime"
"slices"
"strconv"
"strings"
"syscall"
"time"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"go.uber.org/zap"
"github.com/apernet/hysteria/app/v2/internal/forwarding"
"github.com/apernet/hysteria/app/v2/internal/http"
"github.com/apernet/hysteria/app/v2/internal/proxymux"
"github.com/apernet/hysteria/app/v2/internal/redirect"
"github.com/apernet/hysteria/app/v2/internal/sockopts"
"github.com/apernet/hysteria/app/v2/internal/socks5"
"github.com/apernet/hysteria/app/v2/internal/tproxy"
"github.com/apernet/hysteria/app/v2/internal/tun"
"github.com/apernet/hysteria/app/v2/internal/url"
"github.com/apernet/hysteria/app/v2/internal/utils"
"github.com/apernet/hysteria/core/v2/client"
"github.com/apernet/hysteria/extras/v2/correctnet"
"github.com/apernet/hysteria/extras/v2/obfs"
"github.com/apernet/hysteria/extras/v2/transport/udphop"
)
// Client flags
var (
showQR bool
)
var clientCmd = &cobra.Command{
Use: "client",
Short: "Client mode",
Run: runClient,
}
func init() {
initClientFlags()
rootCmd.AddCommand(clientCmd)
}
func initClientFlags() {
clientCmd.Flags().BoolVar(&showQR, "qr", false, "show QR code for server config sharing")
}
type clientConfig struct {
Server string `mapstructure:"server"`
Auth string `mapstructure:"auth"`
Transport clientConfigTransport `mapstructure:"transport"`
Obfs clientConfigObfs `mapstructure:"obfs"`
TLS clientConfigTLS `mapstructure:"tls"`
QUIC clientConfigQUIC `mapstructure:"quic"`
Bandwidth clientConfigBandwidth `mapstructure:"bandwidth"`
FastOpen bool `mapstructure:"fastOpen"`
Lazy bool `mapstructure:"lazy"`
SOCKS5 *socks5Config `mapstructure:"socks5"`
HTTP *httpConfig `mapstructure:"http"`
TCPForwarding []tcpForwardingEntry `mapstructure:"tcpForwarding"`
UDPForwarding []udpForwardingEntry `mapstructure:"udpForwarding"`
TCPTProxy *tcpTProxyConfig `mapstructure:"tcpTProxy"`
UDPTProxy *udpTProxyConfig `mapstructure:"udpTProxy"`
TCPRedirect *tcpRedirectConfig `mapstructure:"tcpRedirect"`
TUN *tunConfig `mapstructure:"tun"`
}
type clientConfigTransportUDP struct {
HopInterval time.Duration `mapstructure:"hopInterval"`
}
type clientConfigTransport struct {
Type string `mapstructure:"type"`
UDP clientConfigTransportUDP `mapstructure:"udp"`
}
type clientConfigObfsSalamander struct {
Password string `mapstructure:"password"`
}
type clientConfigObfs struct {
Type string `mapstructure:"type"`
Salamander clientConfigObfsSalamander `mapstructure:"salamander"`
}
type clientConfigTLS struct {
SNI string `mapstructure:"sni"`
Insecure bool `mapstructure:"insecure"`
PinSHA256 string `mapstructure:"pinSHA256"`
CA string `mapstructure:"ca"`
}
type clientConfigQUIC struct {
InitStreamReceiveWindow uint64 `mapstructure:"initStreamReceiveWindow"`
MaxStreamReceiveWindow uint64 `mapstructure:"maxStreamReceiveWindow"`
InitConnectionReceiveWindow uint64 `mapstructure:"initConnReceiveWindow"`
MaxConnectionReceiveWindow uint64 `mapstructure:"maxConnReceiveWindow"`
MaxIdleTimeout time.Duration `mapstructure:"maxIdleTimeout"`
KeepAlivePeriod time.Duration `mapstructure:"keepAlivePeriod"`
DisablePathMTUDiscovery bool `mapstructure:"disablePathMTUDiscovery"`
Sockopts clientConfigQUICSockopts `mapstructure:"sockopts"`
}
type clientConfigQUICSockopts struct {
BindInterface *string `mapstructure:"bindInterface"`
FirewallMark *uint32 `mapstructure:"fwmark"`
FdControlUnixSocket *string `mapstructure:"fdControlUnixSocket"`
}
type clientConfigBandwidth struct {
Up string `mapstructure:"up"`
Down string `mapstructure:"down"`
}
type socks5Config struct {
Listen string `mapstructure:"listen"`
Username string `mapstructure:"username"`
Password string `mapstructure:"password"`
DisableUDP bool `mapstructure:"disableUDP"`
}
type httpConfig struct {
Listen string `mapstructure:"listen"`
Username string `mapstructure:"username"`
Password string `mapstructure:"password"`
Realm string `mapstructure:"realm"`
}
type tcpForwardingEntry struct {
Listen string `mapstructure:"listen"`
Remote string `mapstructure:"remote"`
}
type udpForwardingEntry struct {
Listen string `mapstructure:"listen"`
Remote string `mapstructure:"remote"`
Timeout time.Duration `mapstructure:"timeout"`
}
type tcpTProxyConfig struct {
Listen string `mapstructure:"listen"`
}
type udpTProxyConfig struct {
Listen string `mapstructure:"listen"`
Timeout time.Duration `mapstructure:"timeout"`
}
type tcpRedirectConfig struct {
Listen string `mapstructure:"listen"`
}
type tunConfig struct {
Name string `mapstructure:"name"`
MTU uint32 `mapstructure:"mtu"`
Timeout time.Duration `mapstructure:"timeout"`
Address struct {
IPv4 string `mapstructure:"ipv4"`
IPv6 string `mapstructure:"ipv6"`
} `mapstructure:"address"`
Route *struct {
Strict bool `mapstructure:"strict"`
IPv4 []string `mapstructure:"ipv4"`
IPv6 []string `mapstructure:"ipv6"`
IPv4Exclude []string `mapstructure:"ipv4Exclude"`
IPv6Exclude []string `mapstructure:"ipv6Exclude"`
} `mapstructure:"route"`
}
func (c *clientConfig) fillServerAddr(hyConfig *client.Config) error {
if c.Server == "" {
return configError{Field: "server", Err: errors.New("server address is empty")}
}
var addr net.Addr
var err error
host, port, hostPort := parseServerAddrString(c.Server)
if !isPortHoppingPort(port) {
addr, err = net.ResolveUDPAddr("udp", hostPort)
} else {
addr, err = udphop.ResolveUDPHopAddr(hostPort)
}
if err != nil {
return configError{Field: "server", Err: err}
}
hyConfig.ServerAddr = addr
// Special handling for SNI
if c.TLS.SNI == "" {
// Use server hostname as SNI
hyConfig.TLSConfig.ServerName = host
}
return nil
}
// fillConnFactory must be called after fillServerAddr, as we have different logic
// for ConnFactory depending on whether we have a port hopping address.
func (c *clientConfig) fillConnFactory(hyConfig *client.Config) error {
so := &sockopts.SocketOptions{
BindInterface: c.QUIC.Sockopts.BindInterface,
FirewallMark: c.QUIC.Sockopts.FirewallMark,
FdControlUnixSocket: c.QUIC.Sockopts.FdControlUnixSocket,
}
if err := so.CheckSupported(); err != nil {
var unsupportedErr *sockopts.UnsupportedError
if errors.As(err, &unsupportedErr) {
return configError{
Field: "quic.sockopts." + unsupportedErr.Field,
Err: errors.New("unsupported on this platform"),
}
}
return configError{Field: "quic.sockopts", Err: err}
}
// Inner PacketConn
var newFunc func(addr net.Addr) (net.PacketConn, error)
switch strings.ToLower(c.Transport.Type) {
case "", "udp":
if hyConfig.ServerAddr.Network() == "udphop" {
hopAddr := hyConfig.ServerAddr.(*udphop.UDPHopAddr)
newFunc = func(addr net.Addr) (net.PacketConn, error) {
return udphop.NewUDPHopPacketConn(hopAddr, c.Transport.UDP.HopInterval, so.ListenUDP)
}
} else {
newFunc = func(addr net.Addr) (net.PacketConn, error) {
return so.ListenUDP()
}
}
default:
return configError{Field: "transport.type", Err: errors.New("unsupported transport type")}
}
// Obfuscation
var ob obfs.Obfuscator
var err error
switch strings.ToLower(c.Obfs.Type) {
case "", "plain":
// Keep it nil
case "salamander":
ob, err = obfs.NewSalamanderObfuscator([]byte(c.Obfs.Salamander.Password))
if err != nil {
return configError{Field: "obfs.salamander.password", Err: err}
}
default:
return configError{Field: "obfs.type", Err: errors.New("unsupported obfuscation type")}
}
hyConfig.ConnFactory = &adaptiveConnFactory{
NewFunc: newFunc,
Obfuscator: ob,
}
return nil
}
func (c *clientConfig) fillAuth(hyConfig *client.Config) error {
hyConfig.Auth = c.Auth
return nil
}
func (c *clientConfig) fillTLSConfig(hyConfig *client.Config) error {
if c.TLS.SNI != "" {
hyConfig.TLSConfig.ServerName = c.TLS.SNI
}
hyConfig.TLSConfig.InsecureSkipVerify = c.TLS.Insecure
if c.TLS.PinSHA256 != "" {
nHash := normalizeCertHash(c.TLS.PinSHA256)
hyConfig.TLSConfig.VerifyPeerCertificate = func(rawCerts [][]byte, _ [][]*x509.Certificate) error {
for _, cert := range rawCerts {
hash := sha256.Sum256(cert)
hashHex := hex.EncodeToString(hash[:])
if hashHex == nHash {
return nil
}
}
// No match
return errors.New("no certificate matches the pinned hash")
}
}
if c.TLS.CA != "" {
ca, err := os.ReadFile(c.TLS.CA)
if err != nil {
return configError{Field: "tls.ca", Err: err}
}
cPool := x509.NewCertPool()
if !cPool.AppendCertsFromPEM(ca) {
return configError{Field: "tls.ca", Err: errors.New("failed to parse CA certificate")}
}
hyConfig.TLSConfig.RootCAs = cPool
}
return nil
}
func (c *clientConfig) fillQUICConfig(hyConfig *client.Config) error {
hyConfig.QUICConfig = client.QUICConfig{
InitialStreamReceiveWindow: c.QUIC.InitStreamReceiveWindow,
MaxStreamReceiveWindow: c.QUIC.MaxStreamReceiveWindow,
InitialConnectionReceiveWindow: c.QUIC.InitConnectionReceiveWindow,
MaxConnectionReceiveWindow: c.QUIC.MaxConnectionReceiveWindow,
MaxIdleTimeout: c.QUIC.MaxIdleTimeout,
KeepAlivePeriod: c.QUIC.KeepAlivePeriod,
DisablePathMTUDiscovery: c.QUIC.DisablePathMTUDiscovery,
}
return nil
}
func (c *clientConfig) fillBandwidthConfig(hyConfig *client.Config) error {
// New core now allows users to omit bandwidth values and use built-in congestion control
var err error
if c.Bandwidth.Up != "" {
hyConfig.BandwidthConfig.MaxTx, err = utils.ConvBandwidth(c.Bandwidth.Up)
if err != nil {
return configError{Field: "bandwidth.up", Err: err}
}
}
if c.Bandwidth.Down != "" {
hyConfig.BandwidthConfig.MaxRx, err = utils.ConvBandwidth(c.Bandwidth.Down)
if err != nil {
return configError{Field: "bandwidth.down", Err: err}
}
}
return nil
}
func (c *clientConfig) fillFastOpen(hyConfig *client.Config) error {
hyConfig.FastOpen = c.FastOpen
return nil
}
// URI generates a URI for sharing the config with others.
// Note that only the bare minimum of information required to
// connect to the server is included in the URI, specifically:
// - server address
// - authentication
// - obfuscation type
// - obfuscation password
// - TLS SNI
// - TLS insecure
// - TLS pinned SHA256 hash (normalized)
func (c *clientConfig) URI() string {
q := url.Values{}
switch strings.ToLower(c.Obfs.Type) {
case "salamander":
q.Set("obfs", "salamander")
q.Set("obfs-password", c.Obfs.Salamander.Password)
}
if c.TLS.SNI != "" {
q.Set("sni", c.TLS.SNI)
}
if c.TLS.Insecure {
q.Set("insecure", "1")
}
if c.TLS.PinSHA256 != "" {
q.Set("pinSHA256", normalizeCertHash(c.TLS.PinSHA256))
}
var user *url.Userinfo
if c.Auth != "" {
// We need to handle the special case of user:pass pairs
rs := strings.SplitN(c.Auth, ":", 2)
if len(rs) == 2 {
user = url.UserPassword(rs[0], rs[1])
} else {
user = url.User(c.Auth)
}
}
u := url.URL{
Scheme: "hysteria2",
User: user,
Host: c.Server,
Path: "/",
RawQuery: q.Encode(),
}
return u.String()
}
// parseURI tries to parse the server address field as a URI,
// and fills the config with the information contained in the URI.
// Returns whether the server address field is a valid URI.
// This allows a user to use put a URI as the server address and
// omit the fields that are already contained in the URI.
func (c *clientConfig) parseURI() bool {
u, err := url.Parse(c.Server)
if err != nil {
return false
}
if u.Scheme != "hysteria2" && u.Scheme != "hy2" {
return false
}
if u.User != nil {
auth, err := url.QueryUnescape(u.User.String())
if err != nil {
return false
}
c.Auth = auth
}
c.Server = u.Host
q := u.Query()
if obfsType := q.Get("obfs"); obfsType != "" {
c.Obfs.Type = obfsType
switch strings.ToLower(obfsType) {
case "salamander":
c.Obfs.Salamander.Password = q.Get("obfs-password")
}
}
if sni := q.Get("sni"); sni != "" {
c.TLS.SNI = sni
}
if insecure, err := strconv.ParseBool(q.Get("insecure")); err == nil {
c.TLS.Insecure = insecure
}
if pinSHA256 := q.Get("pinSHA256"); pinSHA256 != "" {
c.TLS.PinSHA256 = pinSHA256
}
return true
}
// Config validates the fields and returns a ready-to-use Hysteria client config
func (c *clientConfig) Config() (*client.Config, error) {
c.parseURI()
hyConfig := &client.Config{}
fillers := []func(*client.Config) error{
c.fillServerAddr,
c.fillConnFactory,
c.fillAuth,
c.fillTLSConfig,
c.fillQUICConfig,
c.fillBandwidthConfig,
c.fillFastOpen,
}
for _, f := range fillers {
if err := f(hyConfig); err != nil {
return nil, err
}
}
return hyConfig, nil
}
func runClient(cmd *cobra.Command, args []string) {
logger.Info("client mode")
if err := viper.ReadInConfig(); err != nil {
logger.Fatal("failed to read client config", zap.Error(err))
}
var config clientConfig
if err := viper.Unmarshal(&config); err != nil {
logger.Fatal("failed to parse client config", zap.Error(err))
}
c, err := client.NewReconnectableClient(
config.Config,
func(c client.Client, info *client.HandshakeInfo, count int) {
connectLog(info, count)
// On the client side, we start checking for updates after we successfully connect
// to the server, which, depending on whether lazy mode is enabled, may or may not
// be immediately after the client starts. We don't want the update check request
// to interfere with the lazy mode option.
if count == 1 && !disableUpdateCheck {
go runCheckUpdateClient(c)
}
}, config.Lazy)
if err != nil {
logger.Fatal("failed to initialize client", zap.Error(err))
}
defer c.Close()
uri := config.URI()
logger.Info("use this URI to share your server", zap.String("uri", uri))
if showQR {
utils.PrintQR(uri)
}
// Register modes
var runner clientModeRunner
if config.SOCKS5 != nil {
runner.Add("SOCKS5 server", func() error {
return clientSOCKS5(*config.SOCKS5, c)
})
}
if config.HTTP != nil {
runner.Add("HTTP proxy server", func() error {
return clientHTTP(*config.HTTP, c)
})
}
if len(config.TCPForwarding) > 0 {
runner.Add("TCP forwarding", func() error {
return clientTCPForwarding(config.TCPForwarding, c)
})
}
if len(config.UDPForwarding) > 0 {
runner.Add("UDP forwarding", func() error {
return clientUDPForwarding(config.UDPForwarding, c)
})
}
if config.TCPTProxy != nil {
runner.Add("TCP transparent proxy", func() error {
return clientTCPTProxy(*config.TCPTProxy, c)
})
}
if config.UDPTProxy != nil {
runner.Add("UDP transparent proxy", func() error {
return clientUDPTProxy(*config.UDPTProxy, c)
})
}
if config.TCPRedirect != nil {
runner.Add("TCP redirect", func() error {
return clientTCPRedirect(*config.TCPRedirect, c)
})
}
if config.TUN != nil {
runner.Add("TUN", func() error {
return clientTUN(*config.TUN, c)
})
}
signalChan := make(chan os.Signal, 1)
signal.Notify(signalChan, os.Interrupt, syscall.SIGTERM)
defer signal.Stop(signalChan)
runnerChan := make(chan clientModeRunnerResult, 1)
go func() {
runnerChan <- runner.Run()
}()
select {
case <-signalChan:
logger.Info("received signal, shutting down gracefully")
case r := <-runnerChan:
if r.OK {
logger.Info(r.Msg)
} else {
_ = c.Close() // Close the client here as Fatal will exit the program without running defer
if r.Err != nil {
logger.Fatal(r.Msg, zap.Error(r.Err))
} else {
logger.Fatal(r.Msg)
}
}
}
}
type clientModeRunner struct {
ModeMap map[string]func() error
}
type clientModeRunnerResult struct {
OK bool
Msg string
Err error
}
func (r *clientModeRunner) Add(name string, f func() error) {
if r.ModeMap == nil {
r.ModeMap = make(map[string]func() error)
}
r.ModeMap[name] = f
}
func (r *clientModeRunner) Run() clientModeRunnerResult {
if len(r.ModeMap) == 0 {
return clientModeRunnerResult{OK: false, Msg: "no mode specified"}
}
type modeError struct {
Name string
Err error
}
errChan := make(chan modeError, len(r.ModeMap))
for name, f := range r.ModeMap {
go func(name string, f func() error) {
err := f()
errChan <- modeError{name, err}
}(name, f)
}
// Fatal if any one of the modes fails
for i := 0; i < len(r.ModeMap); i++ {
e := <-errChan
if e.Err != nil {
return clientModeRunnerResult{OK: false, Msg: "failed to run " + e.Name, Err: e.Err}
}
}
// We don't really have any such cases, as currently none of our modes would stop on themselves without error.
// But we leave the possibility here for future expansion.
return clientModeRunnerResult{OK: true, Msg: "finished without error"}
}
func clientSOCKS5(config socks5Config, c client.Client) error {
if config.Listen == "" {
return configError{Field: "listen", Err: errors.New("listen address is empty")}
}
l, err := proxymux.ListenSOCKS(config.Listen)
if err != nil {
return configError{Field: "listen", Err: err}
}
var authFunc func(username, password string) bool
username, password := config.Username, config.Password
if username != "" && password != "" {
authFunc = func(u, p string) bool {
return u == username && p == password
}
}
s := socks5.Server{
HyClient: c,
AuthFunc: authFunc,
DisableUDP: config.DisableUDP,
EventLogger: &socks5Logger{},
}
logger.Info("SOCKS5 server listening", zap.String("addr", config.Listen))
return s.Serve(l)
}
func clientHTTP(config httpConfig, c client.Client) error {
if config.Listen == "" {
return configError{Field: "listen", Err: errors.New("listen address is empty")}
}
l, err := proxymux.ListenHTTP(config.Listen)
if err != nil {
return configError{Field: "listen", Err: err}
}
var authFunc func(username, password string) bool
username, password := config.Username, config.Password
if username != "" && password != "" {
authFunc = func(u, p string) bool {
return u == username && p == password
}
}
if config.Realm == "" {
config.Realm = "Hysteria"
}
h := http.Server{
HyClient: c,
AuthFunc: authFunc,
AuthRealm: config.Realm,
EventLogger: &httpLogger{},
}
logger.Info("HTTP proxy server listening", zap.String("addr", config.Listen))
return h.Serve(l)
}
func clientTCPForwarding(entries []tcpForwardingEntry, c client.Client) error {
errChan := make(chan error, len(entries))
for _, e := range entries {
if e.Listen == "" {
return configError{Field: "listen", Err: errors.New("listen address is empty")}
}
if e.Remote == "" {
return configError{Field: "remote", Err: errors.New("remote address is empty")}
}
l, err := correctnet.Listen("tcp", e.Listen)
if err != nil {
return configError{Field: "listen", Err: err}
}
logger.Info("TCP forwarding listening", zap.String("addr", e.Listen), zap.String("remote", e.Remote))
go func(remote string) {
t := &forwarding.TCPTunnel{
HyClient: c,
Remote: remote,
EventLogger: &tcpLogger{},
}
errChan <- t.Serve(l)
}(e.Remote)
}
// Return if any one of the forwarding fails
return <-errChan
}
func clientUDPForwarding(entries []udpForwardingEntry, c client.Client) error {
errChan := make(chan error, len(entries))
for _, e := range entries {
if e.Listen == "" {
return configError{Field: "listen", Err: errors.New("listen address is empty")}
}
if e.Remote == "" {
return configError{Field: "remote", Err: errors.New("remote address is empty")}
}
l, err := correctnet.ListenPacket("udp", e.Listen)
if err != nil {
return configError{Field: "listen", Err: err}
}
logger.Info("UDP forwarding listening", zap.String("addr", e.Listen), zap.String("remote", e.Remote))
go func(remote string, timeout time.Duration) {
u := &forwarding.UDPTunnel{
HyClient: c,
Remote: remote,
Timeout: timeout,
EventLogger: &udpLogger{},
}
errChan <- u.Serve(l)
}(e.Remote, e.Timeout)
}
// Return if any one of the forwarding fails
return <-errChan
}
func clientTCPTProxy(config tcpTProxyConfig, c client.Client) error {
if config.Listen == "" {
return configError{Field: "listen", Err: errors.New("listen address is empty")}
}
laddr, err := net.ResolveTCPAddr("tcp", config.Listen)
if err != nil {
return configError{Field: "listen", Err: err}
}
p := &tproxy.TCPTProxy{
HyClient: c,
EventLogger: &tcpTProxyLogger{},
}
logger.Info("TCP transparent proxy listening", zap.String("addr", config.Listen))
return p.ListenAndServe(laddr)
}
func clientUDPTProxy(config udpTProxyConfig, c client.Client) error {
if config.Listen == "" {
return configError{Field: "listen", Err: errors.New("listen address is empty")}
}
laddr, err := net.ResolveUDPAddr("udp", config.Listen)
if err != nil {
return configError{Field: "listen", Err: err}
}
p := &tproxy.UDPTProxy{
HyClient: c,
Timeout: config.Timeout,
EventLogger: &udpTProxyLogger{},
}
logger.Info("UDP transparent proxy listening", zap.String("addr", config.Listen))
return p.ListenAndServe(laddr)
}
func clientTCPRedirect(config tcpRedirectConfig, c client.Client) error {
if config.Listen == "" {
return configError{Field: "listen", Err: errors.New("listen address is empty")}
}
laddr, err := net.ResolveTCPAddr("tcp", config.Listen)
if err != nil {
return configError{Field: "listen", Err: err}
}
p := &redirect.TCPRedirect{
HyClient: c,
EventLogger: &tcpRedirectLogger{},
}
logger.Info("TCP redirect listening", zap.String("addr", config.Listen))
return p.ListenAndServe(laddr)
}
func clientTUN(config tunConfig, c client.Client) error {
supportedPlatforms := []string{"linux", "darwin", "windows", "android"}
if !slices.Contains(supportedPlatforms, runtime.GOOS) {
logger.Error("TUN is not supported on this platform", zap.String("platform", runtime.GOOS))
}
if config.Name == "" {
return configError{Field: "name", Err: errors.New("name is empty")}
}
if config.MTU == 0 {
config.MTU = 1500
}
timeout := int64(config.Timeout.Seconds())
if timeout == 0 {
timeout = 300
}
if config.Address.IPv4 == "" {
config.Address.IPv4 = "100.100.100.101/30"
}
prefix4, err := netip.ParsePrefix(config.Address.IPv4)
if err != nil {
return configError{Field: "address.ipv4", Err: err}
}
if config.Address.IPv6 == "" {
config.Address.IPv6 = "2001::ffff:ffff:ffff:fff1/126"
}
prefix6, err := netip.ParsePrefix(config.Address.IPv6)
if err != nil {
return configError{Field: "address.ipv6", Err: err}
}
server := &tun.Server{
HyClient: c,
EventLogger: &tunLogger{},
Logger: logger,
IfName: config.Name,
MTU: config.MTU,
Timeout: timeout,
Inet4Address: []netip.Prefix{prefix4},
Inet6Address: []netip.Prefix{prefix6},
}
if config.Route != nil {
server.AutoRoute = true
server.StructRoute = config.Route.Strict
parsePrefixes := func(field string, ss []string) ([]netip.Prefix, error) {
var prefixes []netip.Prefix
for i, s := range ss {
var p netip.Prefix
if strings.Contains(s, "/") {
var err error
p, err = netip.ParsePrefix(s)
if err != nil {
return nil, configError{Field: fmt.Sprintf("%s[%d]", field, i), Err: err}
}
} else {
pa, err := netip.ParseAddr(s)
if err != nil {
return nil, configError{Field: fmt.Sprintf("%s[%d]", field, i), Err: err}
}
p = netip.PrefixFrom(pa, pa.BitLen())
}
prefixes = append(prefixes, p)
}
return prefixes, nil
}
server.Inet4RouteAddress, err = parsePrefixes("route.ipv4", config.Route.IPv4)
if err != nil {
return err
}
server.Inet6RouteAddress, err = parsePrefixes("route.ipv6", config.Route.IPv6)
if err != nil {
return err
}
server.Inet4RouteExcludeAddress, err = parsePrefixes("route.ipv4Exclude", config.Route.IPv4Exclude)
if err != nil {
return err
}
server.Inet6RouteExcludeAddress, err = parsePrefixes("route.ipv6Exclude", config.Route.IPv6Exclude)
if err != nil {
return err
}
}
logger.Info("TUN listening", zap.String("interface", config.Name))
return server.Serve()
}
// parseServerAddrString parses server address string.
// Server address can be in either "host:port" or "host" format (in which case we assume port 443).
func parseServerAddrString(addrStr string) (host, port, hostPort string) {
h, p, err := net.SplitHostPort(addrStr)
if err != nil {
return addrStr, "443", net.JoinHostPort(addrStr, "443")
}
return h, p, addrStr
}
// isPortHoppingPort returns whether the port string is a port hopping port.
// We consider a port string to be a port hopping port if it contains "-" or ",".
func isPortHoppingPort(port string) bool {
return strings.Contains(port, "-") || strings.Contains(port, ",")
}
// normalizeCertHash normalizes a certificate hash string.
// It converts all characters to lowercase and removes possible separators such as ":" and "-".
func normalizeCertHash(hash string) string {
r := strings.ToLower(hash)
r = strings.ReplaceAll(r, ":", "")
r = strings.ReplaceAll(r, "-", "")
return r
}
type adaptiveConnFactory struct {
NewFunc func(addr net.Addr) (net.PacketConn, error)
Obfuscator obfs.Obfuscator // nil if no obfuscation
}
func (f *adaptiveConnFactory) New(addr net.Addr) (net.PacketConn, error) {
if f.Obfuscator == nil {
return f.NewFunc(addr)
} else {
conn, err := f.NewFunc(addr)
if err != nil {
return nil, err
}
return obfs.WrapPacketConn(conn, f.Obfuscator), nil
}
}
func connectLog(info *client.HandshakeInfo, count int) {
logger.Info("connected to server",
zap.Bool("udpEnabled", info.UDPEnabled),
zap.Uint64("tx", info.Tx),
zap.Int("count", count))
}
type socks5Logger struct{}
func (l *socks5Logger) TCPRequest(addr net.Addr, reqAddr string) {
logger.Debug("SOCKS5 TCP request", zap.String("addr", addr.String()), zap.String("reqAddr", reqAddr))
}
func (l *socks5Logger) TCPError(addr net.Addr, reqAddr string, err error) {
if err == nil {
logger.Debug("SOCKS5 TCP closed", zap.String("addr", addr.String()), zap.String("reqAddr", reqAddr))
} else {
logger.Warn("SOCKS5 TCP error", zap.String("addr", addr.String()), zap.String("reqAddr", reqAddr), zap.Error(err))
}
}
func (l *socks5Logger) UDPRequest(addr net.Addr) {
logger.Debug("SOCKS5 UDP request", zap.String("addr", addr.String()))
}
func (l *socks5Logger) UDPError(addr net.Addr, err error) {
if err == nil {
logger.Debug("SOCKS5 UDP closed", zap.String("addr", addr.String()))
} else {
logger.Warn("SOCKS5 UDP error", zap.String("addr", addr.String()), zap.Error(err))
}
}
type httpLogger struct{}
func (l *httpLogger) ConnectRequest(addr net.Addr, reqAddr string) {
logger.Debug("HTTP CONNECT request", zap.String("addr", addr.String()), zap.String("reqAddr", reqAddr))
}
func (l *httpLogger) ConnectError(addr net.Addr, reqAddr string, err error) {
if err == nil {
logger.Debug("HTTP CONNECT closed", zap.String("addr", addr.String()), zap.String("reqAddr", reqAddr))
} else {
logger.Warn("HTTP CONNECT error", zap.String("addr", addr.String()), zap.String("reqAddr", reqAddr), zap.Error(err))
}
}
func (l *httpLogger) HTTPRequest(addr net.Addr, reqURL string) {
logger.Debug("HTTP request", zap.String("addr", addr.String()), zap.String("reqURL", reqURL))
}
func (l *httpLogger) HTTPError(addr net.Addr, reqURL string, err error) {
if err == nil {
logger.Debug("HTTP closed", zap.String("addr", addr.String()), zap.String("reqURL", reqURL))
} else {
logger.Warn("HTTP error", zap.String("addr", addr.String()), zap.String("reqURL", reqURL), zap.Error(err))
}
}
type tcpLogger struct{}
func (l *tcpLogger) Connect(addr net.Addr) {
logger.Debug("TCP forwarding connect", zap.String("addr", addr.String()))
}
func (l *tcpLogger) Error(addr net.Addr, err error) {
if err == nil {
logger.Debug("TCP forwarding closed", zap.String("addr", addr.String()))
} else {
logger.Warn("TCP forwarding error", zap.String("addr", addr.String()), zap.Error(err))
}
}
type udpLogger struct{}
func (l *udpLogger) Connect(addr net.Addr) {
logger.Debug("UDP forwarding connect", zap.String("addr", addr.String()))
}
func (l *udpLogger) Error(addr net.Addr, err error) {
if err == nil {
logger.Debug("UDP forwarding closed", zap.String("addr", addr.String()))
} else {
logger.Warn("UDP forwarding error", zap.String("addr", addr.String()), zap.Error(err))
}
}
type tcpTProxyLogger struct{}
func (l *tcpTProxyLogger) Connect(addr, reqAddr net.Addr) {
logger.Debug("TCP transparent proxy connect", zap.String("addr", addr.String()), zap.String("reqAddr", reqAddr.String()))
}
func (l *tcpTProxyLogger) Error(addr, reqAddr net.Addr, err error) {
if err == nil {
logger.Debug("TCP transparent proxy closed", zap.String("addr", addr.String()), zap.String("reqAddr", reqAddr.String()))
} else {
logger.Warn("TCP transparent proxy error", zap.String("addr", addr.String()), zap.String("reqAddr", reqAddr.String()), zap.Error(err))
}
}
type udpTProxyLogger struct{}
func (l *udpTProxyLogger) Connect(addr, reqAddr net.Addr) {
logger.Debug("UDP transparent proxy connect", zap.String("addr", addr.String()), zap.String("reqAddr", reqAddr.String()))
}
func (l *udpTProxyLogger) Error(addr, reqAddr net.Addr, err error) {
if err == nil {
logger.Debug("UDP transparent proxy closed", zap.String("addr", addr.String()), zap.String("reqAddr", reqAddr.String()))
} else {
logger.Warn("UDP transparent proxy error", zap.String("addr", addr.String()), zap.String("reqAddr", reqAddr.String()), zap.Error(err))
}
}
type tcpRedirectLogger struct{}
func (l *tcpRedirectLogger) Connect(addr, reqAddr net.Addr) {
logger.Debug("TCP redirect connect", zap.String("addr", addr.String()), zap.String("reqAddr", reqAddr.String()))
}
func (l *tcpRedirectLogger) Error(addr, reqAddr net.Addr, err error) {
if err == nil {
logger.Debug("TCP redirect closed", zap.String("addr", addr.String()), zap.String("reqAddr", reqAddr.String()))
} else {
logger.Warn("TCP redirect error", zap.String("addr", addr.String()), zap.String("reqAddr", reqAddr.String()), zap.Error(err))
}
}
type tunLogger struct{}
func (l *tunLogger) TCPRequest(addr, reqAddr string) {
logger.Debug("TUN TCP request", zap.String("addr", addr), zap.String("reqAddr", reqAddr))
}
func (l *tunLogger) TCPError(addr, reqAddr string, err error) {
if err == nil {
logger.Debug("TUN TCP closed", zap.String("addr", addr), zap.String("reqAddr", reqAddr))
} else {
logger.Warn("TUN TCP error", zap.String("addr", addr), zap.String("reqAddr", reqAddr), zap.Error(err))
}
}
func (l *tunLogger) UDPRequest(addr string) {
logger.Debug("TUN UDP request", zap.String("addr", addr))
}
func (l *tunLogger) UDPError(addr string, err error) {
if err == nil {
logger.Debug("TUN UDP closed", zap.String("addr", addr))
} else {
logger.Warn("TUN UDP error", zap.String("addr", addr), zap.Error(err))
}
}
================================================
FILE: app/cmd/client_test.go
================================================
package cmd
import (
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/spf13/viper"
)
// TestClientConfig tests the parsing of the client config
func TestClientConfig(t *testing.T) {
viper.SetConfigFile("client_test.yaml")
err := viper.ReadInConfig()
assert.NoError(t, err)
var config clientConfig
err = viper.Unmarshal(&config)
assert.NoError(t, err)
assert.Equal(t, config, clientConfig{
Server: "example.com",
Auth: "weak_ahh_password",
Transport: clientConfigTransport{
Type: "udp",
UDP: clientConfigTransportUDP{
HopInterval: 30 * time.Second,
},
},
Obfs: clientConfigObfs{
Type: "salamander",
Salamander: clientConfigObfsSalamander{
Password: "cry_me_a_r1ver",
},
},
TLS: clientConfigTLS{
SNI: "another.example.com",
Insecure: true,
PinSHA256: "114515DEADBEEF",
CA: "custom_ca.crt",
},
QUIC: clientConfigQUIC{
InitStreamReceiveWindow: 1145141,
MaxStreamReceiveWindow: 1145142,
InitConnectionReceiveWindow: 1145143,
MaxConnectionReceiveWindow: 1145144,
MaxIdleTimeout: 10 * time.Second,
KeepAlivePeriod: 4 * time.Second,
DisablePathMTUDiscovery: true,
Sockopts: clientConfigQUICSockopts{
BindInterface: stringRef("eth0"),
FirewallMark: uint32Ref(1234),
FdControlUnixSocket: stringRef("test.sock"),
},
},
Bandwidth: clientConfigBandwidth{
Up: "200 mbps",
Down: "1 gbps",
},
FastOpen: true,
Lazy: true,
SOCKS5: &socks5Config{
Listen: "127.0.0.1:1080",
Username: "anon",
Password: "bro",
DisableUDP: true,
},
HTTP: &httpConfig{
Listen: "127.0.0.1:8080",
Username: "qqq",
Password: "bruh",
Realm: "martian",
},
TCPForwarding: []tcpForwardingEntry{
{
Listen: "127.0.0.1:8088",
Remote: "internal.example.com:80",
},
},
UDPForwarding: []udpForwardingEntry{
{
Listen: "127.0.0.1:5353",
Remote: "internal.example.com:53",
Timeout: 50 * time.Second,
},
},
TCPTProxy: &tcpTProxyConfig{
Listen: "127.0.0.1:2500",
},
UDPTProxy: &udpTProxyConfig{
Listen: "127.0.0.1:2501",
Timeout: 20 * time.Second,
},
TCPRedirect: &tcpRedirectConfig{
Listen: "127.0.0.1:3500",
},
TUN: &tunConfig{
Name: "hytun",
MTU: 1500,
Timeout: 60 * time.Second,
Address: struct {
IPv4 string `mapstructure:"ipv4"`
IPv6 string `mapstructure:"ipv6"`
}{IPv4: "100.100.100.101/30", IPv6: "2001::ffff:ffff:ffff:fff1/126"},
Route: &struct {
Strict bool `mapstructure:"strict"`
IPv4 []string `mapstructure:"ipv4"`
IPv6 []string `mapstructure:"ipv6"`
IPv4Exclude []string `mapstructure:"ipv4Exclude"`
IPv6Exclude []string `mapstructure:"ipv6Exclude"`
}{
Strict: true,
IPv4: []string{"0.0.0.0/0"},
IPv6: []string{"2000::/3"},
IPv4Exclude: []string{"192.0.2.1/32"},
IPv6Exclude: []string{"2001:db8::1/128"},
},
},
})
}
// TestClientConfigURI tests URI-related functions of clientConfig
func TestClientConfigURI(t *testing.T) {
tests := []struct {
uri string
uriOK bool
config *clientConfig
}{
{
uri: "hysteria2://god@zilla.jp/",
uriOK: true,
config: &clientConfig{
Server: "zilla.jp",
Auth: "god",
},
},
{
uri: "hysteria2://john:wick@continental.org:4443/",
uriOK: true,
config: &clientConfig{
Server: "continental.org:4443",
Auth: "john:wick",
},
},
{
uri: "hysteria2://saul@better.call:7000-10000,20000/",
uriOK: true,
config: &clientConfig{
Server: "better.call:7000-10000,20000",
Auth: "saul",
},
},
{
uri: "hysteria2://noauth.com/?insecure=1&obfs=salamander&obfs-password=66ccff&pinSHA256=deadbeef&sni=crap.cc",
uriOK: true,
config: &clientConfig{
Server: "noauth.com",
Auth: "",
Obfs: clientConfigObfs{
Type: "salamander",
Salamander: clientConfigObfsSalamander{
Password: "66ccff",
},
},
TLS: clientConfigTLS{
SNI: "crap.cc",
Insecure: true,
PinSHA256: "deadbeef",
},
},
},
{
uri: "invalid.bs",
uriOK: false,
config: nil,
},
{
uri: "https://www.google.com/search?q=test",
uriOK: false,
config: nil,
},
}
for _, test := range tests {
t.Run(test.uri, func(t *testing.T) {
// Test parseURI
nc := &clientConfig{Server: test.uri}
assert.Equal(t, nc.parseURI(), test.uriOK)
if test.uriOK {
assert.Equal(t, nc, test.config)
}
// Test URI generation
if test.config != nil {
assert.Equal(t, test.config.URI(), test.uri)
}
})
}
}
func stringRef(s string) *string {
return &s
}
func uint32Ref(i uint32) *uint32 {
return &i
}
================================================
FILE: app/cmd/client_test.yaml
================================================
server: example.com
auth: weak_ahh_password
transport:
type: udp
udp:
hopInterval: 30s
obfs:
type: salamander
salamander:
password: cry_me_a_r1ver
tls:
sni: another.example.com
insecure: true
pinSHA256: 114515DEADBEEF
ca: custom_ca.crt
quic:
initStreamReceiveWindow: 1145141
maxStreamReceiveWindow: 1145142
initConnReceiveWindow: 1145143
maxConnReceiveWindow: 1145144
maxIdleTimeout: 10s
keepAlivePeriod: 4s
disablePathMTUDiscovery: true
sockopts:
bindInterface: eth0
fwmark: 1234
fdControlUnixSocket: test.sock
bandwidth:
up: 200 mbps
down: 1 gbps
fastOpen: true
lazy: true
socks5:
listen: 127.0.0.1:1080
username: anon
password: bro
disableUDP: true
http:
listen: 127.0.0.1:8080
username: qqq
password: bruh
realm: martian
tcpForwarding:
- listen: 127.0.0.1:8088
remote: internal.example.com:80
udpForwarding:
- listen: 127.0.0.1:5353
remote: internal.example.com:53
timeout: 50s
tcpTProxy:
listen: 127.0.0.1:2500
udpTProxy:
listen: 127.0.0.1:2501
timeout: 20s
tcpRedirect:
listen: 127.0.0.1:3500
tun:
name: "hytun"
mtu: 1500
timeout: 1m
address:
ipv4: 100.100.100.101/30
ipv6: 2001::ffff:ffff:ffff:fff1/126
route:
strict: true
ipv4: [ 0.0.0.0/0 ]
ipv6: [ "2000::/3" ]
ipv4Exclude: [ 192.0.2.1/32 ]
ipv6Exclude: [ "2001:db8::1/128" ]
================================================
FILE: app/cmd/errors.go
================================================
package cmd
import (
"fmt"
)
type configError struct {
Field string
Err error
}
func (e configError) Error() string {
return fmt.Sprintf("invalid config: %s: %s", e.Field, e.Err)
}
func (e configError) Unwrap() error {
return e.Err
}
================================================
FILE: app/cmd/ping.go
================================================
package cmd
import (
"time"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"go.uber.org/zap"
"github.com/apernet/hysteria/core/v2/client"
)
// pingCmd represents the ping command
var pingCmd = &cobra.Command{
Use: "ping address",
Short: "Ping mode",
Long: "Perform a TCP ping to a specified remote address through the proxy server. Can be used as a simple connectivity test.",
Run: runPing,
}
func init() {
rootCmd.AddCommand(pingCmd)
}
func runPing(cmd *cobra.Command, args []string) {
logger.Info("ping mode")
if len(args) != 1 {
logger.Fatal("must specify one and only one address")
}
addr := args[0]
if err := viper.ReadInConfig(); err != nil {
logger.Fatal("failed to read client config", zap.Error(err))
}
var config clientConfig
if err := viper.Unmarshal(&config); err != nil {
logger.Fatal("failed to parse client config", zap.Error(err))
}
hyConfig, err := config.Config()
if err != nil {
logger.Fatal("failed to load client config", zap.Error(err))
}
c, info, err := client.NewClient(hyConfig)
if err != nil {
logger.Fatal("failed to initialize client", zap.Error(err))
}
defer c.Close()
logger.Info("connected to server",
zap.Bool("udpEnabled", info.UDPEnabled),
zap.Uint64("tx", info.Tx))
logger.Info("connecting", zap.String("addr", addr))
start := time.Now()
conn, err := c.TCP(addr)
if err != nil {
logger.Fatal("failed to connect", zap.Error(err), zap.String("time", time.Since(start).String()))
}
defer conn.Close()
logger.Info("connected", zap.String("time", time.Since(start).String()))
}
================================================
FILE: app/cmd/root.go
================================================
package cmd
import (
"fmt"
"os"
"strconv"
"strings"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)
const (
appLogo = `
░█░█░█░█░█▀▀░▀█▀░█▀▀░█▀▄░▀█▀░█▀█░░░▀▀▄
░█▀█░░█░░▀▀█░░█░░█▀▀░█▀▄░░█░░█▀█░░░▄▀░
░▀░▀░░▀░░▀▀▀░░▀░░▀▀▀░▀░▀░▀▀▀░▀░▀░░░▀▀▀
`
appDesc = "a powerful, lightning fast and censorship resistant proxy"
appAuthors = "Aperture Internet Laboratory <https://github.com/apernet>"
appLogLevelEnv = "HYSTERIA_LOG_LEVEL"
appLogFormatEnv = "HYSTERIA_LOG_FORMAT"
appDisableUpdateCheckEnv = "HYSTERIA_DISABLE_UPDATE_CHECK"
appACMEDirEnv = "HYSTERIA_ACME_DIR"
)
var (
// These values will be injected by the build system
appVersion = "Unknown"
appDate = "Unknown"
appType = "Unknown" // aka channel
appCommit = "Unknown"
appPlatform = "Unknown"
appArch = "Unknown"
appVersionLong = fmt.Sprintf("Version:\t%s\n"+
"BuildDate:\t%s\n"+
"BuildType:\t%s\n"+
"CommitHash:\t%s\n"+
"Platform:\t%s\n"+
"Architecture:\t%s",
appVersion, appDate, appType, appCommit, appPlatform, appArch)
appAboutLong = fmt.Sprintf("%s\n%s\n%s\n\n%s", appLogo, appDesc, appAuthors, appVersionLong)
)
var logger *zap.Logger
// Flags
var (
cfgFile string
logLevel string
logFormat string
disableUpdateCheck bool
)
var rootCmd = &cobra.Command{
Use: "hysteria",
Short: appDesc,
Long: appAboutLong,
Run: runClient, // Default to client mode
}
var logLevelMap = map[string]zapcore.Level{
"debug": zapcore.DebugLevel,
"info": zapcore.InfoLevel,
"warn": zapcore.WarnLevel,
"error": zapcore.ErrorLevel,
}
var logFormatMap = map[string]zapcore.EncoderConfig{
"console": {
TimeKey: "time",
LevelKey: "level",
NameKey: "logger",
MessageKey: "msg",
LineEnding: zapcore.DefaultLineEnding,
EncodeLevel: zapcore.CapitalColorLevelEncoder,
EncodeTime: zapcore.RFC3339TimeEncoder,
EncodeDuration: zapcore.SecondsDurationEncoder,
},
"json": {
TimeKey: "time",
LevelKey: "level",
NameKey: "logger",
MessageKey: "msg",
LineEnding: zapcore.DefaultLineEnding,
EncodeLevel: zapcore.LowercaseLevelEncoder,
EncodeTime: zapcore.EpochMillisTimeEncoder,
EncodeDuration: zapcore.SecondsDurationEncoder,
},
}
func Execute() {
err := rootCmd.Execute()
if err != nil {
os.Exit(1)
}
}
func init() {
initFlags()
cobra.MousetrapHelpText = "" // Disable the mousetrap so Windows users can run the exe directly by double-clicking
cobra.OnInitialize(initConfig)
cobra.OnInitialize(initLogger) // initLogger must come after initConfig as it depends on config
}
func initFlags() {
rootCmd.PersistentFlags().StringVarP(&cfgFile, "config", "c", "", "config file")
rootCmd.PersistentFlags().StringVarP(&logLevel, "log-level", "l", envOrDefaultString(appLogLevelEnv, "info"), "log level")
rootCmd.PersistentFlags().StringVarP(&logFormat, "log-format", "f", envOrDefaultString(appLogFormatEnv, "console"), "log format")
rootCmd.PersistentFlags().BoolVar(&disableUpdateCheck, "disable-update-check", envOrDefaultBool(appDisableUpdateCheckEnv, false), "disable update check")
}
func initConfig() {
if cfgFile != "" {
viper.SetConfigFile(cfgFile)
} else {
viper.SetConfigName("config")
viper.SetConfigType("yaml")
viper.SupportedExts = append([]string{"yaml", "yml"}, viper.SupportedExts...)
viper.AddConfigPath(".")
viper.AddConfigPath("$HOME/.hysteria")
viper.AddConfigPath("/etc/hysteria/")
}
}
func initLogger() {
level, ok := logLevelMap[strings.ToLower(logLevel)]
if !ok {
fmt.Printf("unsupported log level: %s\n", logLevel)
os.Exit(1)
}
enc, ok := logFormatMap[strings.ToLower(logFormat)]
if !ok {
fmt.Printf("unsupported log format: %s\n", logFormat)
os.Exit(1)
}
c := zap.Config{
Level: zap.NewAtomicLevelAt(level),
DisableCaller: true,
DisableStacktrace: true,
Encoding: strings.ToLower(logFormat),
EncoderConfig: enc,
OutputPaths: []string{"stderr"},
ErrorOutputPaths: []string{"stderr"},
}
var err error
logger, err = c.Build()
if err != nil {
fmt.Printf("failed to initialize logger: %s\n", err)
os.Exit(1)
}
}
func envOrDefaultString(key, def string) string {
if v := os.Getenv(key); v != "" {
return v
}
return def
}
func envOrDefaultBool(key string, def bool) bool {
if v := os.Getenv(key); v != "" {
b, _ := strconv.ParseBool(v)
return b
}
return def
}
================================================
FILE: app/cmd/server.go
================================================
package cmd
import (
"context"
"crypto/tls"
"encoding/json"
"errors"
"fmt"
"io"
"net"
"net/http"
"net/http/httputil"
"net/url"
"os"
"strconv"
"strings"
"time"
"github.com/caddyserver/certmagic"
"github.com/libdns/cloudflare"
"github.com/libdns/duckdns"
"github.com/libdns/gandi"
"github.com/libdns/godaddy"
"github.com/libdns/namedotcom"
"github.com/libdns/vultr"
"github.com/mholt/acmez/acme"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"go.uber.org/zap"
"github.com/apernet/hysteria/app/v2/internal/utils"
"github.com/apernet/hysteria/core/v2/server"
"github.com/apernet/hysteria/extras/v2/auth"
"github.com/apernet/hysteria/extras/v2/correctnet"
"github.com/apernet/hysteria/extras/v2/masq"
"github.com/apernet/hysteria/extras/v2/obfs"
"github.com/apernet/hysteria/extras/v2/outbounds"
"github.com/apernet/hysteria/extras/v2/sniff"
"github.com/apernet/hysteria/extras/v2/trafficlogger"
eUtils "github.com/apernet/hysteria/extras/v2/utils"
)
const (
defaultListenAddr = ":443"
)
var serverCmd = &cobra.Command{
Use: "server",
Short: "Server mode",
Run: runServer,
}
func init() {
rootCmd.AddCommand(serverCmd)
}
type serverConfig struct {
V2board *v2boardConfig `mapstructure:"v2board"`
Listen string `mapstructure:"listen"`
Obfs serverConfigObfs `mapstructure:"obfs"`
TLS *serverConfigTLS `mapstructure:"tls"`
ACME *serverConfigACME `mapstructure:"acme"`
QUIC serverConfigQUIC `mapstructure:"quic"`
Bandwidth serverConfigBandwidth `mapstructure:"bandwidth"`
IgnoreClientBandwidth bool `mapstructure:"ignoreClientBandwidth"`
SpeedTest bool `mapstructure:"speedTest"`
DisableUDP bool `mapstructure:"disableUDP"`
UDPIdleTimeout time.Duration `mapstructure:"udpIdleTimeout"`
Auth serverConfigAuth `mapstructure:"auth"`
Resolver serverConfigResolver `mapstructure:"resolver"`
Sniff serverConfigSniff `mapstructure:"sniff"`
ACL serverConfigACL `mapstructure:"acl"`
Outbounds []serverConfigOutboundEntry `mapstructure:"outbounds"`
TrafficStats serverConfigTrafficStats `mapstructure:"trafficStats"`
Masquerade serverConfigMasquerade `mapstructure:"masquerade"`
}
type v2boardConfig struct {
ApiHost string `mapstructure:"apiHost"`
ApiKey string `mapstructure:"apiKey"`
NodeID uint `mapstructure:"nodeID"`
PullInterval time.Duration `mapstructure:"pullInterval"`
PushInterval time.Duration `mapstructure:"pushInterval"`
}
type serverConfigObfsSalamander struct {
Password string `mapstructure:"password"`
}
type serverConfigObfs struct {
Type string `mapstructure:"type"`
Salamander serverConfigObfsSalamander `mapstructure:"salamander"`
}
type serverConfigTLS struct {
Cert string `mapstructure:"cert"`
Key string `mapstructure:"key"`
SNIGuard string `mapstructure:"sniGuard"` // "disable", "dns-san", "strict"
}
type serverConfigACME struct {
// Common fields
Domains []string `mapstructure:"domains"`
Email string `mapstructure:"email"`
CA string `mapstructure:"ca"`
ListenHost string `mapstructure:"listenHost"`
Dir string `mapstructure:"dir"`
// Type selection
Type string `mapstructure:"type"`
HTTP serverConfigACMEHTTP `mapstructure:"http"`
TLS serverConfigACMETLS `mapstructure:"tls"`
DNS serverConfigACMEDNS `mapstructure:"dns"`
// Legacy fields for backwards compatibility
// Only applicable when Type is empty
DisableHTTP bool `mapstructure:"disableHTTP"`
DisableTLSALPN bool `mapstructure:"disableTLSALPN"`
AltHTTPPort int `mapstructure:"altHTTPPort"`
AltTLSALPNPort int `mapstructure:"altTLSALPNPort"`
}
type serverConfigACMEHTTP struct {
AltPort int `mapstructure:"altPort"`
}
type serverConfigACMETLS struct {
AltPort int `mapstructure:"altPort"`
}
type serverConfigACMEDNS struct {
Name string `mapstructure:"name"`
Config map[string]string `mapstructure:"config"`
}
type serverConfigQUIC struct {
InitStreamReceiveWindow uint64 `mapstructure:"initStreamReceiveWindow"`
MaxStreamReceiveWindow uint64 `mapstructure:"maxStreamReceiveWindow"`
InitConnectionReceiveWindow uint64 `mapstructure:"initConnReceiveWindow"`
MaxConnectionReceiveWindow uint64 `mapstructure:"maxConnReceiveWindow"`
MaxIdleTimeout time.Duration `mapstructure:"maxIdleTimeout"`
MaxIncomingStreams int64 `mapstructure:"maxIncomingStreams"`
DisablePathMTUDiscovery bool `mapstructure:"disablePathMTUDiscovery"`
}
type serverConfigBandwidth struct {
Up string `mapstructure:"up"`
Down string `mapstructure:"down"`
}
type serverConfigAuthHTTP struct {
URL string `mapstructure:"url"`
Insecure bool `mapstructure:"insecure"`
}
type serverConfigAuth struct {
Type string `mapstructure:"type"`
Password string `mapstructure:"password"`
UserPass map[string]string `mapstructure:"userpass"`
HTTP serverConfigAuthHTTP `mapstructure:"http"`
Command string `mapstructure:"command"`
}
type serverConfigResolverTCP struct {
Addr string `mapstructure:"addr"`
Timeout time.Duration `mapstructure:"timeout"`
}
type serverConfigResolverUDP struct {
Addr string `mapstructure:"addr"`
Timeout time.Duration `mapstructure:"timeout"`
}
type serverConfigResolverTLS struct {
Addr string `mapstructure:"addr"`
Timeout time.Duration `mapstructure:"timeout"`
SNI string `mapstructure:"sni"`
Insecure bool `mapstructure:"insecure"`
}
type serverConfigResolverHTTPS struct {
Addr string `mapstructure:"addr"`
Timeout time.Duration `mapstructure:"timeout"`
SNI string `mapstructure:"sni"`
Insecure bool `mapstructure:"insecure"`
}
type serverConfigResolver struct {
Type string `mapstructure:"type"`
TCP serverConfigResolverTCP `mapstructure:"tcp"`
UDP serverConfigResolverUDP `mapstructure:"udp"`
TLS serverConfigResolverTLS `mapstructure:"tls"`
HTTPS serverConfigResolverHTTPS `mapstructure:"https"`
}
type serverConfigSniff struct {
Enable bool `mapstructure:"enable"`
Timeout time.Duration `mapstructure:"timeout"`
RewriteDomain bool `mapstructure:"rewriteDomain"`
TCPPorts string `mapstructure:"tcpPorts"`
UDPPorts string `mapstructure:"udpPorts"`
}
type serverConfigACL struct {
File string `mapstructure:"file"`
Inline []string `mapstructure:"inline"`
GeoIP string `mapstructure:"geoip"`
GeoSite string `mapstructure:"geosite"`
GeoUpdateInterval time.Duration `mapstructure:"geoUpdateInterval"`
}
type serverConfigOutboundDirect struct {
Mode string `mapstructure:"mode"`
BindIPv4 string `mapstructure:"bindIPv4"`
BindIPv6 string `mapstructure:"bindIPv6"`
BindDevice string `mapstructure:"bindDevice"`
}
type serverConfigOutboundSOCKS5 struct {
Addr string `mapstructure:"addr"`
Username string `mapstructure:"username"`
Password string `mapstructure:"password"`
}
type serverConfigOutboundHTTP struct {
URL string `mapstructure:"url"`
Insecure bool `mapstructure:"insecure"`
}
type serverConfigOutboundEntry struct {
Name string `mapstructure:"name"`
Type string `mapstructure:"type"`
Direct serverConfigOutboundDirect `mapstructure:"direct"`
SOCKS5 serverConfigOutboundSOCKS5 `mapstructure:"socks5"`
HTTP serverConfigOutboundHTTP `mapstructure:"http"`
}
type serverConfigTrafficStats struct {
Listen string `mapstructure:"listen"`
Secret string `mapstructure:"secret"`
}
type serverConfigMasqueradeFile struct {
Dir string `mapstructure:"dir"`
}
type serverConfigMasqueradeProxy struct {
URL string `mapstructure:"url"`
RewriteHost bool `mapstructure:"rewriteHost"`
}
type serverConfigMasqueradeString struct {
Content string `mapstructure:"content"`
Headers map[string]string `mapstructure:"headers"`
StatusCode int `mapstructure:"statusCode"`
}
type serverConfigMasquerade struct {
Type string `mapstructure:"type"`
File serverConfigMasqueradeFile `mapstructure:"file"`
Proxy serverConfigMasqueradeProxy `mapstructure:"proxy"`
String serverConfigMasqueradeString `mapstructure:"string"`
ListenHTTP string `mapstructure:"listenHTTP"`
ListenHTTPS string `mapstructure:"listenHTTPS"`
ForceHTTPS bool `mapstructure:"forceHTTPS"`
}
func (c *serverConfig) fillConn(hyConfig *server.Config) error {
listenAddr := c.Listen
if listenAddr == "" {
listenAddr = defaultListenAddr
}
uAddr, err := net.ResolveUDPAddr("udp", listenAddr)
if err != nil {
return configError{Field: "listen", Err: err}
}
conn, err := correctnet.ListenUDP("udp", uAddr)
if err != nil {
return configError{Field: "listen", Err: err}
}
switch strings.ToLower(c.Obfs.Type) {
case "", "plain":
hyConfig.Conn = conn
return nil
case "salamander":
ob, err := obfs.NewSalamanderObfuscator([]byte(c.Obfs.Salamander.Password))
if err != nil {
return configError{Field: "obfs.salamander.password", Err: err}
}
hyConfig.Conn = obfs.WrapPacketConn(conn, ob)
return nil
default:
return configError{Field: "obfs.type", Err: errors.New("unsupported obfuscation type")}
}
}
func (c *serverConfig) fillTLSConfig(hyConfig *server.Config) error {
if c.TLS == nil && c.ACME == nil {
return configError{Field: "tls", Err: errors.New("must set either tls or acme")}
}
if c.TLS != nil && c.ACME != nil {
return configError{Field: "tls", Err: errors.New("cannot set both tls and acme")}
}
if c.TLS != nil {
// SNI guard
var sniGuard utils.SNIGuardFunc
switch strings.ToLower(c.TLS.SNIGuard) {
case "", "dns-san":
sniGuard = utils.SNIGuardDNSSAN
case "strict":
sniGuard = utils.SNIGuardStrict
case "disable":
sniGuard = nil
default:
return configError{Field: "tls.sniGuard", Err: errors.New("unsupported SNI guard")}
}
// Local TLS cert
if c.TLS.Cert == "" || c.TLS.Key == "" {
return configError{Field: "tls", Err: errors.New("empty cert or key path")}
}
certLoader := &utils.LocalCertificateLoader{
CertFile: c.TLS.Cert,
KeyFile: c.TLS.Key,
SNIGuard: sniGuard,
}
// Try loading the cert-key pair here to catch errors early
// (e.g. invalid files or insufficient permissions)
err := certLoader.InitializeCache()
if err != nil {
var pathErr *os.PathError
if errors.As(err, &pathErr) {
if pathErr.Path == c.TLS.Cert {
return configError{Field: "tls.cert", Err: pathErr}
}
if pathErr.Path == c.TLS.Key {
return configError{Field: "tls.key", Err: pathErr}
}
}
return configError{Field: "tls", Err: err}
}
// Use GetCertificate instead of Certificates so that
// users can update the cert without restarting the server.
hyConfig.TLSConfig.GetCertificate = certLoader.GetCertificate
} else {
// ACME
dataDir := c.ACME.Dir
if dataDir == "" {
// If not specified in the config, check the environment variable
// before resorting to the default "acme" value. The main reason
// we have this is so that our setup script can set it to the
// user's home directory.
dataDir = envOrDefaultString(appACMEDirEnv, "acme")
}
cmCfg := &certmagic.Config{
RenewalWindowRatio: certmagic.DefaultRenewalWindowRatio,
KeySource: certmagic.DefaultKeyGenerator,
Storage: &certmagic.FileStorage{Path: dataDir},
Logger: logger,
}
cmIssuer := certmagic.NewACMEIssuer(cmCfg, certmagic.ACMEIssuer{
Email: c.ACME.Email,
Agreed: true,
ListenHost: c.ACME.ListenHost,
Logger: logger,
})
switch strings.ToLower(c.ACME.CA) {
case "letsencrypt", "le", "":
// Default to Let's Encrypt
cmIssuer.CA = certmagic.LetsEncryptProductionCA
case "zerossl", "zero":
cmIssuer.CA = certmagic.ZeroSSLProductionCA
eab, err := genZeroSSLEAB(c.ACME.Email)
if err != nil {
return configError{Field: "acme.ca", Err: err}
}
cmIssuer.ExternalAccount = eab
default:
return configError{Field: "acme.ca", Err: errors.New("unsupported CA")}
}
switch strings.ToLower(c.ACME.Type) {
case "http":
cmIssuer.DisableHTTPChallenge = false
cmIssuer.DisableTLSALPNChallenge = true
cmIssuer.DNS01Solver = nil
cmIssuer.AltHTTPPort = c.ACME.HTTP.AltPort
case "tls":
cmIssuer.DisableHTTPChallenge = true
cmIssuer.DisableTLSALPNChallenge = false
cmIssuer.DNS01Solver = nil
cmIssuer.AltTLSALPNPort = c.ACME.TLS.AltPort
case "dns":
cmIssuer.DisableHTTPChallenge = true
cmIssuer.DisableTLSALPNChallenge = true
if c.ACME.DNS.Name == "" {
return configError{Field: "acme.dns.name", Err: errors.New("empty DNS provider name")}
}
if c.ACME.DNS.Config == nil {
return configError{Field: "acme.dns.config", Err: errors.New("empty DNS provider config")}
}
switch strings.ToLower(c.ACME.DNS.Name) {
case "cloudflare":
cmIssuer.DNS01Solver = &certmagic.DNS01Solver{
DNSProvider: &cloudflare.Provider{
APIToken: c.ACME.DNS.Config["cloudflare_api_token"],
},
}
case "duckdns":
cmIssuer.DNS01Solver = &certmagic.DNS01Solver{
DNSProvider: &duckdns.Provider{
APIToken: c.ACME.DNS.Config["duckdns_api_token"],
OverrideDomain: c.ACME.DNS.Config["duckdns_override_domain"],
},
}
case "gandi":
cmIssuer.DNS01Solver = &certmagic.DNS01Solver{
DNSProvider: &gandi.Provider{
BearerToken: c.ACME.DNS.Config["gandi_api_token"],
},
}
case "godaddy":
cmIssuer.DNS01Solver = &certmagic.DNS01Solver{
DNSProvider: &godaddy.Provider{
APIToken: c.ACME.DNS.Config["godaddy_api_token"],
},
}
case "namedotcom":
cmIssuer.DNS01Solver = &certmagic.DNS01Solver{
DNSProvider: &namedotcom.Provider{
Token: c.ACME.DNS.Config["namedotcom_token"],
User: c.ACME.DNS.Config["namedotcom_user"],
Server: c.ACME.DNS.Config["namedotcom_server"],
},
}
case "vultr":
cmIssuer.DNS01Solver = &certmagic.DNS01Solver{
DNSProvider: &vultr.Provider{
APIToken: c.ACME.DNS.Config["vultr_api_token"],
},
}
default:
return configError{Field: "acme.dns.name", Err: errors.New("unsupported DNS provider")}
}
case "":
// Legacy compatibility mode
cmIssuer.DisableHTTPChallenge = c.ACME.DisableHTTP
cmIssuer.DisableTLSALPNChallenge = c.ACME.DisableTLSALPN
cmIssuer.AltHTTPPort = c.ACME.AltHTTPPort
cmIssuer.AltTLSALPNPort = c.ACME.AltTLSALPNPort
default:
return configError{Field: "acme.type", Err: errors.New("unsupported ACME type")}
}
cmCfg.Issuers = []certmagic.Issuer{cmIssuer}
cmCache := certmagic.NewCache(certmagic.CacheOptions{
GetConfigForCert: func(cert certmagic.Certificate) (*certmagic.Config, error) {
return cmCfg, nil
},
Logger: logger,
})
cmCfg = certmagic.New(cmCache, *cmCfg)
if len(c.ACME.Domains) == 0 {
return configError{Field: "acme.domains", Err: errors.New("empty domains")}
}
err := cmCfg.ManageSync(context.Background(), c.ACME.Domains)
if err != nil {
return configError{Field: "acme.domains", Err: err}
}
hyConfig.TLSConfig.GetCertificate = cmCfg.GetCertificate
}
return nil
}
func genZeroSSLEAB(email string) (*acme.EAB, error) {
req, err := http.NewRequest(
http.MethodPost,
"https://api.zerossl.com/acme/eab-credentials-email",
strings.NewReader(url.Values{"email": []string{email}}.Encode()),
)
if err != nil {
return nil, fmt.Errorf("failed to creare ZeroSSL EAB request: %w", err)
}
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
req.Header.Set("User-Agent", certmagic.UserAgent)
resp, err := http.DefaultClient.Do(req)
if err != nil {
return nil, fmt.Errorf("failed to send ZeroSSL EAB request: %w", err)
}
defer func() { _ = resp.Body.Close() }()
var result struct {
Success bool `json:"success"`
Error struct {
Code int `json:"code"`
Type string `json:"type"`
} `json:"error"`
EABKID string `json:"eab_kid"`
EABHMACKey string `json:"eab_hmac_key"`
}
if err = json.NewDecoder(resp.Body).Decode(&result); err != nil {
return nil, fmt.Errorf("failed decoding ZeroSSL EAB API response: %w", err)
}
if result.Error.Code != 0 {
return nil, fmt.Errorf("failed getting ZeroSSL EAB credentials: HTTP %d: %s (code %d)", resp.StatusCode, result.Error.Type, result.Error.Code)
}
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("failed getting EAB credentials: HTTP %d", resp.StatusCode)
}
return &acme.EAB{
KeyID: result.EABKID,
MACKey: result.EABHMACKey,
}, nil
}
func (c *serverConfig) fillQUICConfig(hyConfig *server.Config) error {
hyConfig.QUICConfig = server.QUICConfig{
InitialStreamReceiveWindow: c.QUIC.InitStreamReceiveWindow,
MaxStreamReceiveWindow: c.QUIC.MaxStreamReceiveWindow,
InitialConnectionReceiveWindow: c.QUIC.InitConnectionReceiveWindow,
MaxConnectionReceiveWindow: c.QUIC.MaxConnectionReceiveWindow,
MaxIdleTimeout: c.QUIC.MaxIdleTimeout,
MaxIncomingStreams: c.QUIC.MaxIncomingStreams,
DisablePathMTUDiscovery: c.QUIC.DisablePathMTUDiscovery,
}
return nil
}
func serverConfigOutboundDirectToOutbound(c serverConfigOutboundDirect) (outbounds.PluggableOutbound, error) {
var mode outbounds.DirectOutboundMode
switch strings.ToLower(c.Mode) {
case "", "auto":
mode = outbounds.DirectOutboundModeAuto
case "64":
mode = outbounds.DirectOutboundMode64
case "46":
mode = outbounds.DirectOutboundMode46
case "6":
mode = outbounds.DirectOutboundMode6
case "4":
mode = outbounds.DirectOutboundMode4
default:
return nil, configError{Field: "outbounds.direct.mode", Err: errors.New("unsupported mode")}
}
bindIP := len(c.BindIPv4) > 0 || len(c.BindIPv6) > 0
bindDevice := len(c.BindDevice) > 0
if bindIP && bindDevice {
return nil, configError{Field: "outbounds.direct", Err: errors.New("cannot bind both IP and device")}
}
if bindIP {
ip4, ip6 := net.ParseIP(c.BindIPv4), net.ParseIP(c.BindIPv6)
if len(c.BindIPv4) > 0 && ip4 == nil {
return nil, configError{Field: "outbounds.direct.bindIPv4", Err: errors.New("invalid IPv4 address")}
}
if len(c.BindIPv6) > 0 && ip6 == nil {
return nil, configError{Field: "outbounds.direct.bindIPv6", Err: errors.New("invalid IPv6 address")}
}
return outbounds.NewDirectOutboundBindToIPs(mode, ip4, ip6)
}
if bindDevice {
return outbounds.NewDirectOutboundBindToDevice(mode, c.BindDevice)
}
return outbounds.NewDirectOutboundSimple(mode), nil
}
func serverConfigOutboundSOCKS5ToOutbound(c serverConfigOutboundSOCKS5) (outbounds.PluggableOutbound, error) {
if c.Addr == "" {
return nil, configError{Field: "outbounds.socks5.addr", Err: errors.New("empty socks5 address")}
}
return outbounds.NewSOCKS5Outbound(c.Addr, c.Username, c.Password), nil
}
func serverConfigOutboundHTTPToOutbound(c serverConfigOutboundHTTP) (outbounds.PluggableOutbound, error) {
if c.URL == "" {
return nil, configError{Field: "outbounds.http.url", Err: errors.New("empty http address")}
}
return outbounds.NewHTTPOutbound(c.URL, c.Insecure)
}
func (c *serverConfig) fillRequestHook(hyConfig *server.Config) error {
if c.Sniff.Enable {
s := &sniff.Sniffer{
Timeout: c.Sniff.Timeout,
RewriteDomain: c.Sniff.RewriteDomain,
}
if c.Sniff.TCPPorts != "" {
s.TCPPorts = eUtils.ParsePortUnion(c.Sniff.TCPPorts)
if s.TCPPorts == nil {
return configError{Field: "sniff.tcpPorts", Err: errors.New("invalid port union")}
}
}
if c.Sniff.UDPPorts != "" {
s.UDPPorts = eUtils.ParsePortUnion(c.Sniff.UDPPorts)
if s.UDPPorts == nil {
return configError{Field: "sniff.udpPorts", Err: errors.New("invalid port union")}
}
}
hyConfig.RequestHook = s
}
return nil
}
func (c *serverConfig) fillOutboundConfig(hyConfig *server.Config) error {
// Resolver, ACL, actual outbound are all implemented through the Outbound interface.
// Depending on the config, we build a chain like this:
// Resolver(ACL(Outbounds...))
// Outbounds
var obs []outbounds.OutboundEntry
if len(c.Outbounds) == 0 {
// Guarantee we have at least one outbound
obs = []outbounds.OutboundEntry{{
Name: "default",
Outbound: outbounds.NewDirectOutboundSimple(outbounds.DirectOutboundModeAuto),
}}
} else {
obs = make([]outbounds.OutboundEntry, len(c.Outbounds))
for i, entry := range c.Outbounds {
if entry.Name == "" {
return configError{Field: "outbounds.name", Err: errors.New("empty outbound name")}
}
var ob outbounds.PluggableOutbound
var err error
switch strings.ToLower(entry.Type) {
case "direct":
ob, err = serverConfigOutboundDirectToOutbound(entry.Direct)
case "socks5":
ob, err = serverConfigOutboundSOCKS5ToOutbound(entry.SOCKS5)
case "http":
ob, err = serverConfigOutboundHTTPToOutbound(entry.HTTP)
default:
err = configError{Field: "outbounds.type", Err: errors.New("unsupported outbound type")}
}
if err != nil {
return err
}
obs[i] = outbounds.OutboundEntry{Name: entry.Name, Outbound: ob}
}
}
var uOb outbounds.PluggableOutbound // "unified" outbound
// ACL
hasACL := false
if c.ACL.File != "" && len(c.ACL.Inline) > 0 {
return configError{Field: "acl", Err: errors.New("cannot set both acl.file and acl.inline")}
}
gLoader := &utils.GeoLoader{
GeoIPFilename: c.ACL.GeoIP,
GeoSiteFilename: c.ACL.GeoSite,
UpdateInterval: c.ACL.GeoUpdateInterval,
DownloadFunc: geoDownloadFunc,
DownloadErrFunc: geoDownloadErrFunc,
}
if c.ACL.File != "" {
hasACL = true
acl, err := outbounds.NewACLEngineFromFile(c.ACL.File, obs, gLoader)
if err != nil {
return configError{Field: "acl.file", Err: err}
}
uOb = acl
} else if len(c.ACL.Inline) > 0 {
hasACL = true
acl, err := outbounds.NewACLEngineFromString(strings.Join(c.ACL.Inline, "\n"), obs, gLoader)
if err != nil {
return configError{Field: "acl.inline", Err: err}
}
uOb = acl
} else {
// No ACL, use the first outbound
uOb = obs[0].Outbound
}
// Resolver
switch strings.ToLower(c.Resolver.Type) {
case "", "system":
if hasACL {
// If the user uses ACL, we must put a resolver in front of it,
// for IP rules to work on domain requests.
uOb = outbounds.NewSystemResolver(uOb)
}
// Otherwise we can just rely on outbound handling on its own.
case "tcp":
if c.Resolver.TCP.Addr == "" {
return configError{Field: "resolver.tcp.addr", Err: errors.New("empty resolver address")}
}
uOb = outbounds.NewStandardResolverTCP(c.Resolver.TCP.Addr, c.Resolver.TCP.Timeout, uOb)
case "udp":
if c.Resolver.UDP.Addr == "" {
return configError{Field: "resolver.udp.addr", Err: errors.New("empty resolver address")}
}
uOb = outbounds.NewStandardResolverUDP(c.Resolver.UDP.Addr, c.Resolver.UDP.Timeout, uOb)
case "tls", "tcp-tls":
if c.Resolver.TLS.Addr == "" {
return configError{Field: "resolver.tls.addr", Err: errors.New("empty resolver address")}
}
uOb = outbounds.NewStandardResolverTLS(c.Resolver.TLS.Addr, c.Resolver.TLS.Timeout, c.Resolver.TLS.SNI, c.Resolver.TLS.Insecure, uOb)
case "https", "http":
if c.Resolver.HTTPS.Addr == "" {
return configError{Field: "resolver.https.addr", Err: errors.New("empty resolver address")}
}
uOb = outbounds.NewDoHResolver(c.Resolver.HTTPS.Addr, c.Resolver.HTTPS.Timeout, c.Resolver.HTTPS.SNI, c.Resolver.HTTPS.Insecure, uOb)
default:
return configError{Field: "resolver.type", Err: errors.New("unsupported resolver type")}
}
// Speed test
if c.SpeedTest {
uOb = outbounds.NewSpeedtestHandler(uOb)
}
hyConfig.Outbound = &outbounds.PluggableOutboundAdapter{PluggableOutbound: uOb}
return nil
}
func (c *serverConfig) fillBandwidthConfig(hyConfig *server.Config) error {
var err error
if c.Bandwidth.Up != "" {
hyConfig.BandwidthConfig.MaxTx, err = utils.ConvBandwidth(c.Bandwidth.Up)
if err != nil {
return configError{Field: "bandwidth.up", Err: err}
}
}
if c.Bandwidth.Down != "" {
hyConfig.BandwidthConfig.MaxRx, err = utils.ConvBandwidth(c.Bandwidth.Down)
if err != nil {
return configError{Field: "bandwidth.down", Err: err}
}
}
return nil
}
func (c *serverConfig) fillIgnoreClientBandwidth(hyConfig *server.Config) error {
hyConfig.IgnoreClientBandwidth = c.IgnoreClientBandwidth
return nil
}
func (c *serverConfig) fillDisableUDP(hyConfig *server.Config) error {
hyConfig.DisableUDP = c.DisableUDP
return nil
}
func (c *serverConfig) fillUDPIdleTimeout(hyConfig *server.Config) error {
hyConfig.UDPIdleTimeout = c.UDPIdleTimeout
return nil
}
func (c *serverConfig) fillAuthenticator(hyConfig *server.Config) error {
if c.Auth.Type == "" {
return configError{Field: "auth.type", Err: errors.New("empty auth type")}
}
switch strings.ToLower(c.Auth.Type) {
case "password":
if c.Auth.Password == "" {
return configError{Field: "auth.password", Err: errors.New("empty auth password")}
}
hyConfig.Authenticator = &auth.PasswordAuthenticator{Password: c.Auth.Password}
return nil
case "userpass":
if len(c.Auth.UserPass) == 0 {
return configError{Field: "auth.userpass", Err: errors.New("empty auth userpass")}
}
hyConfig.Authenticator = &auth.UserPassAuthenticator{Users: c.Auth.UserPass}
return nil
case "http", "https":
if c.Auth.HTTP.URL == "" {
return configError{Field: "auth.http.url", Err: errors.New("empty auth http url")}
}
hyConfig.Authenticator = auth.NewHTTPAuthenticator(c.Auth.HTTP.URL, c.Auth.HTTP.Insecure)
return nil
case "command", "cmd":
if c.Auth.Command == "" {
return configError{Field: "auth.command", Err: errors.New("empty auth command")}
}
hyConfig.Authenticator = &auth.CommandAuthenticator{Cmd: c.Auth.Command}
return nil
case "v2board":
v2boardConfig := c.V2board
if v2boardConfig.ApiHost == "" || v2boardConfig.ApiKey == "" || v2boardConfig.NodeID == 0 {
return configError{Field: "auth.v2board", Err: errors.New("v2board config error")}
}
hyConfig.Authenticator = &auth.V2boardApiProvider{URL: fmt.Sprintf("%s?token=%s&node_id=%d&node_type=hysteria", c.V2board.ApiHost+"/api/v1/server/UniProxy/user", c.V2board.ApiKey, c.V2board.NodeID)}
return nil
default:
return configError{Field: "auth.type", Err: errors.New("unsupported auth type")}
}
}
func (c *serverConfig) fillEventLogger(hyConfig *server.Config) error {
hyConfig.EventLogger = &serverLogger{}
return nil
}
func (c *serverConfig) fillTrafficLogger(hyConfig *server.Config) error {
pullInterval := time.Second * 5
if c.V2board.PullInterval > 0 {
pullInterval = time.Duration(c.V2board.PullInterval) * time.Second
}
pushInterval := time.Second * 60
if c.V2board.PushInterval > 0 {
pushInterval = time.Duration(c.V2board.PushInterval) * time.Second
}
userURL := fmt.Sprintf("%s?token=%s&node_id=%d&node_type=hysteria", c.V2board.ApiHost+"/api/v1/server/UniProxy/user", c.V2board.ApiKey, c.V2board.NodeID)
pushURL := fmt.Sprintf("%s?token=%s&node_id=%d&node_type=hysteria", c.V2board.ApiHost+"/api/v1/server/UniProxy/push", c.V2board.ApiKey, c.V2board.NodeID)
if c.TrafficStats.Listen != "" {
tss := trafficlogger.NewTrafficStatsServer(c.TrafficStats.Secret)
hyConfig.TrafficLogger = tss
if c.V2board != nil && c.V2board.ApiHost != "" {
go auth.UpdateUsers(userURL, pullInterval, hyConfig.TrafficLogger)
go hyConfig.TrafficLogger.PushTrafficToV2boardInterval(pushURL, pushInterval)
}
go runTrafficStatsServer(c.TrafficStats.Listen, tss)
} else {
go auth.UpdateUsers(userURL, pullInterval, nil)
}
return nil
}
// fillMasqHandler must be called after fillConn, as we may need to extract the QUIC
// port number from Conn for MasqTCPServer.
func (c *serverConfig) fillMasqHandler(hyConfig *server.Config) error {
var handler http.Handler
switch strings.ToLower(c.Masquerade.Type) {
case "", "404":
handler = http.NotFoundHandler()
case "file":
if c.Masquerade.File.Dir == "" {
return configError{Field: "masquerade.file.dir", Err: errors.New("empty file directory")}
}
handler = http.FileServer(http.Dir(c.Masquerade.File.Dir))
case "proxy":
if c.Masquerade.Proxy.URL == "" {
return configError{Field: "masquerade.proxy.url", Err: errors.New("empty proxy url")}
}
u, err := url.Parse(c.Masquerade.Proxy.URL)
if err != nil {
return configError{Field: "masquerade.proxy.url", Err: err}
}
if u.Scheme != "http" && u.Scheme != "https" {
return configError{Field: "masquerade.proxy.url", Err: fmt.Errorf("unsupported protocol scheme \"%s\"", u.Scheme)}
}
handler = &httputil.ReverseProxy{
Rewrite: func(r *httputil.ProxyRequest) {
r.SetURL(u)
// SetURL rewrites the Host header,
// but we don't want that if rewriteHost is false
if !c.Masquerade.Proxy.RewriteHost {
r.Out.Host = r.In.Host
}
},
ErrorHandler: func(w http.ResponseWriter, r *http.Request, err error) {
logger.Error("HTTP reverse proxy error", zap.Error(err))
w.WriteHeader(http.StatusBadGateway)
},
}
case "string":
if c.Masquerade.String.Content == "" {
return configError{Field: "masquerade.string.content", Err: errors.New("empty string content")}
}
if c.Masquerade.String.StatusCode != 0 &&
(c.Masquerade.String.StatusCode < 200 ||
c.Masquerade.String.StatusCode > 599 ||
c.Masquerade.String.StatusCode == 233) {
// 233 is reserved for Hysteria authentication
return configError{Field: "masquerade.string.statusCode", Err: errors.New("invalid status code (must be 200-599, except 233)")}
}
handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
for k, v := range c.Masquerade.String.Headers {
w.Header().Set(k, v)
}
if c.Masquerade.String.StatusCode != 0 {
w.WriteHeader(c.Masquerade.String.StatusCode)
} else {
w.WriteHeader(http.StatusOK) // Use 200 OK by default
}
_, _ = w.Write([]byte(c.Masquerade.String.Content))
})
default:
return configError{Field: "masquerade.type", Err: errors.New("unsupported masquerade type")}
}
hyConfig.MasqHandler = &masqHandlerLogWrapper{H: handler, QUIC: true}
if c.Masquerade.ListenHTTP != "" || c.Masquerade.ListenHTTPS != "" {
if c.Masquerade.ListenHTTP != "" && c.Masquerade.ListenHTTPS == "" {
return configError{Field: "masquerade.listenHTTPS", Err: errors.New("having only HTTP server without HTTPS is not supported")}
}
s := masq.MasqTCPServer{
QUICPort: extractPortFromAddr(hyConfig.Conn.LocalAddr().String()),
HTTPSPort: extractPortFromAddr(c.Masquerade.ListenHTTPS),
Handler: &masqHandlerLogWrapper{H: handler, QUIC: false},
TLSConfig: &tls.Config{
Certificates: hyConfig.TLSConfig.Certificates,
GetCertificate: hyConfig.TLSConfig.GetCertificate,
},
ForceHTTPS: c.Masquerade.ForceHTTPS,
}
go runMasqTCPServer(&s, c.Masquerade.ListenHTTP, c.Masquerade.ListenHTTPS)
}
return nil
}
// Config validates the fields and returns a ready-to-use Hysteria server config
func (c *serverConfig) Config() (*server.Config, error) {
hyConfig := &server.Config{}
fillers := []func(*server.Config) error{
c.fillConn,
c.fillTLSConfig,
c.fillQUICConfig,
c.fillRequestHook,
c.fillOutboundConfig,
c.fillBandwidthConfig,
c.fillIgnoreClientBandwidth,
c.fillDisableUDP,
c.fillUDPIdleTimeout,
c.fillAuthenticator,
c.fillEventLogger,
c.fillTrafficLogger,
c.fillMasqHandler,
}
for _, f := range fillers {
if err := f(hyConfig); err != nil {
return nil, err
}
}
return hyConfig, nil
}
type ResponseNodeInfo struct {
Host string `json:"host"`
ServerPort uint `json:"server_port"`
ServerName string `json:"server_name"`
UpMbps uint `json:"down_mbps"`
DownMbps uint `json:"up_mbps"`
Obfs string `json:"obfs"`
BaseConfig struct {
PushInterval int `json:"push_interval"`
PullInterval int `json:"pull_interval"`
} `json:"base_config"`
}
func runServer(cmd *cobra.Command, args []string) {
logger.Info("server mode")
if err := viper.ReadInConfig(); err != nil {
logger.Fatal("failed to read server config", zap.Error(err))
}
var config serverConfig
if err := viper.Unmarshal(&config); err != nil {
logger.Fatal("failed to parse server config", zap.Error(err))
}
// 如果配置了v2board 则自动获取监听端口、obfs
if config.V2board != nil && config.V2board.ApiHost != "" {
// 创建一个url.Values来存储查询参数
queryParams := url.Values{
"token": {config.V2board.ApiKey},
"node_id": {strconv.Itoa(int(config.V2board.NodeID))},
"node_type": {"hysteria"},
}
nodeInfoUrl := config.V2board.ApiHost + "/api/v1/server/UniProxy/config?" + queryParams.Encode()
resp, err := http.Get(nodeInfoUrl)
if err != nil {
// 处理错误
fmt.Println("HTTP GET 请求出错:", err)
logger.Fatal("failed to client v2board api to get nodeInfo", zap.Error(err))
}
defer resp.Body.Close()
// 读取响应数据
body, err := io.ReadAll(resp.Body)
if err != nil {
logger.Fatal("failed to read v2board reaponse", zap.Error(err))
}
// 解析JSON数据
var responseNodeInfo ResponseNodeInfo
err = json.Unmarshal(body, &responseNodeInfo)
if err != nil {
logger.Fatal("failed to unmarshal v2board reaponse", zap.Error(err))
}
// 给 hy的端口、obfs、上行下行进行赋值
if responseNodeInfo.ServerPort != 0 {
config.Listen = ":" + strconv.Itoa(int(responseNodeInfo.ServerPort))
}
if responseNodeInfo.DownMbps != 0 {
config.Bandwidth.Down = strconv.Itoa(int(responseNodeInfo.DownMbps)) + "Mbps"
}
if responseNodeInfo.UpMbps != 0 {
config.Bandwidth.Up = strconv.Itoa(int(responseNodeInfo.UpMbps)) + "Mbps"
}
if responseNodeInfo.Obfs != "" {
config.Obfs.Type = "salamander"
config.Obfs.Salamander.Password = responseNodeInfo.Obfs
}
}
hyConfig, err := config.Config()
if err != nil {
logger.Fatal("failed to load server config", zap.Error(err))
}
s, err := server.NewServer(hyConfig)
if err != nil {
logger.Fatal("failed to initialize server", zap.Error(err))
}
if config.Listen != "" {
logger.Info("server up and running", zap.String("listen", config.Listen))
} else {
logger.Info("server up and running", zap.String("listen", defaultListenAddr))
}
if !disableUpdateCheck {
go runCheckUpdateServer()
}
if err := s.Serve(); err != nil {
logger.Fatal("failed to serve", zap.Error(err))
}
}
func runTrafficStatsServer(listen string, handler http.Handler) {
logger.Info("traffic stats server up and running", zap.String("listen", listen))
if err := correctnet.HTTPListenAndServe(listen, handler); err != nil {
logger.Fatal("failed to serve traffic stats", zap.Error(err))
}
}
func runMasqTCPServer(s *masq.MasqTCPServer, httpAddr, httpsAddr string) {
errChan := make(chan error, 2)
if httpAddr != "" {
go func() {
logger.Info("masquerade HTTP server up and running", zap.String("listen", httpAddr))
errChan <- s.ListenAndServeHTTP(httpAddr)
}()
}
if httpsAddr != "" {
go func() {
logger.Info("masquerade HTTPS server up and running", zap.String("listen", httpsAddr))
errChan <- s.ListenAndServeHTTPS(httpsAddr)
}()
}
err := <-errChan
if err != nil {
logger.Fatal("failed to serve masquerade HTTP(S)", zap.Error(err))
}
}
func geoDownloadFunc(filename, url string) {
logger.Info("downloading database", zap.String("filename", filename), zap.String("url", url))
}
func geoDownloadErrFunc(err error) {
if err != nil {
logger.Error("failed to download database", zap.Error(err))
}
}
type serverLogger struct{}
func (l *serverLogger) Connect(addr net.Addr, id string, tx uint64) {
logger.Info("client connected", zap.String("addr", addr.String()), zap.String("id", id), zap.Uint64("tx", tx))
}
func (l *serverLogger) Disconnect(addr net.Addr, id string, err error) {
logger.Info("client disconnected", zap.String("addr", addr.String()), zap.String("id", id), zap.Error(err))
}
func (l *serverLogger) TCPRequest(addr net.Addr, id, reqAddr string) {
logger.Debug("TCP request", zap.String("addr", addr.String()), zap.String("id", id), zap.String("reqAddr", reqAddr))
}
func (l *serverLogger) TCPError(addr net.Addr, id, reqAddr string, err error) {
if err == nil {
logger.Debug("TCP closed", zap.String("addr", addr.String()), zap.String("id", id), zap.String("reqAddr", reqAddr))
} else {
logger.Warn("TCP error", zap.String("addr", addr.String()), zap.String("id", id), zap.String("reqAddr", reqAddr), zap.Error(err))
}
}
func (l *serverLogger) UDPRequest(addr net.Addr, id string, sessionID uint32, reqAddr string) {
logger.Debug("UDP request", zap.String("addr", addr.String()), zap.String("id", id), zap.Uint32("sessionID", sessionID), zap.String("reqAddr", reqAddr))
}
func (l *serverLogger) UDPError(addr net.Addr, id string, sessionID uint32, err error) {
if err == nil {
logger.Debug("UDP closed", zap.String("addr", addr.String()), zap.String("id", id), zap.Uint32("sessionID", sessionID))
} else {
logger.Warn("UDP error", zap.String("addr", addr.String()), zap.String("id", id), zap.Uint32("sessionID", sessionID), zap.Error(err))
}
}
type masqHandlerLogWrapper struct {
H http.Handler
QUIC bool
}
func (m *masqHandlerLogWrapper) ServeHTTP(w http.ResponseWriter, r *http.Request) {
logger.Debug("masquerade request",
zap.String("addr", r.RemoteAddr),
zap.String("method", r.Method),
zap.String("host", r.Host),
zap.String("url", r.URL.String()),
zap.Bool("quic", m.QUIC))
m.H.ServeHTTP(w, r)
}
func extractPortFromAddr(addr string) int {
_, portStr, err := net.SplitHostPort(addr)
if err != nil {
return 0
}
port, err := strconv.Atoi(portStr)
if err != nil {
return 0
}
return port
}
================================================
FILE: app/cmd/server_test.go
================================================
package cmd
import (
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/spf13/viper"
)
// TestServerConfig tests the parsing of the server config
func TestServerConfig(t *testing.T) {
viper.SetConfigFile("server_test.yaml")
err := viper.ReadInConfig()
assert.NoError(t, err)
var config serverConfig
err = viper.Unmarshal(&config)
assert.NoError(t, err)
assert.Equal(t, config, serverConfig{
Listen: ":8443",
Obfs: serverConfigObfs{
Type: "salamander",
Salamander: serverConfigObfsSalamander{
Password: "cry_me_a_r1ver",
},
},
TLS: &serverConfigTLS{
Cert: "some.crt",
Key: "some.key",
SNIGuard: "strict",
},
ACME: &serverConfigACME{
Domains: []string{
"sub1.example.com",
"sub2.example.com",
},
Email: "haha@cringe.net",
CA: "zero",
ListenHost: "127.0.0.9",
Dir: "random_dir",
Type: "dns",
HTTP: serverConfigACMEHTTP{
AltPort: 8888,
},
TLS: serverConfigACMETLS{
AltPort: 44333,
},
DNS: serverConfigACMEDNS{
Name: "gomommy",
Config: map[string]string{
"key1": "value1",
"key2": "value2",
},
},
DisableHTTP: true,
DisableTLSALPN: true,
AltHTTPPort: 8080,
AltTLSALPNPort: 4433,
},
QUIC: serverConfigQUIC{
InitStreamReceiveWindow: 77881,
MaxStreamReceiveWindow: 77882,
InitConnectionReceiveWindow: 77883,
MaxConnectionReceiveWindow: 77884,
MaxIdleTimeout: 999 * time.Second,
MaxIncomingStreams: 256,
DisablePathMTUDiscovery: true,
},
Bandwidth: serverConfigBandwidth{
Up: "500 mbps",
Down: "100 mbps",
},
IgnoreClientBandwidth: true,
SpeedTest: true,
DisableUDP: true,
UDPIdleTimeout: 120 * time.Second,
Auth: serverConfigAuth{
Type: "password",
Password: "goofy_ahh_password",
UserPass: map[string]string{
"yolo": "swag",
"lol": "kek",
"foo": "bar",
},
HTTP: serverConfigAuthHTTP{
URL: "http://127.0.0.1:5000/auth",
Insecure: true,
},
Command: "/etc/some_command",
},
Resolver: serverConfigResolver{
Type: "udp",
TCP: serverConfigResolverTCP{
Addr: "123.123.123.123:5353",
Timeout: 4 * time.Second,
},
UDP: serverConfigResolverUDP{
Addr: "4.6.8.0:53",
Timeout: 2 * time.Second,
},
TLS: serverConfigResolverTLS{
Addr: "dot.yolo.com:8853",
Timeout: 10 * time.Second,
SNI: "server1.yolo.net",
Insecure: true,
},
HTTPS: serverConfigResolverHTTPS{
Addr: "cringe.ahh.cc",
Timeout: 5 * time.Second,
SNI: "real.stuff.net",
Insecure: true,
},
},
Sniff: serverConfigSniff{
Enable: true,
Timeout: 1 * time.Second,
RewriteDomain: true,
TCPPorts: "80,443,1000-2000",
UDPPorts: "443",
},
ACL: serverConfigACL{
File: "chnroute.txt",
Inline: []string{
"lmao(ok)",
"kek(cringe,boba,tea)",
},
GeoIP: "some.dat",
GeoSite: "some_site.dat",
GeoUpdateInterval: 168 * time.Hour,
},
Outbounds: []serverConfigOutboundEntry{
{
Name: "goodstuff",
Type: "direct",
Direct: serverConfigOutboundDirect{
Mode: "64",
BindIPv4: "2.4.6.8",
BindIPv6: "0:0:0:0:0:ffff:0204:0608",
BindDevice: "eth233",
},
},
{
Name: "badstuff",
Type: "socks5",
SOCKS5: serverConfigOutboundSOCKS5{
Addr: "shady.proxy.ru:1080",
Username: "hackerman",
Password: "Elliot Alderson",
},
},
{
Name: "weirdstuff",
Type: "http",
HTTP: serverConfigOutboundHTTP{
URL: "https://eyy.lmao:4443/goofy",
Insecure: true,
},
},
},
TrafficStats: serverConfigTrafficStats{
Listen: ":9999",
Secret: "its_me_mario",
},
Masquerade: serverConfigMasquerade{
Type: "proxy",
File: serverConfigMasqueradeFile{
Dir: "/www/masq",
},
Proxy: serverConfigMasqueradeProxy{
URL: "https://some.site.net",
RewriteHost: true,
},
String: serverConfigMasqueradeString{
Content: "aint nothin here",
Headers: map[string]string{
"content-type": "text/plain",
"custom-haha": "lol",
},
StatusCode: 418,
},
ListenHTTP: ":80",
ListenHTTPS: ":443",
ForceHTTPS: true,
},
})
}
================================================
FILE: app/cmd/server_test.yaml
================================================
listen: :8443
obfs:
type: salamander
salamander:
password: cry_me_a_r1ver
tls:
cert: some.crt
key: some.key
sniGuard: strict
acme:
domains:
- sub1.example.com
- sub2.example.com
email: haha@cringe.net
ca: zero
listenHost: 127.0.0.9
dir: random_dir
type: dns
http:
altPort: 8888
tls:
altPort: 44333
dns:
name: gomommy
config:
key1: value1
key2: value2
disableHTTP: true
disableTLSALPN: true
altHTTPPort: 8080
altTLSALPNPort: 4433
quic:
initStreamReceiveWindow: 77881
maxStreamReceiveWindow: 77882
initConnReceiveWindow: 77883
maxConnReceiveWindow: 77884
maxIdleTimeout: 999s
maxIncomingStreams: 256
disablePathMTUDiscovery: true
bandwidth:
up: 500 mbps
down: 100 mbps
ignoreClientBandwidth: true
speedTest: true
disableUDP: true
udpIdleTimeout: 120s
auth:
type: password
password: goofy_ahh_password
userpass:
yolo: swag
lol: kek
foo: bar
http:
url: http://127.0.0.1:5000/auth
insecure: true
command: /etc/some_command
resolver:
type: udp
tcp:
addr: 123.123.123.123:5353
timeout: 4s
udp:
addr: 4.6.8.0:53
timeout: 2s
tls:
addr: dot.yolo.com:8853
timeout: 10s
sni: server1.yolo.net
insecure: true
https:
addr: cringe.ahh.cc
timeout: 5s
sni: real.stuff.net
insecure: true
sniff:
enable: true
timeout: 1s
rewriteDomain: true
tcpPorts: 80,443,1000-2000
udpPorts: 443
acl:
file: chnroute.txt
inline:
- lmao(ok)
- kek(cringe,boba,tea)
geoip: some.dat
geosite: some_site.dat
geoUpdateInterval: 168h
outbounds:
- name: goodstuff
type: direct
direct:
mode: 64
bindIPv4: 2.4.6.8
bindIPv6: 0:0:0:0:0:ffff:0204:0608
bindDevice: eth233
- name: badstuff
type: socks5
socks5:
addr: shady.proxy.ru:1080
username: hackerman
password: Elliot Alderson
- name: weirdstuff
type: http
http:
url: https://eyy.lmao:4443/goofy
insecure: true
trafficStats:
listen: :9999
secret: its_me_mario
masquerade:
type: proxy
file:
dir: /www/masq
proxy:
url: https://some.site.net
rewriteHost: true
string:
content: aint nothin here
headers:
content-type: text/plain
custom-haha: lol
statusCode: 418
listenHTTP: :80
listenHTTPS: :443
forceHTTPS: true
================================================
FILE: app/cmd/share.go
================================================
package cmd
import (
"fmt"
"github.com/apernet/hysteria/app/v2/internal/utils"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"go.uber.org/zap"
)
var (
noText bool
withQR bool
)
// shareCmd represents the share command
var shareCmd = &cobra.Command{
Use: "share",
Short: "Generate share URI",
Long: "Generate a hysteria2:// URI from a client config for sharing",
Run: runShare,
}
func init() {
initShareFlags()
rootCmd.AddCommand(shareCmd)
}
func initShareFlags() {
shareCmd.Flags().BoolVar(&noText, "notext", false, "do not show URI as text")
shareCmd.Flags().BoolVar(&withQR, "qr", false, "show URI as QR code")
}
func runShare(cmd *cobra.Command, args []string) {
if err := viper.ReadInConfig(); err != nil {
logger.Fatal("failed to read client config", zap.Error(err))
}
var config clientConfig
if err := viper.Unmarshal(&config); err != nil {
logger.Fatal("failed to parse client config", zap.Error(err))
}
if _, err := config.Config(); err != nil {
logger.Fatal("failed to load client config", zap.Error(err))
}
u := config.URI()
if !noText {
fmt.Println(u)
}
if withQR {
utils.PrintQR(u)
}
}
================================================
FILE: app/cmd/speedtest.go
================================================
package cmd
import (
"errors"
"fmt"
"os"
"os/signal"
"syscall"
"time"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"go.uber.org/zap"
"github.com/apernet/hysteria/core/v2/client"
hyErrors "github.com/apernet/hysteria/core/v2/errors"
"github.com/apernet/hysteria/extras/v2/outbounds"
"github.com/apernet/hysteria/extras/v2/outbounds/speedtest"
)
var (
skipDownload bool
skipUpload bool
dataSize uint32
useBytes bool
speedtestAddr = fmt.Sprintf("%s:%d", outbounds.SpeedtestDest, 0)
)
// speedtestCmd represents the speedtest command
var speedtestCmd = &cobra.Command{
Use: "speedtest",
Short: "Speed test mode",
Long: "Perform a speed test through the proxy server. The server must have speed test support enabled.",
Run: runSpeedtest,
}
func init() {
initSpeedtestFlags()
rootCmd.AddCommand(speedtestCmd)
}
func initSpeedtestFlags() {
speedtestCmd.Flags().BoolVar(&skipDownload, "skip-download", false, "Skip download test")
speedtestCmd.Flags().BoolVar(&skipUpload, "skip-upload", false, "Skip upload test")
speedtestCmd.Flags().Uint32Var(&dataSize, "data-size", 1024*1024*100, "Data size for download and upload tests")
speedtestCmd.Flags().BoolVar(&useBytes, "use-bytes", false, "Use bytes per second instead of bits per second")
}
func runSpeedtest(cmd *cobra.Command, args []string) {
logger.Info("speed test mode")
if err := viper.ReadInConfig(); err != nil {
logger.Fatal("failed to read client config", zap.Error(err))
}
var config clientConfig
if err := viper.Unmarshal(&config); err != nil {
logger.Fatal("failed to parse client config", zap.Error(err))
}
hyConfig, err := config.Config()
if err != nil {
logger.Fatal("failed to load client config", zap.Error(err))
}
c, info, err := client.NewClient(hyConfig)
if err != nil {
logger.Fatal("failed to initialize client", zap.Error(err))
}
defer c.Close()
logger.Info("connected to server",
zap.Bool("udpEnabled", info.UDPEnabled),
zap.Uint64("tx", info.Tx))
signalChan := make(chan os.Signal, 1)
signal.Notify(signalChan, os.Interrupt, syscall.SIGTERM)
defer signal.Stop(signalChan)
runChan := make(chan struct{}, 1)
go func() {
if !skipDownload {
runDownloadTest(c)
}
if !skipUpload {
runUploadTest(c)
}
runChan <- struct{}{}
}()
select {
case <-signalChan:
logger.Info("received signal, shutting down gracefully")
case <-runChan:
logger.Info("speed test complete")
}
}
func runDownloadTest(c client.Client) {
logger.Info("performing download test")
downConn, err := c.TCP(speedtestAddr)
if err != nil {
if errors.As(err, &hyErrors.DialError{}) {
logger.Fatal("failed to connect (server may not support speed test)", zap.Error(err))
} else {
logger.Fatal("failed to connect", zap.Error(err))
}
}
defer downConn.Close()
downClient := &speedtest.Client{Conn: downConn}
currentTotal := uint32(0)
err = downClient.Download(dataSize, func(d time.Duration, b uint32, done bool) {
if !done {
currentTotal += b
logger.Info("downloading",
zap.Uint32("bytes", b),
zap.String("progress", fmt.Sprintf("%.2f%%", float64(currentTotal)/float64(dataSize)*100)),
zap.String("speed", formatSpeed(b, d, useBytes)))
} else {
logger.Info("download complete",
zap.Uint32("bytes", b),
zap.String("speed", formatSpeed(b, d, useBytes)))
}
})
if err != nil {
logger.Fatal("download test failed", zap.Error(err))
}
logger.Info("download test complete")
}
func runUploadTest(c client.Client) {
logger.Info("performing upload test")
upConn, err := c.TCP(speedtestAddr)
if err != nil {
if errors.As(err, &hyErrors.DialError{}) {
logger.Fatal("failed to connect (server may not support speed test)", zap.Error(err))
} else {
logger.Fatal("failed to connect", zap.Error(err))
}
}
defer upConn.Close()
upClient := &speedtest.Client{Conn: upConn}
currentTotal := uint32(0)
err = upClient.Upload(dataSize, func(d time.Duration, b uint32, done bool) {
if !done {
currentTotal += b
logger.Info("uploading",
zap.Uint32("bytes", b),
zap.String("progress", fmt.Sprintf("%.2f%%", float64(currentTotal)/float64(dataSize)*100)),
zap.String("speed", formatSpeed(b, d, useBytes)))
} else {
logger.Info("upload complete",
zap.Uint32("bytes", b),
zap.String("speed", formatSpeed(b, d, useBytes)))
}
})
if err != nil {
logger.Fatal("upload test failed", zap.Error(err))
}
logger.Info("upload test complete")
}
func formatSpeed(bytes uint32, duration time.Duration, useBytes bool) string {
speed := float64(bytes) / duration.Seconds()
var units []string
if useBytes {
units = []string{"B/s", "KB/s", "MB/s", "GB/s"}
} else {
units = []string{"bps", "Kbps", "Mbps", "Gbps"}
speed *= 8
}
unitIndex := 0
for speed > 1000 && unitIndex < len(units)-1 {
speed /= 1000
unitIndex++
}
return fmt.Sprintf("%.2f %s", speed, units[unitIndex])
}
================================================
FILE: app/cmd/update.go
================================================
package cmd
import (
"time"
"github.com/spf13/cobra"
"go.uber.org/zap"
"github.com/apernet/hysteria/app/v2/internal/utils"
"github.com/apernet/hysteria/core/v2/client"
)
const (
updateCheckInterval = 24 * time.Hour
)
// checkUpdateCmd represents the checkUpdate command
var checkUpdateCmd = &cobra.Command{
Use: "check-update",
Short: "Check for updates",
Long: "Check for updates.",
Run: runCheckUpdate,
}
func init() {
rootCmd.AddCommand(checkUpdateCmd)
}
func runCheckUpdate(cmd *cobra.Command, args []string) {
logger.Info("checking for updates",
zap.String("version", appVersion),
zap.String("platform", appPlatform),
zap.String("arch", appArch),
zap.String("channel", appType),
)
checker := utils.NewServerUpdateChecker(appVersion, appPlatform, appArch, appType)
resp, err := checker.Check()
if err != nil {
logger.Fatal("failed to check for updates", zap.Error(err))
}
if resp.HasUpdate {
logger.Info("update available",
zap.String("version", resp.LatestVersion),
zap.String("url", resp.URL),
zap.Bool("urgent", resp.Urgent),
)
} else {
logger.Info("no update available")
}
}
// runCheckUpdateServer is the background update checking routine for server mode
func runCheckUpdateServer() {
checker := utils.NewServerUpdateChecker(appVersion, appPlatform, appArch, appType)
checkUpdateRoutine(checker)
}
// runCheckUpdateClient is the background update checking routine for client mode
func runCheckUpdateClient(hyClient client.Client) {
checker := utils.NewClientUpdateChecker(appVersion, appPlatform, appArch, appType, hyClient)
checkUpdateRoutine(checker)
}
func checkUpdateRoutine(checker *utils.UpdateChecker) {
ticker := time.NewTicker(updateCheckInterval)
for {
logger.Debug("checking for updates",
zap.String("version", appVersion),
zap.String("platform", appPlatform),
zap.String("arch", appArch),
zap.String("channel", appType),
)
resp, err := checker.Check()
if err != nil {
logger.Debug("failed to check for updates", zap.Error(err))
} else if resp.HasUpdate {
logger.Info("update available",
zap.String("version", resp.LatestVersion),
zap.String("url", resp.URL),
zap.Bool("urgent", resp.Urgent),
)
} else {
logger.Debug("no update available")
}
<-ticker.C
}
}
================================================
FILE: app/cmd/version.go
================================================
package cmd
import (
"fmt"
"github.com/spf13/cobra"
)
// versionCmd represents the version command
var versionCmd = &cobra.Command{
Use: "version",
Short: "Show version",
Long: "Show version.",
Run: runVersion,
}
func init() {
rootCmd.AddCommand(versionCmd)
}
func runVersion(cmd *cobra.Command, args []string) {
fmt.Println(appAboutLong)
}
================================================
FILE: app/go.mod
================================================
module github.com/apernet/hysteria/app/v2
go 1.22
toolchain go1.23.2
require (
github.com/apernet/go-tproxy v0.0.0-20230809025308-8f4723fd742f
github.com/apernet/hysteria/core/v2 v2.0.0-00010101000000-000000000000
github.com/apernet/hysteria/extras/v2 v2.0.0-00010101000000-000000000000
github.com/apernet/sing-tun v0.2.6-0.20240323130332-b9f6511036ad
github.com/caddyserver/certmagic v0.17.2
github.com/libdns/cloudflare v0.1.1
github.com/libdns/duckdns v0.2.0
github.com/libdns/gandi v1.0.3
github.com/libdns/godaddy v1.0.3
github.com/libdns/namedotcom v0.3.3
github.com/libdns/vultr v1.0.0
github.com/mdp/qrterminal/v3 v3.1.1
github.com/mholt/acmez v1.0.4
github.com/sagernet/sing v0.3.2
github.com/spf13/cobra v1.7.0
github.com/spf13/viper v1.15.0
github.com/stretchr/testify v1.9.0
github.com/txthinking/socks5 v0.0.0-20230325130024-4230056ae301
go.uber.org/zap v1.24.0
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842
golang.org/x/sys v0.23.0
)
require (
github.com/andybalholm/brotli v1.1.0 // indirect
github.com/apernet/quic-go v0.47.1-0.20241004180137-a80d14e2080d // indirect
github.com/babolivier/go-doh-client v0.0.0-20201028162107-a76cff4cb8b6 // indirect
github.com/cloudflare/circl v1.3.9 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/go-ole/go-ole v1.3.0 // indirect
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
github.com/google/go-querystring v1.1.0 // indirect
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hashicorp/go-retryablehttp v0.7.6 // indirect
github.com/hashicorp/golang-lru/v2 v2.0.5 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/klauspost/compress v1.17.9 // indirect
github.com/klauspost/cpuid/v2 v2.1.1 // indirect
github.com/libdns/libdns v0.2.2 // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/miekg/dns v1.1.59 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/onsi/ginkgo/v2 v2.9.5 // indirect
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
github.com/pelletier/go-toml/v2 v2.0.6 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/quic-go/qpack v0.5.1 // indirect
github.com/refraction-networking/utls v1.6.6 // indirect
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 // indirect
github.com/scjalliance/comshim v0.0.0-20230315213746-5e51f40bd3b9 // indirect
github.com/spf13/afero v1.9.3 // indirect
github.com/spf13/cast v1.5.0 // indirect
github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/stretchr/objx v0.5.2 // indirect
github.com/subosito/gotenv v1.4.2 // indirect
github.com/txthinking/runnergroup v0.0.0-20210608031112-152c7c4432bf // indirect
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 // indirect
github.com/vultr/govultr/v3 v3.6.4 // indirect
go.uber.org/atomic v1.11.0 // indirect
go.uber.org/mock v0.4.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba // indirect
golang.org/x/crypto v0.26.0 // indirect
golang.org/x/mod v0.17.0 // indirect
golang.org/x/net v0.28.0 // indirect
golang.org/x/oauth2 v0.20.0 // indirect
golang.org/x/sync v0.8.0 // indirect
golang.org/x/text v0.17.0 // indirect
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect
google.golang.org/protobuf v1.34.1 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
rsc.io/qr v0.2.0 // indirect
)
replace github.com/apernet/hysteria/core/v2 => ../core
replace github.com/apernet/hysteria/extras/v2 => ../extras
================================================
FILE: app/go.sum
================================================
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
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.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY=
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.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
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.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
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/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.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
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.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M=
github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY=
github.com/apernet/go-tproxy v0.0.0-20230809025308-8f4723fd742f h1:uVh0qpEslrWjgzx9vOcyCqsOY3c9kofDZ1n+qaw35ZY=
github.com/apernet/go-tproxy v0.0.0-20230809025308-8f4723fd742f/go.mod h1:xkkq9D4ygcldQQhKS/w9CadiCKwCngU7K9E3DaKahpM=
github.com/apernet/quic-go v0.47.1-0.20241004180137-a80d14e2080d h1:KWRCWISqJOgY9/0hhH8Bevjw/k4tCQ7oJlXLyFv8u9s=
github.com/apernet/quic-go v0.47.1-0.20241004180137-a80d14e2080d/go.mod h1:x0paLlmCzNOUDDQIgmgFWmnpWQIEuH1GNfA6NdgSTuM=
github.com/apernet/sing-tun v0.2.6-0.20240323130332-b9f6511036ad h1:QzQ2sKpc9o42HNRR8ukM5uMC/RzR2HgZd/Nvaqol2C0=
github.com/apernet/sing-tun v0.2.6-0.20240323130332-b9f6511036ad/go.mod h1:S5IydyLSN/QAfvY+r2GoomPJ6hidtXWm/Ad18sJVssk=
github.com/babolivier/go-doh-client v0.0.0-20201028162107-a76cff4cb8b6 h1:4NNbNM2Iq/k57qEu7WfL67UrbPq1uFWxW4qODCohi+0=
github.com/babolivier/go-doh-client v0.0.0-20201028162107-a76cff4cb8b6/go.mod h1:J29hk+f9lJrblVIfiJOtTFk+OblBawmib4uz/VdKzlg=
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/caddyserver/certmagic v0.17.2 h1:o30seC1T/dBqBCNNGNHWwj2i5/I/FMjBbTAhjADP3nE=
github.com/caddyserver/certmagic v0.17.2/go.mod h1:ouWUuC490GOLJzkyN35eXfV8bSbwMwSf4bdhkIxtdQE=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
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/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cloudflare/circl v1.3.9 h1:QFrlgFYf2Qpi8bSpVPK1HBvWpx16v/1TZivyo7pGuBE=
github.com/cloudflare/circl v1.3.9/go.mod h1:PDRU+oXvdD7KCtgKxW95M5Z8BpSCJXQORiZFnBQS5QU=
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-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
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.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.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE=
github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps=
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
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-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
github.com/golang/mock v1.4.0/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.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
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.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
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/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.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
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.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
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-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
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-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE=
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
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/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k=
github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
github.com/hashicorp/go-retryablehttp v0.7.6 h1:TwRYfx2z2C4cLbXmT8I5PgP/xmuqASDyiVuGYfs9GZM=
github.com/hashicorp/go-retryablehttp v0.7.6/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru/v2 v2.0.5 h1:wW7h1TG88eUIJ2i69gaE3uNVtEPIagzhGvHgwfx2Vm4=
github.com/hashicorp/golang-lru/v2 v2.0.5/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
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/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
github.com/klauspost/cpuid/v2 v2.1.1 h1:t0wUqjowdm8ezddV5k0tLWVklVuvLJpoHeb4WBdydm0=
github.com/klauspost/cpuid/v2 v2.1.1/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/libdns/cloudflare v0.1.1 h1:FVPfWwP8zZCqj268LZjmkDleXlHPlFU9KC4OJ3yn054=
github.com/libdns/cloudflare v0.1.1/go.mod h1:9VK91idpOjg6v7/WbjkEW49bSCxj00ALesIFDhJ8PBU=
github.com/libdns/duckdns v0.2.0 h1:vd3pE09G2qTx1Zh1o3LmrivWSByD3Z5FbL7csX5vDgE=
github.com/libdns/duckdns v0.2.0/go.mod h1:jCQ/7+qvhLK39+28qXvKEYGBBvmHBCmIwNqdJTCUmVs=
github.com/libdns/gandi v1.0.3 h1:FIvipWOg/O4zi75fPRmtcolRKqI6MgrbpFy2p5KYdUk=
github.com/libdns/gandi v1.0.3/go.mod h1:G6dw58Xnji2xX+lb+uZxGbtmfxKllm1CGHE2bOPG3WA=
github.com/libdns/godaddy v1.0.3 h1:PX1FOYDQ1HGQzz8mVOmtwm3aa6Sv5MwCkNzivUUTA44=
github.com/libdns/godaddy v1.0.3/go.mod h1:vuKWUXnvblDvcaiRwutOoLl7DuB21x8tI06owsF/JTM=
github.com/libdns/libdns v0.2.0/go.mod h1:yQCXzk1lEZmmCPa857bnk4TsOiqYasqpyOEeSObbb40=
github.com/libdns/libdns v0.2.2 h1:O6ws7bAfRPaBsgAYt8MDe2HcNBGC29hkZ9MX2eUSX3s=
github.com/libdns/libdns v0.2.2/go.mod h1:4Bj9+5CQiNMVGf87wjX4CY3HQJypUHRuLvlsfsZqLWQ=
github.com/libdns/namedotcom v0.3.3 h1:R10C7+IqQGVeC4opHHMiFNBxdNBg1bi65ZwqLESl+jE=
github.com/libdns/namedotcom v0.3.3/go.mod h1:GbYzsAF2yRUpI0WgIK5fs5UX+kDVUPaYCFLpTnKQm0s=
github.com/libdns/vultr v1.0.0 h1:W8B4+k2bm9ro3bZLSZV9hMOQI+uO6Svu+GmD+Olz7ZI=
github.com/libdns/vultr v1.0.0/go.mod h1:8K1HJExcbeHS4YPkFHRZpqpXZzZ+DZAA0m0VikJgEqk=
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mdp/qrterminal/v3 v3.1.1 h1:cIPwg3QU0OIm9+ce/lRfWXhPwEjOSKwk3HBwL3HBTyc=
github.com/mdp/qrterminal/v3 v3.1.1/go.mod h1:5lJlXe7Jdr8wlPDdcsJttv1/knsRgzXASyr4dcGZqNU=
github.com/mholt/acmez v1.0.4 h1:N3cE4Pek+dSolbsofIkAYz6H1d3pE+2G0os7QHslf80=
github.com/mholt/acmez v1.0.4/go.mod h1:qFGLZ4u+ehWINeJZjzPlsnjJBCPAADWTcIqE/7DAYQY=
github.com/miekg/dns v1.1.40/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM=
github.com/miekg/dns v1.1.51/go.mod h1:2Z9d3CP1LQWihRZUf29mQ19yDThaI4DAYzte2CaQW5c=
github.com/miekg/dns v1.1.59 h1:C9EXc/UToRwKLhK5wKU/I4QVsBUc8kE6MkHBkeypWZs=
github.com/miekg/dns v1.1.59/go.mod h1:nZpewl5p6IvctfgrckopVx2OlSEHPRO/U4SYkRklrEk=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/onsi/ginkgo/v2 v2.9.5 h1:+6Hr4uxzP4XIUyAkg61dWBw8lb/gc4/X5luuxN/EC+Q=
github.com/onsi/ginkgo/v2 v2.9.5/go.mod h1:tvAoo1QUJwNEU2ITftXTpR7R1RbCzoZUOs3RonqW57k=
github.com/onsi/gomega v1.27.6 h1:ENqfyGeS5AX/rlXDd/ETokDz93u0YufY1Pgxuy/PvWE=
github.com/onsi/gomega v1.27.6/go.mod h1:PIQNjfQwkP3aQAH7lf7j87O/5FiNr+ZR8+ipb+qQlhg=
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
github.com/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU=
github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI=
github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg=
github.com/refraction-networking/utls v1.6.6 h1:igFsYBUJPYM8Rno9xUuDoM5GQrVEqY4llzEXOkL43Ig=
github.com/refraction-networking/utls v1.6.6/go.mod h1:BC3O4vQzye5hqpmDTWUqi4P5DDhzJfkV1tdqtawQIH0=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 h1:iL5gZI3uFp0X6EslacyapiRz7LLSJyr4RajF/BhMVyE=
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97/go.mod h1:xLnfdiJbSp8rNqYEdIW/6eDO4mVoogml14Bh2hSiFpM=
github.com/sagernet/sing v0.3.2 h1:CwWcxUBPkMvwgfe2/zUgY5oHG9qOL8Aob/evIFYK9jo=
github.com/sagernet/sing v0.3.2/go.mod h1:qHySJ7u8po9DABtMYEkNBcOumx7ZZJf/fbv2sfTkNHE=
github.com/scjalliance/comshim v0.0.0-20230315213746-5e51f40bd3b9 h1:rc/CcqLH3lh8n+csdOuDfP+NuykE0U6AeYSJJHKDgSg=
github.com/scjalliance/comshim v0.0.0-20230315213746-5e51f40bd3b9/go.mod h1:a/83NAfUXvEuLpmxDssAXxgUgrEy12MId3Wd7OTs76s=
github.com/spf13/afero v1.9.3 h1:41FoI0fD7OR7mGcKE/aOiLkGreyf8ifIOQmJANWogMk=
github.com/spf13/afero v1.9.3/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y=
github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w=
github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU=
github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I=
github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0=
github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
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/viper v1.15.0 h1:js3yy885G8xwJa6iOISGFwd+qlUo5AvyXb7CiihdtiU=
github.com/spf13/viper v1.15.0/go.mod h1:fFcTBJxvhhzSJiZy8n+PeW6t8l+KeT/uTARa0jHOQLA=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
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.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
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.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8=
github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0=
github.com/txthinking/runnergroup v0.0.0-20210608031112-152c7c4432bf h1:7PflaKRtU4np/epFxRXlFhlzLXZzKFrH5/I4so5Ove0=
github.com/txthinking/runnergroup v0.0.0-20210608031112-152c7c4432bf/go.mod h1:CLUSJbazqETbaR+i0YAhXBICV9TrKH93pziccMhmhpM=
github.com/txthinking/socks5 v0.0.0-20230325130024-4230056ae301 h1:d/Wr/Vl/wiJHc3AHYbYs5I3PucJvRuw3SvbmlIRf+oM=
github.com/txthinking/socks5 v0.0.0-20230325130024-4230056ae301/go.mod h1:ntmMHL/xPq1WLeKiw8p/eRATaae6PiVRNipHFJxI8PM=
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 h1:gga7acRE695APm9hlsSMoOoE65U4/TcqNj90mc69Rlg=
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
github.com/vultr/govultr/v3 v3.6.4 h1:unvY9eXlBw667ECQZDbBDOIaWB8wkk6Bx+yB0IMKXJ4=
github.com/vultr/govultr/v3 v3.6.4/go.mod h1:rt9v2x114jZmmLAE/h5N5jnxTmsK9ewwS2oQZ0UBQzM=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A=
go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4=
go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU=
go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw=
go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60=
go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg=
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBseWJUpBw5I82+2U4M=
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/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.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw=
golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54=
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-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20191227195350-da58074b4299/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-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 h1:vr/HnozRka3pE4EsMEg1lgkXJkTFJCVUX+S/ZT6wYzM=
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc=
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/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
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-20201208152925-83fdc39ff7b5/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-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.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
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.1/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/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
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-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/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-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20220630215102-69896b714898/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE=
golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/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-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.20.0 h1:4mQdhULixXKP1rwYBW0vAijoXnkTG0BLCDRzfe1idMo=
golang.org/x/oauth2 v0.20.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
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-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/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-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/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-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/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-20200523222454-059865788121/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-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/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-20210615035016-665e8c7367d1/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-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.23.0 h1:YfKFowiIMvtgl1UERQoTPPToxltDeZfbj4H7dVUCwmM=
golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
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.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
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.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc=
golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
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-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
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/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
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-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
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.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/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-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
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/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-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.1-
gitextract_5rjruq7m/
├── .github/
│ ├── FUNDING.yml
│ ├── ISSUE_TEMPLATE/
│ │ ├── bug_report.md
│ │ ├── bug_report.zh.md
│ │ ├── feature_request.md
│ │ └── feature_request.zh.md
│ ├── dependabot.yml
│ └── workflows/
│ ├── autotag.yaml
│ ├── docker.yml
│ ├── master.yml
│ ├── release.yml
│ └── scripts.yml
├── .gitignore
├── CHANGELOG.md
├── Dockerfile
├── LICENSE.md
├── PROTOCOL.md
├── README.md
├── app/
│ ├── cmd/
│ │ ├── client.go
│ │ ├── client_test.go
│ │ ├── client_test.yaml
│ │ ├── errors.go
│ │ ├── ping.go
│ │ ├── root.go
│ │ ├── server.go
│ │ ├── server_test.go
│ │ ├── server_test.yaml
│ │ ├── share.go
│ │ ├── speedtest.go
│ │ ├── update.go
│ │ └── version.go
│ ├── go.mod
│ ├── go.sum
│ ├── internal/
│ │ ├── forwarding/
│ │ │ ├── tcp.go
│ │ │ ├── tcp_test.go
│ │ │ ├── udp.go
│ │ │ └── udp_test.go
│ │ ├── http/
│ │ │ ├── server.go
│ │ │ ├── server_test.go
│ │ │ ├── server_test.py
│ │ │ ├── test.crt
│ │ │ └── test.key
│ │ ├── proxymux/
│ │ │ ├── .mockery.yaml
│ │ │ ├── internal/
│ │ │ │ └── mocks/
│ │ │ │ ├── mock_Conn.go
│ │ │ │ └── mock_Listener.go
│ │ │ ├── manager.go
│ │ │ ├── manager_test.go
│ │ │ ├── mux.go
│ │ │ └── mux_test.go
│ │ ├── redirect/
│ │ │ ├── getsockopt_linux.go
│ │ │ ├── getsockopt_linux_386.go
│ │ │ ├── syscall_socketcall_linux_386.s
│ │ │ ├── tcp_linux.go
│ │ │ └── tcp_others.go
│ │ ├── sockopts/
│ │ │ ├── fd_control_unix_socket_test.py
│ │ │ ├── sockopts.go
│ │ │ ├── sockopts_linux.go
│ │ │ └── sockopts_linux_test.go
│ │ ├── socks5/
│ │ │ ├── server.go
│ │ │ ├── server_test.go
│ │ │ └── server_test.py
│ │ ├── tproxy/
│ │ │ ├── tcp_linux.go
│ │ │ ├── tcp_others.go
│ │ │ ├── udp_linux.go
│ │ │ └── udp_others.go
│ │ ├── tun/
│ │ │ ├── log.go
│ │ │ └── server.go
│ │ ├── url/
│ │ │ ├── url.go
│ │ │ └── url_test.go
│ │ ├── utils/
│ │ │ ├── bpsconv.go
│ │ │ ├── bpsconv_test.go
│ │ │ ├── certloader.go
│ │ │ ├── certloader_test.go
│ │ │ ├── certloader_test_gencert.py
│ │ │ ├── certloader_test_tlsclient.py
│ │ │ ├── geoloader.go
│ │ │ ├── qr.go
│ │ │ ├── testcerts/
│ │ │ │ └── .gitignore
│ │ │ └── update.go
│ │ └── utils_test/
│ │ └── mock.go
│ ├── main.go
│ ├── misc/
│ │ └── socks5_test.py
│ └── pprof.go
├── core/
│ ├── client/
│ │ ├── .mockery.yaml
│ │ ├── client.go
│ │ ├── config.go
│ │ ├── mock_udpIO.go
│ │ ├── reconnect.go
│ │ ├── udp.go
│ │ └── udp_test.go
│ ├── errors/
│ │ └── errors.go
│ ├── go.mod
│ ├── go.sum
│ ├── internal/
│ │ ├── congestion/
│ │ │ ├── bbr/
│ │ │ │ ├── bandwidth.go
│ │ │ │ ├── bandwidth_sampler.go
│ │ │ │ ├── bbr_sender.go
│ │ │ │ ├── clock.go
│ │ │ │ ├── packet_number_indexed_queue.go
│ │ │ │ ├── ringbuffer.go
│ │ │ │ └── windowed_filter.go
│ │ │ ├── brutal/
│ │ │ │ └── brutal.go
│ │ │ ├── common/
│ │ │ │ └── pacer.go
│ │ │ └── utils.go
│ │ ├── frag/
│ │ │ ├── frag.go
│ │ │ └── frag_test.go
│ │ ├── integration_tests/
│ │ │ ├── .mockery.yaml
│ │ │ ├── close_test.go
│ │ │ ├── hook_test.go
│ │ │ ├── masq_test.go
│ │ │ ├── mocks/
│ │ │ │ ├── mock_Authenticator.go
│ │ │ │ ├── mock_Conn.go
│ │ │ │ ├── mock_EventLogger.go
│ │ │ │ ├── mock_Outbound.go
│ │ │ │ ├── mock_RequestHook.go
│ │ │ │ ├── mock_TrafficLogger.go
│ │ │ │ └── mock_UDPConn.go
│ │ │ ├── smoke_test.go
│ │ │ ├── stress_test.go
│ │ │ ├── test.crt
│ │ │ ├── test.key
│ │ │ ├── trafficlogger_test.go
│ │ │ └── utils_test.go
│ │ ├── pmtud/
│ │ │ ├── avail.go
│ │ │ └── unavail.go
│ │ ├── protocol/
│ │ │ ├── http.go
│ │ │ ├── padding.go
│ │ │ ├── proxy.go
│ │ │ └── proxy_test.go
│ │ └── utils/
│ │ ├── atomic.go
│ │ └── qstream.go
│ └── server/
│ ├── .mockery.yaml
│ ├── config.go
│ ├── copy.go
│ ├── mock_UDPConn.go
│ ├── mock_udpEventLogger.go
│ ├── mock_udpIO.go
│ ├── server.go
│ ├── udp.go
│ └── udp_test.go
├── entrypoint
├── extras/
│ ├── auth/
│ │ ├── command.go
│ │ ├── http.go
│ │ ├── http_test.go
│ │ ├── http_test.py
│ │ ├── password.go
│ │ ├── password_test.go
│ │ ├── userpass.go
│ │ ├── userpass_test.go
│ │ └── v2board.go
│ ├── correctnet/
│ │ └── correctnet.go
│ ├── go.mod
│ ├── go.sum
│ ├── masq/
│ │ └── server.go
│ ├── obfs/
│ │ ├── conn.go
│ │ ├── salamander.go
│ │ └── salamander_test.go
│ ├── outbounds/
│ │ ├── .mockery.yaml
│ │ ├── acl/
│ │ │ ├── compile.go
│ │ │ ├── compile_test.go
│ │ │ ├── matchers.go
│ │ │ ├── matchers_test.go
│ │ │ ├── matchers_v2geo.go
│ │ │ ├── matchers_v2geo_test.go
│ │ │ ├── parse.go
│ │ │ ├── parse_test.go
│ │ │ └── v2geo/
│ │ │ ├── load.go
│ │ │ ├── load_test.go
│ │ │ ├── v2geo.pb.go
│ │ │ └── v2geo.proto
│ │ ├── acl.go
│ │ ├── acl_test.go
│ │ ├── dns_https.go
│ │ ├── dns_standard.go
│ │ ├── dns_system.go
│ │ ├── interface.go
│ │ ├── interface_test.go
│ │ ├── mock_PluggableOutbound.go
│ │ ├── mock_UDPConn.go
│ │ ├── ob_direct.go
│ │ ├── ob_direct_linux.go
│ │ ├── ob_direct_others.go
│ │ ├── ob_http.go
│ │ ├── ob_socks5.go
│ │ ├── speedtest/
│ │ │ ├── client.go
│ │ │ ├── protocol.go
│ │ │ ├── protocol_test.go
│ │ │ └── server.go
│ │ ├── speedtest.go
│ │ ├── utils.go
│ │ └── utils_test.go
│ ├── sniff/
│ │ ├── .mockery.yaml
│ │ ├── internal/
│ │ │ └── quic/
│ │ │ ├── LICENSE
│ │ │ ├── README.md
│ │ │ ├── header.go
│ │ │ ├── packet_protector.go
│ │ │ ├── packet_protector_test.go
│ │ │ ├── payload.go
│ │ │ └── quic.go
│ │ ├── mock_Stream.go
│ │ ├── sniff.go
│ │ └── sniff_test.go
│ ├── trafficlogger/
│ │ └── http.go
│ ├── transport/
│ │ └── udphop/
│ │ ├── addr.go
│ │ └── conn.go
│ └── utils/
│ ├── portunion.go
│ └── portunion_test.go
├── go.work.sum
├── hyperbole.py
├── platforms.txt
├── requirements.txt
└── scripts/
├── _redirects
└── install_server.sh
SYMBOL INDEX (1877 symbols across 165 files)
FILE: app/cmd/client.go
function init (line 51) | func init() {
function initClientFlags (line 56) | func initClientFlags() {
type clientConfig (line 60) | type clientConfig struct
method fillServerAddr (line 182) | func (c *clientConfig) fillServerAddr(hyConfig *client.Config) error {
method fillConnFactory (line 208) | func (c *clientConfig) fillConnFactory(hyConfig *client.Config) error {
method fillAuth (line 262) | func (c *clientConfig) fillAuth(hyConfig *client.Config) error {
method fillTLSConfig (line 267) | func (c *clientConfig) fillTLSConfig(hyConfig *client.Config) error {
method fillQUICConfig (line 300) | func (c *clientConfig) fillQUICConfig(hyConfig *client.Config) error {
method fillBandwidthConfig (line 313) | func (c *clientConfig) fillBandwidthConfig(hyConfig *client.Config) er...
method fillFastOpen (line 331) | func (c *clientConfig) fillFastOpen(hyConfig *client.Config) error {
method URI (line 346) | func (c *clientConfig) URI() string {
method parseURI (line 387) | func (c *clientConfig) parseURI() bool {
method Config (line 424) | func (c *clientConfig) Config() (*client.Config, error) {
type clientConfigTransportUDP (line 80) | type clientConfigTransportUDP struct
type clientConfigTransport (line 84) | type clientConfigTransport struct
type clientConfigObfsSalamander (line 89) | type clientConfigObfsSalamander struct
type clientConfigObfs (line 93) | type clientConfigObfs struct
type clientConfigTLS (line 98) | type clientConfigTLS struct
type clientConfigQUIC (line 105) | type clientConfigQUIC struct
type clientConfigQUICSockopts (line 116) | type clientConfigQUICSockopts struct
type clientConfigBandwidth (line 122) | type clientConfigBandwidth struct
type socks5Config (line 127) | type socks5Config struct
type httpConfig (line 134) | type httpConfig struct
type tcpForwardingEntry (line 141) | type tcpForwardingEntry struct
type udpForwardingEntry (line 146) | type udpForwardingEntry struct
type tcpTProxyConfig (line 152) | type tcpTProxyConfig struct
type udpTProxyConfig (line 156) | type udpTProxyConfig struct
type tcpRedirectConfig (line 161) | type tcpRedirectConfig struct
type tunConfig (line 165) | type tunConfig struct
function runClient (line 444) | func runClient(cmd *cobra.Command, args []string) {
type clientModeRunner (line 547) | type clientModeRunner struct
method Add (line 557) | func (r *clientModeRunner) Add(name string, f func() error) {
method Run (line 564) | func (r *clientModeRunner) Run() clientModeRunnerResult {
type clientModeRunnerResult (line 551) | type clientModeRunnerResult struct
function clientSOCKS5 (line 593) | func clientSOCKS5(config socks5Config, c client.Client) error {
function clientHTTP (line 618) | func clientHTTP(config httpConfig, c client.Client) error {
function clientTCPForwarding (line 646) | func clientTCPForwarding(entries []tcpForwardingEntry, c client.Client) ...
function clientUDPForwarding (line 673) | func clientUDPForwarding(entries []udpForwardingEntry, c client.Client) ...
function clientTCPTProxy (line 701) | func clientTCPTProxy(config tcpTProxyConfig, c client.Client) error {
function clientUDPTProxy (line 717) | func clientUDPTProxy(config udpTProxyConfig, c client.Client) error {
function clientTCPRedirect (line 734) | func clientTCPRedirect(config tcpRedirectConfig, c client.Client) error {
function clientTUN (line 750) | func clientTUN(config tunConfig, c client.Client) error {
function parseServerAddrString (line 838) | func parseServerAddrString(addrStr string) (host, port, hostPort string) {
function isPortHoppingPort (line 848) | func isPortHoppingPort(port string) bool {
function normalizeCertHash (line 854) | func normalizeCertHash(hash string) string {
type adaptiveConnFactory (line 861) | type adaptiveConnFactory struct
method New (line 866) | func (f *adaptiveConnFactory) New(addr net.Addr) (net.PacketConn, erro...
function connectLog (line 878) | func connectLog(info *client.HandshakeInfo, count int) {
type socks5Logger (line 885) | type socks5Logger struct
method TCPRequest (line 887) | func (l *socks5Logger) TCPRequest(addr net.Addr, reqAddr string) {
method TCPError (line 891) | func (l *socks5Logger) TCPError(addr net.Addr, reqAddr string, err err...
method UDPRequest (line 899) | func (l *socks5Logger) UDPRequest(addr net.Addr) {
method UDPError (line 903) | func (l *socks5Logger) UDPError(addr net.Addr, err error) {
type httpLogger (line 911) | type httpLogger struct
method ConnectRequest (line 913) | func (l *httpLogger) ConnectRequest(addr net.Addr, reqAddr string) {
method ConnectError (line 917) | func (l *httpLogger) ConnectError(addr net.Addr, reqAddr string, err e...
method HTTPRequest (line 925) | func (l *httpLogger) HTTPRequest(addr net.Addr, reqURL string) {
method HTTPError (line 929) | func (l *httpLogger) HTTPError(addr net.Addr, reqURL string, err error) {
type tcpLogger (line 937) | type tcpLogger struct
method Connect (line 939) | func (l *tcpLogger) Connect(addr net.Addr) {
method Error (line 943) | func (l *tcpLogger) Error(addr net.Addr, err error) {
type udpLogger (line 951) | type udpLogger struct
method Connect (line 953) | func (l *udpLogger) Connect(addr net.Addr) {
method Error (line 957) | func (l *udpLogger) Error(addr net.Addr, err error) {
type tcpTProxyLogger (line 965) | type tcpTProxyLogger struct
method Connect (line 967) | func (l *tcpTProxyLogger) Connect(addr, reqAddr net.Addr) {
method Error (line 971) | func (l *tcpTProxyLogger) Error(addr, reqAddr net.Addr, err error) {
type udpTProxyLogger (line 979) | type udpTProxyLogger struct
method Connect (line 981) | func (l *udpTProxyLogger) Connect(addr, reqAddr net.Addr) {
method Error (line 985) | func (l *udpTProxyLogger) Error(addr, reqAddr net.Addr, err error) {
type tcpRedirectLogger (line 993) | type tcpRedirectLogger struct
method Connect (line 995) | func (l *tcpRedirectLogger) Connect(addr, reqAddr net.Addr) {
method Error (line 999) | func (l *tcpRedirectLogger) Error(addr, reqAddr net.Addr, err error) {
type tunLogger (line 1007) | type tunLogger struct
method TCPRequest (line 1009) | func (l *tunLogger) TCPRequest(addr, reqAddr string) {
method TCPError (line 1013) | func (l *tunLogger) TCPError(addr, reqAddr string, err error) {
method UDPRequest (line 1021) | func (l *tunLogger) UDPRequest(addr string) {
method UDPError (line 1025) | func (l *tunLogger) UDPError(addr string, err error) {
FILE: app/cmd/client_test.go
function TestClientConfig (line 13) | func TestClientConfig(t *testing.T) {
function TestClientConfigURI (line 122) | func TestClientConfigURI(t *testing.T) {
function stringRef (line 198) | func stringRef(s string) *string {
function uint32Ref (line 202) | func uint32Ref(i uint32) *uint32 {
FILE: app/cmd/errors.go
type configError (line 7) | type configError struct
method Error (line 12) | func (e configError) Error() string {
method Unwrap (line 16) | func (e configError) Unwrap() error {
FILE: app/cmd/ping.go
function init (line 21) | func init() {
function runPing (line 25) | func runPing(cmd *cobra.Command, args []string) {
FILE: app/cmd/root.go
constant appLogo (line 16) | appLogo = `
constant appDesc (line 21) | appDesc = "a powerful, lightning fast and censorship resistant proxy"
constant appAuthors (line 22) | appAuthors = "Aperture Internet Laboratory <https://github.com/apernet>"
constant appLogLevelEnv (line 24) | appLogLevelEnv = "HYSTERIA_LOG_LEVEL"
constant appLogFormatEnv (line 25) | appLogFormatEnv = "HYSTERIA_LOG_FORMAT"
constant appDisableUpdateCheckEnv (line 26) | appDisableUpdateCheckEnv = "HYSTERIA_DISABLE_UPDATE_CHECK"
constant appACMEDirEnv (line 27) | appACMEDirEnv = "HYSTERIA_ACME_DIR"
function Execute (line 97) | func Execute() {
function init (line 104) | func init() {
function initFlags (line 111) | func initFlags() {
function initConfig (line 118) | func initConfig() {
function initLogger (line 131) | func initLogger() {
function envOrDefaultString (line 159) | func envOrDefaultString(key, def string) string {
function envOrDefaultBool (line 166) | func envOrDefaultBool(key string, def bool) bool {
FILE: app/cmd/server.go
constant defaultListenAddr (line 44) | defaultListenAddr = ":443"
function init (line 53) | func init() {
type serverConfig (line 57) | type serverConfig struct
method fillConn (line 268) | func (c *serverConfig) fillConn(hyConfig *server.Config) error {
method fillTLSConfig (line 297) | func (c *serverConfig) fillTLSConfig(hyConfig *server.Config) error {
method fillQUICConfig (line 517) | func (c *serverConfig) fillQUICConfig(hyConfig *server.Config) error {
method fillRequestHook (line 581) | func (c *serverConfig) fillRequestHook(hyConfig *server.Config) error {
method fillOutboundConfig (line 604) | func (c *serverConfig) fillOutboundConfig(hyConfig *server.Config) err...
method fillBandwidthConfig (line 717) | func (c *serverConfig) fillBandwidthConfig(hyConfig *server.Config) er...
method fillIgnoreClientBandwidth (line 734) | func (c *serverConfig) fillIgnoreClientBandwidth(hyConfig *server.Conf...
method fillDisableUDP (line 739) | func (c *serverConfig) fillDisableUDP(hyConfig *server.Config) error {
method fillUDPIdleTimeout (line 744) | func (c *serverConfig) fillUDPIdleTimeout(hyConfig *server.Config) err...
method fillAuthenticator (line 749) | func (c *serverConfig) fillAuthenticator(hyConfig *server.Config) error {
method fillEventLogger (line 791) | func (c *serverConfig) fillEventLogger(hyConfig *server.Config) error {
method fillTrafficLogger (line 796) | func (c *serverConfig) fillTrafficLogger(hyConfig *server.Config) error {
method fillMasqHandler (line 824) | func (c *serverConfig) fillMasqHandler(hyConfig *server.Config) error {
method Config (line 906) | func (c *serverConfig) Config() (*server.Config, error) {
type v2boardConfig (line 78) | type v2boardConfig struct
type serverConfigObfsSalamander (line 86) | type serverConfigObfsSalamander struct
type serverConfigObfs (line 90) | type serverConfigObfs struct
type serverConfigTLS (line 95) | type serverConfigTLS struct
type serverConfigACME (line 101) | type serverConfigACME struct
type serverConfigACMEHTTP (line 123) | type serverConfigACMEHTTP struct
type serverConfigACMETLS (line 127) | type serverConfigACMETLS struct
type serverConfigACMEDNS (line 131) | type serverConfigACMEDNS struct
type serverConfigQUIC (line 136) | type serverConfigQUIC struct
type serverConfigBandwidth (line 146) | type serverConfigBandwidth struct
type serverConfigAuthHTTP (line 151) | type serverConfigAuthHTTP struct
type serverConfigAuth (line 156) | type serverConfigAuth struct
type serverConfigResolverTCP (line 164) | type serverConfigResolverTCP struct
type serverConfigResolverUDP (line 169) | type serverConfigResolverUDP struct
type serverConfigResolverTLS (line 174) | type serverConfigResolverTLS struct
type serverConfigResolverHTTPS (line 181) | type serverConfigResolverHTTPS struct
type serverConfigResolver (line 188) | type serverConfigResolver struct
type serverConfigSniff (line 196) | type serverConfigSniff struct
type serverConfigACL (line 204) | type serverConfigACL struct
type serverConfigOutboundDirect (line 212) | type serverConfigOutboundDirect struct
type serverConfigOutboundSOCKS5 (line 219) | type serverConfigOutboundSOCKS5 struct
type serverConfigOutboundHTTP (line 225) | type serverConfigOutboundHTTP struct
type serverConfigOutboundEntry (line 230) | type serverConfigOutboundEntry struct
type serverConfigTrafficStats (line 238) | type serverConfigTrafficStats struct
type serverConfigMasqueradeFile (line 243) | type serverConfigMasqueradeFile struct
type serverConfigMasqueradeProxy (line 247) | type serverConfigMasqueradeProxy struct
type serverConfigMasqueradeString (line 252) | type serverConfigMasqueradeString struct
type serverConfigMasquerade (line 258) | type serverConfigMasquerade struct
function genZeroSSLEAB (line 475) | func genZeroSSLEAB(email string) (*acme.EAB, error) {
function serverConfigOutboundDirectToOutbound (line 530) | func serverConfigOutboundDirectToOutbound(c serverConfigOutboundDirect) ...
function serverConfigOutboundSOCKS5ToOutbound (line 567) | func serverConfigOutboundSOCKS5ToOutbound(c serverConfigOutboundSOCKS5) ...
function serverConfigOutboundHTTPToOutbound (line 574) | func serverConfigOutboundHTTPToOutbound(c serverConfigOutboundHTTP) (out...
type ResponseNodeInfo (line 932) | type ResponseNodeInfo struct
function runServer (line 945) | func runServer(cmd *cobra.Command, args []string) {
function runTrafficStatsServer (line 1021) | func runTrafficStatsServer(listen string, handler http.Handler) {
function runMasqTCPServer (line 1028) | func runMasqTCPServer(s *masq.MasqTCPServer, httpAddr, httpsAddr string) {
function geoDownloadFunc (line 1048) | func geoDownloadFunc(filename, url string) {
function geoDownloadErrFunc (line 1052) | func geoDownloadErrFunc(err error) {
type serverLogger (line 1058) | type serverLogger struct
method Connect (line 1060) | func (l *serverLogger) Connect(addr net.Addr, id string, tx uint64) {
method Disconnect (line 1064) | func (l *serverLogger) Disconnect(addr net.Addr, id string, err error) {
method TCPRequest (line 1068) | func (l *serverLogger) TCPRequest(addr net.Addr, id, reqAddr string) {
method TCPError (line 1072) | func (l *serverLogger) TCPError(addr net.Addr, id, reqAddr string, err...
method UDPRequest (line 1080) | func (l *serverLogger) UDPRequest(addr net.Addr, id string, sessionID ...
method UDPError (line 1084) | func (l *serverLogger) UDPError(addr net.Addr, id string, sessionID ui...
type masqHandlerLogWrapper (line 1092) | type masqHandlerLogWrapper struct
method ServeHTTP (line 1097) | func (m *masqHandlerLogWrapper) ServeHTTP(w http.ResponseWriter, r *ht...
function extractPortFromAddr (line 1107) | func extractPortFromAddr(addr string) int {
FILE: app/cmd/server_test.go
function TestServerConfig (line 13) | func TestServerConfig(t *testing.T) {
FILE: app/cmd/share.go
function init (line 25) | func init() {
function initShareFlags (line 30) | func initShareFlags() {
function runShare (line 35) | func runShare(cmd *cobra.Command, args []string) {
FILE: app/cmd/speedtest.go
function init (line 38) | func init() {
function initSpeedtestFlags (line 43) | func initSpeedtestFlags() {
function runSpeedtest (line 50) | func runSpeedtest(cmd *cobra.Command, args []string) {
function runDownloadTest (line 97) | func runDownloadTest(c client.Client) {
function runUploadTest (line 130) | func runUploadTest(c client.Client) {
function formatSpeed (line 163) | func formatSpeed(bytes uint32, duration time.Duration, useBytes bool) st...
FILE: app/cmd/update.go
constant updateCheckInterval (line 14) | updateCheckInterval = 24 * time.Hour
function init (line 25) | func init() {
function runCheckUpdate (line 29) | func runCheckUpdate(cmd *cobra.Command, args []string) {
function runCheckUpdateServer (line 54) | func runCheckUpdateServer() {
function runCheckUpdateClient (line 60) | func runCheckUpdateClient(hyClient client.Client) {
function checkUpdateRoutine (line 65) | func checkUpdateRoutine(checker *utils.UpdateChecker) {
FILE: app/cmd/version.go
function init (line 17) | func init() {
function runVersion (line 21) | func runVersion(cmd *cobra.Command, args []string) {
FILE: app/internal/forwarding/tcp.go
type TCPTunnel (line 10) | type TCPTunnel struct
method Serve (line 21) | func (t *TCPTunnel) Serve(listener net.Listener) error {
method handle (line 31) | func (t *TCPTunnel) handle(conn net.Conn) {
type TCPEventLogger (line 16) | type TCPEventLogger interface
FILE: app/internal/forwarding/tcp_test.go
function TestTCPTunnel (line 13) | func TestTCPTunnel(t *testing.T) {
FILE: app/internal/forwarding/udp.go
constant udpBufferSize (line 13) | udpBufferSize = 4096
constant defaultTimeout (line 15) | defaultTimeout = 60 * time.Second
constant idleCleanupInterval (line 16) | idleCleanupInterval = 1 * time.Second
type atomicTime (line 19) | type atomicTime struct
method Set (line 29) | func (t *atomicTime) Set(new time.Time) {
method Get (line 33) | func (t *atomicTime) Get() time.Time {
function newAtomicTime (line 23) | func newAtomicTime(t time.Time) *atomicTime {
type sessionEntry (line 37) | type sessionEntry struct
method Feed (line 43) | func (e *sessionEntry) Feed(data []byte, addr string) error {
method ReceiveLoop (line 48) | func (e *sessionEntry) ReceiveLoop(pc net.PacketConn, addr net.Addr) e...
type UDPTunnel (line 62) | type UDPTunnel struct
method Serve (line 77) | func (t *UDPTunnel) Serve(pc net.PacketConn) error {
method idleCleanupLoop (line 95) | func (t *UDPTunnel) idleCleanupLoop(stopCh <-chan struct{}) {
method cleanup (line 108) | func (t *UDPTunnel) cleanup(idleOnly bool) {
method feed (line 129) | func (t *UDPTunnel) feed(pc net.PacketConn, addr net.Addr, data []byte) {
type UDPEventLogger (line 72) | type UDPEventLogger interface
FILE: app/internal/forwarding/udp_test.go
function TestUDPTunnel (line 13) | func TestUDPTunnel(t *testing.T) {
FILE: app/internal/http/server.go
constant httpClientTimeout (line 19) | httpClientTimeout = 10 * time.Second
type Server (line 23) | type Server struct
method Serve (line 39) | func (s *Server) Serve(listener net.Listener) error {
method dispatch (line 49) | func (s *Server) dispatch(conn net.Conn) {
method handleConnect (line 137) | func (s *Server) handleConnect(conn net.Conn, req *http.Request) {
method handleRequest (line 181) | func (s *Server) handleRequest(conn net.Conn, req *http.Request) bool {
method initHTTPClient (line 231) | func (s *Server) initHTTPClient() {
type EventLogger (line 32) | type EventLogger interface
type cachedConn (line 120) | type cachedConn struct
method Read (line 125) | func (c *cachedConn) Read(b []byte) (int, error) {
function removeHopByHopHeaders (line 246) | func removeHopByHopHeaders(header http.Header) {
function removeExtraHTTPHostPort (line 259) | func removeExtraHTTPHostPort(req *http.Request) {
function sendSimpleResponse (line 272) | func sendSimpleResponse(conn net.Conn, req *http.Request, statusCode int...
function sendProxyAuthRequired (line 290) | func sendProxyAuthRequired(conn net.Conn, req *http.Request, realm strin...
FILE: app/internal/http/server_test.go
constant testCertFile (line 17) | testCertFile = "test.crt"
constant testKeyFile (line 18) | testKeyFile = "test.key"
type mockHyClient (line 21) | type mockHyClient struct
method TCP (line 23) | func (c *mockHyClient) TCP(addr string) (net.Conn, error) {
method UDP (line 27) | func (c *mockHyClient) UDP() (client.HyUDPConn, error) {
method Close (line 31) | func (c *mockHyClient) Close() error {
function TestServer (line 35) | func TestServer(t *testing.T) {
FILE: app/internal/http/server_test.py
function test_http (line 9) | def test_http(it):
function test_https (line 15) | def test_https(it):
FILE: app/internal/proxymux/internal/mocks/mock_Conn.go
type MockConn (line 14) | type MockConn struct
method EXPECT (line 22) | func (_m *MockConn) EXPECT() *MockConn_Expecter {
method Close (line 27) | func (_m *MockConn) Close() error {
method LocalAddr (line 72) | func (_m *MockConn) LocalAddr() net.Addr {
method Read (line 119) | func (_m *MockConn) Read(b []byte) (int, error) {
method RemoteAddr (line 175) | func (_m *MockConn) RemoteAddr() net.Addr {
method SetDeadline (line 222) | func (_m *MockConn) SetDeadline(t time.Time) error {
method SetReadDeadline (line 268) | func (_m *MockConn) SetReadDeadline(t time.Time) error {
method SetWriteDeadline (line 314) | func (_m *MockConn) SetWriteDeadline(t time.Time) error {
method Write (line 360) | func (_m *MockConn) Write(b []byte) (int, error) {
type MockConn_Expecter (line 18) | type MockConn_Expecter struct
method Close (line 50) | func (_e *MockConn_Expecter) Close() *MockConn_Close_Call {
method LocalAddr (line 97) | func (_e *MockConn_Expecter) LocalAddr() *MockConn_LocalAddr_Call {
method Read (line 153) | func (_e *MockConn_Expecter) Read(b interface{}) *MockConn_Read_Call {
method RemoteAddr (line 200) | func (_e *MockConn_Expecter) RemoteAddr() *MockConn_RemoteAddr_Call {
method SetDeadline (line 246) | func (_e *MockConn_Expecter) SetDeadline(t interface{}) *MockConn_SetD...
method SetReadDeadline (line 292) | func (_e *MockConn_Expecter) SetReadDeadline(t interface{}) *MockConn_...
method SetWriteDeadline (line 338) | func (_e *MockConn_Expecter) SetWriteDeadline(t interface{}) *MockConn...
method Write (line 394) | func (_e *MockConn_Expecter) Write(b interface{}) *MockConn_Write_Call {
type MockConn_Close_Call (line 45) | type MockConn_Close_Call struct
method Run (line 54) | func (_c *MockConn_Close_Call) Run(run func()) *MockConn_Close_Call {
method Return (line 61) | func (_c *MockConn_Close_Call) Return(_a0 error) *MockConn_Close_Call {
method RunAndReturn (line 66) | func (_c *MockConn_Close_Call) RunAndReturn(run func() error) *MockCon...
type MockConn_LocalAddr_Call (line 92) | type MockConn_LocalAddr_Call struct
method Run (line 101) | func (_c *MockConn_LocalAddr_Call) Run(run func()) *MockConn_LocalAddr...
method Return (line 108) | func (_c *MockConn_LocalAddr_Call) Return(_a0 net.Addr) *MockConn_Loca...
method RunAndReturn (line 113) | func (_c *MockConn_LocalAddr_Call) RunAndReturn(run func() net.Addr) *...
type MockConn_Read_Call (line 147) | type MockConn_Read_Call struct
method Run (line 157) | func (_c *MockConn_Read_Call) Run(run func(b []byte)) *MockConn_Read_C...
method Return (line 164) | func (_c *MockConn_Read_Call) Return(n int, err error) *MockConn_Read_...
method RunAndReturn (line 169) | func (_c *MockConn_Read_Call) RunAndReturn(run func([]byte) (int, erro...
type MockConn_RemoteAddr_Call (line 195) | type MockConn_RemoteAddr_Call struct
method Run (line 204) | func (_c *MockConn_RemoteAddr_Call) Run(run func()) *MockConn_RemoteAd...
method Return (line 211) | func (_c *MockConn_RemoteAddr_Call) Return(_a0 net.Addr) *MockConn_Rem...
method RunAndReturn (line 216) | func (_c *MockConn_RemoteAddr_Call) RunAndReturn(run func() net.Addr) ...
type MockConn_SetDeadline_Call (line 240) | type MockConn_SetDeadline_Call struct
method Run (line 250) | func (_c *MockConn_SetDeadline_Call) Run(run func(t time.Time)) *MockC...
method Return (line 257) | func (_c *MockConn_SetDeadline_Call) Return(_a0 error) *MockConn_SetDe...
method RunAndReturn (line 262) | func (_c *MockConn_SetDeadline_Call) RunAndReturn(run func(time.Time) ...
type MockConn_SetReadDeadline_Call (line 286) | type MockConn_SetReadDeadline_Call struct
method Run (line 296) | func (_c *MockConn_SetReadDeadline_Call) Run(run func(t time.Time)) *M...
method Return (line 303) | func (_c *MockConn_SetReadDeadline_Call) Return(_a0 error) *MockConn_S...
method RunAndReturn (line 308) | func (_c *MockConn_SetReadDeadline_Call) RunAndReturn(run func(time.Ti...
type MockConn_SetWriteDeadline_Call (line 332) | type MockConn_SetWriteDeadline_Call struct
method Run (line 342) | func (_c *MockConn_SetWriteDeadline_Call) Run(run func(t time.Time)) *...
method Return (line 349) | func (_c *MockConn_SetWriteDeadline_Call) Return(_a0 error) *MockConn_...
method RunAndReturn (line 354) | func (_c *MockConn_SetWriteDeadline_Call) RunAndReturn(run func(time.T...
type MockConn_Write_Call (line 388) | type MockConn_Write_Call struct
method Run (line 398) | func (_c *MockConn_Write_Call) Run(run func(b []byte)) *MockConn_Write...
method Return (line 405) | func (_c *MockConn_Write_Call) Return(n int, err error) *MockConn_Writ...
method RunAndReturn (line 410) | func (_c *MockConn_Write_Call) RunAndReturn(run func([]byte) (int, err...
function NewMockConn (line 417) | func NewMockConn(t interface {
FILE: app/internal/proxymux/internal/mocks/mock_Listener.go
type MockListener (line 12) | type MockListener struct
method EXPECT (line 20) | func (_m *MockListener) EXPECT() *MockListener_Expecter {
method Accept (line 25) | func (_m *MockListener) Accept() (net.Conn, error) {
method Addr (line 82) | func (_m *MockListener) Addr() net.Addr {
method Close (line 129) | func (_m *MockListener) Close() error {
type MockListener_Expecter (line 16) | type MockListener_Expecter struct
method Accept (line 60) | func (_e *MockListener_Expecter) Accept() *MockListener_Accept_Call {
method Addr (line 107) | func (_e *MockListener_Expecter) Addr() *MockListener_Addr_Call {
method Close (line 152) | func (_e *MockListener_Expecter) Close() *MockListener_Close_Call {
type MockListener_Accept_Call (line 55) | type MockListener_Accept_Call struct
method Run (line 64) | func (_c *MockListener_Accept_Call) Run(run func()) *MockListener_Acce...
method Return (line 71) | func (_c *MockListener_Accept_Call) Return(_a0 net.Conn, _a1 error) *M...
method RunAndReturn (line 76) | func (_c *MockListener_Accept_Call) RunAndReturn(run func() (net.Conn,...
type MockListener_Addr_Call (line 102) | type MockListener_Addr_Call struct
method Run (line 111) | func (_c *MockListener_Addr_Call) Run(run func()) *MockListener_Addr_C...
method Return (line 118) | func (_c *MockListener_Addr_Call) Return(_a0 net.Addr) *MockListener_A...
method RunAndReturn (line 123) | func (_c *MockListener_Addr_Call) RunAndReturn(run func() net.Addr) *M...
type MockListener_Close_Call (line 147) | type MockListener_Close_Call struct
method Run (line 156) | func (_c *MockListener_Close_Call) Run(run func()) *MockListener_Close...
method Return (line 163) | func (_c *MockListener_Close_Call) Return(_a0 error) *MockListener_Clo...
method RunAndReturn (line 168) | func (_c *MockListener_Close_Call) RunAndReturn(run func() error) *Moc...
function NewMockListener (line 175) | func NewMockListener(t interface {
FILE: app/internal/proxymux/manager.go
type muxManager (line 10) | type muxManager struct
method GetOrCreate (line 23) | func (m *muxManager) GetOrCreate(address string) (*muxListener, error) {
method canonicalizeAddrPort (line 50) | func (m *muxManager) canonicalizeAddrPort(address string) (string, err...
function init (line 17) | func init() {
function ListenHTTP (line 58) | func ListenHTTP(address string) (net.Listener, error) {
function ListenSOCKS (line 66) | func ListenSOCKS(address string) (net.Listener, error) {
FILE: app/internal/proxymux/manager_test.go
function TestListenSOCKS (line 11) | func TestListenSOCKS(t *testing.T) {
function TestListenHTTP (line 40) | func TestListenHTTP(t *testing.T) {
function TestRelease (line 69) | func TestRelease(t *testing.T) {
method testAddressExists (line 104) | func (m *muxManager) testAddressExists(address string) bool {
FILE: app/internal/proxymux/mux.go
function newMuxListener (line 11) | func newMuxListener(listener net.Listener, deleteFunc func()) *muxListen...
type muxListener (line 23) | type muxListener struct
method acceptLoop (line 37) | func (l *muxListener) acceptLoop() {
method mainLoop (line 56) | func (l *muxListener) mainLoop() {
method dispatch (line 116) | func (l *muxListener) dispatch(conn net.Conn) {
method checkIdle (line 145) | func (l *muxListener) checkIdle() bool {
method getAndClearAcceptError (line 152) | func (l *muxListener) getAndClearAcceptError() error {
method ListenHTTP (line 164) | func (l *muxListener) ListenHTTP() (net.Listener, error) {
method ListenSOCKS (line 197) | func (l *muxListener) ListenSOCKS() (net.Listener, error) {
function newSubListener (line 230) | func newSubListener(acceptErrorFunc func() error, addrFunc func() net.Ad...
type subListener (line 239) | type subListener struct
method Accept (line 251) | func (l *subListener) Accept() (net.Conn, error) {
method Addr (line 268) | func (l *subListener) Addr() net.Addr {
method Close (line 274) | func (l *subListener) Close() error {
type connWithOneByte (line 286) | type connWithOneByte struct
method Read (line 293) | func (c *connWithOneByte) Read(bs []byte) (int, error) {
type OpErr (line 305) | type OpErr struct
method Error (line 312) | func (m OpErr) Error() string {
method Unwrap (line 316) | func (m OpErr) Unwrap() error {
FILE: app/internal/proxymux/mux_test.go
function testMockListener (line 18) | func testMockListener(t *testing.T, connChan <-chan net.Conn) net.Listen...
function testMockConn (line 43) | func testMockConn(t *testing.T, b []byte) net.Conn {
function TestMuxHTTP (line 60) | func TestMuxHTTP(t *testing.T) {
function TestMuxSOCKS (line 108) | func TestMuxSOCKS(t *testing.T) {
FILE: app/internal/redirect/getsockopt_linux.go
function getsockopt (line 11) | func getsockopt(s, level, name uintptr, val unsafe.Pointer, vallen *uint...
FILE: app/internal/redirect/getsockopt_linux_386.go
constant sysGetsockopt (line 9) | sysGetsockopt = 15
function syscall_socketcall (line 15) | func syscall_socketcall(call int, a0, a1, a2, a3, a4, a5 uintptr) (n int...
function getsockopt (line 17) | func getsockopt(s, level, name uintptr, val unsafe.Pointer, vallen *uint...
FILE: app/internal/redirect/tcp_linux.go
constant soOriginalDst (line 15) | soOriginalDst = 80
constant soOriginalDstV6 (line 16) | soOriginalDstV6 = 80
type TCPRedirect (line 19) | type TCPRedirect struct
method ListenAndServe (line 29) | func (r *TCPRedirect) ListenAndServe(laddr *net.TCPAddr) error {
method handle (line 44) | func (r *TCPRedirect) handle(conn *net.TCPConn) {
type TCPEventLogger (line 24) | type TCPEventLogger interface
type sockAddr (line 82) | type sockAddr struct
function getOriginalDst (line 88) | func getOriginalDst(fd uintptr) (*sockAddr, error) {
function getDstAddr (line 102) | func getDstAddr(conn *net.TCPConn) (*net.TCPAddr, error) {
FILE: app/internal/redirect/tcp_others.go
type TCPRedirect (line 12) | type TCPRedirect struct
method ListenAndServe (line 22) | func (r *TCPRedirect) ListenAndServe(laddr *net.TCPAddr) error {
type TCPEventLogger (line 17) | type TCPEventLogger interface
FILE: app/internal/sockopts/fd_control_unix_socket_test.py
function serve (line 8) | def serve(path):
function fd_to_socket (line 57) | def fd_to_socket(fd):
FILE: app/internal/sockopts/sockopts.go
type SocketOptions (line 8) | type SocketOptions struct
method CheckSupported (line 21) | func (o *SocketOptions) CheckSupported() (err error) {
method ListenUDP (line 42) | func (o *SocketOptions) ListenUDP() (uconn net.PacketConn, err error) {
method applyToUDPConn (line 56) | func (o *SocketOptions) applyToUDPConn(c *net.UDPConn) error {
type UnsupportedError (line 34) | type UnsupportedError struct
method Error (line 38) | func (e *UnsupportedError) Error() string {
FILE: app/internal/sockopts/sockopts_linux.go
constant fdControlUnixTimeout (line 15) | fdControlUnixTimeout = 3 * time.Second
function init (line 18) | func init() {
function controlUDPConn (line 24) | func controlUDPConn(c *net.UDPConn, cb func(fd int) error) (err error) {
function bindInterfaceImpl (line 42) | func bindInterfaceImpl(c *net.UDPConn, device string) error {
function firewallMarkImpl (line 48) | func firewallMarkImpl(c *net.UDPConn, fwmark uint32) error {
function fdControlUnixSocketImpl (line 54) | func fdControlUnixSocketImpl(c *net.UDPConn, path string) error {
function castAssignInteger (line 94) | func castAssignInteger[F, T constraints.Integer](from F, to *T) {
FILE: app/internal/sockopts/sockopts_linux_test.go
function Test_fdControlUnixSocketImpl (line 16) | func Test_fdControlUnixSocketImpl(t *testing.T) {
FILE: app/internal/socks5/server.go
constant udpBufferSize (line 13) | udpBufferSize = 4096
type Server (line 16) | type Server struct
method Serve (line 30) | func (s *Server) Serve(listener net.Listener) error {
method dispatch (line 40) | func (s *Server) dispatch(conn net.Conn) {
method negotiate (line 68) | func (s *Server) negotiate(conn net.Conn) (bool, error) {
method handleTCP (line 121) | func (s *Server) handleTCP(conn net.Conn, req *socks5.Request) {
method handleUDP (line 160) | func (s *Server) handleUDP(conn net.Conn, req *socks5.Request) {
method udpServer (line 223) | func (s *Server) udpServer(udpConn *net.UDPConn, hyUDP client.HyUDPCon...
type EventLogger (line 23) | type EventLogger interface
function sendSimpleReply (line 278) | func sendSimpleReply(conn net.Conn, rep byte) error {
function sendUDPReply (line 285) | func sendUDPReply(conn net.Conn, addr *net.UDPAddr) error {
FILE: app/internal/socks5/server_test.go
function TestServer (line 14) | func TestServer(t *testing.T) {
FILE: app/internal/socks5/server_test.py
function test_tcp (line 9) | def test_tcp(size, count, it, domain=False):
function test_udp (line 28) | def test_udp(size, count, it, domain=False):
FILE: app/internal/tproxy/tcp_linux.go
type TCPTProxy (line 11) | type TCPTProxy struct
method ListenAndServe (line 21) | func (r *TCPTProxy) ListenAndServe(laddr *net.TCPAddr) error {
method handle (line 36) | func (r *TCPTProxy) handle(conn net.Conn) {
type TCPEventLogger (line 16) | type TCPEventLogger interface
FILE: app/internal/tproxy/tcp_others.go
type TCPTProxy (line 12) | type TCPTProxy struct
method ListenAndServe (line 22) | func (r *TCPTProxy) ListenAndServe(laddr *net.TCPAddr) error {
type TCPEventLogger (line 17) | type TCPEventLogger interface
FILE: app/internal/tproxy/udp_linux.go
constant udpBufferSize (line 13) | udpBufferSize = 4096
constant defaultTimeout (line 14) | defaultTimeout = 60 * time.Second
type UDPTProxy (line 17) | type UDPTProxy struct
method ListenAndServe (line 28) | func (r *UDPTProxy) ListenAndServe(laddr *net.UDPAddr) error {
method newPair (line 47) | func (r *UDPTProxy) newPair(srcAddr, dstAddr *net.UDPAddr, initPkt []b...
method forwarding (line 94) | func (r *UDPTProxy) forwarding(conn *net.UDPConn, hyConn client.HyUDPC...
method updateConnDeadline (line 134) | func (r *UDPTProxy) updateConnDeadline(conn *net.UDPConn) error {
type UDPEventLogger (line 23) | type UDPEventLogger interface
FILE: app/internal/tproxy/udp_others.go
type UDPTProxy (line 13) | type UDPTProxy struct
method ListenAndServe (line 24) | func (r *UDPTProxy) ListenAndServe(laddr *net.UDPAddr) error {
type UDPEventLogger (line 19) | type UDPEventLogger interface
FILE: app/internal/tun/log.go
type singLogger (line 10) | type singLogger struct
method Trace (line 23) | func (l *singLogger) Trace(args ...any) {
method Debug (line 31) | func (l *singLogger) Debug(args ...any) {
method Info (line 39) | func (l *singLogger) Info(args ...any) {
method Warn (line 47) | func (l *singLogger) Warn(args ...any) {
method Error (line 55) | func (l *singLogger) Error(args ...any) {
method Fatal (line 63) | func (l *singLogger) Fatal(args ...any) {
method Panic (line 71) | func (l *singLogger) Panic(args ...any) {
function extractSingExceptions (line 15) | func extractSingExceptions(args []any) {
FILE: app/internal/tun/server.go
type Server (line 20) | type Server struct
method Serve (line 51) | func (s *Server) Serve() error {
type EventLogger (line 44) | type EventLogger interface
type tunHandler (line 95) | type tunHandler struct
method NewConnection (line 101) | func (t *tunHandler) NewConnection(ctx context.Context, conn net.Conn,...
method NewPacketConnection (line 139) | func (t *tunHandler) NewPacketConnection(ctx context.Context, conn net...
method NewError (line 208) | func (t *tunHandler) NewError(ctx context.Context, err error) {
type interfaceFinder (line 212) | type interfaceFinder struct
method InterfaceIndexByName (line 216) | func (f *interfaceFinder) InterfaceIndexByName(name string) (int, erro...
method InterfaceNameByIndex (line 224) | func (f *interfaceFinder) InterfaceNameByIndex(index int) (string, err...
FILE: app/internal/url/url.go
type Error (line 27) | type Error struct
method Unwrap (line 33) | func (e *Error) Unwrap() error { return e.Err }
method Error (line 34) | func (e *Error) Error() string { return fmt.Sprintf("%s %q: %s", e.Op,...
method Timeout (line 36) | func (e *Error) Timeout() bool {
method Temporary (line 43) | func (e *Error) Temporary() bool {
constant upperhex (line 50) | upperhex = "0123456789ABCDEF"
function ishex (line 52) | func ishex(c byte) bool {
function unhex (line 64) | func unhex(c byte) byte {
type encoding (line 76) | type encoding
constant encodePath (line 79) | encodePath encoding = 1 + iota
constant encodePathSegment (line 80) | encodePathSegment
constant encodeHost (line 81) | encodeHost
constant encodeZone (line 82) | encodeZone
constant encodeUserPassword (line 83) | encodeUserPassword
constant encodeQueryComponent (line 84) | encodeQueryComponent
constant encodeFragment (line 85) | encodeFragment
type EscapeError (line 88) | type EscapeError
method Error (line 90) | func (e EscapeError) Error() string {
type InvalidHostError (line 94) | type InvalidHostError
method Error (line 96) | func (e InvalidHostError) Error() string {
function shouldEscape (line 105) | func shouldEscape(c byte, mode encoding) bool {
function QueryUnescape (line 187) | func QueryUnescape(s string) (string, error) {
function PathUnescape (line 198) | func PathUnescape(s string) (string, error) {
function unescape (line 204) | func unescape(s string, mode encoding) (string, error) {
function QueryEscape (line 279) | func QueryEscape(s string) string {
function PathEscape (line 285) | func PathEscape(s string) string {
function escape (line 289) | func escape(s string, mode encoding) string {
type URL (line 366) | type URL struct
method setPath (line 677) | func (u *URL) setPath(p string) error {
method EscapedPath (line 701) | func (u *URL) EscapedPath() string {
method setFragment (line 741) | func (u *URL) setFragment(f string) error {
method EscapedFragment (line 764) | func (u *URL) EscapedFragment() string {
method String (line 813) | func (u *URL) String() string {
method Redacted (line 868) | func (u *URL) Redacted() string {
method IsAbs (line 1063) | func (u *URL) IsAbs() bool {
method Parse (line 1070) | func (u *URL) Parse(ref string) (*URL, error) {
method ResolveReference (line 1084) | func (u *URL) ResolveReference(ref *URL) *URL {
method Query (line 1119) | func (u *URL) Query() Values {
method RequestURI (line 1126) | func (u *URL) RequestURI() string {
method Hostname (line 1148) | func (u *URL) Hostname() string {
method Port (line 1156) | func (u *URL) Port() string {
method MarshalBinary (line 1182) | func (u *URL) MarshalBinary() (text []byte, err error) {
method UnmarshalBinary (line 1186) | func (u *URL) UnmarshalBinary(text []byte) error {
method JoinPath (line 1198) | func (u *URL) JoinPath(elem ...string) *URL {
function User (line 382) | func User(username string) *Userinfo {
function UserPassword (line 394) | func UserPassword(username, password string) *Userinfo {
type Userinfo (line 402) | type Userinfo struct
method Username (line 409) | func (u *Userinfo) Username() string {
method Password (line 417) | func (u *Userinfo) Password() (string, bool) {
method String (line 426) | func (u *Userinfo) String() string {
function getScheme (line 440) | func getScheme(rawURL string) (scheme, path string, err error) {
function Parse (line 470) | func Parse(rawURL string) (*URL, error) {
function ParseRequestURI (line 491) | func ParseRequestURI(rawURL string) (*URL, error) {
function parse (line 503) | func parse(rawURL string, viaRequest bool) (*URL, error) {
function parseAuthority (line 583) | func parseAuthority(authority string) (user *Userinfo, host string, err ...
function parseHost (line 620) | func parseHost(host string) (string, error) {
function validEncoded (line 717) | func validEncoded(s string, mode encoding) bool {
function validOptionalPort (line 776) | func validOptionalPort(port string) bool {
type Values (line 884) | type Values
method Get (line 890) | func (v Values) Get(key string) string {
method Set (line 900) | func (v Values) Set(key, value string) {
method Add (line 906) | func (v Values) Add(key, value string) {
method Del (line 911) | func (v Values) Del(key string) {
method Has (line 916) | func (v Values) Has(key string) bool {
method Encode (line 970) | func (v Values) Encode() string {
function ParseQuery (line 931) | func ParseQuery(query string) (Values, error) {
function parseQuery (line 937) | func parseQuery(m Values, query string) (err error) {
function resolvePath (line 997) | func resolvePath(base, ref string) string {
function splitHostPort (line 1164) | func splitHostPort(hostPort string) (host, port string) {
function validUserinfo (line 1228) | func validUserinfo(s string) bool {
function stringContainsCTLByte (line 1251) | func stringContainsCTLByte(s string) bool {
function JoinPath (line 1263) | func JoinPath(base string, elem ...string) (result string, err error) {
FILE: app/internal/url/url_test.go
function TestParse (line 8) | func TestParse(t *testing.T) {
FILE: app/internal/utils/bpsconv.go
constant Byte (line 11) | Byte = 1
constant Kilobyte (line 12) | Kilobyte = Byte * 1000
constant Megabyte (line 13) | Megabyte = Kilobyte * 1000
constant Gigabyte (line 14) | Gigabyte = Megabyte * 1000
constant Terabyte (line 15) | Terabyte = Gigabyte * 1000
function StringToBps (line 20) | func StringToBps(s string) (uint64, error) {
function ConvBandwidth (line 59) | func ConvBandwidth(bw interface{}) (uint64, error) {
FILE: app/internal/utils/bpsconv_test.go
function TestStringToBps (line 5) | func TestStringToBps(t *testing.T) {
FILE: app/internal/utils/certloader.go
type LocalCertificateLoader (line 15) | type LocalCertificateLoader struct
method InitializeCache (line 37) | func (l *LocalCertificateLoader) InitializeCache() error {
method GetCertificate (line 50) | func (l *LocalCertificateLoader) GetCertificate(info *tls.ClientHelloI...
method checkModTime (line 67) | func (l *LocalCertificateLoader) checkModTime() (certModTime, keyModTi...
method makeCache (line 84) | func (l *LocalCertificateLoader) makeCache() (cache *localCertificateC...
method getCertificateWithCache (line 109) | func (l *LocalCertificateLoader) getCertificateWithCache() (*tls.Certi...
type SNIGuardFunc (line 24) | type SNIGuardFunc
type localCertificateCache (line 31) | type localCertificateCache struct
function getNameFromClientHello (line 159) | func getNameFromClientHello(hello *tls.ClientHelloInfo) string {
function SNIGuardDNSSAN (line 184) | func SNIGuardDNSSAN(info *tls.ClientHelloInfo, cert *tls.Certificate) er...
function SNIGuardStrict (line 191) | func SNIGuardStrict(info *tls.ClientHelloInfo, cert *tls.Certificate) er...
FILE: app/internal/utils/certloader_test.go
constant testListen (line 16) | testListen = "127.82.39.147:12947"
constant testCAFile (line 17) | testCAFile = "./testcerts/ca"
constant testCertFile (line 18) | testCertFile = "./testcerts/cert"
constant testKeyFile (line 19) | testKeyFile = "./testcerts/key"
function TestCertificateLoaderPathError (line 22) | func TestCertificateLoaderPathError(t *testing.T) {
function TestCertificateLoaderFullChain (line 35) | func TestCertificateLoaderFullChain(t *testing.T) {
function TestCertificateLoaderNoSAN (line 57) | func TestCertificateLoaderNoSAN(t *testing.T) {
function TestCertificateLoaderReplaceCertificate (line 77) | func TestCertificateLoaderReplaceCertificate(t *testing.T) {
function generateTestCertificate (line 103) | func generateTestCertificate(dnssan []string, certType string) error {
function runTestTLSClient (line 123) | func runTestTLSClient(sni string) error {
FILE: app/internal/utils/certloader_test_gencert.py
function create_key (line 10) | def create_key():
function create_certificate (line 14) | def create_certificate(cert_type, subject, issuer, private_key, public_k...
function main (line 58) | def main():
FILE: app/internal/utils/certloader_test_tlsclient.py
function check_tls (line 7) | def check_tls(server, ca_cert, sni, alpn):
function main (line 36) | def main():
FILE: app/internal/utils/geoloader.go
constant geoipFilename (line 15) | geoipFilename = "geoip.dat"
constant geoipURL (line 16) | geoipURL = "https://cdn.jsdelivr.net/gh/Loyalsoldier/v2ray-rules-...
constant geositeFilename (line 17) | geositeFilename = "geosite.dat"
constant geositeURL (line 18) | geositeURL = "https://cdn.jsdelivr.net/gh/Loyalsoldier/v2ray-rules-...
constant geoDlTmpPattern (line 19) | geoDlTmpPattern = ".hysteria-geoloader.dlpart.*"
constant geoDefaultUpdateInterval (line 21) | geoDefaultUpdateInterval = 7 * 24 * time.Hour
type GeoLoader (line 29) | type GeoLoader struct
method shouldDownload (line 41) | func (l *GeoLoader) shouldDownload(filename string) bool {
method downloadAndCheck (line 58) | func (l *GeoLoader) downloadAndCheck(filename, url string, checkFunc f...
method LoadGeoIP (line 98) | func (l *GeoLoader) LoadGeoIP() (map[string]*v2geo.GeoIP, error) {
method LoadGeoSite (line 136) | func (l *GeoLoader) LoadGeoSite() (map[string]*v2geo.GeoSite, error) {
FILE: app/internal/utils/qr.go
function PrintQR (line 9) | func PrintQR(str string) {
FILE: app/internal/utils/update.go
constant updateCheckEndpoint (line 15) | updateCheckEndpoint = "https://api.hy2.io/v1/update"
constant updateCheckTimeout (line 16) | updateCheckTimeout = 10 * time.Second
type UpdateChecker (line 19) | type UpdateChecker struct
method Check (line 72) | func (uc *UpdateChecker) Check() (*UpdateResponse, error) {
function NewServerUpdateChecker (line 28) | func NewServerUpdateChecker(currentVersion, platform, architecture, chan...
function NewClientUpdateChecker (line 46) | func NewClientUpdateChecker(currentVersion, platform, architecture, chan...
type UpdateResponse (line 65) | type UpdateResponse struct
FILE: app/internal/utils_test/mock.go
type MockEchoHyClient (line 11) | type MockEchoHyClient struct
method TCP (line 13) | func (c *MockEchoHyClient) TCP(addr string) (net.Conn, error) {
method UDP (line 19) | func (c *MockEchoHyClient) UDP() (client.HyUDPConn, error) {
method Close (line 25) | func (c *MockEchoHyClient) Close() error {
type mockEchoTCPConn (line 29) | type mockEchoTCPConn struct
method Read (line 33) | func (c *mockEchoTCPConn) Read(b []byte) (n int, err error) {
method Write (line 42) | func (c *mockEchoTCPConn) Write(b []byte) (n int, err error) {
method Close (line 47) | func (c *mockEchoTCPConn) Close() error {
method LocalAddr (line 52) | func (c *mockEchoTCPConn) LocalAddr() net.Addr {
method RemoteAddr (line 57) | func (c *mockEchoTCPConn) RemoteAddr() net.Addr {
method SetDeadline (line 62) | func (c *mockEchoTCPConn) SetDeadline(t time.Time) error {
method SetReadDeadline (line 67) | func (c *mockEchoTCPConn) SetReadDeadline(t time.Time) error {
method SetWriteDeadline (line 72) | func (c *mockEchoTCPConn) SetWriteDeadline(t time.Time) error {
type mockEchoUDPPacket (line 77) | type mockEchoUDPPacket struct
type mockEchoUDPConn (line 82) | type mockEchoUDPConn struct
method Receive (line 86) | func (c *mockEchoUDPConn) Receive() ([]byte, string, error) {
method Send (line 95) | func (c *mockEchoUDPConn) Send(bytes []byte, s string) error {
method Close (line 103) | func (c *mockEchoUDPConn) Close() error {
FILE: app/main.go
function main (line 5) | func main() {
FILE: app/misc/socks5_test.py
function test_tcp (line 8) | def test_tcp() -> None:
function test_udp (line 29) | def test_udp() -> None:
FILE: app/pprof.go
constant pprofListenAddr (line 12) | pprofListenAddr = ":6060"
function init (line 15) | func init() {
FILE: core/client/client.go
constant closeErrCodeOK (line 21) | closeErrCodeOK = 0x100
constant closeErrCodeProtocolError (line 22) | closeErrCodeProtocolError = 0x101
type Client (line 25) | type Client interface
type HyUDPConn (line 31) | type HyUDPConn interface
type HandshakeInfo (line 37) | type HandshakeInfo struct
function NewClient (line 42) | func NewClient(config *Config) (Client, *HandshakeInfo, error) {
type clientImpl (line 56) | type clientImpl struct
method connect (line 65) | func (c *clientImpl) connect() (*HandshakeInfo, error) {
method openStream (line 163) | func (c *clientImpl) openStream() (quic.Stream, error) {
method TCP (line 171) | func (c *clientImpl) TCP(addr string) (net.Conn, error) {
method UDP (line 211) | func (c *clientImpl) UDP() (HyUDPConn, error) {
method Close (line 218) | func (c *clientImpl) Close() error {
function wrapIfConnectionClosed (line 229) | func wrapIfConnectionClosed(err error) error {
type tcpConn (line 238) | type tcpConn struct
method Read (line 245) | func (c *tcpConn) Read(b []byte) (n int, err error) {
method Write (line 260) | func (c *tcpConn) Write(b []byte) (n int, err error) {
method Close (line 264) | func (c *tcpConn) Close() error {
method LocalAddr (line 268) | func (c *tcpConn) LocalAddr() net.Addr {
method RemoteAddr (line 272) | func (c *tcpConn) RemoteAddr() net.Addr {
method SetDeadline (line 276) | func (c *tcpConn) SetDeadline(t time.Time) error {
method SetReadDeadline (line 280) | func (c *tcpConn) SetReadDeadline(t time.Time) error {
method SetWriteDeadline (line 284) | func (c *tcpConn) SetWriteDeadline(t time.Time) error {
type udpIOImpl (line 288) | type udpIOImpl struct
method ReceiveMessage (line 292) | func (io *udpIOImpl) ReceiveMessage() (*protocol.UDPMessage, error) {
method SendMessage (line 308) | func (io *udpIOImpl) SendMessage(buf []byte, msg *protocol.UDPMessage)...
FILE: core/client/config.go
constant defaultStreamReceiveWindow (line 13) | defaultStreamReceiveWindow = 8388608
constant defaultConnReceiveWindow (line 14) | defaultConnReceiveWindow = defaultStreamReceiveWindow * 5 / 2
constant defaultMaxIdleTimeout (line 15) | defaultMaxIdleTimeout = 30 * time.Second
constant defaultKeepAlivePeriod (line 16) | defaultKeepAlivePeriod = 10 * time.Second
type Config (line 19) | type Config struct
method verifyAndFill (line 33) | func (c *Config) verifyAndFill() error {
type ConnFactory (line 79) | type ConnFactory interface
type udpConnFactory (line 83) | type udpConnFactory struct
method New (line 85) | func (f *udpConnFactory) New(addr net.Addr) (net.PacketConn, error) {
type TLSConfig (line 90) | type TLSConfig struct
type QUICConfig (line 98) | type QUICConfig struct
type BandwidthConfig (line 109) | type BandwidthConfig struct
FILE: core/client/mock_udpIO.go
type mockUDPIO (line 11) | type mockUDPIO struct
method EXPECT (line 19) | func (_m *mockUDPIO) EXPECT() *mockUDPIO_Expecter {
method ReceiveMessage (line 24) | func (_m *mockUDPIO) ReceiveMessage() (*protocol.UDPMessage, error) {
method SendMessage (line 81) | func (_m *mockUDPIO) SendMessage(_a0 []byte, _a1 *protocol.UDPMessage)...
type mockUDPIO_Expecter (line 15) | type mockUDPIO_Expecter struct
method ReceiveMessage (line 59) | func (_e *mockUDPIO_Expecter) ReceiveMessage() *mockUDPIO_ReceiveMessa...
method SendMessage (line 106) | func (_e *mockUDPIO_Expecter) SendMessage(_a0 interface{}, _a1 interfa...
type mockUDPIO_ReceiveMessage_Call (line 54) | type mockUDPIO_ReceiveMessage_Call struct
method Run (line 63) | func (_c *mockUDPIO_ReceiveMessage_Call) Run(run func()) *mockUDPIO_Re...
method Return (line 70) | func (_c *mockUDPIO_ReceiveMessage_Call) Return(_a0 *protocol.UDPMessa...
method RunAndReturn (line 75) | func (_c *mockUDPIO_ReceiveMessage_Call) RunAndReturn(run func() (*pro...
type mockUDPIO_SendMessage_Call (line 99) | type mockUDPIO_SendMessage_Call struct
method Run (line 110) | func (_c *mockUDPIO_SendMessage_Call) Run(run func(_a0 []byte, _a1 *pr...
method Return (line 117) | func (_c *mockUDPIO_SendMessage_Call) Return(_a0 error) *mockUDPIO_Sen...
method RunAndReturn (line 122) | func (_c *mockUDPIO_SendMessage_Call) RunAndReturn(run func([]byte, *p...
function newMockUDPIO (line 129) | func newMockUDPIO(t interface {
FILE: core/client/reconnect.go
type reconnectableClientImpl (line 12) | type reconnectableClientImpl struct
method reconnect (line 38) | func (rc *reconnectableClientImpl) reconnect() error {
method clientDo (line 63) | func (rc *reconnectableClientImpl) clientDo(f func(Client) (interface{...
method TCP (line 92) | func (rc *reconnectableClientImpl) TCP(addr string) (net.Conn, error) {
method UDP (line 102) | func (rc *reconnectableClientImpl) UDP() (HyUDPConn, error) {
method Close (line 112) | func (rc *reconnectableClientImpl) Close() error {
function NewReconnectableClient (line 25) | func NewReconnectableClient(configFunc func() (*Config, error), connecte...
FILE: core/client/udp.go
constant udpMessageChanSize (line 17) | udpMessageChanSize = 1024
type udpIO (line 20) | type udpIO interface
type udpConn (line 25) | type udpConn struct
method Receive (line 35) | func (u *udpConn) Receive() ([]byte, string, error) {
method Send (line 52) | func (u *udpConn) Send(data []byte, addr string) error {
method Close (line 80) | func (u *udpConn) Close() error {
type udpSessionManager (line 85) | type udpSessionManager struct
method run (line 105) | func (m *udpSessionManager) run() error {
method closeCleanup (line 116) | func (m *udpSessionManager) closeCleanup() {
method feed (line 126) | func (m *udpSessionManager) feed(msg *protocol.UDPMessage) {
method NewUDP (line 145) | func (m *udpSessionManager) NewUDP() (HyUDPConn, error) {
method close (line 173) | func (m *udpSessionManager) close(conn *udpConn) {
method Count (line 181) | func (m *udpSessionManager) Count() int {
function newUDPSessionManager (line 95) | func newUDPSessionManager(io udpIO) *udpSessionManager {
FILE: core/client/udp_test.go
function TestUDPSessionManager (line 17) | func TestUDPSessionManager(t *testing.T) {
FILE: core/errors/errors.go
type ConfigError (line 9) | type ConfigError struct
method Error (line 14) | func (c ConfigError) Error() string {
type ConnectError (line 19) | type ConnectError struct
method Error (line 23) | func (c ConnectError) Error() string {
method Unwrap (line 27) | func (c ConnectError) Unwrap() error {
type AuthError (line 32) | type AuthError struct
method Error (line 36) | func (a AuthError) Error() string {
type DialError (line 42) | type DialError struct
method Error (line 46) | func (c DialError) Error() string {
type ClosedError (line 51) | type ClosedError struct
method Error (line 55) | func (c ClosedError) Error() string {
method Unwrap (line 63) | func (c ClosedError) Unwrap() error {
type ProtocolError (line 69) | type ProtocolError struct
method Error (line 73) | func (p ProtocolError) Error() string {
FILE: core/internal/congestion/bbr/bandwidth.go
constant infBandwidth (line 11) | infBandwidth = Bandwidth(math.MaxUint64)
type Bandwidth (line 15) | type Bandwidth
constant BitsPerSecond (line 19) | BitsPerSecond Bandwidth = 1
constant BytesPerSecond (line 21) | BytesPerSecond = 8 * BitsPerSecond
function BandwidthFromDelta (line 25) | func BandwidthFromDelta(bytes congestion.ByteCount, delta time.Duration)...
FILE: core/internal/congestion/bbr/bandwidth_sampler.go
constant infRTT (line 11) | infRTT = time.Duration(math.MaxInt64)
constant defaultConnectionStateMapQueueSize (line 12) | defaultConnectionStateMapQueueSize = 256
constant defaultCandidatesBufferSize (line 13) | defaultCandidatesBufferSize = 256
type roundTripCount (line 16) | type roundTripCount
type sendTimeState (line 20) | type sendTimeState struct
function newSendTimeState (line 41) | func newSendTimeState(
type extraAckedEvent (line 58) | type extraAckedEvent struct
function maxExtraAckedEventFunc (line 69) | func maxExtraAckedEventFunc(a, b extraAckedEvent) int {
type bandwidthSample (line 79) | type bandwidthSample struct
function newBandwidthSample (line 93) | func newBandwidthSample() *bandwidthSample {
type maxAckHeightTracker (line 101) | type maxAckHeightTracker struct
method Get (line 126) | func (m *maxAckHeightTracker) Get() congestion.ByteCount {
method Update (line 130) | func (m *maxAckHeightTracker) Update(
method SetFilterWindowLength (line 210) | func (m *maxAckHeightTracker) SetFilterWindowLength(length roundTripCo...
method Reset (line 214) | func (m *maxAckHeightTracker) Reset(newHeight congestion.ByteCount, ne...
method SetAckAggregationBandwidthThreshold (line 222) | func (m *maxAckHeightTracker) SetAckAggregationBandwidthThreshold(thre...
method SetStartNewAggregationEpochAfterFullRound (line 226) | func (m *maxAckHeightTracker) SetStartNewAggregationEpochAfterFullRoun...
method SetReduceExtraAckedOnBandwidthIncrease (line 230) | func (m *maxAckHeightTracker) SetReduceExtraAckedOnBandwidthIncrease(v...
method AckAggregationBandwidthThreshold (line 234) | func (m *maxAckHeightTracker) AckAggregationBandwidthThreshold() float...
method NumAckAggregationEpochs (line 238) | func (m *maxAckHeightTracker) NumAckAggregationEpochs() uint64 {
function newMaxAckHeightTracker (line 118) | func newMaxAckHeightTracker(windowLength roundTripCount) *maxAckHeightTr...
type ackPoint (line 243) | type ackPoint struct
type recentAckPoints (line 249) | type recentAckPoints struct
method Update (line 253) | func (r *recentAckPoints) Update(ackTime time.Time, totalBytesAcked co...
method Clear (line 264) | func (r *recentAckPoints) Clear() {
method MostRecentPoint (line 269) | func (r *recentAckPoints) MostRecentPoint() *ackPoint {
method LessRecentPoint (line 273) | func (r *recentAckPoints) LessRecentPoint() *ackPoint {
type connectionStateOnSentPacket (line 285) | type connectionStateOnSentPacket struct
function newConnectionStateOnSentPacket (line 307) | func newConnectionStateOnSentPacket(
type congestionEventSample (line 412) | type congestionEventSample struct
function newCongestionEventSample (line 434) | func newCongestionEventSample() *congestionEventSample {
type bandwidthSampler (line 440) | type bandwidthSampler struct
method MaxAckHeight (line 512) | func (b *bandwidthSampler) MaxAckHeight() congestion.ByteCount {
method NumAckAggregationEpochs (line 516) | func (b *bandwidthSampler) NumAckAggregationEpochs() uint64 {
method SetMaxAckHeightTrackerWindowLength (line 520) | func (b *bandwidthSampler) SetMaxAckHeightTrackerWindowLength(length r...
method ResetMaxAckHeightTracker (line 524) | func (b *bandwidthSampler) ResetMaxAckHeightTracker(newHeight congesti...
method SetStartNewAggregationEpochAfterFullRound (line 528) | func (b *bandwidthSampler) SetStartNewAggregationEpochAfterFullRound(v...
method SetLimitMaxAckHeightTrackerBySendRate (line 532) | func (b *bandwidthSampler) SetLimitMaxAckHeightTrackerBySendRate(value...
method SetReduceExtraAckedOnBandwidthIncrease (line 536) | func (b *bandwidthSampler) SetReduceExtraAckedOnBandwidthIncrease(valu...
method EnableOverestimateAvoidance (line 540) | func (b *bandwidthSampler) EnableOverestimateAvoidance() {
method IsOverestimateAvoidanceEnabled (line 549) | func (b *bandwidthSampler) IsOverestimateAvoidanceEnabled() bool {
method OnPacketSent (line 553) | func (b *bandwidthSampler) OnPacketSent(
method OnCongestionEvent (line 597) | func (b *bandwidthSampler) OnCongestionEvent(
method OnPacketLost (line 676) | func (b *bandwidthSampler) OnPacketLost(packetNumber congestion.Packet...
method OnPacketNeutered (line 684) | func (b *bandwidthSampler) OnPacketNeutered(packetNumber congestion.Pa...
method OnAppLimited (line 690) | func (b *bandwidthSampler) OnAppLimited() {
method RemoveObsoletePackets (line 695) | func (b *bandwidthSampler) RemoveObsoletePackets(leastUnacked congesti...
method TotalBytesSent (line 704) | func (b *bandwidthSampler) TotalBytesSent() congestion.ByteCount {
method TotalBytesLost (line 708) | func (b *bandwidthSampler) TotalBytesLost() congestion.ByteCount {
method TotalBytesAcked (line 712) | func (b *bandwidthSampler) TotalBytesAcked() congestion.ByteCount {
method TotalBytesNeutered (line 716) | func (b *bandwidthSampler) TotalBytesNeutered() congestion.ByteCount {
method IsAppLimited (line 720) | func (b *bandwidthSampler) IsAppLimited() bool {
method EndOfAppLimitedPhase (line 724) | func (b *bandwidthSampler) EndOfAppLimitedPhase() congestion.PacketNum...
method max_ack_height (line 728) | func (b *bandwidthSampler) max_ack_height() congestion.ByteCount {
method chooseA0Point (line 732) | func (b *bandwidthSampler) chooseA0Point(totalBytesAcked congestion.By...
method onPacketAcknowledged (line 761) | func (b *bandwidthSampler) onPacketAcknowledged(ackTime time.Time, pac...
method onAckEventEnd (line 833) | func (b *bandwidthSampler) onAckEventEnd(
function newBandwidthSampler (line 498) | func newBandwidthSampler(maxAckHeightTrackerWindowLength roundTripCount)...
function sentPacketToSendTimeState (line 860) | func sentPacketToSendTimeState(sentPacket *connectionStateOnSentPacket, ...
function bytesFromBandwidthAndTimeDelta (line 867) | func bytesFromBandwidthAndTimeDelta(bandwidth Bandwidth, delta time.Dura...
function timeDeltaFromBytesAndBandwidth (line 872) | func timeDeltaFromBytesAndBandwidth(bytes congestion.ByteCount, bandwidt...
FILE: core/internal/congestion/bbr/bbr_sender.go
constant minBps (line 26) | minBps = 65536
constant invalidPacketNumber (line 28) | invalidPacketNumber = -1
constant initialCongestionWindowPackets (line 29) | initialCongestionWindowPackets = 32
constant defaultMinimumCongestionWindow (line 34) | defaultMinimumCongestionWindow = 4 * congestion.ByteCount(congestion.Ini...
constant defaultHighGain (line 37) | defaultHighGain = 2.885
constant derivedHighGain (line 39) | derivedHighGain = 2.773
constant derivedHighCWNDGain (line 41) | derivedHighCWNDGain = 2.0
constant debugEnv (line 43) | debugEnv = "HYSTERIA_BBR_DEBUG"
constant gainCycleLength (line 51) | gainCycleLength = len(pacingGain)
constant bandwidthWindowSize (line 53) | bandwidthWindowSize = gainCycleLength + 2
constant minRttExpiry (line 56) | minRttExpiry = 10 * time.Second
constant probeRttTime (line 58) | probeRttTime = 200 * time.Millisecond
constant startupGrowthTarget (line 62) | startupGrowthTarget = 1.25
constant roundTripsWithoutGrowthBeforeExitingStartup (line 63) | roundTripsWithoutGrowthBeforeExitingStartup = int64(3)
constant defaultStartupFullLossCount (line 66) | defaultStartupFullLossCount = 8
constant quicBbr2DefaultLossThreshold (line 67) | quicBbr2DefaultLossThreshold = 0.02
constant maxBbrBurstPackets (line 68) | maxBbrBurstPackets = 10
type bbrMode (line 71) | type bbrMode
constant bbrModeStartup (line 75) | bbrModeStartup = iota
constant bbrModeDrain (line 78) | bbrModeDrain
constant bbrModeProbeBw (line 80) | bbrModeProbeBw
constant bbrModeProbeRtt (line 83) | bbrModeProbeRtt
type bbrRecoveryState (line 87) | type bbrRecoveryState
constant bbrRecoveryStateNotInRecovery (line 91) | bbrRecoveryStateNotInRecovery = iota
constant bbrRecoveryStateConservation (line 93) | bbrRecoveryStateConservation
constant bbrRecoveryStateGrowth (line 96) | bbrRecoveryStateGrowth
type bbrSender (line 99) | type bbrSender struct
method SetRTTStatsProvider (line 311) | func (b *bbrSender) SetRTTStatsProvider(provider congestion.RTTStatsPr...
method TimeUntilSend (line 316) | func (b *bbrSender) TimeUntilSend(bytesInFlight congestion.ByteCount) ...
method HasPacingBudget (line 321) | func (b *bbrSender) HasPacingBudget(now time.Time) bool {
method OnPacketSent (line 326) | func (b *bbrSender) OnPacketSent(
method CanSend (line 346) | func (b *bbrSender) CanSend(bytesInFlight congestion.ByteCount) bool {
method MaybeExitSlowStart (line 351) | func (b *bbrSender) MaybeExitSlowStart() {
method OnPacketAcked (line 356) | func (b *bbrSender) OnPacketAcked(number congestion.PacketNumber, acke...
method OnPacketLost (line 361) | func (b *bbrSender) OnPacketLost(number congestion.PacketNumber, lostB...
method OnRetransmissionTimeout (line 366) | func (b *bbrSender) OnRetransmissionTimeout(packetsRetransmitted bool) {
method SetMaxDatagramSize (line 371) | func (b *bbrSender) SetMaxDatagramSize(s congestion.ByteCount) {
method InSlowStart (line 384) | func (b *bbrSender) InSlowStart() bool {
method InRecovery (line 389) | func (b *bbrSender) InRecovery() bool {
method GetCongestionWindow (line 394) | func (b *bbrSender) GetCongestionWindow() congestion.ByteCount {
method OnCongestionEvent (line 406) | func (b *bbrSender) OnCongestionEvent(number congestion.PacketNumber, ...
method OnCongestionEventEx (line 410) | func (b *bbrSender) OnCongestionEventEx(priorInFlight congestion.ByteC...
method PacingRate (line 512) | func (b *bbrSender) PacingRate() Bandwidth {
method hasGoodBandwidthEstimateForResumption (line 521) | func (b *bbrSender) hasGoodBandwidthEstimateForResumption() bool {
method hasNonAppLimitedSample (line 525) | func (b *bbrSender) hasNonAppLimitedSample() bool {
method setHighGain (line 530) | func (b *bbrSender) setHighGain(highGain float64) {
method setHighCwndGain (line 538) | func (b *bbrSender) setHighCwndGain(highCwndGain float64) {
method setDrainGain (line 546) | func (b *bbrSender) setDrainGain(drainGain float64) {
method bandwidthEstimate (line 551) | func (b *bbrSender) bandwidthEstimate() Bandwidth {
method bandwidthForPacer (line 555) | func (b *bbrSender) bandwidthForPacer() congestion.ByteCount {
method getMinRtt (line 568) | func (b *bbrSender) getMinRtt() time.Duration {
method getTargetCongestionWindow (line 584) | func (b *bbrSender) getTargetCongestionWindow(gain float64) congestion...
method probeRttCongestionWindow (line 597) | func (b *bbrSender) probeRttCongestionWindow() congestion.ByteCount {
method maybeUpdateMinRtt (line 601) | func (b *bbrSender) maybeUpdateMinRtt(now time.Time, sampleMinRtt time...
method enterStartupMode (line 613) | func (b *bbrSender) enterStartupMode(now time.Time) {
method enterProbeBandwidthMode (line 625) | func (b *bbrSender) enterProbeBandwidthMode(now time.Time) {
method updateRoundTripCounter (line 648) | func (b *bbrSender) updateRoundTripCounter(lastAckedPacket congestion....
method updateGainCyclePhase (line 658) | func (b *bbrSender) updateGainCyclePhase(now time.Time, priorInFlight ...
method checkIfFullBandwidthReached (line 694) | func (b *bbrSender) checkIfFullBandwidthReached(lastPacketSendState *s...
method maybeAppLimited (line 717) | func (b *bbrSender) maybeAppLimited(bytesInFlight congestion.ByteCount) {
method maybeExitStartupOrDrain (line 725) | func (b *bbrSender) maybeExitStartupOrDrain(now time.Time) {
method maybeEnterOrExitProbeRtt (line 742) | func (b *bbrSender) maybeEnterOrExitProbeRtt(now time.Time, isRoundSta...
method updateRecoveryState (line 794) | func (b *bbrSender) updateRecoveryState(lastAckedPacket congestion.Pac...
method calculatePacingRate (line 830) | func (b *bbrSender) calculatePacingRate(bytesLost congestion.ByteCount) {
method calculateCongestionWindow (line 870) | func (b *bbrSender) calculateCongestionWindow(bytesAcked, excessAcked ...
method calculateRecoveryWindow (line 903) | func (b *bbrSender) calculateRecoveryWindow(bytesAcked, bytesLost cong...
method shouldExitStartupDueToLoss (line 935) | func (b *bbrSender) shouldExitStartupDueToLoss(lastPacketSendState *se...
method debugPrint (line 951) | func (b *bbrSender) debugPrint(format string, a ...any) {
function NewBbrSender (line 250) | func NewBbrSender(
function newBbrSender (line 262) | func newBbrSender(
function bdpFromRttAndBandwidth (line 957) | func bdpFromRttAndBandwidth(rtt time.Duration, bandwidth Bandwidth) cong...
function GetInitialPacketSize (line 961) | func GetInitialPacketSize(addr net.Addr) congestion.ByteCount {
function formatSpeed (line 975) | func formatSpeed(bw Bandwidth) string {
FILE: core/internal/congestion/bbr/clock.go
type Clock (line 6) | type Clock interface
type DefaultClock (line 11) | type DefaultClock struct
method Now (line 16) | func (DefaultClock) Now() time.Time {
FILE: core/internal/congestion/bbr/packet_number_indexed_queue.go
type entryWrapper (line 29) | type entryWrapper struct
type packetNumberIndexedQueue (line 34) | type packetNumberIndexedQueue struct
function newPacketNumberIndexedQueue (line 40) | func newPacketNumberIndexedQueue[T any](size int) *packetNumberIndexedQu...
method Emplace (line 54) | func (p *packetNumberIndexedQueue[T]) Emplace(packetNumber congestion.Pa...
method GetEntry (line 92) | func (p *packetNumberIndexedQueue[T]) GetEntry(packetNumber congestion.P...
method Remove (line 103) | func (p *packetNumberIndexedQueue[T]) Remove(packetNumber congestion.Pac...
method RemoveUpTo (line 124) | func (p *packetNumberIndexedQueue[T]) RemoveUpTo(packetNumber congestion...
method IsEmpty (line 140) | func (p *packetNumberIndexedQueue[T]) IsEmpty() bool {
method NumberOfPresentEntries (line 145) | func (p *packetNumberIndexedQueue[T]) NumberOfPresentEntries() int {
method EntrySlotsUsed (line 151) | func (p *packetNumberIndexedQueue[T]) EntrySlotsUsed() int {
method FirstPacket (line 156) | func (p *packetNumberIndexedQueue[T]) FirstPacket() (packetNumber conges...
method LastPacket (line 163) | func (p *packetNumberIndexedQueue[T]) LastPacket() (packetNumber congest...
method clearup (line 171) | func (p *packetNumberIndexedQueue[T]) clearup() {
method getEntryWraper (line 181) | func (p *packetNumberIndexedQueue[T]) getEntryWraper(packetNumber conges...
FILE: core/internal/congestion/bbr/ringbuffer.go
type RingBuffer (line 5) | type RingBuffer struct
method Init (line 12) | func (r *RingBuffer[T]) Init(size int) {
method Len (line 17) | func (r *RingBuffer[T]) Len() int {
method Empty (line 28) | func (r *RingBuffer[T]) Empty() bool {
method PushBack (line 34) | func (r *RingBuffer[T]) PushBack(t T) {
method PopFront (line 51) | func (r *RingBuffer[T]) PopFront() T {
method Offset (line 69) | func (r *RingBuffer[T]) Offset(index int) *T {
method Front (line 80) | func (r *RingBuffer[T]) Front() *T {
method Back (line 90) | func (r *RingBuffer[T]) Back() *T {
method grow (line 99) | func (r *RingBuffer[T]) grow() {
method Clear (line 112) | func (r *RingBuffer[T]) Clear() {
FILE: core/internal/congestion/bbr/windowed_filter.go
type WindowedFilterValue (line 33) | type WindowedFilterValue interface
type WindowedFilterTime (line 37) | type WindowedFilterTime interface
type WindowedFilter (line 41) | type WindowedFilter struct
type entry (line 48) | type entry struct
function MaxFilter (line 55) | func MaxFilter[O constraints.Ordered](a, b O) int {
function MinFilter (line 66) | func MinFilter[O constraints.Ordered](a, b O) int {
function NewWindowedFilter (line 75) | func NewWindowedFilter[V WindowedFilterValue, T WindowedFilterTime](wind...
method SetWindowLength (line 84) | func (f *WindowedFilter[V, T]) SetWindowLength(windowLength T) {
method GetBest (line 88) | func (f *WindowedFilter[V, T]) GetBest() V {
method GetSecondBest (line 92) | func (f *WindowedFilter[V, T]) GetSecondBest() V {
method GetThirdBest (line 96) | func (f *WindowedFilter[V, T]) GetThirdBest() V {
method Update (line 102) | func (f *WindowedFilter[V, T]) Update(newSample V, newTime T) {
method Reset (line 154) | func (f *WindowedFilter[V, T]) Reset(newSample V, newTime T) {
method Clear (line 160) | func (f *WindowedFilter[V, T]) Clear() {
FILE: core/internal/congestion/brutal/brutal.go
constant pktInfoSlotCount (line 15) | pktInfoSlotCount = 5
constant minSampleCount (line 16) | minSampleCount = 50
constant minAckRate (line 17) | minAckRate = 0.8
constant congestionWindowMultiplier (line 18) | congestionWindowMultiplier = 2
constant debugEnv (line 20) | debugEnv = "HYSTERIA_BRUTAL_DEBUG"
constant debugPrintInterval (line 21) | debugPrintInterval = 2
type BrutalSender (line 26) | type BrutalSender struct
method SetRTTStatsProvider (line 59) | func (b *BrutalSender) SetRTTStatsProvider(rttStats congestion.RTTStat...
method TimeUntilSend (line 63) | func (b *BrutalSender) TimeUntilSend(bytesInFlight congestion.ByteCoun...
method HasPacingBudget (line 67) | func (b *BrutalSender) HasPacingBudget(now time.Time) bool {
method CanSend (line 71) | func (b *BrutalSender) CanSend(bytesInFlight congestion.ByteCount) bool {
method GetCongestionWindow (line 75) | func (b *BrutalSender) GetCongestionWindow() congestion.ByteCount {
method OnPacketSent (line 87) | func (b *BrutalSender) OnPacketSent(sentTime time.Time, bytesInFlight ...
method OnPacketAcked (line 93) | func (b *BrutalSender) OnPacketAcked(number congestion.PacketNumber, a...
method OnCongestionEvent (line 99) | func (b *BrutalSender) OnCongestionEvent(number congestion.PacketNumbe...
method OnCongestionEventEx (line 105) | func (b *BrutalSender) OnCongestionEventEx(priorInFlight congestion.By...
method SetMaxDatagramSize (line 120) | func (b *BrutalSender) SetMaxDatagramSize(size congestion.ByteCount) {
method updateAckRate (line 128) | func (b *BrutalSender) updateAckRate(currentTimestamp int64) {
method InSlowStart (line 165) | func (b *BrutalSender) InSlowStart() bool {
method InRecovery (line 169) | func (b *BrutalSender) InRecovery() bool {
method MaybeExitSlowStart (line 173) | func (b *BrutalSender) MaybeExitSlowStart() {}
method OnRetransmissionTimeout (line 175) | func (b *BrutalSender) OnRetransmissionTimeout(packetsRetransmitted bo...
method canPrintAckRate (line 177) | func (b *BrutalSender) canPrintAckRate(currentTimestamp int64) bool {
method debugPrint (line 181) | func (b *BrutalSender) debugPrint(format string, a ...any) {
type pktInfo (line 39) | type pktInfo struct
function NewBrutalSender (line 45) | func NewBrutalSender(bps uint64) *BrutalSender {
FILE: core/internal/congestion/common/pacer.go
constant maxBurstPackets (line 10) | maxBurstPackets = 10
constant maxBurstPacingDelayMultiplier (line 11) | maxBurstPacingDelayMultiplier = 4
type Pacer (line 15) | type Pacer struct
method SentPacket (line 31) | func (p *Pacer) SentPacket(sendTime time.Time, size congestion.ByteCou...
method Budget (line 41) | func (p *Pacer) Budget(now time.Time) congestion.ByteCount {
method maxBurstSize (line 52) | func (p *Pacer) maxBurstSize() congestion.ByteCount {
method TimeUntilSend (line 61) | func (p *Pacer) TimeUntilSend() time.Time {
method SetMaxDatagramSize (line 77) | func (p *Pacer) SetMaxDatagramSize(s congestion.ByteCount) {
function NewPacer (line 22) | func NewPacer(getBandwidth func() congestion.ByteCount) *Pacer {
FILE: core/internal/congestion/utils.go
function UseBBR (line 9) | func UseBBR(conn quic.Connection) {
function UseBrutal (line 16) | func UseBrutal(conn quic.Connection, tx uint64) {
FILE: core/internal/frag/frag.go
function FragUDPMessage (line 7) | func FragUDPMessage(m *protocol.UDPMessage, maxSize int) []protocol.UDPM...
type Defragger (line 37) | type Defragger struct
method Feed (line 44) | func (d *Defragger) Feed(m *protocol.UDPMessage) *protocol.UDPMessage {
FILE: core/internal/frag/frag_test.go
function TestFragUDPMessage (line 10) | func TestFragUDPMessage(t *testing.T) {
function TestDefragger (line 134) | func TestDefragger(t *testing.T) {
FILE: core/internal/integration_tests/close_test.go
function TestClientServerTCPClose (line 20) | func TestClientServerTCPClose(t *testing.T) {
function TestClientServerUDPIdleTimeout (line 98) | func TestClientServerUDPIdleTimeout(t *testing.T) {
function TestClientServerClientShutdown (line 181) | func TestClientServerClientShutdown(t *testing.T) {
function TestClientServerServerShutdown (line 214) | func TestClientServerServerShutdown(t *testing.T) {
FILE: core/internal/integration_tests/hook_test.go
function TestClientServerHookTCP (line 16) | func TestClientServerHookTCP(t *testing.T) {
function TestClientServerHookUDP (line 80) | func TestClientServerHookUDP(t *testing.T) {
FILE: core/internal/integration_tests/masq_test.go
function TestServerMasquerade (line 26) | func TestServerMasquerade(t *testing.T) {
FILE: core/internal/integration_tests/mocks/mock_Authenticator.go
type MockAuthenticator (line 12) | type MockAuthenticator struct
method EXPECT (line 20) | func (_m *MockAuthenticator) EXPECT() *MockAuthenticator_Expecter {
method Authenticate (line 25) | func (_m *MockAuthenticator) Authenticate(addr net.Addr, auth string, ...
type MockAuthenticator_Expecter (line 16) | type MockAuthenticator_Expecter struct
method Authenticate (line 61) | func (_e *MockAuthenticator_Expecter) Authenticate(addr interface{}, a...
type MockAuthenticator_Authenticate_Call (line 53) | type MockAuthenticator_Authenticate_Call struct
method Run (line 65) | func (_c *MockAuthenticator_Authenticate_Call) Run(run func(addr net.A...
method Return (line 72) | func (_c *MockAuthenticator_Authenticate_Call) Return(ok bool, id stri...
method RunAndReturn (line 77) | func (_c *MockAuthenticator_Authenticate_Call) RunAndReturn(run func(n...
function NewMockAuthenticator (line 84) | func NewMockAuthenticator(t interface {
FILE: core/internal/integration_tests/mocks/mock_Conn.go
type MockConn (line 14) | type MockConn struct
method EXPECT (line 22) | func (_m *MockConn) EXPECT() *MockConn_Expecter {
method Close (line 27) | func (_m *MockConn) Close() error {
method LocalAddr (line 72) | func (_m *MockConn) LocalAddr() net.Addr {
method Read (line 119) | func (_m *MockConn) Read(b []byte) (int, error) {
method RemoteAddr (line 175) | func (_m *MockConn) RemoteAddr() net.Addr {
method SetDeadline (line 222) | func (_m *MockConn) SetDeadline(t time.Time) error {
method SetReadDeadline (line 268) | func (_m *MockConn) SetReadDeadline(t time.Time) error {
method SetWriteDeadline (line 314) | func (_m *MockConn) SetWriteDeadline(t time.Time) error {
method Write (line 360) | func (_m *MockConn) Write(b []byte) (int, error) {
type MockConn_Expecter (line 18) | type MockConn_Expecter struct
method Close (line 50) | func (_e *MockConn_Expecter) Close() *MockConn_Close_Call {
method LocalAddr (line 97) | func (_e *MockConn_Expecter) LocalAddr() *MockConn_LocalAddr_Call {
method Read (line 153) | func (_e *MockConn_Expecter) Read(b interface{}) *MockConn_Read_Call {
method RemoteAddr (line 200) | func (_e *MockConn_Expecter) RemoteAddr() *MockConn_RemoteAddr_Call {
method SetDeadline (line 246) | func (_e *MockConn_Expecter) SetDeadline(t interface{}) *MockConn_SetD...
method SetReadDeadline (line 292) | func (_e *MockConn_Expecter) SetReadDeadline(t interface{}) *MockConn_...
method SetWriteDeadline (line 338) | func (_e *MockConn_Expecter) SetWriteDeadline(t interface{}) *MockConn...
method Write (line 394) | func (_e *MockConn_Expecter) Write(b interface{}) *MockConn_Write_Call {
type MockConn_Close_Call (line 45) | type MockConn_Close_Call struct
method Run (line 54) | func (_c *MockConn_Close_Call) Run(run func()) *MockConn_Close_Call {
method Return (line 61) | func (_c *MockConn_Close_Call) Return(_a0 error) *MockConn_Close_Call {
method RunAndReturn (line 66) | func (_c *MockConn_Close_Call) RunAndReturn(run func() error) *MockCon...
type MockConn_LocalAddr_Call (line 92) | type MockConn_LocalAddr_Call struct
method Run (line 101) | func (_c *MockConn_LocalAddr_Call) Run(run func()) *MockConn_LocalAddr...
method Return (line 108) | func (_c *MockConn_LocalAddr_Call) Return(_a0 net.Addr) *MockConn_Loca...
method RunAndReturn (line 113) | func (_c *MockConn_LocalAddr_Call) RunAndReturn(run func() net.Addr) *...
type MockConn_Read_Call (line 147) | type MockConn_Read_Call struct
method Run (line 157) | func (_c *MockConn_Read_Call) Run(run func(b []byte)) *MockConn_Read_C...
method Return (line 164) | func (_c *MockConn_Read_Call) Return(n int, err error) *MockConn_Read_...
method RunAndReturn (line 169) | func (_c *MockConn_Read_Call) RunAndReturn(run func([]byte) (int, erro...
type MockConn_RemoteAddr_Call (line 195) | type MockConn_RemoteAddr_Call struct
method Run (line 204) | func (_c *MockConn_RemoteAddr_Call) Run(run func()) *MockConn_RemoteAd...
method Return (line 211) | func (_c *MockConn_RemoteAddr_Call) Return(_a0 net.Addr) *MockConn_Rem...
method RunAndReturn (line 216) | func (_c *MockConn_RemoteAddr_Call) RunAndReturn(run func() net.Addr) ...
type MockConn_SetDeadline_Call (line 240) | type MockConn_SetDeadline_Call struct
method Run (line 250) | func (_c *MockConn_SetDeadline_Call) Run(run func(t time.Time)) *MockC...
method Return (line 257) | func (_c *MockConn_SetDeadline_Call) Return(_a0 error) *MockConn_SetDe...
method RunAndReturn (line 262) | func (_c *MockConn_SetDeadline_Call) RunAndReturn(run func(time.Time) ...
type MockConn_SetReadDeadline_Call (line 286) | type MockConn_SetReadDeadline_Call struct
method Run (line 296) | func (_c *MockConn_SetReadDeadline_Call) Run(run func(t time.Time)) *M...
method Return (line 303) | func (_c *MockConn_SetReadDeadline_Call) Return(_a0 error) *MockConn_S...
method RunAndReturn (line 308) | func (_c *MockConn_SetReadDeadline_Call) RunAndReturn(run func(time.Ti...
type MockConn_SetWriteDeadline_Call (line 332) | type MockConn_SetWriteDeadline_Call struct
method Run (line 342) | func (_c *MockConn_SetWriteDeadline_Call) Run(run func(t time.Time)) *...
method Return (line 349) | func (_c *MockConn_SetWriteDeadline_Call) Return(_a0 error) *MockConn_...
method RunAndReturn (line 354) | func (_c *MockConn_SetWriteDeadline_Call) RunAndReturn(run func(time.T...
type MockConn_Write_Call (line 388) | type MockConn_Write_Call struct
method Run (line 398) | func (_c *MockConn_Write_Call) Run(run func(b []byte)) *MockConn_Write...
method Return (line 405) | func (_c *MockConn_Write_Call) Return(n int, err error) *MockConn_Writ...
method RunAndReturn (line 410) | func (_c *MockConn_Write_Call) RunAndReturn(run func([]byte) (int, err...
function NewMockConn (line 417) | func NewMockConn(t interface {
FILE: core/internal/integration_tests/mocks/mock_EventLogger.go
type MockEventLogger (line 12) | type MockEventLogger struct
method EXPECT (line 20) | func (_m *MockEventLogger) EXPECT() *MockEventLogger_Expecter {
method Connect (line 25) | func (_m *MockEventLogger) Connect(addr net.Addr, id string, tx uint64) {
method Disconnect (line 60) | func (_m *MockEventLogger) Disconnect(addr net.Addr, id string, err er...
method TCPError (line 95) | func (_m *MockEventLogger) TCPError(addr net.Addr, id string, reqAddr ...
method TCPRequest (line 131) | func (_m *MockEventLogger) TCPRequest(addr net.Addr, id string, reqAdd...
method UDPError (line 166) | func (_m *MockEventLogger) UDPError(addr net.Addr, id string, sessionI...
method UDPRequest (line 202) | func (_m *MockEventLogger) UDPRequest(addr net.Addr, id string, sessio...
type MockEventLogger_Expecter (line 16) | type MockEventLogger_Expecter struct
method Connect (line 38) | func (_e *MockEventLogger_Expecter) Connect(addr interface{}, id inter...
method Disconnect (line 73) | func (_e *MockEventLogger_Expecter) Disconnect(addr interface{}, id in...
method TCPError (line 109) | func (_e *MockEventLogger_Expecter) TCPError(addr interface{}, id inte...
method TCPRequest (line 144) | func (_e *MockEventLogger_Expecter) TCPRequest(addr interface{}, id in...
method UDPError (line 180) | func (_e *MockEventLogger_Expecter) UDPError(addr interface{}, id inte...
method UDPRequest (line 216) | func (_e *MockEventLogger_Expecter) UDPRequest(addr interface{}, id in...
type MockEventLogger_Connect_Call (line 30) | type MockEventLogger_Connect_Call struct
method Run (line 42) | func (_c *MockEventLogger_Connect_Call) Run(run func(addr net.Addr, id...
method Return (line 49) | func (_c *MockEventLogger_Connect_Call) Return() *MockEventLogger_Conn...
method RunAndReturn (line 54) | func (_c *MockEventLogger_Connect_Call) RunAndReturn(run func(net.Addr...
type MockEventLogger_Disconnect_Call (line 65) | type MockEventLogger_Disconnect_Call struct
method Run (line 77) | func (_c *MockEventLogger_Disconnect_Call) Run(run func(addr net.Addr,...
method Return (line 84) | func (_c *MockEventLogger_Disconnect_Call) Return() *MockEventLogger_D...
method RunAndReturn (line 89) | func (_c *MockEventLogger_Disconnect_Call) RunAndReturn(run func(net.A...
type MockEventLogger_TCPError_Call (line 100) | type MockEventLogger_TCPError_Call struct
method Run (line 113) | func (_c *MockEventLogger_TCPError_Call) Run(run func(addr net.Addr, i...
method Return (line 120) | func (_c *MockEventLogger_TCPError_Call) Return() *MockEventLogger_TCP...
method RunAndReturn (line 125) | func (_c *MockEventLogger_TCPError_Call) RunAndReturn(run func(net.Add...
type MockEventLogger_TCPRequest_Call (line 136) | type MockEventLogger_TCPRequest_Call struct
method Run (line 148) | func (_c *MockEventLogger_TCPRequest_Call) Run(run func(addr net.Addr,...
method Return (line 155) | func (_c *MockEventLogger_TCPRequest_Call) Return() *MockEventLogger_T...
method RunAndReturn (line 160) | func (_c *MockEventLogger_TCPRequest_Call) RunAndReturn(run func(net.A...
type MockEventLogger_UDPError_Call (line 171) | type MockEventLogger_UDPError_Call struct
method Run (line 184) | func (_c *MockEventLogger_UDPError_Call) Run(run func(addr net.Addr, i...
method Return (line 191) | func (_c *MockEventLogger_UDPError_Call) Return() *MockEventLogger_UDP...
method RunAndReturn (line 196) | func (_c *MockEventLogger_UDPError_Call) RunAndReturn(run func(net.Add...
type MockEventLogger_UDPRequest_Call (line 207) | type MockEventLogger_UDPRequest_Call struct
method Run (line 220) | func (_c *MockEventLogger_UDPRequest_Call) Run(run func(addr net.Addr,...
method Return (line 227) | func (_c *MockEventLogger_UDPRequest_Call) Return() *MockEventLogger_U...
method RunAndReturn (line 232) | func (_c *MockEventLogger_UDPRequest_Call) RunAndReturn(run func(net.A...
function NewMockEventLogger (line 239) | func NewMockEventLogger(t interface {
FILE: core/internal/integration_tests/mocks/mock_Outbound.go
type MockOutbound (line 14) | type MockOutbound struct
method EXPECT (line 22) | func (_m *MockOutbound) EXPECT() *MockOutbound_Expecter {
method TCP (line 27) | func (_m *MockOutbound) TCP(reqAddr string) (net.Conn, error) {
method UDP (line 85) | func (_m *MockOutbound) UDP(reqAddr string) (server.UDPConn, error) {
type MockOutbound_Expecter (line 18) | type MockOutbound_Expecter struct
method TCP (line 63) | func (_e *MockOutbound_Expecter) TCP(reqAddr interface{}) *MockOutboun...
method UDP (line 121) | func (_e *MockOutbound_Expecter) UDP(reqAddr interface{}) *MockOutboun...
type MockOutbound_TCP_Call (line 57) | type MockOutbound_TCP_Call struct
method Run (line 67) | func (_c *MockOutbound_TCP_Call) Run(run func(reqAddr string)) *MockOu...
method Return (line 74) | func (_c *MockOutbound_TCP_Call) Return(_a0 net.Conn, _a1 error) *Mock...
method RunAndReturn (line 79) | func (_c *MockOutbound_TCP_Call) RunAndReturn(run func(string) (net.Co...
type MockOutbound_UDP_Call (line 115) | type MockOutbound_UDP_Call struct
method Run (line 125) | func (_c *MockOutbound_UDP_Call) Run(run func(reqAddr string)) *MockOu...
method Return (line 132) | func (_c *MockOutbound_UDP_Call) Return(_a0 server.UDPConn, _a1 error)...
method RunAndReturn (line 137) | func (_c *MockOutbound_UDP_Call) RunAndReturn(run func(string) (server...
function NewMockOutbound (line 144) | func NewMockOutbound(t interface {
FILE: core/internal/integration_tests/mocks/mock_RequestHook.go
type MockRequestHook (line 11) | type MockRequestHook struct
method EXPECT (line 19) | func (_m *MockRequestHook) EXPECT() *MockRequestHook_Expecter {
method Check (line 24) | func (_m *MockRequestHook) Check(isUDP bool, reqAddr string) bool {
method TCP (line 71) | func (_m *MockRequestHook) TCP(stream quic.Stream, reqAddr *string) ([...
method UDP (line 130) | func (_m *MockRequestHook) UDP(data []byte, reqAddr *string) error {
type MockRequestHook_Expecter (line 15) | type MockRequestHook_Expecter struct
method Check (line 49) | func (_e *MockRequestHook_Expecter) Check(isUDP interface{}, reqAddr i...
method TCP (line 108) | func (_e *MockRequestHook_Expecter) TCP(stream interface{}, reqAddr in...
method UDP (line 155) | func (_e *MockRequestHook_Expecter) UDP(data interface{}, reqAddr inte...
type MockRequestHook_Check_Call (line 42) | type MockRequestHook_Check_Call struct
method Run (line 53) | func (_c *MockRequestHook_Check_Call) Run(run func(isUDP bool, reqAddr...
method Return (line 60) | func (_c *MockRequestHook_Check_Call) Return(_a0 bool) *MockRequestHoo...
method RunAndReturn (line 65) | func (_c *MockRequestHook_Check_Call) RunAndReturn(run func(bool, stri...
type MockRequestHook_TCP_Call (line 101) | type MockRequestHook_TCP_Call struct
method Run (line 112) | func (_c *MockRequestHook_TCP_Call) Run(run func(stream quic.Stream, r...
method Return (line 119) | func (_c *MockRequestHook_TCP_Call) Return(_a0 []byte, _a1 error) *Moc...
method RunAndReturn (line 124) | func (_c *MockRequestHook_TCP_Call) RunAndReturn(run func(quic.Stream,...
type MockRequestHook_UDP_Call (line 148) | type MockRequestHook_UDP_Call struct
method Run (line 159) | func (_c *MockRequestHook_UDP_Call) Run(run func(data []byte, reqAddr ...
method Return (line 166) | func (_c *MockRequestHook_UDP_Call) Return(_a0 error) *MockRequestHook...
method RunAndReturn (line 171) | func (_c *MockRequestHook_UDP_Call) RunAndReturn(run func([]byte, *str...
function NewMockRequestHook (line 178) | func NewMockRequestHook(t interface {
FILE: core/internal/integration_tests/mocks/mock_TrafficLogger.go
type MockTrafficLogger (line 8) | type MockTrafficLogger struct
method EXPECT (line 16) | func (_m *MockTrafficLogger) EXPECT() *MockTrafficLogger_Expecter {
method LogOnlineState (line 21) | func (_m *MockTrafficLogger) LogOnlineState(id string, online bool) {
method LogTraffic (line 55) | func (_m *MockTrafficLogger) LogTraffic(id string, tx uint64, rx uint6...
type MockTrafficLogger_Expecter (line 12) | type MockTrafficLogger_Expecter struct
method LogOnlineState (line 33) | func (_e *MockTrafficLogger_Expecter) LogOnlineState(id interface{}, o...
method LogTraffic (line 81) | func (_e *MockTrafficLogger_Expecter) LogTraffic(id interface{}, tx in...
type MockTrafficLogger_LogOnlineState_Call (line 26) | type MockTrafficLogger_LogOnlineState_Call struct
method Run (line 37) | func (_c *MockTrafficLogger_LogOnlineState_Call) Run(run func(id strin...
method Return (line 44) | func (_c *MockTrafficLogger_LogOnlineState_Call) Return() *MockTraffic...
method RunAndReturn (line 49) | func (_c *MockTrafficLogger_LogOnlineState_Call) RunAndReturn(run func...
type MockTrafficLogger_LogTraffic_Call (line 73) | type MockTrafficLogger_LogTraffic_Call struct
method Run (line 85) | func (_c *MockTrafficLogger_LogTraffic_Call) Run(run func(id string, t...
method Return (line 92) | func (_c *MockTrafficLogger_LogTraffic_Call) Return(ok bool) *MockTraf...
method RunAndReturn (line 97) | func (_c *MockTrafficLogger_LogTraffic_Call) RunAndReturn(run func(str...
function NewMockTrafficLogger (line 104) | func NewMockTrafficLogger(t interface {
FILE: core/internal/integration_tests/mocks/mock_UDPConn.go
type MockUDPConn (line 8) | type MockUDPConn struct
method EXPECT (line 16) | func (_m *MockUDPConn) EXPECT() *MockUDPConn_Expecter {
method Close (line 21) | func (_m *MockUDPConn) Close() error {
method ReadFrom (line 66) | func (_m *MockUDPConn) ReadFrom(b []byte) (int, string, error) {
method WriteTo (line 129) | func (_m *MockUDPConn) WriteTo(b []byte, addr string) (int, error) {
type MockUDPConn_Expecter (line 12) | type MockUDPConn_Expecter struct
method Close (line 44) | func (_e *MockUDPConn_Expecter) Close() *MockUDPConn_Close_Call {
method ReadFrom (line 107) | func (_e *MockUDPConn_Expecter) ReadFrom(b interface{}) *MockUDPConn_R...
method WriteTo (line 164) | func (_e *MockUDPConn_Expecter) WriteTo(b interface{}, addr interface{...
type MockUDPConn_Close_Call (line 39) | type MockUDPConn_Close_Call struct
method Run (line 48) | func (_c *MockUDPConn_Close_Call) Run(run func()) *MockUDPConn_Close_C...
method Return (line 55) | func (_c *MockUDPConn_Close_Call) Return(_a0 error) *MockUDPConn_Close...
method RunAndReturn (line 60) | func (_c *MockUDPConn_Close_Call) RunAndReturn(run func() error) *Mock...
type MockUDPConn_ReadFrom_Call (line 101) | type MockUDPConn_ReadFrom_Call struct
method Run (line 111) | func (_c *MockUDPConn_ReadFrom_Call) Run(run func(b []byte)) *MockUDPC...
method Return (line 118) | func (_c *MockUDPConn_ReadFrom_Call) Return(_a0 int, _a1 string, _a2 e...
method RunAndReturn (line 123) | func (_c *MockUDPConn_ReadFrom_Call) RunAndReturn(run func([]byte) (in...
type MockUDPConn_WriteTo_Call (line 157) | type MockUDPConn_WriteTo_Call struct
method Run (line 168) | func (_c *MockUDPConn_WriteTo_Call) Run(run func(b []byte, addr string...
method Return (line 175) | func (_c *MockUDPConn_WriteTo_Call) Return(_a0 int, _a1 error) *MockUD...
method RunAndReturn (line 180) | func (_c *MockUDPConn_WriteTo_Call) RunAndReturn(run func([]byte, stri...
function NewMockUDPConn (line 187) | func NewMockUDPConn(t interface {
FILE: core/internal/integration_tests/smoke_test.go
function TestClientNoServer (line 21) | func TestClientNoServer(t *testing.T) {
function TestClientServerBadAuth (line 33) | func TestClientServerBadAuth(t *testing.T) {
function TestClientServerUDPDisabled (line 61) | func TestClientServerUDPDisabled(t *testing.T) {
function TestClientServerTCPEcho (line 92) | func TestClientServerTCPEcho(t *testing.T) {
function TestClientServerUDPEcho (line 139) | func TestClientServerUDPEcho(t *testing.T) {
function TestClientServerHandshakeInfo (line 186) | func TestClientServerHandshakeInfo(t *testing.T) {
FILE: core/internal/integration_tests/stress_test.go
type tcpStressor (line 21) | type tcpStressor struct
method Run (line 28) | func (s *tcpStressor) Run(t *testing.T) {
type udpStressor (line 65) | type udpStressor struct
method Run (line 74) | func (s *udpStressor) Run(t *testing.T) {
function TestClientServerTCPStress (line 127) | func TestClientServerTCPStress(t *testing.T) {
function TestClientServerUDPStress (line 171) | func TestClientServerUDPStress(t *testing.T) {
FILE: core/internal/integration_tests/trafficlogger_test.go
function TestClientServerTrafficLoggerTCP (line 19) | func TestClientServerTrafficLoggerTCP(t *testing.T) {
function TestClientServerTrafficLoggerUDP (line 101) | func TestClientServerTrafficLoggerUDP(t *testing.T) {
FILE: core/internal/integration_tests/utils_test.go
constant testCertFile (line 14) | testCertFile = "test.crt"
constant testKeyFile (line 15) | testKeyFile = "test.key"
function serverTLSConfig (line 18) | func serverTLSConfig() server.TLSConfig {
function serverConn (line 28) | func serverConn() (net.PacketConn, net.Addr, error) {
type tcpEchoServer (line 39) | type tcpEchoServer struct
method Serve (line 43) | func (s *tcpEchoServer) Serve() error {
method Close (line 56) | func (s *tcpEchoServer) Close() error {
type udpEchoServer (line 62) | type udpEchoServer struct
method Serve (line 66) | func (s *udpEchoServer) Serve() error {
method Close (line 80) | func (s *udpEchoServer) Close() error {
FILE: core/internal/pmtud/avail.go
constant DisablePathMTUDiscovery (line 6) | DisablePathMTUDiscovery = false
FILE: core/internal/pmtud/unavail.go
constant DisablePathMTUDiscovery (line 12) | DisablePathMTUDiscovery = true
FILE: core/internal/protocol/http.go
constant URLHost (line 9) | URLHost = "hysteria"
constant URLPath (line 10) | URLPath = "/auth"
constant RequestHeaderAuth (line 12) | RequestHeaderAuth = "Hysteria-Auth"
constant ResponseHeaderUDPEnabled (line 13) | ResponseHeaderUDPEnabled = "Hysteria-UDP"
constant CommonHeaderCCRX (line 14) | CommonHeaderCCRX = "Hysteria-CC-RX"
constant CommonHeaderPadding (line 15) | CommonHeaderPadding = "Hysteria-Padding"
constant StatusAuthOK (line 17) | StatusAuthOK = 233
type AuthRequest (line 21) | type AuthRequest struct
type AuthResponse (line 27) | type AuthResponse struct
function AuthRequestFromHeader (line 33) | func AuthRequestFromHeader(h http.Header) AuthRequest {
function AuthRequestToHeader (line 41) | func AuthRequestToHeader(h http.Header, req AuthRequest) {
function AuthResponseFromHeader (line 47) | func AuthResponseFromHeader(h http.Header) AuthResponse {
function AuthResponseToHeader (line 60) | func AuthResponseToHeader(h http.Header, resp AuthResponse) {
FILE: core/internal/protocol/padding.go
constant paddingChars (line 8) | paddingChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123...
type padding (line 12) | type padding struct
method String (line 17) | func (p padding) String() string {
FILE: core/internal/protocol/proxy.go
constant FrameTypeTCPRequest (line 15) | FrameTypeTCPRequest = 0x401
constant MaxAddressLength (line 19) | MaxAddressLength = 2048
constant MaxMessageLength (line 20) | MaxMessageLength = 2048
constant MaxPaddingLength (line 21) | MaxPaddingLength = 4096
constant MaxUDPSize (line 23) | MaxUDPSize = 4096
constant maxVarInt1 (line 25) | maxVarInt1 = 63
constant maxVarInt2 (line 26) | maxVarInt2 = 16383
constant maxVarInt4 (line 27) | maxVarInt4 = 1073741823
constant maxVarInt8 (line 28) | maxVarInt8 = 4611686018427387903
function ReadTCPRequest (line 38) | func ReadTCPRequest(r io.Reader) (string, error) {
function WriteTCPRequest (line 68) | func WriteTCPRequest(w io.Writer, addr string) error {
function ReadTCPResponse (line 92) | func ReadTCPResponse(r io.Reader) (bool, string, error) {
function WriteTCPResponse (line 130) | func WriteTCPResponse(w io.Writer, ok bool, msg string) error {
type UDPMessage (line 159) | type UDPMessage struct
method HeaderSize (line 168) | func (m *UDPMessage) HeaderSize() int {
method Size (line 173) | func (m *UDPMessage) Size() int {
method Serialize (line 177) | func (m *UDPMessage) Serialize(buf []byte) int {
function ParseUDPMessage (line 192) | func ParseUDPMessage(msg []byte) (*UDPMessage, error) {
function varintPut (line 226) | func varintPut(b []byte, i uint64) int {
FILE: core/internal/protocol/proxy_test.go
function TestUDPMessage (line 10) | func TestUDPMessage(t *testing.T) {
function TestUDPMessageMalformed (line 93) | func TestUDPMessageMalformed(t *testing.T) {
function TestReadTCPRequest (line 128) | func TestReadTCPRequest(t *testing.T) {
function TestWriteTCPRequest (line 175) | func TestWriteTCPRequest(t *testing.T) {
function TestReadTCPResponse (line 216) | func TestReadTCPResponse(t *testing.T) {
function TestWriteTCPResponse (line 274) | func TestWriteTCPResponse(t *testing.T) {
FILE: core/internal/utils/atomic.go
type AtomicTime (line 8) | type AtomicTime struct
method Set (line 18) | func (t *AtomicTime) Set(new time.Time) {
method Get (line 22) | func (t *AtomicTime) Get() time.Time {
function NewAtomicTime (line 12) | func NewAtomicTime(t time.Time) *AtomicTime {
FILE: core/internal/utils/qstream.go
type QStream (line 19) | type QStream struct
method StreamID (line 23) | func (s *QStream) StreamID() quic.StreamID {
method Read (line 27) | func (s *QStream) Read(p []byte) (n int, err error) {
method CancelRead (line 31) | func (s *QStream) CancelRead(code quic.StreamErrorCode) {
method SetReadDeadline (line 35) | func (s *QStream) SetReadDeadline(t time.Time) error {
method Write (line 39) | func (s *QStream) Write(p []byte) (n int, err error) {
method Close (line 43) | func (s *QStream) Close() error {
method CancelWrite (line 48) | func (s *QStream) CancelWrite(code quic.StreamErrorCode) {
method Context (line 52) | func (s *QStream) Context() context.Context {
method SetWriteDeadline (line 56) | func (s *QStream) SetWriteDeadline(t time.Time) error {
method SetDeadline (line 60) | func (s *QStream) SetDeadline(t time.Time) error {
FILE: core/server/config.go
constant defaultStreamReceiveWindow (line 15) | defaultStreamReceiveWindow = 8388608
constant defaultConnReceiveWindow (line 16) | defaultConnReceiveWindow = defaultStreamReceiveWindow * 5 / 2
constant defaultMaxIdleTimeout (line 17) | defaultMaxIdleTimeout = 30 * time.Second
constant defaultMaxIncomingStreams (line 18) | defaultMaxIncomingStreams = 1024
constant defaultUDPIdleTimeout (line 19) | defaultUDPIdleTimeout = 60 * time.Second
type Config (line 22) | type Config struct
method fill (line 40) | func (c *Config) fill() error {
type TLSConfig (line 99) | type TLSConfig struct
type QUICConfig (line 105) | type QUICConfig struct
type RequestHook (line 122) | type RequestHook interface
type Outbound (line 132) | type Outbound interface
type UDPConn (line 138) | type UDPConn interface
type defaultOutbound (line 144) | type defaultOutbound struct
method TCP (line 150) | func (o *defaultOutbound) TCP(reqAddr string) (net.Conn, error) {
method UDP (line 154) | func (o *defaultOutbound) UDP(reqAddr string) (UDPConn, error) {
type defaultUDPConn (line 162) | type defaultUDPConn struct
method ReadFrom (line 166) | func (c *defaultUDPConn) ReadFrom(b []byte) (int, string, error) {
method WriteTo (line 175) | func (c *defaultUDPConn) WriteTo(b []byte, addr string) (int, error) {
type BandwidthConfig (line 184) | type BandwidthConfig struct
type Authenticator (line 190) | type Authenticator interface
type EventLogger (line 195) | type EventLogger interface
type TrafficLogger (line 212) | type TrafficLogger interface
FILE: core/server/copy.go
function copyBufferLog (line 10) | func copyBufferLog(dst io.Writer, src io.Reader, log func(n uint64) bool...
function copyTwoWayWithLogger (line 34) | func copyTwoWayWithLogger(id string, serverRw, remoteRw io.ReadWriter, l...
function copyTwoWay (line 52) | func copyTwoWay(serverRw, remoteRw io.ReadWriter) error {
FILE: core/server/mock_UDPConn.go
type mockUDPConn (line 8) | type mockUDPConn struct
method EXPECT (line 16) | func (_m *mockUDPConn) EXPECT() *mockUDPConn_Expecter {
method Close (line 21) | func (_m *mockUDPConn) Close() error {
method ReadFrom (line 66) | func (_m *mockUDPConn) ReadFrom(b []byte) (int, string, error) {
method WriteTo (line 129) | func (_m *mockUDPConn) WriteTo(b []byte, addr string) (int, error) {
type mockUDPConn_Expecter (line 12) | type mockUDPConn_Expecter struct
method Close (line 44) | func (_e *mockUDPConn_Expecter) Close() *mockUDPConn_Close_Call {
method ReadFrom (line 107) | func (_e *mockUDPConn_Expecter) ReadFrom(b interface{}) *mockUDPConn_R...
method WriteTo (line 164) | func (_e *mockUDPConn_Expecter) WriteTo(b interface{}, addr interface{...
type mockUDPConn_Close_Call (line 39) | type mockUDPConn_Close_Call struct
method Run (line 48) | func (_c *mockUDPConn_Close_Call) Run(run func()) *mockUDPConn_Close_C...
method Return (line 55) | func (_c *mockUDPConn_Close_Call) Return(_a0 error) *mockUDPConn_Close...
method RunAndReturn (line 60) | func (_c *mockUDPConn_Close_Call) RunAndReturn(run func() error) *mock...
type mockUDPConn_ReadFrom_Call (line 101) | type mockUDPConn_ReadFrom_Call struct
method Run (line 111) | func (_c *mockUDPConn_ReadFrom_Call) Run(run func(b []byte)) *mockUDPC...
method Return (line 118) | func (_c *mockUDPConn_ReadFrom_Call) Return(_a0 int, _a1 string, _a2 e...
method RunAndReturn (line 123) | func (_c *mockUDPConn_ReadFrom_Call) RunAndReturn(run func([]byte) (in...
type mockUDPConn_WriteTo_Call (line 157) | type mockUDPConn_WriteTo_Call struct
method Run (line 168) | func (_c *mockUDPConn_WriteTo_Call) Run(run func(b []byte, addr string...
method Return (line 175) | func (_c *mockUDPConn_WriteTo_Call) Return(_a0 int, _a1 error) *mockUD...
method RunAndReturn (line 180) | func (_c *mockUDPConn_WriteTo_Call) RunAndReturn(run func([]byte, stri...
function newMockUDPConn (line 187) | func newMockUDPConn(t interface {
FILE: core/server/mock_udpEventLogger.go
type mockUDPEventLogger (line 8) | type mockUDPEventLogger struct
method EXPECT (line 16) | func (_m *mockUDPEventLogger) EXPECT() *mockUDPEventLogger_Expecter {
method Close (line 21) | func (_m *mockUDPEventLogger) Close(sessionID uint32, err error) {
method New (line 55) | func (_m *mockUDPEventLogger) New(sessionID uint32, reqAddr string) {
type mockUDPEventLogger_Expecter (line 12) | type mockUDPEventLogger_Expecter struct
method Close (line 33) | func (_e *mockUDPEventLogger_Expecter) Close(sessionID interface{}, er...
method New (line 67) | func (_e *mockUDPEventLogger_Expecter) New(sessionID interface{}, reqA...
type mockUDPEventLogger_Close_Call (line 26) | type mockUDPEventLogger_Close_Call struct
method Run (line 37) | func (_c *mockUDPEventLogger_Close_Call) Run(run func(sessionID uint32...
method Return (line 44) | func (_c *mockUDPEventLogger_Close_Call) Return() *mockUDPEventLogger_...
method RunAndReturn (line 49) | func (_c *mockUDPEventLogger_Close_Call) RunAndReturn(run func(uint32,...
type mockUDPEventLogger_New_Call (line 60) | type mockUDPEventLogger_New_Call struct
method Run (line 71) | func (_c *mockUDPEventLogger_New_Call) Run(run func(sessionID uint32, ...
method Return (line 78) | func (_c *mockUDPEventLogger_New_Call) Return() *mockUDPEventLogger_Ne...
method RunAndReturn (line 83) | func (_c *mockUDPEventLogger_New_Call) RunAndReturn(run func(uint32, s...
function newMockUDPEventLogger (line 90) | func newMockUDPEventLogger(t interface {
FILE: core/server/mock_udpIO.go
type mockUDPIO (line 11) | type mockUDPIO struct
method EXPECT (line 19) | func (_m *mockUDPIO) EXPECT() *mockUDPIO_Expecter {
method Hook (line 24) | func (_m *mockUDPIO) Hook(data []byte, reqAddr *string) error {
method ReceiveMessage (line 71) | func (_m *mockUDPIO) ReceiveMessage() (*protocol.UDPMessage, error) {
method SendMessage (line 128) | func (_m *mockUDPIO) SendMessage(_a0 []byte, _a1 *protocol.UDPMessage)...
method UDP (line 175) | func (_m *mockUDPIO) UDP(reqAddr string) (UDPConn, error) {
type mockUDPIO_Expecter (line 15) | type mockUDPIO_Expecter struct
method Hook (line 49) | func (_e *mockUDPIO_Expecter) Hook(data interface{}, reqAddr interface...
method ReceiveMessage (line 106) | func (_e *mockUDPIO_Expecter) ReceiveMessage() *mockUDPIO_ReceiveMessa...
method SendMessage (line 153) | func (_e *mockUDPIO_Expecter) SendMessage(_a0 interface{}, _a1 interfa...
method UDP (line 211) | func (_e *mockUDPIO_Expecter) UDP(reqAddr interface{}) *mockUDPIO_UDP_...
type mockUDPIO_Hook_Call (line 42) | type mockUDPIO_Hook_Call struct
method Run (line 53) | func (_c *mockUDPIO_Hook_Call) Run(run func(data []byte, reqAddr *stri...
method Return (line 60) | func (_c *mockUDPIO_Hook_Call) Return(_a0 error) *mockUDPIO_Hook_Call {
method RunAndReturn (line 65) | func (_c *mockUDPIO_Hook_Call) RunAndReturn(run func([]byte, *string) ...
type mockUDPIO_ReceiveMessage_Call (line 101) | type mockUDPIO_ReceiveMessage_Call struct
method Run (line 110) | func (_c *mockUDPIO_ReceiveMessage_Call) Run(run func()) *mockUDPIO_Re...
method Return (line 117) | func (_c *mockUDPIO_ReceiveMessage_Call) Return(_a0 *protocol.UDPMessa...
method RunAndReturn (line 122) | func (_c *mockUDPIO_ReceiveMessage_Call) RunAndReturn(run func() (*pro...
type mockUDPIO_SendMessage_Call (line 146) | type mockUDPIO_SendMessage_Call struct
method Run (line 157) | func (_c *mockUDPIO_SendMessage_Call) Run(run func(_a0 []byte, _a1 *pr...
method Return (line 164) | func (_c *mockUDPIO_SendMessage_Call) Return(_a0 error) *mockUDPIO_Sen...
method RunAndReturn (line 169) | func (_c *mockUDPIO_SendMessage_Call) RunAndReturn(run func([]byte, *p...
type mockUDPIO_UDP_Call (line 205) | type mockUDPIO_UDP_Call struct
method Run (line 215) | func (_c *mockUDPIO_UDP_Call) Run(run func(reqAddr string)) *mockUDPIO...
method Return (line 222) | func (_c *mockUDPIO_UDP_Call) Return(_a0 UDPConn, _a1 error) *mockUDPI...
method RunAndReturn (line 227) | func (_c *mockUDPIO_UDP_Call) RunAndReturn(run func(string) (UDPConn, ...
function newMockUDPIO (line 234) | func newMockUDPIO(t interface {
FILE: core/server/server.go
constant closeErrCodeOK (line 18) | closeErrCodeOK = 0x100
constant closeErrCodeTrafficLimitReached (line 19) | closeErrCodeTrafficLimitReached = 0x107
type Server (line 22) | type Server interface
function NewServer (line 27) | func NewServer(config *Config) (Server, error) {
type serverImpl (line 56) | type serverImpl struct
method Serve (line 61) | func (s *serverImpl) Serve() error {
method Close (line 71) | func (s *serverImpl) Close() error {
method handleClient (line 77) | func (s *serverImpl) handleClient(conn quic.Connection) {
type h3sHandler (line 96) | type h3sHandler struct
method ServeHTTP (line 114) | func (h *h3sHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
method ProxyStreamHijacker (line 190) | func (h *h3sHandler) ProxyStreamHijacker(ft http3.FrameType, id quic.C...
method handleTCPRequest (line 207) | func (h *h3sHandler) handleTCPRequest(stream quic.Stream) {
method masqHandler (line 274) | func (h *h3sHandler) masqHandler(w http.ResponseWriter, r *http.Reques...
function newH3sHandler (line 107) | func newH3sHandler(config *Config, conn quic.Connection) *h3sHandler {
type udpIOImpl (line 284) | type udpIOImpl struct
method ReceiveMessage (line 292) | func (io *udpIOImpl) ReceiveMessage() (*protocol.UDPMessage, error) {
method SendMessage (line 316) | func (io *udpIOImpl) SendMessage(buf []byte, msg *protocol.UDPMessage)...
method Hook (line 333) | func (io *udpIOImpl) Hook(data []byte, reqAddr *string) error {
method UDP (line 341) | func (io *udpIOImpl) UDP(reqAddr string) (UDPConn, error) {
type udpEventLoggerImpl (line 345) | type udpEventLoggerImpl struct
method New (line 351) | func (l *udpEventLoggerImpl) New(sessionID uint32, reqAddr string) {
method Close (line 357) | func (l *udpEventLoggerImpl) Close(sessionID uint32, err error) {
FILE: core/server/udp.go
constant idleCleanupInterval (line 17) | idleCleanupInterval = 1 * time.Second
type udpIO (line 20) | type udpIO interface
type udpEventLogger (line 27) | type udpEventLogger interface
type udpSessionEntry (line 32) | type udpSessionEntry struct
method CloseWithErr (line 68) | func (e *udpSessionEntry) CloseWithErr(err error) {
method Feed (line 92) | func (e *udpSessionEntry) Feed(msg *protocol.UDPMessage) (int, error) {
method initConn (line 116) | func (e *udpSessionEntry) initConn(firstMsg *protocol.UDPMessage) error {
method receiveLoop (line 152) | func (e *udpSessionEntry) receiveLoop() {
function newUDPSessionEntry (line 48) | func newUDPSessionEntry(
function sendMessageAutoFrag (line 189) | func sendMessageAutoFrag(io udpIO, buf []byte, msg *protocol.UDPMessage)...
type udpSessionManager (line 213) | type udpSessionManager struct
method Run (line 233) | func (m *udpSessionManager) Run() error {
method idleCleanupLoop (line 248) | func (m *udpSessionManager) idleCleanupLoop(stopCh <-chan struct{}) {
method cleanup (line 261) | func (m *udpSessionManager) cleanup(idleOnly bool) {
method feed (line 281) | func (m *udpSessionManager) feed(msg *protocol.UDPMessage) {
method Count (line 325) | func (m *udpSessionManager) Count() int {
function newUDPSessionManager (line 222) | func newUDPSessionManager(io udpIO, eventLogger udpEventLogger, idleTime...
FILE: core/server/udp_test.go
function TestUDPSessionManager (line 15) | func TestUDPSessionManager(t *testing.T) {
FILE: extras/auth/command.go
type CommandAuthenticator (line 14) | type CommandAuthenticator struct
method Authenticate (line 18) | func (a *CommandAuthenticator) Authenticate(addr net.Addr, auth string...
FILE: extras/auth/http.go
constant httpAuthTimeout (line 17) | httpAuthTimeout = 10 * time.Second
type HTTPAuthenticator (line 24) | type HTTPAuthenticator struct
method post (line 54) | func (a *HTTPAuthenticator) post(req *httpAuthRequest) (*httpAuthRespo...
method Authenticate (line 79) | func (a *HTTPAuthenticator) Authenticate(addr net.Addr, auth string, t...
function NewHTTPAuthenticator (line 29) | func NewHTTPAuthenticator(url string, insecure bool) *HTTPAuthenticator {
type httpAuthRequest (line 43) | type httpAuthRequest struct
type httpAuthResponse (line 49) | type httpAuthResponse struct
FILE: extras/auth/http_test.go
function TestHTTPAuthenticator (line 12) | func TestHTTPAuthenticator(t *testing.T) {
FILE: extras/auth/http_test.py
function auth (line 7) | def auth():
FILE: extras/auth/password.go
type PasswordAuthenticator (line 12) | type PasswordAuthenticator struct
method Authenticate (line 16) | func (a *PasswordAuthenticator) Authenticate(addr net.Addr, auth strin...
FILE: extras/auth/password_test.go
function TestPasswordAuthenticator (line 8) | func TestPasswordAuthenticator(t *testing.T) {
FILE: extras/auth/userpass.go
constant userPassSeparator (line 11) | userPassSeparator = ":"
type UserPassAuthenticator (line 18) | type UserPassAuthenticator struct
method Authenticate (line 22) | func (a *UserPassAuthenticator) Authenticate(addr net.Addr, auth strin...
function splitUserPass (line 34) | func splitUserPass(auth string) (user, pass string, ok bool) {
FILE: extras/auth/userpass_test.go
function TestUserPassAuthenticator (line 8) | func TestUserPassAuthenticator(t *testing.T) {
FILE: extras/auth/v2board.go
type V2boardApiProvider (line 17) | type V2boardApiProvider struct
method Authenticate (line 100) | func (v *V2boardApiProvider) Authenticate(addr net.Addr, auth string, ...
type User (line 28) | type User struct
type ResponseData (line 33) | type ResponseData struct
function getUserList (line 37) | func getUserList(url string) ([]User, error) {
function UpdateUsers (line 53) | func UpdateUsers(url string, interval time.Duration, trafficlogger serve...
function processUserList (line 79) | func processUserList(userList []User, trafficlogger server.TrafficLogger) {
FILE: extras/correctnet/correctnet.go
function extractIPFamily (line 9) | func extractIPFamily(ip net.IP) (family string) {
function tcpAddrNetwork (line 20) | func tcpAddrNetwork(addr *net.TCPAddr) (network string) {
function udpAddrNetwork (line 27) | func udpAddrNetwork(addr *net.UDPAddr) (network string) {
function ipAddrNetwork (line 34) | func ipAddrNetwork(addr *net.IPAddr) (network string) {
function Listen (line 41) | func Listen(network, address string) (net.Listener, error) {
function ListenTCP (line 52) | func ListenTCP(network string, laddr *net.TCPAddr) (*net.TCPListener, er...
function ListenPacket (line 59) | func ListenPacket(network, address string) (listener net.PacketConn, err...
function ListenUDP (line 78) | func ListenUDP(network string, laddr *net.UDPAddr) (*net.UDPConn, error) {
function HTTPListenAndServe (line 85) | func HTTPListenAndServe(address string, handler http.Handler) error {
FILE: extras/masq/server.go
type MasqTCPServer (line 16) | type MasqTCPServer struct
method ListenAndServeHTTP (line 24) | func (s *MasqTCPServer) ListenAndServeHTTP(addr string) error {
method ListenAndServeHTTPS (line 39) | func (s *MasqTCPServer) ListenAndServeHTTPS(addr string) error {
type altSvcHijackResponseWriter (line 59) | type altSvcHijackResponseWriter struct
method WriteHeader (line 64) | func (w *altSvcHijackResponseWriter) WriteHeader(statusCode int) {
type altSvcHijackResponseWriterHijacker (line 73) | type altSvcHijackResponseWriterHijacker struct
method Hijack (line 77) | func (w *altSvcHijackResponseWriterHijacker) Hijack() (net.Conn, *bufi...
function newAltSvcHijackResponseWriter (line 81) | func newAltSvcHijackResponseWriter(w http.ResponseWriter, port int) http...
FILE: extras/obfs/conn.go
constant udpBufferSize (line 10) | udpBufferSize = 2048
type Obfuscator (line 15) | type Obfuscator interface
type obfsPacketConn (line 22) | type obfsPacketConn struct
method ReadFrom (line 61) | func (c *obfsPacketConn) ReadFrom(p []byte) (n int, addr net.Addr, err...
method WriteTo (line 78) | func (c *obfsPacketConn) WriteTo(p []byte, addr net.Addr) (n int, err ...
method Close (line 89) | func (c *obfsPacketConn) Close() error {
method LocalAddr (line 93) | func (c *obfsPacketConn) LocalAddr() net.Addr {
method SetDeadline (line 97) | func (c *obfsPacketConn) SetDeadline(t time.Time) error {
method SetReadDeadline (line 101) | func (c *obfsPacketConn) SetReadDeadline(t time.Time) error {
method SetWriteDeadline (line 105) | func (c *obfsPacketConn) SetWriteDeadline(t time.Time) error {
type obfsPacketConnUDP (line 35) | type obfsPacketConnUDP struct
method SetReadBuffer (line 111) | func (c *obfsPacketConnUDP) SetReadBuffer(bytes int) error {
method SetWriteBuffer (line 115) | func (c *obfsPacketConnUDP) SetWriteBuffer(bytes int) error {
method SyscallConn (line 119) | func (c *obfsPacketConnUDP) SyscallConn() (syscall.RawConn, error) {
function WrapPacketConn (line 44) | func WrapPacketConn(conn net.PacketConn, obfs Obfuscator) net.PacketConn {
FILE: extras/obfs/salamander.go
constant smPSKMinLen (line 13) | smPSKMinLen = 4
constant smSaltLen (line 14) | smSaltLen = 8
constant smKeyLen (line 15) | smKeyLen = blake2b.Size256
type SalamanderObfuscator (line 25) | type SalamanderObfuscator struct
method Obfuscate (line 42) | func (o *SalamanderObfuscator) Obfuscate(in, out []byte) int {
method Deobfuscate (line 57) | func (o *SalamanderObfuscator) Deobfuscate(in, out []byte) int {
method key (line 69) | func (o *SalamanderObfuscator) key(salt []byte) [smKeyLen]byte {
function NewSalamanderObfuscator (line 32) | func NewSalamanderObfuscator(psk []byte) (*SalamanderObfuscator, error) {
FILE: extras/obfs/salamander_test.go
function BenchmarkSalamanderObfuscator_Obfuscate (line 10) | func BenchmarkSalamanderObfuscator_Obfuscate(b *testing.B) {
function BenchmarkSalamanderObfuscator_Deobfuscate (line 21) | func BenchmarkSalamanderObfuscator_Deobfuscate(b *testing.B) {
function TestSalamanderObfuscator (line 32) | func TestSalamanderObfuscator(t *testing.T) {
FILE: extras/outbounds/acl.go
constant aclCacheSize (line 13) | aclCacheSize = 1024
type aclEngine (line 26) | type aclEngine struct
method handle (line 79) | func (a *aclEngine) handle(reqAddr *AddrEx, proto acl.Protocol) Plugga...
method TCP (line 103) | func (a *aclEngine) TCP(reqAddr *AddrEx) (net.Conn, error) {
method UDP (line 108) | func (a *aclEngine) UDP(reqAddr *AddrEx) (UDPConn, error) {
type OutboundEntry (line 31) | type OutboundEntry struct
function NewACLEngineFromString (line 36) | func NewACLEngineFromString(rules string, outbounds []OutboundEntry, geo...
function NewACLEngineFromFile (line 49) | func NewACLEngineFromFile(filename string, outbounds []OutboundEntry, ge...
function outboundsToMap (line 57) | func outboundsToMap(outbounds []OutboundEntry) map[string]PluggableOutbo...
type aclRejectOutbound (line 113) | type aclRejectOutbound struct
method TCP (line 115) | func (a *aclRejectOutbound) TCP(reqAddr *AddrEx) (net.Conn, error) {
method UDP (line 119) | func (a *aclRejectOutbound) UDP(reqAddr *AddrEx) (UDPConn, error) {
FILE: extras/outbounds/acl/compile.go
type Protocol (line 14) | type Protocol
constant ProtocolBoth (line 17) | ProtocolBoth Protocol = iota
constant ProtocolTCP (line 18) | ProtocolTCP
constant ProtocolUDP (line 19) | ProtocolUDP
type Outbound (line 22) | type Outbound interface
type HostInfo (line 26) | type HostInfo struct
method String (line 32) | func (h HostInfo) String() string {
type CompiledRuleSet (line 36) | type CompiledRuleSet interface
type compiledRule (line 40) | type compiledRule struct
method Match (line 49) | func (r *compiledRule[O]) Match(host HostInfo, proto Protocol, port uint...
type matchResult (line 59) | type matchResult struct
type compiledRuleSetImpl (line 64) | type compiledRuleSetImpl struct
method Match (line 69) | func (s *compiledRuleSetImpl[O]) Match(host HostInfo, proto Protocol, po...
type CompilationError (line 88) | type CompilationError struct
method Error (line 93) | func (e *CompilationError) Error() string {
type GeoLoader (line 97) | type GeoLoader interface
function Compile (line 107) | func Compile[O Outbound](rules []TextRule, outbounds map[string]O,
function parseProtoPort (line 152) | func parseProtoPort(protoPort string) (Protocol, uint16, uint16, bool) {
function compileHostMatcher (line 212) | func compileHostMatcher(addr string, geoLoader GeoLoader) (hostMatcher, ...
function parseGeoSiteName (line 295) | func parseGeoSiteName(s string) (string, []string) {
FILE: extras/outbounds/acl/compile_test.go
type testGeoLoader (line 14) | type testGeoLoader struct
method LoadGeoIP (line 16) | func (l *testGeoLoader) LoadGeoIP() (map[string]*v2geo.GeoIP, error) {
method LoadGeoSite (line 20) | func (l *testGeoLoader) LoadGeoSite() (map[string]*v2geo.GeoSite, erro...
function TestCompile (line 24) | func TestCompile(t *testing.T) {
function Test_parseGeoSiteName (line 286) | func Test_parseGeoSiteName(t *testing.T) {
FILE: extras/outbounds/acl/matchers.go
constant domainMatchExact (line 11) | domainMatchExact = uint8(iota)
constant domainMatchWildcard (line 12) | domainMatchWildcard
constant domainMatchSuffix (line 13) | domainMatchSuffix
type hostMatcher (line 16) | type hostMatcher interface
type ipMatcher (line 20) | type ipMatcher struct
method Match (line 24) | func (m *ipMatcher) Match(host HostInfo) bool {
type cidrMatcher (line 28) | type cidrMatcher struct
method Match (line 32) | func (m *cidrMatcher) Match(host HostInfo) bool {
type domainMatcher (line 36) | type domainMatcher struct
method Match (line 41) | func (m *domainMatcher) Match(host HostInfo) bool {
function deepMatchRune (line 58) | func deepMatchRune(str, pattern []rune) bool {
type allMatcher (line 75) | type allMatcher struct
method Match (line 77) | func (m *allMatcher) Match(host HostInfo) bool {
FILE: extras/outbounds/acl/matchers_test.go
function Test_ipMatcher_Match (line 8) | func Test_ipMatcher_Match(t *testing.T) {
function Test_cidrMatcher_Match (line 64) | func Test_cidrMatcher_Match(t *testing.T) {
function Test_domainMatcher_Match (line 143) | func Test_domainMatcher_Match(t *testing.T) {
FILE: extras/outbounds/acl/matchers_v2geo.go
type geoipMatcher (line 16) | type geoipMatcher struct
method matchIP (line 24) | func (m *geoipMatcher) matchIP(ip net.IP) bool {
method Match (line 48) | func (m *geoipMatcher) Match(host HostInfo) bool {
function newGeoIPMatcher (line 62) | func newGeoIPMatcher(list *v2geo.GeoIP) (*geoipMatcher, error) {
type geositeDomainType (line 98) | type geositeDomainType
constant geositeDomainPlain (line 101) | geositeDomainPlain geositeDomainType = iota
constant geositeDomainRegex (line 102) | geositeDomainRegex
constant geositeDomainRoot (line 103) | geositeDomainRoot
constant geositeDomainFull (line 104) | geositeDomainFull
type geositeDomain (line 107) | type geositeDomain struct
type geositeMatcher (line 114) | type geositeMatcher struct
method matchDomain (line 121) | func (m *geositeMatcher) matchDomain(domain geositeDomain, host HostIn...
method Match (line 154) | func (m *geositeMatcher) Match(host HostInfo) bool {
function newGeositeMatcher (line 163) | func newGeositeMatcher(list *v2geo.GeoSite, attrs []string) (*geositeMat...
function domainAttributeToMap (line 205) | func domainAttributeToMap(attrs []*v2geo.Domain_Attribute) map[string]bo...
FILE: extras/outbounds/acl/matchers_v2geo_test.go
function Test_geoipMatcher_Match (line 11) | func Test_geoipMatcher_Match(t *testing.T) {
function Test_geositeMatcher_Match (line 66) | func Test_geositeMatcher_Match(t *testing.T) {
FILE: extras/outbounds/acl/parse.go
type InvalidSyntaxError (line 11) | type InvalidSyntaxError struct
method Error (line 16) | func (e *InvalidSyntaxError) Error() string {
type TextRule (line 28) | type TextRule struct
function parseLine (line 36) | func parseLine(line string, num int) *TextRule {
function ParseTextRules (line 50) | func ParseTextRules(text string) ([]TextRule, error) {
FILE: extras/outbounds/acl/parse_test.go
function TestParseTextRules (line 8) | func TestParseTextRules(t *testing.T) {
FILE: extras/outbounds/acl/v2geo/load.go
function LoadGeoIP (line 12) | func LoadGeoIP(filename string) (map[string]*GeoIP, error) {
function LoadGeoSite (line 30) | func LoadGeoSite(filename string) (map[string]*GeoSite, error) {
FILE: extras/outbounds/acl/v2geo/load_test.go
function TestLoadGeoIP (line 9) | func TestLoadGeoIP(t *testing.T) {
function TestLoadGeoSite (line 27) | func TestLoadGeoSite(t *testing.T) {
FILE: extras/outbounds/acl/v2geo/v2geo.pb.go
constant _ (line 18) | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
constant _ (line 20) | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
type Domain_Type (line 24) | type Domain_Type
method Enum (line 53) | func (x Domain_Type) Enum() *Domain_Type {
method String (line 59) | func (x Domain_Type) String() string {
method Descriptor (line 63) | func (Domain_Type) Descriptor() protoreflect.EnumDescriptor {
method Type (line 67) | func (Domain_Type) Type() protoreflect.EnumType {
method Number (line 71) | func (x Domain_Type) Number() protoreflect.EnumNumber {
method EnumDescriptor (line 76) | func (Domain_Type) EnumDescriptor() ([]byte, []int) {
constant Domain_Plain (line 28) | Domain_Plain Domain_Type = 0
constant Domain_Regex (line 30) | Domain_Regex Domain_Type = 1
constant Domain_RootDomain (line 32) | Domain_RootDomain Domain_Type = 2
constant Domain_Full (line 34) | Domain_Full Domain_Type = 3
type Domain (line 81) | type Domain struct
method Reset (line 94) | func (x *Domain) Reset() {
method String (line 103) | func (x *Domain) String() string {
method ProtoMessage (line 107) | func (*Domain) ProtoMessage() {}
method ProtoReflect (line 109) | func (x *Domain) ProtoReflect() protoreflect.Message {
method Descriptor (line 122) | func (*Domain) Descriptor() ([]byte, []int) {
method GetType (line 126) | func (x *Domain) GetType() Domain_Type {
method GetValue (line 133) | func (x *Domain) GetValue() string {
method GetAttribute (line 140) | func (x *Domain) GetAttribute() []*Domain_Attribute {
type CIDR (line 148) | type CIDR struct
method Reset (line 159) | func (x *CIDR) Reset() {
method String (line 168) | func (x *CIDR) String() string {
method ProtoMessage (line 172) | func (*CIDR) ProtoMessage() {}
method ProtoReflect (line 174) | func (x *CIDR) ProtoReflect() protoreflect.Message {
method Descriptor (line 187) | func (*CIDR) Descriptor() ([]byte, []int) {
method GetIp (line 191) | func (x *CIDR) GetIp() []byte {
method GetPrefix (line 198) | func (x *CIDR) GetPrefix() uint32 {
type GeoIP (line 205) | type GeoIP struct
method Reset (line 218) | func (x *GeoIP) Reset() {
method String (line 227) | func (x *GeoIP) String() string {
method ProtoMessage (line 231) | func (*GeoIP) ProtoMessage() {}
method ProtoReflect (line 233) | func (x *GeoIP) ProtoReflect() protoreflect.Message {
method Descriptor (line 246) | func (*GeoIP) Descriptor() ([]byte, []int) {
method GetCountryCode (line 250) | func (x *GeoIP) GetCountryCode() string {
method GetCidr (line 257) | func (x *GeoIP) GetCidr() []*CIDR {
method GetInverseMatch (line 264) | func (x *GeoIP) GetInverseMatch() bool {
method GetResourceHash (line 271) | func (x *GeoIP) GetResourceHash() []byte {
method GetCode (line 278) | func (x *GeoIP) GetCode() string {
type GeoIPList (line 285) | type GeoIPList struct
method Reset (line 293) | func (x *GeoIPList) Reset() {
method String (line 302) | func (x *GeoIPList) String() string {
method ProtoMessage (line 306) | func (*GeoIPList) ProtoMessage() {}
method ProtoReflect (line 308) | func (x *GeoIPList) ProtoReflect() protoreflect.Message {
method Descriptor (line 321) | func (*GeoIPList) Descriptor() ([]byte, []int) {
method GetEntry (line 325) | func (x *GeoIPList) GetEntry() []*GeoIP {
type GeoSite (line 332) | type GeoSite struct
method Reset (line 344) | func (x *GeoSite) Reset() {
method String (line 353) | func (x *GeoSite) String() string {
method ProtoMessage (line 357) | func (*GeoSite) ProtoMessage() {}
method ProtoReflect (line 359) | func (x *GeoSite) ProtoReflect() protoreflect.Message {
method Descriptor (line 372) | func (*GeoSite) Descriptor() ([]byte, []int) {
method GetCountryCode (line 376) | func (x *GeoSite) GetCountryCode() string {
method GetDomain (line 383) | func (x *GeoSite) GetDomain() []*Domain {
method GetResourceHash (line 390) | func (x *GeoSite) GetResourceHash() []byte {
method GetCode (line 397) | func (x *GeoSite) GetCode() string {
type GeoSiteList (line 404) | type GeoSiteList struct
method Reset (line 412) | func (x *GeoSiteList) Reset() {
method String (line 421) | func (x *GeoSiteList) String() string {
method ProtoMessage (line 425) | func (*GeoSiteList) ProtoMessage() {}
method ProtoReflect (line 427) | func (x *GeoSiteList) ProtoReflect() protoreflect.Message {
method Descriptor (line 440) | func (*GeoSiteList) Descriptor() ([]byte, []int) {
method GetEntry (line 444) | func (x *GeoSiteList) GetEntry() []*GeoSite {
type Domain_Attribute (line 451) | type Domain_Attribute struct
method Reset (line 464) | func (x *Domain_Attribute) Reset() {
method String (line 473) | func (x *Domain_Attribute) String() string {
method ProtoMessage (line 477) | func (*Domain_Attribute) ProtoMessage() {}
method ProtoReflect (line 479) | func (x *Domain_Attribute) ProtoReflect() protoreflect.Message {
method Descriptor (line 492) | func (*Domain_Attribute) Descriptor() ([]byte, []int) {
method GetKey (line 496) | func (x *Domain_Attribute) GetKey() string {
method GetTypedValue (line 503) | func (m *Domain_Attribute) GetTypedValue() isDomain_Attribute_TypedVal...
method GetBoolValue (line 510) | func (x *Domain_Attribute) GetBoolValue() bool {
method GetIntValue (line 517) | func (x *Domain_Attribute) GetIntValue() int64 {
type isDomain_Attribute_TypedValue (line 524) | type isDomain_Attribute_TypedValue interface
type Domain_Attribute_BoolValue (line 528) | type Domain_Attribute_BoolValue struct
method isDomain_Attribute_TypedValue (line 536) | func (*Domain_Attribute_BoolValue) isDomain_Attribute_TypedValue() {}
type Domain_Attribute_IntValue (line 532) | type Domain_Attribute_IntValue struct
method isDomain_Attribute_TypedValue (line 538) | func (*Domain_Attribute_IntValue) isDomain_Attribute_TypedValue() {}
function file_v2geo_proto_rawDescGZIP (line 598) | func file_v2geo_proto_rawDescGZIP() []byte {
function init (line 631) | func init() { file_v2geo_proto_init() }
function file_v2geo_proto_init (line 632) | func file_v2geo_proto_init() {
FILE: extras/outbounds/acl_test.go
function TestACLEngine (line 10) | func TestACLEngine(t *testing.T) {
FILE: extras/outbounds/dns_https.go
type dohResolver (line 14) | type dohResolver struct
method resolve (line 38) | func (r *dohResolver) resolve(reqAddr *AddrEx) {
method TCP (line 76) | func (r *dohResolver) TCP(reqAddr *AddrEx) (net.Conn, error) {
method UDP (line 81) | func (r *dohResolver) UDP(reqAddr *AddrEx) (UDPConn, error) {
function NewDoHResolver (line 19) | func NewDoHResolver(host string, timeout time.Duration, sni string, inse...
FILE: extras/outbounds/dns_standard.go
constant resolverDefaultTimeout (line 12) | resolverDefaultTimeout = 2 * time.Second
constant standardResolverRetryTimes (line 13) | standardResolverRetryTimes = 2
type standardResolver (line 19) | type standardResolver struct
method skipCNAMEChain (line 90) | func (r *standardResolver) skipCNAMEChain(answers []dns.RR) string {
method lookup4 (line 111) | func (r *standardResolver) lookup4(host string) (net.IP, error) {
method lookup6 (line 141) | func (r *standardResolver) lookup6(host string) (net.IP, error) {
method resolve (line 169) | func (r *standardResolver) resolve(reqAddr *AddrEx) {
method TCP (line 213) | func (r *standardResolver) TCP(reqAddr *AddrEx) (net.Conn, error) {
method UDP (line 218) | func (r *standardResolver) UDP(reqAddr *AddrEx) (UDPConn, error) {
function NewStandardResolverUDP (line 25) | func NewStandardResolverUDP(addr string, timeout time.Duration, next Plu...
function NewStandardResolverTCP (line 35) | func NewStandardResolverTCP(addr string, timeout time.Duration, next Plu...
function NewStandardResolverTLS (line 46) | func NewStandardResolverTLS(addr string, timeout time.Duration, sni stri...
function addDefaultPort (line 62) | func addDefaultPort(addr string) string {
function addDefaultPortTLS (line 70) | func addDefaultPortTLS(addr string) string {
function timeoutOrDefault (line 77) | func timeoutOrDefault(timeout time.Duration) time.Duration {
FILE: extras/outbounds/dns_system.go
type systemResolver (line 12) | type systemResolver struct
method resolve (line 22) | func (r *systemResolver) resolve(reqAddr *AddrEx) {
method TCP (line 33) | func (r *systemResolver) TCP(reqAddr *AddrEx) (net.Conn, error) {
method UDP (line 38) | func (r *systemResolver) UDP(reqAddr *AddrEx) (UDPConn, error) {
function NewSystemResolver (line 16) | func NewSystemResolver(next PluggableOutbound) PluggableOutbound {
FILE: extras/outbounds/interface.go
type PluggableOutbound (line 23) | type PluggableOutbound interface
type UDPConn (line 28) | type UDPConn interface
type AddrEx (line 41) | type AddrEx struct
method String (line 47) | func (a *AddrEx) String() string {
type ResolveInfo (line 57) | type ResolveInfo struct
type PluggableOutboundAdapter (line 65) | type PluggableOutboundAdapter struct
method TCP (line 69) | func (a *PluggableOutboundAdapter) TCP(reqAddr string) (net.Conn, erro...
method UDP (line 84) | func (a *PluggableOutboundAdapter) UDP(reqAddr string) (server.UDPConn...
type udpConnAdapter (line 103) | type udpConnAdapter struct
method ReadFrom (line 107) | func (u *udpConnAdapter) ReadFrom(b []byte) (int, string, error) {
method WriteTo (line 116) | func (u *udpConnAdapter) WriteTo(b []byte, addr string) (int, error) {
method Close (line 131) | func (u *udpConnAdapter) Close() error {
FILE: extras/outbounds/interface_test.go
function TestPluggableOutboundAdapter (line 10) | func TestPluggableOutboundAdapter(t *testing.T) {
FILE: extras/outbounds/mock_PluggableOutbound.go
type mockPluggableOutbound (line 12) | type mockPluggableOutbound struct
method EXPECT (line 20) | func (_m *mockPluggableOutbound) EXPECT() *mockPluggableOutbound_Expec...
method TCP (line 25) | func (_m *mockPluggableOutbound) TCP(reqAddr *AddrEx) (net.Conn, error) {
method UDP (line 83) | func (_m *mockPluggableOutbound) UDP(reqAddr *AddrEx) (UDPConn, error) {
type mockPluggableOutbound_Expecter (line 16) | type mockPluggableOutbound_Expecter struct
method TCP (line 61) | func (_e *mockPluggableOutbound_Expecter) TCP(reqAddr interface{}) *mo...
method UDP (line 119) | func (_e *mockPluggableOutbound_Expecter) UDP(reqAddr interface{}) *mo...
type mockPluggableOutbound_TCP_Call (line 55) | type mockPluggableOutbound_TCP_Call struct
method Run (line 65) | func (_c *mockPluggableOutbound_TCP_Call) Run(run func(reqAddr *AddrEx...
method Return (line 72) | func (_c *mockPluggableOutbound_TCP_Call) Return(_a0 net.Conn, _a1 err...
method RunAndReturn (line 77) | func (_c *mockPluggableOutbound_TCP_Call) RunAndReturn(run func(*AddrE...
type mockPluggableOutbound_UDP_Call (line 113) | type mockPluggableOutbound_UDP_Call struct
method Run (line 123) | func (_c *mockPluggableOutbound_UDP_Call) Run(run func(reqAddr *AddrEx...
method Return (line 130) | func (_c *mockPluggableOutbound_UDP_Call) Return(_a0 UDPConn, _a1 erro...
method RunAndReturn (line 135) | func (_c *mockPluggableOutbound_UDP_Call) RunAndReturn(run func(*AddrE...
function newMockPluggableOutbound (line 142) | func newMockPluggableOutbound(t interface {
FILE: extras/outbounds/mock_UDPConn.go
type mockUDPConn (line 8) | type mockUDPConn struct
method EXPECT (line 16) | func (_m *mockUDPConn) EXPECT() *mockUDPConn_Expecter {
method Close (line 21) | func (_m *mockUDPConn) Close() error {
method ReadFrom (line 66) | func (_m *mockUDPConn) ReadFrom(b []byte) (int, *AddrEx, error) {
method WriteTo (line 131) | func (_m *mockUDPConn) WriteTo(b []byte, addr *AddrEx) (int, error) {
type mockUDPConn_Expecter (line 12) | type mockUDPConn_Expecter struct
method Close (line 44) | func (_e *mockUDPConn_Expecter) Close() *mockUDPConn_Close_Call {
method ReadFrom (line 109) | func (_e *mockUDPConn_Expecter) ReadFrom(b interface{}) *mockUDPConn_R...
method WriteTo (line 166) | func (_e *mockUDPConn_Expecter) WriteTo(b interface{}, addr interface{...
type mockUDPConn_Close_Call (line 39) | type mockUDPConn_Close_Call struct
method Run (line 48) | func (_c *mockUDPConn_Close_Call) Run(run func()) *mockUDPConn_Close_C...
method Return (line 55) | func (_c *mockUDPConn_Close_Call) Return(_a0 error) *mockUDPConn_Close...
method RunAndReturn (line 60) | func (_c *mockUDPConn_Close_Call) RunAndReturn(run func() error) *mock...
type mockUDPConn_ReadFrom_Call (line 103) | type mockUDPConn_ReadFrom_Call struct
method Run (line 113) | func (_c *mockUDPConn_ReadFrom_Call) Run(run func(b []byte)) *mockUDPC...
method Return (line 120) | func (_c *mockUDPConn_ReadFrom_Call) Return(_a0 int, _a1 *AddrEx, _a2 ...
method RunAndReturn (line 125) | func (_c *mockUDPConn_ReadFrom_Call) RunAndReturn(run func([]byte) (in...
type mockUDPConn_WriteTo_Call (line 159) | type mockUDPConn_WriteTo_Call struct
method Run (line 170) | func (_c *mockUDPConn_WriteTo_Call) Run(run func(b []byte, addr *AddrE...
method Return (line 177) | func (_c *mockUDPConn_WriteTo_Call) Return(_a0 int, _a1 error) *mockUD...
method RunAndReturn (line 182) | func (_c *mockUDPConn_WriteTo_Call) RunAndReturn(run func([]byte, *Add...
function newMockUDPConn (line 189) | func newMockUDPConn(t interface {
FILE: extras/outbounds/ob_direct.go
type DirectOutboundMode (line 10) | type DirectOutboundMode
type udpConnState (line 12) | type udpConnState
constant DirectOutboundModeAuto (line 15) | DirectOutboundModeAuto DirectOutboundMode = iota
constant DirectOutboundMode64 (line 16) | DirectOutboundMode64
constant DirectOutboundMode46 (line 17) | DirectOutboundMode46
constant DirectOutboundMode6 (line 18) | DirectOutboundMode6
constant DirectOutboundMode4 (line 19) | DirectOutboundMode4
constant defaultDialerTimeout (line 21) | defaultDialerTimeout = 10 * time.Second
constant udpConnStateDualStack (line 25) | udpConnStateDualStack udpConnState = iota
constant udpConnStateIPv4 (line 26) | udpConnStateIPv4
constant udpConnStateIPv6 (line 27) | udpConnStateIPv6
type directOutbound (line 34) | type directOutbound struct
method resolve (line 137) | func (d *directOutbound) resolve(reqAddr *AddrEx) {
method TCP (line 151) | func (d *directOutbound) TCP(reqAddr *AddrEx) (net.Conn, error) {
method dialTCP (line 202) | func (d *directOutbound) dialTCP(ip net.IP, port uint16) (net.Conn, er...
method dualStackDialTCP (line 218) | func (d *directOutbound) dualStackDialTCP(ipv4, ipv6 net.IP, port uint...
method UDP (line 358) | func (d *directOutbound) UDP(reqAddr *AddrEx) (UDPConn, error) {
type noAddressError (line 48) | type noAddressError struct
method Error (line 53) | func (e noAddressError) Error() string {
type invalidOutboundModeError (line 65) | type invalidOutboundModeError struct
method Error (line 67) | func (e invalidOutboundModeError) Error() string {
type resolveError (line 71) | type resolveError struct
method Error (line 75) | func (e resolveError) Error() string {
method Unwrap (line 83) | func (e resolveError) Unwrap() error {
function NewDirectOutboundSimple (line 89) | func NewDirectOutboundSimple(mode DirectOutboundMode) PluggableOutbound {
function NewDirectOutboundBindToIPs (line 104) | func NewDirectOutboundBindToIPs(mode DirectOutboundMode, bindIP4, bindIP...
type dialResult (line 210) | type dialResult struct
type directOutboundUDPConn (line 245) | type directOutboundUDPConn struct
method ReadFrom (line 251) | func (u *directOutboundUDPConn) ReadFrom(b []byte) (int, *AddrEx, erro...
method WriteTo (line 263) | func (u *directOutboundUDPConn) WriteTo(b []byte, addr *AddrEx) (int, ...
method Close (line 354) | func (u *directOutboundUDPConn) Close() error {
FILE: extras/outbounds/ob_direct_linux.go
function NewDirectOutboundBindToDevice (line 11) | func NewDirectOutboundBindToDevice(mode DirectOutboundMode, deviceName s...
function verifyDeviceName (line 36) | func verifyDeviceName(deviceName string) error {
function udpConnBindToDevice (line 44) | func udpConnBindToDevice(conn *net.UDPConn, deviceName string) error {
FILE: extras/outbounds/ob_direct_others.go
function NewDirectOutboundBindToDevice (line 13) | func NewDirectOutboundBindToDevice(mode DirectOutboundMode, deviceName s...
function udpConnBindToDevice (line 17) | func udpConnBindToDevice(conn *net.UDPConn, deviceName string) error {
FILE: extras/outbounds/ob_http.go
constant httpRequestTimeout (line 19) | httpRequestTimeout = 10 * time.Second
type errHTTPRequestFailed (line 27) | type errHTTPRequestFailed struct
method Error (line 31) | func (e errHTTPRequestFailed) Error() string {
type httpOutbound (line 41) | type httpOutbound struct
method dial (line 82) | func (o *httpOutbound) dial() (net.Conn, error) {
method addrExToRequest (line 97) | func (o *httpOutbound) addrExToRequest(reqAddr *AddrEx) (*http.Request...
method TCP (line 113) | func (o *httpOutbound) TCP(reqAddr *AddrEx) (net.Conn, error) {
method UDP (line 169) | func (o *httpOutbound) UDP(reqAddr *AddrEx) (UDPConn, error) {
function NewHTTPOutbound (line 50) | func NewHTTPOutbound(proxyURL string, insecure bool) (PluggableOutbound,...
type cachedConn (line 175) | type cachedConn struct
method Read (line 180) | func (c *cachedConn) Read(b []byte) (int, error) {
FILE: extras/outbounds/ob_socks5.go
constant socks5NegotiationTimeout (line 15) | socks5NegotiationTimeout = 10 * time.Second
constant socks5RequestTimeout (line 16) | socks5RequestTimeout = 10 * time.Second
type errSOCKS5UnsupportedAuthMethod (line 21) | type errSOCKS5UnsupportedAuthMethod struct
method Error (line 25) | func (e errSOCKS5UnsupportedAuthMethod) Error() string {
type errSOCKS5RequestFailed (line 29) | type errSOCKS5RequestFailed struct
method Error (line 33) | func (e errSOCKS5RequestFailed) Error() string {
type socks5Outbound (line 65) | type socks5Outbound struct
method dialAndNegotiate (line 86) | func (o *socks5Outbound) dialAndNegotiate() (net.Conn, error) {
method request (line 140) | func (o *socks5Outbound) request(conn net.Conn, req *socks5.Request) (...
method TCP (line 160) | func (s *socks5Outbound) TCP(reqAddr *AddrEx) (net.Conn, error) {
method UDP (line 174) | func (s *socks5Outbound) UDP(reqAddr *AddrEx) (UDPConn, error) {
function NewSOCKS5Outbound (line 72) | func NewSOCKS5Outbound(addr, username, password string) PluggableOutbound {
type socks5UDPConn (line 189) | type socks5UDPConn struct
method hold (line 207) | func (c *socks5UDPConn) hold() {
method ReadFrom (line 213) | func (c *socks5UDPConn) ReadFrom(b []byte) (int, *AddrEx, error) {
method WriteTo (line 227) | func (c *socks5UDPConn) WriteTo(b []byte, addr *AddrEx) (int, error) {
method Close (line 237) | func (c *socks5UDPConn) Close() error {
function newSOCKS5UDPConn (line 194) | func newSOCKS5UDPConn(tcpConn net.Conn, udpAddr string) (*socks5UDPConn,...
function addrExToSOCKS5Addr (line 243) | func addrExToSOCKS5Addr(addr *AddrEx) (atyp byte, dstAddr, dstPort []byt...
function socks5AddrToAddrEx (line 264) | func socks5AddrToAddrEx(atyp byte, dstAddr, dstPort []byte) *AddrEx {
FILE: extras/outbounds/speedtest.go
constant SpeedtestDest (line 10) | SpeedtestDest = "@SpeedTest"
type speedtestHandler (line 16) | type speedtestHandler struct
method TCP (line 26) | func (s *speedtestHandler) TCP(reqAddr *AddrEx) (net.Conn, error) {
method UDP (line 34) | func (s *speedtestHandler) UDP(reqAddr *AddrEx) (UDPConn, error) {
function NewSpeedtestHandler (line 20) | func NewSpeedtestHandler(next PluggableOutbound) PluggableOutbound {
FILE: extras/outbounds/speedtest/client.go
type Client (line 11) | type Client struct
method Download (line 18) | func (c *Client) Download(l uint32, cb func(time.Duration, uint32, boo...
method Upload (line 72) | func (c *Client) Upload(l uint32, cb func(time.Duration, uint32, bool)...
FILE: extras/outbounds/speedtest/protocol.go
constant typeDownload (line 10) | typeDownload = 0x1
constant typeUpload (line 11) | typeUpload = 0x2
function readDownloadRequest (line 18) | func readDownloadRequest(r io.Reader) (uint32, error) {
function writeDownloadRequest (line 24) | func writeDownloadRequest(w io.Writer, l uint32) error {
function readDownloadResponse (line 37) | func readDownloadResponse(r io.Reader) (bool, string, error) {
function writeDownloadResponse (line 58) | func writeDownloadResponse(w io.Writer, ok bool, msg string) error {
function readUploadRequest (line 76) | func readUploadRequest(r io.Reader) (uint32, error) {
function writeUploadRequest (line 82) | func writeUploadRequest(w io.Writer, l uint32) error {
function readUploadResponse (line 95) | func readUploadResponse(r io.Reader) (bool, string, error) {
function writeUploadResponse (line 116) | func writeUploadResponse(w io.Writer, ok bool, msg string) error {
function readUploadSummary (line 134) | func readUploadSummary(r io.Reader) (time.Duration, uint32, error) {
function writeUploadSummary (line 146) | func writeUploadSummary(w io.Writer, duration time.Duration, l uint32) e...
FILE: extras/outbounds/speedtest/protocol_test.go
function TestReadDownloadRequest (line 9) | func TestReadDownloadRequest(t *testing.T) {
function TestWriteDownloadRequest (line 50) | func TestWriteDownloadRequest(t *testing.T) {
function TestReadDownloadResponse (line 85) | func TestReadDownloadResponse(t *testing.T) {
function TestWriteDownloadResponse (line 140) | func TestWriteDownloadResponse(t *testing.T) {
function TestReadUploadRequest (line 185) | func TestReadUploadRequest(t *testing.T) {
function TestWriteUploadRequest (line 226) | func TestWriteUploadRequest(t *testing.T) {
function TestReadUploadResponse (line 261) | func TestReadUploadResponse(t *testing.T) {
function TestWriteUploadResponse (line 316) | func TestWriteUploadResponse(t *testing.T) {
function TestReadUploadSummary (line 361) | func TestReadUploadSummary(t *testing.T) {
function TestWriteUploadSummary (line 409) | func TestWriteUploadSummary(t *testing.T) {
FILE: extras/outbounds/speedtest/server.go
constant chunkSize (line 12) | chunkSize = 64 * 1024
function NewServerConn (line 17) | func NewServerConn() net.Conn {
function server (line 24) | func server(conn net.Conn) error {
function handleDownload (line 42) | func handleDownload(conn net.Conn) error {
function handleUpload (line 75) | func handleUpload(conn net.Conn) error {
FILE: extras/outbounds/utils.go
function splitIPv4IPv6 (line 7) | func splitIPv4IPv6(ips []net.IP) (ipv4, ipv6 net.IP) {
function tryParseIP (line 29) | func tryParseIP(addr *AddrEx) bool {
FILE: extras/outbounds/utils_test.go
function TestSplitIPv4IPv6 (line 10) | func TestSplitIPv4IPv6(t *testing.T) {
FILE: extras/sniff/internal/quic/header.go
type Header (line 13) | type Header struct
function ParseInitialHeader (line 24) | func ParseInitialHeader(data []byte) (*Header, int64, error) {
function parseLongHeader (line 34) | func parseLongHeader(b *bytes.Reader) (*Header, error) {
function readConnectionID (line 91) | func readConnectionID(r io.Reader, cid []byte) error {
function beUint32 (line 99) | func beUint32(r io.Reader) (uint32, error) {
FILE: extras/sniff/internal/quic/packet_protector.go
function NewProtectionKey (line 21) | func NewProtectionKey(suite uint16, secret []byte, v uint32) (*Protectio...
function NewInitialProtectionKey (line 29) | func NewInitialProtectionKey(secret []byte, v uint32) (*ProtectionKey, e...
function NewPacketProtector (line 34) | func NewPacketProtector(key *ProtectionKey) *PacketProtector {
type PacketProtector (line 41) | type PacketProtector struct
method UnProtect (line 46) | func (pp *PacketProtector) UnProtect(packet []byte, pnOffset, pnMax in...
type ProtectionKey (line 82) | type ProtectionKey struct
method nonce (line 93) | func (pk *ProtectionKey) nonce(pn int64) []byte {
function newProtectionKey (line 102) | func newProtectionKey(suite uint16, secret []byte, v uint32) (*Protectio...
function decodePacketNumber (line 161) | func decodePacketNumber(largest, truncated int64, nbits uint8) int64 {
function hkdfExpandLabel (line 177) | func hkdfExpandLabel(hash func() hash.Hash, secret []byte, label string,...
FILE: extras/sniff/internal/quic/packet_protector_test.go
function TestInitialPacketProtector_UnProtect (line 15) | func TestInitialPacketProtector_UnProtect(t *testing.T) {
function TestPacketProtectorShortHeader_UnProtect (line 55) | func TestPacketProtectorShortHeader_UnProtect(t *testing.T) {
function mustHexDecodeString (line 79) | func mustHexDecodeString(s string) []byte {
function normalizeHex (line 87) | func normalizeHex(s string) string {
FILE: extras/sniff/internal/quic/payload.go
function ReadCryptoPayload (line 15) | func ReadCryptoPayload(packet []byte) ([]byte, error) {
constant paddingFrameType (line 57) | paddingFrameType = 0x00
constant pingFrameType (line 58) | pingFrameType = 0x01
constant cryptoFrameType (line 59) | cryptoFrameType = 0x06
type cryptoFrame (line 62) | type cryptoFrame struct
function extractCryptoFrames (line 67) | func extractCryptoFrames(r *bytes.Reader) ([]cryptoFrame, error) {
function assembleCryptoFrames (line 101) | func assembleCryptoFrames(frames []cryptoFrame) []byte {
FILE: extras/sniff/internal/quic/quic.go
constant V1 (line 4) | V1 uint32 = 0x1
constant V2 (line 5) | V2 uint32 = 0x6b3343cf
constant hkdfLabelKeyV1 (line 7) | hkdfLabelKeyV1 = "quic key"
constant hkdfLabelKeyV2 (line 8) | hkdfLabelKeyV2 = "quicv2 key"
constant hkdfLabelIVV1 (line 9) | hkdfLabelIVV1 = "quic iv"
constant hkdfLabelIVV2 (line 10) | hkdfLabelIVV2 = "quicv2 iv"
constant hkdfLabelHPV1 (line 11) | hkdfLabelHPV1 = "quic hp"
constant hkdfLabelHPV2 (line 12) | hkdfLabelHPV2 = "quicv2 hp"
function isLongHeader (line 24) | func isLongHeader(b byte) bool {
function getSalt (line 28) | func getSalt(v uint32) []byte {
function keyLabel (line 38) | func keyLabel(v uint32) string {
function ivLabel (line 46) | func ivLabel(v uint32) string {
function headerProtectionLabel (line 54) | func headerProtectionLabel(v uint32) string {
FILE: extras/sniff/mock_Stream.go
type mockStream (line 15) | type mockStream struct
method EXPECT (line 23) | func (_m *mockStream) EXPECT() *mockStream_Expecter {
method CancelRead (line 28) | func (_m *mockStream) CancelRead(_a0 qerr.StreamErrorCode) {
method CancelWrite (line 61) | func (_m *mockStream) CancelWrite(_a0 qerr.StreamErrorCode) {
method Close (line 94) | func (_m *mockStream) Close() error {
method Context (line 139) | func (_m *mockStream) Context() context.Context {
method Read (line 186) | func (_m *mockStream) Read(p []byte) (int, error) {
method SetDeadline (line 242) | func (_m *mockStream) SetDeadline(t time.Time) error {
method SetReadDeadline (line 288) | func (_m *mockStream) SetReadDeadline(t time.Time) error {
method SetWriteDeadline (line 334) | func (_m *mockStream) SetWriteDeadline(t time.Time) error {
method StreamID (line 380) | func (_m *mockStream) StreamID() qerr.StreamID {
method Write (line 425) | func (_m *mockStream) Write(p []byte) (int, error) {
type mockStream_Expecter (line 19) | type mockStream_Expecter struct
method CancelRead (line 39) | func (_e *mockStream_Expecter) CancelRead(_a0 interface{}) *mockStream...
method CancelWrite (line 72) | func (_e *mockStream_Expecter) CancelWrite(_a0 interface{}) *mockStrea...
method Close (line 117) | func (_e *mockStream_Expecter) Close() *mockStream_Close_Call {
method Context (line 164) | func (_e *mockStream_Expecter) Context() *mockStream_Context_Call {
method Read (line 220) | func (_e *mockStream_Expecter) Read(p interface{}) *mockStream_Read_Ca...
method SetDeadline (line 266) | func (_e *mockStream_Expecter) SetDeadline(t interface{}) *mockStream_...
method SetReadDeadline (line 312) | func (_e *mockStream_Expecter) SetReadDeadline(t interface{}) *mockStr...
method SetWriteDeadline (line 358) | func (_e *mockStream_Expecter) SetWriteDeadline(t interface{}) *mockSt...
method StreamID (line 403) | func (_e *mockStream_Expecter) StreamID() *mockStream_StreamID_Call {
method Write (line 459) | func (_e *mockStream_Expecter) Write(p interface{}) *mockStream_Write_...
type mockStream_CancelRead_Call (line 33) | type mockStream_CancelRead_Call struct
method Run (line 43) | func (_c *mockStream_CancelRead_Call) Run(run func(_a0 qerr.StreamErro...
method Return (line 50) | func (_c *mockStream_CancelRead_Call) Return() *mockStream_CancelRead_...
method RunAndReturn (line 55) | func (_c *mockStream_CancelRead_Call) RunAndReturn(run func(qerr.Strea...
type mockStream_CancelWrite_Call (line 66) | type mockStream_CancelWrite_Call struct
method Run (line 76) | func (_c *mockStream_CancelWrite_Call) Run(run func(_a0 qerr.StreamErr...
method Return (line 83) | func (_c *mockStream_CancelWrite_Call) Return() *mockStream_CancelWrit...
method RunAndReturn (line 88) | func (_c *mockStream_CancelWrite_Call) RunAndReturn(run func(qerr.Stre...
type mockStream_Close_Call (line 112) | type mockStream_Close_Call struct
method Run (line 121) | func (_c *mockStream_Close_Call) Run(run func()) *mockStream_Close_Call {
method Return (line 128) | func (_c *mockStream_Close_Call) Return(_a0 error) *mockStream_Close_C...
method RunAndReturn (line 133) | func (_c *mockStream_Close_Call) RunAndReturn(run func() error) *mockS...
type mockStream_Context_Call (line 159) | type mockStream_Context_Call struct
method Run (line 168) | func (_c *mockStream_Context_Call) Run(run func()) *mockStream_Context...
method Return (line 175) | func (_c *mockStream_Context_Call) Return(_a0 context.Context) *mockSt...
method RunAndReturn (line 180) | func (_c *mockStream_Context_Call) RunAndReturn(run func() context.Con...
type mockStream_Read_Call (line 214) | type mockStream_Read_Call struct
method Run (line 224) | func (_c *mockStream_Read_Call) Run(run func(p []byte)) *mockStream_Re...
method Return (line 231) | func (_c *mockStream_Read_Call) Return(n int, err error) *mockStream_R...
method RunAndReturn (line 236) | func (_c *mockStream_Read_Call) RunAndReturn(run func([]byte) (int, er...
type mockStream_SetDeadline_Call (line 260) | type mockStream_SetDeadline_Call struct
method Run (line 270) | func (_c *mockStream_SetDeadline_Call) Run(run func(t time.Time)) *moc...
method Return (line 277) | func (_c *mockStream_SetDeadline_Call) Return(_a0 error) *mockStream_S...
method RunAndReturn (line 282) | func (_c *mockStream_SetDeadline_Call) RunAndReturn(run func(time.Time...
type mockStream_SetReadDeadline_Call (line 306) | type mockStream_SetReadDeadline_Call struct
method Run (line 316) | func (_c *mockStream_SetReadDeadline_Call) Run(run func(t time.Time)) ...
method Return (line 323) | func (_c *mockStream_SetReadDeadline_Call) Return(_a0 error) *mockStre...
method RunAndReturn (line 328) | func (_c *mockStream_SetReadDeadline_Call) RunAndReturn(run func(time....
type mockStream_SetWriteDeadline_Call (line 352) | type mockStream_SetWriteDeadline_Call struct
method Run (line 362) | func (_c *mockStream_SetWriteDeadline_Call) Run(run func(t time.Time))...
method Return (line 369) | func (_c *mockStream_SetWriteDeadline_Call) Return(_a0 error) *mockStr...
method RunAndReturn (line 374) | func (_c *mockStream_SetWriteDeadline_Call) RunAndReturn(run func(time...
type mockStream_StreamID_Call (line 398) | type mockStream_StreamID_Call struct
method Run (line 407) | func (_c *mockStream_StreamID_Call) Run(run func()) *mockStream_Stream...
method Return (line 414) | func (_c *mockStream_StreamID_Call) Return(_a0 qerr.StreamID) *mockStr...
method RunAndReturn (line 419) | func (_c *mockStream_StreamID_Call) RunAndReturn(run func() qerr.Strea...
type mockStream_Write_Call (line 453) | type mockStream_Write_Call struct
method Run (line 463) | func (_c *mockStream_Write_Call) Run(run func(p []byte)) *mockStream_W...
method Return (line 470) | func (_c *mockStream_Write_Call) Return(n int, err error) *mockStream_...
method RunAndReturn (line 475) | func (_c *mockStream_Write_Call) RunAndReturn(run func([]byte) (int, e...
function newMockStream (line 482) | func newMockStream(t interface {
FILE: extras/sniff/sniff.go
constant sniffDefaultTimeout (line 21) | sniffDefaultTimeout = 4 * time.Second
type Sniffer (line 31) | type Sniffer struct
method isDomain (line 38) | func (h *Sniffer) isDomain(addr string) bool {
method isHTTP (line 46) | func (h *Sniffer) isHTTP(buf []byte) bool {
method isTLS (line 59) | func (h *Sniffer) isTLS(buf []byte) bool {
method Check (line 67) | func (h *Sniffer) Check(isUDP bool, reqAddr string) bool {
method TCP (line 91) | func (h *Sniffer) TCP(stream quic.Stream, reqAddr *string) ([]byte, er...
method UDP (line 159) | func (h *Sniffer) UDP(data []byte, reqAddr *string) error {
type teeReader (line 176) | type teeReader struct
method Read (line 183) | func (c *teeReader) Read(b []byte) (n int, err error) {
method Buffer (line 197) | func (c *teeReader) Buffer() []byte {
FILE: extras/sniff/sniff_test.go
function TestSnifferCheck (line 15) | func TestSnifferCheck(t *testing.T) {
function TestSnifferTCP (line 38) | func TestSnifferTCP(t *testing.T) {
function TestSnifferUDP (line 127) | func TestSnifferUDP(t *testing.T) {
FILE: extras/trafficlogger/http.go
constant indexHTML (line 17) | indexHTML = `<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"...
type TrafficStatsServer (line 22) | type TrafficStatsServer interface
function NewTrafficStatsServer (line 27) | func NewTrafficStatsServer(secret string) TrafficStatsServer {
type TrafficPushRequest (line 36) | type TrafficPushRequest struct
type trafficStatsServerImpl (line 87) | type trafficStatsServerImpl struct
method PushTrafficToV2boardInterval (line 41) | func (s *trafficStatsServerImpl) PushTrafficToV2boardInterval(url stri...
method PushTrafficToV2board (line 56) | func (s *trafficStatsServerImpl) PushTrafficToV2board(url string) error {
method LogTraffic (line 100) | func (s *trafficStatsServerImpl) LogTraffic(id string, tx, rx uint64) ...
method LogOnlineState (line 122) | func (s *trafficStatsServerImpl) LogOnlineState(id string, online bool) {
method ServeHTTP (line 136) | func (s *trafficStatsServerImpl) ServeHTTP(w http.ResponseWriter, r *h...
method getTraffic (line 160) | func (s *trafficStatsServerImpl) getTraffic(w http.ResponseWriter, r *...
method getOnline (line 182) | func (s *trafficStatsServerImpl) getOnline(w http.ResponseWriter, r *h...
method kick (line 195) | func (s *trafficStatsServerImpl) kick(w http.ResponseWriter, r *http.R...
method NewKick (line 212) | func (s *trafficStatsServerImpl) NewKick(id string) bool {
type trafficStatsEntry (line 95) | type trafficStatsEntry struct
FILE: extras/transport/udphop/addr.go
type InvalidPortError (line 10) | type InvalidPortError struct
method Error (line 14) | func (e InvalidPortError) Error() string {
type UDPHopAddr (line 19) | type UDPHopAddr struct
method Network (line 25) | func (a *UDPHopAddr) Network() string {
method String (line 29) | func (a *UDPHopAddr) String() string {
method addrs (line 34) | func (a *UDPHopAddr) addrs() ([]net.Addr, error) {
function ResolveUDPHopAddr (line 46) | func ResolveUDPHopAddr(addr string) (*UDPHopAddr, error) {
FILE: extras/transport/udphop/conn.go
constant packetQueueSize (line 13) | packetQueueSize = 1024
constant udpBufferSize (line 14) | udpBufferSize = 2048
constant defaultHopInterval (line 16) | defaultHopInterval = 30 * time.Second
type udpHopPacketConn (line 19) | type udpHopPacketConn struct
method recvLoop (line 89) | func (u *udpHopPacketConn) recvLoop(conn net.PacketConn) {
method hopLoop (line 114) | func (u *udpHopPacketConn) hopLoop() {
method hop (line 127) | func (u *udpHopPacketConn) hop() {
method ReadFrom (line 163) | func (u *udpHopPacketConn) ReadFrom(b []byte) (n int, addr net.Addr, e...
method WriteTo (line 181) | func (u *udpHopPacketConn) WriteTo(b []byte, addr net.Addr) (n int, er...
method Close (line 192) | func (u *udpHopPacketConn) Close() error {
method LocalAddr (line 211) | func (u *udpHopPacketConn) LocalAddr() net.Addr {
method SetDeadline (line 217) | func (u *udpHopPacketConn) SetDeadline(t time.Time) error {
method SetReadDeadline (line 226) | func (u *udpHopPacketConn) SetReadDeadline(t time.Time) error {
method SetWriteDeadline (line 235) | func (u *udpHopPacketConn) SetWriteDeadline(t time.Time) error {
method SetReadBuffer (line 246) | func (u *udpHopPacketConn) SetReadBuffer(bytes int) error {
method SetWriteBuffer (line 256) | func (u *udpHopPacketConn) SetWriteBuffer(bytes int) error {
method SyscallConn (line 266) | func (u *udpHopPacketConn) SyscallConn() (syscall.RawConn, error) {
type udpPacket (line 40) | type udpPacket struct
function NewUDPHopPacketConn (line 49) | func NewUDPHopPacketConn(addr *UDPHopAddr, hopInterval time.Duration, li...
function trySetReadBuffer (line 276) | func trySetReadBuffer(pc net.PacketConn, bytes int) error {
function trySetWriteBuffer (line 286) | func trySetWriteBuffer(pc net.PacketConn, bytes int) error {
FILE: extras/utils/portunion.go
type PortUnion (line 10) | type PortUnion
method Normalize (line 64) | func (u PortUnion) Normalize() PortUnion {
method Ports (line 89) | func (u PortUnion) Ports() []uint16 {
method Contains (line 100) | func (u PortUnion) Contains(port uint16) bool {
type PortRange (line 14) | type PortRange struct
function ParsePortUnion (line 21) | func ParsePortUnion(s string) PortUnion {
FILE: extras/utils/portunion_test.go
function TestParsePortUnion (line 8) | func TestParsePortUnion(t *testing.T) {
FILE: hyperbole.py
function check_command (line 80) | def check_command(args):
function check_build_env (line 90) | def check_build_env():
function get_app_version (line 103) | def get_app_version():
function get_app_version_code (line 120) | def get_app_version_code(str=None):
function get_app_commit (line 136) | def get_app_commit():
function get_current_os_arch (line 148) | def get_current_os_arch():
function get_app_platforms (line 154) | def get_app_platforms():
function cmd_build (line 172) | def cmd_build(pprof=False, release=False, race=False):
function cmd_run (line 265) | def cmd_run(args, pprof=False, race=False):
function cmd_format (line 308) | def cmd_format():
function cmd_mockgen (line 319) | def cmd_mockgen():
function cmd_protogen (line 334) | def cmd_protogen():
function cmd_tidy (line 355) | def cmd_tidy():
function cmd_test (line 373) | def cmd_test(module=None):
function cmd_publish (line 392) | def cmd_publish(urgent=False):
function cmd_clean (line 423) | def cmd_clean():
function cmd_about (line 427) | def cmd_about():
function main (line 432) | def main():
Condensed preview — 211 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,019K chars).
[
{
"path": ".github/FUNDING.yml",
"chars": 57,
"preview": "custom: [ 'https://v2.hysteria.network/docs/Donation/' ]\n"
},
{
"path": ".github/ISSUE_TEMPLATE/bug_report.md",
"chars": 536,
"preview": "---\nname: Bug report\nabout: Report anything you think is a bug and needs to be fixed.\ntitle: ''\nlabels: bug\nassignees: '"
},
{
"path": ".github/ISSUE_TEMPLATE/bug_report.zh.md",
"chars": 245,
"preview": "---\nname: Bug 反馈\nabout: 反馈任何你认为是 bug 需要修复的问题。\ntitle: ''\nlabels: bug\nassignees: ''\n\n---\n\n**描述问题**\n请尽量清晰精准地描述你遇到的问题。\n\n**如何"
},
{
"path": ".github/ISSUE_TEMPLATE/feature_request.md",
"chars": 605,
"preview": "---\nname: Feature request\nabout: Suggest an idea for this project.\ntitle: ''\nlabels: enhancement\nassignees: ''\n\n---\n\n**I"
},
{
"path": ".github/ISSUE_TEMPLATE/feature_request.zh.md",
"chars": 279,
"preview": "---\nname: 功能请求\nabout: 为这个项目提出改进意见。\ntitle: ''\nlabels: enhancement\nassignees: ''\n\n---\n\n**你的功能请求是否与某个问题有关?**\n请尽量清晰精准地描述你遇到的"
},
{
"path": ".github/dependabot.yml",
"chars": 204,
"preview": "version: 2\nupdates:\n - package-ecosystem: \"gomod\"\n directory: \"/\"\n schedule:\n interval: \"daily\"\n - package-"
},
{
"path": ".github/workflows/autotag.yaml",
"chars": 3552,
"preview": "name: \"Create release tags for nested modules\"\n\non:\n push:\n tags:\n - app/v*.*.*\n\npermissions:\n contents: write"
},
{
"path": ".github/workflows/docker.yml",
"chars": 3086,
"preview": "name: Docker\n\n# This workflow uses actions that are not certified by GitHub.\n# They are provided by a third-party and ar"
},
{
"path": ".github/workflows/master.yml",
"chars": 1188,
"preview": "name: \"Build master branch\"\n\non:\n push:\n branches:\n - master\n\njobs:\n build:\n name: Build\n runs-on: ubunt"
},
{
"path": ".github/workflows/release.yml",
"chars": 1947,
"preview": "name: \"Build release\"\n\non:\n push:\n tags:\n - app/v*.*.*\n\njobs:\n build:\n name: Build\n runs-on: ubuntu-late"
},
{
"path": ".github/workflows/scripts.yml",
"chars": 668,
"preview": "name: \"Publish scripts\"\n\non:\n push:\n branches:\n - master\n paths:\n - scripts/**\n\njobs:\n publish:\n ru"
},
{
"path": ".gitignore",
"chars": 9265,
"preview": "# Created by https://www.toptal.com/developers/gitignore/api/goland+all,intellij+all,go,windows,linux,macos,python,pycha"
},
{
"path": "CHANGELOG.md",
"chars": 57,
"preview": "# Changelog\n\nhttps://v2.hysteria.network/docs/Changelog/\n"
},
{
"path": "Dockerfile",
"chars": 1339,
"preview": "FROM golang:1-alpine AS builder\n\n# GOPROXY is disabled by default, use:\n# docker build --build-arg GOPROXY=\"https://gopr"
},
{
"path": "LICENSE.md",
"chars": 1044,
"preview": "Copyright 2023 Toby\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and a"
},
{
"path": "PROTOCOL.md",
"chars": 8028,
"preview": "# Hysteria 2 Protocol Specification\n\nHysteria is a TCP & UDP proxy based on QUIC, designed for speed, security and censo"
},
{
"path": "README.md",
"chars": 973,
"preview": "# \n\n# 支持对接V2board面板的Hysteria2后端\n\n### 项目说明\n本项目基于hysteria官方内核二次开发,添加了从v2b获取节点信息、用户鉴权信息与上报用户流量的功能。\n性"
},
{
"path": "app/cmd/client.go",
"chars": 31445,
"preview": "package cmd\n\nimport (\n\t\"crypto/sha256\"\n\t\"crypto/x509\"\n\t\"encoding/hex\"\n\t\"errors\"\n\t\"fmt\"\n\t\"net\"\n\t\"net/netip\"\n\t\"os\"\n\t\"os/si"
},
{
"path": "app/cmd/client_test.go",
"chars": 4790,
"preview": "package cmd\n\nimport (\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/stretchr/testify/assert\"\n\n\t\"github.com/spf13/viper\"\n)\n\n// TestCli"
},
{
"path": "app/cmd/client_test.yaml",
"chars": 1386,
"preview": "server: example.com\n\nauth: weak_ahh_password\n\ntransport:\n type: udp\n udp:\n hopInterval: 30s\n\nobfs:\n type: salamand"
},
{
"path": "app/cmd/errors.go",
"chars": 245,
"preview": "package cmd\n\nimport (\n\t\"fmt\"\n)\n\ntype configError struct {\n\tField string\n\tErr error\n}\n\nfunc (e configError) Error() str"
},
{
"path": "app/cmd/ping.go",
"chars": 1577,
"preview": "package cmd\n\nimport (\n\t\"time\"\n\n\t\"github.com/spf13/cobra\"\n\t\"github.com/spf13/viper\"\n\t\"go.uber.org/zap\"\n\n\t\"github.com/aper"
},
{
"path": "app/cmd/root.go",
"chars": 4509,
"preview": "package cmd\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/spf13/cobra\"\n\t\"github.com/spf13/viper\"\n\t\"go.uber."
},
{
"path": "app/cmd/server.go",
"chars": 38215,
"preview": "package cmd\n\nimport (\n\t\"context\"\n\t\"crypto/tls\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"net\"\n\t\"net/http\"\n\t\"net/http/htt"
},
{
"path": "app/cmd/server_test.go",
"chars": 4359,
"preview": "package cmd\n\nimport (\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/stretchr/testify/assert\"\n\n\t\"github.com/spf13/viper\"\n)\n\n// TestSer"
},
{
"path": "app/cmd/server_test.yaml",
"chars": 2377,
"preview": "listen: :8443\n\nobfs:\n type: salamander\n salamander:\n password: cry_me_a_r1ver\n\ntls:\n cert: some.crt\n key: some.ke"
},
{
"path": "app/cmd/share.go",
"chars": 1153,
"preview": "package cmd\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/apernet/hysteria/app/v2/internal/utils\"\n\t\"github.com/spf13/cobra\"\n\t\"github.co"
},
{
"path": "app/cmd/speedtest.go",
"chars": 4907,
"preview": "package cmd\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"os\"\n\t\"os/signal\"\n\t\"syscall\"\n\t\"time\"\n\n\t\"github.com/spf13/cobra\"\n\t\"github.com/spf"
},
{
"path": "app/cmd/update.go",
"chars": 2298,
"preview": "package cmd\n\nimport (\n\t\"time\"\n\n\t\"github.com/spf13/cobra\"\n\t\"go.uber.org/zap\"\n\n\t\"github.com/apernet/hysteria/app/v2/intern"
},
{
"path": "app/cmd/version.go",
"chars": 359,
"preview": "package cmd\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/spf13/cobra\"\n)\n\n// versionCmd represents the version command\nvar versionCmd ="
},
{
"path": "app/go.mod",
"chars": 3907,
"preview": "module github.com/apernet/hysteria/app/v2\n\ngo 1.22\n\ntoolchain go1.23.2\n\nrequire (\n\tgithub.com/apernet/go-tproxy v0.0.0-2"
},
{
"path": "app/go.sum",
"chars": 64004,
"preview": "cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=\ncloud.google.com/go v0.34.0/go.mod h1"
},
{
"path": "app/internal/forwarding/tcp.go",
"chars": 1050,
"preview": "package forwarding\n\nimport (\n\t\"io\"\n\t\"net\"\n\n\t\"github.com/apernet/hysteria/core/v2/client\"\n)\n\ntype TCPTunnel struct {\n\tHyC"
},
{
"path": "app/internal/forwarding/tcp_test.go",
"chars": 746,
"preview": "package forwarding\n\nimport (\n\t\"crypto/rand\"\n\t\"net\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\n\t\"github.com/apern"
},
{
"path": "app/internal/forwarding/udp.go",
"chars": 3636,
"preview": "package forwarding\n\nimport (\n\t\"net\"\n\t\"sync\"\n\t\"sync/atomic\"\n\t\"time\"\n\n\t\"github.com/apernet/hysteria/core/v2/client\"\n)\n\ncon"
},
{
"path": "app/internal/forwarding/udp_test.go",
"chars": 752,
"preview": "package forwarding\n\nimport (\n\t\"crypto/rand\"\n\t\"net\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\n\t\"github.com/apern"
},
{
"path": "app/internal/http/server.go",
"chars": 7955,
"preview": "package http\n\nimport (\n\t\"bufio\"\n\t\"bytes\"\n\t\"context\"\n\t\"encoding/base64\"\n\t\"fmt\"\n\t\"io\"\n\t\"net\"\n\t\"net/http\"\n\t\"strings\"\n\t\"time"
},
{
"path": "app/internal/http/server_test.go",
"chars": 1319,
"preview": "package http\n\nimport (\n\t\"errors\"\n\t\"net\"\n\t\"net/http\"\n\t\"os/exec\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/asse"
},
{
"path": "app/internal/http/server_test.py",
"chars": 582,
"preview": "import requests\n\nproxies = {\n \"http\": \"http://127.0.0.1:18080\",\n \"https\": \"http://127.0.0.1:18080\",\n}\n\n\ndef test_h"
},
{
"path": "app/internal/http/test.crt",
"chars": 1363,
"preview": "-----BEGIN CERTIFICATE-----\nMIIDwTCCAqmgAwIBAgIUMeefneiCXWS2ovxNN+fJcdrOIfAwDQYJKoZIhvcNAQEL\nBQAwcDELMAkGA1UEBhMCVFcxEzA"
},
{
"path": "app/internal/http/test.key",
"chars": 1675,
"preview": "-----BEGIN RSA PRIVATE KEY-----\nMIIEowIBAAKCAQEA5T3/gBP/p8MrITJkwwsXNQRULxkMkegpn7eDrlkVAvFEqqUR\n2G87CrhmzFgXSxx5Q8MCx2t"
},
{
"path": "app/internal/proxymux/.mockery.yaml",
"chars": 209,
"preview": "with-expecter: true\ndir: internal/mocks\noutpkg: mocks\npackages:\n net:\n interfaces:\n Listener:\n config:\n "
},
{
"path": "app/internal/proxymux/internal/mocks/mock_Conn.go",
"chars": 10390,
"preview": "// Code generated by mockery v2.43.0. DO NOT EDIT.\n\npackage mocks\n\nimport (\n\tnet \"net\"\n\n\tmock \"github.com/stretchr/testi"
},
{
"path": "app/internal/proxymux/internal/mocks/mock_Listener.go",
"chars": 4297,
"preview": "// Code generated by mockery v2.43.0. DO NOT EDIT.\n\npackage mocks\n\nimport (\n\tnet \"net\"\n\n\tmock \"github.com/stretchr/testi"
},
{
"path": "app/internal/proxymux/manager.go",
"chars": 1346,
"preview": "package proxymux\n\nimport (\n\t\"net\"\n\t\"sync\"\n\n\t\"github.com/apernet/hysteria/extras/v2/correctnet\"\n)\n\ntype muxManager struct"
},
{
"path": "app/internal/proxymux/manager_test.go",
"chars": 1789,
"preview": "package proxymux\n\nimport (\n\t\"net\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestListenSOCKS(t *t"
},
{
"path": "app/internal/proxymux/mux.go",
"chars": 5951,
"preview": "package proxymux\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"net\"\n\t\"sync\"\n)\n\nfunc newMuxListener(listener net.Listener, deleteFun"
},
{
"path": "app/internal/proxymux/mux_test.go",
"chars": 3047,
"preview": "package proxymux\n\nimport (\n\t\"bytes\"\n\t\"net\"\n\t\"sync\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/apernet/hysteria/app/v2/internal/pro"
},
{
"path": "app/internal/redirect/getsockopt_linux.go",
"chars": 328,
"preview": "//go:build !386\n// +build !386\n\npackage redirect\n\nimport (\n\t\"syscall\"\n\t\"unsafe\"\n)\n\nfunc getsockopt(s, level, name uintpt"
},
{
"path": "app/internal/redirect/getsockopt_linux_386.go",
"chars": 551,
"preview": "package redirect\n\nimport (\n\t\"syscall\"\n\t\"unsafe\"\n)\n\nconst (\n\tsysGetsockopt = 15\n)\n\n// On 386 we cannot call socketcall wi"
},
{
"path": "app/internal/redirect/syscall_socketcall_linux_386.s",
"chars": 122,
"preview": "//go:build gc\n// +build gc\n\n#include \"textflag.h\"\n\nTEXT ·syscall_socketcall(SB),NOSPLIT,$0-36\n\tJMP\tsyscall·socketcall(SB"
},
{
"path": "app/internal/redirect/tcp_linux.go",
"chars": 2737,
"preview": "package redirect\n\nimport (\n\t\"encoding/binary\"\n\t\"errors\"\n\t\"io\"\n\t\"net\"\n\t\"syscall\"\n\t\"unsafe\"\n\n\t\"github.com/apernet/hysteria"
},
{
"path": "app/internal/redirect/tcp_others.go",
"chars": 427,
"preview": "//go:build !linux\n\npackage redirect\n\nimport (\n\t\"errors\"\n\t\"net\"\n\n\t\"github.com/apernet/hysteria/core/v2/client\"\n)\n\ntype TC"
},
{
"path": "app/internal/sockopts/fd_control_unix_socket_test.py",
"chars": 1981,
"preview": "import socket\nimport array\nimport os\nimport struct\nimport sys\n\n\ndef serve(path):\n try:\n os.unlink(path)\n ex"
},
{
"path": "app/internal/sockopts/sockopts.go",
"chars": 1900,
"preview": "package sockopts\n\nimport (\n\t\"fmt\"\n\t\"net\"\n)\n\ntype SocketOptions struct {\n\tBindInterface *string\n\tFirewallMark "
},
{
"path": "app/internal/sockopts/sockopts_linux.go",
"chars": 2300,
"preview": "//go:build linux\n\npackage sockopts\n\nimport (\n\t\"fmt\"\n\t\"net\"\n\t\"time\"\n\n\t\"golang.org/x/exp/constraints\"\n\t\"golang.org/x/sys/u"
},
{
"path": "app/internal/sockopts/sockopts_linux_test.go",
"chars": 1105,
"preview": "//go:build linux\n\npackage sockopts\n\nimport (\n\t\"net\"\n\t\"os\"\n\t\"os/exec\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/stretchr/testify/a"
},
{
"path": "app/internal/socks5/server.go",
"chars": 7616,
"preview": "package socks5\n\nimport (\n\t\"encoding/binary\"\n\t\"io\"\n\t\"net\"\n\n\t\"github.com/txthinking/socks5\"\n\n\t\"github.com/apernet/hysteria"
},
{
"path": "app/internal/socks5/server_test.go",
"chars": 581,
"preview": "package socks5\n\nimport (\n\t\"net\"\n\t\"os/exec\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\n\t\"github.com/ap"
},
{
"path": "app/internal/socks5/server_test.py",
"chars": 1423,
"preview": "import socket\nimport socks\nimport os\n\nADDR = \"127.0.0.1\"\nPORT = 11080\n\n\ndef test_tcp(size, count, it, domain=False):\n "
},
{
"path": "app/internal/tproxy/tcp_linux.go",
"chars": 1411,
"preview": "package tproxy\n\nimport (\n\t\"io\"\n\t\"net\"\n\n\t\"github.com/apernet/go-tproxy\"\n\t\"github.com/apernet/hysteria/core/v2/client\"\n)\n\n"
},
{
"path": "app/internal/tproxy/tcp_others.go",
"chars": 421,
"preview": "//go:build !linux\n\npackage tproxy\n\nimport (\n\t\"errors\"\n\t\"net\"\n\n\t\"github.com/apernet/hysteria/core/v2/client\"\n)\n\ntype TCPT"
},
{
"path": "app/internal/tproxy/udp_linux.go",
"chars": 3085,
"preview": "package tproxy\n\nimport (\n\t\"errors\"\n\t\"net\"\n\t\"time\"\n\n\t\"github.com/apernet/go-tproxy\"\n\t\"github.com/apernet/hysteria/core/v2"
},
{
"path": "app/internal/tproxy/udp_others.go",
"chars": 456,
"preview": "//go:build !linux\n\npackage tproxy\n\nimport (\n\t\"errors\"\n\t\"net\"\n\t\"time\"\n\n\t\"github.com/apernet/hysteria/core/v2/client\"\n)\n\nt"
},
{
"path": "app/internal/tun/log.go",
"chars": 1450,
"preview": "package tun\n\nimport (\n\t\"github.com/sagernet/sing/common/logger\"\n\t\"go.uber.org/zap\"\n)\n\nvar _ logger.Logger = (*singLogger"
},
{
"path": "app/internal/tun/server.go",
"chars": 5117,
"preview": "package tun\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"io\"\n\t\"net\"\n\t\"net/netip\"\n\n\ttun \"github.com/apernet/sing-tun\"\n\t\"github.com/sager"
},
{
"path": "app/internal/url/url.go",
"chars": 35743,
"preview": "// Copyright 2009 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "app/internal/url/url_test.go",
"chars": 1760,
"preview": "package url\n\nimport (\n\t\"reflect\"\n\t\"testing\"\n)\n\nfunc TestParse(t *testing.T) {\n\ttype args struct {\n\t\trawURL string\n\t}\n\tte"
},
{
"path": "app/internal/utils/bpsconv.go",
"chars": 1549,
"preview": "package utils\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"strconv\"\n\t\"strings\"\n)\n\nconst (\n\tByte = 1\n\tKilobyte = Byte * 1000\n\tMegabyt"
},
{
"path": "app/internal/utils/bpsconv_test.go",
"chars": 1088,
"preview": "package utils\n\nimport \"testing\"\n\nfunc TestStringToBps(t *testing.T) {\n\ttype args struct {\n\t\ts string\n\t}\n\ttests := []stru"
},
{
"path": "app/internal/utils/certloader.go",
"chars": 4510,
"preview": "package utils\n\nimport (\n\t\"crypto/tls\"\n\t\"crypto/x509\"\n\t\"fmt\"\n\t\"net\"\n\t\"os\"\n\t\"strings\"\n\t\"sync\"\n\t\"sync/atomic\"\n\t\"time\"\n)\n\nty"
},
{
"path": "app/internal/utils/certloader_test.go",
"chars": 3400,
"preview": "package utils\n\nimport (\n\t\"crypto/tls\"\n\t\"log\"\n\t\"net/http\"\n\t\"os\"\n\t\"os/exec\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/stretchr/t"
},
{
"path": "app/internal/utils/certloader_test_gencert.py",
"chars": 5499,
"preview": "import argparse\nimport datetime\nfrom cryptography import x509\nfrom cryptography.x509.oid import NameOID\nfrom cryptograph"
},
{
"path": "app/internal/utils/certloader_test_tlsclient.py",
"chars": 2009,
"preview": "import argparse\nimport ssl\nimport socket\nimport sys\n\n\ndef check_tls(server, ca_cert, sni, alpn):\n try:\n host, "
},
{
"path": "app/internal/utils/geoloader.go",
"chars": 3893,
"preview": "package utils\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"os\"\n\t\"time\"\n\n\t\"github.com/apernet/hysteria/extras/v2/outbounds/acl\"\n\t"
},
{
"path": "app/internal/utils/qr.go",
"chars": 267,
"preview": "package utils\n\nimport (\n\t\"os\"\n\n\t\"github.com/mdp/qrterminal/v3\"\n)\n\nfunc PrintQR(str string) {\n\tqrterminal.GenerateWithCon"
},
{
"path": "app/internal/utils/testcerts/.gitignore",
"chars": 90,
"preview": "# This directory is used for certificate generation in certloader_test.go\n/*\n!/.gitignore\n"
},
{
"path": "app/internal/utils/update.go",
"chars": 2522,
"preview": "package utils\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net\"\n\t\"net/http\"\n\t\"time\"\n\n\t\"github.com/apernet/hysteria/cor"
},
{
"path": "app/internal/utils_test/mock.go",
"chars": 1826,
"preview": "package utils_test\n\nimport (\n\t\"io\"\n\t\"net\"\n\t\"time\"\n\n\t\"github.com/apernet/hysteria/core/v2/client\"\n)\n\ntype MockEchoHyClien"
},
{
"path": "app/main.go",
"chars": 94,
"preview": "package main\n\nimport \"github.com/apernet/hysteria/app/v2/cmd\"\n\nfunc main() {\n\tcmd.Execute()\n}\n"
},
{
"path": "app/misc/socks5_test.py",
"chars": 1405,
"preview": "import socket\nimport socks\nimport time\n\nTARGET = \"1.1.1.1\"\n\n\ndef test_tcp() -> None:\n s = socks.socksocket(socket.AF_"
},
{
"path": "app/pprof.go",
"chars": 310,
"preview": "//go:build pprof\n\npackage main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t_ \"net/http/pprof\"\n)\n\nconst (\n\tpprofListenAddr = \":6060\"\n)\n"
},
{
"path": "core/client/.mockery.yaml",
"chars": 174,
"preview": "with-expecter: true\ninpackage: true\ndir: .\npackages:\n github.com/apernet/hysteria/core/v2/client:\n interfaces:\n "
},
{
"path": "core/client/client.go",
"chars": 8110,
"preview": "package client\n\nimport (\n\t\"context\"\n\t\"crypto/tls\"\n\t\"net\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"time\"\n\n\tcoreErrs \"github.com/apernet/h"
},
{
"path": "core/client/config.go",
"chars": 4196,
"preview": "package client\n\nimport (\n\t\"crypto/x509\"\n\t\"net\"\n\t\"time\"\n\n\t\"github.com/apernet/hysteria/core/v2/errors\"\n\t\"github.com/apern"
},
{
"path": "core/client/mock_udpIO.go",
"chars": 3773,
"preview": "// Code generated by mockery v2.43.0. DO NOT EDIT.\n\npackage client\n\nimport (\n\tprotocol \"github.com/apernet/hysteria/core"
},
{
"path": "core/client/reconnect.go",
"chars": 3138,
"preview": "package client\n\nimport (\n\t\"net\"\n\t\"sync\"\n\n\tcoreErrs \"github.com/apernet/hysteria/core/v2/errors\"\n)\n\n// reconnectableClien"
},
{
"path": "core/client/udp.go",
"chars": 3411,
"preview": "package client\n\nimport (\n\t\"errors\"\n\t\"io\"\n\t\"math/rand\"\n\t\"sync\"\n\n\t\"github.com/apernet/quic-go\"\n\n\tcoreErrs \"github.com/aper"
},
{
"path": "core/client/udp_test.go",
"chars": 2940,
"preview": "package client\n\nimport (\n\t\"errors\"\n\tio2 \"io\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/stre"
},
{
"path": "core/errors/errors.go",
"chars": 1590,
"preview": "package errors\n\nimport (\n\t\"fmt\"\n\t\"strconv\"\n)\n\n// ConfigError is returned when a configuration field is invalid.\ntype Con"
},
{
"path": "core/go.mod",
"chars": 1282,
"preview": "module github.com/apernet/hysteria/core/v2\n\ngo 1.22\n\ntoolchain go1.23.2\n\nrequire (\n\tgithub.com/apernet/quic-go v0.47.1-0"
},
{
"path": "core/go.sum",
"chars": 6780,
"preview": "github.com/apernet/quic-go v0.47.1-0.20241004180137-a80d14e2080d h1:KWRCWISqJOgY9/0hhH8Bevjw/k4tCQ7oJlXLyFv8u9s=\ngithub."
},
{
"path": "core/internal/congestion/bbr/bandwidth.go",
"chars": 602,
"preview": "package bbr\n\nimport (\n\t\"math\"\n\t\"time\"\n\n\t\"github.com/apernet/quic-go/congestion\"\n)\n\nconst (\n\tinfBandwidth = Bandwidth(mat"
},
{
"path": "core/internal/congestion/bbr/bandwidth_sampler.go",
"chars": 31585,
"preview": "package bbr\n\nimport (\n\t\"math\"\n\t\"time\"\n\n\t\"github.com/apernet/quic-go/congestion\"\n)\n\nconst (\n\tinfRTT "
},
{
"path": "core/internal/congestion/bbr/bbr_sender.go",
"chars": 33439,
"preview": "package bbr\n\nimport (\n\t\"fmt\"\n\t\"math/rand\"\n\t\"net\"\n\t\"os\"\n\t\"strconv\"\n\t\"time\"\n\n\t\"github.com/apernet/quic-go/congestion\"\n\n\t\"g"
},
{
"path": "core/internal/congestion/bbr/clock.go",
"chars": 327,
"preview": "package bbr\n\nimport \"time\"\n\n// A Clock returns the current time\ntype Clock interface {\n\tNow() time.Time\n}\n\n// DefaultClo"
},
{
"path": "core/internal/congestion/bbr/packet_number_indexed_queue.go",
"chars": 5684,
"preview": "package bbr\n\nimport (\n\t\"github.com/apernet/quic-go/congestion\"\n)\n\n// packetNumberIndexedQueue is a queue of mostly conti"
},
{
"path": "core/internal/congestion/bbr/ringbuffer.go",
"chars": 3225,
"preview": "package bbr\n\n// A RingBuffer is a ring buffer.\n// It acts as a heap that doesn't cause any allocations.\ntype RingBuffer["
},
{
"path": "core/internal/congestion/bbr/windowed_filter.go",
"chars": 5609,
"preview": "package bbr\n\nimport (\n\t\"golang.org/x/exp/constraints\"\n)\n\n// Implements Kathleen Nichols' algorithm for tracking the mini"
},
{
"path": "core/internal/congestion/brutal/brutal.go",
"chars": 5435,
"preview": "package brutal\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"strconv\"\n\t\"time\"\n\n\t\"github.com/apernet/hysteria/core/v2/internal/congestion/comm"
},
{
"path": "core/internal/congestion/common/pacer.go",
"chars": 2267,
"preview": "package common\n\nimport (\n\t\"time\"\n\n\t\"github.com/apernet/quic-go/congestion\"\n)\n\nconst (\n\tmaxBurstPackets = 1"
},
{
"path": "core/internal/congestion/utils.go",
"chars": 455,
"preview": "package congestion\n\nimport (\n\t\"github.com/apernet/hysteria/core/v2/internal/congestion/bbr\"\n\t\"github.com/apernet/hysteri"
},
{
"path": "core/internal/frag/frag.go",
"chars": 1955,
"preview": "package frag\n\nimport (\n\t\"github.com/apernet/hysteria/core/v2/internal/protocol\"\n)\n\nfunc FragUDPMessage(m *protocol.UDPMe"
},
{
"path": "core/internal/frag/frag_test.go",
"chars": 5870,
"preview": "package frag\n\nimport (\n\t\"reflect\"\n\t\"testing\"\n\n\t\"github.com/apernet/hysteria/core/v2/internal/protocol\"\n)\n\nfunc TestFragU"
},
{
"path": "core/internal/integration_tests/.mockery.yaml",
"chars": 616,
"preview": "with-expecter: true\ndir: mocks\noutpkg: mocks\npackages:\n net:\n interfaces:\n Conn:\n config:\n mock"
},
{
"path": "core/internal/integration_tests/close_test.go",
"chars": 8168,
"preview": "package integration_tests\n\nimport (\n\t\"io\"\n\t\"sync\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com"
},
{
"path": "core/internal/integration_tests/hook_test.go",
"chars": 4193,
"preview": "package integration_tests\n\nimport (\n\t\"io\"\n\t\"net\"\n\t\"testing\"\n\n\t\"github.com/apernet/hysteria/core/v2/client\"\n\t\"github.com/"
},
{
"path": "core/internal/integration_tests/masq_test.go",
"chars": 2567,
"preview": "package integration_tests\n\nimport (\n\t\"context\"\n\t\"crypto/tls\"\n\t\"net\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github."
},
{
"path": "core/internal/integration_tests/mocks/mock_Authenticator.go",
"chars": 2753,
"preview": "// Code generated by mockery v2.43.0. DO NOT EDIT.\n\npackage mocks\n\nimport (\n\tnet \"net\"\n\n\tmock \"github.com/stretchr/testi"
},
{
"path": "core/internal/integration_tests/mocks/mock_Conn.go",
"chars": 10390,
"preview": "// Code generated by mockery v2.43.0. DO NOT EDIT.\n\npackage mocks\n\nimport (\n\tnet \"net\"\n\n\tmock \"github.com/stretchr/testi"
},
{
"path": "core/internal/integration_tests/mocks/mock_EventLogger.go",
"chars": 8645,
"preview": "// Code generated by mockery v2.43.0. DO NOT EDIT.\n\npackage mocks\n\nimport (\n\tnet \"net\"\n\n\tmock \"github.com/stretchr/testi"
},
{
"path": "core/internal/integration_tests/mocks/mock_Outbound.go",
"chars": 3803,
"preview": "// Code generated by mockery v2.43.0. DO NOT EDIT.\n\npackage mocks\n\nimport (\n\tnet \"net\"\n\n\tmock \"github.com/stretchr/testi"
},
{
"path": "core/internal/integration_tests/mocks/mock_RequestHook.go",
"chars": 5199,
"preview": "// Code generated by mockery v2.43.0. DO NOT EDIT.\n\npackage mocks\n\nimport (\n\tquic \"github.com/apernet/quic-go\"\n\tmock \"gi"
},
{
"path": "core/internal/integration_tests/mocks/mock_TrafficLogger.go",
"chars": 3580,
"preview": "// Code generated by mockery v2.43.0. DO NOT EDIT.\n\npackage mocks\n\nimport mock \"github.com/stretchr/testify/mock\"\n\n// Mo"
},
{
"path": "core/internal/integration_tests/mocks/mock_UDPConn.go",
"chars": 4910,
"preview": "// Code generated by mockery v2.43.0. DO NOT EDIT.\n\npackage mocks\n\nimport mock \"github.com/stretchr/testify/mock\"\n\n// Mo"
},
{
"path": "core/internal/integration_tests/smoke_test.go",
"chars": 7716,
"preview": "package integration_tests\n\nimport (\n\t\"io\"\n\t\"net\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/stretchr"
},
{
"path": "core/internal/integration_tests/stress_test.go",
"chars": 6030,
"preview": "package integration_tests\n\nimport (\n\t\"context\"\n\t\"crypto/rand\"\n\t\"fmt\"\n\t\"io\"\n\t\"net\"\n\t\"sync\"\n\t\"testing\"\n\n\t\"github.com/stret"
},
{
"path": "core/internal/integration_tests/test.crt",
"chars": 1363,
"preview": "-----BEGIN CERTIFICATE-----\nMIIDwTCCAqmgAwIBAgIUMeefneiCXWS2ovxNN+fJcdrOIfAwDQYJKoZIhvcNAQEL\nBQAwcDELMAkGA1UEBhMCVFcxEzA"
},
{
"path": "core/internal/integration_tests/test.key",
"chars": 1675,
"preview": "-----BEGIN RSA PRIVATE KEY-----\nMIIEowIBAAKCAQEA5T3/gBP/p8MrITJkwwsXNQRULxkMkegpn7eDrlkVAvFEqqUR\n2G87CrhmzFgXSxx5Q8MCx2t"
},
{
"path": "core/internal/integration_tests/trafficlogger_test.go",
"chars": 5634,
"preview": "package integration_tests\n\nimport (\n\t\"io\"\n\t\"sync\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com"
},
{
"path": "core/internal/integration_tests/utils_test.go",
"chars": 1614,
"preview": "package integration_tests\n\nimport (\n\t\"crypto/tls\"\n\t\"io\"\n\t\"net\"\n\n\t\"github.com/apernet/hysteria/core/v2/server\"\n)\n\n// This"
},
{
"path": "core/internal/pmtud/avail.go",
"chars": 97,
"preview": "//go:build linux || windows || darwin\n\npackage pmtud\n\nconst (\n\tDisablePathMTUDiscovery = false\n)\n"
},
{
"path": "core/internal/pmtud/unavail.go",
"chars": 480,
"preview": "//go:build !linux && !windows && !darwin\n\npackage pmtud\n\n// quic-go's MTU detection is enabled by default on all platfor"
},
{
"path": "core/internal/protocol/http.go",
"chars": 1826,
"preview": "package protocol\n\nimport (\n\t\"net/http\"\n\t\"strconv\"\n)\n\nconst (\n\tURLHost = \"hysteria\"\n\tURLPath = \"/auth\"\n\n\tRequestHeaderAut"
},
{
"path": "core/internal/protocol/padding.go",
"chars": 637,
"preview": "package protocol\n\nimport (\n\t\"math/rand\"\n)\n\nconst (\n\tpaddingChars = \"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
},
{
"path": "core/internal/protocol/proxy.go",
"chars": 6133,
"preview": "package protocol\n\nimport (\n\t\"bytes\"\n\t\"encoding/binary\"\n\t\"fmt\"\n\t\"io\"\n\n\t\"github.com/apernet/hysteria/core/v2/errors\"\n\n\t\"gi"
},
{
"path": "core/internal/protocol/proxy_test.go",
"chars": 11136,
"preview": "package protocol\n\nimport (\n\t\"bytes\"\n\t\"reflect\"\n\t\"strings\"\n\t\"testing\"\n)\n\nfunc TestUDPMessage(t *testing.T) {\n\tt.Run(\"buff"
},
{
"path": "core/internal/utils/atomic.go",
"chars": 316,
"preview": "package utils\n\nimport (\n\t\"sync/atomic\"\n\t\"time\"\n)\n\ntype AtomicTime struct {\n\tv atomic.Value\n}\n\nfunc NewAtomicTime(t time."
},
{
"path": "core/internal/utils/qstream.go",
"chars": 1517,
"preview": "package utils\n\nimport (\n\t\"context\"\n\t\"time\"\n\n\t\"github.com/apernet/quic-go\"\n)\n\n// QStream is a wrapper of quic.Stream that"
},
{
"path": "core/server/.mockery.yaml",
"chars": 314,
"preview": "with-expecter: true\ninpackage: true\ndir: .\npackages:\n github.com/apernet/hysteria/core/v2/server:\n interfaces:\n "
},
{
"path": "core/server/config.go",
"chars": 8526,
"preview": "package server\n\nimport (\n\t\"crypto/tls\"\n\t\"net\"\n\t\"net/http\"\n\t\"time\"\n\n\t\"github.com/apernet/hysteria/core/v2/errors\"\n\t\"githu"
},
{
"path": "core/server/copy.go",
"chars": 1526,
"preview": "package server\n\nimport (\n\t\"errors\"\n\t\"io\"\n)\n\nvar errDisconnect = errors.New(\"traffic logger requested disconnect\")\n\nfunc "
},
{
"path": "core/server/mock_UDPConn.go",
"chars": 4911,
"preview": "// Code generated by mockery v2.43.0. DO NOT EDIT.\n\npackage server\n\nimport mock \"github.com/stretchr/testify/mock\"\n\n// m"
},
{
"path": "core/server/mock_udpEventLogger.go",
"chars": 3130,
"preview": "// Code generated by mockery v2.43.0. DO NOT EDIT.\n\npackage server\n\nimport mock \"github.com/stretchr/testify/mock\"\n\n// m"
},
{
"path": "core/server/mock_udpIO.go",
"chars": 6423,
"preview": "// Code generated by mockery v2.43.0. DO NOT EDIT.\n\npackage server\n\nimport (\n\tprotocol \"github.com/apernet/hysteria/core"
},
{
"path": "core/server/server.go",
"chars": 10214,
"preview": "package server\n\nimport (\n\t\"context\"\n\t\"crypto/tls\"\n\t\"net/http\"\n\t\"sync\"\n\n\t\"github.com/apernet/quic-go\"\n\t\"github.com/aperne"
},
{
"path": "core/server/udp.go",
"chars": 8208,
"preview": "package server\n\nimport (\n\t\"errors\"\n\t\"math/rand\"\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com/apernet/quic-go\"\n\n\t\"github.com/apernet/hys"
},
{
"path": "core/server/udp_test.go",
"chars": 5747,
"preview": "package server\n\nimport (\n\t\"errors\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/stretchr/testi"
},
{
"path": "entrypoint",
"chars": 899,
"preview": "#!/bin/sh\n\nCONFIG_FILE=\"/etc/hysteria/server.yaml\"\n\n# 判断配置文件是否存存在,如果不存在走不存在的逻辑\nif [ ! -f \"$CONFIG_FILE\" ]; then\n echo"
},
{
"path": "extras/auth/command.go",
"chars": 624,
"preview": "package auth\n\nimport (\n\t\"net\"\n\t\"os/exec\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/apernet/hysteria/core/v2/server\"\n)\n\nvar _ s"
},
{
"path": "extras/auth/http.go",
"chars": 1759,
"preview": "package auth\n\nimport (\n\t\"bytes\"\n\t\"crypto/tls\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"io\"\n\t\"net\"\n\t\"net/http\"\n\t\"time\"\n\n\t\"github.com/"
},
{
"path": "extras/auth/http_test.go",
"chars": 760,
"preview": "package auth\n\nimport (\n\t\"net\"\n\t\"os/exec\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestHTTPAuthe"
},
{
"path": "extras/auth/http_test.py",
"chars": 547,
"preview": "from flask import Flask, request, jsonify\n\napp = Flask(__name__)\n\n\n@app.route(\"/auth\", methods=[\"POST\"])\ndef auth():\n "
},
{
"path": "extras/auth/password.go",
"chars": 480,
"preview": "package auth\n\nimport (\n\t\"net\"\n\n\t\"github.com/apernet/hysteria/core/v2/server\"\n)\n\nvar _ server.Authenticator = &PasswordAu"
},
{
"path": "extras/auth/password_test.go",
"chars": 1106,
"preview": "package auth\n\nimport (\n\t\"net\"\n\t\"testing\"\n)\n\nfunc TestPasswordAuthenticator(t *testing.T) {\n\ttype fields struct {\n\t\tPassw"
},
{
"path": "extras/auth/userpass.go",
"chars": 850,
"preview": "package auth\n\nimport (\n\t\"net\"\n\t\"strings\"\n\n\t\"github.com/apernet/hysteria/core/v2/server\"\n)\n\nconst (\n\tuserPassSeparator = "
},
{
"path": "extras/auth/userpass_test.go",
"chars": 1729,
"preview": "package auth\n\nimport (\n\t\"net\"\n\t\"testing\"\n)\n\nfunc TestUserPassAuthenticator(t *testing.T) {\n\ttype fields struct {\n\t\tUsers"
},
{
"path": "extras/auth/v2board.go",
"chars": 2107,
"preview": "package auth\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net\"\n\t\"net/http\"\n\t\"strconv\"\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com/apernet/hyste"
},
{
"path": "extras/correctnet/correctnet.go",
"chars": 2064,
"preview": "package correctnet\n\nimport (\n\t\"net\"\n\t\"net/http\"\n\t\"strings\"\n)\n\nfunc extractIPFamily(ip net.IP) (family string) {\n\tif len("
},
{
"path": "extras/go.mod",
"chars": 1755,
"preview": "module github.com/apernet/hysteria/extras/v2\n\ngo 1.22\n\ntoolchain go1.23.2\n\nrequire (\n\tgithub.com/apernet/hysteria/core/v"
},
{
"path": "extras/go.sum",
"chars": 11324,
"preview": "github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M=\ngithub.com/andybalholm/brotli v1.1."
},
{
"path": "extras/masq/server.go",
"chars": 2868,
"preview": "package masq\n\nimport (\n\t\"bufio\"\n\t\"crypto/tls\"\n\t\"fmt\"\n\t\"net\"\n\t\"net/http\"\n\n\t\"github.com/apernet/hysteria/extras/v2/correct"
},
{
"path": "extras/obfs/conn.go",
"chars": 2915,
"preview": "package obfs\n\nimport (\n\t\"net\"\n\t\"sync\"\n\t\"syscall\"\n\t\"time\"\n)\n\nconst udpBufferSize = 2048 // QUIC packets are at most 1500 "
},
{
"path": "extras/obfs/salamander.go",
"chars": 1527,
"preview": "package obfs\n\nimport (\n\t\"fmt\"\n\t\"math/rand\"\n\t\"sync\"\n\t\"time\"\n\n\t\"golang.org/x/crypto/blake2b\"\n)\n\nconst (\n\tsmPSKMinLen = 4\n\t"
},
{
"path": "extras/obfs/salamander_test.go",
"chars": 1048,
"preview": "package obfs\n\nimport (\n\t\"crypto/rand\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc BenchmarkSalamanderObfus"
},
{
"path": "extras/outbounds/.mockery.yaml",
"chars": 266,
"preview": "with-expecter: true\ninpackage: true\ndir: .\npackages:\n github.com/apernet/hysteria/extras/v2/outbounds:\n interfaces:\n"
},
{
"path": "extras/outbounds/acl/compile.go",
"chars": 7741,
"preview": "package acl\n\nimport (\n\t\"fmt\"\n\t\"net\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/apernet/hysteria/extras/v2/outbounds/acl/v2geo\"\n"
},
{
"path": "extras/outbounds/acl/compile_test.go",
"chars": 6604,
"preview": "package acl\n\nimport (\n\t\"net\"\n\t\"testing\"\n\n\t\"github.com/apernet/hysteria/extras/v2/outbounds/acl/v2geo\"\n\n\t\"github.com/stre"
},
{
"path": "extras/outbounds/acl/matchers.go",
"chars": 1468,
"preview": "package acl\n\nimport (\n\t\"net\"\n\t\"strings\"\n\n\t\"golang.org/x/net/idna\"\n)\n\nconst (\n\tdomainMatchExact = uint8(iota)\n\tdomainMatc"
},
{
"path": "extras/outbounds/acl/matchers_test.go",
"chars": 6061,
"preview": "package acl\n\nimport (\n\t\"net\"\n\t\"testing\"\n)\n\nfunc Test_ipMatcher_Match(t *testing.T) {\n\ttests := []struct {\n\t\tname string\n"
},
{
"path": "extras/outbounds/acl/matchers_v2geo.go",
"chars": 4811,
"preview": "package acl\n\nimport (\n\t\"bytes\"\n\t\"errors\"\n\t\"net\"\n\t\"regexp\"\n\t\"sort\"\n\t\"strings\"\n\n\t\"github.com/apernet/hysteria/extras/v2/ou"
},
{
"path": "extras/outbounds/acl/matchers_v2geo_test.go",
"chars": 2492,
"preview": "package acl\n\nimport (\n\t\"net\"\n\t\"testing\"\n\n\t\"github.com/apernet/hysteria/extras/v2/outbounds/acl/v2geo\"\n\t\"github.com/stret"
},
{
"path": "extras/outbounds/acl/parse.go",
"chars": 1716,
"preview": "package acl\n\nimport (\n\t\"fmt\"\n\t\"regexp\"\n\t\"strings\"\n)\n\nvar linePattern = regexp.MustCompile(`^(\\w+)\\s*\\(([^,]+)(?:,([^,]+)"
},
{
"path": "extras/outbounds/acl/parse_test.go",
"chars": 1611,
"preview": "package acl\n\nimport (\n\t\"reflect\"\n\t\"testing\"\n)\n\nfunc TestParseTextRules(t *testing.T) {\n\ttests := []struct {\n\t\tname st"
},
{
"path": "extras/outbounds/acl/v2geo/load.go",
"chars": 1080,
"preview": "package v2geo\n\nimport (\n\t\"os\"\n\t\"strings\"\n\n\t\"google.golang.org/protobuf/proto\"\n)\n\n// LoadGeoIP loads a GeoIP data file an"
},
{
"path": "extras/outbounds/acl/v2geo/load_test.go",
"chars": 1348,
"preview": "package v2geo\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestLoadGeoIP(t *testing.T) {\n\tm, err "
},
{
"path": "extras/outbounds/acl/v2geo/v2geo.pb.go",
"chars": 21809,
"preview": "// Code generated by protoc-gen-go. DO NOT EDIT.\n// versions:\n// \tprotoc-gen-go v1.31.0\n// \tprotoc v4.24.4\n// sou"
},
{
"path": "extras/outbounds/acl/v2geo/v2geo.proto",
"chars": 1561,
"preview": "syntax = \"proto3\";\n\noption go_package = \"./v2geo\";\n\n// This file is copied from\n// https://github.com/v2fly/v2ray-core/b"
},
{
"path": "extras/outbounds/acl.go",
"chars": 3269,
"preview": "package outbounds\n\nimport (\n\t\"errors\"\n\t\"net\"\n\t\"os\"\n\t\"strings\"\n\n\t\"github.com/apernet/hysteria/extras/v2/outbounds/acl\"\n)\n"
},
{
"path": "extras/outbounds/acl_test.go",
"chars": 1675,
"preview": "package outbounds\n\nimport (\n\t\"net\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestACLEngine(t *testing.T)"
},
{
"path": "extras/outbounds/dns_https.go",
"chars": 1956,
"preview": "package outbounds\n\nimport (\n\t\"crypto/tls\"\n\t\"net\"\n\t\"net/http\"\n\t\"time\"\n\n\t\"github.com/babolivier/go-doh-client\"\n)\n\n// dohRe"
},
{
"path": "extras/outbounds/dns_standard.go",
"chars": 5508,
"preview": "package outbounds\n\nimport (\n\t\"crypto/tls\"\n\t\"net\"\n\t\"time\"\n\n\t\"github.com/miekg/dns\"\n)\n\nconst (\n\tresolverDefaultTimeout "
},
{
"path": "extras/outbounds/dns_system.go",
"chars": 1053,
"preview": "package outbounds\n\nimport (\n\t\"net\"\n)\n\n// systemResolver is a PluggableOutbound DNS resolver that resolves hostnames\n// u"
},
{
"path": "extras/outbounds/interface.go",
"chars": 3916,
"preview": "package outbounds\n\nimport (\n\t\"net\"\n\t\"strconv\"\n\n\t\"github.com/apernet/hysteria/core/v2/server\"\n)\n\n// The PluggableOutbound"
},
{
"path": "extras/outbounds/interface_test.go",
"chars": 1225,
"preview": "package outbounds\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/stretchr/testify/mock\"\n)\n\nfun"
},
{
"path": "extras/outbounds/mock_PluggableOutbound.go",
"chars": 4044,
"preview": "// Code generated by mockery v2.43.0. DO NOT EDIT.\n\npackage outbounds\n\nimport (\n\tnet \"net\"\n\n\tmock \"github.com/stretchr/t"
},
{
"path": "extras/outbounds/mock_UDPConn.go",
"chars": 4959,
"preview": "// Code generated by mockery v2.43.0. DO NOT EDIT.\n\npackage outbounds\n\nimport mock \"github.com/stretchr/testify/mock\"\n\n/"
},
{
"path": "extras/outbounds/ob_direct.go",
"chars": 11736,
"preview": "package outbounds\n\nimport (\n\t\"errors\"\n\t\"net\"\n\t\"strconv\"\n\t\"time\"\n)\n\ntype DirectOutboundMode int\n\ntype udpConnState int\n\nc"
},
{
"path": "extras/outbounds/ob_direct_linux.go",
"chars": 1287,
"preview": "package outbounds\n\nimport (\n\t\"errors\"\n\t\"net\"\n\t\"syscall\"\n)\n\n// NewDirectOutboundBindToDevice creates a new directOutbound"
},
{
"path": "extras/outbounds/ob_direct_others.go",
"chars": 628,
"preview": "//go:build !linux\n\npackage outbounds\n\nimport (\n\t\"errors\"\n\t\"net\"\n)\n\n// NewDirectOutboundBindToDevice creates a new direct"
},
{
"path": "extras/outbounds/ob_http.go",
"chars": 4596,
"preview": "package outbounds\n\nimport (\n\t\"bufio\"\n\t\"bytes\"\n\t\"crypto/tls\"\n\t\"encoding/base64\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"net\"\n\t\"net/http\""
},
{
"path": "extras/outbounds/ob_socks5.go",
"chars": 6928,
"preview": "package outbounds\n\nimport (\n\t\"encoding/binary\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"net\"\n\t\"time\"\n\n\t\"github.com/txthinking/socks5\"\n)\n"
},
{
"path": "extras/outbounds/speedtest/client.go",
"chars": 3031,
"preview": "package speedtest\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"net\"\n\t\"sync/atomic\"\n\t\"time\"\n)\n\ntype Client struct {\n\tConn net.Conn\n}\n\n// Down"
},
{
"path": "extras/outbounds/speedtest/protocol.go",
"chars": 3381,
"preview": "package speedtest\n\nimport (\n\t\"encoding/binary\"\n\t\"io\"\n\t\"time\"\n)\n\nconst (\n\ttypeDownload = 0x1\n\ttypeUpload = 0x2\n)\n\n// Do"
},
{
"path": "extras/outbounds/speedtest/protocol_test.go",
"chars": 9544,
"preview": "package speedtest\n\nimport (\n\t\"bytes\"\n\t\"testing\"\n\t\"time\"\n)\n\nfunc TestReadDownloadRequest(t *testing.T) {\n\ttests := []stru"
},
{
"path": "extras/outbounds/speedtest/server.go",
"chars": 2163,
"preview": "package speedtest\n\nimport (\n\t\"crypto/rand\"\n\t\"fmt\"\n\t\"io\"\n\t\"net\"\n\t\"time\"\n)\n\nconst (\n\tchunkSize = 64 * 1024\n)\n\n// NewServer"
},
{
"path": "extras/outbounds/speedtest.go",
"chars": 799,
"preview": "package outbounds\n\nimport (\n\t\"net\"\n\n\t\"github.com/apernet/hysteria/extras/v2/outbounds/speedtest\"\n)\n\nconst (\n\tSpeedtestDe"
},
{
"path": "extras/outbounds/utils.go",
"chars": 963,
"preview": "package outbounds\n\nimport \"net\"\n\n// splitIPv4IPv6 gets the first IPv4 and IPv6 address from a list of IP addresses.\n// B"
},
{
"path": "extras/outbounds/utils_test.go",
"chars": 1603,
"preview": "package outbounds\n\nimport (\n\t\"net\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestSplitIPv4IPv6(t *testin"
},
{
"path": "extras/sniff/.mockery.yaml",
"chars": 385,
"preview": "with-expecter: true\ndir: .\noutpkg: sniff\npackages:\n github.com/apernet/quic-go:\n interfaces:\n Stream:\n c"
},
{
"path": "extras/sniff/internal/quic/LICENSE",
"chars": 1566,
"preview": "Author:: Cuong Manh Le <cuong.manhle.vn@gmail.com>\nCopyright:: Copyright (c) 2023, Cuong Manh Le\nAll rights reserved.\n\nR"
},
{
"path": "extras/sniff/internal/quic/README.md",
"chars": 84,
"preview": "The code here is from https://github.com/cuonglm/quicsni with various modifications."
},
{
"path": "extras/sniff/internal/quic/header.go",
"chars": 2245,
"preview": "package quic\n\nimport (\n\t\"bytes\"\n\t\"encoding/binary\"\n\t\"errors\"\n\t\"io\"\n\n\t\"github.com/apernet/quic-go/quicvarint\"\n)\n\n// The H"
},
{
"path": "extras/sniff/internal/quic/packet_protector.go",
"chars": 6132,
"preview": "package quic\n\nimport (\n\t\"crypto\"\n\t\"crypto/aes\"\n\t\"crypto/cipher\"\n\t\"crypto/sha256\"\n\t\"crypto/tls\"\n\t\"encoding/binary\"\n\t\"erro"
},
{
"path": "extras/sniff/internal/quic/packet_protector_test.go",
"chars": 2609,
"preview": "package quic\n\nimport (\n\t\"bytes\"\n\t\"crypto\"\n\t\"crypto/tls\"\n\t\"encoding/hex\"\n\t\"strings\"\n\t\"testing\"\n\t\"unicode\"\n\n\t\"golang.org/x"
},
{
"path": "extras/sniff/internal/quic/payload.go",
"chars": 3332,
"preview": "package quic\n\nimport (\n\t\"bytes\"\n\t\"crypto\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"sort\"\n\n\t\"github.com/apernet/quic-go/quicvarint\"\n\t\"gol"
},
{
"path": "extras/sniff/internal/quic/quic.go",
"chars": 1416,
"preview": "package quic\n\nconst (\n\tV1 uint32 = 0x1\n\tV2 uint32 = 0x6b3343cf\n\n\thkdfLabelKeyV1 = \"quic key\"\n\thkdfLabelKeyV2 = \"quicv2 k"
},
{
"path": "extras/sniff/mock_Stream.go",
"chars": 12723,
"preview": "// Code generated by mockery v2.43.0. DO NOT EDIT.\n\npackage sniff\n\nimport (\n\tcontext \"context\"\n\n\tqerr \"github.com/aperne"
},
{
"path": "extras/sniff/sniff.go",
"chars": 5124,
"preview": "package sniff\n\nimport (\n\t\"bufio\"\n\t\"io\"\n\t\"net\"\n\t\"net/http\"\n\t\"strconv\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/apernet/quic-go\"\n\t"
},
{
"path": "extras/sniff/sniff_test.go",
"chars": 5969,
"preview": "package sniff\n\nimport (\n\t\"encoding/base64\"\n\t\"io\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/apernet/hysteria/extras/v2/utils\"\n\n\t\"g"
}
]
// ... and 11 more files (download for full content)
About this extraction
This page contains the full source code of the cedar2025/hysteria GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 211 files (909.8 KB), approximately 314.4k tokens, and a symbol index with 1877 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.