Browse Source

feat: add bind interface

fix: clone route without interface and mark config
pull/846/head
IndexDoge 4 years ago
committed by ginuerzh
parent
commit
f94293b454
  1. 23
      chain.go
  2. 1
      cmd/gost/main.go
  3. 2
      cmd/gost/route.go
  4. 4
      sockopts_linux.go
  5. 4
      sockopts_other.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)

1
cmd/gost/main.go

@ -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 {

2
cmd/gost/route.go

@ -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 {

4
sockopts_linux.go

@ -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)
}

4
sockopts_other.go

@ -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…
Cancel
Save