diff --git a/gtun/client.go b/gtun/client.go index 1056949..8ee4e41 100644 --- a/gtun/client.go +++ b/gtun/client.go @@ -57,6 +57,12 @@ func NewClient(cfg *ClientConfig) *Client { } func (client *Client) Run() { + ifce, err := NewIfce() + if err != nil { + logs.Error("new interface fail: %v", err) + return + } + for { server := client.serverAddr conn, err := net.DialTimeout("tcp", server, time.Second*10) @@ -78,13 +84,7 @@ func (client *Client) Run() { client.myip = s2c.AccessIP client.gw = s2c.Gateway sndqueue := make(chan []byte) - ifce, err := NewIfce() - if err != nil { - logs.Error("new interface fail: %v", err) - return - } - - err = setupIface(ifce, s2c.AccessIP, s2c.Gateway) + err = SetIfaceIP(ifce, s2c.AccessIP) if err != nil { logs.Error("setup iface fail: %v", err) time.Sleep(time.Second * 3) @@ -101,8 +101,7 @@ func (client *Client) Run() { go rcv(conn, ifce, wg) wg.Wait() - setdownIface(ifce, s2c.AccessIP, s2c.Gateway) - ifce.Close() + RemoveIfaceIP(ifce, s2c.AccessIP) logs.Info("reconnecting") } } @@ -190,13 +189,15 @@ func snd(conn net.Conn, sndqueue chan []byte, done chan struct{}, wg *sync.WaitG func heartbeat(sndqueue chan []byte, done chan struct{}, wg *sync.WaitGroup) { defer wg.Done() + tick := time.NewTicker(time.Second * 3) + defer tick.Stop() for { select { case <-done: return - case <-time.After(time.Second * 3): + case <-tick.C: bytes, _ := common.Encode(common.C2S_HEARTBEAT, nil) sndqueue <- bytes } diff --git a/gtun/ifce.go b/gtun/ifce.go index 31ec353..0fc1d94 100644 --- a/gtun/ifce.go +++ b/gtun/ifce.go @@ -5,7 +5,6 @@ package gtun import ( "fmt" "os/exec" - "runtime" "strings" "github.com/ICKelin/gtun/pkg/logs" @@ -20,78 +19,30 @@ func NewIfce() (*water.Interface, error) { return nil, err } - return ifce, err -} + output, err := exec.Command("ifconfig", []string{ifce.Name(), "up"}...).CombinedOutput() + if err != nil { + logs.Error("up inface %s fail: %s %v", ifce.Name(), string(output), err) + return nil, err + } -type CMD struct { - cmd string - args []string + return ifce, err } -func setupIface(ifce *water.Interface, ip string, gw string) (err error) { - cmdlist := make([]*CMD, 0) - - switch runtime.GOOS { - case "linux": - cmdlist = append(cmdlist, &CMD{cmd: "ifconfig", args: []string{ifce.Name(), "up"}}) - args := strings.Split(fmt.Sprintf("addr add %s/24 dev %s", ip, ifce.Name()), " ") - cmdlist = append(cmdlist, &CMD{cmd: "ip", args: args}) - - case "darwin": - cmdlist = append(cmdlist, &CMD{cmd: "ifconfig", args: []string{ifce.Name(), "up"}}) - - args := strings.Split(fmt.Sprintf("%s %s %s", ifce.Name(), ip, ip), " ") - cmdlist = append(cmdlist, &CMD{cmd: "ifconfig", args: args}) - - args = strings.Split(fmt.Sprintf("add -net %s/24 %s", gw, ip), " ") - cmdlist = append(cmdlist, &CMD{cmd: "route", args: args}) - - case "windows": - logs.Error("do not support %s", runtime.GOOS) - - } - - logs.Info("set up interface") - for _, c := range cmdlist { - logs.Info("%s %s", c.cmd, c.args) - output, err := exec.Command(c.cmd, c.args...).CombinedOutput() - if err != nil { - return fmt.Errorf("run %s error %s", c, string(output)) - } +func SetIfaceIP(ifce *water.Interface, ip string) error { + args := strings.Split(fmt.Sprintf("addr add %s/24 dev %s", ip, ifce.Name()), " ") + output, err := exec.Command("ip", args...).CombinedOutput() + if err != nil { + return fmt.Errorf("set ip fail: %s %v", string(output), err) } return nil } -func setdownIface(ifce *water.Interface, ip string, gw string) (err error) { - cmdlist := make([]*CMD, 0) - - switch runtime.GOOS { - case "linux": - cmdlist = append(cmdlist, &CMD{cmd: "ifconfig", args: []string{ifce.Name(), "down"}}) - args := strings.Split(fmt.Sprintf("addr del %s/24 dev %s", ip, ifce.Name()), " ") - cmdlist = append(cmdlist, &CMD{cmd: "ip", args: args}) - - case "darwin": - cmdlist = append(cmdlist, &CMD{cmd: "ifconfig", args: []string{ifce.Name(), "down"}}) - - args := strings.Split(fmt.Sprintf("%s %s %s", ifce.Name(), ip, ip), " ") - cmdlist = append(cmdlist, &CMD{cmd: "ifconfig", args: args}) - - args = strings.Split(fmt.Sprintf("del -net %s/24 %s", gw, ip), " ") - cmdlist = append(cmdlist, &CMD{cmd: "route", args: args}) - - case "windows": - logs.Error("do not support %s", runtime.GOOS) - } - - logs.Info("set down interface") - for _, c := range cmdlist { - logs.Info("%s %s", c.cmd, c.args) - output, err := exec.Command(c.cmd, c.args...).CombinedOutput() - if err != nil { - return fmt.Errorf("run %s error %s", c, string(output)) - } +func RemoveIfaceIP(ifce *water.Interface, ip string) (err error) { + args := strings.Split(fmt.Sprintf("addr del %s/24 dev %s", ip, ifce.Name()), " ") + output, err := exec.Command("ip", args...).CombinedOutput() + if err != nil { + return fmt.Errorf("remove ip fail: %s %v", string(output), err) } return nil diff --git a/gtund/forward.go b/gtund/forward.go index 595cb63..5714f27 100644 --- a/gtund/forward.go +++ b/gtund/forward.go @@ -57,7 +57,10 @@ func (forward *Forward) Peer(dst string, buff []byte) error { return err } - sndbuf <- bytes + select { + case sndbuf <- bytes: + default: + } logs.Debug("send dst %s bytes size: %d", dst, len(bytes)) return nil } diff --git a/gtund/server.go b/gtund/server.go index 5690c95..2014b48 100644 --- a/gtund/server.go +++ b/gtund/server.go @@ -55,7 +55,6 @@ func NewServer(cfg ServerConfig, dhcp *DHCP, iface *Interface) (*Server, error) func (s *Server) Run() error { go s.readIface() - // go s.snd() listener, err := net.Listen("tcp", s.listenAddr) if err != nil { @@ -117,7 +116,7 @@ func (s *Server) onConn(conn net.Conn) { s2c.Nameservers = s.nameservers s.authResp(conn, s2c) - sndbuf := make(chan []byte) + sndbuf := make(chan []byte, 10) s.forward.Add(s2c.AccessIP, sndbuf) defer s.forward.Del(s2c.AccessIP)