Parole chiave dinamiche del firewall

Usare le API delle parole chiave dinamiche del firewall per gestire gli indirizzi delle parole chiave dinamici in Microsoft Defender Firewall. Un indirizzo di parola chiave dinamico viene usato per creare un set di indirizzi IP a cui può fare riferimento una o più regole del firewall. Gli indirizzi delle parole chiave dinamici supportano sia IPv4 che IPv6.

Nota

Per informazioni di riferimento sulle API per le API introdotte in questo argomento, vedere Informazioni di riferimento sulle parole chiave dinamiche del firewall.

Operazioni sugli indirizzi delle parole chiave dinamici

Con le API delle parole chiave dinamiche firewall, è possibile eseguire le operazioni seguenti.

  • Aggiungere indirizzi di parole chiave dinamici
  • Eliminare gli indirizzi delle parole chiave dinamici
  • Enumerare gli indirizzi delle parole chiave dinamici in base all'ID o al tipo
  • Aggiornare gli indirizzi delle parole chiave dinamici
  • Sottoscrivere e gestire le notifiche di modifica degli indirizzi delle parole chiave dinamiche

In questo argomento sono disponibili esempi di codice per tutte queste operazioni.

Dopo aver aggiunto un indirizzo di parola chiave dinamico, viene mantenuto in modo permanente tra i riavvii. È necessario eliminare un indirizzo di parola chiave dinamico dopo aver eseguito l'operazione con l'oggetto .

Esistono due classi di indirizzi di parole chiave dinamici, come descritto nelle due sezioni successive.

Indirizzi delle parole chiave dinamica AutoResolve

Il primo tipo è AutoResolve, dove il campo parola chiave rappresenta un nome risolvibile e gli indirizzi IP non vengono definiti alla creazione.

Questi oggetti devono avere automaticamente gli indirizzi IP risolti. Ovvero, non tramite un amministratore in fase di creazione dell'oggetto; né tramite il sistema operativo stesso. Un componente esterno al servizio firewall deve eseguire la risoluzione degli indirizzi IP per questi oggetti e aggiornarli in modo appropriato. L'implementazione di tale componente non rientra nell'ambito di questo contenuto.

Un indirizzo di parola chiave dinamico viene indicato come autoResolve impostando il flag di FW_DYNAMIC_KEYWORD_ADDRESS_FLAGS_AUTO_RESOLVE nell'oggetto quando si chiama la funzione FWAddDynamicKeywordAddress0 . Il campo della parola chiave deve essere usato per rappresentare il valore risolto, ovvero un nome di dominio completo (FQDN) o un nome host. Il campo indirizzi deve inizialmente essere NULL per questi oggetti. Questi oggetti non avranno gli indirizzi IP persistenti nei cicli di avvio e si dovrebbe rivalutare/ricompopolare gli indirizzi durante il ciclo di avvio successivo.

Nota

Gli oggetti degli indirizzi di parole chiave dinamici AutoResolve attivano notifiche su FWAddDynamicKeywordAddress0 e FWDeleteDynamicKeywordAddress0, ma non FWUpdateDynamicKeywordAddress0.

Indirizzi di parole chiave dinamici non AutoResolve

Il secondo tipo non è AutoResolve, dove il campo della parola chiave è qualsiasi stringa e gli indirizzi vengono definiti in fase di creazione.

Questi oggetti vengono usati per archiviare un set di indirizzi IP, subnet o intervalli. Il campo della parola chiave qui viene usato per praticità di gestione e può essere impostato su qualsiasi stringa. Il campo indirizzi deve essere diverso da NULL alla creazione. Gli indirizzi per questi oggetti vengono mantenuti tra i riavvii.

Nota

Gli oggetti degli indirizzi di parole chiave dinamici non AutoResolve attivano notifiche su FWAddDynamicKeywordAddress0, FWDeleteDynamicKeywordAddress0 e anche FWUpdateDynamicKeywordAddress0.

Altre informazioni sugli indirizzi delle parole chiave dinamici

Tutti gli indirizzi delle parole chiave dinamici devono avere un identificatore GUID univoco per rappresentarli.

L'API FwpmDynamicKeywordSubscribe0 invia notifiche a un client quando gli indirizzi delle parole chiave dinamici cambiano. Non è disponibile alcun payload recapitato al client che descrive esattamente ciò che è cambiato nel sistema. Se è necessario conoscere gli oggetti modificati, è necessario eseguire una query sullo stato corrente degli oggetti nel sistema usando le API FWEnumDynamicKeywordAddressById0 o FWEnumDynamicKeywordAddressesByType0 . È possibile usare i vari flag per richiedere notifiche solo per un subset di oggetti. Se non si usano flag, le notifiche di modifica verranno recapitate per tutti gli oggetti.

Una regola del firewall può usare indirizzi di parole chiave dinamici anziché definire in modo esplicito gli indirizzi IP per la relativa condizione di indirizzo remoto. Una regola del firewall può usare sia indirizzi di parole chiave dinamici che intervalli di indirizzi remoti definiti in modo statico. Un singolo oggetto indirizzo parola chiave dinamico può essere riutilizzato tra più regole del firewall. Se una regola del firewall non dispone di indirizzi remoti configurati, ovvero configurati con solo oggetti AutoResolve non ancora risolti, la regola non verrà applicata. Inoltre, se una regola usa più indirizzi di parole chiave dinamici, la regola verrà applicata per tutti gli indirizzi attualmente risolti, anche se sono presenti altri oggetti non ancora risolti. Quando viene aggiornato un indirizzo di parola chiave dinamico, tutti gli oggetti regola associati avranno anche gli indirizzi remoti aggiornati.

Il sistema operativo stesso non applica alcuna dipendenza tra una regola e un indirizzo parola chiave dinamica. Ciò significa che è possibile creare prima di tutto l'oggetto: la regola può fare riferimento agli ID degli indirizzi delle parole chiave dinamici che non esistono ancora (in tal caso, la regola non verrà applicata). Inoltre, è possibile eliminare un indirizzo di parola chiave dinamico anche se è in uso da una regola del firewall. Questo argomento illustra come un amministratore può configurare le regole per l'uso dell'indirizzo della parola chiave dinamica.

Esempi di codice

Per provare ognuno di questi esempi di codice, avviare prima Visual Studio e creare un nuovo progetto in base al modello di progetto app console . È sufficiente sostituire il contenuto di con l'elenco di main.cpp codice.

La maggior parte degli esempi di codice usa le librerie di implementazioni di Windows (WIL). Un modo pratico per installare WIL consiste nel passare a Visual Studio, fare clic su Project>Manage NuGet Packages( Gestione pacchetti NuGet).>Sfogliare, digitare o incollare Microsoft.Windows.ImplementationLibrary nella casella di ricerca, selezionare l'elemento nei risultati della ricerca e quindi fare clic su Installa per installare il pacchetto per tale progetto.

Nota

I tipi di puntatore per le funzioni gratuite NetFw vengono pubblicati tramite NetFw.h, ma non viene pubblicata una libreria di collegamenti statici. Usare il modello LoadLibraryExW/GetProcAddress per chiamare queste funzioni, come illustrato in questi esempi di codice.

Aggiungere un indirizzo di parola chiave dinamico

In questo esempio viene illustrato come usare la funzione 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;
}

Eliminare un indirizzo di parola chiave dinamico

In questo esempio viene illustrato come usare la funzione 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;
}

Enumerare e liberare indirizzi di parole chiave dinamica in base all'ID

In questo esempio viene illustrato come usare le funzioni FWEnumDynamicKeywordAddressById0 e 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;
}

Enumerare e liberare indirizzi di parole chiave dinamica per tipo

In questo esempio viene illustrato come usare le funzioni FWEnumDynamicKeywordAddressesByType0 e 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;
}

Aggiornare gli indirizzi delle parole chiave dinamici

In questo esempio viene illustrato come usare la funzione 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;
}

Sottoscrivere e gestire le notifiche di modifica degli indirizzi delle parole chiave dinamiche

In questo esempio viene illustrato come usare le funzioni FwpmDynamicKeywordSubscribe0 e FwpmDynamicKeywordUnsubscribe0 e il callback 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;
}