Merge pull request #165 from cxjava/pr-multiple-relay

multiple relay
This commit is contained in:
Toby 2021-12-09 00:11:51 -08:00 committed by GitHub
commit d7bda39f9e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 175 additions and 94 deletions

1
.gitignore vendored
View File

@ -181,3 +181,4 @@ $RECYCLE.BIN/
cmd/relay/*.json cmd/relay/*.json
hy_linux hy_linux
.vscode

View File

@ -280,16 +280,30 @@ hysteria_traffic_uplink_bytes_total{auth="aGFja2VyISE="} 37452
"dns": [ "8.8.8.8", "8.8.4.4" ], // TUN interface DNS, only applicable for Windows "dns": [ "8.8.8.8", "8.8.4.4" ], // TUN interface DNS, only applicable for Windows
"persist": false // Persist TUN interface after exit, only applicable for Linux "persist": false // Persist TUN interface after exit, only applicable for Linux
}, },
"relay_tcp": { "relay_tcps": [
"listen": "127.0.0.1:2222", // TCP relay listen address {
"remote": "123.123.123.123:22", // TCP relay remote address "listen": "127.0.0.1:2222", // TCP relay listen address
"timeout": 300 // TCP timeout in seconds "remote": "123.123.123.123:22", // TCP relay remote address
}, "timeout": 300 // TCP timeout in seconds
"relay_udp": { },
"listen": "127.0.0.1:5333", // UDP relay listen address {
"remote": "8.8.8.8:53", // UDP relay remote address "listen": "127.0.0.1:13389", // TCP relay listen address
"timeout": 60 // UDP session timeout in seconds "remote": "124.124.124.124:3389", // TCP relay remote address
}, "timeout": 300 // TCP timeout in seconds
}
],
"relay_udps": [
{
"listen": "127.0.0.1:5333", // UDP relay listen address
"remote": "8.8.8.8:53", // UDP relay remote address
"timeout": 60 // UDP session timeout in seconds
},
{
"listen": "127.0.0.1:11080", // UDP relay listen address
"remote": "9.9.9.9.9:1080", // UDP relay remote address
"timeout": 60 // UDP session timeout in seconds
}
],
"tproxy_tcp": { "tproxy_tcp": {
"listen": "127.0.0.1:9000", // TCP TProxy listen address "listen": "127.0.0.1:9000", // TCP TProxy listen address
"timeout": 300 // TCP timeout in seconds "timeout": 300 // TCP timeout in seconds

View File

@ -265,16 +265,30 @@ hysteria_traffic_uplink_bytes_total{auth="aGFja2VyISE="} 37452
"dns": [ "8.8.8.8", "8.8.4.4" ], // TUN 接口 DNS 服务器(仅适用于 Windows "dns": [ "8.8.8.8", "8.8.4.4" ], // TUN 接口 DNS 服务器(仅适用于 Windows
"persist": false // 在程序退出之后保留接口(仅适用于 Linux "persist": false // 在程序退出之后保留接口(仅适用于 Linux
}, },
"relay_tcp": { "relay_tcps": [
"listen": "127.0.0.1:2222", // TCP 转发监听地址 {
"remote": "123.123.123.123:22", // TCP 转发目标地址 "listen": "127.0.0.1:2222", // TCP 转发监听地址
"timeout": 300 // TCP 超时秒数 "remote": "123.123.123.123:22", // TCP 转发目标地址
}, "timeout": 300 // TCP 超时秒数
"relay_udp": { },
"listen": "127.0.0.1:5333", // UDP 转发监听地址 {
"remote": "8.8.8.8:53", // UDP 转发目标地址 "listen": "127.0.0.1:13389", // TCP 转发监听地址
"timeout": 60 // UDP 超时秒数 "remote": "124.124.124.124:3389", // TCP 转发目标地址
}, "timeout": 300 // TCP 超时秒数
}
],
"relay_udps": [
{
"listen": "127.0.0.1:5333", // UDP 转发监听地址
"remote": "8.8.8.8:53", // UDP 转发目标地址
"timeout": 60 // UDP 超时秒数
},
{
"listen": "127.0.0.1:11080", // UDP 转发监听地址
"remote": "9.9.9.9.9:1080", // UDP 转发目标地址
"timeout": 60 // UDP 超时秒数
}
],
"tproxy_tcp": { "tproxy_tcp": {
"listen": "127.0.0.1:9000", // TCP 透明代理监听地址 "listen": "127.0.0.1:9000", // TCP 透明代理监听地址
"timeout": 300 // TCP 超时秒数 "timeout": 300 // TCP 超时秒数

View File

@ -3,6 +3,13 @@ package main
import ( import (
"crypto/tls" "crypto/tls"
"crypto/x509" "crypto/x509"
"io"
"io/ioutil"
"net"
"net/http"
"strings"
"time"
"github.com/lucas-clemente/quic-go" "github.com/lucas-clemente/quic-go"
"github.com/lucas-clemente/quic-go/congestion" "github.com/lucas-clemente/quic-go/congestion"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
@ -16,12 +23,6 @@ import (
"github.com/tobyxdd/hysteria/pkg/tproxy" "github.com/tobyxdd/hysteria/pkg/tproxy"
"github.com/tobyxdd/hysteria/pkg/transport" "github.com/tobyxdd/hysteria/pkg/transport"
"github.com/tobyxdd/hysteria/pkg/tun" "github.com/tobyxdd/hysteria/pkg/tun"
"io"
"io/ioutil"
"net"
"net/http"
"strings"
"time"
) )
func client(config *clientConfig) { func client(config *clientConfig) {
@ -245,63 +246,83 @@ func client(config *clientConfig) {
} }
if len(config.TCPRelay.Listen) > 0 { if len(config.TCPRelay.Listen) > 0 {
go func() { config.TCPRelays = append(config.TCPRelays, Relay{
rl, err := relay.NewTCPRelay(client, transport.DefaultTransport, Listen: config.TCPRelay.Listen,
config.TCPRelay.Listen, config.TCPRelay.Remote, Remote: config.TCPRelay.Remote,
time.Duration(config.TCPRelay.Timeout)*time.Second, Timeout: config.TCPRelay.Timeout,
func(addr net.Addr) { })
logrus.WithFields(logrus.Fields{ }
"src": addr.String(),
}).Debug("TCP relay request") if len(config.TCPRelays) > 0 {
}, for _, tcpr := range config.TCPRelays {
func(addr net.Addr, err error) { go func(tcpr Relay) {
if err != io.EOF { rl, err := relay.NewTCPRelay(client, transport.DefaultTransport,
logrus.WithFields(logrus.Fields{ tcpr.Listen, tcpr.Remote,
"error": err, time.Duration(tcpr.Timeout)*time.Second,
"src": addr.String(), func(addr net.Addr) {
}).Info("TCP relay error")
} else {
logrus.WithFields(logrus.Fields{ logrus.WithFields(logrus.Fields{
"src": addr.String(), "src": addr.String(),
}).Debug("TCP relay EOF") }).Debug("TCP relay request")
} },
}) func(addr net.Addr, err error) {
if err != nil { if err != io.EOF {
logrus.WithField("error", err).Fatal("Failed to initialize TCP relay") logrus.WithFields(logrus.Fields{
} "error": err,
logrus.WithField("addr", config.TCPRelay.Listen).Info("TCP relay up and running") "src": addr.String(),
errChan <- rl.ListenAndServe() }).Info("TCP relay error")
}() } else {
logrus.WithFields(logrus.Fields{
"src": addr.String(),
}).Debug("TCP relay EOF")
}
})
if err != nil {
logrus.WithField("error", err).Fatal("Failed to initialize TCP relay")
}
logrus.WithField("addr", tcpr.Listen).Info("TCP relay up and running")
errChan <- rl.ListenAndServe()
}(tcpr)
}
} }
if len(config.UDPRelay.Listen) > 0 { if len(config.UDPRelay.Listen) > 0 {
go func() { config.UDPRelays = append(config.UDPRelays, Relay{
rl, err := relay.NewUDPRelay(client, transport.DefaultTransport, Listen: config.UDPRelay.Listen,
config.UDPRelay.Listen, config.UDPRelay.Remote, Remote: config.UDPRelay.Remote,
time.Duration(config.UDPRelay.Timeout)*time.Second, Timeout: config.UDPRelay.Timeout,
func(addr net.Addr) { })
logrus.WithFields(logrus.Fields{ }
"src": addr.String(),
}).Debug("UDP relay request") if len(config.UDPRelays) > 0 {
}, for _, udpr := range config.UDPRelays {
func(addr net.Addr, err error) { go func(udpr Relay) {
if err != relay.ErrTimeout { rl, err := relay.NewUDPRelay(client, transport.DefaultTransport,
logrus.WithFields(logrus.Fields{ udpr.Listen, udpr.Remote,
"error": err, time.Duration(udpr.Timeout)*time.Second,
"src": addr.String(), func(addr net.Addr) {
}).Info("UDP relay error")
} else {
logrus.WithFields(logrus.Fields{ logrus.WithFields(logrus.Fields{
"src": addr.String(), "src": addr.String(),
}).Debug("UDP relay session closed") }).Debug("UDP relay request")
} },
}) func(addr net.Addr, err error) {
if err != nil { if err != relay.ErrTimeout {
logrus.WithField("error", err).Fatal("Failed to initialize UDP relay") logrus.WithFields(logrus.Fields{
} "error": err,
logrus.WithField("addr", config.UDPRelay.Listen).Info("UDP relay up and running") "src": addr.String(),
errChan <- rl.ListenAndServe() }).Info("UDP relay error")
}() } else {
logrus.WithFields(logrus.Fields{
"src": addr.String(),
}).Debug("UDP relay session closed")
}
})
if err != nil {
logrus.WithField("error", err).Fatal("Failed to initialize UDP relay")
}
logrus.WithField("addr", udpr.Listen).Info("UDP relay up and running")
errChan <- rl.ListenAndServe()
}(udpr)
}
} }
if len(config.TCPTProxy.Listen) > 0 { if len(config.TCPTProxy.Listen) > 0 {

View File

@ -3,6 +3,8 @@ package main
import ( import (
"errors" "errors"
"fmt" "fmt"
"github.com/sirupsen/logrus"
"github.com/yosuke-furukawa/json5/encoding/json5" "github.com/yosuke-furukawa/json5/encoding/json5"
) )
@ -70,6 +72,25 @@ func (c *serverConfig) String() string {
return fmt.Sprintf("%+v", *c) return fmt.Sprintf("%+v", *c)
} }
type Relay struct {
Listen string `json:"listen"`
Remote string `json:"remote"`
Timeout int `json:"timeout"`
}
func (r *Relay) Check() error {
if len(r.Listen) == 0 {
return errors.New("no relay listen address")
}
if len(r.Remote) == 0 {
return errors.New("no relay remote address")
}
if r.Timeout != 0 && r.Timeout <= 4 {
return errors.New("invalid relay timeout")
}
return nil
}
type clientConfig struct { type clientConfig struct {
Server string `json:"server"` Server string `json:"server"`
UpMbps int `json:"up_mbps"` UpMbps int `json:"up_mbps"`
@ -99,16 +120,10 @@ type clientConfig struct {
DNS []string `json:"dns"` DNS []string `json:"dns"`
Persist bool `json:"persist"` Persist bool `json:"persist"`
} `json:"tun"` } `json:"tun"`
TCPRelay struct { TCPRelays []Relay `json:"relay_tcps"`
Listen string `json:"listen"` TCPRelay Relay `json:"relay_tcp"` // deprecated, but we still support it for backward compatibility
Remote string `json:"remote"` UDPRelays []Relay `json:"relay_udps"`
Timeout int `json:"timeout"` UDPRelay Relay `json:"relay_udp"` // deprecated, but we still support it for backward compatibility
} `json:"relay_tcp"`
UDPRelay struct {
Listen string `json:"listen"`
Remote string `json:"remote"`
Timeout int `json:"timeout"`
} `json:"relay_udp"`
TCPTProxy struct { TCPTProxy struct {
Listen string `json:"listen"` Listen string `json:"listen"`
Timeout int `json:"timeout"` Timeout int `json:"timeout"`
@ -133,15 +148,10 @@ type clientConfig struct {
func (c *clientConfig) Check() error { func (c *clientConfig) Check() error {
if len(c.SOCKS5.Listen) == 0 && len(c.HTTP.Listen) == 0 && len(c.TUN.Name) == 0 && if len(c.SOCKS5.Listen) == 0 && len(c.HTTP.Listen) == 0 && len(c.TUN.Name) == 0 &&
len(c.TCPRelay.Listen) == 0 && len(c.UDPRelay.Listen) == 0 && len(c.TCPRelay.Listen) == 0 && len(c.UDPRelay.Listen) == 0 &&
len(c.TCPRelays) == 0 && len(c.UDPRelays) == 0 &&
len(c.TCPTProxy.Listen) == 0 && len(c.UDPTProxy.Listen) == 0 { len(c.TCPTProxy.Listen) == 0 && len(c.UDPTProxy.Listen) == 0 {
return errors.New("please enable at least one mode") return errors.New("please enable at least one mode")
} }
if len(c.TCPRelay.Listen) > 0 && len(c.TCPRelay.Remote) == 0 {
return errors.New("no TCP relay remote address")
}
if len(c.UDPRelay.Listen) > 0 && len(c.UDPRelay.Remote) == 0 {
return errors.New("no UDP relay remote address")
}
if c.SOCKS5.Timeout != 0 && c.SOCKS5.Timeout <= 4 { if c.SOCKS5.Timeout != 0 && c.SOCKS5.Timeout <= 4 {
return errors.New("invalid SOCKS5 timeout") return errors.New("invalid SOCKS5 timeout")
} }
@ -151,12 +161,28 @@ func (c *clientConfig) Check() error {
if c.TUN.Timeout != 0 && c.TUN.Timeout < 4 { if c.TUN.Timeout != 0 && c.TUN.Timeout < 4 {
return errors.New("invalid TUN timeout") return errors.New("invalid TUN timeout")
} }
if len(c.TCPRelay.Listen) > 0 && len(c.TCPRelay.Remote) == 0 {
return errors.New("no TCP relay remote address")
}
if len(c.UDPRelay.Listen) > 0 && len(c.UDPRelay.Remote) == 0 {
return errors.New("no UDP relay remote address")
}
if c.TCPRelay.Timeout != 0 && c.TCPRelay.Timeout <= 4 { if c.TCPRelay.Timeout != 0 && c.TCPRelay.Timeout <= 4 {
return errors.New("invalid TCP relay timeout") return errors.New("invalid TCP relay timeout")
} }
if c.UDPRelay.Timeout != 0 && c.UDPRelay.Timeout <= 4 { if c.UDPRelay.Timeout != 0 && c.UDPRelay.Timeout <= 4 {
return errors.New("invalid UDP relay timeout") return errors.New("invalid UDP relay timeout")
} }
for _, r := range c.TCPRelays {
if err := r.Check(); err != nil {
return err
}
}
for _, r := range c.UDPRelays {
if err := r.Check(); err != nil {
return err
}
}
if c.TCPTProxy.Timeout != 0 && c.TCPTProxy.Timeout <= 4 { if c.TCPTProxy.Timeout != 0 && c.TCPTProxy.Timeout <= 4 {
return errors.New("invalid TCP TProxy timeout") return errors.New("invalid TCP TProxy timeout")
} }
@ -173,6 +199,12 @@ func (c *clientConfig) Check() error {
(c.ReceiveWindow != 0 && c.ReceiveWindow < 65536) { (c.ReceiveWindow != 0 && c.ReceiveWindow < 65536) {
return errors.New("invalid receive window size") return errors.New("invalid receive window size")
} }
if len(c.TCPRelay.Listen) > 0 {
logrus.Warn("'relay_tcp' is deprecated, please use 'relay_tcps' instead")
}
if len(c.UDPRelay.Listen) > 0 {
logrus.Warn("config 'relay_udp' is deprecated, please use 'relay_udps' instead")
}
return nil return nil
} }

View File

@ -9,9 +9,8 @@ import (
nested "github.com/antonfisher/nested-logrus-formatter" nested "github.com/antonfisher/nested-logrus-formatter"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/yosuke-furukawa/json5/encoding/json5"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
"github.com/yosuke-furukawa/json5/encoding/json5"
) )
var ( var (