Powershell

PowerShell IP Geolocation based on State

PowerShell IP Geolocation based on State. Learn how to setup IPstack API in PowerShell and alert based on State specific connections

Highlights

  • I wanted to add the IP geolocation to my IP address checks that I am making so I could then use the details gathered from an IP geolocation check to hone in on more specifics of where RDP traffic is coming from.
  • However, if it is from a state I don’t expect, I will get both an email and a page out (just email to text address provided by carrier).
  • I had an outside box that even with the other security measures in place, I wanted to have a way to see who is connected and which IP address they are coming from.

I have been revisiting a few things in the lab environment, including monitoring and other alerting that I have had set for a while. I had an outside box that even with the other security measures in place, I wanted to have a way to see who is connected and which IP address they are coming from. I wanted to add the IP geolocation to my IP address checks that I am making so I could then use the details gathered from an IP geolocation check to hone in on more specifics of where RDP traffic is coming from. In most modern firewalls, most geolocation checks are country-based. In the United States, let’s see how we can use an API call, PowerShell and filtering on the PowerShell return to form logic around not only the Country, but also the State. Let’s look at PowerShell IP Geolocation based on State.

IPstack IP Geolocation API

There is a service that works great for performing IP geolocation checks using an API. You can use this in your PowerShell scripts to make a call to the API check the geolocation information and return the results as XML, JSON, etc. The IPstack IP geolocation API allows you to make 5000 calls to their API a month. For moderately sized businesses this wouldn’t be enough, however, for home labs, testing, and other use cases, it works great.

Sign up for the IPstack account. No payment information is requested during the sign up which is also another great aspect of the service.

Sign up for a free ipstack account to hit their API for IP geolocation
Sign up for a free ipstack account to hit their API for IP geolocation

Once you have your account, you will be provided an API key to work with to perform lookups that hit their API.

PowerShell cmdlets for gathering network information

You can use the get-nettcpconnection to gather network connection information much like netstat. What I like about the cmdlet as opposed to netstat is that you can do all of the great things with the returns due to PowerShell’s object-based approach. It is a lot easier to work with than trying to find strings and use information from the netstat return.

How can you display the remote IP of a remote client connected to a terminal server/workstation? You can use the following

get-nettcpconnection | where-object {$_.LocalPort -like "3389" -and $_.LocalAddress -ne "::" -and $_.LocalAddress -ne "0.0.0.0"} | select-object -expandproperty RemoteAddress

That’s it. Once you have the remote IP address, you can then pass this information into the ipstack API using PowerShell and get a return on the IP address. Below is an example of the returned output coming back from ipstack. It tells you the:

  • ip
  • type
  • continent_code
  • continent_name
  • country_code
  • country_name
  • region_name
  • region_code
  • region_name
  • city
  • zip
  • latitude
  • longitude
  • location
Information returned from IPstack using the IP geolocation API
Information returned from IPstack using the IP geolocation API

Once you get this information back, you can then select the properties you want to key off of, like the following:

$region = Invoke-RestMethod -Uri "http://api.ipstack.com/$ip$access_key" | select -expandproperty region_code

For the United States, the region_code refers to the State. So, let’s see how we can use this in a script. Below is the rough version of the script I have put together that works. Essentially, if someone connects from the state that I expect to be connected from, I will just get an email with the details of the connection. However, if it is from a state I don’t expect, I will get both an email and a page out (just email to text address provided by carrier).

##Variables

$ip = get-nettcpconnection | where-object {$_.LocalPort -like "3389" -and $_.LocalAddress -ne "::" -and $_.LocalAddress -ne "0.0.0.0"} | select-object -expandproperty RemoteAddress
$access_key = "?access_key=<yourkeygoes here>"
$region = Invoke-RestMethod -Uri "http://api.ipstack.com/$ip$access_key" | select -expandproperty region_code

##Email Alert variables

$SMTPServer = "<your mail server"
$SMTPPort = "587"
$Username = "<your username"
$Password = "<password>"
$to_email = "<recipient email>"
$to_page = "<page email""

##Checking IP and Email alert

Invoke-RestMethod -Uri "http://api.ipstack.com/$ip$access_key" | out-file alldetails.txt


if ($region -eq "CA") {

$message = New-Object System.Net.Mail.MailMessage
$message.subject = "$ip has connected"
$message.body = (Get-Content alldetails.txt) -join "`n" 
$message.to.add($to_email)
$message.from = $username

$smtp = New-Object System.Net.Mail.SmtpClient($SMTPServer, $SMTPPort);
$smtp.EnableSSL = $true
$smtp.Credentials = New-Object System.Net.NetworkCredential($Username, $Password);

$smtp.send($message)
write-host "Mail Sent"

}

if ($region -ne "CA") {



$message = New-Object System.Net.Mail.MailMessage
$message.subject = "$ip has connected"
$message.body = (Get-Content alldetails.txt) -join "`n"
$message.to.add("$to_page,$to_email")
$message.from = $username

$smtp = New-Object System.Net.Mail.SmtpClient($SMTPServer, $SMTPPort);
$smtp.EnableSSL = $true
$smtp.Credentials = New-Object System.Net.NetworkCredential($Username, $Password);

$smtp.send($message)
write-host "Mail Sent"

}



Where does this go?

You can add this script to fire off on a system event in your scheduled tasks. I have long used log on and reconnect events to trigger scripts to run. This is where you can place the script and it fires off when the event specified is noted. I have written about this in a previous blog post that you can read through here:

There is a lot of room to add additional functionality here. In the next version of the script, I would like to add the functionality of an RD filtering type solution where if it is not coming from the state I expect, it will be added to a Windows firewall rule upon connecting, on top of the notification received.

Wrapping up

The great thing about PowerShell is that generally real-world use cases are what cause scripts to be born. I have had a need recently to revisit my security on the edge on top of things I am already doing. You can never have too much visibility into who is connecting to your network resources, even if you have additional security measures in place such as firewall rules, third-party brute force type tools, etc.

Subscribe to VirtualizationHowto via Email 🔔

Enter your email address to subscribe to this blog and receive notifications of new posts by email.

Brandon Lee

Brandon Lee is the Senior Writer, Engineer and owner at Virtualizationhowto.com and has over two decades of experience in Information Technology. Having worked for numerous Fortune 500 companies as well as in various industries, Brandon has extensive experience in various IT segments and is a strong advocate for open source technologies. Brandon holds many industry certifications, loves the outdoors and spending time with family.

Related Articles

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.