Compare commits
2 commits
603e93355b
...
4be2bc9343
| Author | SHA1 | Date | |
|---|---|---|---|
| 4be2bc9343 | |||
| 77f8ee4024 |
6 changed files with 54 additions and 26 deletions
42
README.md
42
README.md
|
|
@ -9,26 +9,30 @@ Deep TLS / certificate analysis is intentionally **delegated to
|
||||||
[checker-tls](https://git.happydns.org/checker-tls)** - this checker only
|
[checker-tls](https://git.happydns.org/checker-tls)** - this checker only
|
||||||
relies on TLS for transport.
|
relies on TLS for transport.
|
||||||
|
|
||||||
## What it checks
|
## Rules
|
||||||
|
|
||||||
| Rule | What it verifies |
|
| Code | Description | Severity |
|
||||||
| --------------------------------- | --------------------------------------------------------------------------------- |
|
|-------------------------------|-------------------------------------------------------------------------------------------------------------------|---------------------|
|
||||||
| `http.tcp_reachable` | Port 80 accepts connections on every A/AAAA address. |
|
| `http.tcp_reachable` | Verifies that every probed IP accepts an HTTP connection on the standard port. | CRITICAL |
|
||||||
| `https.tcp_reachable` | Port 443 accepts connections on every A/AAAA address. |
|
| `https.tcp_reachable` | Verifies that every probed IP accepts an HTTPS connection on the standard port. | CRITICAL |
|
||||||
| `http.https_redirect` | Plain HTTP redirects to HTTPS (warning if not). |
|
| `http.https_redirect` | Plain HTTP responses must redirect to an HTTPS URL on the same host. | WARNING |
|
||||||
| `http.hsts` | `Strict-Transport-Security` is present with a sufficient `max-age`. |
|
| `http.redirect_chain` | Inspects the redirect chain (RFC 9110 §15.4) for loops, excessive length, and scheme downgrades. | WARNING |
|
||||||
| `http.csp` | `Content-Security-Policy` is set; flags `'unsafe-inline'` / `'unsafe-eval'`. |
|
| `http.redirect_permanence` | HTTP→HTTPS upgrade should use 301 or 308 (permanent) rather than 302/307 (temporary). | WARNING |
|
||||||
| `http.x_frame_options` | `X-Frame-Options` or CSP `frame-ancestors` provides clickjacking protection. |
|
| `http.hsts` | Verifies the presence and quality of the Strict-Transport-Security header on HTTPS responses. | WARNING |
|
||||||
| `http.x_content_type_options` | `X-Content-Type-Options: nosniff` is set. |
|
| `http.csp` | Verifies the presence and quality of the Content-Security-Policy header on HTTPS responses. | WARNING |
|
||||||
| `http.x_xss_protection` | Reports the legacy `X-XSS-Protection` header (recommendation: disable). |
|
| `http.x_frame_options` | Verifies that responses set X-Frame-Options or a CSP frame-ancestors directive. | WARNING |
|
||||||
| `http.referrer_policy` | `Referrer-Policy` is set to a privacy-preserving value (W3C Referrer Policy). |
|
| `http.x_content_type_options` | Verifies that responses set X-Content-Type-Options: nosniff. | WARNING |
|
||||||
| `http.permissions_policy` | `Permissions-Policy` is set (W3C Permissions Policy, replaces Feature-Policy). |
|
| `http.x_xss_protection` | Reports the value of the legacy X-XSS-Protection header (disabled is preferred; CSP is the proper replacement). | INFO |
|
||||||
| `http.coop` | `Cross-Origin-Opener-Policy` isolates the document from cross-origin windows. |
|
| `http.referrer_policy` | Verifies that responses set a Referrer-Policy header with a privacy-preserving value. | WARNING |
|
||||||
| `http.coep` | `Cross-Origin-Embedder-Policy` requires CORP/CORS opt-in for embedded resources. |
|
| `http.permissions_policy` | Verifies that the Permissions-Policy header restricts powerful APIs (camera, microphone, geolocation, …). | WARNING |
|
||||||
| `http.corp` | `Cross-Origin-Resource-Policy` restricts cross-origin embedding of responses. |
|
| `http.coop` | Verifies the Cross-Origin-Opener-Policy (COOP) header for cross-origin process isolation. | WARNING |
|
||||||
| `http.cookie_flags` | Every Set-Cookie has `Secure`, `HttpOnly`, and a `SameSite` attribute. |
|
| `http.coep` | Verifies the Cross-Origin-Embedder-Policy (COEP) header, required (with COOP) to enable cross-origin isolation. | WARNING |
|
||||||
| `http.sri` | Cross-origin `<script>`/`<link>` tags carry `integrity=` (Subresource Integrity). |
|
| `http.corp` | Verifies the Cross-Origin-Resource-Policy (CORP) header restricts cross-origin/cross-site embedding of responses. | WARNING |
|
||||||
| `http.security_txt` | `/.well-known/security.txt` is published (RFC 9116). |
|
| `http.cookie_flags` | Verifies that cookies set over HTTPS use the Secure, HttpOnly and SameSite attributes. | WARNING |
|
||||||
|
| `http.cookie_prefixes` | Verifies cookies using the __Secure- / __Host- name prefixes meet the RFC 6265bis constraints. | WARNING |
|
||||||
|
| `http.cookie_size` | Flags cookies whose Set-Cookie line exceeds the 4096-byte minimum browsers must support (RFC 6265 §6.1). | WARNING |
|
||||||
|
| `http.sri` | Reports cross-origin script and stylesheet tags that are missing Subresource Integrity (integrity=) attributes. | WARNING |
|
||||||
|
| `http.security_txt` | Reports whether /.well-known/security.txt (RFC 9116) is published. | WARNING |
|
||||||
|
|
||||||
## Options
|
## Options
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
sdk "git.happydns.org/checker-sdk-go/checker"
|
sdk "git.happydns.org/checker-sdk-go/checker"
|
||||||
|
happydns "git.happydns.org/happyDomain/model"
|
||||||
"golang.org/x/net/html"
|
"golang.org/x/net/html"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -143,7 +144,22 @@ func buildTarget(ctx context.Context, opts sdk.CheckerOptions) (Target, error) {
|
||||||
userAgent = v
|
userAgent = v
|
||||||
}
|
}
|
||||||
|
|
||||||
host, ips := addressesFromServer(server)
|
// Origin is the FQDN where the service is mounted: svc.Domain holds the
|
||||||
|
// subdomain (relative to apex; "@" for apex), and the domain_name
|
||||||
|
// autofill carries the zone apex.
|
||||||
|
apex := ""
|
||||||
|
if v, ok := sdk.GetOption[string](opts, OptionDomainName); ok {
|
||||||
|
apex = strings.TrimSuffix(v, ".")
|
||||||
|
}
|
||||||
|
subdomain := ""
|
||||||
|
if svc, ok := sdk.GetOption[happydns.ServiceMessage](opts, OptionService); ok {
|
||||||
|
subdomain = strings.TrimSuffix(svc.Domain, ".")
|
||||||
|
}
|
||||||
|
origin := sdk.JoinRelative(subdomain, apex)
|
||||||
|
host, ips := addressesFromServer(server, origin)
|
||||||
|
if host == "" {
|
||||||
|
host = origin
|
||||||
|
}
|
||||||
// abstract.Server only pins one A and one AAAA. Resolve the host to
|
// abstract.Server only pins one A and one AAAA. Resolve the host to
|
||||||
// pick up any additional records the authoritative DNS exposes, so
|
// pick up any additional records the authoritative DNS exposes, so
|
||||||
// multi-IP deployments aren't silently under-probed. Failures are
|
// multi-IP deployments aren't silently under-probed. Failures are
|
||||||
|
|
|
||||||
|
|
@ -82,6 +82,12 @@ func (p *httpProvider) Definition() *sdk.CheckerDefinition {
|
||||||
AutoFill: sdk.AutoFillService,
|
AutoFill: sdk.AutoFillService,
|
||||||
Hide: true,
|
Hide: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Id: OptionDomainName,
|
||||||
|
Label: "Parent domain name",
|
||||||
|
AutoFill: sdk.AutoFillDomainName,
|
||||||
|
Hide: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Rules: Rules(),
|
Rules: Rules(),
|
||||||
|
|
|
||||||
|
|
@ -227,7 +227,7 @@ func TestAddressesFromServer(t *testing.T) {
|
||||||
}
|
}
|
||||||
for _, c := range cases {
|
for _, c := range cases {
|
||||||
t.Run(c.name, func(t *testing.T) {
|
t.Run(c.name, func(t *testing.T) {
|
||||||
host, ips := addressesFromServer(c.srv)
|
host, ips := addressesFromServer(c.srv, "")
|
||||||
if host != c.wantHost {
|
if host != c.wantHost {
|
||||||
t.Errorf("host = %q, want %q", host, c.wantHost)
|
t.Errorf("host = %q, want %q", host, c.wantHost)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,6 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"strings"
|
|
||||||
|
|
||||||
sdk "git.happydns.org/checker-sdk-go/checker"
|
sdk "git.happydns.org/checker-sdk-go/checker"
|
||||||
happydns "git.happydns.org/happyDomain/model"
|
happydns "git.happydns.org/happyDomain/model"
|
||||||
|
|
@ -36,15 +35,17 @@ func resolveServer(opts sdk.CheckerOptions) (*abstract.Server, error) {
|
||||||
return &server, nil
|
return &server, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// addressesFromServer returns the (host, ips) tuple to probe.
|
// addressesFromServer returns the (host, ips) tuple to probe. origin is
|
||||||
func addressesFromServer(server *abstract.Server) (host string, ips []string) {
|
// the service's parent zone; the A/AAAA Hdr.Name is relative to it as
|
||||||
|
// happyDomain encodes service owners, so we must join before using as FQDN.
|
||||||
|
func addressesFromServer(server *abstract.Server, origin string) (host string, ips []string) {
|
||||||
if server.A != nil && len(server.A.A) > 0 {
|
if server.A != nil && len(server.A.A) > 0 {
|
||||||
host = strings.TrimSuffix(server.A.Hdr.Name, ".")
|
host = sdk.JoinRelative(server.A.Hdr.Name, origin)
|
||||||
ips = append(ips, server.A.A.String())
|
ips = append(ips, server.A.A.String())
|
||||||
}
|
}
|
||||||
if server.AAAA != nil && len(server.AAAA.AAAA) > 0 {
|
if server.AAAA != nil && len(server.AAAA.AAAA) > 0 {
|
||||||
if host == "" {
|
if host == "" {
|
||||||
host = strings.TrimSuffix(server.AAAA.Hdr.Name, ".")
|
host = sdk.JoinRelative(server.AAAA.Hdr.Name, origin)
|
||||||
}
|
}
|
||||||
ips = append(ips, server.AAAA.AAAA.String())
|
ips = append(ips, server.AAAA.AAAA.String())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ const ObservationKeyHTTP = "http"
|
||||||
|
|
||||||
const (
|
const (
|
||||||
OptionService = "service"
|
OptionService = "service"
|
||||||
|
OptionDomainName = "domain_name"
|
||||||
OptionProbeTimeoutMs = "probeTimeoutMs"
|
OptionProbeTimeoutMs = "probeTimeoutMs"
|
||||||
OptionMaxRedirects = "maxRedirects"
|
OptionMaxRedirects = "maxRedirects"
|
||||||
OptionUserAgent = "userAgent"
|
OptionUserAgent = "userAgent"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue