- Correct WELIST_ALLOW_LEGACY_PING: legacy pings are accepted by default,
the flag only disables them.
- Describe onion delegation: v2-only inclusion, service-side host
normalization, strict expiry check, deployment order and rollback.
- Warn that disabled delegation rejects onion pings when SSL_KEY_PATH is
the dedicated ping key.
- Document certificate lifetime and revocation limits, offline master
key requirements, helper --days bounds, and a delegation verification
checklist.
- Fix the bal-pusher.sh comment about the service-side defaults.
-`BAL_SERVER_URL` must be the public DNS hostname. The pusher normalizes it by
-`BAL_SERVER_URL` must be the public DNS hostname. The pusher normalizes it by
trimming whitespace and trailing slashes before signing.
trimming whitespace and trailing slashes before signing.
-`WELIST_PING_SIG_VERSION=2` activates the canonical JSON signature. Leaving it
-`WELIST_PING_SIG_VERSION=2` activates the canonical JSON signature. Leaving it
unset (or `1`) keeps the legacy v1 scheme, which the service rejects unless
unset (or `1`) keeps the legacy v1 scheme, which the service accepts by
`WELIST_ALLOW_LEGACY_PING=true`.
default (set `WELIST_ALLOW_LEGACY_PING=false` to require v2).
For onion hosts, also configure the delegation certificate (see
For onion hosts, also configure the delegation certificate (see
[Onion URLs](#onion-urls)):
[Onion URLs](#onion-urls)):
@@ -365,6 +367,23 @@ values are persisted.
A response of `"ko"` means the signature was rejected. Check the service logs
A response of `"ko"` means the signature was rejected. Check the service logs
for the specific `PING REJECTED` reason.
for the specific `PING REJECTED` reason.
### Onion delegation
For an onion pusher with delegation configured:
1. At startup, the pusher must not log `disabling onion delegation`.
2. After the next block, look for `Report to welist(...) status=200 body="ok"`
and `PING ADDED` in the service log.
3. Negative check: send a crafted v2 ping with a tampered certificate (change
`key` or `valid_until` after signing) directly to the WeTime service. It must
answer `"ko"` and log `PING REJECTED invalid onion delegation`. Do not run
the pusher with a tampered certificate: it disables delegation locally
instead of sending it.
`bal-welist/scripts/test_v2_ping.py` is a local end-to-end reference: it
generates a throwaway onion identity key, issues a delegation certificate, and
checks the accepted and rejected paths on a throwaway database.
---
---
## 9. Key rotation
## 9. Key rotation
@@ -398,10 +417,10 @@ keys for that host.
| `v2 DNS lookup requires a hostname` | `BAL_SERVER_URL` uses an IP address | Use a DNS hostname |
| `v2 DNS lookup requires a hostname` | `BAL_SERVER_URL` uses an IP address | Use a DNS hostname |
| `invalid v2 signature` | Key mismatch or non-canonical URL | Ensure the TXT key matches `SSL_KEY_PATH` and the URL has no trailing slash |
| `invalid v2 signature` | Key mismatch or non-canonical URL | Ensure the TXT key matches `SSL_KEY_PATH` and the URL has no trailing slash |
| `invalid onion delegation` | Certificate signature does not verify against the onion identity key | Re-issue the certificate with the correct onion key; do not edit `key`/`valid_until` after signing |
| `invalid onion delegation` | Certificate signature does not verify against the onion identity key | Re-issue the certificate with the correct onion key; do not edit `key`/`valid_until` after signing |
| `delegation does not match the ping onion host` | `onion` field differs from `BAL_SERVER_URL` | Re-issue the certificate for the exact host |
| `delegation does not match the ping onion host` | `onion` field differs from `BAL_SERVER_URL` after normalization | Re-issue the certificate for the exact host |
| `delegation expired` | `valid_until` is in the past | Re-issue the certificate and restart the pusher |
| `delegation expired` | `valid_until` is at or before the current time | Re-issue the certificate and restart the pusher |
| `delegation is only supported for onion hosts` | `delegation` sent with a DNS URL | Unset `WELIST_PING_DELEGATION_FILE` for DNS hosts |
| `delegation is only supported for onion hosts` | `delegation` sent with a DNS URL | Unset `WELIST_PING_DELEGATION_FILE` for DNS hosts |
| `legacy ping disabled` | v1 ping sent while the service requires v2 | Set `WELIST_PING_SIG_VERSION=2` (or enable legacy on the service) |
| `legacy ping disabled` | v1 ping sent while the service requires v2 | Set `WELIST_PING_SIG_VERSION=2` (or set `WELIST_ALLOW_LEGACY_PING=true` if it was disabled) |
Useful diagnostics:
Useful diagnostics:
@@ -440,7 +459,7 @@ The request carries:
{
{
"onion":"<address>.onion",
"onion":"<address>.onion",
"key":"<base64 SPKI DER of the delegated Ed25519 key>",
"key":"<base64 SPKI DER of the delegated Ed25519 key>",
"valid_until":1767225600,
"valid_until":1800000000,
"signature":"<base64 Ed25519 signature by the onion identity key>"
"signature":"<base64 Ed25519 signature by the onion identity key>"
Delegation is only sent with v2 pings. With `WELIST_PING_SIG_VERSION=1` (or
unset) the certificate is loaded and validated but never included in the
request.
The pusher sends `delegation` only when `BAL_SERVER_URL` is an `.onion` host. It
The pusher sends `delegation` only when `BAL_SERVER_URL` is an `.onion` host. It
validates the certificate at startup against the onion host, its expiry, and
validates the certificate at startup against the onion host, its expiry, and
`SSL_KEY_PATH`. If the file is missing or malformed, or validation fails,
`SSL_KEY_PATH`. If the file is missing or malformed, or validation fails,
delegation is disabled and the pusher signs with `SSL_KEY_PATH` directly; that
delegation is disabled and the pusher signs with `SSL_KEY_PATH` directly.
works only when `SSL_KEY_PATH` is the onion identity key.
> **Warning — disabled delegation means onion pings fail.** In this setup
> `SSL_KEY_PATH` is the dedicated ping key, so when delegation is disabled the
> service verifies the ping against the onion identity key and rejects every
> request (`invalid v2 signature`). The executor then stops earning WeTime
> points. Watch for the pusher warning `disabling onion delegation` and
> re-issue before `valid_until`.
### Deployment order
1. Upgrade the WeTime service (`bal-welist`) to a version that supports v2
onion delegation.
2. Then set `WELIST_PING_DELEGATION_FILE` on the pusher and restart it.
A pusher that sends delegation to an older service receives `"ko"`: the old
service ignores the `delegation` field and verifies the ping with the onion
identity key. When rolling back the service, unset
`WELIST_PING_DELEGATION_FILE` first.
For local development, the `WELIST_ALLOW_LOCALHOST_PING` and legacy v1 notes
For local development, the `WELIST_ALLOW_LOCALHOST_PING` and legacy v1 notes
above still apply; delegation itself needs no network access.
above still apply; delegation itself needs no network access.
@@ -526,13 +579,32 @@ above still apply; delegation itself needs no network access.
The onion address does not change, and the identity key stays offline. There is
The onion address does not change, and the identity key stays offline. There is
no DNS cache to wait for; the service checks the certificate on every ping.
no DNS cache to wait for; the service checks the certificate on every ping.
Rotation does **not** revoke the previous certificate; see
[Revocation and lifetime](#revocation-and-lifetime).
### Revocation and lifetime
The service has no revocation list. It accepts any certificate that is bound to
the onion host and not expired, so rotating to a new ping key does not stop the
old key from working until the old certificate's `valid_until` passes.
Treat the certificate lifetime as the exposure window:
- Prefer short lifetimes (for example 30–90 days) and re-issue before expiry.
- Keep `--days` well below the helper maximum (3650).
- If a ping key leaks, the only immediate revocation is changing the onion
identity, which also changes the `.onion` address. Otherwise the leaked key
remains usable until the certificate expires.
### Security notes
### Security notes
- Delegation limits the blast radius: a compromised online ping key forges
- Delegation limits the blast radius: a compromised online ping key can publish
pings only until rotation, not the onion service identity.
pings and metadata for that onion host until the certificate expires, but it
- A long `valid_until` increases the impact of a leaked delegated key. Prefer
cannot take over the onion service identity or sign for another host.
one year or less and rotate before expiry.
- The delegated key authorizes the full ping capability for that host, including
the `info`, `base_fee` and `version` metadata.
- The certificate is public data and can be copied freely; only the ping private
key is secret.
- The onion identity key should never be copied to the executor.
- The onion identity key should never be copied to the executor.
### Metadata for onion pings
### Metadata for onion pings
@@ -563,9 +635,14 @@ authenticated and stored.
For onion hosts, replace the TXT/DNSSEC items with:
For onion hosts, replace the TXT/DNSSEC items with:
- [ ] The WeTime service (`bal-welist`) runs a version with onion delegation support.
- [ ] A dedicated `ping_private_key.pem` exists and is `chmod 600`.
- [ ] A dedicated `ping_private_key.pem` exists and is `chmod 600`.
- [ ]`onion-delegation.json` was issued offline by the onion identity key.
- [ ]`onion-delegation.json` was issued offline by the v3 **master** identity
key (not a blinded signing key).
- [ ]`SSL_KEY_PATH` points at the delegated ping key, not the identity key.
- [ ]`SSL_KEY_PATH` points at the delegated ping key, not the identity key.
- [ ]`WELIST_PING_DELEGATION_FILE` points at the certificate.
- [ ]`WELIST_PING_DELEGATION_FILE` points at the certificate.
- [ ]`valid_until` is in the future and rotation is scheduled.
- [ ]`WELIST_PING_SIG_VERSION=2` is set.
- [ ]`valid_until` is strictly in the future, monitored, and rotation is
scheduled before it.
- [ ] The pusher starts without a `disabling onion delegation` warning.
- [ ] Pusher restarted and reports `body="ok"`.
- [ ] Pusher restarted and reports `body="ok"`.
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.