Skip to content

Instantly share code, notes, and snippets.

@dindoliboon
Last active December 6, 2020 23:55
Show Gist options
  • Save dindoliboon/32d9aa78842d33359c5ce624c570ca96 to your computer and use it in GitHub Desktop.
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
Copy link
Author

dindoliboon commented Jul 13, 2018

# Perform an IP lookup using the city database.
# Performs a single lookup, then closes the database reader.

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'
}

$ipDbCity = Join-Path -Path ([Environment]::GetFolderPath('UserProfile')) -ChildPath 'Downloads\GeoLite2-City_20200317\GeoLite2-City.mmdb'

Find-GeoIp2 -Library $maxMindDbDll -Database $ipDbCity -IpAddress '8.8.8.8' | ConvertTo-Json -Depth 5

@dindoliboon
Copy link
Author

dindoliboon commented Jul 13, 2018

# 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

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

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