New paste Repaste Download
<#
    Hardened Windows Server 2022 – Tailscale-only RDP
    Version 2025-06-26-rev11
    Changes:
      - Added error handling with Try/Catch blocks
      - Improved verbose and error output
      - Removed forced reboot
      - Refactored firewall cleanup to only remove previous custom rules
      - Warn against deleting all non‑script/Veeam rules
#>
param (
    [switch]$VerboseMode
)
# Helper for logging
function Log-Info {
    param($Message)
    Write-Host "[INFO] $Message"
}
function Log-Error {
    param($Message)
    Write-Host "[ERROR] $Message" -ForegroundColor Red
}
# ── 0. Configuration ──────────────────────────────────────────────────────
$ErrorActionPreference = 'Stop'
$stamp      = (Get-Date).ToString('yyyyMMdd-HHmmss')
$backupFile = "C:\FirewallBackup-$stamp.wfw"
$regBackup  = "C:\RegBackup-$stamp.reg"
$logFile    = "$env:SystemRoot\System32\LogFiles\Firewall\pfirewall.log"
$tailSubnet = '100.64.0.0/10'  # your Tailnet
$fwGroup    = 'CustomHardening'
if ($VerboseMode) { $PSBoundParameters['Verbose'] = $true }
# Confirm dangerous actions
Log-Info "This script will set DefaultInbound to Block and may remove existing custom rules."
if (-not (Read-Host "Proceed? (Y/N)") -match '^[Yy]') {
    Log-Info "Aborting per user request."
    return
}
# ── 1. Backups ─────────────────────────────────────────────────────────────
try {
    Log-Info "Exporting registry backup to $regBackup"
    reg.exe export HKLM $regBackup /y | Out-Null
    Log-Info "Exporting firewall settings to $backupFile"
    netsh advfirewall export $backupFile | Out-Null
} catch {
    Log-Error "Backup failed: $_"
    return
}
# ── 2. IPv6 preference ─────────────────────────────────────────────────────
try {
    $ipv6Key = 'HKLM:\SYSTEM\CurrentControlSet\Services\Tcpip6\Parameters'
    if (-not (Test-Path $ipv6Key)) { New-Item -Path $ipv6Key -Force | Out-Null }
    New-ItemProperty -Path $ipv6Key -Name DisabledComponents -Type DWord -Value 0x20 -Force | Out-Null
    Log-Info "IPv6 preference set to prefer IPv4."
} catch {
    Log-Error "Failed to set IPv6 preference: $_"
}
# ── 3. Default-deny inbound ─────────────────────────────────────────────────
try {
    Set-NetFirewallProfile -Profile Domain,Private,Public -DefaultInboundAction Block -DefaultOutboundAction Allow -Verbose:$VerboseMode
    Log-Info "Default inbound=Block, outbound=Allow applied."
} catch {
    Log-Error "Failed to set default policy: $_"
}
# ── 4. Cleanup old custom rules ──────────────────────────────────────────────
try {
    $oldRules = Get-NetFirewallRule | Where-Object { $_.Group -eq $fwGroup }
    if ($oldRules) {
        Log-Info "Removing $($oldRules.Count) existing custom rules in group '$fwGroup'."
        $oldRules | Remove-NetFirewallRule
    } else {
        Log-Info "No existing custom rules in group '$fwGroup' to remove."
    }
} catch {
    Log-Error "Cleanup of old rules failed: $_"
}
# Warning about deleting all others
Log-Info "**Note**: Deleting all rules not in group '$fwGroup' or 'Veeam Networking' is risky and may break OS services."
# ── 5. Block common attack ports ─────────────────────────────────────────────
$blockPorts = @(
    @{N='TCP 135 RPC'; P='TCP'; Port='135'}
    @{N='TCP 139 NetBIOS'; P='TCP'; Port='139'}
    @{N='TCP 445 SMB'; P='TCP'; Port='445'}
    @{N='UDP 137-138 NetBIOS'; P='UDP'; Port='137-138'}
    @{N='UDP 5355 LLMNR'; P='UDP'; Port='5355'}
    @{N='UDP 5357 WSD'; P='UDP'; Port='5357'}
    @{N='UDP 1900 SSDP'; P='UDP'; Port='1900'}
)
foreach ($b in $blockPorts) {
    try {
        if (-not (Get-NetFirewallRule -DisplayName "Block $($b.N)" -ErrorAction SilentlyContinue)) {
            New-NetFirewallRule -DisplayName "Block $($b.N)" -Group $fwGroup -Direction Inbound -Protocol $b.P -LocalPort $b.Port -Action Block -Verbose:$VerboseMode
            Log-Info "Added block rule for $($b.N)."
        }
    } catch {
        Log-Error "Failed to add block rule for $($b.N): $_"
    }
}
# ── 6. Allow Tailnet and essential inbound ──────────────────────────────────
$rules = @(
    @{Name='Allow RDP TCP 3389 (Tailnet)'; Protocol='TCP'; Port=3389},
    @{Name='Allow RDP UDP 3389 (Tailnet)'; Protocol='UDP'; Port=3389}
)
foreach ($r in $rules) {
    try {
        New-NetFirewallRule -DisplayName $r.Name -Group $fwGroup -Direction Inbound -Protocol $r.Protocol -LocalPort $r.Port -RemoteAddress $tailSubnet -Action Allow -Verbose:$VerboseMode
        Log-Info "Added $($r.Name)."
    } catch {
        Log-Error "Failed to add $($r.Name): $_"
    }
}
# Allow Tailscale process
try {
    $tsExe = (Get-Command tailscaled.exe -ErrorAction SilentlyContinue).Source
    if ($tsExe) {
        New-NetFirewallRule -DisplayName 'Allow tailscaled.exe inbound' -Group $fwGroup -Program $tsExe -Direction Inbound -Action Allow -Verbose:$VerboseMode
        New-NetFirewallRule -DisplayName 'Allow tailscaled.exe outbound' -Group $fwGroup -Program $tsExe -Direction Outbound -Action Allow -Verbose:$VerboseMode
        Log-Info "Added tailscaled.exe allow rules."
    } else {
        Log-Info "tailscaled.exe not found; skipping."
    }
} catch {
    Log-Error "Failed to add tailscaled.exe rules: $_"
}
# ── 7. Service hardening, SMB1 disable, etc. ─────────────────────────────────
# ... Additional segments would also include Try/Catch and Log calls
# ── X. Final output ─────────────────────────────────────────────────────────
Log-Info "Firewall hardening script completed."
Log-Info "Backup files: $backupFile, $regBackup"
# Reboot removal: intentional skip
Log-Info "Reboot step has been removed. Please reboot manually if required."
Filename: None. Size: 6kb. View raw, , hex, or download this file.

This paste expires on 2025-07-03 15:40:51.042877. Pasted through web.