mirror of
https://github.com/kubenetworks/kubevpn.git
synced 2025-10-23 15:23:13 +08:00
feat: add connect lite mode and optimize dns
This commit is contained in:
@@ -1,81 +0,0 @@
|
|||||||
package cmds
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
cmdutil "k8s.io/kubectl/pkg/cmd/util"
|
|
||||||
"k8s.io/kubectl/pkg/util/i18n"
|
|
||||||
"k8s.io/kubectl/pkg/util/templates"
|
|
||||||
|
|
||||||
"github.com/wencaiwulue/kubevpn/pkg/config"
|
|
||||||
"github.com/wencaiwulue/kubevpn/pkg/handler"
|
|
||||||
"github.com/wencaiwulue/kubevpn/pkg/util"
|
|
||||||
)
|
|
||||||
|
|
||||||
func CmdConnectFork(f cmdutil.Factory) *cobra.Command {
|
|
||||||
var connect = &handler.ConnectOptions{}
|
|
||||||
var sshConf = &util.SshConfig{}
|
|
||||||
var transferImage bool
|
|
||||||
cmd := &cobra.Command{
|
|
||||||
Hidden: true,
|
|
||||||
Use: "connect-fork",
|
|
||||||
Short: i18n.T("Connect to kubernetes cluster network"),
|
|
||||||
Long: templates.LongDesc(i18n.T(`Connect to kubernetes cluster network`)),
|
|
||||||
Example: templates.Examples(i18n.T(`
|
|
||||||
# Connect to k8s cluster network
|
|
||||||
kubevpn connect
|
|
||||||
|
|
||||||
# Connect to api-server behind of bastion host or ssh jump host
|
|
||||||
kubevpn connect --ssh-addr 192.168.1.100:22 --ssh-username root --ssh-keyfile /Users/naison/.ssh/ssh.pem
|
|
||||||
kubevpn connect --ssh-addr 192.168.1.100:22 --ssh-username root --ssh-keyfile ~/.ssh/ssh.pem
|
|
||||||
|
|
||||||
# it also support ProxyJump, like
|
|
||||||
┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ ┌────────────┐
|
|
||||||
│ pc ├────►│ ssh1 ├────►│ ssh2 ├────►│ ssh3 ├─────►... ─────► │ api-server │
|
|
||||||
└──────┘ └──────┘ └──────┘ └──────┘ └────────────┘
|
|
||||||
kubevpn connect --ssh-alias <alias>
|
|
||||||
|
|
||||||
`)),
|
|
||||||
PreRunE: func(cmd *cobra.Command, args []string) (err error) {
|
|
||||||
util.InitLogger(false)
|
|
||||||
if transferImage {
|
|
||||||
err = util.TransferImage(cmd.Context(), sshConf, config.OriginImage, config.Image, os.Stdout)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return handler.SshJumpAndSetEnv(cmd.Context(), sshConf, cmd.Flags(), true)
|
|
||||||
},
|
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
|
||||||
if err := connect.InitClient(f); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
_, err := connect.RentInnerIP(cmd.Context())
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
err = connect.DoConnect(cmd.Context())
|
|
||||||
defer connect.Cleanup()
|
|
||||||
if err != nil {
|
|
||||||
log.Errorln(err)
|
|
||||||
} else {
|
|
||||||
util.Print(os.Stdout, "Now you can access resources in the kubernetes cluster, enjoy it :)")
|
|
||||||
}
|
|
||||||
<-cmd.Context().Done()
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
cmd.Flags().BoolVar(&config.Debug, "debug", false, "enable debug mode or not, true or false")
|
|
||||||
cmd.Flags().StringVar(&config.Image, "image", config.Image, "use this image to startup container")
|
|
||||||
cmd.Flags().StringArrayVar(&connect.ExtraCIDR, "extra-cidr", []string{}, "Extra cidr string, eg: --extra-cidr 192.168.0.159/24 --extra-cidr 192.168.1.160/32")
|
|
||||||
cmd.Flags().StringArrayVar(&connect.ExtraDomain, "extra-domain", []string{}, "Extra domain string, the resolved ip will add to route table, eg: --extra-domain test.abc.com --extra-domain foo.test.com")
|
|
||||||
cmd.Flags().BoolVar(&transferImage, "transfer-image", false, "transfer image to remote registry, it will transfer image "+config.OriginImage+" to flags `--image` special image, default: "+config.Image)
|
|
||||||
cmd.Flags().BoolVar(&connect.UseLocalDNS, "use-localdns", false, "if use-lcoaldns is true, kubevpn will start coredns listen at 53 to forward your dns queries. only support on linux now")
|
|
||||||
cmd.Flags().StringVar((*string)(&connect.Engine), "engine", string(config.EngineRaw), fmt.Sprintf(`transport engine ("%s"|"%s") %s: use gvisor and raw both (both performance and stable), %s: use raw mode (best stable)`, config.EngineMix, config.EngineRaw, config.EngineMix, config.EngineRaw))
|
|
||||||
|
|
||||||
addSshFlags(cmd, sshConf)
|
|
||||||
return cmd
|
|
||||||
}
|
|
@@ -23,7 +23,7 @@ import (
|
|||||||
func CmdConnect(f cmdutil.Factory) *cobra.Command {
|
func CmdConnect(f cmdutil.Factory) *cobra.Command {
|
||||||
var connect = &handler.ConnectOptions{}
|
var connect = &handler.ConnectOptions{}
|
||||||
var sshConf = &util.SshConfig{}
|
var sshConf = &util.SshConfig{}
|
||||||
var transferImage, foreground bool
|
var transferImage, foreground, lite bool
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: "connect",
|
Use: "connect",
|
||||||
Short: i18n.T("Connect to kubernetes cluster network"),
|
Short: i18n.T("Connect to kubernetes cluster network"),
|
||||||
@@ -66,8 +66,8 @@ func CmdConnect(f cmdutil.Factory) *cobra.Command {
|
|||||||
Level: int32(log.DebugLevel),
|
Level: int32(log.DebugLevel),
|
||||||
}
|
}
|
||||||
// if is foreground, send to sudo daemon server
|
// if is foreground, send to sudo daemon server
|
||||||
if foreground {
|
cli := daemon.GetClient(false)
|
||||||
cli := daemon.GetClient(true)
|
if lite {
|
||||||
resp, err := cli.ConnectFork(cmd.Context(), req)
|
resp, err := cli.ConnectFork(cmd.Context(), req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -84,7 +84,6 @@ func CmdConnect(f cmdutil.Factory) *cobra.Command {
|
|||||||
fmt.Fprint(os.Stdout, recv.GetMessage())
|
fmt.Fprint(os.Stdout, recv.GetMessage())
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
cli := daemon.GetClient(false)
|
|
||||||
resp, err := cli.Connect(cmd.Context(), req)
|
resp, err := cli.Connect(cmd.Context(), req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -100,6 +99,8 @@ func CmdConnect(f cmdutil.Factory) *cobra.Command {
|
|||||||
}
|
}
|
||||||
fmt.Fprint(os.Stdout, recv.GetMessage())
|
fmt.Fprint(os.Stdout, recv.GetMessage())
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if !req.Foreground {
|
||||||
util.Print(os.Stdout, "Now you can access resources in the kubernetes cluster, enjoy it :)")
|
util.Print(os.Stdout, "Now you can access resources in the kubernetes cluster, enjoy it :)")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@@ -112,7 +113,8 @@ func CmdConnect(f cmdutil.Factory) *cobra.Command {
|
|||||||
cmd.Flags().BoolVar(&transferImage, "transfer-image", false, "transfer image to remote registry, it will transfer image "+config.OriginImage+" to flags `--image` special image, default: "+config.Image)
|
cmd.Flags().BoolVar(&transferImage, "transfer-image", false, "transfer image to remote registry, it will transfer image "+config.OriginImage+" to flags `--image` special image, default: "+config.Image)
|
||||||
cmd.Flags().BoolVar(&connect.UseLocalDNS, "use-localdns", false, "if use-lcoaldns is true, kubevpn will start coredns listen at 53 to forward your dns queries. only support on linux now")
|
cmd.Flags().BoolVar(&connect.UseLocalDNS, "use-localdns", false, "if use-lcoaldns is true, kubevpn will start coredns listen at 53 to forward your dns queries. only support on linux now")
|
||||||
cmd.Flags().StringVar((*string)(&connect.Engine), "engine", string(config.EngineRaw), fmt.Sprintf(`transport engine ("%s"|"%s") %s: use gvisor and raw both (both performance and stable), %s: use raw mode (best stable)`, config.EngineMix, config.EngineRaw, config.EngineMix, config.EngineRaw))
|
cmd.Flags().StringVar((*string)(&connect.Engine), "engine", string(config.EngineRaw), fmt.Sprintf(`transport engine ("%s"|"%s") %s: use gvisor and raw both (both performance and stable), %s: use raw mode (best stable)`, config.EngineMix, config.EngineRaw, config.EngineMix, config.EngineRaw))
|
||||||
cmd.Flags().BoolVar(&foreground, "foreground", false, "connect to multiple cluster, you needs to special this options")
|
cmd.Flags().BoolVar(&foreground, "foreground", false, "Hang up")
|
||||||
|
cmd.Flags().BoolVar(&lite, "lite", false, "connect to multiple cluster in lite mode, you needs to special this options")
|
||||||
|
|
||||||
addSshFlags(cmd, sshConf)
|
addSshFlags(cmd, sshConf)
|
||||||
return cmd
|
return cmd
|
||||||
|
@@ -50,7 +50,6 @@ func NewKubeVPNCommand() *cobra.Command {
|
|||||||
Message: "Develop commands:",
|
Message: "Develop commands:",
|
||||||
Commands: []*cobra.Command{
|
Commands: []*cobra.Command{
|
||||||
CmdConnect(factory),
|
CmdConnect(factory),
|
||||||
CmdConnectFork(factory),
|
|
||||||
CmdDisconnect(factory),
|
CmdDisconnect(factory),
|
||||||
CmdProxy(factory),
|
CmdProxy(factory),
|
||||||
CmdLeave(factory),
|
CmdLeave(factory),
|
||||||
|
@@ -26,7 +26,7 @@ func CmdStatus(f cmdutil.Factory) *cobra.Command {
|
|||||||
return daemon.StartupDaemon(cmd.Context())
|
return daemon.StartupDaemon(cmd.Context())
|
||||||
},
|
},
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
client, err := daemon.GetClient(true).Status(
|
client, err := daemon.GetClient(false).Status(
|
||||||
cmd.Context(),
|
cmd.Context(),
|
||||||
&rpc.StatusRequest{},
|
&rpc.StatusRequest{},
|
||||||
)
|
)
|
||||||
|
@@ -91,6 +91,8 @@ const (
|
|||||||
|
|
||||||
// transport mode
|
// transport mode
|
||||||
ConfigKubeVPNTransportEngine = "transport-engine"
|
ConfigKubeVPNTransportEngine = "transport-engine"
|
||||||
|
// hosts entry key word
|
||||||
|
HostsKeyWord = "# Add by KubeVPN"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"k8s.io/utils/pointer"
|
||||||
defaultlog "log"
|
defaultlog "log"
|
||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
@@ -86,6 +87,7 @@ func (svr *Server) ConnectFork(req *rpc.ConnectRequest, resp rpc.Daemon_ConnectF
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
svr.secondaryConnect = append(svr.secondaryConnect, connect)
|
svr.secondaryConnect = append(svr.secondaryConnect, connect)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -147,7 +149,7 @@ func (svr *Server) redirectConnectForkToSudoDaemon(req *rpc.ConnectRequest, resp
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
connResp, err := cli.Connect(ctx, req)
|
connResp, err := cli.ConnectFork(ctx, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -165,6 +167,36 @@ func (svr *Server) redirectConnectForkToSudoDaemon(req *rpc.ConnectRequest, resp
|
|||||||
}
|
}
|
||||||
|
|
||||||
svr.secondaryConnect = append(svr.secondaryConnect, connect)
|
svr.secondaryConnect = append(svr.secondaryConnect, connect)
|
||||||
|
|
||||||
|
if req.Foreground {
|
||||||
|
<-resp.Context().Done()
|
||||||
|
for i := 0; i < len(svr.secondaryConnect); i++ {
|
||||||
|
if svr.secondaryConnect[i] == connect {
|
||||||
|
cli := svr.GetClient(false)
|
||||||
|
if cli == nil {
|
||||||
|
return fmt.Errorf("sudo daemon not start")
|
||||||
|
}
|
||||||
|
disconnect, err := cli.Disconnect(context.Background(), &rpc.DisconnectRequest{
|
||||||
|
ID: pointer.Int32(int32(i)),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("disconnect error: %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for {
|
||||||
|
recv, err := disconnect.Recv()
|
||||||
|
if err == io.EOF {
|
||||||
|
break
|
||||||
|
} else if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
log.Info(recv.Message)
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -181,6 +181,34 @@ func (svr *Server) redirectToSudoDaemon(req *rpc.ConnectRequest, resp rpc.Daemon
|
|||||||
|
|
||||||
svr.t = time.Now()
|
svr.t = time.Now()
|
||||||
svr.connect = connect
|
svr.connect = connect
|
||||||
|
|
||||||
|
// hangup
|
||||||
|
if req.Foreground {
|
||||||
|
<-resp.Context().Done()
|
||||||
|
|
||||||
|
client := svr.GetClient(false)
|
||||||
|
if client == nil {
|
||||||
|
return fmt.Errorf("daemon not start")
|
||||||
|
}
|
||||||
|
disconnect, err := client.Disconnect(context.Background(), &rpc.DisconnectRequest{
|
||||||
|
ID: pointer.Int32(int32(0)),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("disconnect error: %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for {
|
||||||
|
recv, err := disconnect.Recv()
|
||||||
|
if err == io.EOF {
|
||||||
|
break
|
||||||
|
} else if err != nil {
|
||||||
|
log.Error(err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
log.Info(recv.Message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -8,6 +8,7 @@ import (
|
|||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/wencaiwulue/kubevpn/pkg/daemon/rpc"
|
"github.com/wencaiwulue/kubevpn/pkg/daemon/rpc"
|
||||||
|
"github.com/wencaiwulue/kubevpn/pkg/dns"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (svr *Server) Disconnect(req *rpc.DisconnectRequest, resp rpc.Daemon_DisconnectServer) error {
|
func (svr *Server) Disconnect(req *rpc.DisconnectRequest, resp rpc.Daemon_DisconnectServer) error {
|
||||||
@@ -77,6 +78,10 @@ func (svr *Server) Disconnect(req *rpc.DisconnectRequest, resp rpc.Daemon_Discon
|
|||||||
log.Errorf("index %d out of range", req.GetID())
|
log.Errorf("index %d out of range", req.GetID())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if svr.connect == nil && len(svr.secondaryConnect) == 0 {
|
||||||
|
dns.CleanupHosts()
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -6,6 +6,7 @@ import (
|
|||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/wencaiwulue/kubevpn/pkg/daemon/rpc"
|
"github.com/wencaiwulue/kubevpn/pkg/daemon/rpc"
|
||||||
|
"github.com/wencaiwulue/kubevpn/pkg/dns"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (svr *Server) Quit(req *rpc.QuitRequest, resp rpc.Daemon_QuitServer) error {
|
func (svr *Server) Quit(req *rpc.QuitRequest, resp rpc.Daemon_QuitServer) error {
|
||||||
@@ -33,6 +34,9 @@ func (svr *Server) Quit(req *rpc.QuitRequest, resp rpc.Daemon_QuitServer) error
|
|||||||
log.Info("quit: cleanup connection")
|
log.Info("quit: cleanup connection")
|
||||||
options.Cleanup()
|
options.Cleanup()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dns.CleanupHosts()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -28,7 +28,7 @@ import (
|
|||||||
|
|
||||||
"github.com/wencaiwulue/kubevpn/pkg/config"
|
"github.com/wencaiwulue/kubevpn/pkg/config"
|
||||||
"github.com/wencaiwulue/kubevpn/pkg/cp"
|
"github.com/wencaiwulue/kubevpn/pkg/cp"
|
||||||
"github.com/wencaiwulue/kubevpn/pkg/dns"
|
util2 "github.com/wencaiwulue/kubevpn/pkg/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
type RunConfig struct {
|
type RunConfig struct {
|
||||||
@@ -186,7 +186,7 @@ func GetDNS(ctx context.Context, f util.Factory, ns, pod string) (*miekgdns.Clie
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
clientConfig, err := dns.GetDNSServiceIPFromPod(clientSet, client, config, pod, ns)
|
clientConfig, err := util2.GetDNSServiceIPFromPod(clientSet, client, config, pod, ns)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@@ -9,17 +9,17 @@ type CoreFile struct {
|
|||||||
Content []byte
|
Content []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets the Caddyfile contents
|
// Body Gets the Caddyfile contents
|
||||||
func (c *CoreFile) Body() []byte {
|
func (c *CoreFile) Body() []byte {
|
||||||
return c.Content
|
return c.Content
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets the path to the origin file
|
// Path Gets the path to the origin file
|
||||||
func (c *CoreFile) Path() string {
|
func (c *CoreFile) Path() string {
|
||||||
return "CoreFile"
|
return "CoreFile"
|
||||||
}
|
}
|
||||||
|
|
||||||
// The type of server this input is intended for
|
// ServerType The type of server this input is intended for
|
||||||
func (c *CoreFile) ServerType() string {
|
func (c *CoreFile) ServerType() string {
|
||||||
return "dns"
|
return "dns"
|
||||||
}
|
}
|
||||||
|
181
pkg/dns/dns.go
181
pkg/dns/dns.go
@@ -12,87 +12,41 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
miekgdns "github.com/miekg/dns"
|
miekgdns "github.com/miekg/dns"
|
||||||
"github.com/pkg/errors"
|
|
||||||
v12 "k8s.io/api/core/v1"
|
v12 "k8s.io/api/core/v1"
|
||||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||||
"k8s.io/apimachinery/pkg/apis/meta/v1"
|
"k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/fields"
|
|
||||||
utilnet "k8s.io/apimachinery/pkg/util/net"
|
utilnet "k8s.io/apimachinery/pkg/util/net"
|
||||||
"k8s.io/apimachinery/pkg/util/sets"
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
"k8s.io/apimachinery/pkg/watch"
|
"k8s.io/apimachinery/pkg/watch"
|
||||||
"k8s.io/client-go/kubernetes"
|
|
||||||
v13 "k8s.io/client-go/kubernetes/typed/core/v1"
|
v13 "k8s.io/client-go/kubernetes/typed/core/v1"
|
||||||
"k8s.io/client-go/rest"
|
|
||||||
"k8s.io/client-go/util/flowcontrol"
|
"k8s.io/client-go/util/flowcontrol"
|
||||||
|
|
||||||
"github.com/wencaiwulue/kubevpn/pkg/util"
|
"github.com/wencaiwulue/kubevpn/pkg/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetDNSServiceIPFromPod(clientset *kubernetes.Clientset, restclient *rest.RESTClient, config *rest.Config, podName, namespace string) (*miekgdns.ClientConfig, error) {
|
type Config struct {
|
||||||
resolvConfStr, err := util.Shell(clientset, restclient, config, podName, "", namespace, []string{"cat", "/etc/resolv.conf"})
|
Config *miekgdns.ClientConfig
|
||||||
if err != nil {
|
Ns []string
|
||||||
return nil, err
|
UseLocalDNS bool
|
||||||
}
|
TunName string
|
||||||
resolvConf, err := miekgdns.ClientConfigFromReader(bytes.NewBufferString(resolvConfStr))
|
|
||||||
if err != nil {
|
Hosts []Entry
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if ips, err := GetDNSIPFromDnsPod(clientset); err == nil && len(ips) != 0 {
|
|
||||||
resolvConf.Servers = ips
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// linux nameserver only support amount is 3, so if namespace too much, just use two, left one to system
|
func (c *Config) AddServiceNameToHosts(ctx context.Context, serviceInterface v13.ServiceInterface, hosts ...Entry) {
|
||||||
if len(resolvConf.Servers) > 2 {
|
|
||||||
resolvConf.Servers = resolvConf.Servers[:2]
|
|
||||||
}
|
|
||||||
|
|
||||||
return resolvConf, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetDNSIPFromDnsPod(clientset *kubernetes.Clientset) (ips []string, err error) {
|
|
||||||
var serviceList *v12.ServiceList
|
|
||||||
serviceList, err = clientset.CoreV1().Services(v1.NamespaceSystem).List(context.Background(), v1.ListOptions{
|
|
||||||
LabelSelector: fields.OneTermEqualSelector("k8s-app", "kube-dns").String(),
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for _, item := range serviceList.Items {
|
|
||||||
if len(item.Spec.ClusterIP) != 0 {
|
|
||||||
ips = append(ips, item.Spec.ClusterIP)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var podList *v12.PodList
|
|
||||||
podList, err = clientset.CoreV1().Pods(v1.NamespaceSystem).List(context.Background(), v1.ListOptions{
|
|
||||||
LabelSelector: fields.OneTermEqualSelector("k8s-app", "kube-dns").String(),
|
|
||||||
})
|
|
||||||
if err == nil {
|
|
||||||
for _, pod := range podList.Items {
|
|
||||||
if pod.Status.Phase == v12.PodRunning && pod.DeletionTimestamp == nil {
|
|
||||||
ips = append(ips, pod.Status.PodIP)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(ips) == 0 {
|
|
||||||
err = errors.New("can not found any dns service ip")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err = nil
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func AddServiceNameToHosts(ctx context.Context, serviceInterface v13.ServiceInterface, hosts ...Entry) {
|
|
||||||
rateLimiter := flowcontrol.NewTokenBucketRateLimiter(0.2, 1)
|
rateLimiter := flowcontrol.NewTokenBucketRateLimiter(0.2, 1)
|
||||||
defer rateLimiter.Stop()
|
defer rateLimiter.Stop()
|
||||||
var last string
|
var last string
|
||||||
|
|
||||||
serviceList, err := serviceInterface.List(ctx, v1.ListOptions{})
|
serviceList, err := serviceInterface.List(ctx, v1.ListOptions{})
|
||||||
if err == nil && len(serviceList.Items) != 0 {
|
if err == nil && len(serviceList.Items) != 0 {
|
||||||
entry := generateHostsEntry(serviceList.Items, hosts)
|
entry := c.generateHostsEntry(serviceList.Items, hosts)
|
||||||
if err = updateHosts(entry); err == nil {
|
if entry != "" {
|
||||||
|
if err = c.updateHosts(entry); err == nil {
|
||||||
last = entry
|
last = entry
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
@@ -102,6 +56,7 @@ func AddServiceNameToHosts(ctx context.Context, serviceInterface v13.ServiceInte
|
|||||||
w, err := serviceInterface.Watch(ctx, v1.ListOptions{
|
w, err := serviceInterface.Watch(ctx, v1.ListOptions{
|
||||||
Watch: true, ResourceVersion: serviceList.ResourceVersion,
|
Watch: true, ResourceVersion: serviceList.ResourceVersion,
|
||||||
})
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if utilnet.IsConnectionRefused(err) || apierrors.IsTooManyRequests(err) {
|
if utilnet.IsConnectionRefused(err) || apierrors.IsTooManyRequests(err) {
|
||||||
time.Sleep(time.Second * 5)
|
time.Sleep(time.Second * 5)
|
||||||
@@ -111,11 +66,11 @@ func AddServiceNameToHosts(ctx context.Context, serviceInterface v13.ServiceInte
|
|||||||
defer w.Stop()
|
defer w.Stop()
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case c, ok := <-w.ResultChan():
|
case event, ok := <-w.ResultChan():
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if watch.Error == c.Type || watch.Bookmark == c.Type {
|
if watch.Error == event.Type || watch.Bookmark == event.Type {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if !rateLimiter.TryAccept() {
|
if !rateLimiter.TryAccept() {
|
||||||
@@ -125,11 +80,14 @@ func AddServiceNameToHosts(ctx context.Context, serviceInterface v13.ServiceInte
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
entry := generateHostsEntry(list.Items, hosts)
|
entry := c.generateHostsEntry(list.Items, hosts)
|
||||||
|
if entry == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
if entry == last {
|
if entry == last {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if err = updateHosts(entry); err != nil {
|
if err = c.updateHosts(entry); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
last = entry
|
last = entry
|
||||||
@@ -140,46 +98,44 @@ func AddServiceNameToHosts(ctx context.Context, serviceInterface v13.ServiceInte
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateHosts(str string) error {
|
func (c *Config) updateHosts(str string) error {
|
||||||
if len(str) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
path := GetHostFile()
|
path := GetHostFile()
|
||||||
file, err := os.ReadFile(path)
|
file, err := os.ReadFile(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
split := strings.Split(string(file), "\n")
|
lines := strings.Split(string(file), "\n")
|
||||||
//for i := 0; i < len(split); i++ {
|
for i := 0; i < len(lines); i++ {
|
||||||
// if strings.Contains(split[i], "KubeVPN") {
|
line := lines[i]
|
||||||
// split = append(split[:i], split[i+1:]...)
|
if strings.Contains(line, config.HostsKeyWord) {
|
||||||
// i--
|
for _, host := range c.Hosts {
|
||||||
// }
|
if strings.Contains(line, host.Domain) {
|
||||||
//}
|
lines = append(lines[:i], lines[i+1:]...)
|
||||||
var sb strings.Builder
|
i--
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(lines) == 0 {
|
||||||
|
return fmt.Errorf("empty hosts file")
|
||||||
|
}
|
||||||
|
|
||||||
sb.WriteString(strings.Join(split, "\n"))
|
var sb strings.Builder
|
||||||
|
sb.WriteString(strings.Join(lines, "\n"))
|
||||||
if str != "" {
|
if str != "" {
|
||||||
sb.WriteString("\n")
|
sb.WriteString("\n")
|
||||||
sb.WriteString(str)
|
sb.WriteString(str)
|
||||||
}
|
}
|
||||||
|
|
||||||
s := sb.String()
|
s := sb.String()
|
||||||
|
|
||||||
// remove last empty line
|
// remove last empty line
|
||||||
strList := strings.Split(s, "\n")
|
s = strings.TrimRight(s, "\n")
|
||||||
for {
|
|
||||||
if len(strList) > 0 {
|
if strings.TrimSpace(s) == "" {
|
||||||
if strList[len(strList)-1] == "" {
|
return fmt.Errorf("empty content after update")
|
||||||
strList = strList[:len(strList)-1]
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return os.WriteFile(path, []byte(strings.Join(strList, "\n")), 0644)
|
return os.WriteFile(path, []byte(s), 0644)
|
||||||
}
|
}
|
||||||
|
|
||||||
type Entry struct {
|
type Entry struct {
|
||||||
@@ -187,10 +143,11 @@ type Entry struct {
|
|||||||
Domain string
|
Domain string
|
||||||
}
|
}
|
||||||
|
|
||||||
func generateHostsEntry(list []v12.Service, hosts []Entry) string {
|
func (c *Config) generateHostsEntry(list []v12.Service, hosts []Entry) string {
|
||||||
const ServiceKubernetes = "kubernetes"
|
const ServiceKubernetes = "kubernetes"
|
||||||
var entryList []Entry
|
var entryList []Entry
|
||||||
|
|
||||||
|
// get all service ip
|
||||||
for _, item := range list {
|
for _, item := range list {
|
||||||
if strings.EqualFold(item.Name, ServiceKubernetes) {
|
if strings.EqualFold(item.Name, ServiceKubernetes) {
|
||||||
continue
|
continue
|
||||||
@@ -214,7 +171,7 @@ func generateHostsEntry(list []v12.Service, hosts []Entry) string {
|
|||||||
})
|
})
|
||||||
entryList = append(entryList, hosts...)
|
entryList = append(entryList, hosts...)
|
||||||
|
|
||||||
// 判断是否是通的,或者直接用查询是否有同样条目的记录
|
// if dns already works well, not needs to add it to hosts file
|
||||||
for i := 0; i < len(entryList); i++ {
|
for i := 0; i < len(entryList); i++ {
|
||||||
e := entryList[i]
|
e := entryList[i]
|
||||||
host, err := net.LookupHost(e.Domain)
|
host, err := net.LookupHost(e.Domain)
|
||||||
@@ -224,11 +181,53 @@ func generateHostsEntry(list []v12.Service, hosts []Entry) string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if hosts file already contains item, not needs to add it to hosts file
|
||||||
|
file, err := os.ReadFile(GetHostFile())
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
lines := strings.Split(string(file), "\n")
|
||||||
|
for i := 0; i < len(lines); i++ {
|
||||||
|
line := lines[i]
|
||||||
|
for j := 0; j < len(entryList); j++ {
|
||||||
|
entry := entryList[j]
|
||||||
|
if strings.Contains(line, entry.Domain) && strings.Contains(line, entry.IP) {
|
||||||
|
entryList = append(entryList[:j], entryList[j+1:]...)
|
||||||
|
j--
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Hosts = append(c.Hosts, entryList...)
|
||||||
var sb = new(bytes.Buffer)
|
var sb = new(bytes.Buffer)
|
||||||
w := tabwriter.NewWriter(sb, 1, 1, 1, ' ', 0)
|
w := tabwriter.NewWriter(sb, 1, 1, 1, ' ', 0)
|
||||||
for _, e := range entryList {
|
for _, e := range entryList {
|
||||||
_, _ = fmt.Fprintf(w, "%s\t%s\t%s\t%s\n", e.IP, e.Domain, "", "# Add by KubeVPN")
|
_, _ = fmt.Fprintf(w, "%s\t%s\t%s\t%s\n", e.IP, e.Domain, "", config.HostsKeyWord)
|
||||||
}
|
}
|
||||||
_ = w.Flush()
|
_ = w.Flush()
|
||||||
return sb.String()
|
return sb.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func CleanupHosts() error {
|
||||||
|
path := GetHostFile()
|
||||||
|
file, err := os.ReadFile(path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
lines := strings.Split(string(file), "\n")
|
||||||
|
for i := 0; i < len(lines); i++ {
|
||||||
|
line := lines[i]
|
||||||
|
if strings.Contains(line, config.HostsKeyWord) {
|
||||||
|
lines = append(lines[:i], lines[i+1:]...)
|
||||||
|
i--
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(lines) == 0 {
|
||||||
|
return fmt.Errorf("empty hosts file")
|
||||||
|
}
|
||||||
|
|
||||||
|
var sb strings.Builder
|
||||||
|
sb.WriteString(strings.Join(lines, "\n"))
|
||||||
|
|
||||||
|
return os.WriteFile(path, []byte(sb.String()), 0644)
|
||||||
|
}
|
||||||
|
@@ -1,5 +1,4 @@
|
|||||||
//go:build linux
|
//go:build linux
|
||||||
// +build linux
|
|
||||||
|
|
||||||
package dns
|
package dns
|
||||||
|
|
||||||
@@ -21,7 +20,11 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// systemd-resolve --status, systemd-resolve --flush-caches
|
// systemd-resolve --status, systemd-resolve --flush-caches
|
||||||
func SetupDNS(clientConfig *miekgdns.ClientConfig, _ []string, useLocalDNS bool, tunName string) error {
|
func (c *Config) SetupDNS() error {
|
||||||
|
clientConfig := c.Config
|
||||||
|
useLocalDNS := c.UseLocalDNS
|
||||||
|
tunName := c.TunName
|
||||||
|
|
||||||
existNameservers := make([]string, 0)
|
existNameservers := make([]string, 0)
|
||||||
existSearches := make([]string, 0)
|
existSearches := make([]string, 0)
|
||||||
filename := filepath.Join("/", "etc", "resolv.conf")
|
filename := filepath.Join("/", "etc", "resolv.conf")
|
||||||
@@ -39,7 +42,7 @@ func SetupDNS(clientConfig *miekgdns.ClientConfig, _ []string, useLocalDNS bool,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if useLocalDNS {
|
if useLocalDNS {
|
||||||
if err := SetupLocalDNS(clientConfig, existNameservers); err != nil {
|
if err = SetupLocalDNS(clientConfig, existNameservers); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
clientConfig.Servers[0] = "127.0.0.1"
|
clientConfig.Servers[0] = "127.0.0.1"
|
||||||
@@ -103,8 +106,8 @@ func SetupLocalDNS(clientConfig *miekgdns.ClientConfig, existNameservers []strin
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func CancelDNS(tunName string) {
|
func (c *Config) CancelDNS() {
|
||||||
updateHosts("")
|
c.updateHosts("")
|
||||||
|
|
||||||
filename := filepath.Join("/", "etc", "resolv.conf")
|
filename := filepath.Join("/", "etc", "resolv.conf")
|
||||||
_ = os.Rename(getBackupFilename(filename), filename)
|
_ = os.Rename(getBackupFilename(filename), filename)
|
||||||
|
@@ -1,5 +1,4 @@
|
|||||||
//go:build darwin
|
//go:build darwin
|
||||||
// +build darwin
|
|
||||||
|
|
||||||
package dns
|
package dns
|
||||||
|
|
||||||
@@ -31,15 +30,18 @@ var resolv = "/etc/resolv.conf"
|
|||||||
// service.namespace.svc:port
|
// service.namespace.svc:port
|
||||||
// service.namespace.svc.cluster:port
|
// service.namespace.svc.cluster:port
|
||||||
// service.namespace.svc.cluster.local:port
|
// service.namespace.svc.cluster.local:port
|
||||||
func SetupDNS(config *miekgdns.ClientConfig, ns []string, _ bool, tunName string) error {
|
func (c *Config) SetupDNS() error {
|
||||||
usingResolver(config, ns, tunName)
|
c.usingResolver()
|
||||||
_ = exec.Command("killall", "mDNSResponderHelper").Run()
|
_ = exec.Command("killall", "mDNSResponderHelper").Run()
|
||||||
_ = exec.Command("killall", "-HUP", "mDNSResponder").Run()
|
_ = exec.Command("killall", "-HUP", "mDNSResponder").Run()
|
||||||
_ = exec.Command("dscacheutil", "-flushcache").Run()
|
_ = exec.Command("dscacheutil", "-flushcache").Run()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func usingResolver(clientConfig *miekgdns.ClientConfig, ns []string, tunName string) {
|
func (c *Config) usingResolver() {
|
||||||
|
var clientConfig = c.Config
|
||||||
|
var ns = c.Ns
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
_ = os.RemoveAll(filepath.Join("/", "etc", "resolver"))
|
_ = os.RemoveAll(filepath.Join("/", "etc", "resolver"))
|
||||||
if err = os.MkdirAll(filepath.Join("/", "etc", "resolver"), fs.ModePerm); err != nil {
|
if err = os.MkdirAll(filepath.Join("/", "etc", "resolver"), fs.ModePerm); err != nil {
|
||||||
@@ -80,7 +82,7 @@ func usingResolver(clientConfig *miekgdns.ClientConfig, ns []string, tunName str
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func usingNetworkSetup(ip string, namespace string) {
|
func (c *Config) usingNetworkSetup(ip string, namespace string) {
|
||||||
networkSetup(ip, namespace)
|
networkSetup(ip, namespace)
|
||||||
var ctx context.Context
|
var ctx context.Context
|
||||||
ctx, cancel = context.WithCancel(context.Background())
|
ctx, cancel = context.WithCancel(context.Background())
|
||||||
@@ -153,13 +155,13 @@ func toString(config miekgdns.ClientConfig) string {
|
|||||||
return builder.String()
|
return builder.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func CancelDNS(tunName string) {
|
func (c *Config) CancelDNS() {
|
||||||
if cancel != nil {
|
if cancel != nil {
|
||||||
cancel()
|
cancel()
|
||||||
}
|
}
|
||||||
_ = os.RemoveAll(filepath.Join("/", "etc", "resolver"))
|
_ = os.RemoveAll(filepath.Join("/", "etc", "resolver"))
|
||||||
//networkCancel()
|
//networkCancel()
|
||||||
//updateHosts("")
|
c.updateHosts("")
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -1,5 +1,4 @@
|
|||||||
//go:build windows
|
//go:build windows
|
||||||
// +build windows
|
|
||||||
|
|
||||||
package dns
|
package dns
|
||||||
|
|
||||||
@@ -9,18 +8,23 @@ import (
|
|||||||
"net/netip"
|
"net/netip"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
|
||||||
miekgdns "github.com/miekg/dns"
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"golang.org/x/sys/windows"
|
"golang.org/x/sys/windows"
|
||||||
"golang.zx2c4.com/wireguard/windows/tunnel/winipcfg"
|
"golang.zx2c4.com/wireguard/windows/tunnel/winipcfg"
|
||||||
)
|
)
|
||||||
|
|
||||||
func SetupDNS(clientConfig *miekgdns.ClientConfig, _ []string, _ bool, tunName string) error {
|
func (c *Config) SetupDNS() error {
|
||||||
|
clientConfig := c.Config
|
||||||
|
tunName := c.TunName
|
||||||
|
|
||||||
tun, err := net.InterfaceByName(tunName)
|
tun, err := net.InterfaceByName(tunName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
luid := winipcfg.LUIDFromIndex(tun.Index)
|
luid, err := winipcfg.LUIDFromIndex(uint32(tun.Index))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
var servers []netip.Addr
|
var servers []netip.Addr
|
||||||
for _, s := range clientConfig.Servers {
|
for _, s := range clientConfig.Servers {
|
||||||
var addr netip.Addr
|
var addr netip.Addr
|
||||||
@@ -41,13 +45,16 @@ func SetupDNS(clientConfig *miekgdns.ClientConfig, _ []string, _ bool, tunName s
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func CancelDNS(tunName string) {
|
func (c *Config) CancelDNS() {
|
||||||
updateHosts("")
|
c.updateHosts("")
|
||||||
tun, err := net.InterfaceByName(tunName)
|
tun, err := net.InterfaceByName(c.TunName)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
luid, err := winipcfg.LUIDFromIndex(uint32(tun.Index))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
luid := winipcfg.LUIDFromIndex(tun.Index)
|
|
||||||
_ = luid.FlushDNS(windows.AF_INET)
|
_ = luid.FlushDNS(windows.AF_INET)
|
||||||
_ = luid.FlushRoutes(windows.AF_INET)
|
_ = luid.FlushRoutes(windows.AF_INET)
|
||||||
}
|
}
|
||||||
|
@@ -21,7 +21,6 @@ import (
|
|||||||
"k8s.io/utils/pointer"
|
"k8s.io/utils/pointer"
|
||||||
|
|
||||||
"github.com/wencaiwulue/kubevpn/pkg/config"
|
"github.com/wencaiwulue/kubevpn/pkg/config"
|
||||||
"github.com/wencaiwulue/kubevpn/pkg/dns"
|
|
||||||
"github.com/wencaiwulue/kubevpn/pkg/util"
|
"github.com/wencaiwulue/kubevpn/pkg/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -79,11 +78,10 @@ func (c *ConnectOptions) Cleanup() {
|
|||||||
c.cancel()
|
c.cancel()
|
||||||
}
|
}
|
||||||
c.RollbackFuncList = c.RollbackFuncList[:]
|
c.RollbackFuncList = c.RollbackFuncList[:]
|
||||||
name, err := c.GetTunDeviceName()
|
if c.dnsConfig != nil {
|
||||||
if err == nil {
|
log.Infof("clean up dns")
|
||||||
log.Errorf("get tun device error: %v", err)
|
c.dnsConfig.CancelDNS()
|
||||||
}
|
}
|
||||||
dns.CancelDNS(name)
|
|
||||||
log.Info("clean up successfully")
|
log.Info("clean up successfully")
|
||||||
util.CleanExtensionLib()
|
util.CleanExtensionLib()
|
||||||
}
|
}
|
||||||
|
@@ -92,6 +92,7 @@ type ConnectOptions struct {
|
|||||||
localTunIPv4 *net.IPNet
|
localTunIPv4 *net.IPNet
|
||||||
localTunIPv6 *net.IPNet
|
localTunIPv6 *net.IPNet
|
||||||
RollbackFuncList []func()
|
RollbackFuncList []func()
|
||||||
|
dnsConfig *dns.Config
|
||||||
|
|
||||||
apiServerIPs []net.IP
|
apiServerIPs []net.IP
|
||||||
extraHost []dns.Entry
|
extraHost []dns.Entry
|
||||||
@@ -620,7 +621,7 @@ func (c *ConnectOptions) setupDNS(ctx context.Context) error {
|
|||||||
log.Errorf("get running pod list failed, err: %v", err)
|
log.Errorf("get running pod list failed, err: %v", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
relovConf, err := dns.GetDNSServiceIPFromPod(c.clientset, c.restclient, c.config, pod[0].GetName(), c.Namespace)
|
relovConf, err := util.GetDNSServiceIPFromPod(c.clientset, c.restclient, c.config, pod[0].GetName(), c.Namespace)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorln(err)
|
log.Errorln(err)
|
||||||
return err
|
return err
|
||||||
@@ -645,11 +646,18 @@ func (c *ConnectOptions) setupDNS(ctx context.Context) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err = dns.SetupDNS(relovConf, ns.UnsortedList(), c.UseLocalDNS, tunName); err != nil {
|
c.dnsConfig = &dns.Config{
|
||||||
|
Config: relovConf,
|
||||||
|
Ns: ns.UnsortedList(),
|
||||||
|
UseLocalDNS: c.UseLocalDNS,
|
||||||
|
TunName: tunName,
|
||||||
|
Hosts: c.extraHost,
|
||||||
|
}
|
||||||
|
if err = c.dnsConfig.SetupDNS(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// dump service in current namespace for support DNS resolve service:port
|
// dump service in current namespace for support DNS resolve service:port
|
||||||
go dns.AddServiceNameToHosts(ctx, c.clientset.CoreV1().Services(c.Namespace), c.extraHost...)
|
go c.dnsConfig.AddServiceNameToHosts(ctx, c.clientset.CoreV1().Services(c.Namespace), c.extraHost...)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1077,7 +1085,7 @@ func (c *ConnectOptions) addExtraRoute(ctx context.Context) error {
|
|||||||
if len(c.ExtraDomain) == 0 {
|
if len(c.ExtraDomain) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
ips, err := dns.GetDNSIPFromDnsPod(c.clientset)
|
ips, err := util.GetDNSIPFromDnsPod(c.clientset)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@@ -91,7 +91,10 @@ func addTunRoutes(tunName string, routes ...types.Route) error {
|
|||||||
if err2 != nil {
|
if err2 != nil {
|
||||||
return err2
|
return err2
|
||||||
}
|
}
|
||||||
ifName := winipcfg.LUIDFromIndex(name.Index)
|
ifName, err := winipcfg.LUIDFromIndex(uint32(name.Index))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
for _, route := range routes {
|
for _, route := range routes {
|
||||||
if route.Dst.String() == "" {
|
if route.Dst.String() == "" {
|
||||||
continue
|
continue
|
||||||
|
67
pkg/util/dns.go
Normal file
67
pkg/util/dns.go
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
package util
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/miekg/dns"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"k8s.io/api/core/v1"
|
||||||
|
v12 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/fields"
|
||||||
|
"k8s.io/client-go/kubernetes"
|
||||||
|
"k8s.io/client-go/rest"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetDNSServiceIPFromPod(clientset *kubernetes.Clientset, restclient *rest.RESTClient, config *rest.Config, podName, namespace string) (*dns.ClientConfig, error) {
|
||||||
|
resolvConfStr, err := Shell(clientset, restclient, config, podName, "", namespace, []string{"cat", "/etc/resolv.conf"})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
resolvConf, err := dns.ClientConfigFromReader(bytes.NewBufferString(resolvConfStr))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if ips, err := GetDNSIPFromDnsPod(clientset); err == nil && len(ips) != 0 {
|
||||||
|
resolvConf.Servers = ips
|
||||||
|
}
|
||||||
|
|
||||||
|
// linux nameserver only support amount is 3, so if namespace too much, just use two, left one to system
|
||||||
|
if len(resolvConf.Servers) > 2 {
|
||||||
|
resolvConf.Servers = resolvConf.Servers[:2]
|
||||||
|
}
|
||||||
|
|
||||||
|
return resolvConf, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetDNSIPFromDnsPod(clientset *kubernetes.Clientset) (ips []string, err error) {
|
||||||
|
var serviceList *v1.ServiceList
|
||||||
|
serviceList, err = clientset.CoreV1().Services(v12.NamespaceSystem).List(context.Background(), v12.ListOptions{
|
||||||
|
LabelSelector: fields.OneTermEqualSelector("k8s-app", "kube-dns").String(),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, item := range serviceList.Items {
|
||||||
|
if len(item.Spec.ClusterIP) != 0 {
|
||||||
|
ips = append(ips, item.Spec.ClusterIP)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var podList *v1.PodList
|
||||||
|
podList, err = clientset.CoreV1().Pods(v12.NamespaceSystem).List(context.Background(), v12.ListOptions{
|
||||||
|
LabelSelector: fields.OneTermEqualSelector("k8s-app", "kube-dns").String(),
|
||||||
|
})
|
||||||
|
if err == nil {
|
||||||
|
for _, pod := range podList.Items {
|
||||||
|
if pod.Status.Phase == v1.PodRunning && pod.DeletionTimestamp == nil {
|
||||||
|
ips = append(ips, pod.Status.PodIP)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(ips) == 0 {
|
||||||
|
err = errors.New("can not found any dns service ip")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = nil
|
||||||
|
return
|
||||||
|
}
|
Reference in New Issue
Block a user