次の方法で共有


ファイアウォールの動的キーワード

ファイアウォールの動的キーワード API を使用して、Microsoft Defender ファイアウォールの動的キーワード (keyword) アドレスを管理します。 動的キーワード アドレスは、1 つ以上のファイアウォール規則から参照できる IP アドレスのセットを作成するために使用されます。 動的キーワード アドレスは、IPv4 と IPv6 の両方をサポートします。

Note

このトピックで紹介する API の API リファレンス コンテンツについては、「 Firewall dynamic keywords reference」を参照してください。

動的キーワード (keyword) アドレスに対する操作

Firewall 動的キーワード API を使用すると、次の操作を実行できます。

  • 動的なキーワード (keyword) アドレスを追加する
  • 動的なキーワード (keyword) アドレスを削除する
  • 動的キーワード (keyword) アドレスを ID または種類別に列挙する
  • 動的なキーワード (keyword) アドレスを更新する
  • 動的キーワード (keyword)アドレス変更通知をサブスクライブして処理する

これらのすべての操作のコード例については、このトピックの後半で説明します。

動的なキーワード (keyword) アドレスを追加すると、再起動後も保持されます。 オブジェクトの使用が完了したら、動的キーワード (keyword)アドレスを削除する必要があります。

次の 2 つのセクションで説明するように、動的キーワード (keyword) アドレスには 2 つのクラスがあります。

動的キーワード (keyword) アドレスの自動解決

最初の型は AutoResolve です。ここで、キーワード (keyword) フィールドは解決可能な名前を表し、作成時に IP アドレスは定義されません。

これらのオブジェクトは、IP アドレスを自動的に解決することを目的としています。 つまり、オブジェクトの作成時に管理者を介したものではありません。また、オペレーティング システム (OS) 自体を使用することもできません。 ファイアウォール サービスの外部のコンポーネントは、これらのオブジェクトの IP アドレス解決を行い、適切に更新する必要があります。 このようなコンポーネントの実装は、このコンテンツの範囲外です。

動的キーワード (keyword)アドレスは、FWAddDynamicKeywordAddress0 関数を呼び出すときにオブジェクトでFW_DYNAMIC_KEYWORD_ADDRESS_FLAGS_AUTO_RESOLVE フラグを設定することで、AutoResolve として示されます。 解決される値 (完全修飾ドメイン名 (FQDN) またはホスト名) を表すには、キーワード (keyword) フィールドを使用する必要があります。 これらのオブジェクトの アドレス フィールドは、最初は NULL である必要があります。 これらのオブジェクトの IP アドレスはブート サイクル間で保持されないため、次のブート サイクル中にアドレスを再評価または再入力する必要があります。

Note

動的キーワード (keyword)アドレス オブジェクトを自動解決すると、FWAddDynamicKeywordAddress0FWDeleteDynamicKeywordAddress0 で通知がトリガーされますが、FWUpdateDynamicKeywordAddress0 はトリガーされません。

非自動解決動的キーワード (keyword) アドレス

2 番目の型は AutoResolve 以外で、キーワード (keyword) フィールドは任意の文字列であり、アドレスは作成時に定義されます。

これらのオブジェクトは、IP アドレス、サブネット、または範囲のセットを格納するために使用されます。 ここでキーワード (keyword)フィールドは管理上の利便性のために使用され、任意の文字列に設定できます。 アドレス フィールドは、作成時に NULL 以外である必要があります。 これらのオブジェクトのアドレスは、再起動後も保持されます。

Note

非自動解決動的キーワード (keyword)アドレス オブジェクトは、FWAddDynamicKeywordAddress0FWDeleteDynamicKeywordAddress0、および FWUpdateDynamicKeywordAddress0 に対する通知をトリガーします。

動的キーワード (keyword)アドレスの詳細

動的キーワード (keyword)アドレスはすべて、それらを表す一意の GUID 識別子を持っている必要があります。

FwpmDynamicKeywordSubscribe0 API は、動的なキーワード (keyword)アドレスの変更時にクライアントに通知を配信します。 システムで何が変更されたかを正確に説明するペイロードはクライアントに配信されません。 変更されたオブジェクトを把握する必要がある場合は、FWEnumDynamicKeywordAddressById0 API または FWEnumDynamicKeywordAddressesByType0 API を使用して、システム上のオブジェクトの現在の状態を照会する必要があります。 さまざまなフラグを使用して、オブジェクトのサブセットに対してのみ通知を要求できます。 フラグを使用しない場合、変更通知はすべてのオブジェクトに対して配信されます。

ファイアウォール規則では、リモート アドレスの状態に対して IP アドレスを明示的に定義する代わりに、動的なキーワード (keyword) アドレスを使用できます。 ファイアウォール規則では、動的キーワード (keyword)アドレスと静的に定義されたリモート アドレス範囲の両方を使用できます。 1 つの動的キーワード (keyword) アドレス オブジェクトを複数のファイアウォール規則で再利用できます。 ファイアウォール規則にリモート アドレスが構成されていない場合 (つまり、解決されていない AutoResolve オブジェクトのみを使用して構成されている場合)、規則は適用されません。 さらに、ルールで複数の動的キーワード (keyword) アドレスが使用されている場合、まだ解決されていない他のオブジェクトがある場合でも、現在解決されているすべてのアドレスにルールが適用されます。 動的キーワード (keyword) アドレスが更新されると、関連付けられているすべてのルール オブジェクトにもリモート アドレスが更新されます。

オペレーティング システム (OS) 自体では、ルールと動的なキーワード (keyword) アドレス間の依存関係は適用されません。 つまり、どちらのオブジェクトも最初に作成できます。ルールは、まだ存在しない動的キーワード (keyword)アドレス ID を参照できます (この場合、ルールは適用されません)。 さらに、ファイアウォール規則で使用されている場合でも、動的なキーワード (keyword) アドレスを削除できます。 このトピックでは、管理者が動的なキーワード (keyword) アドレスを使用するようにルールを構成する方法について説明します。

コード例

これらの各コード例を試すには、まず Visual Studio を起動し、 コンソール アプリ プロジェクト テンプレートに基づいて新しいプロジェクトを作成します。 の内容 main.cpp をコード 一覧に置き換えることができます。

ほとんどのコード例では、 Windows 実装ライブラリ (WIL) を使用します。 WIL をインストールする便利な方法は、Visual Studio に移動し、[プロジェクト>] [NuGet パッケージの管理] の順にクリックすることです。>検索ボックスに Microsoft.Windows.ImplementationLibrary を参照、入力、貼り付け、検索結果の項目を選択し、[インストール] をクリックしてそのプロジェクトのパッケージをインストールします。

Note

NetFw 無料関数のポインター型は を介して NetFw.h公開されますが、静的リンク ライブラリは公開されません。 これらのコード例に示すように、これらの関数を呼び出す 場合は LoadLibraryExW/GetProcAddress パターンを使用します。

動的なキーワード (keyword) アドレスを追加する

この例では、 FWAddDynamicKeywordAddress0 関数の使用方法を示します。

// main.cpp in a Console App project.
#include <windows.h>
#include <wil/resource.h>
#include <netfw.h>

// {26548e4f-d486-4a1d-8a1d-22b0837cd53b}
const GUID DYNAMIC_KEYWORD_ADDRESS_ID_1 =
{
    0x26548e4f,
    0xd486,
    0x4a1d,
    {0x8a,0x1d,0x22,0xb0,0x83,0x7c,0xd5,0x3b}
};

// {e9d5c993-9369-4a96-8228-9c5c37aac51a}
const GUID DYNAMIC_KEYWORD_ADDRESS_ID_2 =
{
    0xe9d5c993,
    0x9369,
    0x4a96,
    {0x82,0x28,0x9c,0x5c,0x37,0xaa,0xc5,0x1a}
};

int main()
{
    DWORD error = ERROR_SUCCESS;
    PFN_FWADDDYNAMICKEYWORDADDRESS0 addDynamicKeywordAddressFn = NULL;
    HMODULE moduleHandle = NULL;
    FW_DYNAMIC_KEYWORD_ADDRESS0 autoResolveKeywordAddress = { 0 };
    FW_DYNAMIC_KEYWORD_ADDRESS0 nonAutoResolveKeywordAddress = { 0 };

    // Use LoadLibrary/GetProcAddress to invoke this function
    moduleHandle = LoadLibraryExW(L"firewallapi.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
    auto onExitFreeModuleHandle = wil::scope_exit([&]
        {
            if (moduleHandle)
            {
                FreeLibrary(moduleHandle);
            }
        });

    if (moduleHandle != NULL)
    {
        addDynamicKeywordAddressFn = (PFN_FWADDDYNAMICKEYWORDADDRESS0)GetProcAddress(
            moduleHandle,
            "FWAddDynamicKeywordAddress0"
        );
    }

    if (addDynamicKeywordAddressFn == NULL)
    {
        error = GetLastError();
        return error;
    }

    // Ensure the ID is unique. If not, the add operation will fail with ERROR_ALREADY_EXISTS
    // and you should invoke the API with a new ID.

    // Initialize and add an auto-resolve dynamic keyword address
    autoResolveKeywordAddress.id = DYNAMIC_KEYWORD_ADDRESS_ID_1;
    autoResolveKeywordAddress.keyword = L"bing.com";
    autoResolveKeywordAddress.flags = FW_DYNAMIC_KEYWORD_ADDRESS_FLAGS_AUTO_RESOLVE;
    // must be NULL as we have set the auto resolve flag
    autoResolveKeywordAddress.addresses = NULL;

    error = addDynamicKeywordAddressFn(&autoResolveKeywordAddress);
    if (error != ERROR_SUCCESS)
    {
        return error;
    }

    // Initialize and add a non auto-resolve dynamic keyword address
    nonAutoResolveKeywordAddress.id = DYNAMIC_KEYWORD_ADDRESS_ID_2;
    nonAutoResolveKeywordAddress.keyword = L"myServerIPs";
    nonAutoResolveKeywordAddress.flags = 0;
    nonAutoResolveKeywordAddress.addresses = L"10.0.0.5,20.0.0.0/24,30.0.0.0-40.0.0.0";

    error = addDynamicKeywordAddressFn(&nonAutoResolveKeywordAddress);
    if (error != ERROR_SUCCESS)
    {
        return error;
    }
    return error;
}

動的なキーワード (keyword) アドレスを削除する

この例では、 FWDeleteDynamicKeywordAddress0 関数の使用方法を示します。

// main.cpp in a Console App project.
#include <windows.h>
#include <wil/resource.h>
#include <netfw.h>

// {26548e4f-d486-4a1d-8a1d-22b0837cd53b}
const GUID DYNAMIC_KEYWORD_ADDRESS_ID_1 =
{
    0x26548e4f,
    0xd486,
    0x4a1d,
    {0x8a,0x1d,0x22,0xb0,0x83,0x7c,0xd5,0x3b}
};


// {e9d5c993-9369-4a96-8228-9c5c37aac51a}
const GUID DYNAMIC_KEYWORD_ADDRESS_ID_2 =
{
    0xe9d5c993,
    0x9369,
    0x4a96,
    {0x82,0x28,0x9c,0x5c,0x37,0xaa,0xc5,0x1a}
};

int main()
{
    DWORD error = ERROR_SUCCESS;
    PFN_FWDELETEDYNAMICKEYWORDADDRESS0 deleteDynamicKeywordAddressFn = NULL;
    HMODULE moduleHandle = NULL;

    // Use LoadLibrary/GetProcAddress to invoke this function
    moduleHandle = LoadLibraryExW(L"firewallapi.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
    auto onExitFreeModuleHandle = wil::scope_exit([&]
        {
            if (moduleHandle)
            {
                FreeLibrary(moduleHandle);
            }
        });


    if (moduleHandle != NULL)
    {
        deleteDynamicKeywordAddressFn = (PFN_FWDELETEDYNAMICKEYWORDADDRESS0)GetProcAddress(
            moduleHandle,
            "FWDeleteDynamicKeywordAddress0"
        );
    }

    if (deleteDynamicKeywordAddressFn == NULL)
    {
        error = GetLastError();
        return error;
    }

    // Invoke the functions
    error = deleteDynamicKeywordAddressFn(DYNAMIC_KEYWORD_ADDRESS_ID_1);
    if (error != ERROR_SUCCESS)
    {
        wprintf(L"Failed to delete object with ID 1, err=[%d]", error);
    }

    error = deleteDynamicKeywordAddressFn(DYNAMIC_KEYWORD_ADDRESS_ID_2);
    if (error != ERROR_SUCCESS)
    {
        wprintf(L"Failed to delete object with ID 2, err=[%d]", error);
    }

    return error;
}

動的キーワード (keyword)アドレスを ID で列挙して解放する

この例では、 FWEnumDynamicKeywordAddressById0 関数と FWFreeDynamicKeywordAddressData0 関数を使用する方法を示します。

// main.cpp in a Console App project.
#include <windows.h>
#include <wil/resource.h>
#include <netfw.h>

// {26548e4f-d486-4a1d-8a1d-22b0837cd53b}
const GUID DYNAMIC_KEYWORD_ADDRESS_ID_1 =
{
    0x26548e4f,
    0xd486,
    0x4a1d,
    {0x8a,0x1d,0x22,0xb0,0x83,0x7c,0xd5,0x3b}
};

// {e9d5c993-9369-4a96-8228-9c5c37aac51a}
const GUID DYNAMIC_KEYWORD_ADDRESS_ID_2 =
{
    0xe9d5c993,
    0x9369,
    0x4a96,
    {0x82,0x28,0x9c,0x5c,0x37,0xaa,0xc5,0x1a}
};

int main()
{
    DWORD error = ERROR_SUCCESS;
    PFN_FWENUMDYNAMICKEYWORDADDRESSBYID0 enumDynamicKeywordAddressByIdFn = NULL;
    PFN_FWFREEDYNAMICKEYWORDADDRESSDATA0 freeDynamicKeywordAddressDataFn = NULL;
    HMODULE moduleHandle = NULL;
    PFW_DYNAMIC_KEYWORD_ADDRESS_DATA0 dynamicKeywordAddressData = NULL;

    // Use LoadLibrary/GetProcAddress to invoke this function
    moduleHandle = LoadLibraryExW(L"firewallapi.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
    auto onExitFreeModuleHandle = wil::scope_exit([&]
        {
            if (moduleHandle)
            {
                FreeLibrary(moduleHandle);
            }
        });

    if (moduleHandle != NULL)
    {
        enumDynamicKeywordAddressByIdFn = (PFN_FWENUMDYNAMICKEYWORDADDRESSBYID0)GetProcAddress(
            moduleHandle,
            "FWEnumDynamicKeywordAddressById0"
        );
        freeDynamicKeywordAddressDataFn = (PFN_FWFREEDYNAMICKEYWORDADDRESSDATA0)GetProcAddress(
            moduleHandle,
            "FWFreeDynamicKeywordAddressData0"
        );
    }

    if (enumDynamicKeywordAddressByIdFn == NULL ||
        freeDynamicKeywordAddressDataFn == NULL)
    {
        error = GetLastError();
        return error;
    }

    error = enumDynamicKeywordAddressByIdFn(
        DYNAMIC_KEYWORD_ADDRESS_ID_1,
        &dynamicKeywordAddressData
    );
    if (error != ERROR_SUCCESS)
    {
        return error;
    }

    if (dynamicKeywordAddressData != NULL)
    {
        // Process this dynamic keyword address
    }

    // Free the dynamic keyword address
    freeDynamicKeywordAddressDataFn(dynamicKeywordAddressData);
    return error;
}

動的なキーワード (keyword) アドレスを列挙して解放する (種類別)

この例では、 FWEnumDynamicKeywordAddressesByType0 関数と FWFreeDynamicKeywordAddressData0 関数を使用する方法を示します。

// main.cpp in a Console App project.
#include <windows.h>
#include <wil/resource.h>
#include <netfw.h>

int main()
{
    DWORD error = ERROR_SUCCESS;
    PFN_FWENUMDYNAMICKEYWORDADDRESSESBYTYPE0 enumDynamicKeywordAddressesByTypeFn = NULL;
    PFN_FWFREEDYNAMICKEYWORDADDRESSDATA0 freeDynamicKeywordAddressDataFn = NULL;
    HMODULE moduleHandle = NULL;

    PFW_DYNAMIC_KEYWORD_ADDRESS_DATA0 dynamicKeywordAddressData = NULL;
    PFW_DYNAMIC_KEYWORD_ADDRESS_DATA0 currDynamicKeywordAddressData = NULL;

    // Use LoadLibrary/GetProcAddress to invoke this function
    moduleHandle = LoadLibraryExW(L"firewallapi.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
    auto onExitFreeModuleHandle = wil::scope_exit([&]
        {
            if (moduleHandle)
            {
                FreeLibrary(moduleHandle);
            }
        });

    if (moduleHandle != NULL)
    {
        enumDynamicKeywordAddressesByTypeFn = (PFN_FWENUMDYNAMICKEYWORDADDRESSESBYTYPE0)GetProcAddress(
            moduleHandle,
            "FWEnumDynamicKeywordAddressesByType0"
        );
        freeDynamicKeywordAddressDataFn = (PFN_FWFREEDYNAMICKEYWORDADDRESSDATA0)GetProcAddress(
            moduleHandle,
            "FWFreeDynamicKeywordAddressData0"
        );
    }

    if (enumDynamicKeywordAddressesByTypeFn == NULL ||
        freeDynamicKeywordAddressDataFn == NULL)
    {
        error = GetLastError();
        return error;
    }

    // Invoke enum for ALL dynamic keyword addresses
    error = enumDynamicKeywordAddressesByTypeFn(
        FW_DYNAMIC_KEYWORD_ADDRESS_ENUM_FLAGS_ALL,
        &dynamicKeywordAddressData
    );
    if (error != ERROR_SUCCESS)
    {
        return error;
    }

    currDynamicKeywordAddressData = dynamicKeywordAddressData;
    while (currDynamicKeywordAddressData != NULL)
    {
        // Process this dynamic keyword address

        // iterate to the next one in the list
        currDynamicKeywordAddressData = currDynamicKeywordAddressData->next;
    }

    // Free the dynamic keyword addresses
    freeDynamicKeywordAddressDataFn(dynamicKeywordAddressData);

    return error;
}

動的なキーワード (keyword) アドレスを更新する

この例では、 FWUpdateDynamicKeywordAddress0 関数の使用方法を示します。

// main.cpp in a Console App project.
#include <windows.h>
#include <wil/resource.h>
#include <netfw.h>

// {26548e4f-d486-4a1d-8a1d-22b0837cd53b}
const GUID DYNAMIC_KEYWORD_ADDRESS_ID_1 =
{
    0x26548e4f,
    0xd486,
    0x4a1d,
    {0x8a,0x1d,0x22,0xb0,0x83,0x7c,0xd5,0x3b}
};

int main()
{
    DWORD error = ERROR_SUCCESS;
    PFN_FWUPDATEDYNAMICKEYWORDADDRESS0 updateDynamicKeywordAddressFn = NULL;
    HMODULE moduleHandle = NULL;
    BOOL appendToCurrentAddresses = TRUE;

    // Use LoadLibrary/GetProcAddress to invoke this function
    moduleHandle = LoadLibraryExW(L"firewallapi.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
    auto onExitFreeModuleHandle = wil::scope_exit([&]
        {
            if (moduleHandle)
            {
                FreeLibrary(moduleHandle);
            }
        });

    if (moduleHandle != NULL)
    {
        updateDynamicKeywordAddressFn = (PFN_FWUPDATEDYNAMICKEYWORDADDRESS0)GetProcAddress(
            moduleHandle,
            "FWUpdateDynamicKeywordAddress0"
        );
    }

    if (updateDynamicKeywordAddressFn == NULL)
    {
        error = GetLastError();
        return error;
    }

    // Invoke the function
    error = updateDynamicKeywordAddressFn(
        DYNAMIC_KEYWORD_ADDRESS_ID_1,
        L"20.0.0.5",
        appendToCurrentAddresses);
    return error;
}

動的キーワード (keyword)アドレス変更通知をサブスクライブして処理する

この例では、 FwpmDynamicKeywordSubscribe0 関数と FwpmDynamicKeywordUnsubscribe0 関数と 、FWPM_DYNAMIC_KEYWORD_CALLBACK0 コールバックを使用する方法を示します。

// main.cpp in a Console App project.
#include <windows.h>
#include <netfw.h>
#include <fwpmu.h>
#pragma comment(lib, "Fwpuclnt")

void CALLBACK TestCallback(_Inout_ VOID* /*pNotification*/, _Inout_ VOID* pContext)
{
    DWORD error = ERROR_SUCCESS;
    PFN_FWENUMDYNAMICKEYWORDADDRESSESBYTYPE0 enumDynamicKeywordAddressesByTypeFn = NULL;
    PFN_FWFREEDYNAMICKEYWORDADDRESSDATA0 freeDynamicKeywordAddressDataFn = NULL;
    HMODULE moduleHandle = NULL;

    PFW_DYNAMIC_KEYWORD_ADDRESS_DATA0 dynamicKeywordAddressData = NULL;
    PFW_DYNAMIC_KEYWORD_ADDRESS_DATA0 currDynamicKeywordAddressData = NULL;
    HANDLE* waitHandle = (HANDLE*)pContext;

    // Use LoadLibrary/GetProcAddress to invoke this function
    moduleHandle = LoadLibraryW(L"firewallapi.dll");
    if (moduleHandle != NULL)
    {
        enumDynamicKeywordAddressesByTypeFn = (PFN_FWENUMDYNAMICKEYWORDADDRESSESBYTYPE0)GetProcAddress(
            moduleHandle,
            "FWEnumDynamicKeywordAddressesByType0"
        );
        freeDynamicKeywordAddressDataFn = (PFN_FWFREEDYNAMICKEYWORDADDRESSDATA0)GetProcAddress(
            moduleHandle,
            "FWFreeDynamicKeywordAddressData0"
        );
    }

    if (enumDynamicKeywordAddressesByTypeFn == NULL ||
        freeDynamicKeywordAddressDataFn == NULL)
    {
        return;
    }

    // Invoke enum for ALL AutoResolve dynamic keyword addresses
    error = enumDynamicKeywordAddressesByTypeFn(
        FW_DYNAMIC_KEYWORD_ADDRESS_ENUM_FLAGS_AUTO_RESOLVE,
        &dynamicKeywordAddressData
    );
    if (error != ERROR_SUCCESS)
    {
        return;
    }

    currDynamicKeywordAddressData = dynamicKeywordAddressData;
    while (currDynamicKeywordAddressData != NULL)
    {
        // Process this dynamic keyword address

        currDynamicKeywordAddressData = currDynamicKeywordAddressData->next;
    }

    // Free the dynamic keyword addresses
    freeDynamicKeywordAddressDataFn(dynamicKeywordAddressData);

    SetEvent(*waitHandle);
}

int main()
{
    DWORD error = ERROR_SUCCESS;
    HANDLE notifyHandle;
    HANDLE waitHandle;

    waitHandle = CreateEventW(
        NULL,
        TRUE,
        FALSE,
        L"subscriptionWaitEvent"
    );


    // Subscribe for change notifications
    error = FwpmDynamicKeywordSubscribe0(
        FWPM_NOTIFY_ADDRESSES_AUTO_RESOLVE,
        TestCallback,
        &waitHandle,
        &notifyHandle);
    if (error != ERROR_SUCCESS)
    {
        return error;
    }

    WaitForSingleObject(waitHandle, INFINITE);

    // When client is ready to unsubscribe
    error = FwpmDynamicKeywordUnsubscribe0(notifyHandle);

    return error;
}