dialer: add bind device
This commit is contained in:
parent
ffdf11e89e
commit
b96d37d4cc
@ -7,9 +7,9 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/go-gost/gost/pkg/common/net/dialer"
|
||||||
"github.com/go-gost/gost/pkg/common/util/udp"
|
"github.com/go-gost/gost/pkg/common/util/udp"
|
||||||
"github.com/go-gost/gost/pkg/connector"
|
"github.com/go-gost/gost/pkg/connector"
|
||||||
"github.com/go-gost/gost/pkg/dialer"
|
|
||||||
"github.com/go-gost/gost/pkg/logger"
|
"github.com/go-gost/gost/pkg/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
net_dialer "github.com/go-gost/gost/pkg/common/net/dialer"
|
||||||
"github.com/go-gost/gost/pkg/connector"
|
"github.com/go-gost/gost/pkg/connector"
|
||||||
"github.com/go-gost/gost/pkg/dialer"
|
"github.com/go-gost/gost/pkg/dialer"
|
||||||
)
|
)
|
||||||
@ -39,7 +40,7 @@ func (tr *Transport) WithConnector(connector connector.Connector) *Transport {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (tr *Transport) Dial(ctx context.Context, addr string) (net.Conn, error) {
|
func (tr *Transport) Dial(ctx context.Context, addr string) (net.Conn, error) {
|
||||||
netd := &dialer.NetDialer{
|
netd := &net_dialer.NetDialer{
|
||||||
Interface: tr.ifceName,
|
Interface: tr.ifceName,
|
||||||
Timeout: 30 * time.Second,
|
Timeout: 30 * time.Second,
|
||||||
}
|
}
|
||||||
|
144
pkg/common/net/dialer/dialer.go
Normal file
144
pkg/common/net/dialer/dialer.go
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
package dialer
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"syscall"
|
||||||
|
"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)
|
||||||
|
Logger logger.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *NetDialer) Dial(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||||
|
if d == nil {
|
||||||
|
d = DefaultNetDialer
|
||||||
|
}
|
||||||
|
log := d.Logger
|
||||||
|
if log == nil {
|
||||||
|
log = logger.Default()
|
||||||
|
}
|
||||||
|
|
||||||
|
ifceName, 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/%s", ifceName, ifAddr, network)
|
||||||
|
|
||||||
|
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,
|
||||||
|
Control: func(network, address string, c syscall.RawConn) error {
|
||||||
|
var cerr error
|
||||||
|
err := c.Control(func(fd uintptr) {
|
||||||
|
cerr = bindDevice(fd, ifceName)
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if cerr != nil {
|
||||||
|
return cerr
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return netd.DialContext(ctx, network, addr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseInterfaceAddr(ifceName, network string) (ifce string, addr net.Addr, err error) {
|
||||||
|
if ifceName == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ip := net.ParseIP(ifceName)
|
||||||
|
if ip == nil {
|
||||||
|
var ife *net.Interface
|
||||||
|
ife, err = net.InterfaceByName(ifceName)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var addrs []net.Addr
|
||||||
|
addrs, err = ife.Addrs()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if len(addrs) == 0 {
|
||||||
|
err = fmt.Errorf("addr not found for interface %s", ifceName)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ip = addrs[0].(*net.IPNet).IP
|
||||||
|
ifce = ifceName
|
||||||
|
} else {
|
||||||
|
ifce, err = findInterfaceByIP(ip)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
port := 0
|
||||||
|
switch network {
|
||||||
|
case "tcp", "tcp4", "tcp6":
|
||||||
|
addr = &net.TCPAddr{IP: ip, Port: port}
|
||||||
|
return
|
||||||
|
case "udp", "udp4", "udp6":
|
||||||
|
addr = &net.UDPAddr{IP: ip, Port: port}
|
||||||
|
return
|
||||||
|
default:
|
||||||
|
addr = &net.IPAddr{IP: ip}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func findInterfaceByIP(ip net.IP) (string, error) {
|
||||||
|
ifces, err := net.Interfaces()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
for _, ifce := range ifces {
|
||||||
|
addrs, _ := ifce.Addrs()
|
||||||
|
if len(addrs) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for _, addr := range addrs {
|
||||||
|
ipAddr, _ := addr.(*net.IPNet)
|
||||||
|
if ipAddr == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// logger.Default().Infof("%s-%s", ipAddr, ip)
|
||||||
|
if ipAddr.IP.Equal(ip) {
|
||||||
|
return ifce.Name, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "", nil
|
||||||
|
}
|
14
pkg/common/net/dialer/dialer_linux.go
Normal file
14
pkg/common/net/dialer/dialer_linux.go
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
package dialer
|
||||||
|
|
||||||
|
import (
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
|
)
|
||||||
|
|
||||||
|
func bindDevice(fd uintptr, ifceName string) error {
|
||||||
|
// unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_REUSEADDR, 1)
|
||||||
|
// unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_REUSEPORT, 1)
|
||||||
|
if ifceName == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return unix.BindToDevice(int(fd), ifceName)
|
||||||
|
}
|
7
pkg/common/net/dialer/dialer_other.go
Normal file
7
pkg/common/net/dialer/dialer_other.go
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
//go:build !linux
|
||||||
|
|
||||||
|
package dialer
|
||||||
|
|
||||||
|
func bindDevice(fd uintptr, ifceName string) error {
|
||||||
|
return nil
|
||||||
|
}
|
@ -75,11 +75,7 @@ func (d *grpcDialer) Dial(ctx context.Context, addr string, opts ...dialer.DialO
|
|||||||
grpcOpts := []grpc.DialOption{
|
grpcOpts := []grpc.DialOption{
|
||||||
// grpc.WithBlock(),
|
// grpc.WithBlock(),
|
||||||
grpc.WithContextDialer(func(c context.Context, s string) (net.Conn, error) {
|
grpc.WithContextDialer(func(c context.Context, s string) (net.Conn, error) {
|
||||||
netd := options.NetDialer
|
return options.NetDialer.Dial(c, "tcp", s)
|
||||||
if netd == nil {
|
|
||||||
netd = dialer.DefaultNetDialer
|
|
||||||
}
|
|
||||||
return netd.Dial(c, "tcp", s)
|
|
||||||
}),
|
}),
|
||||||
grpc.WithAuthority(host),
|
grpc.WithAuthority(host),
|
||||||
grpc.WithConnectParams(grpc.ConnectParams{
|
grpc.WithConnectParams(grpc.ConnectParams{
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
net_dialer "github.com/go-gost/gost/pkg/common/net/dialer"
|
||||||
"github.com/go-gost/gost/pkg/dialer"
|
"github.com/go-gost/gost/pkg/dialer"
|
||||||
http2_util "github.com/go-gost/gost/pkg/internal/util/http2"
|
http2_util "github.com/go-gost/gost/pkg/internal/util/http2"
|
||||||
"github.com/go-gost/gost/pkg/logger"
|
"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) {
|
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||||
netd := options.NetDialer
|
netd := options.NetDialer
|
||||||
if netd == nil {
|
if netd == nil {
|
||||||
netd = dialer.DefaultNetDialer
|
netd = net_dialer.DefaultNetDialer
|
||||||
}
|
}
|
||||||
return netd.Dial(ctx, network, addr)
|
return netd.Dial(ctx, network, addr)
|
||||||
},
|
},
|
||||||
|
@ -93,22 +93,14 @@ func (d *h2Dialer) Dial(ctx context.Context, address string, opts ...dialer.Dial
|
|||||||
if d.h2c {
|
if d.h2c {
|
||||||
client.Transport = &http2.Transport{
|
client.Transport = &http2.Transport{
|
||||||
DialTLS: func(network, addr string, cfg *tls.Config) (net.Conn, error) {
|
DialTLS: func(network, addr string, cfg *tls.Config) (net.Conn, error) {
|
||||||
netd := options.NetDialer
|
return options.NetDialer.Dial(ctx, network, addr)
|
||||||
if netd == nil {
|
|
||||||
netd = dialer.DefaultNetDialer
|
|
||||||
}
|
|
||||||
return netd.Dial(ctx, network, addr)
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
client.Transport = &http.Transport{
|
client.Transport = &http.Transport{
|
||||||
TLSClientConfig: d.options.TLSConfig,
|
TLSClientConfig: d.options.TLSConfig,
|
||||||
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
|
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||||
netd := options.NetDialer
|
return options.NetDialer.Dial(ctx, network, addr)
|
||||||
if netd == nil {
|
|
||||||
netd = dialer.DefaultNetDialer
|
|
||||||
}
|
|
||||||
return netd.Dial(ctx, network, addr)
|
|
||||||
},
|
},
|
||||||
ForceAttemptHTTP2: true,
|
ForceAttemptHTTP2: true,
|
||||||
MaxIdleConns: 100,
|
MaxIdleConns: 100,
|
||||||
|
@ -2,14 +2,16 @@ package http3
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"crypto/tls"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"sync"
|
||||||
|
|
||||||
"github.com/go-gost/gost/pkg/dialer"
|
"github.com/go-gost/gost/pkg/dialer"
|
||||||
pht_util "github.com/go-gost/gost/pkg/internal/util/pht"
|
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"
|
md "github.com/go-gost/gost/pkg/metadata"
|
||||||
"github.com/go-gost/gost/pkg/registry"
|
"github.com/go-gost/gost/pkg/registry"
|
||||||
|
"github.com/lucas-clemente/quic-go"
|
||||||
"github.com/lucas-clemente/quic-go/http3"
|
"github.com/lucas-clemente/quic-go/http3"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -19,9 +21,9 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type http3Dialer struct {
|
type http3Dialer struct {
|
||||||
client *pht_util.Client
|
clients map[string]*pht_util.Client
|
||||||
|
clientMutex sync.Mutex
|
||||||
md metadata
|
md metadata
|
||||||
logger logger.Logger
|
|
||||||
options dialer.Options
|
options dialer.Options
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,7 +34,7 @@ func NewDialer(opts ...dialer.Option) dialer.Dialer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &http3Dialer{
|
return &http3Dialer{
|
||||||
logger: options.Logger,
|
clients: make(map[string]*pht_util.Client),
|
||||||
options: options,
|
options: options,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -42,13 +44,49 @@ func (d *http3Dialer) Init(md md.Metadata) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
tr := &http3.RoundTripper{
|
return nil
|
||||||
TLSClientConfig: d.options.TLSConfig,
|
|
||||||
}
|
}
|
||||||
d.client = &pht_util.Client{
|
|
||||||
|
func (d *http3Dialer) Dial(ctx context.Context, addr string, opts ...dialer.DialOption) (net.Conn, error) {
|
||||||
|
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{
|
Client: &http.Client{
|
||||||
// Timeout: 60 * time.Second,
|
// Timeout: 60 * time.Second,
|
||||||
Transport: tr,
|
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,
|
AuthorizePath: d.md.authorizePath,
|
||||||
PushPath: d.md.pushPath,
|
PushPath: d.md.pushPath,
|
||||||
@ -56,9 +94,14 @@ func (d *http3Dialer) Init(md md.Metadata) (err error) {
|
|||||||
TLSEnabled: true,
|
TLSEnabled: true,
|
||||||
Logger: d.options.Logger,
|
Logger: d.options.Logger,
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
|
d.clients[addr] = client
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *http3Dialer) Dial(ctx context.Context, addr string, opts ...dialer.DialOption) (net.Conn, error) {
|
return client.Dial(ctx, addr)
|
||||||
return d.client.Dial(ctx, addr)
|
}
|
||||||
|
|
||||||
|
// Multiplex implements dialer.Multiplexer interface.
|
||||||
|
func (d *http3Dialer) Multiplex() bool {
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@ type metadata struct {
|
|||||||
authorizePath string
|
authorizePath string
|
||||||
pushPath string
|
pushPath string
|
||||||
pullPath string
|
pullPath string
|
||||||
|
host string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *http3Dialer) parseMetadata(md mdata.Metadata) (err error) {
|
func (d *http3Dialer) parseMetadata(md mdata.Metadata) (err error) {
|
||||||
@ -30,6 +31,7 @@ func (d *http3Dialer) parseMetadata(md mdata.Metadata) (err error) {
|
|||||||
authorizePath = "authorizePath"
|
authorizePath = "authorizePath"
|
||||||
pushPath = "pushPath"
|
pushPath = "pushPath"
|
||||||
pullPath = "pullPath"
|
pullPath = "pullPath"
|
||||||
|
host = "host"
|
||||||
)
|
)
|
||||||
|
|
||||||
d.md.authorizePath = mdata.GetString(md, authorizePath)
|
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, "/") {
|
if !strings.HasPrefix(d.md.pullPath, "/") {
|
||||||
d.md.pullPath = defaultPullPath
|
d.md.pullPath = defaultPullPath
|
||||||
}
|
}
|
||||||
|
|
||||||
|
d.md.host = mdata.GetString(md, host)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -85,11 +85,7 @@ func (d *kcpDialer) Dial(ctx context.Context, addr string, opts ...dialer.DialOp
|
|||||||
PacketConn: pc,
|
PacketConn: pc,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
netd := options.NetDialer
|
conn, err = options.NetDialer.Dial(ctx, "udp", addr)
|
||||||
if netd == nil {
|
|
||||||
netd = dialer.DefaultNetDialer
|
|
||||||
}
|
|
||||||
conn, err = netd.Dial(ctx, "udp", addr)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
|
@ -40,11 +40,7 @@ func (d *obfsHTTPDialer) Dial(ctx context.Context, addr string, opts ...dialer.D
|
|||||||
opt(options)
|
opt(options)
|
||||||
}
|
}
|
||||||
|
|
||||||
netd := options.NetDialer
|
conn, err := options.NetDialer.Dial(ctx, "tcp", addr)
|
||||||
if netd == nil {
|
|
||||||
netd = dialer.DefaultNetDialer
|
|
||||||
}
|
|
||||||
conn, err := netd.Dial(ctx, "tcp", addr)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
d.logger.Error(err)
|
d.logger.Error(err)
|
||||||
}
|
}
|
||||||
|
@ -40,11 +40,7 @@ func (d *obfsTLSDialer) Dial(ctx context.Context, addr string, opts ...dialer.Di
|
|||||||
opt(options)
|
opt(options)
|
||||||
}
|
}
|
||||||
|
|
||||||
netd := options.NetDialer
|
conn, err := options.NetDialer.Dial(ctx, "tcp", addr)
|
||||||
if netd == nil {
|
|
||||||
netd = dialer.DefaultNetDialer
|
|
||||||
}
|
|
||||||
conn, err := netd.Dial(ctx, "tcp", addr)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
d.logger.Error(err)
|
d.logger.Error(err)
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
|
||||||
|
"github.com/go-gost/gost/pkg/common/net/dialer"
|
||||||
"github.com/go-gost/gost/pkg/logger"
|
"github.com/go-gost/gost/pkg/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -35,7 +36,7 @@ func LoggerOption(logger logger.Logger) Option {
|
|||||||
|
|
||||||
type DialOptions struct {
|
type DialOptions struct {
|
||||||
Host string
|
Host string
|
||||||
NetDialer *NetDialer
|
NetDialer *dialer.NetDialer
|
||||||
}
|
}
|
||||||
|
|
||||||
type DialOption func(opts *DialOptions)
|
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) {
|
return func(opts *DialOptions) {
|
||||||
opts.NetDialer = netd
|
opts.NetDialer = netd
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/go-gost/gost/pkg/dialer"
|
"github.com/go-gost/gost/pkg/dialer"
|
||||||
@ -19,8 +20,9 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type phtDialer struct {
|
type phtDialer struct {
|
||||||
|
clients map[string]*pht_util.Client
|
||||||
|
clientMutex sync.Mutex
|
||||||
tlsEnabled bool
|
tlsEnabled bool
|
||||||
client *pht_util.Client
|
|
||||||
md metadata
|
md metadata
|
||||||
logger logger.Logger
|
logger logger.Logger
|
||||||
options dialer.Options
|
options dialer.Options
|
||||||
@ -33,7 +35,7 @@ func NewDialer(opts ...dialer.Option) dialer.Dialer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &phtDialer{
|
return &phtDialer{
|
||||||
logger: options.Logger,
|
clients: make(map[string]*pht_util.Client),
|
||||||
options: options,
|
options: options,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -46,7 +48,7 @@ func NewTLSDialer(opts ...dialer.Option) dialer.Dialer {
|
|||||||
|
|
||||||
return &phtDialer{
|
return &phtDialer{
|
||||||
tlsEnabled: true,
|
tlsEnabled: true,
|
||||||
logger: options.Logger,
|
clients: make(map[string]*pht_util.Client),
|
||||||
options: options,
|
options: options,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -56,12 +58,33 @@ func (d *phtDialer) Init(md md.Metadata) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *phtDialer) Dial(ctx context.Context, addr string, opts ...dialer.DialOption) (net.Conn, error) {
|
||||||
|
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{
|
tr := &http.Transport{
|
||||||
// Proxy: http.ProxyFromEnvironment,
|
// Proxy: http.ProxyFromEnvironment,
|
||||||
DialContext: (&net.Dialer{
|
DialContext: func(ctx context.Context, network, adr string) (net.Conn, error) {
|
||||||
Timeout: 30 * time.Second,
|
return options.NetDialer.Dial(ctx, network, addr)
|
||||||
KeepAlive: 30 * time.Second,
|
},
|
||||||
}).DialContext,
|
|
||||||
ForceAttemptHTTP2: true,
|
ForceAttemptHTTP2: true,
|
||||||
MaxIdleConns: 100,
|
MaxIdleConns: 100,
|
||||||
IdleConnTimeout: 90 * time.Second,
|
IdleConnTimeout: 90 * time.Second,
|
||||||
@ -72,7 +95,8 @@ func (d *phtDialer) Init(md md.Metadata) (err error) {
|
|||||||
tr.TLSClientConfig = d.options.TLSConfig
|
tr.TLSClientConfig = d.options.TLSConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
d.client = &pht_util.Client{
|
client = &pht_util.Client{
|
||||||
|
Host: host,
|
||||||
Client: &http.Client{
|
Client: &http.Client{
|
||||||
// Timeout: 60 * time.Second,
|
// Timeout: 60 * time.Second,
|
||||||
Transport: tr,
|
Transport: tr,
|
||||||
@ -83,9 +107,8 @@ func (d *phtDialer) Init(md md.Metadata) (err error) {
|
|||||||
TLSEnabled: d.tlsEnabled,
|
TLSEnabled: d.tlsEnabled,
|
||||||
Logger: d.options.Logger,
|
Logger: d.options.Logger,
|
||||||
}
|
}
|
||||||
return nil
|
d.clients[addr] = client
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *phtDialer) Dial(ctx context.Context, addr string, opts ...dialer.DialOption) (net.Conn, error) {
|
return client.Dial(ctx, addr)
|
||||||
return d.client.Dial(ctx, addr)
|
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@ type metadata struct {
|
|||||||
authorizePath string
|
authorizePath string
|
||||||
pushPath string
|
pushPath string
|
||||||
pullPath string
|
pullPath string
|
||||||
|
host string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *phtDialer) parseMetadata(md mdata.Metadata) (err error) {
|
func (d *phtDialer) parseMetadata(md mdata.Metadata) (err error) {
|
||||||
@ -30,6 +31,7 @@ func (d *phtDialer) parseMetadata(md mdata.Metadata) (err error) {
|
|||||||
authorizePath = "authorizePath"
|
authorizePath = "authorizePath"
|
||||||
pushPath = "pushPath"
|
pushPath = "pushPath"
|
||||||
pullPath = "pullPath"
|
pullPath = "pullPath"
|
||||||
|
host = "host"
|
||||||
)
|
)
|
||||||
|
|
||||||
d.md.authorizePath = mdata.GetString(md, authorizePath)
|
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, "/") {
|
if !strings.HasPrefix(d.md.pullPath, "/") {
|
||||||
d.md.pullPath = defaultPullPath
|
d.md.pullPath = defaultPullPath
|
||||||
}
|
}
|
||||||
|
|
||||||
|
d.md.host = mdata.GetString(md, host)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -64,11 +64,14 @@ func (d *quicDialer) Dial(ctx context.Context, addr string, opts ...dialer.DialO
|
|||||||
opt(options)
|
opt(options)
|
||||||
}
|
}
|
||||||
|
|
||||||
netd := options.NetDialer
|
host := d.md.host
|
||||||
if netd == nil {
|
if host == "" {
|
||||||
netd = dialer.DefaultNetDialer
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@ type metadata struct {
|
|||||||
handshakeTimeout time.Duration
|
handshakeTimeout time.Duration
|
||||||
|
|
||||||
cipherKey []byte
|
cipherKey []byte
|
||||||
|
host string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *quicDialer) parseMetadata(md mdata.Metadata) (err error) {
|
func (d *quicDialer) parseMetadata(md mdata.Metadata) (err error) {
|
||||||
@ -21,6 +22,7 @@ func (d *quicDialer) parseMetadata(md mdata.Metadata) (err error) {
|
|||||||
maxIdleTimeout = "maxIdleTimeout"
|
maxIdleTimeout = "maxIdleTimeout"
|
||||||
|
|
||||||
cipherKey = "cipherKey"
|
cipherKey = "cipherKey"
|
||||||
|
host = "host"
|
||||||
)
|
)
|
||||||
|
|
||||||
d.md.handshakeTimeout = mdata.GetDuration(md, handshakeTimeout)
|
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.keepAlive = mdata.GetBool(md, keepAlive)
|
||||||
d.md.handshakeTimeout = mdata.GetDuration(md, handshakeTimeout)
|
d.md.handshakeTimeout = mdata.GetDuration(md, handshakeTimeout)
|
||||||
d.md.maxIdleTimeout = mdata.GetDuration(md, maxIdleTimeout)
|
d.md.maxIdleTimeout = mdata.GetDuration(md, maxIdleTimeout)
|
||||||
|
|
||||||
|
d.md.host = mdata.GetString(md, host)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -66,11 +66,7 @@ func (d *sshDialer) Dial(ctx context.Context, addr string, opts ...dialer.DialOp
|
|||||||
opt(&options)
|
opt(&options)
|
||||||
}
|
}
|
||||||
|
|
||||||
netd := options.NetDialer
|
conn, err = options.NetDialer.Dial(ctx, "tcp", addr)
|
||||||
if netd == nil {
|
|
||||||
netd = dialer.DefaultNetDialer
|
|
||||||
}
|
|
||||||
conn, err = netd.Dial(ctx, "tcp", addr)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -65,11 +65,7 @@ func (d *sshdDialer) Dial(ctx context.Context, addr string, opts ...dialer.DialO
|
|||||||
opt(&options)
|
opt(&options)
|
||||||
}
|
}
|
||||||
|
|
||||||
netd := options.NetDialer
|
conn, err = options.NetDialer.Dial(ctx, "tcp", addr)
|
||||||
if netd == nil {
|
|
||||||
netd = dialer.DefaultNetDialer
|
|
||||||
}
|
|
||||||
conn, err = netd.Dial(ctx, "tcp", addr)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -40,11 +40,7 @@ func (d *tcpDialer) Dial(ctx context.Context, addr string, opts ...dialer.DialOp
|
|||||||
opt(&options)
|
opt(&options)
|
||||||
}
|
}
|
||||||
|
|
||||||
netd := options.NetDialer
|
conn, err := options.NetDialer.Dial(ctx, "tcp", addr)
|
||||||
if netd == nil {
|
|
||||||
netd = dialer.DefaultNetDialer
|
|
||||||
}
|
|
||||||
conn, err := netd.Dial(ctx, "tcp", addr)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
d.logger.Error(err)
|
d.logger.Error(err)
|
||||||
}
|
}
|
||||||
|
@ -44,11 +44,7 @@ func (d *tlsDialer) Dial(ctx context.Context, addr string, opts ...dialer.DialOp
|
|||||||
opt(&options)
|
opt(&options)
|
||||||
}
|
}
|
||||||
|
|
||||||
netd := options.NetDialer
|
conn, err := options.NetDialer.Dial(ctx, "tcp", addr)
|
||||||
if netd == nil {
|
|
||||||
netd = dialer.DefaultNetDialer
|
|
||||||
}
|
|
||||||
conn, err := netd.Dial(ctx, "tcp", addr)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
d.logger.Error(err)
|
d.logger.Error(err)
|
||||||
}
|
}
|
||||||
|
@ -68,11 +68,7 @@ func (d *mtlsDialer) Dial(ctx context.Context, addr string, opts ...dialer.DialO
|
|||||||
opt(&options)
|
opt(&options)
|
||||||
}
|
}
|
||||||
|
|
||||||
netd := options.NetDialer
|
conn, err = options.NetDialer.Dial(ctx, "tcp", addr)
|
||||||
if netd == nil {
|
|
||||||
netd = dialer.DefaultNetDialer
|
|
||||||
}
|
|
||||||
conn, err = netd.Dial(ctx, "tcp", addr)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -40,11 +40,7 @@ func (d *udpDialer) Dial(ctx context.Context, addr string, opts ...dialer.DialOp
|
|||||||
opt(&options)
|
opt(&options)
|
||||||
}
|
}
|
||||||
|
|
||||||
netd := options.NetDialer
|
c, err := options.NetDialer.Dial(ctx, "udp", addr)
|
||||||
if netd == nil {
|
|
||||||
netd = dialer.DefaultNetDialer
|
|
||||||
}
|
|
||||||
c, err := netd.Dial(ctx, "udp", addr)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -61,11 +61,7 @@ func (d *wsDialer) Dial(ctx context.Context, addr string, opts ...dialer.DialOpt
|
|||||||
opt(&options)
|
opt(&options)
|
||||||
}
|
}
|
||||||
|
|
||||||
netd := options.NetDialer
|
conn, err := options.NetDialer.Dial(ctx, "tcp", addr)
|
||||||
if netd == nil {
|
|
||||||
netd = dialer.DefaultNetDialer
|
|
||||||
}
|
|
||||||
conn, err := netd.Dial(ctx, "tcp", addr)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
d.logger.Error(err)
|
d.logger.Error(err)
|
||||||
}
|
}
|
||||||
|
@ -85,11 +85,7 @@ func (d *mwsDialer) Dial(ctx context.Context, addr string, opts ...dialer.DialOp
|
|||||||
opt(&options)
|
opt(&options)
|
||||||
}
|
}
|
||||||
|
|
||||||
netd := options.NetDialer
|
conn, err = options.NetDialer.Dial(ctx, "tcp", addr)
|
||||||
if netd == nil {
|
|
||||||
netd = dialer.DefaultNetDialer
|
|
||||||
}
|
|
||||||
conn, err = netd.Dial(ctx, "tcp", addr)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -8,12 +8,14 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httputil"
|
"net/http/httputil"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/go-gost/gost/pkg/logger"
|
"github.com/go-gost/gost/pkg/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Client struct {
|
type Client struct {
|
||||||
|
Host string
|
||||||
Client *http.Client
|
Client *http.Client
|
||||||
AuthorizePath string
|
AuthorizePath string
|
||||||
PushPath string
|
PushPath string
|
||||||
@ -23,6 +25,16 @@ type Client struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) Dial(ctx context.Context, addr string) (net.Conn, error) {
|
func (c *Client) Dial(ctx context.Context, addr string) (net.Conn, error) {
|
||||||
|
raddr, err := net.ResolveTCPAddr("tcp", addr)
|
||||||
|
if err != nil {
|
||||||
|
c.Logger.Error(err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.Host != "" {
|
||||||
|
addr = net.JoinHostPort(c.Host, strconv.Itoa(raddr.Port))
|
||||||
|
}
|
||||||
|
|
||||||
token, err := c.authorize(ctx, addr)
|
token, err := c.authorize(ctx, addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Logger.Error(err)
|
c.Logger.Error(err)
|
||||||
@ -34,9 +46,9 @@ func (c *Client) Dial(ctx context.Context, addr string) (net.Conn, error) {
|
|||||||
rxc: make(chan []byte, 128),
|
rxc: make(chan []byte, 128),
|
||||||
closed: make(chan struct{}),
|
closed: make(chan struct{}),
|
||||||
localAddr: &net.TCPAddr{},
|
localAddr: &net.TCPAddr{},
|
||||||
|
remoteAddr: raddr,
|
||||||
logger: c.Logger,
|
logger: c.Logger,
|
||||||
}
|
}
|
||||||
cn.remoteAddr, _ = net.ResolveTCPAddr("tcp", addr)
|
|
||||||
|
|
||||||
scheme := "http"
|
scheme := "http"
|
||||||
if c.TLSEnabled {
|
if c.TLSEnabled {
|
||||||
|
@ -53,6 +53,7 @@ func (c *clientConn) Write(b []byte) (n int, err error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.logger.IsLevelEnabled(logger.DebugLevel) {
|
if c.logger.IsLevelEnabled(logger.DebugLevel) {
|
||||||
dump, _ := httputil.DumpRequest(r, false)
|
dump, _ := httputil.DumpRequest(r, false)
|
||||||
c.logger.Debug(string(dump))
|
c.logger.Debug(string(dump))
|
||||||
@ -87,6 +88,7 @@ func (c *clientConn) readLoop() {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.logger.IsLevelEnabled(logger.DebugLevel) {
|
if c.logger.IsLevelEnabled(logger.DebugLevel) {
|
||||||
dump, _ := httputil.DumpRequest(r, false)
|
dump, _ := httputil.DumpRequest(r, false)
|
||||||
c.logger.Debug(string(dump))
|
c.logger.Debug(string(dump))
|
||||||
|
Loading…
Reference in New Issue
Block a user