On Windows 8 & 2012, there’s this nifty function named Get-NetTCPConnection that is useful to verify port connection statuses of remote servers. Unfortunately, older servers such as 2008 or 2008 R2 will not have access to this utility. Here’s the evidence:
PS C:\Users\kimconnect> Get-NetTCPConnection | ? {$_.State -eq "Listen"}
Get-NetTCPConnection : The term 'Get-NetTCPConnection' is not recognized as the name of a cmdlet, function, script
file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct
and try again.
At line:1 char:1
+ Get-NetTCPConnection | ? {$_.State -eq "Listen"}
+ ~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (Get-NetTCPConnection:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
Luckily, Google has brought you to the right place. Here’s a workaround with a feature enhancement of checking remote servers for your dinosaur PCs and EOL’ing servers (January 14, 2020 for Windows 7/2008). The funky function I’m scribbling is called “Check-TcpConnection.” Yeah, my creativity in naming things could use a little boost.
# Dynamic Credential
$who = whoami
if ($who.substring($who.length-6, 6) -eq "-admin"){$username=$who;}
else {$username=$who+"-admin";}
$password = Read-Host -Prompt "Input the password for account $username" -AsSecureString
$cred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $username,$password #To be Invoked with switch -Credential
function Check-TcpConnection {
[CmdletBinding ()]
Param (
[Parameter (Position = 0)]
[string]$Server = "localhost",
[Parameter (Position = 1)]
[int[]]
$Port = 443, #initilize variable and set default value to be overridden
[Parameter (Position = 2)] #Set argument to only accept values from the below validation list
[ValidateSet (
'Established',
'CloseWait',
'TimeWait',
'Synsent',
'Synrecv',
'Finwait1',
'Finwait2',
'Close',
'Lastack',
'Listen',
'Closing',
'Unknown'
)]
[string[]]
$State = @('Established','CloseWait','TimeWait','Synsent','Synrecv','Finwait1','Finwait2','Close','Lastack','Listen','Closing','Unknown') #initilize variable as array
)
$elevate = New-PSSession -ComputerName $Server -Credential $cred
# Local function
function TcpConnection ($Ports,$States) {
<# Check the current host for connection with these statuses
ESTABLISHED
The socket has an established connection.
SYN_SENT
The socket is actively attempting to establish a connection.
SYN_RECV
A connection request has been received from the network.
FIN_WAIT1
The socket is closed, and the connection is shutting down.
FIN_WAIT2
Connection is closed, and the socket is waiting for a shutdown
from the remote end.
TIME_WAIT
The socket is waiting after close to handle packets still in the
network.
CLOSE The socket is not being used.
CLOSE_WAIT
The remote end has shut down, waiting for the socket to close.
LAST_ACK
The remote end has shut down, and the socket is closed. Waiting
for acknowledgement.
LISTEN The socket is listening for incoming connections. Such sockets
are not included in the output unless you specify the
--listening (-l) or --all (-a) option.
CLOSING
Both sockets are shut down but we still don't have all our data
sent.
UNKNOWN
The state of the socket is unknown.
#>
process{
# standardize state values to an array of lowercased strings
$States = @($States).ForEach({$_.ToLower()})
@([System.Net.NetworkInformation.IPGlobalProperties]::GetIPGlobalProperties().
GetActiveTcpConnections()).
Where({
# include only local EndPoint items
$_.LocalEndPoint.Address -ne $_.RemoteEndPoint.Address -and
$_.State.ToString().ToLower() -in $States -and
$_.LocalEndPoint.Port -in $Ports;
})
}
} # end local function
Invoke-Command -Session $elevate -ScriptBlock {
param( $x, $y, $importedFunc)
# Import the function from the variable inside parameters
[ScriptBlock]::Create($importedFunc).Invoke($x,$y)
} -ArgumentList $Port, $State, ${function:TcpConnection}
}
Check-TcpConnection -server SERVER007 -port 808
Sample output:
PS U:\> C:\scripts\check-tcpconnection.ps1
PSComputerName : SERVER007
RunspaceId : 2179dbe0-d2a1-42cd-a36e-a8995be996ff
State : TimeWait
LocalEndPoint : 192.168.1.129:808
RemoteEndPoint : 192.168.1.124:51385
PSComputerName : SERVER007
RunspaceId : 2179dbe0-d2a1-42cd-a36e-a8995be996ff
State : TimeWait
LocalEndPoint : 192.168.1.129:808
RemoteEndPoint : 192.168.1.124:51386
PSComputerName : SERVER007
RunspaceId : 2179dbe0-d2a1-42cd-a36e-a8995be996ff
State : TimeWait
LocalEndPoint : 192.168.1.129:808
RemoteEndPoint : 192.168.1.124:51387
PSComputerName : SERVER007
RunspaceId : 2179dbe0-d2a1-42cd-a36e-a8995be996ff
State : TimeWait
LocalEndPoint : 192.168.1.129:808
RemoteEndPoint : 192.168.1.124:51388
PSComputerName : SERVER007
RunspaceId : 2179dbe0-d2a1-42cd-a36e-a8995be996ff
State : TimeWait
LocalEndPoint : 192.168.1.129:808
RemoteEndPoint : 192.168.1.124:51389
Explanation:
TCP/IP connections have a hold-down timer that prevents sessions from being closed immediately; hence, DDoS works because of this. Packets may be stateless, meaning that they can arrive out of order and be reorganized at the destination, or be re-transmitted.
CLOSE_WAIT is when the remote endpoint (other side of the connection) has closed the connection.
TIME_WAIT indicates that local endpoint (this side) has closed the connection. The session is being on standby so that any delayed packets can be matched to the connection and handled appropriately. The connections will be removed when they time out within the default timer of 4 minutes.
CONNECTED indicates connected. Yup, I’m 100% certain about this.