Windows – Block all non VPN traffic

vpnwindowswindows 10windows-firewall

I’ll shortly be traveling to a country with less lenient laws regarding free speech.

I have a Windows 10 machine. I want to block this machines possibility to communicate on all interfaces except over a VPN tunnel (there is a network port and WiFi). If the VPN tunnel is down for any reason no network traffic is allowed. Not even on LAN.

If it’s easier to do this with windows server I’ll gladly switch.

I have found several posts regarding windows firewall which I have tried to follow but in my experience it does not catch everything (might be errors on my side though).

I also have software such as Windscribe VPN but I have managed to go around its firewall when it goes down so I don’t trust it, and it does not seem to block DNS queries at all (I was catching lots of dns queries in PiHole when Windscribe was blocking)

Can this be accomplished with some clever power shell?

Thanks for the help!

Best Answer

The easiest way to achieve this is using the LockDown VPN Feature on Windows 10. With this feature all traffic must ONLY go over VPN and cannot go over other interfaces (except for traffic needed to establish basic connectivity as well as the VPN Connection) More information on deploying this feature is @ https://docs.microsoft.com/en-us/windows/client-management/mdm/vpnv2-csp

A VPN Profile XML sample for such a configuration is as follows:

<VPNProfile>
 <LockDown>true</LockDown>
 <RememberCredentials>true</RememberCredentials>
 <DnsSuffix>enter.dnsSuffix.forVPNInterface</DnsSuffix>
 <NativeProfile>
    <Servers>enterserveraddress.com</Servers>
    <Authentication>
    <UserMethod>Eap</UserMethod>
    <MachineMethod>Eap</MachineMethod>
    <Eap>
      <Configuration>
         <EapHostConfig xmlns="http://www.microsoft.com/provisioning/EapHostConfig"><EapMethod><Type xmlns="http://www.microsoft.com/provisioning/EapCommon">13</Type><VendorId xmlns="http://www.microsoft.com/provisioning/EapCommon">0</VendorId><VendorType xmlns="http://www.microsoft.com/provisioning/EapCommon">0</VendorType><AuthorId xmlns="http://www.microsoft.com/provisioning/EapCommon">0</AuthorId></EapMethod><Config xmlns="http://www.microsoft.com/provisioning/EapHostConfig"><Eap xmlns="http://www.microsoft.com/provisioning/BaseEapConnectionPropertiesV1"><Type>13</Type><EapType xmlns="http://www.microsoft.com/provisioning/EapTlsConnectionPropertiesV1"><CredentialsSource><CertificateStore><SimpleCertSelection>true</SimpleCertSelection></CertificateStore></CredentialsSource><ServerValidation><DisableUserPromptForServerValidation>false</DisableUserPromptForServerValidation><ServerNames></ServerNames></ServerValidation><DifferentUsername>false</DifferentUsername><PerformServerValidation xmlns="http://www.microsoft.com/provisioning/EapTlsConnectionPropertiesV2">false</PerformServerValidation><AcceptServerName xmlns="http://www.microsoft.com/provisioning/EapTlsConnectionPropertiesV2">false</AcceptServerName></EapType></Eap></Config></EapHostConfig>
      </Configuration>
    </Eap>
    </Authentication>
</NativeProfile>
</VPNProfile>

A Powershell script to feed this VPN Profile XML too will look like as follows. Note that to run this you will need to run the PS script as System using PSexec from: https://technet.microsoft.com/sysinternals/bb897553.aspx, by running Psexec.exe -i -s cmd.exe

Param(
    [string]$xmlFilePath,
    [string]$ProfileName
    )

    $a = Test-Path $xmlFilePath
echo $a
$ProfileXML = Get-Content $xmlFilePath
echo $XML
$ProfileNameEscaped = $ProfileName -replace ' ', '%20'
$Version = 201606090004
$ProfileXML = $ProfileXML -replace '<', '&lt;'
$ProfileXML = $ProfileXML -replace '>', '&gt;'
$ProfileXML = $ProfileXML -replace '"', '&quot;'
$nodeCSPURI = './Vendor/MSFT/VPNv2'
$namespaceName = "root\cimv2\mdm\dmmap"
$className = "MDM_VPNv2_01"
$session = New-CimSession
try
{
    $newInstance = New-Object Microsoft.Management.Infrastructure.CimInstance $className, $namespaceName
    $property = [Microsoft.Management.Infrastructure.CimProperty]::Create("ParentID", "$nodeCSPURI", 'String', 'Key')
    $newInstance.CimInstanceProperties.Add($property)
    $property = [Microsoft.Management.Infrastructure.CimProperty]::Create("InstanceID", "$ProfileNameEscaped", 'String', 'Key')
    $newInstance.CimInstanceProperties.Add($property)
    $property = [Microsoft.Management.Infrastructure.CimProperty]::Create("ProfileXML", "$ProfileXML", 'String', 'Property')
    $newInstance.CimInstanceProperties.Add($property)
    $session.CreateInstance($namespaceName, $newInstance)
    $Message = "Created $ProfileName profile."
    Write-Host "$Message"
}
catch [Exception]
{
    $Message = "Unable to create $ProfileName profile: $_"
    Write-Host "$Message"
    exit
}
$Message = "Complete."
Write-Host "$Message"

You can find more information about Windows 10 VPN options @ https://docs.microsoft.com/en-us/windows/access-protection/vpn/vpn-security-features