pkg/kt/service/tun/tun_linux.go
package tun
import (
"fmt"
"github.com/alibaba/kt-connect/pkg/kt/util"
"github.com/rs/zerolog/log"
"os/exec"
"strings"
)
// CheckContext check everything needed for tun setup
func (s *Cli) CheckContext() error {
if !util.CanRun(exec.Command("which", "ip")) {
return fmt.Errorf("failed to found 'ip' command")
}
return nil
}
// SetRoute let specified ip range route to tun device
func (s *Cli) SetRoute(ipRange []string, excludeIpRange []string) error {
// run command: ip link set dev kt0 up
_, _, err := util.RunAndWait(exec.Command("ip",
"link",
"set",
"dev",
s.GetName(),
"up",
))
if err != nil {
log.Error().Msgf("Failed to set tun device up")
return AllRouteFailError{err}
}
var lastErr error
anyRouteOk := false
for _, r := range ipRange {
log.Info().Msgf("Adding route to %s", r)
// run command: ip route add 10.96.0.0/16 dev kt0
_, _, err = util.RunAndWait(exec.Command("ip",
"route",
"add",
r,
"dev",
s.GetName(),
))
if err != nil {
log.Warn().Msgf("Failed to set route %s to tun device", r)
lastErr = err
} else {
anyRouteOk = true
}
}
if !anyRouteOk {
return AllRouteFailError{lastErr}
}
return lastErr
}
// CheckRoute check whether all route rule setup properly
func (s *Cli) CheckRoute(ipRange []string) []string {
var failedIpRange []string
// run command: ip route show
out, _, err := util.RunAndWait(exec.Command("ip",
"route",
"show",
))
if err != nil {
log.Warn().Msgf("Failed to get route table")
return []string{}
}
_, _ = util.BackgroundLogger.Write([]byte(">> Get route: " + out + util.Eol))
nameWithPadding := fmt.Sprintf(" %s ", s.GetName())
for _, ir := range ipRange {
found := false
for _, line := range strings.Split(out, util.Eol) {
if strings.HasPrefix(line, ir) && strings.Contains(line, nameWithPadding) {
found = true
break
}
}
if !found {
failedIpRange = append(failedIpRange, ir)
}
}
return failedIpRange
}
// RestoreRoute delete route rules made by kt
func (s *Cli) RestoreRoute() error {
// Route will be auto removed when tun device destroyed
return nil
}
func (s *Cli) GetName() string {
return util.TunNameLinux
}