dsh-remote 0.4.0: edge auth – slaves log in to an auth proxy in front of the master

- lib/edge-auth.mjs: basic / bearer / oauth2 client_credentials (Authentik M2M) /
  custom headers (Cloudflare Access), proxy session cookie jar, retry with fresh
  token, clear edge-refusal vs DSH-refusal errors
- link + enroll go through the edge; master.edgeAuth stored at pair time,
  secrets as DSH credential refs only; config edgeAuth override
- /dsh-remote/edge-auth: show/change/probe; Settings UI section + pair form
- pair.mjs / install-mac.sh: --edge … flags, secrets prompted via /dev/tty
- tests: fake Authentik-like proxy for all modes + WebSocket through the edge
This commit is contained in:
lyuksovannyy committed 2026-10-11 12:19:36 +00:00
1 parent 5dff41a3d0
commit 78fce8e1ce
12 files changed
+833 -40

No files matched your search

+5 -2
View File
@@ -167,7 +167,7 @@ export function rejectUpgrade(socket, status, message = '') {
}
/** Client connect: resolves a WsConn, rejects with {status, body} on refusal. */
export function connect(url, { headers = {}, timeoutMs = 15000, rejectUnauthorized = true } = {}) {
export function connect(url, { headers = {}, timeoutMs = 15000, rejectUnauthorized = true, onHeaders } = {}) {
return new Promise((resolve, reject) => {
const u = new URL(url)
const secure = u.protocol === 'wss:' || u.protocol === 'https:'
@@ -192,12 +192,15 @@ export function connect(url, { headers = {}, timeoutMs = 15000, rejectUnauthoriz
req.on('timeout', () => { req.destroy(new Error(`connect timeout after ${timeoutMs} ms`)) })
req.on('error', reject)
req.on('response', (res) => {
onHeaders?.(res.headers)
let body = ''
res.setEncoding('utf8')
res.on('data', (d) => { if (body.length < 4096) body += d })
res.on('end', () => {
const err = new Error(`upgrade refused: HTTP ${res.statusCode} ${body.trim()}`)
const loc = res.headers.location ? ` → ${String(res.headers.location).slice(0, 100)}` : ''
const err = new Error(`upgrade refused: HTTP ${res.statusCode}${loc} ${res.headers.location ? '' : body.trim().slice(0, 200)}`.trim())
err.status = res.statusCode
err.location = res.headers.location
err.body = body
reject(err)
})