windows的WFP过滤域名

经过多方的调研,发现,域名过滤其实本质也是IP地址的过滤,我们接着上篇文章来续写WFP过滤域名的方法:其实大致思路是这样的,首选将域名调用本地的DNS解析成IP地址,然后再将IP地址使用上篇文章的方法添加过滤器,但是这个时候有个问题,就是域名对应的IP地址可能会更新可能会变化,怎么办呢?我的初步解决办法是再添加了过滤器后,创建一个定时任务或者说创建一个线程,定时去DNS解析域名,将解析出来的IP地址去更新之前创建的过滤器,即可实现WFP域名过滤的功能。

1、解析域名

我的入参是多个域名的vector,在解析完vector后,再将解析的Ip地址集合以vector的方式返回,简易代码如下:

cpp 复制代码
DWORD FilterFunC::DomainsToIps(const std::vector<std::string>& domains,std::vector<std::string>& ips) {
    DWORD res = ERROR_SUCCESS;
    // 2. 使用 getaddrinfo 解析域名(示例:允许访问 example.com)
    struct addrinfo hints = { 0 };
    hints.ai_family = AF_INET;  // 只支持 IPv4
    hints.ai_socktype = SOCK_STREAM;

    for (auto domain : domains) {
        struct addrinfo* result = NULL;
        res = getaddrinfo(domain.c_str(), NULL, &hints, &result);
        if (res != 0 || result == NULL)
        {   
            domain = "DomainsToIps 域名转换错误:"+domain;
            ERROR_PRINT(domain.c_str(),ERROR_INVALID_FUNCTION);
            continue;
        }
        sockaddr_in* ipv4_addr = (sockaddr_in*)result->ai_addr;
        uint32_t ip = ipv4_addr->sin_addr.S_un.S_addr; // 网络字节序IP地址
        std::string ipStr = Uint32ToIpStr(ntohl(ip));   
        ips.push_back(ipStr);
    }
    return res;
}

要使用getaddrinfo函数进行转换,需要包含以下头文件

#include <winsock2.h>

#include <ws2tcpip.h>

2、添加过滤器

可以看到上面的输出已经是ip地址的vector数组了,然后使用此数组,去创建多IP的过滤器即可:

cpp 复制代码
DWORD FilterFunC::AddWFPFilterArray(HANDLE engineHandle, const std::vector<std::string>& ipAddresses,GUID filterKeyDef) {
    DWORD result = ERROR_SUCCESS;
    FWPM_FILTER0 filter = {};
    //filter.providerKey = outProviderGUID;
    filter.displayData.name = const_cast<wchar_t*>(L"IP Whitelist");
    filter.displayData.description = const_cast<wchar_t*>(L"Block traffic to Ips");
    filter.layerKey = FWPM_LAYER_ALE_AUTH_CONNECT_V4; // IPv4包层
    filter.weight.type = FWP_EMPTY; // 默认权重
    filter.action.type = FWP_ACTION_PERMIT; // 允许,白名单
    filter.numFilterConditions = ipAddresses.size();
    filter.filterKey = filterKeyDef;

    FWPM_FILTER_CONDITION0 condition[ipAddresses.size()];
    // Initialize conditions for each IP address
    for (size_t i = 0; i < ipAddresses.size(); ++i) {
        condition[i].fieldKey = FWPM_CONDITION_IP_REMOTE_ADDRESS;
        condition[i].matchType = FWP_MATCH_EQUAL;
        condition[i].conditionValue.type = FWP_UINT32;
        
        // Convert IP address string to DWORD
        unsigned long ipAddress = inet_addr(ipAddresses[i].c_str());
        if (ipAddress == INADDR_NONE) {
            std::cerr << "Invalid IP address: " << ipAddresses[i] << std::endl;
            return ERROR_INVALID_DATA;
        }
        condition[i].conditionValue.uint32 = htonl(ipAddress);
    }
    filter.filterCondition = condition;

    result = FwpmTransactionBegin0(engineHandle, 0); // 0 - 读写事务
    if (result != ERROR_SUCCESS) {
        // 错误处理
        ERROR_PRINT("FwpmTransactionBegin0 failed", result);
        return 1;
    }
    result = FwpmFilterAdd0(engineHandle, &filter, NULL, NULL);
    if (result != ERROR_SUCCESS) {
        ERROR_PRINT("FwpmFilterAdd0 failed", result);
        FwpmTransactionAbort0(engineHandle);
    } else {
        SUCCESS_PRINT("Filter added successfully. Traffic to is blocked.");
        FwpmTransactionCommit0(engineHandle);
    }
    return result;
}

这部分的代码和上一篇的文章的代码有些许差别,主要是是否自定义创建filterKey 的区别,上篇文章没有定义filterKey ,使用系统自动分配,这次的功能,将自定义的filterKey 以参数的形式传递进去。此处这样的做法是为了后续定期更新过滤器做准备,因为你需要定期更新过滤器,更新的方法是先删除后创建,删除不能全部删除过滤器,有其他人的设置,所以此处我们自定义一个过滤器的filterKey ,后面删除也通过此filterKey 来进行删除。

3、定期更新过滤器

此处不做详细的代码示例,此处比较简单,要么是在再创建一个进程去定期执行这个事情,要么创建一个进行定期去解析域名,然后更新过滤器。

相关推荐
a程序小傲1 小时前
阿里Java面试被问:.Java 8中Stream API的常用操作和性能考量
开发语言·windows·python
Tony11542 小时前
Windows无法安装到这个磁盘。选中的磁盘具有MBR分区表。在EFI系统上,Windows只能安装到GPT磁盘。
windows·diskgenius
love530love2 小时前
【笔记】Intel oneAPI 开发环境配置
人工智能·windows·笔记·oneapi·onednn·deep neural
分布式存储与RustFS3 小时前
实测!Windows环境下RustFS的安装与避坑指南
人工智能·windows·rust·对象存储·企业存储·rustfs
浪潮IT馆3 小时前
删除Windows系统硬盘的EFI系统分区和恢复分区
windows
我就是你毛毛哥4 小时前
windows启动jmeter
windows·jmeter
取个名字太难了a4 小时前
重写 OpenProcess:绕过 Win32 API,直接进入 NT 内核(Win7 x86)
windows
MyBFuture4 小时前
C# 哈希表与堆栈队列实战指南
开发语言·windows·c#·visual studio
管理大亨4 小时前
Linux vs Windows:五大维度深度对决
linux·arm开发·windows
云技纵横7 小时前
Stream API 从入门到实践:常用操作、易错点与性能建议
开发语言·windows·python