Windows DNS Name Server (NS) Record Management: Analysis & Reverse Lookup Zone Updates

Analyzing and Updating Name Server (NS) Records on Windows DNS Servers

Managing Windows DNS is crucial for ensuring that network infrastructures remain up-to-date and function correctly. The accuracy and timeliness of Name Server (NS) records are essential elements that must be frequently monitored. In this article, we will discuss how a script operates to analyze and update Name Server records on Windows DNS servers.

How Does the Script Work?

The developed script runs on Windows DNS servers and performs the following key operations:

  1. Scanning All Name Server Records:
    • When the “Analyze” button is pressed, the script scans all Forward Lookup Zone and Reverse Lookup Zone areas and lists the current Name Server (NS) records.
  2. Forward Lookup Zone and Reverse Lookup Zone Scanning:
    • It collects the existing Name Server records for the Forward Lookup Zone and Reverse Lookup Zone but does not make any modifications.
  3. Updating Reverse Lookup Zone:
    • When the “Update NS” button is pressed, the NS records in the Reverse Lookup Zone are checked.
    • Missing NS records are added.
    • Old and unused NS records are removed.
  4. Listing Old Name Server Records:
    • No updates are made for the Forward Lookup Zone, but outdated and unused NS records are displayed for the system administrator’s review.

Name Server Checker & Reverse Lookup Zone Update

# DNS Active NS Record Manager GUI Application

Add-Type -AssemblyName System.Windows.Forms

Add-Type -AssemblyName System.Drawing

# Create the main form

$form = New-Object System.Windows.Forms.Form

$form.Text = 'DNS Active NS Record Manager'

$form.Size = New-Object System.Drawing.Size(900,700)

$form.StartPosition = 'CenterScreen'

$form.FormBorderStyle = 'FixedDialog'

$form.MaximizeBox = $false

$form.BackColor = [System.Drawing.Color]::FromArgb(240,240,240)

# Create banner panel

$bannerPanel = New-Object System.Windows.Forms.Panel

$bannerPanel.Size = New-Object System.Drawing.Size(900,60)

$bannerPanel.Location = New-Object System.Drawing.Point(0,0)

$bannerPanel.BackColor = [System.Drawing.Color]::FromArgb(0,120,215)

$form.Controls.Add($bannerPanel)

# Create banner title

$bannerTitle = New-Object System.Windows.Forms.Label

$bannerTitle.Text = "DNS Active NS Record Management"

$bannerTitle.ForeColor = [System.Drawing.Color]::White

$bannerTitle.Font = New-Object System.Drawing.Font("Segoe UI", 16, [System.Drawing.FontStyle]::Regular)

$bannerTitle.AutoSize = $true

$bannerTitle.Location = New-Object System.Drawing.Point(20,15)

$bannerPanel.Controls.Add($bannerTitle)

# Create main panel for controls

$mainPanel = New-Object System.Windows.Forms.Panel

$mainPanel.Size = New-Object System.Drawing.Size(860,580)

$mainPanel.Location = New-Object System.Drawing.Point(20,80)

$mainPanel.BackColor = [System.Drawing.Color]::White

$form.Controls.Add($mainPanel)

# Create DNS Server label and textbox

$lblDNSServer = New-Object System.Windows.Forms.Label

$lblDNSServer.Location = New-Object System.Drawing.Point(20,20)

$lblDNSServer.Size = New-Object System.Drawing.Size(100,20)

$lblDNSServer.Text = 'DNS Server:'

$lblDNSServer.Font = New-Object System.Drawing.Font("Segoe UI", 9)

$mainPanel.Controls.Add($lblDNSServer)

$txtDNSServer = New-Object System.Windows.Forms.TextBox

$txtDNSServer.Location = New-Object System.Drawing.Point(120,20)

$txtDNSServer.Size = New-Object System.Drawing.Size(200,20)

$txtDNSServer.Text = 'localhost'

$txtDNSServer.Font = New-Object System.Drawing.Font("Segoe UI", 9)

$mainPanel.Controls.Add($txtDNSServer)

# Create Active NS Servers ListView

$lblActiveNS = New-Object System.Windows.Forms.Label

$lblActiveNS.Location = New-Object System.Drawing.Point(20,60)

$lblActiveNS.Size = New-Object System.Drawing.Size(150,20)

$lblActiveNS.Text = 'Active NS Servers:'

$lblActiveNS.Font = New-Object System.Drawing.Font("Segoe UI", 9)

$mainPanel.Controls.Add($lblActiveNS)

$listActiveNS = New-Object System.Windows.Forms.ListView

$listActiveNS.Location = New-Object System.Drawing.Point(20,85)

$listActiveNS.Size = New-Object System.Drawing.Size(400,150)

$listActiveNS.View = [System.Windows.Forms.View]::Details

$listActiveNS.FullRowSelect = $true

$listActiveNS.GridLines = $true

$listActiveNS.Font = New-Object System.Drawing.Font("Segoe UI", 9)

$listActiveNS.Columns.Add("NS Server", 380)

$mainPanel.Controls.Add($listActiveNS)

# Create button panel

$buttonPanel = New-Object System.Windows.Forms.Panel

$buttonPanel.Size = New-Object System.Drawing.Size(420,30)

$buttonPanel.Location = New-Object System.Drawing.Point(440,85)

$buttonPanel.BackColor = [System.Drawing.Color]::White

$mainPanel.Controls.Add($buttonPanel)

# Create Refresh button

$btnRefresh = New-Object System.Windows.Forms.Button

$btnRefresh.Location = New-Object System.Drawing.Point(0,0)

$btnRefresh.Size = New-Object System.Drawing.Size(100,30)

$btnRefresh.Text = 'Refresh'

$btnRefresh.FlatStyle = 'Flat'

$btnRefresh.BackColor = [System.Drawing.Color]::FromArgb(0,120,215)

$btnRefresh.ForeColor = [System.Drawing.Color]::White

$btnRefresh.Font = New-Object System.Drawing.Font("Segoe UI", 9)

$btnRefresh.Cursor = [System.Windows.Forms.Cursors]::Hand

$buttonPanel.Controls.Add($btnRefresh)

# Create Analyze button

$btnAnalyze = New-Object System.Windows.Forms.Button

$btnAnalyze.Location = New-Object System.Drawing.Point(105,0)

$btnAnalyze.Size = New-Object System.Drawing.Size(100,30)

$btnAnalyze.Text = 'Analyze'

$btnAnalyze.FlatStyle = 'Flat'

$btnAnalyze.BackColor = [System.Drawing.Color]::FromArgb(0,120,215)

$btnAnalyze.ForeColor = [System.Drawing.Color]::White

$btnAnalyze.Font = New-Object System.Drawing.Font("Segoe UI", 9)

$btnAnalyze.Cursor = [System.Windows.Forms.Cursors]::Hand

$buttonPanel.Controls.Add($btnAnalyze)

# Create Clean button

$btnClean = New-Object System.Windows.Forms.Button

$btnClean.Location = New-Object System.Drawing.Point(210,0)

$btnClean.Size = New-Object System.Drawing.Size(100,30)

$btnClean.Text = 'Update NS'

$btnClean.FlatStyle = 'Flat'

$btnClean.BackColor = [System.Drawing.Color]::FromArgb(0,120,215)

$btnClean.ForeColor = [System.Drawing.Color]::White

$btnClean.Font = New-Object System.Drawing.Font("Segoe UI", 9)

$btnClean.Enabled = $false

$btnClean.Cursor = [System.Windows.Forms.Cursors]::Hand

$buttonPanel.Controls.Add($btnClean)

# Create Exit button

$btnExit = New-Object System.Windows.Forms.Button

$btnExit.Location = New-Object System.Drawing.Point(315,0)

$btnExit.Size = New-Object System.Drawing.Size(100,30)

$btnExit.Text = 'Exit'

$btnExit.FlatStyle = 'Flat'

$btnExit.BackColor = [System.Drawing.Color]::FromArgb(232,17,35)

$btnExit.ForeColor = [System.Drawing.Color]::White

$btnExit.Font = New-Object System.Drawing.Font("Segoe UI", 9)

$btnExit.Cursor = [System.Windows.Forms.Cursors]::Hand

$buttonPanel.Controls.Add($btnExit)

# Create RichTextBox for output

$txtOutput = New-Object System.Windows.Forms.RichTextBox

$txtOutput.Location = New-Object System.Drawing.Point(20,250)

$txtOutput.Size = New-Object System.Drawing.Size(820,310)

$txtOutput.ReadOnly = $true

$txtOutput.BackColor = [System.Drawing.Color]::FromArgb(30,30,30)

$txtOutput.ForeColor = [System.Drawing.Color]::White

$txtOutput.Font = New-Object System.Drawing.Font("Consolas", 10)

$txtOutput.BorderStyle = 'None'

$mainPanel.Controls.Add($txtOutput)

# Function to write colored output

function Write-ColorOutput {

    param([string]$Message, [string]$Color = "White")

    $txtOutput.SelectionColor = [System.Drawing.Color]::$Color

    $txtOutput.AppendText("$Message`n")

    $txtOutput.ScrollToCaret()

}

# Function to write separator line

function Write-Separator {

    Write-ColorOutput ("-" * 80) "DarkGray"

}

# Function to test if a server is online with simple checks

function Test-ServerConnection {

    param([string]$ServerName)

    try {

        Write-ColorOutput "Testing NS server: $ServerName" "Yellow"

        

        # Try to get IP address

        try {

            $ipAddress = [System.Net.Dns]::GetHostAddresses($ServerName) |

                        Where-Object { $_.AddressFamily -eq 'InterNetwork' } |

                        Select-Object -First 1

            

            if ($ipAddress) {

                Write-ColorOutput "  - IP Address: $($ipAddress.IPAddressToString)" "Gray"

            } else {

                Write-ColorOutput "  - Could not resolve IP address" "Red"

                return $false

            }

        } catch {

            Write-ColorOutput "  - DNS resolution failed" "Red"

            return $false

        }

        

        # Try ping

        $ping = Test-Connection -ComputerName $ServerName -Count 2 -Quiet

        if ($ping) {

            Write-ColorOutput "  - Ping successful" "Green"

            

            # Try basic DNS port check

            try {

                $tcp = New-Object System.Net.Sockets.TcpClient

                $tcp.SendTimeout = 2000

                $tcp.ReceiveTimeout = 2000

                $result = $tcp.BeginConnect($ServerName, 53, $null, $null)

                $success = $result.AsyncWaitHandle.WaitOne(2000, $false)

                if ($success) {

                    Write-ColorOutput "  - DNS port is accessible" "Green"

                    $tcp.EndConnect($result)

                    return $true

                } else {

                    Write-ColorOutput "  - DNS port is not accessible" "Red"

                    return $false

                }

            } catch {

                Write-ColorOutput "  - DNS port check failed" "Red"

                return $false

            } finally {

                if ($tcp) { $tcp.Close() }

            }

        } else {

            Write-ColorOutput "  - Ping failed" "Red"

            return $false

        }

    } catch {

        Write-ColorOutput "  - Connection test failed: $_" "Red"

        return $false

    }

}

# Function to validate NS server with simple logic

function Test-NSServerValidity {

    param([string]$NSServer)

    return Test-ServerConnection -ServerName $NSServer

}

# Function to get active NS records

function Get-ActiveNSRecords {

    $listActiveNS.Items.Clear()

    Write-ColorOutput "Loading active NS records..." "Yellow"

    Write-Separator

    

    try {

        # Get all zones (both forward and reverse)

        $allZones = Get-DnsServerZone -ComputerName $txtDNSServer.Text |

                   Where-Object { $_.ZoneName -ne "TrustAnchors" }

        

        $script:activeNSServers = @()

        $script:inactiveNSServers = @{}  # Track inactive NS servers and their source zones

        $potentialNSServers = @{}

        

        foreach ($zone in $allZones) {

            Write-ColorOutput "Checking zone: $($zone.ZoneName)" "Cyan"

            

            # Get NS records for each zone

            $nsRecords = Get-DnsServerResourceRecord -ZoneName $zone.ZoneName -RRType "NS" -ComputerName $txtDNSServer.Text |

                        Where-Object { $_.RecordType -eq "NS" }

            

            foreach ($ns in $nsRecords) {

                $nsHost = $ns.RecordData.NameServer.Trim('.')

                if (-not $potentialNSServers.ContainsKey($nsHost)) {

                    $potentialNSServers[$nsHost] = $zone.ZoneName

                }

            }

        }

        

        Write-ColorOutput "`nValidating NS servers..." "Yellow"

        Write-Separator

        

        foreach ($nsServer in $potentialNSServers.Keys) {

            Write-ColorOutput "Processing NS server from zone '$($potentialNSServers[$nsServer])'" "Cyan"

            

            if (Test-NSServerValidity -NSServer $nsServer) {

                if (-not $script:activeNSServers.Contains($nsServer)) {

                    $script:activeNSServers += $nsServer

                    $listActiveNS.Items.Add($nsServer)

                    Write-ColorOutput "Confirmed active NS: $nsServer" "Green"

                }

            } else {

                Write-ColorOutput "NS server validation failed: $nsServer" "Red"

                if (-not $script:inactiveNSServers.ContainsKey($nsServer)) {

                    $script:inactiveNSServers[$nsServer] = $potentialNSServers[$nsServer]

                }

            }

            Write-Separator

        }

        

        Write-ColorOutput "`nTotal active NS servers found: $($script:activeNSServers.Count)" "Cyan"

        Write-ColorOutput "Active NS Servers:" "Yellow"

        foreach ($ns in $script:activeNSServers) {

            Write-ColorOutput "  $ns" "White"

        }

        Write-Separator

        

    } catch {

        Write-ColorOutput "Error getting active NS records: $_" "Red"

        Write-Separator

    }

}

# Function to analyze DNS zones

function Analyze-ReverseLookupZones {

    Write-ColorOutput "Starting DNS zone analysis..." "Yellow"

    Write-Separator

    

    try {

        # Get all zones for information

        $allZones = Get-DnsServerZone -ComputerName $txtDNSServer.Text |

                   Where-Object { $_.ZoneName -ne "TrustAnchors" }

        

        # Get only reverse lookup zones for updates

        $reverseLookupZones = $allZones | Where-Object { $_.ZoneName -like "*.in-addr.arpa" }

        

        $script:inactiveNSCount = 0

        $script:analyzedZones = @{}  # Will only contain reverse lookup zones

        $script:zonesToUpdate = @{}  # Will only contain reverse lookup zones

        

        # First, show inactive NS servers from all zones (informational)

        Write-ColorOutput "`nInactive NS Servers in All Zones (Informational):" "Yellow"

        Write-Separator

        foreach ($inactiveNS in $script:inactiveNSServers.Keys) {

            Write-ColorOutput "Found inactive NS server: $inactiveNS" "Red"

            Write-ColorOutput "Originally detected in zone: $($script:inactiveNSServers[$inactiveNS])" "Yellow"

            Write-Separator

        }

        

        # Process all zones for information

        Write-ColorOutput "`nAnalyzing All Zones (Informational):" "Yellow"

        Write-Separator

        foreach ($zone in $allZones) {

            if ($zone.ZoneName -notlike "*.in-addr.arpa") {

                Write-ColorOutput "Checking zone: $($zone.ZoneName)" "Cyan"

                

                $nsRecords = Get-DnsServerResourceRecord -ZoneName $zone.ZoneName -RRType "NS" -ComputerName $txtDNSServer.Text |

                            Where-Object { $_.RecordType -eq "NS" }

                

                foreach ($ns in $nsRecords) {

                    $nsHost = $ns.RecordData.NameServer.Trim('.')

                    if ($script:inactiveNSServers.ContainsKey($nsHost)) {

                        Write-ColorOutput "  - Inactive NS found: $nsHost" "Red"

                    } else {

                        Write-ColorOutput "  - Active NS found: $nsHost" "Green"

                    }

                }

                Write-Separator

            }

        }

        

        # Process reverse lookup zones for updates

        Write-ColorOutput "`nAnalyzing Reverse Lookup Zones (Will Be Updated):" "Yellow"

        Write-Separator

        foreach ($zone in $reverseLookupZones) {

            Write-ColorOutput "Analyzing zone: $($zone.ZoneName)" "Cyan"

            

            $nsRecords = Get-DnsServerResourceRecord -ZoneName $zone.ZoneName -RRType "NS" -ComputerName $txtDNSServer.Text |

                        Where-Object { $_.RecordType -eq "NS" }

            

            $inactiveNS = @()

            $existingNS = @()

            $missingNS = @()

            

            # Check for inactive NS records

            foreach ($ns in $nsRecords) {

                $nsHost = $ns.RecordData.NameServer.Trim('.')

                $existingNS += $nsHost

                

                if ($script:inactiveNSServers.ContainsKey($nsHost) -or -not $script:activeNSServers.Contains($nsHost)) {

                    $inactiveNS += $nsHost

                    $script:inactiveNSCount++

                    Write-ColorOutput "  - Inactive NS found: $nsHost" "Red"

                } else {

                    Write-ColorOutput "  - Active NS found: $nsHost" "Green"

                }

            }

            

            # Check for missing active NS records

            foreach ($activeNS in $script:activeNSServers) {

                if (-not $existingNS.Contains($activeNS)) {

                    $missingNS += $activeNS

                    Write-ColorOutput "  + Missing active NS: $activeNS" "Yellow"

                }

            }

            

            if ($inactiveNS.Count -gt 0) {

                $script:analyzedZones[$zone.ZoneName] = $inactiveNS

            }

            

            if ($missingNS.Count -gt 0) {

                $script:zonesToUpdate[$zone.ZoneName] = $missingNS

            }

            

            if ($inactiveNS.Count -eq 0 -and $missingNS.Count -eq 0) {

                Write-ColorOutput "  Zone is properly configured." "Green"

            }

            Write-Separator

        }

        

        Write-ColorOutput "`nAnalysis Summary:" "Cyan"

        Write-ColorOutput "Total zones analyzed: $($allZones.Count)" "White"

        Write-ColorOutput "Reverse lookup zones to update: $($reverseLookupZones.Count)" "White"

        Write-ColorOutput "Total inactive NS records in reverse zones: $script:inactiveNSCount" "Yellow"

        Write-ColorOutput "Total reverse zones needing NS records: $($script:zonesToUpdate.Count)" "Yellow"

        Write-Separator

        

        if ($script:inactiveNSCount -gt 0 -or $script:zonesToUpdate.Count -gt 0) {

            $btnClean.Enabled = $true

        } else {

            $btnClean.Enabled = $false

        }

        

    } catch {

        Write-ColorOutput "Error analyzing zones: $_" "Red"

        Write-Separator

    }

}

# Function to clean inactive NS records and add missing ones

function Clean-InactiveNSRecords {

    if ([System.Windows.Forms.MessageBox]::Show(

        "Are you sure you want to update NS records in reverse lookup zones?`n`nThis will:`n- Remove inactive NS records from reverse lookup zones`n- Add missing active NS records to reverse lookup zones`n`nOther zones will not be modified.",

        "Confirm Update",

        [System.Windows.Forms.MessageBoxButtons]::YesNo,

        [System.Windows.Forms.MessageBoxIcon]::Warning) -eq 'Yes')

    {

        Write-ColorOutput "Starting reverse lookup zone NS records update..." "Yellow"

        Write-Separator

        

        try {

            $removedCount = 0

            $addedCount = 0

            

            # Process only reverse lookup zones

            foreach ($zone in $script:analyzedZones.Keys) {

                Write-ColorOutput "Processing zone: $zone" "Cyan"

                

                foreach ($inactiveNS in $script:analyzedZones[$zone]) {

                    try {

                        Remove-DnsServerResourceRecord -ZoneName $zone -RRType "NS" -Name "@" `

                            -RecordData $inactiveNS -Force -ComputerName $txtDNSServer.Text

                        Write-ColorOutput "Removed NS record: $inactiveNS" "Green"

                        $removedCount++

                    } catch {

                        Write-ColorOutput "Error removing NS record $inactiveNS : $_" "Red"

                    }

                }

            }

            

            foreach ($zone in $script:zonesToUpdate.Keys) {

                Write-ColorOutput "`nAdding missing NS records to zone: $zone" "Cyan"

                

                foreach ($missingNS in $script:zonesToUpdate[$zone]) {

                    try {

                        Add-DnsServerResourceRecord -ZoneName $zone -NS -Name "@" `

                            -NameServer $missingNS -ComputerName $txtDNSServer.Text

                        Write-ColorOutput "Added NS record: $missingNS" "Green"

                        $addedCount++

                    } catch {

                        Write-ColorOutput "Error adding NS record $missingNS : $_" "Red"

                    }

                }

            }

            

            Write-ColorOutput "`nUpdate Summary:" "Cyan"

            Write-ColorOutput "Total NS records removed from reverse zones: $removedCount" "Yellow"

            Write-ColorOutput "Total NS records added to reverse zones: $addedCount" "Yellow"

            Write-Separator

            

            $btnClean.Enabled = $false

            $script:analyzedZones.Clear()

            $script:zonesToUpdate.Clear()

            $script:inactiveNSCount = 0

            

        } catch {

            Write-ColorOutput "Error during update: $_" "Red"

            Write-Separator

        }

    }

}

# Button click events

$btnRefresh.Add_Click({ Get-ActiveNSRecords })

$btnAnalyze.Add_Click({ Analyze-ReverseLookupZones })

$btnClean.Add_Click({ Clean-InactiveNSRecords })

$btnExit.Add_Click({ $form.Close() })

# Load active NS records when form loads

$form.Add_Shown({

    Get-ActiveNSRecords

})

# Show the form

$form.ShowDialog() 

 

What Is the Purpose of This Script?

This script was developed to improve DNS management efficiency. Over time, DNS servers may experience performance issues due to outdated records, making regular updates crucial. It is particularly useful in the following scenarios:

  • When making major changes to the network.
  • When updating existing Name Server records.
  • When identifying and removing old NS records.
  • When regularly optimizing Reverse Lookup Zone areas.

As a result, with this script

To ensure that Windows DNS servers function correctly, NS records must be continuously monitored and updated. This script provides a great convenience for DNS administrators by offering both analysis and update functions. Using automation like this to keep your DNS infrastructure healthy and up to date is highly beneficial.

If you found this trick helpful, feel free to share it with your team and check out my blog for more quick tips and insights!

Can’t See Missing Subnet Information? Don’t Forget to Enable Debug Logging !

Check the Netlogon Log for Missing Subnets
The netlogon.log file contains valuable information about client site associations. Specifically, lines containing the phrase “no client site” indicate subnets that are not yet defined in Active Directory. These unidentified subnets might be the root cause of certain connectivity issues.

 

Netlogon Debug

To review the log, open the netlogon.log file using your preferred method or PowerShell:

Get-Content C:\Windows\Debug\netlogon.log

Search for lines with “no client site” to identify any missing subnets.

Enable Debug Logging (If Necessary)
If your netlogon.log file is empty, debug logging might not be enabled. To enable it, follow these steps:

Open the Registry or PowerShell:

for Regedit :
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Netlogon\Parameters

Create or modify the DBFlag registry value with the following hexadecimal value:
2080FFFF

for Powershell :

nltest /DBFlag:2080FFFF

Restart the Netlogon service to apply the changes. You can do this via PowerShell:

Restart-Service Netlogon

Analyze the Debug Logs
After enabling debug logging and restarting the service, check the netlogon.log file again. Use PowerShell to monitor the log in real time:

Get-Content C:\Windows\Debug\netlogon.log -Wait

Look for entries with “no client site” to identify the subnets that need to be added to Active Directory.

Debug logging and the netlogon.log file are invaluable tools for identifying and resolving missing subnet configurations in Active Directory. By following these steps, you can easily pinpoint the subnets that require definition and ensure smoother network operations.

If you want to see other articles on the subject;

If you found this trick helpful, feel free to share it with your team and check out my blog for more quick tips and insights!

How To : Subnet Creation Dates in Active Directory

Managing an Active Directory (AD) environment requires a clear understanding of its configuration, including its network subnets. Knowing when specific subnets were added can provide valuable insights for audits, troubleshooting, and change tracking. However, this information is not readily visible in the default Active Directory tools. To address this, I created a script that retrieves and displays the creation dates of subnets in Active Directory.

In this article, I’ll share the purpose of this script, explain how it works, and provide usage instructions. If you’ve been looking for a way to streamline your subnet management tasks, this solution might be just what you need.

Subnet creation dates can be important for:

  1. Auditing: Keeping a record of when changes were made.
  2. Troubleshooting: Identifying if a recent subnet addition aligns with network changes.
  3. Change Management: Ensuring compliance with organizational policies.

While the default AD tools allow you to manage subnets, they lack detailed tracking capabilities. This script bridges that gap by retrieving and displaying the creation timestamps.

The script leverages PowerShell and Active Directory cmdlets to query the CN=Subnets container. By parsing the whenCreated attribute of each subnet object, it provides a clear list of subnets along with their creation dates. Below is a summary of its functionality:

  1. Connects to the Active Directory environment.
  2. Queries the CN=Subnets container.
  3. Retrieves the whenCreated attribute for each subnet.
  4. Outputs the data in a readable format (e.g., table or CSV).

Before running the script, ensure the following:

  • You have administrative privileges to access the CN=Subnets container.
  • PowerShell 5.1 or later is installed on your machine.
  • The Active Directory module for Windows PowerShell is installed.

 

When you execute the script, you’ll see

 

Active Directory Subnet History ;

# Import the Active Directory module

Import-Module ActiveDirectory

try {

    # Retrieve the Configuration container

    $configNC = (Get-ADRootDSE).configurationNamingContext

    

    # Retrieve subnet information

    $subnets = Get-ADObject -Filter 'objectClass -eq "subnet"' `

        -SearchBase "CN=Subnets,CN=Sites,$configNC" `

        -Properties Name, Description, Location, whenCreated, whenChanged, siteObject

    # Process the results

    $subnetInfo = $subnets | Select-Object @{

        Name = "Subnet"

        Expression = { $_.Name }

    },

    @{

        Name = "Created Date"

        Expression = { $_.whenCreated }

    },

    @{

        Name = "Last Modified"

        Expression = { $_.whenChanged }

    },

    @{

        Name = "Location"

        Expression = { if ($_.Location) { $_.Location } else { "Not Specified" } }

    },

    @{

        Name = "Description"

        Expression = { if ($_.Description) { $_.Description } else { "No Description" } }

    },

    @{

        Name = "Associated Site"

        Expression = {

            if ($_.siteObject) {

                ($_.siteObject -split ',')[0] -replace 'CN='

            } else {

                "No Site Associated"

            }

        }

    }

    # Display the total count

    Write-Host "Total Number of Subnets:" $subnets.Count -ForegroundColor Green

    Write-Host "`nDetailed Subnet Information:" -ForegroundColor Yellow

    Write-Host "------------------------`n"

    # Print to screen

    $subnetInfo | Format-Table -AutoSize

    # Export to CSV

    $exportPath = "AD_Subnets_Export_$(Get-Date -Format 'yyyyMMdd_HHmmss').csv"

    $subnetInfo | Export-Csv -Path $exportPath -NoTypeInformation -Encoding UTF8

    Write-Host "`nExported to:" $exportPath -ForegroundColor Cyan

} catch {

    Write-Host "Error occurred: $_" -ForegroundColor Red

    Write-Host "`nCheck if you have the following prerequisites:" -ForegroundColor Yellow

    Write-Host "1. Running PowerShell as Administrator" -ForegroundColor Yellow

    Write-Host "2. Domain Admin or appropriate permissions" -ForegroundColor Yellow

    Write-Host "3. Active Directory PowerShell module is installed" -ForegroundColor Yellow

    Write-Host "4. Running on a domain-joined machine" -ForegroundColor Yellow

}

 

While this script fulfills its primary purpose, there’s always room for improvement. Some potential enhancements include:

Adding filtering options to display subnets created within a specific timeframe.
Incorporating logging functionality for audit purposes.
Automating the script to run periodically and generate reports.

This script provides a straightforward way to retrieve subnet creation dates in Active Directory, making it easier to manage and audit your network environment. Feel free to try it out.

You can also check this article to check for missing subnets in your environment.

 

Have a nice day !

SMBv1: Monitoring and Analyzing Access on Domain Controllers

What is SMB1 and What Does It Do?

Server Message Block Version 1 (SMB1) is an older protocol that facilitates file and printer sharing over a network. Widely used in Windows systems, it allows devices on a network to share data with each other.
However, due to security vulnerabilities, more modern and secure alternatives are recommended.

Advantages:

  • Compatible with older hardware.
  • Simplifies file and printer sharing over a network.

Disadvantages:

  • Prone to security issues and more vulnerable to ransomware attacks.
  • May have lower performance.


Finding SMB1 Access on Domain Controllers

To locate SMB1 access on Domain Controller (DC) servers, the first step is to ensure that the Audit-SMB1Access feature is enabled. This feature collects SMB1 access control logs, making them available for analysis.
These logs focus on specific periods (e.g., the last 10 days).

 

SMBAnalysis
SMBAnalysis

 

Enabling the Audit Feature
To enable SMB1 access logging on Domain Controller servers, use the following PowerShell command:

# Get Domain Controllers

$DomainControllers = Get-ADDomainController -Filter * | Select-Object -ExpandProperty Name

# Checking SMBServerConfiguration AuditSmb1Access

foreach ($DC in $DomainControllers) {

    try {

        # Set-SmbServerConfiguration

        $AuditSmb1Access = Invoke-Command -ComputerName $DC -ScriptBlock {

            Set-SmbServerConfiguration -AuditSmb1Access $true -Force

        }

        Write-Host ("Audit SMB1 Access on {0}: {1}" -f $DC, $true) -ForegroundColor Green

    } catch {

        Write-Host ("Failed to enable Audit SMB1 Access on {0}: {1}" -f $DC, $_.Exception.Message) -ForegroundColor Red

    }

}


To check SMB1 access logging on Domain Controller servers, use the following PowerShell command:

# Get Domain Controller

$DomainControllers = Get-ADDomainController -Filter * | Select-Object -ExpandProperty Name

# Checking SMBServerConfiguration AuditSmb1Access

foreach ($DC in $DomainControllers) {

    try {

        # Get-SmbServerConfiguration

        $AuditSmb1Access = Invoke-Command -ComputerName $DC -ScriptBlock {

            Get-SmbServerConfiguration | Select-Object -ExpandProperty AuditSmb1Access

        }

        Write-Host ("Audit SMB1 Access on {0}: {1}" -f $DC, $AuditSmb1Access) -ForegroundColor Green

    } catch {

        Write-Host ("Failed to check Audit SMB1 Access on {0}: {1}" -f $DC, $_.Exception.Message) -ForegroundColor Red

    }

}

Exporting SMB1 Audit Logs

To analyze SMB1 access logs on Domain Controller servers, use PowerShell to deduplicate this data and review activities over the last 10 days.

$DCList = Get-ADDomainController -Filter *

# Calculate the date 10 days ago

$CutOffDate = (Get-Date).AddDays(-10)

foreach ($DC in $DCList) {

    $DCname = $DC.HostName

    Write-Host "Processing domain controller: $DCname"

    Write-Host "---------------------------------------"

    # HashTable to store unique entries (IP as key, latest timestamp as value)

    $UniqueEntries = @{}

    # Retrieve SMB1 audit logs

    $SMB1Audits = Get-WinEvent -LogName Microsoft-Windows-SMBServer/Audit -ComputerName $DCname

    # Process each log message

    $SMB1Audits | Where-Object { $_.TimeCreated -ge $CutOffDate } | ForEach-Object {

        $eventTime = $_.TimeCreated # Get the event timestamp

        $text = $_.Message.ToString().Split([Environment]::NewLine)

        $client = $text | Where-Object {$_ -like "Client*"}

        if ($client) {

            # Extract and clean the IP address

            $clientIP = $client.Trim()

            # Update the hashtable with the latest event time for the IP

            if ($UniqueEntries.ContainsKey($clientIP)) {

                if ($eventTime -gt $UniqueEntries[$clientIP]) {

                    $UniqueEntries[$clientIP] = $eventTime

                }

            } else {

                $UniqueEntries[$clientIP] = $eventTime

            }

        }

    }

    # Write unique entries to the output file

    $OutputPath = "C:\Scripts\SMB1Analysis\$DCname.txt"

    $UniqueEntries.GetEnumerator() | ForEach-Object {

        "$($_.Value) - $($_.Key)"

    } | Set-Content -Path $OutputPath

    Write-Host "Unique client entries (last 10 days) saved to: $OutputPath"

}

Addressing Security Concerns

  • Identify Security Vulnerabilities: SMB1 has inherent security vulnerabilities and, as an older protocol, is more susceptible to ransomware attacks and network threats. Analyze SMB1 logs to identify potential security risks and breaches.
  • Remediation and Updates: If critical security flaws are found in devices using SMB1, it is essential to update them with security patches. Additionally, consider disabling SMB1 or migrating these devices to a more secure SMB version (SMB2 or SMB3).

Protocol Transition and Reconfiguration

  • Transition from SMB1 to SMB2 or SMB3: To close security gaps associated with SMB1 and enhance overall network security, transition all devices from SMB1 to a more modern and secure SMB version (SMB2 or SMB3). This transition can also improve network performance.
  • Configuration Changes: Adjust Domain Controller settings to disable SMB1 access. This can be done via PowerShell or Group Policy.

Updating Network Security Policies

  • Firewall Rules: SMB1 should only be used on trusted networks, with firewall rules restricting SMB1 access. If necessary, SMB1 should not be accessible to the outside world.
  • Monitoring and Auditing: Continuously monitor and audit SMB1 access on all network devices to detect security breaches early. Regularly review audit logs and address any issues promptly.

User Awareness and Training

  • Limit SMB1 Usage: Educate users about the security risks associated with SMB1 and discourage its use. Provide guidance and training to migrate users to more secure alternatives like SMB2 or SMB3.
  • Documentation: Maintain detailed documentation on changes made and security measures taken. This will serve as a reference in case of similar situations in the future and can be used as a resource for network management.

Periodic Checks and Maintenance

  • Regular Checks: SMB1 usage and security audits should be performed regularly. Periodically check SMB1 logs and network security settings to enhance overall network security and quickly identify potential issues.
  • Security Updates and Patching: Regularly update devices with security patches to protect against new vulnerabilities. This is particularly critical for older hardware.

These steps summarize the fundamental processes needed to enhance your network’s security and resilience against potential threats.

Have a nice day !

Efficient DNS Zone Management: Scripts for Forward, Reverse Lookup Zones and Recovery

At its core, DNS is a system that eliminates the complexity of accessing services via IP addresses by allowing users to connect effortlessly using domain names.

  • It facilitates domain name resolution and management.
  • Directs queries to the appropriate destinations.

DNS zones and reverse lookup zones are crucial components of a robust and secure network infrastructure.

In this article, I will share several scripts that you can use as needed. These scripts are designed to address the following requirements:

  • Exporting the names of all zones in DNS
  • Extracting all records associated with the zones listed in the exported file
  • Exporting all records from a specific zone of your choice
  • Restoring a deleted zone if necessary
  • Add Reverse Lookup Zones

Exporting All Zones in DNS

# Output file path

$outputFile = "C:\Script\DNSOperation\DNSZoneNameExport.csv"

try {

    # Fetching DNS zones

    $zones = Get-DnsServerZone

    if ($zones) {

        # Preparing data for export

        $zoneData = $zones | Select-Object -Property ZoneName

        # Exporting to CSV

        $zoneData | Export-Csv -Path $outputFile -NoTypeInformation -Encoding UTF8

        Write-Host "DNS zones have been successfully exported to $outputFile" -ForegroundColor Green

    } else {

        Write-Host "No DNS zones found." -ForegroundColor Yellow

    }

} catch {

    Write-Host "An error occurred while fetching DNS zones: $_" -ForegroundColor Red

}

Exporting All Zones in Records

# Zones CSV Path

$zonesFile = "C:\Script\DNSOperation\DNSZoneNameExport.csv"

$zones = Import-Csv -Path $zonesFile

foreach ($zone in $zones) {

    $zoneName = $zone.ZoneName

    $OutputFile = "C:\Script\DNSOperation\$zoneName.csv"

    $Report = [System.Collections.Generic.List[Object]]::new()

    $zoneInfo = Get-DnsServerResourceRecord -ZoneName $zoneName

    foreach ($info in $zoneInfo) {

        $timestamp = if ($info.Timestamp) { $info.Timestamp } else { "static" }

        $timetolive = $info.TimeToLive.TotalSeconds

        $recordData = switch ($info.RecordType) {

            'A' { $info.RecordData.IPv4Address }

            'CNAME' { $info.RecordData.HostnameAlias }

            'NS' { $info.RecordData.NameServer }

            'SOA' { "[$($info.RecordData.SerialNumber)] $($info.RecordData.PrimaryServer), $($info.RecordData.ResponsiblePerson)" }

            'SRV' { $info.RecordData.DomainName }

            'PTR' { $info.RecordData.PtrDomainName }

            'MX' { $info.RecordData.MailExchange }

            'AAAA' { $info.RecordData.IPv6Address }

            'TXT' { $info.RecordData.DescriptiveText }

            default { $null }

        }

        $ReportLine = [PSCustomObject]@{

            Name       = $zoneName

            Hostname   = $info.Hostname

            Type       = $info.RecordType

            Data       = $recordData

            Timestamp  = $timestamp

            TimeToLive = $timetolive

        }

        $Report.Add($ReportLine)

    }

    $Report | Export-Csv -Path $OutputFile -NoTypeInformation -Encoding utf8

    Write-Host "DNS records for $zoneName exported successfully." -ForegroundColor Green

}


Exporting Specific Zone in Records

try {

    $Report = [System.Collections.Generic.List[Object]]::new()

    $zoneName = "yusufustundag.com"

    # Fetching zone information

    try {

        $zoneInfo = Get-DnsServerResourceRecord -ZoneName $zoneName -ErrorAction Stop

    } catch {

        Write-Host "Error: Unable to fetch zone information. Zone name: $zoneName" -ForegroundColor Red

        throw $_

    }

    # Processing records

    foreach ($info in $zoneInfo) {

        try {

            $timestamp = if ($info.Timestamp) { $info.Timestamp } else { "static" }

            $timetolive = if ($info.TimeToLive) { $info.TimeToLive.TotalSeconds } else { "N/A" }

            $recordData = switch ($info.RecordType) {

                'A'      { if ($info.RecordData.IPv4Address) { $info.RecordData.IPv4Address } else { "No IP" } }

                'CNAME'  { if ($info.RecordData.HostnameAlias) { $info.RecordData.HostnameAlias } else { "No Alias" } }

                'NS'     { if ($info.RecordData.NameServer) { $info.RecordData.NameServer } else { "No NameServer" } }

                'SOA'    { if ($info.RecordData) { "[$($info.RecordData.SerialNumber)] $($info.RecordData.PrimaryServer), $($info.RecordData.ResponsiblePerson)" } else { "No SOA Information" } }

                'SRV'    { if ($info.RecordData.DomainName) { $info.RecordData.DomainName } else { "No Domain" } }

                'PTR'    { if ($info.RecordData.PtrDomainName) { $info.RecordData.PtrDomainName } else { "No PTR" } }

                'MX'     { if ($info.RecordData.MailExchange) { $info.RecordData.MailExchange } else { "No Mail Exchange" } }

                'AAAA'   { if ($info.RecordData.IPv6Address) { $info.RecordData.IPv6Address } else { "No IPv6" } }

                'TXT'    { if ($info.RecordData.DescriptiveText) { $info.RecordData.DescriptiveText } else { "No TXT" } }

                default  { "Unsupported record type: $($info.RecordType)" }

            }

            $ReportLine = [PSCustomObject]@{

                Name       = $zoneName

                Hostname   = $info.Hostname

                Type       = $info.RecordType

                Data       = $recordData

                Timestamp  = $timestamp

                TimeToLive = $timetolive

            }

            $Report.Add($ReportLine)

        } catch {

            Write-Host "Error: An issue occurred while processing the record. Hostname: $($info.Hostname), Type: $($info.RecordType)" -ForegroundColor Red

            Write-Host "Details: $_" -ForegroundColor Yellow

        }

    }

    # Writing to CSV

    try {

        $Report | Export-Csv "C:\Script\DNSOperation\DNSZoneRecord.csv" -NoTypeInformation -Encoding utf8

        Write-Host "DNS records have been successfully exported." -ForegroundColor Green

    } catch {

        Write-Host "Error: Failed to write to the CSV file." -ForegroundColor Red

        throw $_

    }

} catch {

    Write-Host "An unexpected error occurred: $_" -ForegroundColor Red

}

 

These scripts might seem a bit complex, but the .csv data they generate can effectively meet your needs in situations requiring reporting or verification.

Reading data may not always be easier than working with a .csv file, but in the event of a zone deletion, our other script utilizing the Export-DnsServerZone and dnscmd commands will provide a quick recovery solution.

Recovery – Export Import Specific Zone

Export-DNSServerZone -name yusufustundag.com -FileName yusufustundagExport

After completing the export process, you can find the exported file under the C:\Windows\System32\dns directory.

Now, here’s a critical point: suppose you’ve exported all your zones using this method, but someone accidentally deleted one or more zones. How can you quickly recover them in such a scenario?

The script we will use for this recovery must include the zone name and the name of the exported zone, as shown below.

dnscmd /zoneadd "yusufustundag.com" /primary /file yusufustundagExport /Load

 

Add Reverse Lookup Zone

$Zones = @(

    "1.1.0.0/24",  # Subnet /24 (255.255.255.0)

    "2.2.0.0/24",

    "10.10.151.0/24"

)

foreach ($Zone in $Zones) {

    try {

        # Split the NetworkID and Subnet Mask

        $SubnetArray = $Zone -split '/'

        $IPAddress = $SubnetArray[0]

        $SubnetMask = [int]$SubnetArray[1]

        # Generate the Reverse Lookup Zone Name based on Subnet Mask

        $Octets = $IPAddress -split '\.'

        if ($SubnetMask -le 8) {

            $RevZone = "$($Octets[0]).in-addr.arpa"

        } elseif ($SubnetMask -le 16) {

            $RevZone = "$($Octets[1]).$($Octets[0]).in-addr.arpa"

        } elseif ($SubnetMask -le 24) {

            $RevZone = "$($Octets[2]).$($Octets[1]).$($Octets[0]).in-addr.arpa"

        } else {

            $RevZone = "$($Octets[3]).$($Octets[2]).$($Octets[1]).$($Octets[0]).in-addr.arpa"

        }

        # Check if the Reverse Zone Already Exists

        $ExistingZone = Get-DnsServerZone -Name $RevZone -ErrorAction SilentlyContinue

        

        if ($ExistingZone) {

            Write-Output "Reverse Lookup Zone '$RevZone' already exists."

        } else {

            # Add the Reverse Lookup Zone

            Add-DnsServerPrimaryZone -NetworkID $Zone -ReplicationScope "Domain"

            Write-Output "Reverse Lookup Zone '$RevZone' added successfully."

        }

    } catch {

        # Handle Errors Gracefully

        if ($_.Exception.Message -match "ResourceExists") {

            Write-Output "Reverse Lookup Zone '$RevZone' already exists (error caught)."

        } else {

            Write-Error "Failed to add Reverse Lookup Zone '$RevZone': $_"

        }

    }

}

 

Have a nice day!

How to Find Missing Subnet for Active Directory ?

If your Active Directory environment is large and distributed with numerous network blocks, it is essential to add these network blocks as subnets in Active Directory Sites and Services.

Failing to add these subnets can result in several disadvantages.

Disadvantages of Missing Subnet Definitions in Active Directory Environments

In an Active Directory (AD) environment, missing or incomplete subnet definitions can lead to various issues and inefficiencies. Especially in large and complex networks, correctly defining subnets is critical for AD to function properly. Below are the key disadvantages:

1. Site and Replication Issues

  • In AD, sites are used to optimize network traffic. Subnet definitions associate specific subnets with sites to direct traffic efficiently.
  • If subnets are missing, clients and servers might be associated with incorrect sites, leading to unnecessary WAN traffic and replication delays.

2. Delayed Authentication and Group Policy Application

  • Missing or incorrect subnet definitions may prevent clients from locating the nearest Domain Controller (DC). As a result, clients may attempt to authenticate with a DC in a remote location.
  • This can lead to longer login times and delayed Group Policy Object (GPO) applications.

3. Performance Degradation and Bandwidth Overuse

  • Without accurate subnet definitions, clients and servers may connect to DCs in distant sites, which can impact performance, especially in environments with slow WAN links.
  • Replication traffic between incorrectly associated sites may also increase WAN bandwidth usage unnecessarily.

4. Incorrect Site-Link Utilization

  • Sites and subnets are interconnected using site links. Missing subnet definitions can result in clients using inappropriate site links to access DCs or other AD services.
  • This can cause replication delays and incorrect DC selection.

5. DNS Resolution Issues

  • DNS is vital for authentication and replication processes in an AD environment. Missing subnet definitions may cause clients to use inappropriate DNS servers, resulting in delayed or failed DNS queries.
  • This can lead to slow AD services or failures in certain processes.

6. Complications in Log Analysis and Network Management

  • Missing subnet definitions complicate log analysis and network management. For instance, identifying which site specific IP ranges belong to becomes challenging.
  • Troubleshooting network-related issues becomes more complex and time-consuming.

Result

Properly defining subnets in an Active Directory environment is crucial for authentication, replication, and traffic management. Missing subnet definitions, particularly in large and distributed networks, can lead to performance bottlenecks and operational challenges. To avoid these problems, it is essential to define and regularly update subnet configurations for each location.

To avoid encountering these disadvantages, we need to use the Netlogon.log file to identify missing subnets. It is not necessary to enable Netlogon debug parameters to obtain information about missing subnets. By default, No_Client_Site entries can be found in the Netlogon file.

While detecting No_Client_Site information in the Netlogon file is relatively straightforward in environments with a single Domain Controller, it can become time-consuming in environments with multiple Domain Controllers, as you would need to search each Netlogon file individually.

For large and distributed environments, the following PowerShell script can be used to gather missing subnet information:

The script retrieves all Domain Controllers in the environment and categorizes them as accessible or inaccessible.
For accessible Domain Controllers, it accesses the Windows\debug directory, extracts the No_Client_Site entries from the Netlogon.log file, deduplicates the data, and exports the results.

<#
This script analyzes missing subnets in an Active Directory environment.
It uses the Get-ADDomainController parameter to retrieve all Domain Controller servers in the environment.  
The output is divided into two categories based on their accessibility.  
For accessible Domain Controllers, the script examines the lines from the netlogon.log file within the last day.  
Only unique entries are included in the output.  
If you want to analyze the netlogon.log file for the last 5 days instead, you can update the relevant line in the script:  
$lastFiveDays = (Get-Date).AddDays(-5)
#>

#Active Directory Missing Subnet Analysis#
# Output files
$outputPathAccessible = "C:\script\MissingSubnet\Output\Accessible_DCs.txt"
$outputPathInaccessible = "C:\script\MissingSubnet\Output\Inaccessible_DCs.txt"
$outputPathNoClientSite = "C:\script\MissingSubnet\Output\Missing_Subnet.txt"
# Clear or create the output files
if (Test-Path $outputPathAccessible) { Clear-Content -Path $outputPathAccessible } else { New-Item -Path $outputPathAccessible -ItemType File }
if (Test-Path $outputPathInaccessible) { Clear-Content -Path $outputPathInaccessible } else { New-Item -Path $outputPathInaccessible -ItemType File }
if (Test-Path $outputPathNoClientSite) { Clear-Content -Path $outputPathNoClientSite } else { New-Item -Path $outputPathNoClientSite -ItemType File }
# Add header rows
Add-Content -Path $outputPathAccessible -Value "Accessible Domain Controllers"
Add-Content -Path $outputPathInaccessible -Value "Inaccessible Domain Controllers"
Add-Content -Path $outputPathNoClientSite -Value '"Domain Controller" | "Computer Name" | "IP Address"'
# Get all Domain Controllers
$servers = (Get-ADDomainController -Filter *).Hostname
$uniqueEntries = @()  # Temporary list to store unique entries
$yesterday = (Get-Date).AddDays(-1)  # Get the date for one day ago
# Check if each Domain Controller is accessible
foreach ($server in $servers) {
    $logPath = "\\$server\c$\Windows\debug\netlogon.log"
    # Check if the server is reachable by ping
    if (Test-Connection -ComputerName $server -Count 1 -Quiet) {
        # Write reachable servers to the file
        Add-Content -Path $outputPathAccessible -Value $server
        # Perform Netlogon processing
        if (Test-Path $logPath) {
            $lines = Get-Content -Path $logPath
            # Check each line in the log file
            foreach ($line in $lines) {
                # Extract date information from the line and compare with the last 1 day
                if ($line -match "^\d{2}/\d{2}") {
                    $datePart = $line.Substring(0, 5)  # Extract the date part (MM/dd format)
                    $timePart = $line.Substring(6, 8)  # Extract the time part
                    # Combine date and time and convert to a DateTime object
                    $entryDate = Get-Date -Month $datePart.Split("/")[0] -Day $datePart.Split("/")[1] -Hour $timePart.Split(":")[0] -Minute $timePart.Split(":")[1] -Second $timePart.Split(":")[2]
                    # Process only if the entry is within the last 1 day
                    if ($entryDate -ge $yesterday) {
                        if ($line -match "NO_CLIENT_SITE") {
                            # Extract client name and IP address
                            $client = $line.Split(":")[4].Trim().Split(" ")[0]
                            $ip = $line.Split(":")[4].Trim().Split(" ")[1]
                            # Create the entry format
                            $entry = "$server | $client | $ip"
                            # Add to unique list (ignore duplicates)
                            if ($uniqueEntries -notcontains $entry) {
                                $uniqueEntries += $entry
                            }
                        }
                    }
                }
            }
        } else {
            Write-Host "Log file not found: $logPath"
        }
    } else {
        # Write unreachable servers to the file
        Add-Content -Path $outputPathInaccessible -Value $server
        Write-Host "$server is not reachable."
    }
}
# Write unique entries to "No_client_site.txt"
$uniqueEntries | ForEach-Object { Add-Content -Value $_ -Path $outputPathNoClientSite }

 

Simple , Easy, Useful

Have a nice day !

Automatically Deleting Files and Folders When Disk Space is Low

If you need to automatically delete files and folders when disk space on your drive falls below a certain threshold, you can use a PowerShell script to accomplish this task. Here’s how you can set it up.

PowerShell Script

This script will delete files and directories under a specified path when the available disk space is less than 5 GB.

# Define the path to the directory
$directoryPath = "C:\DeleteFilesFolder\

# Set the threshold for disk space (in bytes)
$threshold = 5GB

# Get the drive information
$drive = Get-PSDrive -PSProvider FileSystem | Where-Object { $_.Root -eq "C:\" }

# Check the available free space on the drive
if ($drive.Free -lt $threshold) {
# Get all files in the specified directory and subdirectories
$files = Get-ChildItem -Path $directoryPath -Recurse -File

# Loop through and delete each file
foreach ($file in $files) {
Remove-Item -Path $file.FullName -Force
Write-Output "Deleted file: $($file.FullName)"
}

# Get all directories in the specified directory and subdirectories
$directories = Get-ChildItem -Path $directoryPath -Recurse -Directory | Sort-Object -Property FullName -Descending

# Loop through and delete each directory if it is empty
foreach ($directory in $directories) {
Remove-Item -Path $directory.FullName -Recurse -Force
Write-Output "Deleted directory: $($directory.FullName)"
}

Write-Output "All files and directories in $directoryPath and its subdirectories have been deleted due to low disk space."
} else {
Write-Output "Sufficient disk space available: $($drive.Free / 1GB) GB free."
}

Explanation of the Script

  1. $directoryPath: Specifies the directory path where files and folders will be deleted.
  2. $threshold: Sets the disk space threshold to 5 GB.
  3. $drive: Checks the free space available on the C: drive.
  4. if ($drive.Free -lt $threshold): Checks if the available free space is less than 5 GB.
  5. Get-ChildItem -Path $directoryPath -Recurse -File: Gets all files in the specified directory and subdirectories.
  6. Remove-Item -Path $file.FullName -Force: Deletes each file without user interaction.
  7. Get-ChildItem -Path $directoryPath -Recurse -Directory | Sort-Object -Property FullName -Descending: Gets all directories in descending order to ensure deletion from the deepest level first.
  8. foreach ($directory in $directories): Deletes each directory and its contents without user interaction if it’s empty.

Running the Script Manually

  1. Open PowerShell as Administrator.
  2. Run the Script:
    C:\Scripts\ClearIncomingQueue.ps1

Automating the Script with Task Scheduler

You can use Task Scheduler to automate the script.

  1. Open Task Scheduler: Open it by typing taskschd.msc in the Run dialog.
  2. Create a New Task:
    • Right-click and select “Create Task”.
    • General tab: Name your task (e.g., “Clear Files and Folders”).
    • Triggers tab: Click “New” and choose the schedule (e.g., daily).
    • Actions tab: Click “New” and select “Start a program”. Enter powershell.exe as the program/script.
    • In the “Add arguments (optional)” field, enter:
      -File "C:\Scripts\ClearIncomingQueue.ps1"
    • Conditions tab: Check “Start the task only if the computer is on AC power”.
    • Settings tab: Check “If the task fails, restart every” and set an interval.

This setup ensures that files and directories under the specified path are automatically deleted when the available disk space falls below 5 GB, without any user interaction.

Simple , Easy, Useful

Have a nice day !

What is VMware Heap Size? How to Clear VMware Heap Size ?

Heap size in a VMware infrastructure refers to a portion of memory used to manage virtual machines and VMware-specific operations. The heap is dynamically allocated memory that can be released back to the operating system. It is used to store runtime data required for virtual machines, applications, and system processes.

Factors Increasing Heap Usage:

  • Virtual Machine Density: More VMs increase heap usage.
  • Application Requirements: Applications with high memory needs can raise heap usage.
  • Memory Leaks: Leaks in applications or processes can consume heap memory.
  • System and Service Updates: Updates may temporarily increase heap usage.
  • Configuration Changes: Adjustments in settings can impact heap usage.

Monitoring heap usage is crucial to prevent performance issues and maintain system health.

Methods to Clear VMware Heap Size:

You might need to clear the heap space on your VMware ESXi servers. Usually, the heap space is automatically managed to enhance the functionality of ESXi servers and prevent memory leaks. However, manual intervention might be necessary in certain situations. Here are some methods to consider:

  • Restart the ESXi Host: This is the simplest and most effective method if possible. It clears all memory and resets the heap space.
  • Restart Services: If restarting the host is not an option, you can clear the heap space by restarting key services. For example, use the commands /etc/init.d/hostd restart and /etc/init.d/vpxa restart to restart the management network service.
  • Check Advanced Settings: Some advanced settings, like Config.HostAgent.plugins.solo.enableMob, can affect heap size. Adjusting these settings as specified in VMware’s knowledge base might resolve issues.
  • Manage Memory Resources: Identify and address virtual machines or applications causing high memory usage to indirectly reduce heap usage.
  • Check Log Files: Log files in the /var/log directory, especially vmkernel.log and hostd.log, can help identify and troubleshoot heap issues.

If the methods above do not resolve the problem, you will need to contact VMware support for further assistance.

 

Have a nice day !

How to Add Multiple Subnets to Active Directory Sites and Services

Your infrastructure may have multiple locations and, depending on those locations, many network subnets. In some cases, you may choose to use multiple network subnets to separate services even within a single data centre.

If you are using Active Directory as the directory service in your infrastructure, you need to add these subnets to ‘Sites’ under "Active Directory Sites and Services" and ‘Subnets’ under that.

You can add subnets most simply with a few right clicks on the "Active Directory Sites and Services" console. This is usually the method that everyone uses.

This process also has an equivalent in the PowerShell world. Although it is generally not preferred by those who do not like to work with scripts, there is no better method than this when you want to do batch processing.

If you have hundreds of subnets that you need to define, you can do it in seconds with the following script.

# CSVPath
$csvFilePath = "C:\Subnet.csv"

# CSVRead
$subnets = Import-Csv -Path $csvFilePath

#Created
foreach ($subnet in $subnets) {

$name = $subnet.Name
$site = $subnet.Site
$description = $subnet.Description

try
{
New-ADReplicationSubnet -Name $name -Site $site -Description $description
Write-Host "Subnet $name added."

}catch{
Write-Host "Subnet $name failed: $_"
}
}

 

For mote detailed information ;

Have a nice day!

Republic Day: 100th Anniversary of The Republic of Türkiye

The Turkish Republic is celebrating its Centennial anniversary today (29 October).

Republic Day in Turkey, also known as Cumhuriyet Bayramı, is celebrated on October 29th each year to commemorate the proclamation of The Republic of Turkey. The 100th anniversary of the Republic of Turkey was celebrated on October 29, 2023, marking a significant milestone in Turkish history.

On October 29, 1923, Mustafa Kemal Atatürk, the founder of modern Turkey, officially declared the establishment of The Republic of Turkey, ending the Ottoman Empire’s rule and transforming Turkey into a modern, secular, and democratic nation. This momentous event marked the beginning of a new era for the country and its people.

Republic Day is celebrated with various events and activities across Turkey. These celebrations typically include parades, fireworks, concerts, and other public gatherings. People often adorn their homes and public buildings with the Turkish flag, and the national anthem is sung with great pride.

The 100th anniversary of the Republic of Turkey is an especially significant occasion, and it is likely to be marked with even more grandiose celebrations and festivities, reflecting the importance of this historical milestone in the country’s journey towards modernization and democracy.

When Mustafa Kemal Atatürk proclaimed the Republic of Turkey on October 29, 1923, he made a famous speech to the Turkish Grand National Assembly. In his speech, he expressed his vision for the new Turkish state and emphasized the principles that would guide its transformation. Here is an excerpt from Atatürk's speech on that historic day:

"Turkish people, your existence, your future, your honor and your happiness are in the faith, the determination and the fervor of manhood that are characteristic of you. From the day I took the leadership of the war of salvation until today, the strength of this faith, determination and fervor has never abandoned me, and I have been helped by it. I am grateful to you all for this great service you have done, which I could never repay.
The Republic of Turkey shall be a state of justice, a state where the rule of law, the principle of the equality of citizens before the law, and the principle of the protection of human rights shall be established in accordance with the concepts and understanding of contemporary civilization and law, and which serves its people in accordance with these principles.
A citizen of the Turkish Republic, whatever his religion or race may be, whatever his beliefs or inclinations may be, is a person who has full citizenship rights and responsibilities."

In this speech, Atatürk emphasized the principles of democracy, secularism, and the equality of all citizens, regardless of their religion or ethnicity. He laid the foundation for a modern, secular, and democratic republic, which has since been enshrined in the Turkish Constitution. Atatürk's vision and leadership played a crucial role in shaping modern Turkey.

 

"How happy is the one who says I am a Turk"

Atatürk used this phrase to emphasize the importance of national identity and unity, encouraging citizens to take pride in their Turkish heritage and culture. It signifies a sense of belonging and commitment to the Turkish nation. The motto highlights the idea that being a part of the Turkish nation is a source of happiness and pride.

 

"Peace at home Peace in the World"

This motto reflects Atatürk’s foreign policy principles and his belief that establishing and maintaining peace within a nation is crucial for promoting peace on a global scale.
Atatürk believed that a strong, stable, and united nation at home would contribute to greater harmony and cooperation with other nations in the world. This principle underscores the idea that a nation’s internal stability and peace are closely linked to its ability to maintain peaceful relations with other countries.
The motto “Peace at home, peace in the world” is a call for nations to prioritize diplomacy, cooperation, and peaceful solutions to conflicts rather than resorting to violence or war. It conveys the importance of avoiding external conflicts and focusing on domestic prosperity and harmony as a means to promote global peace and stability. This principle remains an important part of Turkey’s foreign policy and diplomatic efforts.

 

 

 

"How happy is the one who says I am a Turk"