小明思考

高性能服务器端计算
posts - 70, comments - 428, trackbacks - 0, articles - 0
  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

网络包过滤的实现

Posted on 2006-04-19 16:53 小明 阅读(3673) 评论(6)  编辑 收藏 引用 所属分类: Network/ACE
最近在使用金山词霸2005,由于金山词霸2005在启动的时候会发一个UDP包到局域网,然后检测是否有相同序列号的金山词霸,如果发现则要求退出。甚为无奈。windows 2000自带有防火墙的功能,但是只有Permit all 和 Permit only两种模式,居然没有Deny only,奇怪。

所以我就查了一下MSDN,发现有Routing and Remote Access Service一类的API可以用。
于是程序的流程就是这样
1.设置临时防火墙,以阻挡发到端口11113的UDP包
2.启动金山词霸
3.删除设置

代码:


#include 
<stdlib.h>
#include 
<Iphlpapi.h>
#include 
<Fltdefs.h>

#pragma comment(lib, 
"Iphlpapi.lib")

const int XDICT_PORT = 11113;

unsigned 
long CharToIp(const char *sIp)
{
    
int octets[4];
    
int i;
    
const char * auxCad = sIp;
    unsigned 
long lIp = 0;
    
    
//we extract each octet of the ip address
    
//atoi will get characters until it found a non numeric character(in our case '.')
    for(i = 0; i < 4; i++)
    {
        octets[i] 
= atoi(auxCad);

        
if(octets[i] < 0 || octets[i] > 255)
            
return 0;

        lIp 
|= (octets[i] << (i*8));

        
//update auxCad to point to the next octet
        auxCad = strchr(auxCad, '.');

        
if(auxCad == NULL && i!=3)
            
return -1;

        auxCad
++;
    }
    
return lIp;
}

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     
int       nCmdShow)
{
    
//first get adapter info
    PIP_ADAPTER_INFO pAdapterInfo = NULL,tmp;
    unsigned 
long len = 0;
     GetAdaptersInfo(pAdapterInfo,
&len);
    pAdapterInfo 
= (PIP_ADAPTER_INFO) malloc (len);
    DWORD result 
= GetAdaptersInfo(pAdapterInfo, &len);
    
if(result!=ERROR_SUCCESS)
    {
        MessageBox(NULL,
"Fail to call GetAdaptersInfo","ERROR",MB_OK);
        
return -1;
    }

    
//create filters interface
    INTERFACE_HANDLE hInterface = NULL;
    result 
= PfCreateInterface(0,PF_ACTION_FORWARD,PF_ACTION_FORWARD,FALSE,TRUE,&hInterface);
    
if(result!=NO_ERROR)
    {
        MessageBox(NULL,
"Fail to call PfCreateInterface","ERROR",MB_OK);
        
return -1;
    }

    
//add the filter to adapter
    unsigned long dmp = 0;
    PF_FILTER_DESCRIPTOR ipFlt;
    ipFlt.dwFilterFlags     
= 0;
    ipFlt.dwRule            
= 0;
    ipFlt.pfatType          
= PF_IPV4;
    ipFlt.dwProtocol        
= FILTER_PROTO_UDP;
    ipFlt.fLateBound        
= 0;
    ipFlt.wSrcPort          
= 0;
    ipFlt.wSrcPortHighRange 
= 0;
    ipFlt.wDstPort          
= XDICT_PORT;
    ipFlt.wDstPortHighRange 
= XDICT_PORT;
    ipFlt.SrcAddr 
= (PBYTE)&dmp ;
    ipFlt.SrcMask 
= (PBYTE)&dmp;
    ipFlt.DstAddr 
= (PBYTE)&dmp;
    ipFlt.DstMask 
= (PBYTE)&dmp;

    
//bind
    IP_ADDR_STRING *localIp;
    
for(tmp=pAdapterInfo;tmp != NULL;tmp=tmp->Next)
    {
            
// each ip of a adapter
            for(localIp=&tmp->IpAddressList;localIp!=NULL;localIp=localIp->Next)
            {
                unsigned 
long ul = CharToIp(localIp->IpAddress.String);
                PBYTE lIp 
= (PBYTE)&ul;
                PfBindInterfaceToIPAddress(hInterface, PF_IPV4, lIp);
            }
    }

    result 
= PfAddFiltersToInterface(hInterface,1,&ipFlt,1,&ipFlt,NULL);
    
if(result!=NO_ERROR)
    {
        MessageBox(NULL,
"Fail to call PfAddFiltersToInterface","ERROR",MB_OK);
        
return -1;
    }

    
//start XDict
    STARTUPINFO si;
    PROCESS_INFORMATION pi;
    ZeroMemory( 
&si, sizeof(si) );
    si.cb 
= sizeof(si);
    ZeroMemory( 
&pi, sizeof(pi) );
    ::CreateProcess(NULL,
"XDICT.exe",
        NULL,             
// Process handle not inheritable. 
        NULL,             // Thread handle not inheritable. 
        FALSE,            // Set handle inheritance to FALSE. 
        0,                // No creation flags. 
        NULL,             // Use parent's environment block. 
        NULL,             // Use parent's starting directory. 
        &si,              // Pointer to STARTUPINFO structure.
        &pi );            // Pointer to PROCESS_INFORMATION structure.

    
// Wait until child process exits.
    WaitForSingleObject( pi.hProcess, INFINITE );
    
// Close process and thread handles. 
    CloseHandle( pi.hProcess );
    CloseHandle( pi.hThread );


    
//remove filter
    for(tmp=pAdapterInfo;tmp != NULL;tmp=tmp->Next)
    {
        result 
= PfRemoveFiltersFromInterface(hInterface,1,&ipFlt,1,&ipFlt);
        
if(result!=NO_ERROR)
        {
            MessageBox(NULL,
"Fail to call PfRemoveFiltersFromInterface","ERROR",MB_OK);
            
return -1;
        }
    }
    PfUnBindInterface(hInterface); 
    PfDeleteInterface(hInterface);

    
//free
    free(pAdapterInfo);
    
return 0;
}

使用的API有
GetAdapaterInfo --- 取得网卡的信息,如ip
PfCreateInterface ----Create一个Filter Interface
PfBindInterfaceToIPAddress ----绑定Filter Interface到IP
PfAddFiltersToInterface ----增加Filter到Interface
PfRemoveFiltersFromInterface ---Remove Filter
PfUnBindInterface---取消绑定到ip
PfDeleteInterface---删除Filter Interface


附上可执行文件: http://www.cppblog.com/Files/sandy/XDictWrapper.zip
使用的时候解压放在金山词霸同一个目录就可以了,然后通过这个程序来启动金山词霸。

Feedback

# re: 网络包过滤的实现  回复  更多评论   

2006-04-20 11:26 by 小软
阻断UDP包,不错哦

# re: 网络包过滤的实现  回复  更多评论   

2006-08-21 20:11 by 大风
很好,顶了.

# re: 网络包过滤的实现  回复  更多评论   

2007-05-11 14:31 by anfy
up

# re: 网络包过滤的实现  回复  更多评论   

2007-05-14 21:18 by anfy
大哥
能能不能把那个
Iphlpapi.h
Fltdefs.h
Iphlpapi.lib
给我发一个啊
2706204·

# re: 网络包过滤的实现  回复  更多评论   

2007-05-14 21:19 by anfy
大哥
能能不能把那个
Iphlpapi.h
Fltdefs.h
Iphlpapi.lib
给我发一个啊
2706204@163.com

# re: 网络包过滤的实现  回复  更多评论   

2012-03-15 16:56 by yc
这段程序只有在windows2000系统上才有效么?

只有注册用户登录后才能发表评论。
【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理