Edited at

C#でVPN接続(L2TP over IPsec 事前共有キーあり)する

More than 1 year has passed since last update.

需要があるかわからないですが、C#でVPN接続する忘備録。

時間が経っているのでうろ覚え。。。

C#って、こういう処理はすっごい簡単にできそうなんだけど

このVPNに関して言えば、それっぽいWIN APIとかもなくて

とにかく困りました。

softether でVPNサーバーをたててWINアプリからそこにVPN接続したいと考えたんだけど

これがなかなかうまくいかない。

接続方式とか指定しなければもっと簡単に接続できるはずだが、

L2TP over IPsecの事前共有キーありの接続をするのが結構難しかった。

参照でDotRasが必要だった気がする。

結構調べたが情報が古いものが多く、かなり調べると中華系のコミュニティで情報を発見。

で、色んな情報を組み合わせて試行錯誤したけどVISTAぐらいの時代に書かれたソースなので

Win8、Win10で動かないっぽかった。

そっからアレコレ更に試行錯誤してコード調整した記憶がある。

下記はソース(クラス)。クッソ長い。

using System;

using System.Collections.Generic;
using System.Linq;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

/// <summary>
///
/// </summary>
namespace VPNClient
{
/// <summary>
///
/// </summary>
class VPNAPI
{
/// <summary>
///
/// </summary>
public static int CURRENT_VPN_CONN = 0;

/// <summary>
///
/// </summary>
public enum RASCredMask
{
RASCM_UserName = 0x1,
RASCM_password = 0x2,
RASCM_Domain = 0x4,
RASCM_DefaultCreds = 0x8,
RASCM_PreSharedKey = 0x10,
RASCM_ServerPreSharedKey = 0x20,
RASCM_DDMPreSharedKey = 0x40
}

/// <summary>
///
/// </summary>
public enum RasEntryOptions
{
RASEO_UseCountrAndAreaCodes = 0x00000001,
RASEO_SpecificIpAddr = 0x00000002,
RASEO_SpecificNameServers = 0x00000004,
RASEO_IpHeaderCompression = 0x00000008,
RASEO_RemoteDefaultGateway = 0x00000010,
RASEO_DisableLcpExtensions = 0x00000020,
RASEO_TerminalBeforeDial = 0x00000040,
RASEO_TerminalAfterDial = 0x00000080,
RASEO_ModemLights = 0x00000100,
RASEO_SwCompression = 0x00000200,
RASEO_RequireEncrptedPw = 0x00000400,
RASEO_RequireMsEncrptedPw = 0x00000800,
RASEO_RequireDataEncrption = 0x00001000,
RASEO_NetworkLogon = 0x00002000,
RASEO_UseLogonCredentials = 0x00004000,
RASEO_PromoteAlternates = 0x00008000,
RASEO_SecureLocalFiles = 0x00010000,
RASEO_RequireEAP = 0x00020000,
RASEO_RequirePAP = 0x00040000,
RASEO_RequireSPAP = 0x00080000,
RASEO_Custom = 0x00100000,
RASEO_PreviewPhoneNumber = 0x00200000,
RASEO_SharedPhoneNumbers = 0x00800000,
RASEO_PreviewUserPw = 0x01000000,
RASEO_PreviewDomain = 0x02000000,
RASEO_ShowDialingProgress = 0x04000000,
RASEO_RequireCHAP = 0x08000000,
RASEO_RequireMsCHAP = 0x10000000,
RASEO_RequireMsCHAP2 = 0x20000000,
RASEO_RequireW95MSCHAP = 0x40000000

}

/// <summary>
///
/// </summary>
public enum RasEntryOptions2
{
RASEO2_SecureFileAndPrint = 0x1,
RASEO2_SecureClientForMSNet = 0x2,
RASEO2_DontNegotiateMultilink = 0x4,
RASEO2_DontUseRasCredentials = 0x8,
RASEO2_UsePreSharedKey = 0x10,
RASEO2_Internet = 0x20,
RASEO2_DisableNbtOverIP = 0x40,
RASEO2_UseGlobalDeviceSettings = 0x80,
RASEO2_ReconnectIfDropped = 0x100,
RASEO2_SharePhoneNumbers = 0x200,
//winver > 0x600
RASEO2_SecureRoutingCompartment = 0x400,
RASEO2_UseTypicalSettings = 0x800,
RASEO2_IPv6SpecificNameServer = 0x1000,
RASEO2_IPv6RemoteDefaultGateway = 0x2000,
RASEO2_RegisterIpWithDNS = 0x4000,
RASEO2_UseDNSSuffixForRegistration = 0x8000,
RASEO2_IPv4ExplicitMetric = 0x10000,
RASEO2_IPv6ExplicitMetric = 0x20000,
RASEO2_DisableIKENameEkuCheck = 0x40000,
//winver > 0x601
RASEO2_DisableClassBasedStaticRoute = 0x00080000,
RASEO2_SpecificIPv6Addr = 0x00100000,
RASEO2_DisableMobility = 0x00200000,
RASEO2_RequireMachineCertificates = 0x00400000,
//winver > 0x602
RASEO2_UsePreSharedKeyForIkev2Initiator = 0x00800000,
RASEO2_UsePreSharedKeyForIkev2Responder = 0x01000000,
RASEO2_CacheCredentials = 0x02000000,
//winver > 0x603
RASEO2_AutoTriggerCapable = 0x04000000,
RASEO2_IsThirdPartyProfile = 0x08000000,
RASEO2_AuthTypeIsOtp = 0x10000000,
//winver > 0x604
RASEO2_IsAlwaysOn = 0x20000000,
RASEO2_IsPrivateNetwork = 0x40000000
}

/// <summary>
///
/// </summary>
public enum RASNP
{
RASNP_NetBEUI = 0x1,
RASNP_Ipx = 0x2,
RASNP_Ip = 0x4,
RASNP_Ipv6 = 0x8
}

/// <summary>
///
/// </summary>
private const long ET_None = 0; // No encryption

/// <summary>
///
/// </summary>
private const long ET_Require = 1; // Require Encryption

/// <summary>
///
/// </summary>
private const long ET_RequireMax = 2; // Require max encryption

/// <summary>
///
/// </summary>
private const long ET_Optional = 3; // Do encryption if possible. None Ok.

/// <summary>
///
/// </summary>
private const long VS_Default = 0; // default (PPTP for now)

/// <summary>
///
/// </summary>
private const long VS_PptpOnly = 1; // Only PPTP is attempted.

/// <summary>
///
/// </summary>
private const long VS_PptpFirst = 2; // PPTP is tried first.

/// <summary>
///
/// </summary>
private const long VS_L2tpOnly = 3; // Only L2TP is attempted.

/// <summary>
///
/// </summary>
private const long VS_L2tpFirst = 4; // L2TP is tried first.

/// <summary>
///
/// </summary>
private const long RASET_Phone = 1; // Phone lines: modem, ISDN, X.25, etc

/// <summary>
///
/// </summary>
private const long RASET_Vpn = 2; // Virtual private network

/// <summary>
///
/// </summary>
private const long RASET_Direct = 3; // Direct connect: serial, parallel

/// <summary>
///
/// </summary>
private const long RASET_Internet = 4; // BaseCamp internet

/// <summary>
///
/// </summary>
private const long RASET_Broadband = 5; // Broadband

/// <summary>
///
/// </summary>
private const int MAX_PATH = 260;

/// <summary>
///
/// </summary>
private const int RAS_MaxAreaCode = 10;

/// <summary>
///
/// </summary>
private const int RAS_MaxPhoneNumber = 128;

/// <summary>
///
/// </summary>
private const int RAS_MaxDeviceType = 16;

/// <summary>
///
/// </summary>
private const int RAS_MaxDeviceName = 128;

/// <summary>
///
/// </summary>
private const int RAS_MaxPadType = 32;

/// <summary>
///
/// </summary>
private const int RAS_MaxX25Address = 200;

/// <summary>
///
/// </summary>
private const int RAS_MaxFacilities = 200;

/// <summary>
///
/// </summary>
private const int RAS_MaxUserData = 200;

/// <summary>
///
/// </summary>
private const int RAS_MaxDnsSuffix = 256;

/// <summary>
///
/// </summary>
private const int RAS_MaxEntryName = 256;

/// <summary>
///
/// </summary>
private const int RAS_MaxCallbackNumber = RAS_MaxPhoneNumber;

/// <summary>
///
/// </summary>
private const int UNLEN = 256;

/// <summary>
///
/// </summary>
private const int PWLEN = 256;

/// <summary>
///
/// </summary>
private const int DNLEN = 16;

/// <summary>
///
/// </summary>
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
private struct GUID
{
uint data1;
UInt16 data2;
UInt16 data3;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
byte[] data4;
}

/// <summary>
///
/// </summary>
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct RASIPADDR
{
byte a;
byte b;
byte c;
byte d;
}

/// <summary>
///
/// </summary>
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct RASIPV6ADDR
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
byte[] a;
}

/// <summary>
///
/// </summary>
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
private struct RASENTRY
{
/// <summary>
///
/// </summary>
public uint dwSize;

/// <summary>
///
/// </summary>
public uint dwfOptions;

//
// Location/phone number.
//
public uint dwCountryID;

/// <summary>
///
/// </summary>
public uint dwCountryCode;

/// <summary>
///
/// </summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = (int)(RAS_MaxAreaCode + 1))]
public string szAreaCode;

/// <summary>
///
/// </summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = (int)(RAS_MaxPhoneNumber + 1))]
public string szLocalPhoneNumber;

/// <summary>
///
/// </summary>
public uint dwAlternateOffset;

//
// PPP/Ip
//
public RASIPADDR ipaddr;

/// <summary>
///
/// </summary>
public RASIPADDR ipaddrDns;

/// <summary>
///
/// </summary>
public RASIPADDR ipaddrDnsAlt;

/// <summary>
///
/// </summary>
public RASIPADDR ipaddrWins;

/// <summary>
///
/// </summary>
public RASIPADDR ipaddrWinsAlt;

//
// Framing
//
public uint dwFrameSize;

/// <summary>
///
/// </summary>
public uint dwfNetProtocols;

/// <summary>
///
/// </summary>
public uint dwFramingProtocol;

//
// Scripting
//
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = (int)MAX_PATH)]
public string szScript;

//
// AutoDial
//
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = (int)MAX_PATH)]
public string szAutodialDll;

/// <summary>
///
/// </summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = (int)MAX_PATH)]
public string szAutodialFunc;

//
// Device
//
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = (int)(RAS_MaxDeviceType + 1))]
public string szDeviceType;

/// <summary>
///
/// </summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = (int)(RAS_MaxDeviceName + 1))]
public string szDeviceName;

//
// X.25
//
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = (int)(RAS_MaxPadType + 1))]
public string szX25PadType;

/// <summary>
///
/// </summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = (int)(RAS_MaxX25Address + 1))]
public string szX25Address;

/// <summary>
///
/// </summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = (int)(RAS_MaxFacilities + 1))]
public string szX25Facilities;

/// <summary>
///
/// </summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = (int)(RAS_MaxUserData + 1))]
public string szX25UserData;

/// <summary>
///
/// </summary>
public uint dwChannels;

//
// Reserved
//
public uint dwReserved1;

/// <summary>
///
/// </summary>
public uint dwReserved2;

/// <summary>
///
/// </summary>
public uint dwSubEntries;

/// <summary>
///
/// </summary>
public uint dwDialMode;

/// <summary>
///
/// </summary>
public uint dwDialExtraPercent;

/// <summary>
///
/// </summary>
public uint dwDialExtraSampleSeconds;

/// <summary>
///
/// </summary>
public uint dwHangUpExtraPercent;

/// <summary>
///
/// </summary>
public uint dwHangUpExtraSampleSeconds;

/// <summary>
///
/// </summary>
public uint dwIdleDisconnectSeconds;

/// <summary>
///
/// </summary>
public uint dwType;

/// <summary>
///
/// </summary>
public uint dwEncryptionType;

/// <summary>
///
/// </summary>
public uint dwCustomAuthKey;

/// <summary>
///
/// </summary>
public GUID guid;

/// <summary>
///
/// </summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = (int)MAX_PATH)] //259
public string szCustomDialDll;

/// <summary>
///
/// </summary>
public uint dwVpnStrategy;

/// <summary>
///
/// </summary>
public uint dwfOptions2;

/// <summary>
///
/// </summary>
public uint dwfOptions3;

/// <summary>
///
/// </summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = (int)RAS_MaxDnsSuffix)] //255
public string szDnsSuffix;

/// <summary>
///
/// </summary>
public uint dwTcpWindowSize;

/// <summary>
///
/// </summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = (int)MAX_PATH)] //259
public string szPrerequisitePbk;

/// <summary>
///
/// </summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = (int)(RAS_MaxEntryName + 1))] //RAS_MaxEntryName=256
public string szPrerequisiteEntry;

/// <summary>
///
/// </summary>
public uint dwRedialCount;

/// <summary>
///
/// </summary>
public uint dwRedialPause;

/// <summary>
///
/// </summary>
public RASIPV6ADDR ipv6addrDns;

/// <summary>
///
/// </summary>
public RASIPV6ADDR ipv6addrDnsAlt;

/// <summary>
///
/// </summary>
public uint dwIPv4InterfaceMetric;

/// <summary>
///
/// </summary>
public uint dwIPv6InterfaceMetric;

/// <summary>
///
/// </summary>
public RASIPV6ADDR ipv6addr;

/// <summary>
///
/// </summary>
public uint dwIPv6PrefixLength;

/// <summary>
///
/// </summary>
public uint dwNetworkOutageTime;
}

/// <summary>
///
/// </summary>
[StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Auto)]
public struct RASDIALPARAMS
{
/// <summary>
///
/// </summary>
public int dwSize;

/// <summary>
///
/// </summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = RAS_MaxEntryName + 1)]
public string szEntryName;

/// <summary>
///
/// </summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = RAS_MaxPhoneNumber + 1)]
public string szPhoneNumber;

/// <summary>
///
/// </summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = RAS_MaxCallbackNumber + 1)]
public string szCallbackNumber;

/// <summary>
///
/// </summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = UNLEN + 1)]
public string szUserName;

/// <summary>
///
/// </summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = PWLEN + 1)]
public string szPassword;

/// <summary>
///
/// </summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = DNLEN + 1)]
public string szDomain;

/// <summary>
///
/// </summary>
public int dwSubEntry;

/// <summary>
///
/// </summary>
public int dwCallbackId;
}

/// <summary>
///
/// </summary>
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
private struct RASCREDENTIALS
{
/// <summary>
///
/// </summary>
public int dwSize;

/// <summary>
///
/// </summary>
public int dwMask;

/// <summary>
///
/// </summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = (int)UNLEN + 1)]
public string szUserName;

/// <summary>
///
/// </summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = (int)PWLEN + 1)]
public string szPassword;

/// <summary>
///
/// </summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = (int)DNLEN + 1)]
public string szDomain;
}

/// <summary>
///
/// </summary>
/// <param name="unMsg"></param>
/// <param name="rasconnstate"></param>
/// <param name="dwError"></param>
public delegate void Callback(uint unMsg, int rasconnstate, int dwError);

/// <summary>
///
/// </summary>
/// <param name="lpRasDialExtensions"></param>
/// <param name="lpszPhonebook"></param>
/// <param name="lprasdialparams"></param>
/// <param name="dwNotifierType"></param>
/// <param name="lpvNotifier"></param>
/// <param name="lphRasConn"></param>
/// <returns></returns>
[DllImport("rasapi32.dll ", CharSet = CharSet.Auto)]
public static extern int RasDial(IntPtr lpRasDialExtensions, string lpszPhonebook, ref RASDIALPARAMS lprasdialparams, int dwNotifierType, Callback lpvNotifier, ref int lphRasConn);

/// <summary>
///
/// </summary>
/// <param name="hrasconn"></param>
/// <returns></returns>
[DllImport("rasapi32.dll", CharSet = CharSet.Auto)]
public extern static int RasHangUp(int hrasconn); // handle to the RAS connection to hang up );

/// <summary>
///
/// </summary>
/// <param name="lpszPhonebook"></param>
/// <param name="lpszEntry"></param>
/// <param name="lpRasEntry"></param>
/// <param name="dwEntryInfoSize"></param>
/// <param name="lpbDeviceInfo"></param>
/// <param name="dwDeviceInfoSize"></param>
/// <returns></returns>
[DllImport("rasapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern int RasSetEntryProperties(string lpszPhonebook, string lpszEntry, ref RASENTRY lpRasEntry, uint dwEntryInfoSize, IntPtr lpbDeviceInfo, int dwDeviceInfoSize);

/// <summary>
///
/// </summary>
/// <param name="lpszPhonebook"></param>
/// <param name="lpszEntry"></param>
/// <param name="lpCredentials"></param>
/// <param name="fClearCredentials"></param>
/// <returns></returns>
[DllImport("rasapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern int RasSetCredentials(string lpszPhonebook, string lpszEntry, ref RASCREDENTIALS lpCredentials, int fClearCredentials);

/// <summary>
///
/// </summary>
/// <param name="serverIP"></param>
/// <param name="entryName"></param>
/// <param name="user"></param>
/// <param name="pw"></param>
/// <param name="PreSharedKey"></param>
/// <returns></returns>
public static bool rasConnectVPN(string serverIP, string entryName, string user, string pw, string PreSharedKey)
{
bool result = false;
try
{
RASENTRY rasEntry = new RASENTRY();
RASDIALPARAMS RasDialParams = new RASDIALPARAMS();
RASCREDENTIALS Rascredentials = new RASCREDENTIALS();
// uint dwSize = (uint)Marshal.SizeOf(rasEntry);
uint dwSize = (uint)Marshal.SizeOf(typeof(RASENTRY));

// System.Runtime.InteropServices.Marshal.SizeOf(typeof(RasDialParams));
//byte[] lpb = new byte[436];
//int lpbSize = lpb.Length;
int ret = -1;
rasEntry.dwSize = dwSize;
rasEntry.dwCountryCode = 0;
rasEntry.dwCountryID = 0;
rasEntry.dwDialExtraPercent = 75;
rasEntry.dwDialExtraSampleSeconds = 120;
rasEntry.dwDialMode = 0;
rasEntry.dwEncryptionType = (uint)ET_Optional;
rasEntry.dwfNetProtocols = (uint)(RASNP.RASNP_Ip | RASNP.RASNP_Ipv6);
rasEntry.dwfOptions = (uint)(RasEntryOptions.RASEO_RemoteDefaultGateway
| RasEntryOptions.RASEO_SecureLocalFiles
| RasEntryOptions.RASEO_RequireSPAP
| RasEntryOptions.RASEO_PreviewUserPw
| RasEntryOptions.RASEO_PreviewDomain
//| RasEntryOptions.RASEO_RequireCHAP
//| RasEntryOptions.RASEO_RequireMsCHAP
| RasEntryOptions.RASEO_RequireMsCHAP2
| RasEntryOptions.RASEO_ShowDialingProgress
);
//rasEntry.dwfOptions2 = 367;
rasEntry.dwFramingProtocol = 1;
rasEntry.dwHangUpExtraPercent = 10;
rasEntry.dwHangUpExtraSampleSeconds = 120;
rasEntry.dwRedialCount = 3;
rasEntry.dwRedialPause = 60;
rasEntry.dwType = (uint)RASET_Vpn;
rasEntry.dwVpnStrategy = (uint)VS_L2tpOnly;
rasEntry.szDeviceName = "WAN Miniport (L2TP)";
rasEntry.szDeviceType = "Vpn";
rasEntry.szLocalPhoneNumber = serverIP;

rasEntry.dwfOptions2 = (uint)(RasEntryOptions2.RASEO2_SecureFileAndPrint
| RasEntryOptions2.RASEO2_SecureClientForMSNet
| RasEntryOptions2.RASEO2_DontNegotiateMultilink
//| RasEntryOptions2.RASEO2_DontUseRasCredentials
| RasEntryOptions2.RASEO2_Internet
| RasEntryOptions2.RASEO2_ReconnectIfDropped
| RasEntryOptions2.RASEO2_CacheCredentials
);

if (PreSharedKey != string.Empty)
{
rasEntry.dwfOptions2 += (uint)RasEntryOptions2.RASEO2_UsePreSharedKey;
}

ret = RasSetEntryProperties(null, entryName, ref rasEntry, rasEntry.dwSize, IntPtr.Zero, 0);
if (ret != 0)
{
throw new Exception("FailedToRasSetEntryProperties");
}

if (!string.IsNullOrEmpty(PreSharedKey))
{
Rascredentials.dwSize = Marshal.SizeOf(Rascredentials);
Rascredentials.dwMask = (int)RASCredMask.RASCM_PreSharedKey;
Rascredentials.szPassword = PreSharedKey;
ret = RasSetCredentials(null, entryName, ref Rascredentials, 0);
if (ret >= 1)
{
throw new Exception("FailedToRasSetCredentials");
}
}

RasDialParams.dwSize = Marshal.SizeOf(RasDialParams);
RasDialParams.szEntryName = entryName;
RasDialParams.szUserName = user;
RasDialParams.szPassword = pw;
int nn = 0;
ret = RasDial(IntPtr.Zero, null, ref RasDialParams, -1, null, ref nn);

if (ret >= 1)
{
if (nn > 0)
RasHangUp(nn);

throw new Exception("FailedToRasDial");
}

CURRENT_VPN_CONN = nn;

result = true;
}
catch (Exception ex)
{
result = false;
}
finally
{

}

return result;
}

/// <summary>
///
/// </summary>
/// <param name="entryName"></param>
/// <returns></returns>
public static bool rasDisConnectVPN(string entryName)
{
bool result = false;
if (string.IsNullOrEmpty(entryName))
{
return result;
}

try
{
if (CURRENT_VPN_CONN > 0)
{
RasHangUp(CURRENT_VPN_CONN );
}
else
{
//System.Diagnostics.Process.Start("rasdial.exe", entryName + " /d");
Process process = new Process();
process.StartInfo.FileName = "rasdial.exe ";
process.StartInfo.Verb = entryName + " /d runas";
process.StartInfo.UseShellExecute = false;
process.StartInfo.CreateNoWindow = true;//not show cmd window
process.Start();
}

result = true;
}
catch (Exception ex)
{
result = false;
}
finally
{

}

return result;
}
}
}

呼び出すときは

if (!VPNAPI.rasConnectVPN('VPNのホスト', '接続名', 'VPNユーザー', 'パスフレーズ', '事前共有キー'))

{
//"接続ができませんでした";
return;
}

で、アプリ終了タイミングなど適切なタイミングでVPNを切断する場合は下記のようにする。



VPNAPI.rasDisConnectVPN('接続名');

正直よくわからん。