背景
最近给自己一个手机协作软件增加防火墙规则(一直准备发布出来,但感觉写不够完善就一直拖着),于是找了一些网上资料,我感觉资料真的比较少,后面找到微软demo代码,直接copy稍微改了给自己用。
资料
Exercising the Firewall using C++ (Windows) | Microsoft Learn
微软官方代码页,我感觉这个没有下面demo好
Windows-classic-samples/FirewallConfig.cpp at main · microsoft/Windows-classic-samples (github.com)
这个直接demo代码,直接复制firewallConfig.cpp、firewallConfig.h 2个文件就可以了
代码
//这个是关键函数,这个fOpenPortForPNRP 代表是否开启PNRP 端口,这个函数我们改掉,
//我懒的复制我自己工程的代码,直接说明
HRESULT OpenFirewallForDrtSdkSample(BOOL fOpenPortForPNRP)
{
HRESULT hr = S_OK;
HRESULT hrComInitialized = S_OK;
INetFwProfile *fwProfile = NULL;
WCHAR lpFilename[1024];
BOOL fFirewallOn = FALSE;
// Initialize COM.
hr = CoInitializeEx(
0,
COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE
);
// Ignore RPC_E_CHANGED_MODE. Since we don't care what the mode is,
// we'll just use the existing mode.
hrComInitialized = hr;
if (hr != RPC_E_CHANGED_MODE)
{
if (FAILED(hr))
{
printf("CoInitializeEx failed: 0x%08lx\n", hr);
goto error;
}
}
WindowsFirewallInitialize(&fwProfile);
if (FAILED(hr))
{
printf("WindowsFirewallInitialize failed: 0x%08lx\n", hr);
goto error;
}
hr = WindowsFirewallIsOn(fwProfile, &fFirewallOn);
if (FAILED(hr))
{
printf("WindowsFirewallIsOn failed: 0x%08lx\n", hr);
goto error;
}
if(fFirewallOn)
{
hr = GetModuleFileName(
NULL,
lpFilename,
1024);
if (FAILED(hr))
{
printf("GetModuleFileName failed: 0x%08lx\n", hr);
goto error;
}
// Add DrtSdkSample to the authorized application collection.
hr = WindowsFirewallAddApp(
fwProfile,
lpFilename,
L"DrtSdkSample"//这个是规则名字,这个代表全规则
);
if (FAILED(hr))
{
printf("WindowsFirewallAddApp failed: 0x%08lx\n", hr);
goto error;
}
if(fOpenPortForPNRP)
{
// Add PNRP Port to list of globally open ports.
//这个增加指定端口,这里是3540 udp协议
hr = WindowsFirewallPortAdd(fwProfile, 3540, NET_FW_IP_PROTOCOL_UDP, L"PNRP");
if (FAILED(hr))
{
printf("WindowsFirewallPortAdd failed: 0x%08lx\n", hr);
goto error;
}
}
}
error:
// Release the firewall profile.
WindowsFirewallCleanup(fwProfile);
// Uninitialize COM.
if (SUCCEEDED(hrComInitialized))
{
CoUninitialize();
}
return hr;
}
- CoInitializeEx 初始化com ,因为他用com接口的API
- 判断防火墙是否打开
- 如果打开增加 应用程序规则(匹配指定软件指定路径,不管什么协议全部放开) WindowsFirewallAddApp
- 增加指定端口开发,跟程序没有直接关系 WindowsFirewallPortAdd
// Add DrtSdkSample to the authorized application collection.
hr = WindowsFirewallAddApp(
fwProfile,
lpFilename,
L"DrtSdkSample"//这个是规则名字,这个代表全规则
);
规则的名字,指定程序已经存在,那么规则不会生效,我开始测试以后没有生效,后面发现是我以前手动填写指定程序规则。
这个对应控制面板防火墙界面
指定端口类似下面规则
hr = WindowsFirewallPortAdd(fwProfile, 3540, NET_FW_IP_PROTOCOL_UDP, L"PNRP");
图片和代码不一样,因为我手动删除了,我随便找一条规则。
补充
如果不用代码,可以考虑创建进程然后执行防火墙命令进行增加,我只是觉得这样子卡顿一样不好。
如果不添加规则,如果软件监听端口,可能无法访问。
好久没有写博客了,最近太多事情了,主要写在自己笔记里面,我只能说obsidian 加 wps同步yyds..