2018年2月25日日曜日

DotRasを使ってL2TP VPNをWindowsで簡単に設定するような小物プログラム

L2TP(PSK使用)のVPNを構築したけどWindowsの標準インターフェースだとクライアント側の接続設定が面倒なので簡単に設定できるようなプログラムをVB .netでやってみた。
ライブラリはDotRasを使用しています。

開発環境はWindows 10 Pro 64bit + Visual Studio 2017 Communityです。

CodePlexは更新が終わっているのでdownload archiveでダウンロードした上で下記の順番で「6dda3a2b-7ea1-487b-ad75-34d3183bc10c」というファイルを解凍するとDotRas v1.3 SDK.msiを抽出できます。(自分は7-Zipを使いました)
  • releases\
  • 4\
  • 6dda3a2b-7ea1-487b-ad75-34d3183bc10c

Imports System.Text
Imports System
Imports System.Net
Imports DotRas

Public Class Form1

    Private Sub WriteSysRegDWORD(ByVal RegistoryKey As String, ByVal RegistoryComponent As String, ByVal RegistoryValue As Integer)

        'DWORDでシステムレジストリ書き込み
        Dim regkey As Microsoft.Win32.RegistryKey = Microsoft.Win32.Registry.LocalMachine.CreateSubKey(RegistoryKey)

        Try
            regkey.SetValue(RegistoryComponent, RegistoryValue)
            regkey.Close()
        Catch
            MsgBox(Reflection.MethodBase.GetCurrentMethod.Name & ":レジストリ操作に失敗しました。")
        End Try

    End Sub

    Private Sub CreateVPNEntry()

        Dim l2tp_user As String
        Dim l2tp_pass As String

        Do While True
            l2tp_user = InputBox("ユーザー名を入力してください。")
            If l2tp_user = "" Then
                MsgBox("ユーザー名は必須項目です。")
                Exit Do
            End If

            l2tp_pass = InputBox("パスワードを入力してください。")
            If l2tp_pass = "" Then
                MsgBox("パスワードは必須項目です。")
                Exit Do
            End If


            Try
                RasPhoneBook1.Open()

                'エントリが登録済みだった場合は削除する
                '(消さないとCreateVpnEntryに失敗する)
                If RasPhoneBook1.Entries.Contains("MyVPNConnection") = True Then
                    RasPhoneBook1.Entries.Clear()
                End If

                'VPNのエントリ作成
                Dim entry As RasEntry = RasEntry.CreateVpnEntry(
                    "MyVPNConnection",
                    "123.456.789.012",
                    RasVpnStrategy.L2tpOnly,
                    RasDevice.GetDeviceByName("(L2TP)", RasDeviceType.Vpn, False)
                    )

                With entry
                    '切断するまでの待ち時間(秒)
                    .IdleDisconnectSeconds = 600

                    '接続再試行回数
                    .RedialCount = 5

                    '接続再試行間隔(秒)
                    .RedialPause = 60

                    'LCP拡張を使う
                    '(ヤマハルーターは無効にしたほうが良い)
                    .Options.DisableLcpExtensions = False

                    'ソフトウェア圧縮を使用するかどうか
                    .Options.SoftwareCompression = True

                    '暗号化が必要
                    .EncryptionType = RasEncryptionType.Require
                    .Options.RequireEncryptedPassword = True
                    .Options.RequireDataEncryption = True

                    'マルチリンクの無効化
                    '特に使っていないので無効化する
                    .Options.DoNotNegotiateMultilink = False

                    '認証プロトコル設定する
                    .Options.RequireChap = True
                    .Options.RequireEap = False
                    .Options.RequirePap = False
                    .Options.RequireMSChap = False
                    .Options.RequireMSChap2 = False
                    .Options.RequireMSEncryptedPassword = False
                    .Options.RequireSpap = False
                    .Options.RequireWin95MSChap = False

                    '自動再接続を有効にする
                    .Options.ReconnectIfDropped = True

                    '事前共有鍵を使用する
                    .Options.UsePreSharedKey = True

                    'VPN先のゲートウェイをデフォルトゲートウェイとして使用しないようにする
                    '(VPN用ネットワークが閉域な場合、有効にするとVPN接続中にほかのサイトにつながらなくなる)
                    .Options.RemoteDefaultGateway = False

                    '資格情報を保存する
                    .Options.CacheCredentials = True

                    'VPNのエントリを登録する
                    RasPhoneBook1.Entries.Add(entry)

                    '登録したVPNエントリに対して事前共有鍵を登録する
                    .UpdateCredentials(RasPreSharedKey.Client, "pre_shared_key")

                    '登録したVPNエントリに対してユーザー名とパスワードを登録する
                    .UpdateCredentials(New NetworkCredential(l2tp_user, l2tp_pass))

                End With

                Button1.Enabled = False

                MsgBox("登録が完了しました。")

            Catch

                MsgBox("登録に失敗しました。")

            End Try

            Exit Do
        Loop

    End Sub

    Private Sub AddRegEntry()

        'IPSec NAT-Tを有効にするレジストリ設定(要再起動)
        'Windowsではデフォルトで無効になっているため
        WriteSysRegDWORD("SYSTEM\CurrentControlSet\Services\PolicyAgent", "AssumeUDPEncapsulationContextOnSendRule", 2)

    End Sub

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

        'VPNの接続作成
        CreateVPNEntry()

        'レジストリの設定
        AddRegEntry()

    End Sub

End Class