Warda-DNSDocs Warda: from ward — to protect, guardian
v0.7.10

From HTTP to HTTPS

From 0.7.10 (beta; internal/admin/httpsredirect.go, NewRedirectHandler of internal/httpapi). The plain HTTP listener has never served the interface: it sends the browser to HTTPS at the address typed (https://warda, https://ADDRESS-OF-THE-BOX), where the certificate is the one Warda made for itself, to accept in the browser. Once the box has a name whose certificate the browsers trust, HTTP sends the interface and its API to https://<name of the box> instead, by itself: the browser shows no warning any more.

The condition. Every term must hold; the first that does not is the reason told (reason of the API, the sentence of the page and of the command), in this order:

reason The term On the page, when it does not hold
off the redirection is not turned off (a setting of this box, on by default) turned off on the box (warda https-redirect on)
listener Warda listens on HTTPS (WARDA_HTTPS_LISTEN not empty) Warda does not listen on HTTPS
setup the installation is finished: an account exists, the default password is no longer accepted the installation is not finished
name the box has a name: the one of its encrypted DNS (step 1. Certificate of the DNS services, any mode) the box has no name yet
certificate the HTTPS listener presents a certificate for that name the HTTPS interface has no certificate for this name yet
expired that certificate is in force now the certificate is not in force
untrusted it comes from an authority the browsers trust (checked against the authorities of the system of the box, with the chain presented): Let's Encrypt in the modes warda and domain, a public authority in the mode import; a certificate made by Warda (mode self, the certificate of the interface) never does the certificate does not come from an authority the browsers trust
standby in a pair of high availability, this box holds the shared address the other box of the pair holds the shared address
resolve the DNS of Warda answers the name with an address of the box the DNS of Warda does not answer this name with an address of the box

The condition is evaluated again every 30 seconds (it reads the database, the certificate and the state of the pair, never the network), at once for the page and the command, and the end of the certificate is checked at each request. A term that stops holding (the certificate ended, the name given back, HTTPS closed) brings HTTP back to what it did before, by itself: HTTPS at the address typed. Nothing ever locks an administrator out, and for the same reason Warda sends no HSTS (Strict-Transport-Security), over HTTP or over HTTPS: no browser is told to keep to HTTPS, and the redirection itself is not kept by the browser (Cache-Control: no-store).

What is redirected. Everything the plain HTTP listener does not answer itself: the pages of the interface and every call to /api/v1/…, with a 308 (the method and the body are kept, with or without the API token; the call is not made over HTTP, nothing is changed by it), the path and the query kept, the port of HTTPS added when it is not 443 (https://<name>:8443/…).

To the name, only for a client that can find it. The name is answered by the DNS of Warda alone, never published:

  • the box asked by a name Warda alone answers — warda, warda.<local domain>, the name of its encrypted DNS, or a name of before it still serves (after a failover) — is sent to the name, whatever the address of the client: it asks Warda its names;
  • the box asked by an IP address (its own, the address shared by a pair, IPv6), as localhost or by the name of the machine, which say nothing of the DNS of the client: to the name only when the address of the client asked the DNS of Warda over the last 24 hours (the addresses the filter keeps for the devices), or is the box itself (loopback). Any other client is sent to HTTPS at the address it asked, as before: a device whose DNS is not Warda is never sent to a name it cannot find. The limit of that test: the devices behind another router (or a container on a Docker bridge network) reach the box from one address. If one of them asked the DNS of Warda over the last 24 hours, all of them are sent to the name when they type the address of the box, and one whose DNS is not Warda cannot open it: https://<address> still works for it, and warda https-redirect off is the way out.

What is never sent to the name. What the devices of the network, a health check or the other box of a pair ask the plain HTTP listener: /healthz and /api/v1/stats; the page where a child asks for more time and its files (/ask, /api/v1/ask, /assets/…, /fonts/…, /favicon.svg); the proxy auto-configuration (/wpad.dat, /proxy.pac); the calls between the boxes of a pair (/api/v1/ha/peer…); /dns-query; the well-known paths (/.well-known/…: a certificate authority, the detection of a portal). They are answered over HTTP where the listener serves them, and otherwise sent to HTTPS at the address asked, as before. A site whose name points to the box (a blocked site, the page a system opens to detect a portal) is not the interface: HTTPS at the name asked, as before.

The session. The cookie of the interface is __Host-warda, Secure, HttpOnly, SameSite=Strict, for the host it was given at: an administrator signed in at https://warda or at the address signs in once more at the name: after the first redirection to the name the browser asks to sign in again, once.

The state: in the card of the certificate of Network → DNS services, the line Interface over HTTP — "HTTP redirects to https://…", or "HTTP does not redirect to this name:" and the reason — with its help. The same view is encrypted.http_redirect of GET /api/v1/dns-services. The page shows the line only once a certificate exists (it is a line of its card): before that, warda https-redirect tells the reason.

API (administrators; reading needs the area system, a change its write right): GET /api/v1/https-redirect answers {"enabled", "active", "name", "url", "reason"} (url: https://<name>, with the port when it is not 443; reason only while active is false); PUT /api/v1/https-redirect {"enabled": false} (400 without enabled) turns the redirection to the name off or on and answers the new state. The administration log records https.redirect.off and https.redirect.on. The setting (https_redirect of the database) belongs to this box: it is neither in the backups nor in the configuration given to the secondary of a pair.

The way out, without the interface. An administrator whose browser cannot reach the name (a browser with its own DNS over HTTPS, a device whose DNS is no longer Warda) turns the redirection off on the box: sudo warda https-redirect off (docker exec warda warda https-redirect off with Docker). HTTP then leads to HTTPS at the address typed, as before 0.7.10. warda https-redirect alone tells the state and why ("The interface asked over HTTP is sent to https://…", or "… is sent to HTTPS at the address typed …: the box has no name yet (DNS services page, certificate)."), warda https-redirect on turns it back on. The command goes through the socket of the service (api.sock): it needs Warda running, no password and no network.

High availability. Each box of a pair has its own name and its own certificate, and only the box that holds the shared address redirects to its name: the devices ask their names to that box, which answers its own name and not the one of the other. The other box keeps sending to HTTPS at the address typed (reason standby) until it takes the address. A device that types the shared address is sent to the name of the box that holds it, under the rule of the addresses above.

Docker. The same condition and the same command. Two things to set in a bridged container, as for the name warda and the encrypted DNS: WARDA_ADVERTISE_ADDR (the address of the host: without it the name is answered with an address of the container, which the devices cannot reach), and the HTTPS port published on the same port as WARDA_HTTPS_LISTEN (the redirection carries the port Warda listens on). With the network of the host (packaging/docker-compose.yml) nothing is to set.