dialer: add bind device

This commit is contained in:
ginuerzh
2022-03-02 21:36:27 +08:00
parent ffdf11e89e
commit b96d37d4cc
29 changed files with 348 additions and 225 deletions

View File

@ -75,11 +75,7 @@ func (d *grpcDialer) Dial(ctx context.Context, addr string, opts ...dialer.DialO
grpcOpts := []grpc.DialOption{
// grpc.WithBlock(),
grpc.WithContextDialer(func(c context.Context, s string) (net.Conn, error) {
netd := options.NetDialer
if netd == nil {
netd = dialer.DefaultNetDialer
}
return netd.Dial(c, "tcp", s)
return options.NetDialer.Dial(c, "tcp", s)
}),
grpc.WithAuthority(host),
grpc.WithConnectParams(grpc.ConnectParams{

View File

@ -7,6 +7,7 @@ import (
"sync"
"time"
net_dialer "github.com/go-gost/gost/pkg/common/net/dialer"
"github.com/go-gost/gost/pkg/dialer"
http2_util "github.com/go-gost/gost/pkg/internal/util/http2"
"github.com/go-gost/gost/pkg/logger"
@ -75,7 +76,7 @@ func (d *http2Dialer) Dial(ctx context.Context, address string, opts ...dialer.D
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
netd := options.NetDialer
if netd == nil {
netd = dialer.DefaultNetDialer
netd = net_dialer.DefaultNetDialer
}
return netd.Dial(ctx, network, addr)
},

View File

@ -93,22 +93,14 @@ func (d *h2Dialer) Dial(ctx context.Context, address string, opts ...dialer.Dial
if d.h2c {
client.Transport = &http2.Transport{
DialTLS: func(network, addr string, cfg *tls.Config) (net.Conn, error) {
netd := options.NetDialer
if netd == nil {
netd = dialer.DefaultNetDialer
}
return netd.Dial(ctx, network, addr)
return options.NetDialer.Dial(ctx, network, addr)
},
}
} else {
client.Transport = &http.Transport{
TLSClientConfig: d.options.TLSConfig,
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
netd := options.NetDialer
if netd == nil {
netd = dialer.DefaultNetDialer
}
return netd.Dial(ctx, network, addr)
return options.NetDialer.Dial(ctx, network, addr)
},
ForceAttemptHTTP2: true,
MaxIdleConns: 100,

View File

@ -2,14 +2,16 @@ package http3
import (
"context"
"crypto/tls"
"net"
"net/http"
"sync"
"github.com/go-gost/gost/pkg/dialer"
pht_util "github.com/go-gost/gost/pkg/internal/util/pht"
"github.com/go-gost/gost/pkg/logger"
md "github.com/go-gost/gost/pkg/metadata"
"github.com/go-gost/gost/pkg/registry"
"github.com/lucas-clemente/quic-go"
"github.com/lucas-clemente/quic-go/http3"
)
@ -19,10 +21,10 @@ func init() {
}
type http3Dialer struct {
client *pht_util.Client
md metadata
logger logger.Logger
options dialer.Options
clients map[string]*pht_util.Client
clientMutex sync.Mutex
md metadata
options dialer.Options
}
func NewDialer(opts ...dialer.Option) dialer.Dialer {
@ -32,7 +34,7 @@ func NewDialer(opts ...dialer.Option) dialer.Dialer {
}
return &http3Dialer{
logger: options.Logger,
clients: make(map[string]*pht_util.Client),
options: options,
}
}
@ -42,23 +44,64 @@ func (d *http3Dialer) Init(md md.Metadata) (err error) {
return
}
tr := &http3.RoundTripper{
TLSClientConfig: d.options.TLSConfig,
}
d.client = &pht_util.Client{
Client: &http.Client{
// Timeout: 60 * time.Second,
Transport: tr,
},
AuthorizePath: d.md.authorizePath,
PushPath: d.md.pushPath,
PullPath: d.md.pullPath,
TLSEnabled: true,
Logger: d.options.Logger,
}
return nil
}
func (d *http3Dialer) Dial(ctx context.Context, addr string, opts ...dialer.DialOption) (net.Conn, error) {
return d.client.Dial(ctx, addr)
d.clientMutex.Lock()
defer d.clientMutex.Unlock()
client, ok := d.clients[addr]
if !ok {
var options dialer.DialOptions
for _, opt := range opts {
opt(&options)
}
host := d.md.host
if host == "" {
host = options.Host
}
if h, _, _ := net.SplitHostPort(host); h != "" {
host = h
}
client = &pht_util.Client{
Host: host,
Client: &http.Client{
// Timeout: 60 * time.Second,
Transport: &http3.RoundTripper{
TLSClientConfig: d.options.TLSConfig,
Dial: func(network, adr string, tlsCfg *tls.Config, cfg *quic.Config) (quic.EarlySession, error) {
// d.options.Logger.Infof("dial: %s/%s, %s", addr, network, host)
udpAddr, err := net.ResolveUDPAddr("udp", addr)
if err != nil {
return nil, err
}
udpConn, err := options.NetDialer.Dial(context.Background(), "udp", "")
if err != nil {
return nil, err
}
return quic.DialEarly(udpConn.(net.PacketConn), udpAddr, host, tlsCfg, cfg)
},
},
},
AuthorizePath: d.md.authorizePath,
PushPath: d.md.pushPath,
PullPath: d.md.pullPath,
TLSEnabled: true,
Logger: d.options.Logger,
}
d.clients[addr] = client
}
return client.Dial(ctx, addr)
}
// Multiplex implements dialer.Multiplexer interface.
func (d *http3Dialer) Multiplex() bool {
return true
}

View File

@ -23,6 +23,7 @@ type metadata struct {
authorizePath string
pushPath string
pullPath string
host string
}
func (d *http3Dialer) parseMetadata(md mdata.Metadata) (err error) {
@ -30,6 +31,7 @@ func (d *http3Dialer) parseMetadata(md mdata.Metadata) (err error) {
authorizePath = "authorizePath"
pushPath = "pushPath"
pullPath = "pullPath"
host = "host"
)
d.md.authorizePath = mdata.GetString(md, authorizePath)
@ -44,5 +46,7 @@ func (d *http3Dialer) parseMetadata(md mdata.Metadata) (err error) {
if !strings.HasPrefix(d.md.pullPath, "/") {
d.md.pullPath = defaultPullPath
}
d.md.host = mdata.GetString(md, host)
return
}

View File

@ -85,11 +85,7 @@ func (d *kcpDialer) Dial(ctx context.Context, addr string, opts ...dialer.DialOp
PacketConn: pc,
}
} else {
netd := options.NetDialer
if netd == nil {
netd = dialer.DefaultNetDialer
}
conn, err = netd.Dial(ctx, "udp", addr)
conn, err = options.NetDialer.Dial(ctx, "udp", addr)
if err != nil {
return nil, err
}

View File

@ -1,84 +0,0 @@
package dialer
import (
"context"
"fmt"
"net"
"time"
"github.com/go-gost/gost/pkg/logger"
)
var (
DefaultNetDialer = &NetDialer{
Timeout: 30 * time.Second,
}
)
type NetDialer struct {
Interface string
Timeout time.Duration
DialFunc func(ctx context.Context, network, addr string) (net.Conn, error)
}
func (d *NetDialer) Dial(ctx context.Context, network, addr string) (net.Conn, error) {
ifAddr, err := parseInterfaceAddr(d.Interface, network)
if err != nil {
return nil, err
}
if d.DialFunc != nil {
return d.DialFunc(ctx, network, addr)
}
logger.Default().Infof("interface: %s %s %v", d.Interface, network, ifAddr)
switch network {
case "udp", "udp4", "udp6":
if addr == "" {
var laddr *net.UDPAddr
if ifAddr != nil {
laddr, _ = ifAddr.(*net.UDPAddr)
}
return net.ListenUDP(network, laddr)
}
case "tcp", "tcp4", "tcp6":
default:
return nil, fmt.Errorf("dial: unsupported network %s", network)
}
netd := net.Dialer{
Timeout: d.Timeout,
LocalAddr: ifAddr,
}
return netd.DialContext(ctx, network, addr)
}
func parseInterfaceAddr(ifceName, network string) (net.Addr, error) {
if ifceName == "" {
return nil, nil
}
ip := net.ParseIP(ifceName)
if ip == nil {
ifce, err := net.InterfaceByName(ifceName)
if err != nil {
return nil, err
}
addrs, err := ifce.Addrs()
if err != nil {
return nil, err
}
if len(addrs) == 0 {
return nil, fmt.Errorf("addr not found for interface %s", ifceName)
}
ip = addrs[0].(*net.IPNet).IP
}
switch network {
case "tcp", "tcp4", "tcp6":
return &net.TCPAddr{IP: ip}, nil
case "udp", "udp4", "udp6":
return &net.UDPAddr{IP: ip}, nil
default:
return &net.IPAddr{IP: ip}, nil
}
}

View File

@ -40,11 +40,7 @@ func (d *obfsHTTPDialer) Dial(ctx context.Context, addr string, opts ...dialer.D
opt(options)
}
netd := options.NetDialer
if netd == nil {
netd = dialer.DefaultNetDialer
}
conn, err := netd.Dial(ctx, "tcp", addr)
conn, err := options.NetDialer.Dial(ctx, "tcp", addr)
if err != nil {
d.logger.Error(err)
}

View File

@ -40,11 +40,7 @@ func (d *obfsTLSDialer) Dial(ctx context.Context, addr string, opts ...dialer.Di
opt(options)
}
netd := options.NetDialer
if netd == nil {
netd = dialer.DefaultNetDialer
}
conn, err := netd.Dial(ctx, "tcp", addr)
conn, err := options.NetDialer.Dial(ctx, "tcp", addr)
if err != nil {
d.logger.Error(err)
}

View File

@ -4,6 +4,7 @@ import (
"crypto/tls"
"net/url"
"github.com/go-gost/gost/pkg/common/net/dialer"
"github.com/go-gost/gost/pkg/logger"
)
@ -35,7 +36,7 @@ func LoggerOption(logger logger.Logger) Option {
type DialOptions struct {
Host string
NetDialer *NetDialer
NetDialer *dialer.NetDialer
}
type DialOption func(opts *DialOptions)
@ -46,7 +47,7 @@ func HostDialOption(host string) DialOption {
}
}
func NetDialerDialOption(netd *NetDialer) DialOption {
func NetDialerDialOption(netd *dialer.NetDialer) DialOption {
return func(opts *DialOptions) {
opts.NetDialer = netd
}

View File

@ -4,6 +4,7 @@ import (
"context"
"net"
"net/http"
"sync"
"time"
"github.com/go-gost/gost/pkg/dialer"
@ -19,11 +20,12 @@ func init() {
}
type phtDialer struct {
tlsEnabled bool
client *pht_util.Client
md metadata
logger logger.Logger
options dialer.Options
clients map[string]*pht_util.Client
clientMutex sync.Mutex
tlsEnabled bool
md metadata
logger logger.Logger
options dialer.Options
}
func NewDialer(opts ...dialer.Option) dialer.Dialer {
@ -33,7 +35,7 @@ func NewDialer(opts ...dialer.Option) dialer.Dialer {
}
return &phtDialer{
logger: options.Logger,
clients: make(map[string]*pht_util.Client),
options: options,
}
}
@ -46,7 +48,7 @@ func NewTLSDialer(opts ...dialer.Option) dialer.Dialer {
return &phtDialer{
tlsEnabled: true,
logger: options.Logger,
clients: make(map[string]*pht_util.Client),
options: options,
}
}
@ -56,36 +58,57 @@ func (d *phtDialer) Init(md md.Metadata) (err error) {
return
}
tr := &http.Transport{
// Proxy: http.ProxyFromEnvironment,
DialContext: (&net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
}).DialContext,
ForceAttemptHTTP2: true,
MaxIdleConns: 100,
IdleConnTimeout: 90 * time.Second,
TLSHandshakeTimeout: 10 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
}
if d.tlsEnabled {
tr.TLSClientConfig = d.options.TLSConfig
}
d.client = &pht_util.Client{
Client: &http.Client{
// Timeout: 60 * time.Second,
Transport: tr,
},
AuthorizePath: d.md.authorizePath,
PushPath: d.md.pushPath,
PullPath: d.md.pullPath,
TLSEnabled: d.tlsEnabled,
Logger: d.options.Logger,
}
return nil
}
func (d *phtDialer) Dial(ctx context.Context, addr string, opts ...dialer.DialOption) (net.Conn, error) {
return d.client.Dial(ctx, addr)
d.clientMutex.Lock()
defer d.clientMutex.Unlock()
client, ok := d.clients[addr]
if !ok {
var options dialer.DialOptions
for _, opt := range opts {
opt(&options)
}
host := d.md.host
if host == "" {
host = options.Host
}
if h, _, _ := net.SplitHostPort(host); h != "" {
host = h
}
tr := &http.Transport{
// Proxy: http.ProxyFromEnvironment,
DialContext: func(ctx context.Context, network, adr string) (net.Conn, error) {
return options.NetDialer.Dial(ctx, network, addr)
},
ForceAttemptHTTP2: true,
MaxIdleConns: 100,
IdleConnTimeout: 90 * time.Second,
TLSHandshakeTimeout: 10 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
}
if d.tlsEnabled {
tr.TLSClientConfig = d.options.TLSConfig
}
client = &pht_util.Client{
Host: host,
Client: &http.Client{
// Timeout: 60 * time.Second,
Transport: tr,
},
AuthorizePath: d.md.authorizePath,
PushPath: d.md.pushPath,
PullPath: d.md.pullPath,
TLSEnabled: d.tlsEnabled,
Logger: d.options.Logger,
}
d.clients[addr] = client
}
return client.Dial(ctx, addr)
}

View File

@ -23,6 +23,7 @@ type metadata struct {
authorizePath string
pushPath string
pullPath string
host string
}
func (d *phtDialer) parseMetadata(md mdata.Metadata) (err error) {
@ -30,6 +31,7 @@ func (d *phtDialer) parseMetadata(md mdata.Metadata) (err error) {
authorizePath = "authorizePath"
pushPath = "pushPath"
pullPath = "pullPath"
host = "host"
)
d.md.authorizePath = mdata.GetString(md, authorizePath)
@ -44,5 +46,7 @@ func (d *phtDialer) parseMetadata(md mdata.Metadata) (err error) {
if !strings.HasPrefix(d.md.pullPath, "/") {
d.md.pullPath = defaultPullPath
}
d.md.host = mdata.GetString(md, host)
return
}

View File

@ -64,11 +64,14 @@ func (d *quicDialer) Dial(ctx context.Context, addr string, opts ...dialer.DialO
opt(options)
}
netd := options.NetDialer
if netd == nil {
netd = dialer.DefaultNetDialer
host := d.md.host
if host == "" {
host = options.Host
}
conn, err = netd.Dial(ctx, "udp", "")
if h, _, _ := net.SplitHostPort(host); h != "" {
host = h
}
conn, err = options.NetDialer.Dial(ctx, "udp", "")
if err != nil {
return nil, err
}

View File

@ -12,6 +12,7 @@ type metadata struct {
handshakeTimeout time.Duration
cipherKey []byte
host string
}
func (d *quicDialer) parseMetadata(md mdata.Metadata) (err error) {
@ -21,6 +22,7 @@ func (d *quicDialer) parseMetadata(md mdata.Metadata) (err error) {
maxIdleTimeout = "maxIdleTimeout"
cipherKey = "cipherKey"
host = "host"
)
d.md.handshakeTimeout = mdata.GetDuration(md, handshakeTimeout)
@ -32,5 +34,7 @@ func (d *quicDialer) parseMetadata(md mdata.Metadata) (err error) {
d.md.keepAlive = mdata.GetBool(md, keepAlive)
d.md.handshakeTimeout = mdata.GetDuration(md, handshakeTimeout)
d.md.maxIdleTimeout = mdata.GetDuration(md, maxIdleTimeout)
d.md.host = mdata.GetString(md, host)
return
}

View File

@ -66,11 +66,7 @@ func (d *sshDialer) Dial(ctx context.Context, addr string, opts ...dialer.DialOp
opt(&options)
}
netd := options.NetDialer
if netd == nil {
netd = dialer.DefaultNetDialer
}
conn, err = netd.Dial(ctx, "tcp", addr)
conn, err = options.NetDialer.Dial(ctx, "tcp", addr)
if err != nil {
return
}

View File

@ -65,11 +65,7 @@ func (d *sshdDialer) Dial(ctx context.Context, addr string, opts ...dialer.DialO
opt(&options)
}
netd := options.NetDialer
if netd == nil {
netd = dialer.DefaultNetDialer
}
conn, err = netd.Dial(ctx, "tcp", addr)
conn, err = options.NetDialer.Dial(ctx, "tcp", addr)
if err != nil {
return
}

View File

@ -40,11 +40,7 @@ func (d *tcpDialer) Dial(ctx context.Context, addr string, opts ...dialer.DialOp
opt(&options)
}
netd := options.NetDialer
if netd == nil {
netd = dialer.DefaultNetDialer
}
conn, err := netd.Dial(ctx, "tcp", addr)
conn, err := options.NetDialer.Dial(ctx, "tcp", addr)
if err != nil {
d.logger.Error(err)
}

View File

@ -44,11 +44,7 @@ func (d *tlsDialer) Dial(ctx context.Context, addr string, opts ...dialer.DialOp
opt(&options)
}
netd := options.NetDialer
if netd == nil {
netd = dialer.DefaultNetDialer
}
conn, err := netd.Dial(ctx, "tcp", addr)
conn, err := options.NetDialer.Dial(ctx, "tcp", addr)
if err != nil {
d.logger.Error(err)
}

View File

@ -68,11 +68,7 @@ func (d *mtlsDialer) Dial(ctx context.Context, addr string, opts ...dialer.DialO
opt(&options)
}
netd := options.NetDialer
if netd == nil {
netd = dialer.DefaultNetDialer
}
conn, err = netd.Dial(ctx, "tcp", addr)
conn, err = options.NetDialer.Dial(ctx, "tcp", addr)
if err != nil {
return
}

View File

@ -40,11 +40,7 @@ func (d *udpDialer) Dial(ctx context.Context, addr string, opts ...dialer.DialOp
opt(&options)
}
netd := options.NetDialer
if netd == nil {
netd = dialer.DefaultNetDialer
}
c, err := netd.Dial(ctx, "udp", addr)
c, err := options.NetDialer.Dial(ctx, "udp", addr)
if err != nil {
return nil, err
}

View File

@ -61,11 +61,7 @@ func (d *wsDialer) Dial(ctx context.Context, addr string, opts ...dialer.DialOpt
opt(&options)
}
netd := options.NetDialer
if netd == nil {
netd = dialer.DefaultNetDialer
}
conn, err := netd.Dial(ctx, "tcp", addr)
conn, err := options.NetDialer.Dial(ctx, "tcp", addr)
if err != nil {
d.logger.Error(err)
}

View File

@ -85,11 +85,7 @@ func (d *mwsDialer) Dial(ctx context.Context, addr string, opts ...dialer.DialOp
opt(&options)
}
netd := options.NetDialer
if netd == nil {
netd = dialer.DefaultNetDialer
}
conn, err = netd.Dial(ctx, "tcp", addr)
conn, err = options.NetDialer.Dial(ctx, "tcp", addr)
if err != nil {
return
}