Advertisement
al_sedano

openvpn inline export (also for viscosity)

Jul 19th, 2019
770
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. ####
  2. ### Exporting openvpn client to inline unique file
  3. ####
  4. # This ps1 script exports multifile openvpn client configs
  5. # to one inline .ovpn file
  6. #
  7. # The Viscosity (also Tunnelblick) format is valid for MacOS
  8. # This file format uses the UTF8bom encoding.
  9. #
  10. # openVPN Client must be installed in this computer.
  11.  
  12. # Tested on PowerShell 5.1
  13. # Created by Alvaro Sedano Galindo. al_sedano@hotmail.com
  14. #
  15. # https://github.com/alvarsedano/openvpn-configuration-inline-export-also-for-viscosity-
  16. #
  17.  
  18. $ErrorActionPreference = 'SilentlyContinue'
  19.  
  20. #
  21. # Functions
  22. #
  23.  
  24. Function Get-BeginEnd {
  25.     Param([Parameter(Mandatory=$true, Position=0)]
  26.           [string]$path)
  27.  
  28.     [string[]]$text = Get-Content $path -Encoding UTF8
  29.     [int]$beg = ($text | Select-String -Pattern "-BEGIN " -Encoding utf8 | Select -ExpandProperty LineNumber) - 1
  30.     [int]$end =  $text | Select-String -Pattern "-END "   -Encoding utf8 | Select -ExpandProperty LineNumber
  31.     $text[$beg..$end]
  32. }
  33.  
  34. Function BufferAdd {
  35.     Param([Parameter(Mandatory=$true, Position=0)]
  36.           [ref]$dir,
  37.           [Parameter(Mandatory=$true, Position=1)]
  38.           [ref]$buffer,
  39.           [Parameter(Mandatory=$true, Position=2)]
  40.           [string]$pa)
  41.  
  42.     $buffer.Value += "<$pa>"
  43.     $buffer.Value += Get-BeginEnd -path ($dir.value)
  44.     $buffer.Value += "</$pa>"
  45. }
  46.  
  47. Function IfExists {
  48.     Param([Parameter(Mandatory=$true, Position=0)]
  49.           [ref]$ovpn,
  50.           [Parameter(Mandatory=$true, Position=1)]
  51.           [ref]$dir,
  52.           [Parameter(Mandatory=$true, Position=2)]
  53.           [ref]$buffer,
  54.           [Parameter(Mandatory=$true, Position=3)]
  55.           [string]$pa)
  56.  
  57.     $pattern = "^$pa (?<a>.*) *$"
  58.     [string]$a = ($ovpn.Value) -match $pattern
  59.     if ($a -ne $null -and $a -match $pattern) {
  60.         # Pattern found
  61.         [string]$arch = "$($dir.Value)\$($Matches.a)"
  62.  
  63.         if(Test-Path $arch) {
  64.             BufferAdd -dir ([ref]$arch) -buffer $buffer -pa $pa
  65.         }
  66.         else {
  67.             Write-Host "ERROR: The $pa file '$arch' was not found. Process stopped." -BackgroundColor DarkRed
  68.             Exit(2)
  69.         }
  70.     }
  71. }
  72.  
  73. #
  74. # BODY
  75. #
  76.  
  77. # Get from registry the OpenVPN Client path
  78. [string]$rutaREG = "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\OpenVPN"
  79. if (-not (Test-Path($rutaREG))) {
  80.     Write-Output "No openvpn installation found. You must install openvpn client to use this script." -BackgroundColor DarkRed
  81.     Exit (1)
  82. }
  83.  
  84. # openVPN Client installation found
  85. [string[]]$rutaConfig = (Get-ItemProperty -Path $rutaREG).config_dir
  86. $rutaConfig += @("$env:USERPROFILE\OpenVPN\config" `
  87.                 , "$([Environment]::GetFolderPath("MyDocuments"))" )
  88.  
  89. [string]$openSSL = ((Get-ItemProperty -Path $rutaREG).exe_path).Replace("openvpn.exe", "openssl.exe")
  90.  
  91. # List every ovpn tunnel
  92. [string[]]$tunnels = (Get-ChildItem -Filter "*.ovpn" -Path $rutaConfig -Depth 1 -Recurse).Fullname
  93.  
  94. if ($tunnels -eq $null -or $tunnels.Count -eq 0) {
  95.     Write-Host "No ovpn config tunnels found in" -BackgroundColor DarkRed
  96.     foreach ($p in $rutaConfig) {
  97.         Write-Host "`t'$p'"
  98.     }
  99.     Write-Host "and its level 1 subfolders." -BackgroundColor DarkRed
  100.     exit(3)
  101. }
  102.  
  103. for($i=0; $i -lt $tunnels.Count; $i++) {
  104.     Write-Host $([string]::Format("[{0}] - {1}", $i+1, $tunnels[$i]) )
  105. }
  106.  
  107. [int]$max = $tunnels.Count
  108. do {
  109.     [string]$resp = Read-Host "`nWhich ovpn tunnel do you want to export? [1-$max] (Ctrl+C to exit)"
  110. } While ([int]$resp -lt 1 -or [int]$resp -gt $max)
  111. [string]$tun = $tunnels[$resp-1]
  112. [string[]]$content = Get-Content -Path $tun
  113. [string]$retls = "^tls-auth (?<a>.*) (?<b>[0-1])"
  114. [string]$reca = "^ca (?<a>.*) *$"
  115. [string]$recert = "^cert (?<a>.*) *$"
  116. [string]$rekey = "^key (?<a>.*) *$"
  117. [string]$repkcs = "^pkcs12 (?<a>.*)"
  118.  
  119. [string[]]$exported = @()
  120. $exported += $content | Select-String -NotMatch -Pattern $retls  | `
  121.                             Select-String -NotMatch -Pattern $reca   | `
  122.                             Select-String -NotMatch -Pattern $recert | `
  123.                             Select-String -NotMatch -Pattern $rekey  | `
  124.                             Select-String -NotMatch -Pattern $repkcs | `
  125.                             Select-String -NotMatch -Pattern '^#'    | `
  126.                             Select-String -NotMatch -Pattern '^;'
  127. #$exported += ""
  128.  
  129. [System.IO.FileSystemInfo]$ar = Get-ChildItem -Path ($tunnels[$resp-1])
  130. [string]$dir = $ar.Directory.FullName
  131.  
  132. #PKCS12 section found
  133. [string]$a = $content -match $repkcs
  134. if ($a -ne $null -and $a -match $repkcs) {
  135.     # pkcs12 section found
  136.     [string]$arch = "$dir\$($Matches.a)"
  137.  
  138.     #Extract from .p12 the ca,crt,key files
  139.     $f1CA  = New-TemporaryFile
  140.     $f2cer = New-TemporaryFile
  141.     $f3key = New-TemporaryFile
  142.     try {
  143.         & "$openSSL" pkcs12 -in "$arch" -nomac -nokeys -cacerts -out "$($f1CA.FullName)"  -passin pass:
  144.         & "$openSSL" pkcs12 -in "$arch" -nomac -nokeys -clcerts -out "$($f2cer.FullName)" -passin pass:
  145.         & "$openSSL" pkcs12 -in "$arch" -nomac -nodes  -nocerts -out "$($f3key.FullName)" -passin pass:
  146.    
  147.         BufferAdd -dir ([ref]($f1CA.FullName))  -buffer ([ref]$exported) -pa 'ca'
  148.         BufferAdd -dir ([ref]($f2cer.FullName)) -buffer ([ref]$exported) -pa 'cert'
  149.         BufferAdd -dir ([ref]($f3key.FullName)) -buffer ([ref]$exported) -pa 'key'
  150.     }
  151.     catch {}
  152.     finally {
  153.         Remove-Item $f1CA.FullName  -Force
  154.         Remove-Item $f2cer.FullName -Force
  155.         Remove-Item $f3key.FullName -Force
  156.     }
  157. }
  158. else {
  159.     # No PKCS12 section, search for ca, cert, key section
  160.     IfExists -ovpn ([ref]$content) -dir ([ref]$dir) -buffer ([ref]$exported) -pa 'ca'
  161.     IfExists -ovpn ([ref]$content) -dir ([ref]$dir) -buffer ([ref]$exported) -pa 'cert'
  162.     IfExists -ovpn ([ref]$content) -dir ([ref]$dir) -buffer ([ref]$exported) -pa 'key'
  163. }
  164.  
  165. #TLS-AUTH section
  166. [string]$a = $content -match $retls
  167. if ($a -ne $null -and $a -match $retls) {
  168.     # tls-auth section found
  169.     [string]$arch = "$dir\$($Matches.a)"
  170.     [string]$keydir = "key-direction $($Matches.b)"
  171.  
  172.     [string[]]$c = Get-Content $arch
  173.  
  174.     $exported += $keydir
  175.     $exported += "<tls-auth>"
  176.     $exported += Get-Content $arch
  177.     $exported += "</tls-auth>"
  178. }
  179.  
  180. # Obtener nombre archivo
  181. [int]$beg = 1 + $tun.LastIndexOf('\')
  182. [string]$fSal = $tun.Substring($beg)
  183.  
  184. # To choose the exported file type (Viscosity uses UTF8bom encoding), Default/ANSI encodig for the rest
  185. [string]$isVisc = Read-Host "Export for MacOS (Viscosity/Tunnelblick) (UTF8 w BOM)? [y/N]"
  186. if ($isVisc -eq 'y') {
  187.     # Viscosity. Export with "UTF8 w BOM" encoding
  188.     [string]$nombre = $fSal.Replace('.ovpn', '')
  189.     [string[]]$visco = @('#-- Config Generated by ParseOpenVPN for Viscosity --#', '' `
  190.                         ,'#viscosity startonopen false' `
  191.                         ,'#viscosity dhcp true' `
  192.                         ,'#viscosity dnssupport true' `
  193.                         ,"#viscosity name $nombre")
  194.    
  195.     $UTF8bomEnc = [System.Text.UTF8Encoding]::new($true);
  196.     $fSal = $fSal.Replace('.ovpn', '-viscosity.ovpn')
  197.     [System.IO.File]::WriteAllLines("$env:UserProfile\$fSal", $visco + $exported, $UTF8bomEnc)
  198. }
  199. else {
  200.     # Rest of platforms. Export with ANSI encoding
  201.     # TODO: validation pending: is 'default' valid for every Windows OS languages?
  202.     $fSal = $fSal.Replace('.ovpn', '-inline.ovpn')
  203.     $exported | Out-File -Encoding default -FilePath "$env:UserProfile\$fSal"
  204. }
  205.  
  206. Write-host $([string]::Format("`nInline config file '{0}' created in folder '{1}'.", $fSal, $env:UserProfile)) -BackgroundColor DarkGreen
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement