Skip to content

Instantly share code, notes, and snippets.

@tnhung2011
Forked from bytespec/CreateSystemVPN.ps1
Last active February 6, 2022 02:58
Show Gist options
  • Save tnhung2011/365e6e960d8f790f14aa175072948f5d to your computer and use it in GitHub Desktop.
Save tnhung2011/365e6e960d8f790f14aa175072948f5d to your computer and use it in GitHub Desktop.
Example PowerShell code to create a system (all users) SSTP VPN. Use a .cmd file as a launcher within a .scapp file for an almost-one-click deploying via Screen Connect's Toolbox in Backstage mode.
# (a fork of https://gist.github.com/bytespec/862c8f370d6018c76d6122ca423c16cf)
# Parameter defaults
param(
[Parameter()]
[String]$VPN_NAME = 0
[String]$SERVER = 0
[String]$SPLIT = $false
[String[]]$ROUTES = 0 # Empty or set $SPLIT to false to disable tunneling
[String]$USER = 0
)
# ========
if ($VPN_NAME -eq 0) -and ($SERVER -eq 0) -and ($ROUTES -eq 0) -and ($USER -eq 0) {
Write-Host "You must specify the required parameters (vpn_name, server, routes -and user)!`nInstallation aborted" -ForegroundColor Red
Read-Host -Prompt "Press RETURN to exit"
Exit
} else {
if ($SPLIT -eq $false) {
$ROUTES = 0
}
$SPLIT = 0
}
$ErrorActionPreference = "Stop"
# DLL stuff for setting credentials
Add-Type -Name "RAS" -Namespace "Win32" -MemberDefinition @'
public enum RasCredentialsMask {
RASCM_UserName = 0x00000001,
RASCM_Password = 0x00000002,
RASCM_DefaultCreds = 0x00000008
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct RASCREDENTIALS {
public Int32 dwSize;
public Int32 dwMask;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 257)]
public string szUsername;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 257)]
public string szPassword;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 17)]
public string szDomain;
}
[DllImport("rasapi32.dll", CharSet = CharSet.Ansi)]
public static extern int RasSetCredentialsA(
string PhoneBook,
string EntryName,
RASCREDENTIALS Credentials,
bool clearCredentials
);
'@
$pbkPath = "$env:ProgramData\Microsoft\Network\Connections\Pbk\rasphone.pbk"
$host.UI.RawUI.WindowTitle = "$VPN_NAME Installer"
Write-Host "$VPN_NAME Installer" -ForegroundColor Cyan
Write-Host ""
$securePassword = Read-Host -Prompt "Enter VPN password for $USER (or blank to abort)" -AsSecureString
if ($securePassword.Length -eq 0) {
Write-Host "No password entered, installation aborted." -ForegroundColor Yellow
Write-Host ""
Write-Host ""
Read-Host -Prompt "Press RETURN to exit"
exit
}
$password = (New-Object System.Management.Automation.PSCredential "user", $securePassword).GetNetworkCredential().Password
Write-Host ""
Write-Host "Removing existing connection (if exists)... " -NoNewline
Get-VpnConnection -AllUserConnection -Name $VPN_NAME -ErrorAction SilentlyContinue | Remove-VpnConnection -AllUserConnection -Force
Write-Host "OK" -ForegroundColor Green
Write-Host "Creating new VPN... " -NoNewline
Add-VpnConnection -AllUserConnection -Name $VPN_NAME -ServerAddress $SERVER -TunnelType SSTP -EncryptionLevel Required -AuthenticationMethod MSCHAPV2 -RememberCredential
Write-Host "OK" -ForegroundColor Green
if ($ROUTES.Count -gt 0) {
Write-Host "Setting up split tunneling... "
Set-VpnConnection -AllUserConnection -Name $VPN_NAME -SplitTunneling $true
$ROUTES | ForEach-Object {
Write-Host " - $_... " -NoNewline;
Add-VpnConnectionRoute -AllUserConnection -ConnectionName $VPN_NAME -DestinationPrefix $_
Write-Host "OK" -ForegroundColor Green
}
}
Write-Host "Setting VPN credentials... " -NoNewline
$creds = New-Object Win32.RAS+RASCREDENTIALS
$creds.dwSize = [System.Runtime.InteropServices.Marshal]::SizeOf($creds)
$creds.dwMask = [Win32.RAS+RasCredentialsMask]::RASCM_UserName -bor [Win32.RAS+RasCredentialsMask]::RASCM_Password -bor [Win32.RAS+RasCredentialsMask]::RASCM_DefaultCreds
$creds.szUsername = $USER
$creds.szPassword = $password
$result = [Win32.RAS]::RasSetCredentialsA($pbkPath, $VPN_NAME, $creds, $false)
if ($result -ne 0) {
throw ("Failed to set credentials, RasSetCredentialsA returned $result")
}
Write-Host "OK" -ForegroundColor Green
Write-Host "Configuring connection parameters..." -NoNewline
# PreviewUserPw = 0: to connect without interaction
# IpInterfaceMetric = 10: higher priority helps with DNS resolution
# IpDnsFlags = 1: to register IP with DNS after connecting
$processing = $false
(Get-Content -Path $pbkPath) | ForEach-Object {
if ($processing) {
Write-Output (
$_ `
-replace ("^PreviewUserPw=.*", "PreviewUserPw=0") `
-replace ("^IpInterfaceMetric=.*", "IpInterfaceMetric=10") `
-replace ("^IpDnsFlags=.*", "IpDnsFlags=1")
)
if ($_ -match "^\[") {
$processing = $false
}
} else {
Write-Output $_
if ($_ -eq "[$VPN_NAME]") {
$processing = $true
}
}
} | Out-File -FilePath $pbkPath -Encoding ASCII
Write-Host "OK" -ForegroundColor Green
Write-Host ""
Write-Host "$VPN_NAME connection created."
while ($true) {
Write-Host "";
Write-Host "Connect now? (Y/N): " -NoNewline -ForegroundColor Yellow
$response = (Read-Host).ToLower()
if ($response -eq "y") {
break
} elseif ($response -eq "n") {
Write-Host ""
Write-Host "Exiting without connecting."
Write-Host ""
Write-Host ""
Read-Host -Prompt "Press RETURN to exit"
exit
}
}
Write-Host ""
Write-Host "Attempting to connect... " -NoNewline;
$p = Start-Process -FilePath "rasphone.exe" -ArgumentList @("-d", "`"$VPN_NAME`"") -Wait -PassThru
if ($p.ExitCode -eq 0) {
Write-Host "OK" -ForegroundColor Green
} else {
Write-Host "Failed with code: $($p.ExitCode)" -ForegroundColor Red
}
Write-Host ""
Write-Host "Done!"
Write-Host ""
Write-Host ""
Read-Host -Prompt "Press RETURN to exit"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment