mirror of
https://github.com/tailscale/tailscale.git
synced 2025-08-11 13:18:53 +00:00
cli: implement tailscale dns status
(#13353)
Updates tailscale/tailscale#13326 This PR begins implementing a `tailscale dns` command group in the Tailscale CLI. It provides an initial implementation of `tailscale dns status` which dumps the state of the internal DNS forwarder. Two new endpoints were added in LocalAPI to support the CLI functionality: - `/netmap`: dumps a copy of the last received network map (because the CLI shouldn't have to listen to the ipn bus for a copy) - `/dns-osconfig`: dumps the OS DNS configuration (this will be very handy for the UI clients as well, as they currently do not display this information) My plan is to implement other subcommands mentioned in tailscale/tailscale#13326, such as `query`, in later PRs. Signed-off-by: Andrea Gottardo <andrea@gottardo.me>
This commit is contained in:
@@ -597,6 +597,15 @@ func (b *LocalBackend) SetComponentDebugLogging(component string, until time.Tim
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetDNSOSConfig returns the base OS DNS configuration, as seen by the DNS manager.
|
||||
func (b *LocalBackend) GetDNSOSConfig() (dns.OSConfig, error) {
|
||||
manager, ok := b.sys.DNSManager.GetOK()
|
||||
if !ok {
|
||||
return dns.OSConfig{}, errors.New("DNS manager not available")
|
||||
}
|
||||
return manager.GetBaseConfig()
|
||||
}
|
||||
|
||||
// GetComponentDebugLogging gets the time that component's debug logging is
|
||||
// enabled until, or the zero time if component's time is not currently
|
||||
// enabled.
|
||||
|
@@ -98,6 +98,7 @@ var handler = map[string]localAPIHandler{
|
||||
"derpmap": (*Handler).serveDERPMap,
|
||||
"dev-set-state-store": (*Handler).serveDevSetStateStore,
|
||||
"dial": (*Handler).serveDial,
|
||||
"dns-osconfig": (*Handler).serveDNSOSConfig,
|
||||
"drive/fileserver-address": (*Handler).serveDriveServerAddr,
|
||||
"drive/shares": (*Handler).serveShares,
|
||||
"file-targets": (*Handler).serveFileTargets,
|
||||
@@ -2707,6 +2708,44 @@ func (h *Handler) serveUpdateProgress(w http.ResponseWriter, r *http.Request) {
|
||||
json.NewEncoder(w).Encode(ups)
|
||||
}
|
||||
|
||||
// serveDNSOSConfig serves the current system DNS configuration as a JSON object, if
|
||||
// supported by the OS.
|
||||
func (h *Handler) serveDNSOSConfig(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != httpm.GET {
|
||||
http.Error(w, "only GET allowed", http.StatusMethodNotAllowed)
|
||||
return
|
||||
}
|
||||
// Require write access for privacy reasons.
|
||||
if !h.PermitWrite {
|
||||
http.Error(w, "dns-osconfig dump access denied", http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
bCfg, err := h.b.GetDNSOSConfig()
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
nameservers := make([]string, 0, len(bCfg.Nameservers))
|
||||
for _, ns := range bCfg.Nameservers {
|
||||
nameservers = append(nameservers, ns.String())
|
||||
}
|
||||
searchDomains := make([]string, 0, len(bCfg.SearchDomains))
|
||||
for _, sd := range bCfg.SearchDomains {
|
||||
searchDomains = append(searchDomains, sd.WithoutTrailingDot())
|
||||
}
|
||||
matchDomains := make([]string, 0, len(bCfg.MatchDomains))
|
||||
for _, md := range bCfg.MatchDomains {
|
||||
matchDomains = append(matchDomains, md.WithoutTrailingDot())
|
||||
}
|
||||
response := apitype.DNSOSConfig{
|
||||
Nameservers: nameservers,
|
||||
SearchDomains: searchDomains,
|
||||
MatchDomains: matchDomains,
|
||||
}
|
||||
json.NewEncoder(w).Encode(response)
|
||||
}
|
||||
|
||||
// serveDriveServerAddr handles updates of the Taildrive file server address.
|
||||
func (h *Handler) serveDriveServerAddr(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != "PUT" {
|
||||
|
Reference in New Issue
Block a user