Compartir a través de


Palabras clave dinámicas del firewall

Las API de palabras clave dinámicas del firewall se usan para administrar direcciones de palabras clave dinámicas en Microsoft Defender Firewall. Una dirección de palabra clave dinámica se usa para crear un conjunto de direcciones IP a las que una o varias reglas de firewall pueden hacer referencia. Las direcciones de palabras clave dinámicas admiten IPv4 e IPv6.

Nota

Para obtener contenido de referencia de API para las API introducidas en este tema, consulte Referencia de palabras clave dinámicas de firewall.

Operaciones en direcciones de palabras clave dinámicas

Con las API de palabras clave dinámicas de Firewall, puede realizar las siguientes operaciones.

  • Adición de direcciones de palabras clave dinámicas
  • Eliminación de direcciones de palabras clave dinámicas
  • Enumerar direcciones de palabras clave dinámicas por identificador o por tipo
  • Actualización de direcciones de palabras clave dinámicas
  • Suscribirse y controlar las notificaciones de cambio de dirección de palabras clave dinámicas

Hay ejemplos de código para todas esas operaciones más adelante en este tema.

Una vez que haya agregado una dirección de palabra clave dinámica, se conserva en los reinicios. Debe eliminar una dirección de palabra clave dinámica una vez que haya terminado con el objeto .

Hay dos clases de direcciones de palabras clave dinámicas, como se describe en las dos secciones siguientes.

Direcciones de palabras clave dinámicas de AutoResolve

El primer tipo es AutoResolve, donde el campo de palabra clave representa un nombre que se puede resolver y las direcciones IP no se definen al crearse.

Estos objetos están diseñados para que sus direcciones IP se resuelvan automáticamente. Es decir, no a través de un administrador en tiempo de creación de objetos; ni a través del propio sistema operativo (SO). Un componente fuera del servicio de firewall debe realizar la resolución de direcciones IP para estos objetos y actualizarlos correctamente. La implementación de este componente está fuera del ámbito de este contenido.

Una dirección de palabra clave dinámica se indica como AutoResolve estableciendo la marca FW_DYNAMIC_KEYWORD_ADDRESS_FLAGS_AUTO_RESOLVE en el objeto al llamar a la función FWAddDynamicKeywordAddress0 . El campo de palabra clave debe usarse para representar el valor que se va a resolver, es decir, un nombre de dominio completo (FQDN) o un nombre de host. El campo de direcciones debe ser inicialmente NULL para estos objetos. Estos objetos no tendrán sus direcciones IP persistentes en los ciclos de arranque y debe volver a evaluar o volver a rellenar sus direcciones durante el siguiente ciclo de arranque.

Nota

Los objetos de dirección de palabra clave dinámica AutoResolve desencadenan notificaciones en FWAddDynamicKeywordAddress0 y FWDeleteDynamicKeywordAddress0, pero no FWUpdateDynamicKeywordAddress0.

Direcciones de palabras clave dinámicas que no son AutoResolve

El segundo tipo no es AutoResolve, donde el campo de palabra clave es cualquier cadena y las direcciones se definen en el momento de la creación.

Estos objetos se usan para almacenar un conjunto de direcciones IP, subredes o intervalos. El campo de palabra clave aquí se usa para la comodidad de administración y se puede establecer en cualquier cadena. El campo de direcciones debe ser distinto de NULL al crearse. Las direcciones de estos objetos se conservan entre reinicios.

Nota

Los objetos de dirección de palabra clave dinámica que no son AutoResolve desencadenan notificaciones en FWAddDynamicKeywordAddress0, FWDeleteDynamicKeywordAddress0 y también FWUpdateDynamicKeywordAddress0.

Más información sobre las direcciones de palabras clave dinámicas

Todas las direcciones de palabras clave dinámicas deben tener un identificador GUID único para representarlas.

La API FwpmDynamicKeywordSubscribe0 entrega notificaciones a un cliente cuando cambian las direcciones de palabras clave dinámicas. No hay ninguna carga entregada al cliente que describa exactamente lo que ha cambiado en el sistema. Si necesita saber qué objetos han cambiado, debe consultar el estado actual de los objetos en el sistema mediante las API FWEnumDynamicKeywordAddressById0 o FWEnumDynamicKeywordAddressesByType0 . Puede usar las distintas marcas para solicitar notificaciones solo para un subconjunto de objetos. Si no usa marcas, las notificaciones de cambio se entregarán para todos los objetos.

Una regla de firewall puede usar direcciones de palabra clave dinámicas en lugar de definir explícitamente direcciones IP para su condición de dirección remota. Una regla de firewall puede usar direcciones de palabras clave dinámicas y intervalos de direcciones remotas definidos estáticamente. Se puede volver a usar un solo objeto de dirección de palabra clave dinámica en varias reglas de firewall. Si una regla de firewall no tiene direcciones remotas configuradas (es decir, configuradas solo con objetos AutoResolve que aún no se han resuelto), no se aplicará la regla. Además, si una regla usa varias direcciones de palabras clave dinámicas, la regla se aplicará para todas las direcciones que se resuelven actualmente, incluso si hay otros objetos que aún no se han resuelto. Cuando se actualiza una dirección de palabra clave dinámica, todos los objetos de regla asociados también tendrán sus direcciones remotas actualizadas.

El propio sistema operativo (SO) no aplica ninguna dependencia entre una regla y una dirección de palabra clave dinámica. Esto significa que cualquiera de los objetos se puede crear primero: la regla puede hacer referencia a identificadores de dirección de palabra clave dinámica que aún no existen (en cuyo caso, la regla no se aplicará). Además, puede eliminar una dirección de palabra clave dinámica incluso si está en uso por una regla de firewall. En este tema se describe cómo un administrador puede configurar reglas para usar la dirección de palabra clave dinámica.

Ejemplos de código

Para probar cada uno de estos ejemplos de código, inicie Primero Visual Studio y cree un nuevo proyecto basado en la plantilla de proyecto Aplicación de consola . Solo puede reemplazar el contenido de por la lista de main.cpp código.

La mayoría de los ejemplos de código usan las bibliotecas de implementación de Windows (WIL). Una forma cómoda de instalar WIL es ir a Visual Studio, hacer clic en Project>Manage NuGet Packages...>Busque, escriba o pegue Microsoft.Windows.ImplementationLibrary en el cuadro de búsqueda, seleccione el elemento en los resultados de la búsqueda y, a continuación, haga clic en Instalar para instalar el paquete de ese proyecto.

Nota

Los tipos de puntero para las funciones gratuitas de NetFw se publican a través NetFw.hde , pero no se publica una biblioteca de vínculos estáticos. Use el patrónGetProcAddressloadLibraryExW/ para llamar a estas funciones, como se muestra en estos ejemplos de código.

Adición de una dirección de palabra clave dinámica

En este ejemplo se muestra cómo usar la función 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;
}

Eliminación de una dirección de palabra clave dinámica

En este ejemplo se muestra cómo usar la función 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;
}

Enumerar y liberar direcciones de palabras clave dinámicas por identificador

En este ejemplo se muestra cómo usar las funciones FWEnumDynamicKeywordAddressById0 y 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;
}

Enumerar y liberar direcciones de palabras clave dinámicas por tipo

En este ejemplo se muestra cómo usar las funciones FWEnumDynamicKeywordAddressesByType0 y 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;
}

Actualización de direcciones de palabras clave dinámicas

En este ejemplo se muestra cómo usar la función 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;
}

Suscribirse y controlar las notificaciones de cambio de dirección de palabras clave dinámicas

En este ejemplo se muestra cómo usar las funciones FwpmDynamicKeywordSubscribe0 y FwpmDynamicKeywordUnsubscribe0 y la devolución de llamada 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;
}