Symptom: on any machine that had been through a series of installs, one or more older "BNS Local Root CA" certs from earlier builds could accumulate in LocalMachine\Root -- an unconstrained root from before 2026-07, or a rotated one -- and every install added the current constrained root ALONGSIDE the stale ones. Two certs with the same Subject-DN defeat browser chain-builders: Chromium/Edge/Firefox pick one candidate and refuse to try the others, so every .bch site failed with ERR_CERT_AUTHORITY_INVALID / SEC_ERROR_BAD_SIGNATURE in every browser EXCEPT Theseus (which trusts the on-chain tls fingerprint directly, not the machine store). Reproduced on the dev box: two BNS Local Root CAs present (thumbprints EB5DBE98... constrained + 23538FD7... unconstrained), DNS answered correctly, strict Invoke-WebRequest to https://coinspectrum.bch/ failed. Removing the stale one and re-running the chain-build restored HTTPS 200. Fix (install.ps1): - Before Add(imported), enumerate the store and $store.Remove() every "BNS Local Root CA" whose thumbprint differs from the one we're about to trust. Post-condition: exactly one BNS root remains after install. Fix (uninstall.ps1): - Switched from `Get-ChildItem Cert:\LocalMachine\Root` to X509Store direct. The Cert: PSDrive is not always loaded in Inno's [UninstallRun] -NoProfile context, so uninstall could silently leave the CA behind on the store side even while it removed everything else. Verified end-to-end on this box: 0.1.4 upgrade over 0.1.3 finished cleanly, BNS Resolver Daemon Running, 127.0.0.1:53 open, exactly one BNS Local Root CA in the machine store, strict HTTPS to https://coinspectrum.bch/ returned 200 (506,997 bytes) with X509Chain.Build ok=true leaf -> BNS root. Deployed - dl.silentmode.st/AriadneResolver-Setup-0.1.4.exe - s3://bns/silentmode/dl/AriadneResolver-Setup-0.1.4.exe - silentmode.st manifest advertises 0.1.4 - sha256 30ed5e3bb6d6da5325f854c97976410b4fc63067ed52c810a55e9d2e1bdc4e17
69 lines
3.8 KiB
PowerShell
69 lines
3.8 KiB
PowerShell
# Reverses install.ps1 -- run from an ELEVATED PowerShell.
|
|
$ErrorActionPreference = "Stop"
|
|
$stateFile = Join-Path $PSScriptRoot "install-state.json"
|
|
|
|
# install.ps1 adds one rule per activated TLD, each commented "BNS .<tld> resolver".
|
|
# Match them all -- an exact match on ".bch" used to leave every other TLD's rule
|
|
# behind, still pointing at the daemon we are removing.
|
|
Get-DnsClientNrptRule | Where-Object { $_.Comment -like "BNS *resolver" } | ForEach-Object {
|
|
Remove-DnsClientNrptRule -Name $_.Name -Force
|
|
Write-Host "[ok] NRPT rule removed ($($_.Namespace -join ', '))"
|
|
}
|
|
if (Test-Path $stateFile) {
|
|
$state = Get-Content $stateFile | ConvertFrom-Json
|
|
foreach ($a in $state.adapters) {
|
|
# Never "restore" DNS to 127.0.0.1 (the daemon we're removing) -- that leaves the
|
|
# machine with no working resolver. Drop loopback; if nothing real remains, or the
|
|
# install marked this adapter, hand DNS back to DHCP (automatic).
|
|
$servers = @($a.servers | Where-Object { $_ -and $_ -ne '127.0.0.1' -and $_ -ne '::1' })
|
|
if ($a.resetToDhcp -or $servers.Count -eq 0) {
|
|
Set-DnsClientServerAddress -InterfaceAlias $a.alias -ResetServerAddresses -ErrorAction SilentlyContinue
|
|
Write-Host "[ok] adapter '$($a.alias)' DNS reset to automatic (DHCP)"
|
|
} else {
|
|
Set-DnsClientServerAddress -InterfaceAlias $a.alias -ServerAddresses $servers -ErrorAction SilentlyContinue
|
|
Write-Host "[ok] adapter '$($a.alias)' DNS restored to: $($servers -join ', ')"
|
|
}
|
|
}
|
|
Remove-Item $stateFile
|
|
}
|
|
# SAFETY SWEEP -- always, even with a missing/stale state file. No adapter may be
|
|
# left pointing at 127.0.0.1 (or ::1) once the daemon is gone, or the machine loses
|
|
# ALL DNS ("server not responding"). This is the guarantee that a botched or
|
|
# state-less uninstall can never take the user offline.
|
|
foreach ($if in Get-DnsClientServerAddress -AddressFamily IPv4 |
|
|
Where-Object { $_.InterfaceAlias -notmatch 'Loopback' -and ($_.ServerAddresses -contains '127.0.0.1') }) {
|
|
Set-DnsClientServerAddress -InterfaceAlias $if.InterfaceAlias -ResetServerAddresses -ErrorAction SilentlyContinue
|
|
Write-Host "[fix] adapter '$($if.InterfaceAlias)' was still pointed at the resolver -- reset to automatic (DHCP)"
|
|
}
|
|
# Remove the BNS root CA robustly -- by SUBJECT, not only the thumbprint recorded
|
|
# in install-state.json. A missing or stale state file (the daemon was run by
|
|
# hand, or this is an upgrade from an older build) must never leave an orphaned
|
|
# trusted root in the machine store. Use X509Store direct because the Cert:
|
|
# PSDrive is not always loaded in Inno's [UninstallRun] -NoProfile context.
|
|
$removed = 0
|
|
$store = New-Object System.Security.Cryptography.X509Certificates.X509Store('Root','LocalMachine')
|
|
$store.Open('ReadWrite')
|
|
foreach ($c in @($store.Certificates | Where-Object { $_.Subject -match 'BNS Local Root CA' })) {
|
|
$store.Remove($c)
|
|
Write-Host "[ok] BNS Local Root CA removed ($($c.Thumbprint))"
|
|
$removed++
|
|
}
|
|
$store.Close()
|
|
if ($removed -eq 0) { Write-Host "[ok] no BNS root CA left in the machine store" }
|
|
try {
|
|
Remove-Item -Path "HKLM:\SOFTWARE\Policies\Mozilla\Firefox\Certificates" -Recurse -Force -ErrorAction Stop
|
|
Write-Host "[ok] Firefox certificate policies removed (enterprise-roots + install)"
|
|
} catch {}
|
|
try {
|
|
Remove-Item -Path "HKLM:\SOFTWARE\Policies\Mozilla\Firefox\DNSOverHTTPS" -Recurse -Force -ErrorAction Stop
|
|
Write-Host "[ok] Firefox DNS-over-HTTPS policy removed (DoH restored to default)"
|
|
} catch {}
|
|
foreach ($task in "BNS Resolver Daemon", "BNS Sia Bridge") {
|
|
try { Stop-ScheduledTask -TaskName $task -ErrorAction Stop } catch {}
|
|
try {
|
|
Unregister-ScheduledTask -TaskName $task -Confirm:$false -ErrorAction Stop
|
|
Write-Host "[ok] scheduled task '$task' removed"
|
|
} catch {}
|
|
}
|
|
Clear-DnsClientCache
|
|
Write-Host "[done] system DNS configuration restored"
|