Skip to content

Instantly share code, notes, and snippets.

@pldmgg
Created November 27, 2018 19:13
Show Gist options
  • Select an option

  • Save pldmgg/a943205afd6499ab20fc2b620ca2b0ae to your computer and use it in GitHub Desktop.

Select an option

Save pldmgg/a943205afd6499ab20fc2b620ca2b0ae to your computer and use it in GitHub Desktop.
Script to monitor ports 104 and 108 every 30 seconds
#region >> Helper Functions
function TestIsValidIPAddress([string]$IPAddress) {
[boolean]$Octets = (($IPAddress.Split(".") | Measure-Object).Count -eq 4)
[boolean]$Valid = ($IPAddress -as [ipaddress]) -as [boolean]
Return ($Valid -and $Octets)
}
function ResolveHost {
[CmdletBinding()]
Param(
[Parameter(Mandatory=$True)]
[string]$HostNameOrIP
)
##### BEGIN Main Body #####
$RemoteHostNetworkInfoArray = @()
if (!$(TestIsValidIPAddress -IPAddress $HostNameOrIP)) {
try {
$HostNamePrep = $HostNameOrIP
[System.Collections.ArrayList]$RemoteHostArrayOfIPAddresses = @()
$IPv4AddressFamily = "InterNetwork"
$IPv6AddressFamily = "InterNetworkV6"
$ResolutionInfo = [System.Net.Dns]::GetHostEntry($HostNamePrep)
$ResolutionInfo.AddressList | Where-Object {
$_.AddressFamily -eq $IPv4AddressFamily
} | foreach {
if ($RemoteHostArrayOfIPAddresses -notcontains $_.IPAddressToString) {
$null = $RemoteHostArrayOfIPAddresses.Add($_.IPAddressToString)
}
}
}
catch {
Write-Verbose "Unable to resolve $HostNameOrIP when treated as a Host Name (as opposed to IP Address)!"
if ($HostNameOrIP -match "\.") {
try {
$HostNamePrep = $($HostNameOrIP -split "\.")[0]
Write-Verbose "Trying to resolve $HostNameOrIP using only HostName: $HostNamePrep!"
[System.Collections.ArrayList]$RemoteHostArrayOfIPAddresses = @()
$ResolutionInfo = [System.Net.Dns]::GetHostEntry($HostNamePrep)
$ResolutionInfo.AddressList | Where-Object {
$_.AddressFamily -eq $IPv4AddressFamily
} | foreach {
if ($RemoteHostArrayOfIPAddresses -notcontains $_.IPAddressToString) {
$null = $RemoteHostArrayOfIPAddresses.Add($_.IPAddressToString)
}
}
}
catch {
Write-Verbose "Unable to resolve $HostNamePrep!"
}
}
}
}
if (TestIsValidIPAddress -IPAddress $HostNameOrIP) {
try {
$HostIPPrep = $HostNameOrIP
[System.Collections.ArrayList]$RemoteHostArrayOfIPAddresses = @()
$null = $RemoteHostArrayOfIPAddresses.Add($HostIPPrep)
$ResolutionInfo = [System.Net.Dns]::GetHostEntry($HostIPPrep)
[System.Collections.ArrayList]$RemoteHostFQDNs = @()
$null = $RemoteHostFQDNs.Add($ResolutionInfo.HostName)
}
catch {
Write-Verbose "Unable to resolve $HostNameOrIP when treated as an IP Address (as opposed to Host Name)!"
}
}
if ($RemoteHostArrayOfIPAddresses.Count -eq 0) {
Write-Error "Unable to determine IP Address of $HostNameOrIP! Halting!"
$global:FunctionResult = "1"
return
}
# At this point, we have $RemoteHostArrayOfIPAddresses...
[System.Collections.ArrayList]$RemoteHostFQDNs = @()
foreach ($HostIP in $RemoteHostArrayOfIPAddresses) {
try {
$FQDNPrep = [System.Net.Dns]::GetHostEntry($HostIP).HostName
}
catch {
Write-Verbose "Unable to resolve $HostIP. No PTR Record? Please check your DNS config."
continue
}
if ($RemoteHostFQDNs -notcontains $FQDNPrep) {
$null = $RemoteHostFQDNs.Add($FQDNPrep)
}
}
if ($RemoteHostFQDNs.Count -eq 0) {
$null = $RemoteHostFQDNs.Add($ResolutionInfo.HostName)
}
[System.Collections.ArrayList]$HostNameList = @()
[System.Collections.ArrayList]$DomainList = @()
foreach ($fqdn in $RemoteHostFQDNs) {
$PeriodCheck = $($fqdn | Select-String -Pattern "\.").Matches.Success
if ($PeriodCheck) {
$HostName = $($fqdn -split "\.")[0]
$Domain = $($fqdn -split "\.")[1..$($($fqdn -split "\.").Count-1)] -join '.'
}
else {
$HostName = $fqdn
$Domain = "Unknown"
}
$null = $HostNameList.Add($HostName)
$null = $DomainList.Add($Domain)
}
if ($RemoteHostFQDNs[0] -eq $null -and $HostNameList[0] -eq $null -and $DomainList -eq "Unknown" -and $RemoteHostArrayOfIPAddresses) {
[System.Collections.ArrayList]$SuccessfullyPingedIPs = @()
# Test to see if we can reach the IP Addresses
foreach ($ip in $RemoteHostArrayOfIPAddresses) {
try {
$null = [System.Net.NetworkInformation.Ping]::new().Send($ip,1000)
$null = $SuccessfullyPingedIPs.Add($ip)
}
catch {
Write-Verbose "Unable to ping $ip..."
continue
}
}
}
$FQDNPrep = if ($RemoteHostFQDNs) {$RemoteHostFQDNs[0]} else {$null}
if ($FQDNPrep -match ',') {
$FQDN = $($FQDNPrep -split ',')[0]
}
else {
$FQDN = $FQDNPrep
}
$DomainPrep = if ($DomainList) {$DomainList[0]} else {$null}
if ($DomainPrep -match ',') {
$Domain = $($DomainPrep -split ',')[0]
}
else {
$Domain = $DomainPrep
}
$IPAddressList = [System.Collections.ArrayList]@($(if ($SuccessfullyPingedIPs) {$SuccessfullyPingedIPs} else {$RemoteHostArrayOfIPAddresses}))
$HName = if ($HostNameList) {$HostNameList[0].ToLowerInvariant()} else {$null}
if ($SuccessfullyPingedIPs.Count -eq 0 -and !$FQDN -and !$HostName -and !$Domain) {
Write-Error "Unable to resolve $HostNameOrIP! Halting!"
$global:FunctionResult = "1"
return
}
[pscustomobject]@{
IPAddressList = $IPAddressList
PingSuccess = $($SuccessfullyPingedIPs.Count -gt 0)
FQDN = $FQDN
HostName = $HName
Domain = $Domain
}
##### END Main Body #####
}
function Test-Port {
[CmdletBinding()]
Param(
[Parameter(Mandatory=$True)]
[string]$HostNameOrIP,
[Parameter(Mandatory=$True)]
[int]$Port
)
#region >> Main
if (!$(TestIsValidIPAddress -IPAddress $HostNameOrIP)) {
try {
$HostNameNetworkInfo = ResolveHost -HostNameOrIP $HostNameOrIP -ErrorAction Stop
}
catch {
Write-Error "Unable to resolve $HostName! Halting!"
$global:FunctionResult = "1"
return
}
$RHostIP = $HostNameNetworkInfo.IPAddressList[0]
}
else {
$RHostIP = $HostNameOrIP
}
$tcp = New-Object Net.Sockets.TcpClient
try {
$tcp.Connect($RHostIP, $Port)
}
catch {
Write-Warning $_.Exception.Message
}
if ($tcp.Connected) {
$tcp.Close()
$open = $true
}
else {
$open = $false
}
[pscustomobject]@{
Address = $RHostIP
Port = $Port
Open = $open
}
#endregion >> Main
}
# From: https://www.randomizedharmony.com/blog/2018/11/25/using-credentials-in-production-scripts
function ConvertFrom-CredentialFileToCredential {
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
[ValidateScript({ test-path $_ })]
[ValidateNotNullOrEmpty()]
[string]$Path
)
try {
$rawData = Get-Content $Path
$xmlstring = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR((($rawData | ConvertTo-SecureString))))
$type = [PSObject].Assembly.GetType('System.Management.Automation.Deserializer')
$ctor = $type.GetConstructor('instance,nonpublic', $null, @([xml.xmlreader]), $null)
$sr = New-Object System.IO.StringReader $xmlString
$xr = New-Object System.Xml.XmlTextReader $sr
$deserializer = $ctor.Invoke($xr)
$done = $type.GetMethod('Done', [System.Reflection.BindingFlags]'nonpublic,instance')
while (!$type.InvokeMember("Done", "InvokeMethod,NonPublic,Instance", $null, $deserializer, @())) {
try
{
$credentialData = $type.InvokeMember("Deserialize", "InvokeMethod,NonPublic,Instance", $null, $deserializer, @())
}
catch
{
Write-Warning "Could not deserialize ${string}: $_"
}
}
$xr.Close()
$sr.Dispose()
$encryptedPassword = $credentialData.password | ConvertTo-SecureString
New-Object System.Management.Automation.PSCredential($($credentialData.username), $($encryptedPassword))
}
catch {
Write-Error $_
return
}
}
# From: https://blog.ipswitch.com/how-to-build-a-logging-function-in-powershell
function Write-Log {
[CmdletBinding()]
param(
[Parameter()]
[ValidateNotNullOrEmpty()]
[string]$LogFileDirectory,
[Parameter()]
[ValidateNotNullOrEmpty()]
[string]$Message,
[Parameter()]
[ValidateNotNullOrEmpty()]
[ValidateSet('Information','Warning','Error')]
[string]$Severity = 'Information'
)
try {
$LogFileDirectory = (Resolve-Path $LogFilePath -ErrorAction Stop).Path
}
catch {
Write-Error $_
return
}
[pscustomobject]@{
Time = (Get-Date -f g)
Message = $Message
Severity = $Severity
} | Export-Csv -Path "$LogFileDirectory\CoralCheck_$(Get-Date -f MMddyy_hhmmss).csv" -Append -NoTypeInformation
}
#endregion >> Helper Functions
#region >> Additional Prep
$LogFileDir = "$HOME\CoralServerCheckLogs"
$PSCredentialFileLocation = $null
$UseBurntToast = $False
$CoralServerServiceName = "CoralSvc"
$IPOrFQDNofCoralServer = "192.168.2.40"
$PortsToTest = @(104,108)
$PortCheckIntervalInSeconds = 30
if (!$(Test-Path $LogFileDir)) {
$null = New-Item -ItemType Directory -Path $LogFileDir
}
if ($PSCredentialFileLocation) {
try {
$PSCredentialFileLocation = $(Resolve-Path $PSCredentialFileLocation -ErrorAction Stop).Path
}
catch {
Write-Error $_
return
}
$PSRemotingCredentials = ConvertFrom-CredentialFileToCredential -path $PSCredentialFileLocation
}
if ($UseBurntToast -and [Environment]::OSVersion.Version.Major -ge 10) {
try {
if (!$(Get-Module -ListAvailable BurntToast)) {Install-Module BurntToast}
if (!$(Get-Module BurntToast)) {Import-Module BurntToast}
}
catch {
Write-Verbose "Problem with installing the BurntToast Module! Skipping..."
}
}
#endregion >> Additional Prep
#region >> Main
while ($True) {
[System.Collections.Generic.List[PSObject]]$PortTestResults = @()
foreach ($PortNum in $PortsToTest) {
$TestResult = Test-Port -HostNameOrIP $IPOrFQDNofCoralServer -Port $PortNum
$null = $PortTestResults.Add($TestResult)
}
if ($PortTestResults.Open -contains $False) {
$PortsThatAreClosed = $($PortTestResults | Where-Object {$_.Open -eq $False}).Port
$ClosedPortsCommaSeparated = $PortsThatAreClosed -join ', '
$null = Write-Log -LogFileDirectory $LogFileDir -Message "Coral Server port(s) $ClosedPortsCommaSeparated appear to be closed!" -Severity "Warning"
if ($UseBurntToast -and [Environment]::OSVersion.Version.Major -ge 10) {
$NewBTMsgSplatParams = @{
Text = @("Coral Server port(s) $ClosedPortsCommaSeparated appear to be closed! Restarting $CoralServerServiceName")
Button = New-BTButton -Dismiss
}
New-BurntToastNotification @NewBTMsgSplatParams
}
try {
$CoralServerNetworkInfo = ResolveHost -HostNameOrIP $IPOrFQDNofCoralServer -ErrorAction Stop
}
catch {
if (TestIsValidIPAddress $IPOrFQDNofCoralServer) {
if ($(Get-NetIPAddress -AddressFamily IPv4).IPAddress -contains $IPOrFQDNofCoralServer) {
try {
$null = Write-Log -LogFileDirectory $LogFileDir -Message "Restarting $CoralServerServiceName..." -Severity "Information"
Restart-Service $CoralServerServiceName -ErrorAction Stop
}
catch {
Write-Error $_
}
}
}
elseif (@($($IPOrFQDNofCoralServer -split '\.'))[0] -eq $env:ComputerName) {
try {
$null = Write-Log -LogFileDirectory $LogFileDir -Message "Restarting $CoralServerServiceName..." -Severity "Information"
Restart-Service $CoralServerServiceName -ErrorAction Stop
}
catch {
Write-Error $_
}
}
else {
Write-Error "Unable to resolve $IPOrFQDNOfCoralServer! Halting!"
$global:FunctionResult = "1"
return
}
}
if ($CoralServerNetworkInfo.HostName -eq $env:ComputerName) {
try {
$null = Write-Log -LogFileDirectory $LogFileDir -Message "Restarting $CoralServerServiceName..." -Severity "Information"
Restart-Service $CoralServerServiceName -ErrorAction Stop
}
catch {
Write-Error $_
}
}
else {
$InvCmdSplatParams = @{
ComputerName = $CoralServerNetworkInfo.FQDN
Scriptblock = {Restart-Service $using:CoralServerServiceName}
ErrorAction = "Stop"
}
if ($PSRemotingCredentials) {
$InvCmdSplatParams.Add("Credential",$PSRemotingCredentials)
}
try {
$null = Write-Log -LogFileDirectory $LogFileDir -Message "Restarting $CoralServerServiceName on Remote Host $($CoralServerNetworkInfo.FQDN)..." -Severity "Information"
Invoke-Command @InvCmdSplatParams
}
catch {
Write-Error $_
$global:FunctionResult = "1"
return
}
}
}
Start-Sleep -Seconds $PortCheckIntervalInSeconds
}
#endregion >> Main
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment