From 04d1587a77964636d8e50f5cce475ee8621bece7 Mon Sep 17 00:00:00 2001 From: ginuerzh Date: Tue, 25 Feb 2025 20:39:33 +0800 Subject: [PATCH] set dns for tun --- internal/util/tun/config.go | 1 + listener/tun/metadata.go | 32 ++++++++++++++------------------ listener/tun/tun_linux.go | 17 +++++++++++++++++ listener/tun/tun_windows.go | 11 +++++++++++ 4 files changed, 43 insertions(+), 18 deletions(-) diff --git a/internal/util/tun/config.go b/internal/util/tun/config.go index 1253d586..9763be79 100644 --- a/internal/util/tun/config.go +++ b/internal/util/tun/config.go @@ -14,4 +14,5 @@ type Config struct { MTU int Gateway net.IP Router router.Router + DNS []net.IP } diff --git a/listener/tun/metadata.go b/listener/tun/metadata.go index ded8cfe1..938bdff9 100644 --- a/listener/tun/metadata.go +++ b/listener/tun/metadata.go @@ -22,30 +22,20 @@ type metadata struct { } func (l *tunListener) parseMetadata(md mdata.Metadata) (err error) { - const ( - name = "name" - netKey = "net" - peer = "peer" - mtu = "mtu" - route = "route" - routes = "routes" - gateway = "gw" - ) - config := &tun_util.Config{ - Name: mdutil.GetString(md, name), - Peer: mdutil.GetString(md, peer), - MTU: mdutil.GetInt(md, mtu), - Router: registry.RouterRegistry().Get(mdutil.GetString(md, "router")), + Name: mdutil.GetString(md, "name", "tun.name"), + Peer: mdutil.GetString(md, "peer", "tun.peer"), + MTU: mdutil.GetInt(md, "mtu", "tun.mtu"), + Router: registry.RouterRegistry().Get(mdutil.GetString(md, "router", "tun.router")), } if config.MTU <= 0 { config.MTU = defaultMTU } - if gw := mdutil.GetString(md, gateway); gw != "" { + if gw := mdutil.GetString(md, "gw", "tun.gw"); gw != "" { config.Gateway = net.ParseIP(gw) } - for _, s := range strings.Split(mdutil.GetString(md, netKey), ",") { + for _, s := range strings.Split(mdutil.GetString(md, "net", "tun.net"), ",") { if s = strings.TrimSpace(s); s == "" { continue } @@ -59,7 +49,7 @@ func (l *tunListener) parseMetadata(md mdata.Metadata) (err error) { }) } - for _, s := range strings.Split(mdutil.GetString(md, route), ",") { + for _, s := range strings.Split(mdutil.GetString(md, "route", "tun.route"), ",") { gw := "" if config.Gateway != nil { gw = config.Gateway.String() @@ -69,7 +59,7 @@ func (l *tunListener) parseMetadata(md mdata.Metadata) (err error) { } } - for _, s := range mdutil.GetStrings(md, routes) { + for _, s := range mdutil.GetStrings(md, "routes", "tun.routes") { ss := strings.SplitN(s, " ", 2) if len(ss) == 2 { _, ipNet, _ := net.ParseCIDR(strings.TrimSpace(ss[0])) @@ -94,6 +84,12 @@ func (l *tunListener) parseMetadata(md mdata.Metadata) (err error) { } } + for _, v := range strings.Split(mdutil.GetString(md, "dns", "tun.dns"), ",") { + if ip := net.ParseIP(strings.TrimSpace(v)); ip != nil { + config.DNS = append(config.DNS, ip) + } + } + if config.Router == nil && len(l.routes) > 0 { config.Router = xrouter.NewRouter( xrouter.RoutesOption(l.routes), diff --git a/listener/tun/tun_linux.go b/listener/tun/tun_linux.go index 49695c00..2ef7d0cd 100644 --- a/listener/tun/tun_linux.go +++ b/listener/tun/tun_linux.go @@ -4,6 +4,8 @@ import ( "fmt" "io" "net" + "os/exec" + "strings" "github.com/vishvananda/netlink" ) @@ -44,6 +46,21 @@ func (l *tunListener) createTun() (dev io.ReadWriteCloser, name string, ip net.I return } + var dnsServers []string + for _, dns := range l.md.config.DNS { + dnsServers = append(dnsServers, dns.String()) + } + if len(dnsServers) > 0 { + cmd := fmt.Sprintf("resolvectl dns %s %s", name, strings.Join(dnsServers, " ")) + l.logger.Debug(cmd) + + args := strings.Split(cmd, " ") + if er := exec.Command(args[0], args[1:]...).Run(); er != nil { + err = fmt.Errorf("%s: %v", cmd, er) + return + } + } + return } diff --git a/listener/tun/tun_windows.go b/listener/tun/tun_windows.go index 452b9488..2d8015eb 100644 --- a/listener/tun/tun_windows.go +++ b/listener/tun/tun_windows.go @@ -40,6 +40,17 @@ func (l *tunListener) createTun() (ifce io.ReadWriteCloser, name string, ip net. return } + for _, dns := range l.md.config.DNS { + cmd := fmt.Sprintf("netsh interface ip add dnsservers name=%s address=%s validate=no", name, dns.String()) + l.logger.Debug(cmd) + + args := strings.Split(cmd, " ") + if er := exec.Command(args[0], args[1:]...).Run(); er != nil { + err = fmt.Errorf("%s: %v", cmd, er) + return + } + } + return }