@le-space/rootfs 0.6.39 → 0.6.40
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -120,7 +120,15 @@ write_caddyfile() {
|
|
|
120
120
|
https://${hostname} {
|
|
121
121
|
tls {
|
|
122
122
|
issuer acme {
|
|
123
|
-
|
|
123
|
+
# Solve the ACME challenge over TLS-ALPN-01 on :443, NOT HTTP-01.
|
|
124
|
+
# HTTP-01 needs a plaintext listener on :80, but the guest's setup
|
|
125
|
+
# server frees :80 after configuration and Caddy only binds :443, so
|
|
126
|
+
# Let's Encrypt's HTTP-01 probe gets a 503 and no cert is ever issued —
|
|
127
|
+
# browsers then dial wss://.../443 and fail with ERR_SSL_PROTOCOL_ERROR.
|
|
128
|
+
# :443 is already bound and CRN-port-mapped, so TLS-ALPN-01 succeeds
|
|
129
|
+
# (verified live: cert issued in ~45 s). Do NOT flip this back to
|
|
130
|
+
# disable_tlsalpn_challenge — that was b8b8c53 and it broke provisioning.
|
|
131
|
+
disable_http_challenge
|
|
124
132
|
}
|
|
125
133
|
}
|
|
126
134
|
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
2
|
import json
|
|
3
3
|
import os
|
|
4
|
+
import socket
|
|
5
|
+
import ssl
|
|
4
6
|
import time
|
|
5
7
|
import urllib.error
|
|
6
8
|
import urllib.request
|
|
@@ -8,11 +10,39 @@ import urllib.request
|
|
|
8
10
|
|
|
9
11
|
ENV_FILE = os.environ.get("ENV_FILE", "/etc/default/orbitdb-relay")
|
|
10
12
|
METRICS_PORT = int(os.environ.get("METRICS_PORT", "9090"))
|
|
13
|
+
CADDY_HTTPS_PORT = int(os.environ.get("CADDY_HTTPS_PORT", "443"))
|
|
11
14
|
WAIT_TIMEOUT_SECONDS = int(os.environ.get("DESCRIBE_WAIT_TIMEOUT_SECONDS", "240"))
|
|
12
15
|
WAIT_INTERVAL_SECONDS = float(os.environ.get("DESCRIBE_WAIT_INTERVAL_SECONDS", "2"))
|
|
13
16
|
AUTOTLS_EXTRA_WAIT_SECONDS = int(os.environ.get("DESCRIBE_AUTOTLS_EXTRA_WAIT_SECONDS", "120"))
|
|
14
17
|
|
|
15
18
|
|
|
19
|
+
def caddy_cert_serves(hostname: str) -> bool:
|
|
20
|
+
"""True only once Caddy actually serves a publicly-trusted TLS certificate
|
|
21
|
+
for `hostname`.
|
|
22
|
+
|
|
23
|
+
Mode-B failure: describe.py used to advertise the 2n6 proxy-wss address as
|
|
24
|
+
soon as PROXY_HOSTNAME was configured, but Caddy acquires the Let's Encrypt
|
|
25
|
+
certificate asynchronously *after* it (re)starts (the caddy-ready file only
|
|
26
|
+
marks the restart). Browsers dialing before the cert is live got
|
|
27
|
+
net::ERR_SSL_PROTOCOL_ERROR. Verify the real browser-facing certificate with
|
|
28
|
+
a TLS handshake to the local Caddy (127.0.0.1:443) using the public
|
|
29
|
+
hostname as SNI — done locally so hairpin-NAT to the VM's own public IP is
|
|
30
|
+
irrelevant, and validated against the system CA store so Caddy's internal
|
|
31
|
+
self-signed fallback (served before ACME completes) is rejected.
|
|
32
|
+
"""
|
|
33
|
+
if not hostname:
|
|
34
|
+
return False
|
|
35
|
+
context = ssl.create_default_context()
|
|
36
|
+
try:
|
|
37
|
+
with socket.create_connection(("127.0.0.1", CADDY_HTTPS_PORT), timeout=8) as raw:
|
|
38
|
+
with context.wrap_socket(raw, server_hostname=hostname) as tls:
|
|
39
|
+
# A validated peer cert here means the handshake a browser will
|
|
40
|
+
# perform to wss://<hostname>:443 succeeds too.
|
|
41
|
+
return bool(tls.getpeercert())
|
|
42
|
+
except (ssl.SSLError, OSError, ValueError):
|
|
43
|
+
return False
|
|
44
|
+
|
|
45
|
+
|
|
16
46
|
def parse_env_file(path: str) -> dict[str, str]:
|
|
17
47
|
values: dict[str, str] = {}
|
|
18
48
|
if not os.path.exists(path):
|
|
@@ -153,9 +183,28 @@ def main() -> None:
|
|
|
153
183
|
all_multiaddrs = normalize_multiaddrs(multiaddrs_payload)
|
|
154
184
|
grouped = build_grouped_multiaddrs(env_values, all_multiaddrs, peer_id)
|
|
155
185
|
proxy_hostname = env_values.get("PROXY_HOSTNAME", "").strip()
|
|
186
|
+
|
|
187
|
+
# Only treat the 2n6 proxy-wss address as browser-dialable once
|
|
188
|
+
# Caddy actually serves a valid certificate for it. Until then, drop
|
|
189
|
+
# the synthetic (not-yet-serving) proxy address so the relay never
|
|
190
|
+
# advertises an endpoint that would fail a browser's TLS handshake.
|
|
191
|
+
proxy_cert_ready = bool(
|
|
192
|
+
proxy_hostname
|
|
193
|
+
and grouped["proxy_wss_multiaddrs"]
|
|
194
|
+
and caddy_cert_serves(proxy_hostname)
|
|
195
|
+
)
|
|
196
|
+
if grouped["proxy_wss_multiaddrs"] and not proxy_cert_ready:
|
|
197
|
+
proxy_set = set(grouped["proxy_wss_multiaddrs"])
|
|
198
|
+
grouped["browser_bootstrap_multiaddrs"] = [
|
|
199
|
+
addr for addr in grouped["browser_bootstrap_multiaddrs"] if addr not in proxy_set
|
|
200
|
+
]
|
|
201
|
+
|
|
202
|
+
# Break as soon as a genuinely dialable browser address exists:
|
|
203
|
+
# AutoTLS libp2p.direct (only announced once its cert is live) or a
|
|
204
|
+
# cert-verified 2n6 proxy address.
|
|
156
205
|
if grouped["autotls_wss_multiaddrs"]:
|
|
157
206
|
break
|
|
158
|
-
if
|
|
207
|
+
if proxy_cert_ready:
|
|
159
208
|
break
|
|
160
209
|
if not proxy_hostname and time.monotonic() - started_at >= AUTOTLS_EXTRA_WAIT_SECONDS:
|
|
161
210
|
break
|