Skip to content

Instantly share code, notes, and snippets.

@bytespec
Last active February 6, 2022 02:51
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save bytespec/862c8f370d6018c76d6122ca423c16cf to your computer and use it in GitHub Desktop.
Save bytespec/862c8f370d6018c76d6122ca423c16cf 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.
# Settings
$VPN_NAME = "My System VPN"
$SERVER = "vpn.example.com:443"
$ROUTES = @("192.168.5.0/24", "192.168.6.0/24") # Empty to disable split tunneling
$USER = "sys-vpn-username"
# ========
$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"
@tnhung2011
Copy link

`

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