Deploying CyberFOX DNS Via Powershell
Master the essentials of deploying CyberFOX DNS Filtering using PowerShell
Table of Contents
Overview
This PowerShell script installs the CyberFOX DNS Filteringing on Windows devices in a silent, unattended manner. It is designed for use with deployment tools such as Microsoft Intune, RMM platforms, Group Policy, or manual administrative execution.
The script: DNS_Deploy.ps1
- Downloads the latest CyberFOX DNS Filtering installer
- Installs it silently using your Company ID
- Verifies the DNS Filtering service is running
- Cleans up temporary installation files
- Returns clear success or failure exit codes for automation tools
# Copyright (c) 2026 CyberFOX LLC
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of the AutoElevate nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL OPENDNS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
<#
.SYNOPSIS
Installs the CyberFOX DNS Filtering (hardened)
.DESCRIPTION
- Validates Company ID
- Downloads dns-latest.exe with retries
- Runs silent install and captures exit code
- Verifies service exists AND is running (with wait/retry)
- Cleans up installer file (non-fatal)
- Writes clear console output + installer log path
.NOTES
Run from an elevated PowerShell session if your environment requires it.
#>
# =========================
# User-configurable values
# =========================
# Set to 1 to enable debug console output
$DebugPrintEnabled = 1
# REQUIRED: Replace with the actual Company ID from the Company, Location, or Roaming Device
$CompanyID = "ENTER COMPANY ID HERE"
# Optional: If you want the script to hard-fail when NOT running as admin, set to $true
$RequireAdmin = $true
# Optional: Seconds to wait for service to reach Running state
$ServiceStartTimeoutSeconds = 60
# Optional: Download retry behavior
$DownloadRetries = 3
$DownloadRetryDelaySeconds = 3
# =========================
# Installation constants
# =========================
$InstallerName = "dns-latest.exe"
$DownloadBase = "https://cdn.passwordboss.com/dns-client"
$DownloadURL = "$DownloadBase/production/$InstallerName"
# Service name to verify
$ServiceName = "CyberFOX DNS over HTTPS Service"
# Log file (installer log) written by the EXE
$LogBaseName = "DNSFilterInstall"
$LogStamp = Get-Date -Format "yyyy-MM-dd_HHmmss"
$LogFileName = "${LogBaseName}_${LogStamp}.log"
$LogFilePath = Join-Path $env:TEMP $LogFileName
# Download path (unique per run to avoid collisions)
$RunId = [guid]::NewGuid().ToString()
$InstallerPath = Join-Path $env:TEMP ("$RunId-$InstallerName")
# Exit codes (RMM/Intune friendly)
$EXIT_SUCCESS = 0
$EXIT_INVALID_INPUT = 10
$EXIT_DOWNLOAD_FAILED = 20
$EXIT_INSTALL_FAILED = 30
$EXIT_VERIFY_FAILED = 40
$EXIT_PREREQ_FAILED = 50
# =========================
# Helper functions
# =========================
function Get-TimeStamp {
return "[{0:MM/dd/yy} {0:HH:mm:ss}]" -f (Get-Date)
}
function Debug-Print([string]$Msg) {
if ($DebugPrintEnabled -eq 1) {
Write-Host "$(Get-TimeStamp) [DEBUG] $Msg"
}
}
function Assert-AdminIfRequired {
if (-not $RequireAdmin) { return }
$isAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()
).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
if (-not $isAdmin) {
Write-Host "$(Get-TimeStamp) ERROR: This script must be run as Administrator."
exit $EXIT_PREREQ_FAILED
}
}
function Validate-Inputs {
Debug-Print "Validating Company ID..."
if ([string]::IsNullOrWhiteSpace($CompanyID) -or $CompanyID -eq "ENTER COMPANY ID HERE") {
Write-Host "$(Get-TimeStamp) ERROR: COMPANY ID not set. Exiting."
exit $EXIT_INVALID_INPUT
}
Write-Host "$(Get-TimeStamp) CompanyID: $CompanyID"
}
function Ensure-Tls12 {
# Helps in older PS/.NET environments where TLS 1.2 isn't default
try {
[Net.ServicePointManager]::SecurityProtocol = `
[Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12
Debug-Print "TLS 1.2 enabled for download."
} catch {
Debug-Print "Unable to set TLS 1.2 (continuing)."
}
}
function Download-Installer {
Debug-Print "Downloading installer from $DownloadURL"
Ensure-Tls12
for ($attempt = 1; $attempt -le $DownloadRetries; $attempt++) {
try {
# Prefer Invoke-WebRequest when available
if (Get-Command Invoke-WebRequest -ErrorAction SilentlyContinue) {
Invoke-WebRequest -Uri $DownloadURL -OutFile $InstallerPath -UseBasicParsing -ErrorAction Stop
} else {
$wc = New-Object System.Net.WebClient
$wc.DownloadFile($DownloadURL, $InstallerPath)
}
if (Test-Path $InstallerPath) {
Debug-Print "Installer downloaded to $InstallerPath"
return
}
} catch {
Write-Host "$(Get-TimeStamp) WARN: Download attempt $attempt failed: $($_.Exception.Message)"
if ($attempt -lt $DownloadRetries) {
Start-Sleep -Seconds $DownloadRetryDelaySeconds
}
}
}
Write-Host "$(Get-TimeStamp) ERROR: Failed to download installer after $DownloadRetries attempts."
exit $EXIT_DOWNLOAD_FAILED
}
function Install-Agent {
Debug-Print "Executing installer..."
# Installer log argument
$LogArgument = "/LOG=`"$LogFilePath`""
# Silent install arguments + Company ID
$Arguments = "/SP- /SUPPRESSMSGBOXES /VERYSILENT /NORESTART /COMPANY_ID=$CompanyID $LogArgument"
Debug-Print "Installer log path: $LogFilePath"
# Capture exit code
$proc = Start-Process -FilePath $InstallerPath -ArgumentList $Arguments -Wait -PassThru -WindowStyle Hidden
# Many installers use 0 = success, sometimes 3010 = success/reboot required (more common for MSI)
$exitCode = $proc.ExitCode
Write-Host "$(Get-TimeStamp) Installer process exit code: $exitCode"
if ($exitCode -ne 0 -and $exitCode -ne 3010) {
Write-Host "$(Get-TimeStamp) ERROR: Installer returned failure exit code: $exitCode"
Write-Host "$(Get-TimeStamp) Installer log (if created): $LogFilePath"
exit $EXIT_INSTALL_FAILED
}
}
function Wait-ForServiceRunning([string]$Name, [int]$TimeoutSeconds) {
$deadline = (Get-Date).AddSeconds($TimeoutSeconds)
while ((Get-Date) -lt $deadline) {
$svc = Get-Service -Name $Name -ErrorAction SilentlyContinue
if ($null -ne $svc) {
if ($svc.Status -eq 'Running') { return $true }
# Try to start if it exists but isn't running
try { Start-Service -Name $Name -ErrorAction SilentlyContinue } catch { }
}
Start-Sleep -Seconds 2
}
return $false
}
function Verify-Installation {
Debug-Print "Verifying installation (service exists and is running)..."
$svc = Get-Service -Name $ServiceName -ErrorAction SilentlyContinue
if ($null -eq $svc) {
Write-Host "$(Get-TimeStamp) ERROR: Expected service not found: '$ServiceName'"
Write-Host "$(Get-TimeStamp) Installer log (if created): $LogFilePath"
exit $EXIT_VERIFY_FAILED
}
$ok = Wait-ForServiceRunning -Name $ServiceName -TimeoutSeconds $ServiceStartTimeoutSeconds
if (-not $ok) {
$svc = Get-Service -Name $ServiceName -ErrorAction SilentlyContinue
$status = if ($svc) { $svc.Status } else { "NotFound" }
Write-Host "$(Get-TimeStamp) ERROR: Service '$ServiceName' did not reach Running state (status: $status)."
Write-Host "$(Get-TimeStamp) Installer log (if created): $LogFilePath"
exit $EXIT_VERIFY_FAILED
}
Write-Host "$(Get-TimeStamp) Service verified running: '$ServiceName'"
}
function Cleanup {
Debug-Print "Cleaning up installer file..."
try {
if (Test-Path $InstallerPath) {
Remove-Item -Path $InstallerPath -Force -ErrorAction Stop
Debug-Print "Removed $InstallerPath"
}
} catch {
# Non-fatal: don't fail an otherwise successful install due to cleanup
Write-Host "$(Get-TimeStamp) WARN: Cleanup failed: $($_.Exception.Message)"
}
}
# =========================
# Main
# =========================
try {
Assert-AdminIfRequired
Validate-Inputs
Download-Installer
Install-Agent
Verify-Installation
Cleanup
Write-Host "$(Get-TimeStamp) CyberFOX DNS Filtering Client successfully installed!"
Write-Host "$(Get-TimeStamp) Installer log path: $LogFilePath"
exit $EXIT_SUCCESS
}
catch {
Write-Host "$(Get-TimeStamp) ERROR: $($_.Exception.Message)"
Write-Host "$(Get-TimeStamp) Installer log (if created): $LogFilePath"
exit 1
}
``
When to Use This Script
Use this script when you want to:
- Deploy CyberFOX DNS Filtering at scale
- Perform automated or zero‑touch installs
- Ensure reliable verification of installation success
- Capture installer logs for troubleshooting
This script is suitable for:
- ✅ Microsoft Intune (Win32 app or script deployment)
- ✅ RMM tools (Ninja, Datto, N‑able, ConnectWise, etc.)
- ✅ Group Policy startup scripts
- ✅ Manual admin execution
Prerequisites
Before running the script, ensure:
- You have a valid CyberFOX Company ID
- The script is executed on a supported Windows device
- Internet access is available to download the installer
- (Optional) The script is run as Administrator, depending on your environment
Required Configuration
1. Set Your Company ID
Open the script and replace the placeholder value:
➡️ This value links the installed agent to the correct CyberFOX Company, Location, or Roaming Device.
What the Script Does (Step‑by‑Step)
1. Validates Input
- Confirms the Company ID is set
- Exits immediately if missing or invalid
2. Downloads the Installer
- Downloads
dns-latest.exefrom the CyberFOX CDN - Uses secure HTTPS with TLS 1.2
- Retries the download automatically if it fails
3. Installs Silently
- Runs the installer with no prompts or reboots
- Passes the Company ID to bind the agent correctly
- Writes a detailed installer log to the Windows temp directory
4. Verifies Installation
- Confirms the CyberFOX DNS over HTTPS Service exists
- Waits for the service to reach a Running state
- Attempts to start the service if necessary
5. Cleans Up
- Deletes the downloaded installer file
- Cleanup failures do not mark the install as failed
Logging
The installer creates a timestamped log file in the system TEMP directory, for example:
DNSFilterInstall.log_2026-02-26_143012.txt
This log is useful for:
- Troubleshooting failed installs
- Support escalations
- RMM or Intune diagnostics
The script prints the log path on both success and failure.
Exit Codes (Automation Friendly)
| Exit Code | Meaning |
|---|---|
0 |
Installation successful |
10 |
Company ID not set or invalid |
20 |
Installer download failed |
30 |
Installer returned an error |
40 |
Service verification failed |
50 |
Admin or prerequisite failure |
✅ These exit codes allow Intune and RMM tools to correctly detect success or failure.
Example: Manual Execution
Run PowerShell as Administrator (recommended), then execute:
Common Questions
Does this script reboot the device?
No. The installer is run with /NORESTART.
Can I run this more than once?
Yes. The script is safe to re‑run and will not harm an existing installation.
Does the script confirm the agent is actually running?
Yes. It verifies the CyberFOX DNS service exists and reaches a running state before reporting success.
Is admin access required?
In most environments, yes. An optional admin check is included and can be enforced if needed.
Troubleshooting Tips
- Ensure the Company ID is correct and not expired
- Check the installer log path printed by the script
- Confirm the device can reach the CyberFOX CDN over HTTPS
- Verify no endpoint protection tool is blocking the installer
Uninstall Using PowerShell
Please use this article for uninstalling using PowerShell
Summary
This PowerShell script provides a reliable, production‑ready way to deploy the CyberFOX DNS Filtering across Windows endpoints. It is safe for automation, includes verification and logging, and integrates cleanly with modern deployment platforms.