diff --git a/internal/monitor/checker.go b/internal/monitor/checker.go index b5e9235..1f00dd5 100644 --- a/internal/monitor/checker.go +++ b/internal/monitor/checker.go @@ -63,7 +63,7 @@ func RunCheck(ctx context.Context, site models.SiteConfig, strict, insecure *htt case "port": return runPortCheck(ctx, site) case "dns": - return runDNSCheck(ctx, site) + return runDNSCheck(ctx, site, private) default: return CheckResult{SiteID: site.ID, Status: string(models.StatusDown), ErrorReason: "unsupported monitor type: " + site.Type} } @@ -180,7 +180,7 @@ func runPortCheck(_ context.Context, site models.SiteConfig) CheckResult { return CheckResult{SiteID: site.ID, Status: string(models.StatusUp), LatencyNs: latency.Nanoseconds()} } -func runDNSCheck(_ context.Context, site models.SiteConfig) CheckResult { +func runDNSCheck(_ context.Context, site models.SiteConfig, allowPrivate bool) CheckResult { host := site.Hostname if host == "" { host = site.URL @@ -190,9 +190,24 @@ func runDNSCheck(_ context.Context, site models.SiteConfig) CheckResult { if server == "" { server = defaultDNSServer } - if _, _, err := net.SplitHostPort(server); err != nil { - server = net.JoinHostPort(server, defaultDNSPort) + serverHost, serverPort, err := net.SplitHostPort(server) + if err != nil { + serverHost = server + serverPort = defaultDNSPort } + if !allowPrivate { + if serverPort != defaultDNSPort { + return CheckResult{SiteID: site.ID, Status: string(models.StatusDown), ErrorReason: "DNS server port must be 53"} + } + if ips, err := net.LookupIP(serverHost); err == nil { + for _, ip := range ips { + if isPrivateIP(ip) { + return CheckResult{SiteID: site.ID, Status: string(models.StatusDown), ErrorReason: "DNS server resolves to private address"} + } + } + } + } + server = net.JoinHostPort(serverHost, serverPort) qtype := dns.TypeA switch site.DNSResolveType { diff --git a/internal/monitor/safedial.go b/internal/monitor/safedial.go index ae8a0b8..5e85ffa 100644 --- a/internal/monitor/safedial.go +++ b/internal/monitor/safedial.go @@ -11,9 +11,11 @@ var privateRanges []*net.IPNet func init() { cidrs := []string{ + "0.0.0.0/8", "127.0.0.0/8", "::1/128", "10.0.0.0/8", + "100.64.0.0/10", "172.16.0.0/12", "192.168.0.0/16", "169.254.0.0/16", @@ -27,6 +29,9 @@ func init() { } func isPrivateIP(ip net.IP) bool { + if ip.IsUnspecified() || ip.IsMulticast() || ip.IsLoopback() { + return true + } for _, network := range privateRanges { if network.Contains(ip) { return true diff --git a/internal/server/server.go b/internal/server/server.go index 0e6ebf1..cac166e 100644 --- a/internal/server/server.go +++ b/internal/server/server.go @@ -354,8 +354,8 @@ func (s *Server) handleMetrics(w http.ResponseWriter, r *http.Request) { http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) return } - if !s.cfg.MetricsPublic && s.cfg.ClusterKey != "" { - if !checkSecret(r.Header.Get("X-Upkeep-Secret"), s.cfg.ClusterKey) { + if !s.cfg.MetricsPublic { + if !s.requireAuth(r) { http.Error(w, "Unauthorized", http.StatusUnauthorized) return }