Merge pull request #5 from rebecca554owen/master

更新到2.2.3
This commit is contained in:
Xboard
2024-01-16 00:47:51 +08:00
committed by GitHub
16 changed files with 302 additions and 91 deletions

View File

@@ -78,7 +78,7 @@ jobs:
context: .
push: true
platforms: linux/amd64,linux/arm64
tags: ${{ env.REGISTRY }}/cedar2025/hysteria:latest,${{ env.REGISTRY }}/cedar2025/hysteria,${{ env.REGISTRY }}/cedar2025/hysteria:${{ steps.get_version.outputs.version }}
tags: ${{ env.REGISTRY }}/${{ github.repository }}:latest,${{ env.REGISTRY }}/${{ github.repository }},${{ env.REGISTRY }}/${{ github.repository }}:${{ 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

52
.github/workflows/master.yml vendored Normal file
View File

@@ -0,0 +1,52 @@
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.21"
- 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

View File

@@ -21,12 +21,12 @@ jobs:
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@v4
uses: actions/setup-go@v5
with:
go-version: "1.21"
- name: Setup Python # This is for the build script
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: "3.11"

View File

@@ -1,40 +1,95 @@
# ![Hysteria 2](logo.svg)
# 支持对接V2board面板的Hysteria2后端
# 支持对接 Xboard/V2board 面板的Hysteria2后端
### 项目说明
本项目基于hysteria官方内核二次开发添加了从v2b获取节点信息、用户鉴权信息与上报用户流量的功能。
本项目基于hysteria官方内核二次开发添加了从 Xboard/V2board 获取节点信息、用户鉴权信息与上报用户流量的功能。
性能方面已经由hysteria2内核作者亲自指导优化过了。
### TG交流群
欢迎加入交流群 [点击加入](https://t.me/+DcRt8AB2VbI2Yzc1)
准备工作默认在root目录下开始。
配置ssl证书使用acme配置证书要占用80端口CentOS自行把`apt`改成`yum`
```
apt install -y vim curl socat openssl && mkdir hysteria
```
```
curl https://get.acme.sh | sh -s email=rebecca554owen@gmail.com
```
```
~/.acme.sh/acme.sh --upgrade --auto-upgrade
```
可选切换申请letsencrypt的证书`~/.acme.sh/acme.sh --set-default-ca --server letsencrypt`
### 示例配置
每行第一个 example.com 换成你解析到 vps 的域名,后面的 example.com 不用改了。
```
~/.acme.sh/acme.sh --issue -d example.com --standalone
~/.acme.sh/acme.sh --install-cert -d example.com --key-file /root/hysteria/example.com.key
~/.acme.sh/acme.sh --install-cert -d example.com --fullchain-file /root/hysteria/example.com.crt
```
安装dockerdocker compose
```
curl -fsSL https://get.docker.com | bash -s docker && systemctl start docker && systemctl enable docker
```
修改 docker-compose.yml, server.yaml 配置文件。
Finalshell 注意:直接新建文件,复制粘贴过去,用终端粘贴不了符号。
```
cd hysteria
```
---在ssh 终端复制命令写入docker-compose.yml 文件
```
cat > docker-compose.yml << EOF
version: "3.9"
services:
hysteria:
image: ghcr.io/rebecca554owen/hysteria:latest
container_name: hysteria
restart: always
network_mode: "host"
volumes:
- ./server.yaml:/etc/hysteria/server.yaml # 这里不用改。
- ./example.com.crt:/etc/hysteria/example.com.crt # 这里不用改。
- ./example.com.key:/etc/hysteria/example.com.key # 这里不用改。
command: ["server", "-c", "/etc/hysteria/server.yaml"]
EOF
```
---配置文件server.yaml参考
```
vim server.yaml
```
```
v2board:
apiHost: https://面板地址
apiKey: 面板节点密钥
nodeID: 节点ID
apiHost: https://example.com # xboard面板域名
apiKey: 123456789 # 通讯密钥
nodeID: 1 # Hysteria节点id
tls:
type: tls
cert: /etc/hysteria/tls.crt
key: /etc/hysteria/tls.key
cert: /etc/hysteria/example.com.crt # 这里不要改。
key: /etc/hysteria/example.com.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)
- reject(pincong.rocks) #acl规则自行查阅hysteria2文档
```
启动docker compose
```
docker compose up -d
```
停止docker compose(不用的话记得停止运行避免删除Hysteria2节点后数据库v2_log存在大量报错记录)
```
docker compose down
```
> 其他配置完全与hysteria文档的一致可以查看hysteria2官方文档 [点击查看](https://hysteria.network/zh/docs/getting-started/Installation/)
### docker 仓库
查看日志:
```
docker pull ghcr.io/cedar2025/hysteria:v1.0.5
docker logs -f hysteria
```
更新,在 hysteria 目录执行。
```
docker compose pull && docker compose up -d
```

View File

@@ -23,6 +23,7 @@ import (
"github.com/apernet/hysteria/app/internal/url"
"github.com/apernet/hysteria/app/internal/utils"
"github.com/apernet/hysteria/core/client"
"github.com/apernet/hysteria/extras/correctnet"
"github.com/apernet/hysteria/extras/obfs"
"github.com/apernet/hysteria/extras/transport/udphop"
)
@@ -397,21 +398,19 @@ func runClient(cmd *cobra.Command, args []string) {
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, err := client.NewReconnectableClient(hyConfig, 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)
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))
}
@@ -504,7 +503,7 @@ func clientSOCKS5(config socks5Config, c client.Client) error {
if config.Listen == "" {
return configError{Field: "listen", Err: errors.New("listen address is empty")}
}
l, err := net.Listen("tcp", config.Listen)
l, err := correctnet.Listen("tcp", config.Listen)
if err != nil {
return configError{Field: "listen", Err: err}
}
@@ -529,7 +528,7 @@ func clientHTTP(config httpConfig, c client.Client) error {
if config.Listen == "" {
return configError{Field: "listen", Err: errors.New("listen address is empty")}
}
l, err := net.Listen("tcp", config.Listen)
l, err := correctnet.Listen("tcp", config.Listen)
if err != nil {
return configError{Field: "listen", Err: err}
}
@@ -562,7 +561,7 @@ func clientTCPForwarding(entries []tcpForwardingEntry, c client.Client) error {
if e.Remote == "" {
return configError{Field: "remote", Err: errors.New("remote address is empty")}
}
l, err := net.Listen("tcp", e.Listen)
l, err := correctnet.Listen("tcp", e.Listen)
if err != nil {
return configError{Field: "listen", Err: err}
}
@@ -589,7 +588,7 @@ func clientUDPForwarding(entries []udpForwardingEntry, c client.Client) error {
if e.Remote == "" {
return configError{Field: "remote", Err: errors.New("remote address is empty")}
}
l, err := net.ListenPacket("udp", e.Listen)
l, err := correctnet.ListenPacket("udp", e.Listen)
if err != nil {
return configError{Field: "listen", Err: err}
}

View File

@@ -24,6 +24,7 @@ import (
"github.com/apernet/hysteria/app/internal/utils"
"github.com/apernet/hysteria/core/server"
"github.com/apernet/hysteria/extras/auth"
"github.com/apernet/hysteria/extras/correctnet"
"github.com/apernet/hysteria/extras/masq"
"github.com/apernet/hysteria/extras/obfs"
"github.com/apernet/hysteria/extras/outbounds"
@@ -227,7 +228,7 @@ func (c *serverConfig) fillConn(hyConfig *server.Config) error {
if err != nil {
return configError{Field: "listen", Err: err}
}
conn, err := net.ListenUDP("udp", uAddr)
conn, err := correctnet.ListenUDP("udp", uAddr)
if err != nil {
return configError{Field: "listen", Err: err}
}
@@ -259,11 +260,12 @@ func (c *serverConfig) fillTLSConfig(hyConfig *server.Config) error {
if c.TLS.Cert == "" || c.TLS.Key == "" {
return configError{Field: "tls", Err: errors.New("empty cert or key path")}
}
cert, err := tls.LoadX509KeyPair(c.TLS.Cert, c.TLS.Key)
if err != nil {
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 = func(info *tls.ClientHelloInfo) (*tls.Certificate, error) {
cert, err := tls.LoadX509KeyPair(c.TLS.Cert, c.TLS.Key)
return &cert, err
}
hyConfig.TLSConfig.Certificates = []tls.Certificate{cert}
} else {
// ACME
dataDir := c.ACME.Dir
@@ -850,7 +852,7 @@ func runServer(cmd *cobra.Command, args []string) {
func runTrafficStatsServer(listen string, handler http.Handler) {
logger.Info("traffic stats server up and running", zap.String("listen", listen))
if err := http.ListenAndServe(listen, handler); err != nil {
if err := correctnet.HTTPListenAndServe(listen, handler); err != nil {
logger.Fatal("failed to serve traffic stats", zap.Error(err))
}
}

View File

@@ -47,12 +47,12 @@ require (
go.uber.org/atomic v1.11.0 // indirect
go.uber.org/mock v0.3.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/crypto v0.14.0 // indirect
golang.org/x/crypto v0.17.0 // indirect
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db // indirect
golang.org/x/mod v0.12.0 // indirect
golang.org/x/net v0.17.0 // indirect
golang.org/x/sys v0.13.0 // indirect
golang.org/x/text v0.13.0 // indirect
golang.org/x/sys v0.15.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/tools v0.11.1 // indirect
google.golang.org/protobuf v1.28.1 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect

View File

@@ -267,8 +267,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
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.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
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=
@@ -411,8 +411,8 @@ golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
golang.org/x/sys v0.15.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=
@@ -424,8 +424,8 @@ 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.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
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=

View File

@@ -10,23 +10,21 @@ import (
// reconnectableClientImpl is a wrapper of Client, which can reconnect when the connection is closed,
// except when the caller explicitly calls Close() to permanently close this client.
type reconnectableClientImpl struct {
config *Config
configFunc func() (*Config, error) // called before connecting
connectedFunc func(Client, *HandshakeInfo, int) // called when successfully connected
client Client
count int
connectedFunc func(Client, *HandshakeInfo, int) // called when successfully connected
m sync.Mutex
closed bool // permanent close
}
func NewReconnectableClient(config *Config, connectedFunc func(Client, *HandshakeInfo, int), lazy bool) (Client, error) {
// Make sure we capture any error in config and return it here,
// so that the caller doesn't have to wait until the first call
// to TCP() or UDP() to get the error (when lazy is true).
if err := config.verifyAndFill(); err != nil {
return nil, err
}
// NewReconnectableClient creates a reconnectable client.
// If lazy is true, the client will not connect until the first call to TCP() or UDP().
// We use a function for config mainly to delay config evaluation
// (which involves DNS resolution) until the actual connection attempt.
func NewReconnectableClient(configFunc func() (*Config, error), connectedFunc func(Client, *HandshakeInfo, int), lazy bool) (Client, error) {
rc := &reconnectableClientImpl{
config: config,
configFunc: configFunc,
connectedFunc: connectedFunc,
}
if !lazy {
@@ -41,9 +39,12 @@ func (rc *reconnectableClientImpl) reconnect() error {
if rc.client != nil {
_ = rc.client.Close()
}
var err error
var info *HandshakeInfo
rc.client, info, err = NewClient(rc.config)
config, err := rc.configFunc()
if err != nil {
return err
}
rc.client, info, err = NewClient(config)
if err != nil {
return err
} else {

View File

@@ -22,11 +22,11 @@ require (
github.com/quic-go/qtls-go1-20 v0.4.1 // indirect
github.com/stretchr/objx v0.5.0 // indirect
go.uber.org/mock v0.3.0 // indirect
golang.org/x/crypto v0.14.0 // indirect
golang.org/x/crypto v0.17.0 // indirect
golang.org/x/mod v0.12.0 // indirect
golang.org/x/net v0.17.0 // indirect
golang.org/x/sys v0.13.0 // indirect
golang.org/x/text v0.13.0 // indirect
golang.org/x/sys v0.15.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/tools v0.11.1 // indirect
google.golang.org/protobuf v1.28.1 // indirect
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect

View File

@@ -49,8 +49,8 @@ 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.3.0 h1:3mUxI1No2/60yUYax92Pt8eNOEecx2D3lcXZh2NEZJo=
go.uber.org/mock v0.3.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db h1:D/cFflL63o2KSLJIwjlcIt8PR064j/xsmdEJL/YvY/o=
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc=
@@ -58,10 +58,10 @@ golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/time v0.4.0 h1:Z81tqI5ddIoXDPvVQ7/7CC9TnLM7ubaFG2qXYd5BbYY=
golang.org/x/time v0.4.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.11.1 h1:ojD5zOW8+7dOGzdnNgersm8aPfcDjhMp12UfG93NIMc=

View File

@@ -0,0 +1,92 @@
package correctnet
import (
"net"
"net/http"
"strings"
)
func extractIPFamily(ip net.IP) (family string) {
if len(ip) == 0 {
// real family independent wildcard address, such as ":443"
return ""
}
if p4 := ip.To4(); len(p4) == net.IPv4len {
return "4"
}
return "6"
}
func tcpAddrNetwork(addr *net.TCPAddr) (network string) {
if addr == nil {
return "tcp"
}
return "tcp" + extractIPFamily(addr.IP)
}
func udpAddrNetwork(addr *net.UDPAddr) (network string) {
if addr == nil {
return "udp"
}
return "udp" + extractIPFamily(addr.IP)
}
func ipAddrNetwork(addr *net.IPAddr) (network string) {
if addr == nil {
return "ip"
}
return "ip" + extractIPFamily(addr.IP)
}
func Listen(network, address string) (net.Listener, error) {
if network == "tcp" {
tcpAddr, err := net.ResolveTCPAddr(network, address)
if err != nil {
return nil, err
}
return ListenTCP(network, tcpAddr)
}
return net.Listen(network, address)
}
func ListenTCP(network string, laddr *net.TCPAddr) (*net.TCPListener, error) {
if network == "tcp" {
return net.ListenTCP(tcpAddrNetwork(laddr), laddr)
}
return net.ListenTCP(network, laddr)
}
func ListenPacket(network, address string) (listener net.PacketConn, err error) {
if network == "udp" {
udpAddr, err := net.ResolveUDPAddr(network, address)
if err != nil {
return nil, err
}
return ListenUDP(network, udpAddr)
}
if strings.HasPrefix(network, "ip:") {
proto := network[3:]
ipAddr, err := net.ResolveIPAddr(proto, address)
if err != nil {
return nil, err
}
return net.ListenIP(ipAddrNetwork(ipAddr)+":"+proto, ipAddr)
}
return net.ListenPacket(network, address)
}
func ListenUDP(network string, laddr *net.UDPAddr) (*net.UDPConn, error) {
if network == "udp" {
return net.ListenUDP(udpAddrNetwork(laddr), laddr)
}
return net.ListenUDP(network, laddr)
}
func HTTPListenAndServe(address string, handler http.Handler) error {
listener, err := Listen("tcp", address)
if err != nil {
return err
}
defer listener.Close()
return http.Serve(listener, handler)
}

View File

@@ -9,7 +9,7 @@ require (
github.com/miekg/dns v1.1.55
github.com/stretchr/testify v1.8.4
github.com/txthinking/socks5 v0.0.0-20230325130024-4230056ae301
golang.org/x/crypto v0.14.0
golang.org/x/crypto v0.17.0
golang.org/x/net v0.17.0
google.golang.org/protobuf v1.28.1
)
@@ -29,8 +29,8 @@ require (
go.uber.org/mock v0.3.0 // indirect
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db // indirect
golang.org/x/mod v0.12.0 // indirect
golang.org/x/sys v0.13.0 // indirect
golang.org/x/text v0.13.0 // indirect
golang.org/x/sys v0.15.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/tools v0.11.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

View File

@@ -62,8 +62,8 @@ go.uber.org/mock v0.3.0 h1:3mUxI1No2/60yUYax92Pt8eNOEecx2D3lcXZh2NEZJo=
go.uber.org/mock v0.3.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db h1:D/cFflL63o2KSLJIwjlcIt8PR064j/xsmdEJL/YvY/o=
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
@@ -88,8 +88,8 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
golang.org/x/sys v0.15.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=
@@ -97,8 +97,8 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/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.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=

View File

@@ -6,6 +6,8 @@ import (
"fmt"
"net"
"net/http"
"github.com/apernet/hysteria/extras/correctnet"
)
// MasqTCPServer covers the TCP parts of a standard web server (TCP based HTTP/HTTPS).
@@ -20,7 +22,7 @@ type MasqTCPServer struct {
}
func (s *MasqTCPServer) ListenAndServeHTTP(addr string) error {
return http.ListenAndServe(addr, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
return correctnet.HTTPListenAndServe(addr, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if s.ForceHTTPS {
if s.HTTPSPort == 0 || s.HTTPSPort == 443 {
// Omit port if it's the default
@@ -42,7 +44,12 @@ func (s *MasqTCPServer) ListenAndServeHTTPS(addr string) error {
}),
TLSConfig: s.TLSConfig,
}
return server.ListenAndServeTLS("", "")
listener, err := correctnet.Listen("tcp", addr)
if err != nil {
return err
}
defer listener.Close()
return server.ServeTLS(listener, "", "")
}
var _ http.ResponseWriter = (*altSvcHijackResponseWriter)(nil)

View File

@@ -154,14 +154,7 @@ github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a
github.com/openzipkin/zipkin-go v0.1.1 h1:A/ADD6HaPnAKj3yS7HjGHRK77qi41Hi0DirOOIQAeIw=
github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
github.com/pkg/sftp v1.13.1 h1:I2qBYMChEhIjOgazfJmV3/mZM256btk6wkCDRmW7JYs=
github.com/prometheus/client_golang v0.8.0 h1:1921Yw9Gc3iSc4VQh3PIoOqgPCZS7G/4xQNVUp8Mda8=
github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4 h1:gQz4mCbXsO+nc9n1hCxHcGA3Zx3Eo+UHZoInFGUIXNM=
github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e h1:n/3MEhJQjQxrOUCzh1Y3Re6aJUUWRp2M9+Oc3eVn/54=
github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273 h1:agujYaXJSxSo18YNX3jzl+4G6Bstwt+kqv47GS12uL0=
github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
@@ -244,6 +237,8 @@ golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACk
golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
golang.org/x/crypto v0.4.0/go.mod h1:3quD/ATkf6oY+rnes5c3ExXTbLc8mueNue5/DoinL80=
golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b h1:+qEpEAPhDZ1o0x3tHzZTQDArnOixOzGD9HUJfcg0mb4=
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5 h1:2M3HP5CCK1Si9FQhwnzYhXdG6DXeebvUHFpre8QvbyI=
@@ -258,6 +253,7 @@ golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783 h1:nt+Q6cXKz4MosCSpnbMtqiQ8Oz0pxTef2B4Vca2lvfk=
@@ -273,6 +269,9 @@ golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.8.0 h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols=
@@ -280,7 +279,11 @@ golang.org/x/term v0.10.0 h1:3R7pNqamzBraeqj/Tj8qt1aQ2HpmlC+Cx/qL/7hn4/c=
golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o=
golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek=
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4=
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.1.0 h1:xYY+Bajn2a7VBmTM5GikTmnK8ZuX8YgnQCqZpbBNtmA=
golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=