Conduct DNS Leak Test on VPN via PureBasic and Powershell

Share your advanced PureBasic knowledge/code with the community.
smacker
User
User
Posts: 55
Joined: Thu Nov 06, 2014 7:18 pm

Conduct DNS Leak Test on VPN via PureBasic and Powershell

Post by smacker »

If you are using a VPN service with a software client, e.g. PrivateInternetAccess, one of the important things you need to do is make sure your real ISP DNS address is not disclosed. Most VPN software services software provide a VPN DNS to use or some sort of DNS leak prevention.

A DNS leak refers to a security flaw that allows DNS requests to be revealed to ISP DNS servers, despite the use of a VPN service to attempt to conceal them.

A lot of people use one of the many web sites available to test with, e.g https://ipleak.net/ or https://www.dnsleaktest.com/ etc.... but this test can be conducted from your computer if you wish in a command prompt or via powershell. There is a command prompt method available for windows, Mac, Linux but I'm going to just touch on the use of purebasic and powershell here.

In a dns leak test the object is to have the VPN provided public IP address match that of the VPN dns query IP address. If the VPN public IP matches your returned DNS address there is no DNS leak. For example, VPN public IP is 1.2.3.4 and your detected DNS address is 1.2.3.4 then no DNS leak exists, if they do not match then you have a dns leak.

To do the dns leak test from your computer you need a recursive server that will return the dns query address and not your public IP address. I've used such servers in the below windows code using purebasic and powershell (tested on Windows 10)

Code: Select all

Procedure.s GetDnsLeakTest()
  
  a$ = "$pipsA = @('http://ipv4.whatismyip.akamai.com','http://myip.dnsomatic.com','http://icanhazip.com');"
  b$ = "For ($i=0; $i -lt $pipsA.Length; $i++) {;"
  c$ = "$pubip = ((Invoke-WebRequest -Uri $pipsA[$i] –UseBasicParsing -DisableKeepAlive -TimeoutSec 8).Content).Trim();"
  d$ = "If ([bool][ipaddress] $pubip -eq $true) {Break} }; If ($i -eq 2 -And [bool][ipaddress] $pubip -ne $true) {;"
  e$ = "$pubip = ((Invoke-RestMethod -Uri 'https://api.ipify.org?format=json').ip).Trim() }; $pubip = $pubip.Trim();"
  f$ = "$x = 0; $rnuma = -join (%{ [char[]] (48..57 + 65..90 + 97..122) | Get-Random -count 40});"
  g$ = "$rdns = @('whoami.ds.akahelp.net','whoami.ultradns.net','whoami.cryptostorm.is', 'whoami.v4.powerdns.org',"
  h$ = "'resolver.dnscrypt.info', 'whoami.lua.powerdns.org', 'whoami.cloudflare.com', 'o-o.myaddr.l.google.com');"
  i$ = "For ($i=0; $i -lt $rdns.Length; $i++) {$ips = $null;"
  j$ = "If ($i -eq 0) {$ips = (Resolve-DnsName $rdns[$i] -QuickTimeout -Type txt).Strings[1].Trim()};"
  k$ = "If ($i -In 1..4 -eq $true) {$ips = ((Resolve-DnsName $rdns[$i] -QuickTimeout -Type A).IPAddress).Trim()};"
  l$ = "If ($i -In 5..7 -eq $true) {$ips = (Resolve-DnsName $rdns[$i] -QuickTimeout -Type txt).Strings[0].Trim()};"
  m$ = "$isipfour = [bool][ipaddress] $ips; If ($isipfour -eq 'True' -And $ips -ne $pubip) {Return 'Warning! DNS Address Leak = ' +  $ips};"
  n$ = "If ($isipfour -eq 'True' -And $ips -eq $pubip) {$x++} }; If ($x -eq 0) {Return 'NoResource'} Else {Return 'NoLeak'}"
  
  cmdx$ = "$ErrorActionPreference = 'SilentlyContinue';" + a$ + b$ + c$ + d$ + e$ + f$ + g$ + h$ + i$ + j$ + k$ +l$ + m$ + n$
  
  OutCmd$ = ""
  KeepOutCmd$ = ""
  CmdPromptRun = RunProgram("powershell.exe", cmdx$,"", #PB_Program_Hide|#PB_Program_Open|#PB_Program_Read)
  If CmdPromptRun
    While ProgramRunning(CmdPromptRun)
      OutCmd$=ReadProgramString(CmdPromptRun)
      KeepOutCmd$ = KeepOutCmd$ + OutCmd$
    Wend
    CloseProgram(CmdPromptRun)
  EndIf
  
  chkret$ = Trim(KeepOutCmd$)
  
  If CountString(chkret$, "Exception") > 0 Or CountString(chkret$, "FullyQualifiedErrorId") > 0
    ProcedureReturn "Warning! DNS Leak Test Not Conducted"
  EndIf
    
  If CountString(chkret$, "Warning! DNS Address Leak =") > 0
    ProcedureReturn chkret$
  EndIf
  
  If chkret$ = "NoLeak"
    ProcedureReturn "No DNS Address Leak Detected"
  EndIf
  
  If chkret$ = "NoResource"
    ProcedureReturn "Warning! No DNS Leak Test Resource - Test Not Conducted"
  EndIf
  
EndProcedure

Debug GetDnsLeakTest()
You could use just one of the servers but its best to use multiple passes as a DNS leak can be intermittent. In the above code I use multiple passes across different servers.

The code first gets your public IP address ($pubip) which it then uses to compare against the dns query IP returned ($ips). Multiple passes are used across multiple servers. Multiple servers are used to get your public IP in case one is down, and the dns leak is conducted across multiple servers. If it returns "Warning! DNS Address Leak" the leaking DNS IP address will be returned also. Redundancy is built in just in case a server is down or is not reachable for some reason, so the test will have the best chance of success.

Note: The line "$rnuma = -join (%{ [char[]] (48..57 + 65..90 + 97..122) | Get-Random -count 40});" is part of an addition to this if you use a server that wants a generated random asciii character string, you can remove this line if you do not plan to use a server which needs a generated random ascii character string. To use it change the -count to the number of characters. If needed you can alter the ascii characters needed at the (48..57 + 65..90 + 97..122) portion. None of the servers I've included need this string. If you choose to not use this and omit it from the code the line would look like this

Code: Select all

f$ = "$x = 0;"
The world and human nature was screwed up before I was born. It's not my fault and I'm just stuck with trying to deal with the mess left behind, so don't blame me.