<# Hardened Windows Server 2022 – Tailscale-only RDP Version 2025-06-26-rev10-ascii-verbose #> # ── 0. Variables ──────────────────────────────────────────────────────────── $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' $disableSpooler = $false # keep Spooler for RDP printing $autoReboot = $false # disabled automatic reboot Write-Host "Starting Windows Server 2022 Hardening Script at $(Get-Date)" -ForegroundColor Green Write-Host "Script timestamp: $stamp" -ForegroundColor Cyan # ── 0a. Backups ───────────────────────────────────────────────────────────── Write-Host "`n=== Creating System Backups ===" -ForegroundColor Yellow try { reg.exe export HKLM $regBackup /y | Out-Null if (Test-Path $regBackup) { Write-Host "SUCCESS: Registry backup created at $regBackup" -ForegroundColor Green } else { Write-Host "WARNING: Registry backup may not have been created properly" -ForegroundColor Yellow } } catch { Write-Host "ERROR: Failed to create registry backup - $($_.Exception.Message)" -ForegroundColor Red } try { netsh advfirewall export $backupFile | Out-Null if (Test-Path $backupFile) { Write-Host "SUCCESS: Firewall backup created at $backupFile" -ForegroundColor Green } else { Write-Host "WARNING: Firewall backup may not have been created properly" -ForegroundColor Yellow } } catch { Write-Host "ERROR: Failed to create firewall backup - $($_.Exception.Message)" -ForegroundColor Red } # ── 0b. IPv6 preference (0x20) ────────────────────────────────────────────── Write-Host "`n=== Configuring IPv6 Settings ===" -ForegroundColor Yellow try { $ipv6Reg = 'HKLM:\SYSTEM\CurrentControlSet\Services\Tcpip6\Parameters' if (-not (Test-Path $ipv6Reg)) { New-Item -Path $ipv6Reg -Force | Out-Null Write-Host "Created IPv6 registry path" -ForegroundColor Cyan } New-ItemProperty -Path $ipv6Reg -Name DisabledComponents -Type DWord -Value 0x20 -Force | Out-Null Write-Host "SUCCESS: IPv6 preference configured (DisabledComponents = 0x20)" -ForegroundColor Green } catch { Write-Host "ERROR: Failed to configure IPv6 settings - $($_.Exception.Message)" -ForegroundColor Red } # ── 1. Default-deny inbound ──────────────────────────────────────────────── Write-Host "`n=== Setting Firewall Default Policies ===" -ForegroundColor Yellow try { Set-NetFirewallProfile -Profile Domain,Private,Public -DefaultInboundAction Block -DefaultOutboundAction Allow Write-Host "SUCCESS: Set default inbound action to BLOCK and outbound to ALLOW for all profiles" -ForegroundColor Green } catch { Write-Host "ERROR: Failed to set firewall default policies - $($_.Exception.Message)" -ForegroundColor Red } # ── 2. Remove previous custom rules ───────────────────────────────────────── Write-Host "`n=== Removing Previous Custom Rules ===" -ForegroundColor Yellow try { $existingRules = Get-NetFirewallRule | Where-Object { $_.Group -eq $fwGroup } if ($existingRules) { $ruleCount = ($existingRules | Measure-Object).Count $existingRules | Remove-NetFirewallRule Write-Host "SUCCESS: Removed $ruleCount existing custom hardening rules" -ForegroundColor Green } else { Write-Host "INFO: No existing custom hardening rules found to remove" -ForegroundColor Cyan } } catch { Write-Host "ERROR: Failed to remove existing custom rules - $($_.Exception.Message)" -ForegroundColor Red } # ── 2c. Disable built-in RDP rules ───────────────────────────────────────── Write-Host "`n=== Disabling Built-in RDP Rules ===" -ForegroundColor Yellow try { $rdpRules = Get-NetFirewallRule -DisplayName 'Remote Desktop - User Mode *' if ($rdpRules) { $rdpRules | Disable-NetFirewallRule $rdpCount = ($rdpRules | Measure-Object).Count Write-Host "SUCCESS: Disabled $rdpCount built-in RDP firewall rules" -ForegroundColor Green } else { Write-Host "INFO: No built-in RDP rules found to disable" -ForegroundColor Cyan } } catch { Write-Host "ERROR: Failed to disable built-in RDP rules - $($_.Exception.Message)" -ForegroundColor Red } # ── 3. Inbound BLOCK rules ───────────────────────────────────────────────── Write-Host "`n=== Creating Inbound BLOCK Rules ===" -ForegroundColor Yellow $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' } @{ N='TCP 5985 WinRM' ; P='TCP' ; Port='5985' } @{ N='TCP 5986 WinRM-SSL' ; P='TCP' ; Port='5986' } ) 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 Write-Host "SUCCESS: Created block rule for $($b.N)" -ForegroundColor Green } else { Write-Host "INFO: Block rule for $($b.N) already exists, skipping" -ForegroundColor Cyan } } catch { Write-Host "ERROR: Failed to create block rule for $($b.N) - $($_.Exception.Message)" -ForegroundColor Red } } # ── 4. Allow rules (Tailnet only) ─────────────────────────────────────────── Write-Host "`n=== Creating Tailnet Allow Rules ===" -ForegroundColor Yellow try { New-NetFirewallRule -DisplayName 'Allow RDP TCP 3389 (Tailnet)' -Group $fwGroup -Direction Inbound -Protocol TCP -LocalPort 3389 -RemoteAddress $tailSubnet -Action Allow Write-Host "SUCCESS: Created RDP TCP 3389 allow rule for Tailnet ($tailSubnet)" -ForegroundColor Green # Verify the rule was created with correct remote address $createdRule = Get-NetFirewallRule -DisplayName 'Allow RDP TCP 3389 (Tailnet)' | Get-NetFirewallAddressFilter if ($createdRule.RemoteAddress -eq $tailSubnet) { Write-Host " Verified: Remote address correctly set to $tailSubnet" -ForegroundColor Cyan } else { Write-Host " WARNING: Remote address not set correctly. Current: $($createdRule.RemoteAddress)" -ForegroundColor Yellow } } catch { Write-Host "ERROR: Failed to create RDP TCP allow rule - $($_.Exception.Message)" -ForegroundColor Red } try { New-NetFirewallRule -DisplayName 'Allow RDP UDP 3389 (Tailnet)' -Group $fwGroup -Direction Inbound -Protocol UDP -LocalPort 3389 -RemoteAddress $tailSubnet -Action Allow Write-Host "SUCCESS: Created RDP UDP 3389 allow rule for Tailnet ($tailSubnet)" -ForegroundColor Green # Verify the rule was created with correct remote address $createdRule = Get-NetFirewallRule -DisplayName 'Allow RDP UDP 3389 (Tailnet)' | Get-NetFirewallAddressFilter if ($createdRule.RemoteAddress -eq $tailSubnet) { Write-Host " Verified: Remote address correctly set to $tailSubnet" -ForegroundColor Cyan } else { Write-Host " WARNING: Remote address not set correctly. Current: $($createdRule.RemoteAddress)" -ForegroundColor Yellow } } catch { Write-Host "ERROR: Failed to create RDP UDP allow rule - $($_.Exception.Message)" -ForegroundColor Red } $tsExe = (Get-Command tailscaled.exe -ErrorAction SilentlyContinue).Source if ($tsExe) { Write-Host "Found Tailscale daemon at: $tsExe" -ForegroundColor Cyan try { New-NetFirewallRule -DisplayName 'Allow tailscaled.exe inbound' -Group $fwGroup -Program $tsExe -Direction Inbound -Action Allow Write-Host "SUCCESS: Created inbound allow rule for tailscaled.exe" -ForegroundColor Green } catch { Write-Host "ERROR: Failed to create inbound tailscaled rule - $($_.Exception.Message)" -ForegroundColor Red } if ((Get-NetFirewallProfile -Profile Domain,Private,Public | Where-Object { $_.DefaultOutboundAction -eq 'Block' })) { try { New-NetFirewallRule -DisplayName 'Allow tailscaled.exe outbound' -Group $fwGroup -Program $tsExe -Direction Outbound -Action Allow Write-Host "SUCCESS: Created outbound allow rule for tailscaled.exe" -ForegroundColor Green } catch { Write-Host "ERROR: Failed to create outbound tailscaled rule - $($_.Exception.Message)" -ForegroundColor Red } } else { Write-Host "INFO: Outbound traffic allowed by default, skipping outbound tailscaled rule" -ForegroundColor Cyan } } else { Write-Host "WARNING: Tailscale daemon (tailscaled.exe) not found in PATH" -ForegroundColor Yellow } try { New-NetFirewallRule -DisplayName 'Allow ICMPv4 Echo (Tailnet)' -Group $fwGroup -Direction Inbound -Protocol ICMPv4 -IcmpType 8 -RemoteAddress $tailSubnet -Action Allow Write-Host "SUCCESS: Created ICMPv4 Echo allow rule for Tailnet ($tailSubnet)" -ForegroundColor Green # Verify the rule was created with correct remote address $createdRule = Get-NetFirewallRule -DisplayName 'Allow ICMPv4 Echo (Tailnet)' | Get-NetFirewallAddressFilter if ($createdRule.RemoteAddress -eq $tailSubnet) { Write-Host " Verified: Remote address correctly set to $tailSubnet" -ForegroundColor Cyan } else { Write-Host " WARNING: Remote address not set correctly. Current: $($createdRule.RemoteAddress)" -ForegroundColor Yellow } } catch { Write-Host "ERROR: Failed to create ICMPv4 allow rule - $($_.Exception.Message)" -ForegroundColor Red } # ── 5. Service hardening ──────────────────────────────────────────────────── Write-Host "`n=== Service Hardening ===" -ForegroundColor Yellow $servicesToManual = @( 'LanmanServer','WMPNetworkSvc','XboxNetApiSvc', 'CDPSvc','DsSvc','WSDPrintDevice', 'RemoteRegistry','Fax','TrkWks', 'SNMP','SNMPTRAP' ) if ($disableSpooler) { $servicesToManual += 'Spooler' } foreach ($svc in $servicesToManual) { try { $s = Get-Service -Name $svc -ErrorAction SilentlyContinue if ($s) { $originalStatus = $s.Status $originalStartType = $s.StartType if ($s.Status -ne 'Stopped') { Stop-Service $s -Force Write-Host " Stopped service: $svc (was $originalStatus)" -ForegroundColor Cyan } Set-Service -Name $svc -StartupType Manual Write-Host "SUCCESS: Configured service $svc - StartType: $originalStartType -> Manual" -ForegroundColor Green } else { Write-Host "INFO: Service $svc not found on this system" -ForegroundColor Cyan } } catch { Write-Host "ERROR: Failed to configure service $svc - $($_.Exception.Message)" -ForegroundColor Red } } # ── 5b. Spooler defence (when spooler active) if (-not $disableSpooler) { Write-Host "`n=== Configuring Spooler Security ===" -ForegroundColor Yellow try { $ppReg = 'HKLM:\Software\Policies\Microsoft\Windows NT\Printers\PointAndPrint' if (-not (Test-Path $ppReg)) { New-Item -Path $ppReg -Force | Out-Null Write-Host "Created Point and Print registry path" -ForegroundColor Cyan } New-ItemProperty -Path $ppReg -Name RestrictDriverInstallationToAdministrators -Type DWord -Value 1 -Force | Out-Null New-ItemProperty -Path $ppReg -Name NoWarningNoElevationOnInstall -Type DWord -Value 0 -Force | Out-Null Write-Host "SUCCESS: Configured Point and Print security settings" -ForegroundColor Green $spr = Get-NetFirewallRule -DisplayName 'File and Printer Sharing (Spooler Service - RPC)' -ErrorAction SilentlyContinue if ($spr) { $spr | Set-NetFirewallRule -RemoteAddress LocalSubnet -Profile Any -Enabled True Write-Host "SUCCESS: Updated Spooler Service RPC firewall rule to LocalSubnet only" -ForegroundColor Green } else { Write-Host "INFO: Spooler Service RPC firewall rule not found" -ForegroundColor Cyan } } catch { Write-Host "ERROR: Failed to configure spooler security - $($_.Exception.Message)" -ForegroundColor Red } } # ── 6. Disable NetBIOS over TCP/IP ────────────────────────────────────────── Write-Host "`n=== Disabling NetBIOS over TCP/IP ===" -ForegroundColor Yellow try { $adapters = Get-WmiObject Win32_NetworkAdapterConfiguration -Filter 'IPEnabled=True' $adapterCount = 0 foreach ($adapter in $adapters) { $result = $adapter.SetTcpipNetbios(2) if ($result.ReturnValue -eq 0) { $adapterCount++ } } Write-Host "SUCCESS: Disabled NetBIOS over TCP/IP on $adapterCount network adapters" -ForegroundColor Green } catch { Write-Host "ERROR: Failed to disable NetBIOS over TCP/IP - $($_.Exception.Message)" -ForegroundColor Red } # ── 7. Remove SMB1 ────────────────────────────────────────────────────────── Write-Host "`n=== Removing SMB1 Protocol ===" -ForegroundColor Yellow try { $smb1Features = @('SMB1Protocol','SMB1Protocol-Client','SMB1Protocol-Server') foreach ($feature in $smb1Features) { try { $result = Disable-WindowsOptionalFeature -Online -FeatureName $feature -NoRestart -ErrorAction SilentlyContinue if ($result) { Write-Host "SUCCESS: Disabled Windows feature: $feature" -ForegroundColor Green } else { Write-Host "INFO: Feature $feature was already disabled or not found" -ForegroundColor Cyan } } catch { Write-Host "WARNING: Could not disable feature $feature - $($_.Exception.Message)" -ForegroundColor Yellow } } } catch { Write-Host "ERROR: Failed to remove SMB1 protocol - $($_.Exception.Message)" -ForegroundColor Red } # ── 8. Disable WSD / SSDP / UPnP services ────────────────────────────────── Write-Host "`n=== Disabling WSD/SSDP/UPnP Services ===" -ForegroundColor Yellow $servicesToDisable = @('SSDPSRV','upnphost','WSDSvc','WSDPrintDevice') foreach ($serviceName in $servicesToDisable) { try { $reg = "HKLM:\SYSTEM\CurrentControlSet\Services\$serviceName" if (Test-Path $reg) { Set-ItemProperty $reg -Name Start -Value 4 -Force Write-Host "SUCCESS: Disabled service $serviceName (Start = 4)" -ForegroundColor Green } else { Write-Host "INFO: Service registry key for $serviceName not found" -ForegroundColor Cyan } } catch { Write-Host "ERROR: Failed to disable service $serviceName - $($_.Exception.Message)" -ForegroundColor Red } } # ── 9. RDP channel hardening ─────────────────────────────────────────────── Write-Host "`n=== Hardening RDP Channel Security ===" -ForegroundColor Yellow try { $rdpReg = 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp' Set-ItemProperty $rdpReg -Name SecurityLayer -Value 2 Set-ItemProperty $rdpReg -Name fAllowSecProtocolNegotiation -Value 1 Set-ItemProperty $rdpReg -Name UserAuthentication -Value 1 Set-ItemProperty $rdpReg -Name MinEncryptionLevel -Value 3 Write-Host "SUCCESS: Configured RDP security settings:" -ForegroundColor Green Write-Host " SecurityLayer = 2 (TLS)" -ForegroundColor Cyan Write-Host " fAllowSecProtocolNegotiation = 1 (Enabled)" -ForegroundColor Cyan Write-Host " UserAuthentication = 1 (NLA Required)" -ForegroundColor Cyan Write-Host " MinEncryptionLevel = 3 (High)" -ForegroundColor Cyan } catch { Write-Host "ERROR: Failed to configure RDP security settings - $($_.Exception.Message)" -ForegroundColor Red } # ──10. Schannel: disable TLS 1.0/1.1 & weak ciphers ──────────────────────── Write-Host "`n=== Disabling Weak TLS Protocols ===" -ForegroundColor Yellow foreach ($proto in 'TLS 1.0','TLS 1.1') { foreach ($side in 'Client','Server') { try { $path = "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\$proto\$side" if (-not (Test-Path $path)) { New-Item -Path $path -Force | Out-Null Write-Host "Created registry path: $path" -ForegroundColor Cyan } New-ItemProperty -Path $path -Name Enabled -Type DWord -Value 0 -Force | Out-Null New-ItemProperty -Path $path -Name DisabledByDefault -Type DWord -Value 1 -Force | Out-Null Write-Host "SUCCESS: Disabled $proto for $side" -ForegroundColor Green } catch { Write-Host "ERROR: Failed to disable $proto for $side - $($_.Exception.Message)" -ForegroundColor Red } } } Write-Host "`n=== Disabling Weak Cipher Suites ===" -ForegroundColor Yellow if (Get-Command Disable-TlsCipherSuite -ErrorAction SilentlyContinue) { try { $weakCiphers = (Get-TlsCipherSuite | Where-Object { $_.Name -match 'RC4|3DES|SHA$' }) $disabledCount = 0 foreach ($cipher in $weakCiphers) { try { Disable-TlsCipherSuite -Name $cipher.Name -ErrorAction SilentlyContinue $disabledCount++ Write-Host " Disabled cipher suite: $($cipher.Name)" -ForegroundColor Cyan } catch { Write-Host " WARNING: Could not disable cipher suite: $($cipher.Name)" -ForegroundColor Yellow } } Write-Host "SUCCESS: Disabled $disabledCount weak cipher suites" -ForegroundColor Green } catch { Write-Host "ERROR: Failed to disable cipher suites - $($_.Exception.Message)" -ForegroundColor Red } } else { Write-Host "INFO: Disable-TlsCipherSuite cmdlet not available, using registry method" -ForegroundColor Cyan try { $cBase = 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Ciphers' $weakCiphers = @('RC4 128/128','RC4 64/128','RC4 56/128','RC4 40/128','3DES 168/168') foreach ($c in $weakCiphers) { $cPath = "$cBase\$c" if (-not (Test-Path $cPath)) { New-Item -Path $cPath -Force | Out-Null Write-Host "Created cipher registry path: $cPath" -ForegroundColor Cyan } New-ItemProperty -Path $cPath -Name Enabled -Type DWord -Value 0 -Force | Out-Null Write-Host "SUCCESS: Disabled cipher: $c" -ForegroundColor Green } } catch { Write-Host "ERROR: Failed to disable weak ciphers via registry - $($_.Exception.Message)" -ForegroundColor Red } } # ──11. Remote Credential Guard ───────────────────────────────────────────── Write-Host "`n=== Configuring Remote Credential Guard ===" -ForegroundColor Yellow try { $credReg = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\CredentialsDelegation' if (-not (Test-Path $credReg)) { New-Item -Path $credReg -Force | Out-Null Write-Host "Created Credential Delegation registry path" -ForegroundColor Cyan } Set-ItemProperty $credReg -Name AllowProtectedCreds -Type DWord -Value 1 Set-ItemProperty $credReg -Name EnableProtection -Type DWord -Value 1 Write-Host "SUCCESS: Enabled Remote Credential Guard protection" -ForegroundColor Green } catch { Write-Host "ERROR: Failed to configure Remote Credential Guard - $($_.Exception.Message)" -ForegroundColor Red } # ──12. Firewall logging (16 MB) + weekly rotation ────────────────────────── Write-Host "`n=== Configuring Firewall Logging ===" -ForegroundColor Yellow try { Set-NetFirewallProfile -Profile Domain,Private,Public -LogBlocked True -LogAllowed True -LogFileName $logFile -LogMaxSizeKilobytes 16384 Write-Host "SUCCESS: Enabled firewall logging (16MB max, blocked and allowed traffic)" -ForegroundColor Green Write-Host " Log file location: $logFile" -ForegroundColor Cyan } catch { Write-Host "ERROR: Failed to configure firewall logging - $($_.Exception.Message)" -ForegroundColor Red } Write-Host "`n=== Creating Log Rotation Task ===" -ForegroundColor Yellow try { $taskName = 'Rotate-Firewall-Log' if (-not (Get-ScheduledTask -TaskName $taskName -ErrorAction SilentlyContinue)) { $psCmd = '& { Set-NetFirewallProfile -LogAllowed 0 -LogBlocked 0; ' + '$ts=(Get-Date).ToString("yyyyMMdd-HHmmss"); ' + "Rename-Item ''$logFile'' (" + '$ts' + " + ''.pfirewall.log''); " + "New-Item ''$logFile'' -ItemType File -Force | Out-Null; " + 'Set-NetFirewallProfile -LogAllowed 1 -LogBlocked 1 }' $action = New-ScheduledTaskAction -Execute 'powershell.exe' -Argument "-NoProfile -ExecutionPolicy Bypass -Command $psCmd" $trigger = New-ScheduledTaskTrigger -Weekly -DaysOfWeek Sunday -At 03:00 Register-ScheduledTask -TaskName $taskName -Action $action -Trigger $trigger -RunLevel Highest -User.SYSTEM Write-Host "SUCCESS: Created weekly log rotation scheduled task '$taskName'" -ForegroundColor Green } else { Write-Host "INFO: Log rotation task '$taskName' already exists" -ForegroundColor Cyan } } catch { Write-Host "ERROR: Failed to create log rotation task - $($_.Exception.Message)" -ForegroundColor Red } # ──13. Account-lockout policy ────────────────────────────────────────────── Write-Host "`n=== Configuring Account Lockout Policy ===" -ForegroundColor Yellow try { $result = & net.exe accounts /lockoutthreshold:10 /lockoutduration:15 /lockoutwindow:15 2>&1 if ($LASTEXITCODE -eq 0) { Write-Host "SUCCESS: Configured account lockout policy:" -ForegroundColor Green Write-Host " Lockout threshold: 10 attempts" -ForegroundColor Cyan Write-Host " Lockout duration: 15 minutes" -ForegroundColor Cyan Write-Host " Lockout window: 15 minutes" -ForegroundColor Cyan } else { Write-Host "WARNING: Account lockout policy command completed with exit code $LASTEXITCODE" -ForegroundColor Yellow } } catch { Write-Host "ERROR: Failed to configure account lockout policy - $($_.Exception.Message)" -ForegroundColor Red } # ──14. Disable Remote Assistance rules ───────────────────────────────────── Write-Host "`n=== Disabling Remote Assistance Rules ===" -ForegroundColor Yellow try { $raRules = Get-NetFirewallRule | Where-Object { $_.DisplayName -like '*Remote Assistance*' } if ($raRules) { $raRules | Disable-NetFirewallRule $raCount = ($raRules | Measure-Object).Count Write-Host "SUCCESS: Disabled $raCount Remote Assistance firewall rules" -ForegroundColor Green } else { Write-Host "INFO: No Remote Assistance firewall rules found" -ForegroundColor Cyan } } catch { Write-Host "ERROR: Failed to disable Remote Assistance rules - $($_.Exception.Message)" -ForegroundColor Red } # ──14b. Remove/Disable unwanted Built-in Rules ───────────────────────────── # 1) Disable entire rule-groups $groups = @( # Discovery / Multicast "mDNS", "Netzwerkerkennung", # contains LLMNR, SSDP, UPnP, WSD rules "DIAL-Protokollserver", "Cast to Device functionality", # original English group "Wiedergabe auf Gerät", # German group for Play-To # File & Print "Datei- und Druckerfreigabe", # Remote-Management "Windows-Remoteverwaltung", # Updates / Delivery "Übermittlungsoptimierung", # Media-Streaming "Microsoft Media Foundation-Netzwerkquelle", # IoT / Miracast "AllJoyn Router", # Server Features, if unnecessary "Dateiserver-Remoteverwaltung", "Dynamic Host Configuration-Protokoll" # only disable if static IP ) foreach ($g in $groups) { try { Get-NetFirewallRule -DisplayGroup $g -ErrorAction SilentlyContinue | Disable-NetFirewallRule -ErrorAction Stop Write-Host "SUCCESS: Disabled group '$g'" -ForegroundColor Green } catch { Write-Host "WARNING: Group '$g' not found or could not be disabled" -ForegroundColor Yellow } } # 2) Disable individual rules (no group tag) $ruleNames = @( # Core-Networking special paths "Kernnetzwerk - IP-HTTPS (TCP eingehend)", # DirectAccess / IP-HTTPS "Kernnetzwerk - Teredo (UDP eingehend)" # Teredo tunneling ) foreach ($n in $ruleNames) { try { Get-NetFirewallRule -DisplayName $n -ErrorAction SilentlyContinue | Disable-NetFirewallRule -ErrorAction Stop Write-Host "SUCCESS: Disabled rule '$n'" -ForegroundColor Green } catch { Write-Host "WARNING: Rule '$n' not found or could not be disabled" -ForegroundColor Yellow } } # ──14c. Catch-all for remaining Play-To rules by DisplayName ─────────────── Write-Host "`n=== Disabling remaining 'Wiedergabe auf Gerät' rules by DisplayName pattern ===" -ForegroundColor Yellow try { $playTo = Get-NetFirewallRule -DisplayName '*Wiedergabe auf Gerät*' -ErrorAction SilentlyContinue if ($playTo) { $playTo | Disable-NetFirewallRule -ErrorAction Stop $count = ($playTo | Measure-Object).Count Write-Host "SUCCESS: Disabled $count rules matching '*Wiedergabe auf Gerät*'" -ForegroundColor Green } else { Write-Host "INFO: No more rules matching '*Wiedergabe auf Gerät*' found" -ForegroundColor Cyan } } catch { Write-Host "WARNING: Error disabling '*Wiedergabe auf Gerät*' rules – $($_.Exception.Message)" -ForegroundColor Yellow } # ──15. Finish ────────────────────────────────────────────────────────────── Write-Host "`n" + "="*60 -ForegroundColor Yellow Write-Host "HARDENING SCRIPT COMPLETED SUCCESSFULLY" -ForegroundColor Green Write-Host "="*60 -ForegroundColor Yellow Write-Host "Completion time: $(Get-Date)" -ForegroundColor Cyan Write-Host "Registry backup: $regBackup" -ForegroundColor Cyan Write-Host "Firewall backup: $backupFile" -ForegroundColor Cyan Write-Host "`nIMPORTANT: A system reboot is recommended to ensure all changes take effect." -ForegroundColor Yellow Write-Host "Automatic reboot is DISABLED. Please reboot manually when convenient." -ForegroundColor Yellow Write-Host "="*60 -ForegroundColor Yellow