Skip to content

Instantly share code, notes, and snippets.

@dindoliboon
Last active December 6, 2020 23:55
Show Gist options
  • Select an option

  • Save dindoliboon/32d9aa78842d33359c5ce624c570ca96 to your computer and use it in GitHub Desktop.

Select an option

Save dindoliboon/32d9aa78842d33359c5ce624c570ca96 to your computer and use it in GitHub Desktop.
PowerShell library for performing geo IP lookups.
<#
PowerShell library for performing geo IP lookups.
Requirements:
- PowerShell 7.0.0 or Windows PowerShell 5.1.18362.628
https://github.com/PowerShell/PowerShell/releases
- nuget 5.4.0.6315
Invoke-WebRequest -Uri 'https://dist.nuget.org/win-x86-commandline/latest/nuget.exe' -OutFile (Join-Path -Path ([Environment]::GetFolderPath('UserProfile')) -ChildPath 'Downloads\nuget.exe')
- MaxMind.DB 2.6.1 nuget package
Install the nuget package on Windows:
& (Join-Path -Path ([Environment]::GetFolderPath('UserProfile')) -ChildPath 'Downloads\nuget.exe') Install MaxMind.Db -Version 2.6.1 -OutputDirectory (Join-Path -Path ([Environment]::GetFolderPath('UserProfile')) -ChildPath 'Downloads\.nuget')
Install the nuget package on macOS with mono:
& mono (Join-Path -Path ([Environment]::GetFolderPath('UserProfile')) -ChildPath 'Downloads\nuget.exe') Install MaxMind.Db -Version 2.6.1 -OutputDirectory (Join-Path -Path ([Environment]::GetFolderPath('UserProfile')) -ChildPath 'Downloads\.nuget')
- GeoLite2 City and Country binary databases
Requires free registration to download.
https://www.maxmind.com
Installation:
- You may need to change your execution policy to import unsigned modules.
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
- Download the module:
Invoke-WebRequest -Uri 'https://gist.githubusercontent.com/dindoliboon/32d9aa78842d33359c5ce624c570ca96/raw/libMaxMindGeoIp2V1.psm1' -OutFile (Join-Path -Path ([Environment]::GetFolderPath('UserProfile')) -ChildPath 'Downloads\libMaxMindGeoIp2V1.psm1')
- Import the module:
Import-Module -Name (Join-Path -Path ([Environment]::GetFolderPath('UserProfile')) -ChildPath 'Downloads\libMaxMindGeoIp2V1.psm1')
#>
New-Module -Name libMaxMindGeoIp2V1 -ScriptBlock {
function New-GeoIp2Reader {
param (
$Library,
$Database
)
Add-Type -Path $Library | Out-Null
return [MaxMind.Db.Reader]::new($Database)
}
function Close-GeoIp2Reader {
param (
[ref]$Reader
)
$Reader.Value.Dispose()
$Reader.Value = $null
}
function Find-GeoIp2 {
param (
$Reader,
$IpAddress,
$Library,
$Database
)
$results = $null
$useInternalReader = $Reader -eq $null -and $Library -ne $null -and $Database -ne $null
$ip = [System.Net.IPAddress]$IpAddress
if ($useInternalReader) {
$Reader = New-GeoIp2Reader -Library $Library -Database $Database
}
if ($Reader) {
# Use the first Find method and tell it to return type Dictionary<string, object>.
$oldMethod = ($Reader.GetType().GetMethods() |? {$_.Name -eq 'Find'})[0]
$newMethod = $oldMethod.MakeGenericMethod(@([System.Collections.Generic.Dictionary`2[System.String,System.Object]]))
# Call our new method, T Find[T](ipaddress ipAddress, MaxMind.Db.InjectableValues injectables)
$results = $newMethod.Invoke($Reader, @($ip, $null))
if ($useInternalReader) {
Close-GeoIp2Reader -Reader ([ref]$Reader)
}
}
else {
throw 'MaxMind.Db.Reader not defined.'
}
return $results
}
Export-ModuleMember -Function 'New-GeoIp2Reader', 'Find-GeoIp2', 'Close-GeoIp2Reader'
}
@dindoliboon

dindoliboon commented Jul 13, 2018

Copy link
Copy Markdown
Author
# Perform an IP lookup of multiple IPs using the country database.
# Database reader is kept open until manually closed.

Import-Module -Name (Join-Path -Path ([Environment]::GetFolderPath('UserProfile')) -ChildPath 'Downloads\libMaxMindGeoIp2V1.psm1')

if ($PSVersionTable.PSEdition -eq 'Desktop') {
    $maxMindDbDll = Join-Path -Path ([Environment]::GetFolderPath('UserProfile')) -ChildPath '.nuget\packages\maxmind.db\2.6.1\lib\net45\MaxMind.Db.dll'
} else {
    $maxMindDbDll = Join-Path -Path ([Environment]::GetFolderPath('UserProfile')) -ChildPath '.nuget\packages\maxmind.db\2.6.1\lib\netstandard2.1\MaxMind.Db.dll'
}

$ipDbCountry = Join-Path -Path ([Environment]::GetFolderPath('UserProfile')) -ChildPath 'Downloads\GeoLite2-Country_20200317\GeoLite2-Country.mmdb'

$reader = New-GeoIp2Reader -Library $maxMindDbDll -Database $ipDbCountry
Find-GeoIp2 -Reader $reader -IpAddress '8.8.8.8' | ConvertTo-Json -Depth 5
Find-GeoIp2 -Reader $reader -IpAddress '8.8.4.4' | ConvertTo-Json -Depth 5
Find-GeoIp2 -Reader $reader -IpAddress '1.2.3.4' | ConvertTo-Json -Depth 5
Close-GeoIp2Reader -Reader ([ref]$reader)

@myjjuliet

Copy link
Copy Markdown

Hello,
Thanks for sharing the code.

I have one question.
There may be an error when adding a dll through add-type.

Add-Type : Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information.
At line:5 char:1

  • Add-Type -Path $ Library
  •   + CategoryInfo          : NotSpecified: (:) [Add-Type], ReflectionTypeLoadException
      + FullyQualifiedErrorId : System.Reflection.ReflectionTypeLoadException,Microsoft.PowerShell.Commands.AddTypeCommand 
    
    

Some servers work fine, but some servers get errors I can't find the difference.

So instead of add-type I use [System.Reflection.Assembly]::LoadFrom($Library)
I've tried it, but I get an error in the return [MaxMind.Db.Reader]::new($database) part.

@myjjuliet

Copy link
Copy Markdown

The problem occurs only in the powershell-core version or running powershell as an administrator account.

Any problems can you help me?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment