Check DNS for unresponsive servers with ping, compare forward and PTR records

The idea with this script is to check servers with multiple A records, in which the old A record is no longer used and was never deleted. There are some instances in which an A record wouldn’t be discovered (such as if the previous IP used by the A record returns a response to ping) but this particular script was developed to handle a change in subnets.

Future DNS cleanup scripts will handle mismatched records (A and PTR), unmapped CNAMEs (those pointing to a deleted A record), and any duplicate A record entries.

#DNS_health_check.ps1
#Trey smith, 6/22/2017
#Looks through DNS, attempts to ping each computer name, reports on those that do not respond to pings. Checks for PTR records existing of those that don't respond
#writes info to a log file - doesn't take any specific action
#set the following variables:
$domain = ""
$logFile = "DNSrecordResults.txt"
$dc = ""
#variables instantiating - uncomment variable lines in this section when running the script for the first time *********************

$dns = Get-WmiObject -Class MicrosoftDNS_AType -NameSpace Root\MicrosoftDNS -ComputerName $dc  -Filter "DomainName = '$($domain)'"
$rdns = Get-WmiObject -Class MicrosoftDNS_PTRType -NameSpace Root\MicrosoftDNS -ComputerName $dc

#**********************************************************************End of variables instantiating*******************************

#setting up the log file
if (test-path $logFile){
    clear-content $logFile
}
write-output "Hostname,IP,PTR_IP[if_exist],PTR_hostname[if_exist],PTR_lookup_info[if_lookup]" | out-File -append $logFile
$outputString = ""

#non-function script code
foreach ($aRecord in $dns) {
    #Write-Output $aRecord.OwnerName #test, comment for prod
    $IP = $aRecord.RecordData #recorddata is the IP address

    if(!(test-connection $IP -quiet -count 1)){ #recordData should be the IP address - if can't ping, checks to see if PTR record exists
        #write-host $aRecord.OwnerName "ownername" #FQDN
        $outputString = "$($aRecord.OwnerName)," + "$IP" #starts the output string, which will be going into the line in the csv
        $split = $IP.Split("{.}")   # tokenizes IP
        $numbers = $split[0], $split[1], $split[2], $split[3]
        [array]::Reverse($numbers)
        $PI = [string]::Join(".",$numbers)    #should be the PTR IP address
        if($robject = $rdns | Where-Object {$_.OwnerName -eq "${PI}.in-addr.arpa"}){ #this block checks for PTR record in list
            $outputString = $outputString + ","  + "," + $robject.OwnerName + "," + $robject.recorddata
            write-Host $outputString "outputstring when PTR found"
            }
            elseif($robjectName = $rdns | Where-Object {$_.RecordData -eq "$($aRecord.OwnerName)."}){ #This block checks for PTR record with matching hostname (different IP)
                $outputString = $outputString + "," + "," + $robjectName.OwnerName + "," + $robjectName.recorddata
                write-host $outputString "outputString when PTR Hostname Found w/different IP"
            }else{
            #lse no PTR record, just failed
            }
    }#end of checking connection

    if($outputString) {write-output $outputString | out-File -append $logFile}
    $outputString = ""
    #'' next!

}#end of iteration through each record

send web requests to list of URLs belonging to a particular website or server

Requires powershell v3

This script will ignore tls/trust issues that you may be having. You can also take out that part of your script if you keep receiving the error:
The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel.
At Line: Char:

#usage: urlwarmup.ps1 -server [servername]
#for questions, email csmith@avari.tech
param (
[string]$server = "serverName"
)
add-type @"
using System.Net;
using System.Security.Cryptography.X509Certificates;
public class TrustAllCertsPolicy : ICertificatePolicy {
public bool CheckValidationResult(
ServicePoint srvPoint, X509Certificate certificate,
WebRequest request, int certificateProblem) {
return true;
}
}
"@
[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy
$warmupURLS = "https://$server.advocare.com/",`
"https://$server.com/store",`
"https://$server.com/store/item1",`
"https://$server.com/",`
"https://$server.com/api/en/productsapi/getallproducts/false/false/false/false/false"

foreach ($url in $warmupURLS){
$request = Invoke-WebRequest -URI $url -Method GET -TimeoutSec 200
if ($request.StatusCode -eq "200"){write-host "successful request to $url"}
else{write-host "request to $url failed"}
} 

Netscaler server removal automation using powershell and RestAPI

Here we have a script (tested on powershell v3 running on server 2k8 as a scheduled task) that I wrote for a client to disable a server in a load balancer at a certain time for IIS app pool recycles, then to warm the websites up by hitting a list of URLs and emailing on failure. This script talks to the server via the NITRO API that the Citrix Netscaler implements.

What this script does not yet do is check for which netscaler is active in a cluster, nor does it work by disabling individual services at this time, but by the server (based on clients needs). It also doesn’t make sure that the server is a member of the particular VIP that you are checking, so beware if you have multiple VIPS.

Feel free to use parts of this script or the entire thing, modified as needed for your organization.

#VERSION 1.3
#Trey Smith
#trey@avari.tech
#ns-serverManipulate -env [development|production] -server [server] -action [ENABLE|DISABLE]

#note: only 2 environments are on here now. can be updated as needed. 


#FIXME:
#CHECK THAT EVERYTHING IS UP OR DOWN BEFORE CALLING IT A DAY
#POSSIBLY DO IT VIA SERVICE VS SERVER
#MAKE SURE SERVERS SERVICES BELONG TO THE VIP THAT YOU'RE CHECKING



 param (
 [string]$env = "development",
 [string]$server,
 [string]$action
 )


 ##################CONFIGURE PRIOR TO PROD####################
 $errorEmail = "" #email to send to if there is an error
 
 #$server = "server" 
 $mailServer = "" #your SMTP host. Not configured for authentication 

 $fromEmail = "" # rcpt from
 $environment = $env.ToString()
##############################################################
#ERROR CHECKING
if ($action -ne "enable" -and $action -ne "disable"){
    write-host "INCORRECTION ACTION, must be enable or disable. format ns-serverManipulate -env [development|production] -server [server] -action [ENABLE|DISABLE]"
    exit
}
if ($environment -ne "production" -and $environment -ne "development"){
    write-host "INCORRECTION ACTION, must be development or production. format ns-serverManipulate -env [development|production] -server [server] -action [ENABLE|DISABLE]"
    exit
}
$currTime = get-date -format F


 #FIXME: check for active netscaler
 #ENVIRONMENT SPECIFIC###### UPDATE FOR BOTH ENVIRONMNETS!!!!!!!
 if ($environment -eq "development"){
     $hostname = "my-netscaler" 
     $username = "my-operator-account" #dev
     $password = "my-pass" #dev
 
     $VIP_HTTP = "VIP_web_http" #VIP name for HTTP (DEV)
     $VIP_HTTPS = "VIP_web_https" #VIP name for HTTPS 
 }


 #fixme FIX THE WHOLE PROD SECTION###################
  if ($environment -eq "production"){
     $hostname = "" 
     $username = "" 
     $password = "" 
     $VIP_HTTP = "VIP_web_http" #VIP name for HTTP 
     $VIP_HTTPS = "VIP_web_https" #VIP name for HTTPS 
 }
 #fixme FIX THE WHOLE PROD SECTION###################




 $warmupURLS = "https://$server/",`
    "https://$server/store",`

$warmupTimes = @("URL,Total Seconds `n")


Send-MailMessage -From $fromEmail -to $errorEmail  -subject "AUTO-SERVER SCRIPT STARTING RUNNING" -SmtpServer $mailServer -body "(THIS EMAIL IS FROM THE AUTOMATED SCRIPT) ARGUMENTS are $action $environment $server`n CURRENT TIME IS $currTime"
 
 #fixme set enable or disable arguments to call whichever function
 #$response = ""#fixme delete this later for parsing


# Ignore Cert Errors
#[System.Net.ServicePointManager]::ServerCertificateValidationCallback = { $true } #from Carl, but for some reason, this appears to be what it takes:
###############################TRUST ALL CERTS###################################
add-type @"

    using System.Net;

    using System.Security.Cryptography.X509Certificates;

    public class TrustAllCertsPolicy : ICertificatePolicy {

        public bool CheckValidationResult(

            ServicePoint srvPoint, X509Certificate certificate,

            WebRequest request, int certificateProblem) {

            return true;

        }

    }

"@

[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy

#################################################################################

#FUNCTIONS ARE CALLED AT THE BOTTOM OF THE SCRIPT#################################
function Login {

    # Login to NetScaler and save session to global variable

    $body = ConvertTo-JSON @{

        "login"=@{

            "username"="$username";

            "password"="$password"

            }

        }
    
        try{Invoke-RestMethod -uri "$hostname/nitro/v1/config/login" -body $body -SessionVariable NSSession -ContentType "application/vnd.com.citrix.netscaler.login+json" -Method POST}
        catch{#write-host "invoke-restmethod failed to $hostname $VIP_HTTP error message is $_"; 
                HandleError("error connecting to Netscaler invoke-restmethod failed to $hostname $VIP_HTTP error message is $_")
            }


    $Script:NSSession = $local:NSSession

}

function Enable {

# disable server

    $body = ConvertTo-JSON @{
    "server"=@{
        "name"=$server
        
        }
    }
   # $body
   try{Invoke-RestMethod -uri "$hostname/nitro/v1/config/server?action=enable" -body $body -WebSession $NSSession -ContentType "application/json" -Method POST}
   catch{#write-host "invoke-restmethod failed to $hostname $VIP_HTTP error message is $_"; 
            HandleError("error connecting to Netscaler invoke-restmethod failed to $hostname $VIP_HTTP error message is $_")
        }

  
} #fixme: add error cehcking for anything other than 200

function Disable {

# disable server

    $body = ConvertTo-JSON @{
    "server"=@{
        "name"=$server;
        "graceful"="YES"
        }
    }
   # $body
   try{Invoke-RestMethod -uri "$hostname/nitro/v1/config/server?action=disable" -body $body -WebSession $NSSession -ContentType "application/json" -Method POST}
   catch{#write-host "invoke-restmethod failed to $hostname $VIP_HTTP error message is $_"; 
            HandleError("error connecting to Netscaler invoke-restmethod failed to $hostname $VIP_HTTP error message is $_")
        }
    #Invoke-RestMethod -uri "$hostname/nitro/v1/config/login" -body $body -SessionVariable NSSession -ContentType "application/vnd.com.citrix.netscaler.logout+json" -Method POST

    #$Script:NSSession = $local:NSSession
} #fixme: add error cehcking for anything other than 200

function Logout {

# Logout

    $body = ConvertTo-JSON @{
    "logout"=@{}
    }
   # $body
   try{Invoke-RestMethod -uri "$hostname/nitro/v1/config/logout" -body $body -WebSession $NSSession -ContentType "application/vnd.com.citrix.netscaler.logout+json" -Method POST}
   catch{#write-host "invoke-restmethod failed to $hostname $VIP_HTTP error message is $_"; 
            Send-MailMessage -From $fromEmail -to $errorEmail  -subject "AUTO-SERVER REMOVAL SCRIPT FAILED" -SmtpServer $mailServer -body "LOGOUT FAILED"
            exit
        }
    if ($action -eq "disable"){
        Send-MailMessage -From $fromEmail -to $errorEmail  -subject "AUTO-SERVER SCRIPT COMPLETED SUCCESSFULLY" -SmtpServer $mailServer -body "ARGUMENTS are $action $environment $server `n CURRENT TIME IS $currTime"
    }
    if ($action -eq "enable"){
        Send-MailMessage -From $fromEmail -to $errorEmail  -subject "AUTO-SERVER SCRIPT COMPLETED SUCCESSFULLY" -SmtpServer $mailServer -body "ARGUMENTS are $action $environment $server `n URL RESULTS ARE $warmupTimes CURRENT TIME IS $currTime"
        
    }
    $Script:NSSession = $local:NSSession
}

function SanityCheck{
    #fixme: see if actually disabled first. 
    #fixme: See if exist in VIP
   try{$response = Invoke-RestMethod -uri "$hostname/nitro/v1/config/lbvserver/$VIP_HTTPS" -WebSession $NSSession -ContentType "application/vnd.com.citrix.lbvserver_list+json" -Method GET}
   catch{#write-host "invoke-restmethod failed to $hostname $VIP_HTTP error message is $_"; 
            HandleError("error connecting to Netscaler invoke-restmethod failed to $hostname $VIP_HTTP error message is $_")
        }#$response.lbvserver

   $activeServices = $response.lbvserver.activeservices
   $totalservices = $response.lbvserver.totalservices
   #$activeServices;$totalservices
   
    if ($totalservices -gt $activeServices){HandleError("ONE OR MORE SERVERS ARE ALREADY DISABLED - $VIP_HTTPS VIP")}
        #get servers in VIP
        #if any disabled, stop, throw error or email! Exit script
        try{$response = Invoke-RestMethod -uri "$hostname/nitro/v1/config/lbvserver/$VIP_HTTP" -WebSession $NSSession -ContentType "application/vnd.com.citrix.lbvserver_list+json" -Method GET}
        catch{#write-host "invoke-restmethod failed to $hostname $VIP_HTTP error message is $_"; 
            HandleError("error connecting to Netscaler invoke-restmethod failed to $hostname $VIP_HTTP error message is $_")
        }
        $activeServices = $response.lbvserver.activeservices
        $totalservices = $response.lbvserver.totalservices
   
   if ($totalservices -gt $activeServices){HandleError("ONE OR MORE SERVERS ARE ALREADY DISABLED")}
}
function Warmup{

    foreach ($url in $warmupURLS){#Invoke-WebRequest -URI $url -method GET
        try{start-sleep 1
        write-host $url

        $result = measure-command{Invoke-WebRequest -URI $url -Method GET -TimeoutSec 200}

        $script:warmupTimes += "$url," + $result.TotalSeconds.ToString() + "`n"
        
        }catch{HandleError("ERROR WITH WARMUP ON $server")} 


    
    
    } 
}
function HandleError($description){
    $dateTime = Get-Date
    write-Host "SCRIPT STOPPING DUE TO $description"
       Send-MailMessage -From $fromEmail -to $errorEmail  -subject "AUTO-SERVER REMOVAL SCRIPT FAILED" -SmtpServer $mailServer -body "$environment $description $dateTime CURRENT TIME IS $currTime"
   Logout
   exit

}

#BEGIN CALLING FUNCTIONS. 
Login
if ($action -eq "disable"){
    SanityCheck #check to make sure no disabled servers
    Disable #disable the server
}
if ($action -eq "enable"){
    #check if actually disabled fixme    
    Warmup
    start-sleep 1
    Enable

    }

Logout

Ping results over time

This script was useful to me while tracking down a networking issue where packets were lost over a long period of time. I ran this script from 2 different endpoints and compared the times that the packets were dropped. Enjoy!

Source: http://avari.tech/access/pinglog.ps1

#***************************************************************************************#

#pinglog.ps1
#1/18/2016, trey@avari.tech
#pings an IP roughly every second and logs it to a logfile

#instructions: Replace $ip and $logFile variables

$ip = "4.2.2.1"
$logFile = "C:\users\csmith\Documents\working\pingOutput.txt"

while($true){
    $time = get-date | select DateTime
    $timeStr = $time.DateTime -replace " ","" -replace "2017","" #no comma #between year and time so deleted year
    $pingRes = ping -n 1 $ip
    $pingSplit = $pingRes.Split()

    if ($pingSplit[8] -eq "Reply"){$pingStr = $pingSplit[12]}
    else{$pingStr = "Failed"}

    add-content $logFile "$timeStr,$pingStr"
    write-host "$timeStr,$pingStr"
    start-sleep 1
}

ITAaS (IT as a service) and departmental relationships

Here in the IT world it is easy to get an ego about what we do. I don’t know why that is, only that if you ask people in or who deal with IT regularly, they would likely agree. It’s something that we have to recognize and avoid having it interfere with the service that we provide the business.

Today I had a client that has had, according to IT, a very troublesome and needy department. In recent history they had some wireless issues with their hardware, they were using Macs while the rest of the company used Windows desktop OS’. More recently, they complained of the wireless network and asked to be directly wired in like some others in their department. Due to the bad taste left in the mouth of the IT personnel, team members were hesitant to so much as address this issue, much less diagnose it and come to some resolution. This issue had been going on for over a week until the CTO caught wind of the issue and dispatched me to assist in coming up with a solution.

The department in question was indeed having issues as they were working with files several Gigabytes in size while accessing them over the network. They refused (or were unable, citing extreme latency) to work with files locally, reuploading as necessary, and IT refused to yield, citing methodology used by a previous company as being the solution. After gauging what they were trying to do, and their current latency to the internet, I came up with a solution while escorting the IT person on staff out of there as things were beginning to get heated.

After proposing a possible solution to the IT department, I was met with a lot of hostility for working with this other department to come to a solution. The personnel were offended that this department routinely reviewed IT negatively and had an awful reputation, to which the hostility and apathy would only serve to exacerbate. We eventually did get the solution passed and work is going to begin shortly, and perhaps departmental relations can begin improving shortly.

What went wrong here? Based on my descriptions, you may guess that I would blame the rather coarse IT engineer assigned to the task, but that’s not the case. It’s important for both departments to understand that they are each fulfilling the business’ needs. Was the solution revolutionary? No. Can the department function with workarounds until implementation? Absolutely. What we had was an unwillingness to listen on both parts and treat each other as professionals. After the meeting, on my way out the door, I caught the department manager about the fact that we had a solution underway, and a workaround, and why we could not immediately give him what he asked. When the other engineer was there I was unable to explain the situation, but due to the fact that I took his situation seriously and listened to the issues he was having, he was able to be receptive to a workaround until we can get the permanent fix put in place.