In today’s digital landscape, quickly understanding what’s happening behind the scenes on an individual machine can be crucial. Introducing ConnArtist, a streamlined, intuitive PowerShell script designed specifically for monitoring network connections on a single endpoint—ideal for security checks or diagnostic tasks without needing heavyweight tools like Wireshark.
What is ConnArtist?
ConnArtist is a simple yet powerful PowerShell-based network monitoring tool built specifically for single endpoints. Perfect for quick checks by security analysts, sysadmins, or tech support, ConnArtist helps you swiftly identify unexpected or problematic network activity.
With ConnArtist, you can:
- Log active TCP connections along with the responsible processes.
- Optionally capture DNS queries made by the endpoint.
- Filter out local (private) IP traffic for concise logs.
- Continuously monitor and prevent redundant logging through smart duplicate detection.
How Does ConnArtist Work?
Here’s how it operates:
Initialization
The script prompts two straightforward questions:
- Whether to filter local (private IP) traffic.
- Whether to capture DNS queries.
Based on your responses, ConnArtist adjusts its monitoring appropriately.
Active Monitoring
ConnArtist continuously:
- Logs active TCP connections, including detailed metadata (time, process, remote address, remote host).
- Optionally logs DNS queries, capturing query names and timestamps.
- Avoids duplicate entries by maintaining internal tracking.
Clear Logging
Data captured is neatly formatted and stored locally:
- TCP connections logged to
tcp_log.txt
. - DNS queries stored in
dns_log.txt
.
Implementing ConnArtist
Step 1: Preparation
- Save the provided PowerShell script as
ConnArtist.ps1
. - Ensure you have permissions to write logs (
C:UsersPublic
).
Step 2: Execution
-
Run PowerShell as Administrator.
-
Execute the script:
powershell.exe -ExecutionPolicy Bypass -File "C:PathToConnArtist.ps1"
-
Answer prompts regarding local traffic filtering and DNS capture based on your use-case.
Step 3: Continuous Monitoring
- ConnArtist monitors the network every 5 seconds, providing real-time insights.
- Press
Ctrl+C
to stop monitoring at any time.
Example Use Cases
- Security Checks: Quickly identify unexpected external connections that could indicate malware or unauthorized activity.
- Diagnostic Tasks: Troubleshoot connectivity issues by pinpointing problematic connections or DNS resolutions.
Customizing ConnArtist
Adjust log locations or intervals as needed:
$tcpLogFile = "C:UsersPublictcp_log.txt"
$dnsLogFile = "C:UsersPublicdns_log.txt"
# Modify monitoring interval as desired
Start-Sleep -Seconds 5
Adjusting Local Network Filtering
For accurate filtering, you might need to customize your local network’s private IP ranges. Modify the following function to match your network’s octets:
function IsPrivateIP($ipAddress) {
try {
$ip = [System.Net.IPAddress]::Parse($ipAddress)
if ($ip.AddressFamily -eq 'InterNetwork') { # IPv4
return ($ipAddress -like '10.*' -or
$ipAddress -like '172.16.*' -or
$ipAddress -like '192.168.*') # Modify these octets to your local network range
} elseif ($ip.AddressFamily -eq 'InterNetworkV6') { # IPv6
return ($ip.IsIPv6LinkLocal -or $ip.IsIPv6SiteLocal)
} else {
return $false
}
} catch {
return $false
}
}
Why Use ConnArtist?
- Lightweight: No installations or complex setups required.
- Clear Insights: Straightforward, easily readable logs.
- Focused: Designed for pinpoint checks on single endpoints.
- Real-time Monitoring: Quick detection of unusual activities or connection issues.
ConnArtist simplifies endpoint network visibility, allowing quick identification of potential security concerns or troubleshooting network issues swiftly and effectively.
Happy Monitoring!
#Another /_[]_/
# fine |] _||_ [|
# ___ / || /
# /___ ||
# (|0 0|) ||
# __/{U/}_ ___/vvv
# / {~} / _|_P|
# | / ~ /_/ []
# |_| (____)
# _]/______ Barberion
# __||_/_ Production
# (_,_||_,_)
#
# Define log file paths for TCP and DNS logs
$tcpLogFile = "C:UsersPublictcp_log.txt"
$dnsLogFile = "C:UsersPublicdns_log.txt"
# Function to check if an IP address is private
function IsPrivateIP($ipAddress) {
try {
$ip = [System.Net.IPAddress]::Parse($ipAddress)
if ($ip.AddressFamily -eq 'InterNetwork') { # IPv4
return ($ipAddress -like '10.*' -or
$ipAddress -like '172.16.*' -or
$ipAddress -like '192.168.*')
} elseif ($ip.AddressFamily -eq 'InterNetworkV6') { # IPv6
return ($ip.IsIPv6LinkLocal -or $ip.IsIPv6SiteLocal)
} else {
return $false
}
} catch {
return $false
}
}
# Ask the user if they want to filter out local traffic
$filterPrivateIPs = (Read-Host "Do you want to filter out local traffic? (yes/no)").Trim().ToLower()
$filterPrivate = $filterPrivateIPs -eq 'yes' -or $filterPrivateIPs -eq 'y'
# Ask the user if they want to capture DNS requests
$dnsCaptureInput = (Read-Host "Do you want to capture DNS requests? (yes/no)").Trim().ToLower()
$captureDNS = $dnsCaptureInput -eq 'yes' -or $dnsCaptureInput -eq 'y'
# Output the monitoring message at the top
Write-Host "Monitoring network connections. Press Ctrl+C to stop."
Add-Content -Path $tcpLogFile -Value "Monitoring TCP connections. Press Ctrl+C to stop."
Add-Content -Path $dnsLogFile -Value "Monitoring DNS connections. Press Ctrl+C to stop."
# Define the headers
$tcpHeader = "{0,-20} {1,-20} {2,-25} {3}" -f "Date/Time", "Process", "Remote Address", "Remote Host"
$dnsHeader = "{0,-20} {1,-30}" -f "Date/Time", "DNS Query"
Write-Host $tcpHeader
Write-Host ("-" * 90)
Add-Content -Path $tcpLogFile -Value $tcpHeader
Add-Content -Path $tcpLogFile -Value ("-" * 90)
if ($captureDNS) {
$dnsLogName = "Microsoft-Windows-DNS-Client/Operational"
if (-not (Get-WinEvent -ListLog $dnsLogName).IsEnabled) {
Write-Host "Enabling DNS client operational log..."
try {
wevtutil sl $dnsLogName /e:true
} catch {
Write-Host "Failed to enable DNS client operational log. You may need to run PowerShell as Administrator."
$captureDNS = $false
}
}
if ($captureDNS) {
# Initialize the last DNS check time
$lastDNSCheckTime = Get-Date
# Output the DNS header
Write-Host $dnsHeader
Write-Host ("-" * 50)
Add-Content -Path $dnsLogFile -Value $dnsHeader
Add-Content -Path $dnsLogFile -Value ("-" * 50)
}
}
# To prevent duplication, maintain hashsets of logged connections and DNS queries
$loggedConnections = @{}
$loggedDNSQueries = @{}
while ($true) {
# Get current network connections
$currentConnections = Get-NetTCPConnection -State Established
if ($filterPrivate) {
$currentConnections = $currentConnections | Where-Object {
$_.RemoteAddress -ne '127.0.0.1' -and
$_.RemoteAddress -ne '::1'
}
}
foreach ($conn in $currentConnections) {
$connectionKey = "$($conn.OwningProcess)|$($conn.RemoteAddress):$($conn.RemotePort)"
if (-not $loggedConnections.ContainsKey($connectionKey)) {
if (-not $filterPrivate -or (-not (IsPrivateIP $conn.RemoteAddress))) {
$dateTime = Get-Date -Format 'yyyy-MM-dd HH:mm:ss'
$process = Get-Process -Id $conn.OwningProcess -ErrorAction SilentlyContinue
$processName = if ($process) { $process.ProcessName } else { 'N/A' }
$remoteHost = $conn.RemoteAddress
try {
$dnsEntry = [System.Net.Dns]::GetHostEntry($conn.RemoteAddress)
$remoteHost = $dnsEntry.HostName
} catch {
# Could not resolve host
}
$remoteAddressPort = "$($conn.RemoteAddress):$($conn.RemotePort)"
$logEntry = "TCP {0,-20} {1,-20} {2,-25} {3}" -f $dateTime, $processName, $remoteAddressPort, $remoteHost
Add-Content -Path $tcpLogFile -Value $logEntry
Write-Host $logEntry
# Add the connection to the loggedConnections hashset to prevent future duplicates
$loggedConnections[$connectionKey] = $true
}
}
}
if ($captureDNS) {
try {
# Get new DNS query events
$dnsEvents = Get-WinEvent -FilterHashtable @{
LogName = 'Microsoft-Windows-DNS-Client/Operational';
Id = 3008;
StartTime = $lastDNSCheckTime
} -ErrorAction SilentlyContinue
if ($dnsEvents) {
foreach ($event in $dnsEvents) {
$dateTime = $event.TimeCreated.ToString('yyyy-MM-dd HH:mm:ss')
$queryName = $event.Properties[0].Value
if (-not $loggedDNSQueries.ContainsKey($queryName)) {
$dnsEntry = "DNS {0,-20} {1,-30}" -f $dateTime, $queryName
Add-Content -Path $dnsLogFile -Value $dnsEntry
Write-Host $dnsEntry
# Add the DNS query to the loggedDNSQueries hashset to prevent future duplicates
$loggedDNSQueries[$queryName] = $true
}
}
# Update the last DNS check time
$lastDNSCheckTime = Get-Date
}
} catch {
# Suppress any errors related to DNS event fetching
}
}
Start-Sleep -Seconds 5
}