feat: add bind interface
fix: clone route without interface and mark config
This commit is contained in:
parent
45340b2845
commit
8404317ada
23
chain.go
23
chain.go
@ -20,6 +20,7 @@ type Chain struct {
|
|||||||
isRoute bool
|
isRoute bool
|
||||||
Retries int
|
Retries int
|
||||||
Mark int
|
Mark int
|
||||||
|
Interface string
|
||||||
nodeGroups []*NodeGroup
|
nodeGroups []*NodeGroup
|
||||||
route []Node // nodes in the selected route
|
route []Node // nodes in the selected route
|
||||||
}
|
}
|
||||||
@ -36,9 +37,11 @@ func NewChain(nodes ...Node) *Chain {
|
|||||||
|
|
||||||
// newRoute creates a chain route.
|
// newRoute creates a chain route.
|
||||||
// a chain route is the final route after node selection.
|
// 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 := NewChain(nodes...)
|
||||||
chain.isRoute = true
|
chain.isRoute = true
|
||||||
|
chain.Interface = c.Interface
|
||||||
|
chain.Mark = c.Mark
|
||||||
return chain
|
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() {
|
if route.IsEmpty() {
|
||||||
switch network {
|
switch network {
|
||||||
case "udp", "udp4", "udp6":
|
case "udp", "udp4", "udp6":
|
||||||
@ -303,13 +318,13 @@ func (c *Chain) selectRoute() (route *Chain, err error) {
|
|||||||
// selectRouteFor selects route with bypass testing.
|
// selectRouteFor selects route with bypass testing.
|
||||||
func (c *Chain) selectRouteFor(addr string) (route *Chain, err error) {
|
func (c *Chain) selectRouteFor(addr string) (route *Chain, err error) {
|
||||||
if c.IsEmpty() {
|
if c.IsEmpty() {
|
||||||
return newRoute(), nil
|
return c.newRoute(), nil
|
||||||
}
|
}
|
||||||
if c.isRoute {
|
if c.isRoute {
|
||||||
return c, nil
|
return c, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
route = newRoute()
|
route = c.newRoute()
|
||||||
var nl []Node
|
var nl []Node
|
||||||
|
|
||||||
for _, group := range c.nodeGroups {
|
for _, group := range c.nodeGroups {
|
||||||
@ -327,7 +342,7 @@ func (c *Chain) selectRouteFor(addr string) (route *Chain, err error) {
|
|||||||
node.DialOptions = append(node.DialOptions,
|
node.DialOptions = append(node.DialOptions,
|
||||||
ChainDialOption(route),
|
ChainDialOption(route),
|
||||||
)
|
)
|
||||||
route = newRoute() // cutoff the chain for multiplex node.
|
route = c.newRoute() // cutoff the chain for multiplex node.
|
||||||
}
|
}
|
||||||
|
|
||||||
route.AddNode(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.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.IntVar(&baseCfg.route.Mark, "M", 0, "Specify out connection mark")
|
||||||
flag.StringVar(&configureFile, "C", "", "configure file")
|
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(&baseCfg.Debug, "D", false, "enable debug log")
|
||||||
flag.BoolVar(&printVersion, "V", false, "print version")
|
flag.BoolVar(&printVersion, "V", false, "print version")
|
||||||
if pprofEnabled {
|
if pprofEnabled {
|
||||||
|
@ -31,12 +31,14 @@ type route struct {
|
|||||||
ChainNodes stringList
|
ChainNodes stringList
|
||||||
Retries int
|
Retries int
|
||||||
Mark int
|
Mark int
|
||||||
|
Interface string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *route) parseChain() (*gost.Chain, error) {
|
func (r *route) parseChain() (*gost.Chain, error) {
|
||||||
chain := gost.NewChain()
|
chain := gost.NewChain()
|
||||||
chain.Retries = r.Retries
|
chain.Retries = r.Retries
|
||||||
chain.Mark = r.Mark
|
chain.Mark = r.Mark
|
||||||
|
chain.Interface = r.Interface
|
||||||
gid := 1 // group ID
|
gid := 1 // group ID
|
||||||
|
|
||||||
for _, ns := range r.ChainNodes {
|
for _, ns := range r.ChainNodes {
|
||||||
|
@ -5,3 +5,7 @@ import "syscall"
|
|||||||
func setSocketMark(fd int, value int) (e error) {
|
func setSocketMark(fd int, value int) (e error) {
|
||||||
return syscall.SetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_MARK, value)
|
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) {
|
func setSocketMark(fd int, value int) (e error) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func setSocketInterface(fd int, value string) (e error) {
|
||||||
|
return nil
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user