add sockopts config
This commit is contained in:
parent
78089d8887
commit
47cfc087e9
@ -20,7 +20,6 @@ var (
|
|||||||
|
|
||||||
type Route struct {
|
type Route struct {
|
||||||
chain *Chain
|
chain *Chain
|
||||||
ifceName string
|
|
||||||
nodes []*Node
|
nodes []*Node
|
||||||
logger logger.Logger
|
logger logger.Logger
|
||||||
}
|
}
|
||||||
@ -29,14 +28,24 @@ func (r *Route) addNode(node *Node) {
|
|||||||
r.nodes = append(r.nodes, node)
|
r.nodes = append(r.nodes, node)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Route) Dial(ctx context.Context, network, address string) (net.Conn, error) {
|
func (r *Route) Dial(ctx context.Context, network, address string, opts ...DialOption) (net.Conn, error) {
|
||||||
|
var options DialOptions
|
||||||
|
for _, opt := range opts {
|
||||||
|
opt(&options)
|
||||||
|
}
|
||||||
|
|
||||||
if r.Len() == 0 {
|
if r.Len() == 0 {
|
||||||
netd := dialer.NetDialer{
|
netd := dialer.NetDialer{
|
||||||
Timeout: 30 * time.Second,
|
Timeout: options.Timeout,
|
||||||
|
Interface: options.Interface,
|
||||||
|
}
|
||||||
|
if options.SockOpts != nil {
|
||||||
|
netd.Mark = options.SockOpts.Mark
|
||||||
}
|
}
|
||||||
if r != nil {
|
if r != nil {
|
||||||
netd.Interface = r.ifceName
|
netd.Logger = r.logger
|
||||||
}
|
}
|
||||||
|
|
||||||
return netd.Dial(ctx, network, address)
|
return netd.Dial(ctx, network, address)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -198,3 +207,29 @@ func (r *Route) bindLocal(ctx context.Context, network, address string, opts ...
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type DialOptions struct {
|
||||||
|
Timeout time.Duration
|
||||||
|
Interface string
|
||||||
|
SockOpts *SockOpts
|
||||||
|
}
|
||||||
|
|
||||||
|
type DialOption func(opts *DialOptions)
|
||||||
|
|
||||||
|
func TimeoutDialOption(d time.Duration) DialOption {
|
||||||
|
return func(opts *DialOptions) {
|
||||||
|
opts.Timeout = d
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func InterfaceDialOption(ifName string) DialOption {
|
||||||
|
return func(opts *DialOptions) {
|
||||||
|
opts.Interface = ifName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func SockOptsDialOption(so *SockOpts) DialOption {
|
||||||
|
return func(opts *DialOptions) {
|
||||||
|
opts.SockOpts = so
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -13,10 +13,15 @@ import (
|
|||||||
"github.com/go-gost/core/resolver"
|
"github.com/go-gost/core/resolver"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type SockOpts struct {
|
||||||
|
Mark int
|
||||||
|
}
|
||||||
|
|
||||||
type Router struct {
|
type Router struct {
|
||||||
|
ifceName string
|
||||||
|
sockOpts *SockOpts
|
||||||
timeout time.Duration
|
timeout time.Duration
|
||||||
retries int
|
retries int
|
||||||
ifceName string
|
|
||||||
chain Chainer
|
chain Chainer
|
||||||
resolver resolver.Resolver
|
resolver resolver.Resolver
|
||||||
hosts hosts.HostMapper
|
hosts hosts.HostMapper
|
||||||
@ -38,6 +43,11 @@ func (r *Router) WithInterface(ifceName string) *Router {
|
|||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *Router) WithSockOpts(so *SockOpts) *Router {
|
||||||
|
r.sockOpts = so
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
func (r *Router) WithChain(chain Chainer) *Router {
|
func (r *Router) WithChain(chain Chainer) *Router {
|
||||||
r.chain = chain
|
r.chain = chain
|
||||||
return r
|
return r
|
||||||
@ -109,10 +119,11 @@ func (r *Router) dial(ctx context.Context, network, address string) (conn net.Co
|
|||||||
if route == nil {
|
if route == nil {
|
||||||
route = &Route{}
|
route = &Route{}
|
||||||
}
|
}
|
||||||
route.ifceName = r.ifceName
|
|
||||||
route.logger = r.logger
|
route.logger = r.logger
|
||||||
|
conn, err = route.Dial(ctx, network, address,
|
||||||
conn, err = route.Dial(ctx, network, address)
|
InterfaceDialOption(r.ifceName),
|
||||||
|
SockOptsDialOption(r.sockOpts),
|
||||||
|
)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@ import (
|
|||||||
type Transport struct {
|
type Transport struct {
|
||||||
addr string
|
addr string
|
||||||
ifceName string
|
ifceName string
|
||||||
|
sockOpts *SockOpts
|
||||||
route *Route
|
route *Route
|
||||||
dialer dialer.Dialer
|
dialer dialer.Dialer
|
||||||
connector connector.Connector
|
connector connector.Connector
|
||||||
@ -29,6 +30,11 @@ func (tr *Transport) WithInterface(ifceName string) *Transport {
|
|||||||
return tr
|
return tr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (tr *Transport) WithSockOpts(so *SockOpts) *Transport {
|
||||||
|
tr.sockOpts = so
|
||||||
|
return tr
|
||||||
|
}
|
||||||
|
|
||||||
func (tr *Transport) WithDialer(dialer dialer.Dialer) *Transport {
|
func (tr *Transport) WithDialer(dialer dialer.Dialer) *Transport {
|
||||||
tr.dialer = dialer
|
tr.dialer = dialer
|
||||||
return tr
|
return tr
|
||||||
@ -42,7 +48,10 @@ 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 := &net_dialer.NetDialer{
|
netd := &net_dialer.NetDialer{
|
||||||
Interface: tr.ifceName,
|
Interface: tr.ifceName,
|
||||||
Timeout: 30 * time.Second,
|
Timeout: 15 * time.Second,
|
||||||
|
}
|
||||||
|
if tr.sockOpts != nil {
|
||||||
|
netd.Mark = tr.sockOpts.Mark
|
||||||
}
|
}
|
||||||
if tr.route.Len() > 0 {
|
if tr.route.Len() > 0 {
|
||||||
netd.DialFunc = func(ctx context.Context, network, addr string) (net.Conn, error) {
|
netd.DialFunc = func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||||
|
@ -10,14 +10,17 @@ import (
|
|||||||
"github.com/go-gost/core/logger"
|
"github.com/go-gost/core/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
DefaultTimeout = 15 * time.Second
|
||||||
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
DefaultNetDialer = &NetDialer{
|
DefaultNetDialer = &NetDialer{}
|
||||||
Timeout: 30 * time.Second,
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type NetDialer struct {
|
type NetDialer struct {
|
||||||
Interface string
|
Interface string
|
||||||
|
Mark int
|
||||||
Timeout time.Duration
|
Timeout time.Duration
|
||||||
DialFunc func(ctx context.Context, network, addr string) (net.Conn, error)
|
DialFunc func(ctx context.Context, network, addr string) (net.Conn, error)
|
||||||
Logger logger.Logger
|
Logger logger.Logger
|
||||||
@ -27,6 +30,10 @@ func (d *NetDialer) Dial(ctx context.Context, network, addr string) (net.Conn, e
|
|||||||
if d == nil {
|
if d == nil {
|
||||||
d = DefaultNetDialer
|
d = DefaultNetDialer
|
||||||
}
|
}
|
||||||
|
if d.Timeout <= 0 {
|
||||||
|
d.Timeout = DefaultTimeout
|
||||||
|
}
|
||||||
|
|
||||||
log := d.Logger
|
log := d.Logger
|
||||||
if log == nil {
|
if log == nil {
|
||||||
log = logger.Default()
|
log = logger.Default()
|
||||||
@ -39,7 +46,7 @@ func (d *NetDialer) Dial(ctx context.Context, network, addr string) (net.Conn, e
|
|||||||
if d.DialFunc != nil {
|
if d.DialFunc != nil {
|
||||||
return d.DialFunc(ctx, network, addr)
|
return d.DialFunc(ctx, network, addr)
|
||||||
}
|
}
|
||||||
logger.Default().Infof("interface: %s %v/%s", ifceName, ifAddr, network)
|
log.Infof("interface: %s %v/%s", ifceName, ifAddr, network)
|
||||||
|
|
||||||
switch network {
|
switch network {
|
||||||
case "udp", "udp4", "udp6":
|
case "udp", "udp4", "udp6":
|
||||||
@ -59,17 +66,18 @@ func (d *NetDialer) Dial(ctx context.Context, network, addr string) (net.Conn, e
|
|||||||
Timeout: d.Timeout,
|
Timeout: d.Timeout,
|
||||||
LocalAddr: ifAddr,
|
LocalAddr: ifAddr,
|
||||||
Control: func(network, address string, c syscall.RawConn) error {
|
Control: func(network, address string, c syscall.RawConn) error {
|
||||||
var cerr error
|
return c.Control(func(fd uintptr) {
|
||||||
err := c.Control(func(fd uintptr) {
|
if ifceName != "" {
|
||||||
cerr = bindDevice(fd, ifceName)
|
if err := bindDevice(fd, ifceName); err != nil {
|
||||||
|
log.Warnf("bind device: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if d.Mark != 0 {
|
||||||
|
if err := setMark(fd, d.Mark); err != nil {
|
||||||
|
log.Warnf("set mark: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if cerr != nil {
|
|
||||||
return cerr
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
return netd.DialContext(ctx, network, addr)
|
return netd.DialContext(ctx, network, addr)
|
||||||
|
@ -12,3 +12,10 @@ func bindDevice(fd uintptr, ifceName string) error {
|
|||||||
}
|
}
|
||||||
return unix.BindToDevice(int(fd), ifceName)
|
return unix.BindToDevice(int(fd), ifceName)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func setMark(fd uintptr, mark int) error {
|
||||||
|
if mark == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_MARK, mark)
|
||||||
|
}
|
||||||
|
@ -5,3 +5,7 @@ package dialer
|
|||||||
func bindDevice(fd uintptr, ifceName string) error {
|
func bindDevice(fd uintptr, ifceName string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func setMark(fd uintptr, mark int) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@ -41,7 +41,7 @@ func (r *UDPRelay) SetBufferSize(n int) {
|
|||||||
func (r *UDPRelay) Run() (err error) {
|
func (r *UDPRelay) Run() (err error) {
|
||||||
bufSize := r.bufferSize
|
bufSize := r.bufferSize
|
||||||
if bufSize <= 0 {
|
if bufSize <= 0 {
|
||||||
bufSize = 1024
|
bufSize = 1500
|
||||||
}
|
}
|
||||||
|
|
||||||
errc := make(chan error, 2)
|
errc := make(chan error, 2)
|
||||||
|
@ -154,7 +154,7 @@ func (h *httpHandler) handleRequest(ctx context.Context, conn net.Conn, req *htt
|
|||||||
}
|
}
|
||||||
|
|
||||||
if network == "udp" {
|
if network == "udp" {
|
||||||
return h.handleUDP(ctx, conn, network, req.Host, log)
|
return h.handleUDP(ctx, conn, log)
|
||||||
}
|
}
|
||||||
|
|
||||||
if req.Method == "PRI" ||
|
if req.Method == "PRI" ||
|
||||||
|
@ -13,7 +13,7 @@ import (
|
|||||||
"github.com/go-gost/core/logger"
|
"github.com/go-gost/core/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (h *httpHandler) handleUDP(ctx context.Context, conn net.Conn, network, address string, log logger.Logger) error {
|
func (h *httpHandler) handleUDP(ctx context.Context, conn net.Conn, log logger.Logger) error {
|
||||||
log = log.WithFields(map[string]any{
|
log = log.WithFields(map[string]any{
|
||||||
"cmd": "udp",
|
"cmd": "udp",
|
||||||
})
|
})
|
||||||
|
@ -34,7 +34,7 @@ func (h *socks5Handler) parseMetadata(md mdata.Metadata) (err error) {
|
|||||||
if bs := mdata.GetInt(md, udpBufferSize); bs > 0 {
|
if bs := mdata.GetInt(md, udpBufferSize); bs > 0 {
|
||||||
h.md.udpBufferSize = int(math.Min(math.Max(float64(bs), 512), 64*1024))
|
h.md.udpBufferSize = int(math.Min(math.Max(float64(bs), 512), 64*1024))
|
||||||
} else {
|
} else {
|
||||||
h.md.udpBufferSize = 1024
|
h.md.udpBufferSize = 1500
|
||||||
}
|
}
|
||||||
|
|
||||||
h.md.compatibilityMode = mdata.GetBool(md, compatibilityMode)
|
h.md.compatibilityMode = mdata.GetBool(md, compatibilityMode)
|
||||||
|
@ -38,6 +38,15 @@ func (c *serverConn) Write(b []byte) (n int, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *serverConn) SyscallConn() (rc syscall.RawConn, err error) {
|
||||||
|
if sc, ok := c.Conn.(syscall.Conn); ok {
|
||||||
|
rc, err = sc.SyscallConn()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = errUnsupport
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
type packetConn struct {
|
type packetConn struct {
|
||||||
net.PacketConn
|
net.PacketConn
|
||||||
service string
|
service string
|
||||||
@ -168,7 +177,7 @@ func (c *udpConn) WriteMsgUDP(b, oob []byte, addr *net.UDPAddr) (n, oobn int, er
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *udpConn) SyscallConn() (rc syscall.RawConn, err error) {
|
func (c *udpConn) SyscallConn() (rc syscall.RawConn, err error) {
|
||||||
if nc, ok := c.PacketConn.(syscallConn); ok {
|
if nc, ok := c.PacketConn.(syscall.Conn); ok {
|
||||||
return nc.SyscallConn()
|
return nc.SyscallConn()
|
||||||
}
|
}
|
||||||
err = errUnsupport
|
err = errUnsupport
|
||||||
@ -189,8 +198,8 @@ type UDPConn interface {
|
|||||||
readUDP
|
readUDP
|
||||||
writeUDP
|
writeUDP
|
||||||
setBuffer
|
setBuffer
|
||||||
syscallConn
|
|
||||||
remoteAddr
|
remoteAddr
|
||||||
|
syscall.Conn
|
||||||
}
|
}
|
||||||
|
|
||||||
type setBuffer interface {
|
type setBuffer interface {
|
||||||
@ -208,10 +217,6 @@ type writeUDP interface {
|
|||||||
WriteMsgUDP(b, oob []byte, addr *net.UDPAddr) (n, oobn int, err error)
|
WriteMsgUDP(b, oob []byte, addr *net.UDPAddr) (n, oobn int, err error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type syscallConn interface {
|
|
||||||
SyscallConn() (syscall.RawConn, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
type remoteAddr interface {
|
type remoteAddr interface {
|
||||||
RemoteAddr() net.Addr
|
RemoteAddr() net.Addr
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user