Skip to content

Commit

Permalink
hotfix: return error if resolve extra-domain ip is empty (#397)
Browse files Browse the repository at this point in the history
  • Loading branch information
wencaiwulue authored Dec 13, 2024
1 parent 062c69d commit f046e47
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 147 deletions.
165 changes: 21 additions & 144 deletions pkg/handler/connect.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,8 @@ import (
"context"
"encoding/json"
"fmt"
"io"
"math"
"math/rand"
"net"
"net/url"
"os/exec"
"reflect"
"sort"
"strconv"
Expand All @@ -21,7 +17,6 @@ import (
"github.com/distribution/reference"
goversion "github.com/hashicorp/go-version"
"github.com/libp2p/go-netroute"
miekgdns "github.com/miekg/dns"
"github.com/pkg/errors"
log "github.com/sirupsen/logrus"
"google.golang.org/grpc/metadata"
Expand All @@ -34,11 +29,9 @@ import (
utilnet "k8s.io/apimachinery/pkg/util/net"
"k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/cli-runtime/pkg/resource"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"k8s.io/client-go/util/retry"
"k8s.io/kubectl/pkg/cmd/set"
cmdutil "k8s.io/kubectl/pkg/cmd/util"
"k8s.io/kubectl/pkg/polymorphichelpers"
Expand Down Expand Up @@ -427,17 +420,13 @@ func (c *ConnectOptions) startLocalTunServer(ctx context.Context, forwardAddress
}
}()
log.Info("Connected tunnel")
return

c.tunName, err = c.GetTunDeviceName()
return err
}

// Listen all pod, add route if needed
func (c *ConnectOptions) addRouteDynamic(ctx context.Context) error {
var err error
c.tunName, err = c.GetTunDeviceName()
if err != nil {
return err
}

podNs, svcNs, err1 := util.GetNsForListPodAndSvc(ctx, c.clientset, []string{v1.NamespaceAll, c.Namespace})
if err1 != nil {
return err1
Expand Down Expand Up @@ -542,13 +531,14 @@ func (c *ConnectOptions) deleteFirewallRule(ctx context.Context) {

func (c *ConnectOptions) setupDNS(ctx context.Context) error {
const portTCP = 10800
pod, err := c.GetRunningPodList(ctx)
podList, err := c.GetRunningPodList(ctx)
if err != nil {
log.Errorf("Get running pod list failed, err: %v", err)
return err
}
pod := podList[0]
log.Debugf("Get DNS service IP from pod...")
relovConf, err := util.GetDNSServiceIPFromPod(ctx, c.clientset, c.config, pod[0].GetName(), c.Namespace)
relovConf, err := util.GetDNSServiceIPFromPod(ctx, c.clientset, c.config, pod.GetName(), c.Namespace)
if err != nil {
log.Errorln(err)
return err
Expand All @@ -565,17 +555,17 @@ func (c *ConnectOptions) setupDNS(ctx context.Context) error {
d := net.Dialer{Timeout: time.Duration(max(2, relovConf.Timeout)) * time.Second}
conn, err = d.DialContext(ctx, "tcp", net.JoinHostPort(svc.Spec.ClusterIP, strconv.Itoa(portTCP)))
if err != nil {
relovConf.Servers = []string{pod[0].Status.PodIP}
relovConf.Servers = []string{pod.Status.PodIP}
err = nil
log.Debugf("DNS service use pod IP %s", pod[0].Status.PodIP)
log.Debugf("DNS service use pod IP %s", pod.Status.PodIP)
} else {
relovConf.Servers = []string{svc.Spec.ClusterIP}
_ = conn.Close()
log.Debugf("DNS service use service IP %s", svc.Spec.ClusterIP)
}

log.Debugf("Adding extra hosts...")
if err = c.addExtraRoute(c.ctx, relovConf.Servers[0]); err != nil {
if err = c.addExtraRoute(c.ctx, pod.GetName()); err != nil {
log.Errorf("Add extra route failed: %v", err)
return err
}
Expand All @@ -596,15 +586,11 @@ func (c *ConnectOptions) setupDNS(ctx context.Context) error {
serviceList = append(serviceList, services.Items...)
}

tunName, err := c.GetTunDeviceName()
if err != nil {
return err
}
c.dnsConfig = &dns.Config{
Config: relovConf,
Ns: ns,
Services: serviceList,
TunName: tunName,
TunName: c.tunName,
Hosts: c.extraHost,
Lock: c.Lock,
}
Expand Down Expand Up @@ -833,135 +819,26 @@ func (c *ConnectOptions) getCIDR(ctx context.Context, m *dhcp.Manager) (err erro
return
}

func (c *ConnectOptions) addExtraRoute(ctx context.Context, nameserver string) error {
func (c *ConnectOptions) addExtraRoute(ctx context.Context, name string) error {
if len(c.ExtraRouteInfo.ExtraDomain) == 0 {
return nil
}

tunName, err := c.GetTunDeviceName()
if err != nil {
log.Errorf("Get tun interface failed: %s", err.Error())
return err
}

addRouteFunc := func(resource, ip string) {
if net.ParseIP(ip) == nil {
return
}
var mask net.IPMask
if net.ParseIP(ip).To4() != nil {
mask = net.CIDRMask(32, 32)
} else {
mask = net.CIDRMask(128, 128)
}
errs := tun.AddRoutes(tunName, types.Route{Dst: net.IPNet{IP: net.ParseIP(ip), Mask: mask}})
if errs != nil {
log.Errorf("Failed to add route, domain: %s, IP: %s, err: %v", resource, ip, err)
}
}

// 1) use dig +short query, if ok, just return
podList, err := c.GetRunningPodList(ctx)
if err != nil {
return err
}
var ok = true
for _, domain := range c.ExtraRouteInfo.ExtraDomain {
ip, err := util.Shell(ctx, c.clientset, c.config, podList[0].Name, config.ContainerSidecarVPN, c.Namespace, []string{"dig", "+short", domain})
if err == nil || net.ParseIP(ip) != nil {
addRouteFunc(domain, ip)
c.extraHost = append(c.extraHost, dns.Entry{IP: net.ParseIP(ip).String(), Domain: domain})
} else {
ok = false
}
}
if ok {
return nil
}

// 2) wait until can ping dns server ip ok
// 3) use nslookup to query dns at first, it will speed up mikdns query process
ticker := time.NewTicker(2 * time.Second)
defer ticker.Stop()
go func() {
for _, domain := range c.ExtraRouteInfo.ExtraDomain {
go func(domain string) {
for ; true; <-ticker.C {
func() {
subCtx, c2 := context.WithTimeout(ctx, time.Second*2)
defer c2()
cmd := exec.CommandContext(subCtx, "nslookup", domain, nameserver)
cmd.Stderr = io.Discard
cmd.Stdout = io.Discard
_ = cmd.Start()
_ = cmd.Wait()
}()
}
}(domain)
ip, err := util.Shell(ctx, c.clientset, c.config, name, config.ContainerSidecarVPN, c.Namespace, []string{"dig", "+short", domain})
if err != nil {
return errors.WithMessage(err, "failed to resolve DNS for domain by command dig")
}
}()

// 4) query with dns client
client := &miekgdns.Client{Net: "udp", Timeout: time.Second * 2}
for _, domain := range c.ExtraRouteInfo.ExtraDomain {
var success = false
for _, qType := range []uint16{miekgdns.TypeA /*, miekgdns.TypeAAAA*/} {
var iErr = errors.New("No retry")
err = retry.OnError(
wait.Backoff{
Steps: 1000,
Duration: time.Millisecond * 30,
},
func(err error) bool {
return err != nil
},
func() error {
var answer *miekgdns.Msg
answer, _, err = client.ExchangeContext(ctx, &miekgdns.Msg{
MsgHdr: miekgdns.MsgHdr{
Id: uint16(rand.Intn(math.MaxUint16 + 1)),
},
Question: []miekgdns.Question{
{
Name: domain + ".",
Qtype: qType,
},
},
}, fmt.Sprintf("%s:%d", nameserver, 53))
if err != nil {
return err
}
if len(answer.Answer) == 0 {
return iErr
}
for _, rr := range answer.Answer {
switch a := rr.(type) {
case *miekgdns.A:
if ip := net.ParseIP(a.A.String()); ip != nil && !ip.IsLoopback() {
addRouteFunc(domain, a.A.String())
c.extraHost = append(c.extraHost, dns.Entry{IP: a.A.String(), Domain: domain})
success = true
}
case *miekgdns.AAAA:
if ip := net.ParseIP(a.AAAA.String()); ip != nil && !ip.IsLoopback() {
addRouteFunc(domain, a.AAAA.String())
c.extraHost = append(c.extraHost, dns.Entry{IP: a.AAAA.String(), Domain: domain})
success = true
}
}
}
return nil
})
if err != nil && err != iErr {
return err
}
if success {
break
}
if net.ParseIP(ip) == nil {
return fmt.Errorf("failed to resolve DNS for domain %s by command dig", domain)
}
if !success {
return fmt.Errorf("failed to resolve DNS for domain %s", domain)
err = c.addRoute(ip)
if err != nil {
log.Errorf("Failed to add IP: %s to route table: %v", ip, err)
return err
}
c.extraHost = append(c.extraHost, dns.Entry{IP: net.ParseIP(ip).String(), Domain: domain})
}
return nil
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/util/net.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ func GetTunDevice(ips ...net.IP) (*net.Interface, error) {
}
}
}
return nil, fmt.Errorf("can not found any interface with ip %v", ips)
return nil, fmt.Errorf("can not found any interface with IP %v", ips)
}

func GetTunDeviceByConn(tun net.Conn) (*net.Interface, error) {
Expand Down
4 changes: 2 additions & 2 deletions pkg/util/route.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ func ListService(ctx context.Context, lister v12.ServiceInterface, addRouteFunc
for _, service := range serviceList.Items {
err = addRouteFunc(service.Spec.ClusterIP)
if err != nil {
log.Errorf("Failed to add route, resource: %s, IP: %s, err: %v", service.Name, service.Spec.ClusterIP, err)
log.Errorf("Failed to add service: %s IP: %s to route table: %v", service.Name, service.Spec.ClusterIP, err)
}
}
if serviceList.Continue == "" {
Expand Down Expand Up @@ -112,7 +112,7 @@ func ListPod(ctx context.Context, lister v12.PodInterface, addRouteFunc func(ipS
}
err = addRouteFunc(pod.Status.PodIP)
if err != nil {
log.Errorf("Failed to add route, resource: %s, IP: %s, err: %v", pod.Name, pod.Status.PodIP, err)
log.Errorf("Failed to add pod: %s IP: %s to route table: %v", pod.Name, pod.Status.PodIP, err)
}
}
if podList.Continue == "" {
Expand Down

0 comments on commit f046e47

Please sign in to comment.