feat: add bind interface
fix: clone route without interface and mark config
This commit is contained in:
parent
45340b2845
commit
f94293b454
23
chain.go
23
chain.go
@ -20,6 +20,7 @@ type Chain struct {
|
||||
isRoute bool
|
||||
Retries int
|
||||
Mark int
|
||||
Interface string
|
||||
nodeGroups []*NodeGroup
|
||||
route []Node // nodes in the selected route
|
||||
}
|
||||
@ -36,9 +37,11 @@ func NewChain(nodes ...Node) *Chain {
|
||||
|
||||
// newRoute creates a chain route.
|
||||
// a chain route is the final route after node selection.
|
||||
func newRoute(nodes ...Node) *Chain {
|
||||
func (c *Chain) newRoute(nodes ...Node) *Chain {
|
||||
chain := NewChain(nodes...)
|
||||
chain.isRoute = true
|
||||
chain.Interface = c.Interface
|
||||
chain.Mark = c.Mark
|
||||
return chain
|
||||
}
|
||||
|
||||
@ -166,6 +169,18 @@ func (c *Chain) dialWithOptions(ctx context.Context, network, address string, op
|
||||
}
|
||||
}
|
||||
|
||||
if c.Interface != "" {
|
||||
controlFunction = func(_, _ string, cc syscall.RawConn) error {
|
||||
return cc.Control(func(fd uintptr) {
|
||||
err := setSocketInterface(int(fd), c.Interface)
|
||||
|
||||
if err != nil {
|
||||
log.Logf("net dialer set interface %s error: %s", c.Interface, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if route.IsEmpty() {
|
||||
switch network {
|
||||
case "udp", "udp4", "udp6":
|
||||
@ -303,13 +318,13 @@ func (c *Chain) selectRoute() (route *Chain, err error) {
|
||||
// selectRouteFor selects route with bypass testing.
|
||||
func (c *Chain) selectRouteFor(addr string) (route *Chain, err error) {
|
||||
if c.IsEmpty() {
|
||||
return newRoute(), nil
|
||||
return c.newRoute(), nil
|
||||
}
|
||||
if c.isRoute {
|
||||
return c, nil
|
||||
}
|
||||
|
||||
route = newRoute()
|
||||
route = c.newRoute()
|
||||
var nl []Node
|
||||
|
||||
for _, group := range c.nodeGroups {
|
||||
@ -327,7 +342,7 @@ func (c *Chain) selectRouteFor(addr string) (route *Chain, err error) {
|
||||
node.DialOptions = append(node.DialOptions,
|
||||
ChainDialOption(route),
|
||||
)
|
||||
route = newRoute() // cutoff the chain for multiplex node.
|
||||
route = c.newRoute() // cutoff the chain for multiplex node.
|
||||
}
|
||||
|
||||
route.AddNode(node)
|
||||
|
@ -33,6 +33,7 @@ func init() {
|
||||
flag.Var(&baseCfg.route.ServeNodes, "L", "listen address, can listen on multiple ports (required)")
|
||||
flag.IntVar(&baseCfg.route.Mark, "M", 0, "Specify out connection mark")
|
||||
flag.StringVar(&configureFile, "C", "", "configure file")
|
||||
flag.StringVar(&baseCfg.route.Interface, "I", "", "Interface to bind")
|
||||
flag.BoolVar(&baseCfg.Debug, "D", false, "enable debug log")
|
||||
flag.BoolVar(&printVersion, "V", false, "print version")
|
||||
if pprofEnabled {
|
||||
|
@ -31,12 +31,14 @@ type route struct {
|
||||
ChainNodes stringList
|
||||
Retries int
|
||||
Mark int
|
||||
Interface string
|
||||
}
|
||||
|
||||
func (r *route) parseChain() (*gost.Chain, error) {
|
||||
chain := gost.NewChain()
|
||||
chain.Retries = r.Retries
|
||||
chain.Mark = r.Mark
|
||||
chain.Interface = r.Interface
|
||||
gid := 1 // group ID
|
||||
|
||||
for _, ns := range r.ChainNodes {
|
||||
|
@ -5,3 +5,7 @@ import "syscall"
|
||||
func setSocketMark(fd int, value int) (e error) {
|
||||
return syscall.SetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_MARK, value)
|
||||
}
|
||||
|
||||
func setSocketInterface(fd int, value string) (e error) {
|
||||
return syscall.SetsockoptString(fd, syscall.SOL_SOCKET, syscall.SO_BINDTODEVICE, value)
|
||||
}
|
@ -5,3 +5,7 @@ package gost
|
||||
func setSocketMark(fd int, value int) (e error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
func setSocketInterface(fd int, value string) (e error) {
|
||||
return nil
|
||||
}
|
Loading…
Reference in New Issue
Block a user