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、定期更新过滤器

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

相关推荐
笨鸟先飞,勤能补拙2 小时前
从预测到决策:人工智能与机器学习的系统方法、工程闭环与现实边界
大数据·人工智能·windows·python·机器学习·密码学
程序员-李俞3 小时前
Mistral OCR 4真正改变的不是“识字”:文档AI正在变成Agent的数据入口
人工智能·windows·ai作画·aigc·ocr·ai编程·ai写作
C++ 老炮儿的技术栈4 小时前
Qt5.9.1 Windows 完整开发环境搭建流程
开发语言·c++·windows·qt·编辑器·代码化
笨鸟先飞,勤能补拙5 小时前
AI与深度学习:从原理到应用
人工智能·windows·vscode·深度学习·机器学习·网络安全·github
bkspiderx5 小时前
从零开始:VS Code搭建C/C++开发环境全指南(Windows/macOS/Linux)
c语言·c++·windows·vs code·c/c++开发环境
Rudon滨海渔村6 小时前
镜像转换esd转iso - VMware虚拟机如何安装或恢复(.esd)的Windows系统
windows·vmware·iso·esd
西安景驰电子7 小时前
《PTP精确时间协议系列》第二篇:工程部署、调试与性能优化
运维·服务器·网络·数据库·windows·性能优化
问天_观心8 小时前
零基础在windows环境下的WSL使用llamafactory(一)
人工智能·windows·python·神经网络·语言模型·github·模型蒸馏
xrkhy8 小时前
redis-shake的使用windows版本
数据库·windows·redis
我一定会有钱9 小时前
打造完美工作流:Git 配置”一次推送,三端同步”(Gitee/GitCode/GitHub)
开发语言·windows·vscode·搜索引擎·gitlab·github·visual studio code