inpfw 模块防火墙简介
inpfw 是基于 SylixOS 的一款报文截获分析工具。借助它,可以实现基于 SylixOS 的各种嵌入式使用场合的防火墙工具开发。inpfw 具备如下功能:
- 支持多个模块的注册;
- 支持多个网卡报文截获分析;
- 支持截获网卡驱动传入到协议栈的所有报文;
- 支持报文动态分析,并将结果传入到注册的模块;
- 支持动态黑白名单;
- 支持记录发送方设备信息;
- 支持模块自定义发送方保存信息;
- 支持禁止 inpfw 动态删除发送端信息;
- 采用 hash + cache 模式,加速发送端信息查找速度。
inpfw 模块防火墙原理
inpfw 模块防火墙以 ko 形式,加载进 SylixOS 系统。 inpfw 加载后会将自己的 hook 注册到 SylixOS 提供的 innerfw。此时,用户及可以调用 inpfw 提供的一些 API 接口进行子模块的注册等各种操作。
inpfw 模块正常运行时,所有接收到的报文都会被 inpfw 的 hook 截获,并现在 inpfw 内部先对报文进行整体的分析,分析内容包括:
- 对报文类型进行分析,根据报文类型截获对应的报文头,包括,以太网头部,VLAN 头部,ARP 头部,IP 头部, ICMP 头部, UDP 头部, TCP头部;
- 对报文的发送端设备信息数据进行获取并管理;
完成上述两步之后,inpfw 会将分析的结果,报文,以及管理的设备信息一同发给注册的子模块接口,由子模块根据其对应的需求对报文进行进一步细处理。
等到子模块处理完成之后,inpfw 会根据子模块返回的结果,确定当前的报文是否需要被过滤;
inpfw 模块防火墙相关结构
inpfw 防火墙会为注册到其内部的子模块提供对应的报文和设备信息,这些信息主要是由以下这个结构体包含:
/*********************************************************************************************************
报文信息结构定义
*********************************************************************************************************/
struct pkt_info {
struct netdev *pIn; /* 网卡结构 */
struct pbuf *pBuf; /* 报文 */
struct eth_hdr *pEthHdr; /* eth 头 */
struct eth_vlan_hdr *pVlanHdr; /* vlan 头 */
struct etharp_hdr *pArpHdr; /* arp 头 */
struct ip_hdr *pIpHdr; /* ip 头 */
struct udp_hdr *pUdpHdr; /* udp 头 */
struct tcp_hdr *pTcpHdr; /* tcp 头 */
struct icmp_echo_hdr *pImcpHdr; /* icmp 头 */
PVOID pvRemotDevPriv; /* 对端结点私有信息 */
};
typedef struct pkt_info __PKT_INFO;
typedef struct pkt_info *__PPKT_INFO;
这个结构体主要包含以下内容:
pIn:当前收到这个报文的网卡设备
pBuf: 当前收到的完整报文(pbuf 格式)
pEthHdr: 当前报文的以太网头部信息
pVlanHdr: 当前报文的 VLAN 头部信息(如果存在)
pArpHdr: 当前报文的 ARP 头部信息(如果存在)
pIpHdr: 当前报文的 IP 头部信息(如果存在)
pUdpHdr: 当前报文的 UDP 头部信息(如果存在)
pTcpHdr: 当前报文的 TCP 头部信息(如果存在)
pImcpHdr: 当前报文的 ICMP 头部信息(如果存在)
pvRemotDevPriv: 用于保存子模块对当前报文发送端处理的相关信息
inpfw 模块防火墙使用
-
防火墙的加载:
inpfw 是基于 SylixOS 的 ko 模块,只需根据对应硬件平台编译,并加载即可。 -
防火墙操作命令:
inpfw 支持所有有线网卡的接收报文截获,其提供了 inpfw 命令,用于开启对应网卡的防火墙等功能:[root@sylixos:/root]# inpfw input arg error. USAGE: show info: inpfw [-a] | [-m] | [-d] | [-v] | [-h] -a show attched net. -m show registered mod. -d show remote dev. -v show inpfw version. -h show help info. attach or disattach net: inpfw en_name 0 / 1 0 attach net. 0 disattach net. eg. inpfw en1 1 [inpfw] Current Version: 1.3 [root@sylixos:/root]#
-a 用于显示当前已经 attach 的网卡
-m 用于显示已经注册的模块
-d 用于显示 inpfw 已经分析到的远端设备
-v 用于显示当前 inpfw 版本信息
-h 用于显示帮助信息
除了上述命令外, inpfw 也支持 proc 文件系统查看当前相关信息。
查询当前已经注册了的模块
使用 proc 文件系统查看当前防火墙注册的所有子模块信息,如下所示:
其中 FUNC_HANDLE 记录当前总模块回调函数位置。查看防火墙管理的所有网络环境里的设备
inpfw 防火墙可以管理保存当前网络环境中跟本设备通信的其他设备信息,使用 proc 文件系统查看当前防火墙管理的所有设备,使用如下:
其中, IDLE_TIME 表示当前设备空闲时间,即当前设备多久没有跟自己通信,FORBIDDEN_TIMES 表示当前设备被拉黑时间。
防火墙相关 API 介绍
inpfw 提供了如下 API ,下面对其详细介绍:
-
子模块注册:
INT32 inpFWPktAnaRegister (PCHAR pcName, UINT32 uiDevPrivLen, __PFUNC_PKT_ANA pPktAnaFunc);
参数:
pcName:子模块的名字
pcName:子模块需要的设备私有节点的长度
pPktAnaFunc:子模块的回调函数,子模块通过这个函数来接收防火墙提供的报文和设备信息。
其格式如下:typedef INT32 (*__PFUNC_PKT_ANA)(__PPKT_INFO);
返回值:
本 API 的返回值,是对应模块的 ID 号,此 ID 号用于卸载子模块。如果,注册失败,则返回 PX_ERROR. -
子模块卸载:
INT32 inpFWPktAnaUnRegister (UINT32 uiModID);
参数:
uiModID:子模块注册时获取的 ID
返回值:
本 API 返回卸载结果,注册成功返回 ERROR_NONE,失败则返回 PX_ERROR. -
远端设备不允许自动删除:
INT32 inpFWDevNotDel (PVOID pvRemotDevPriv);
inpfw 对于空闲时间长的设备会进行自动删除操作,用户可以使用此接口,禁止 inpfw 自动删除对应的模块。
参数:
pvRemotDevPriv:远端设备私有信息
返回值:
本 API 返回操作结果,注册成功返回 ERROR_NONE,失败则返回 PX_ERROR. -
远端设备允许自动删除:
INT32 inpFWDevAllowDel (PVOID pvRemotDevPriv);
此函数用于通知 inpfw ,当前设备可以进行自动删除操作。
参数:
pvRemotDevPriv:远端设备私有信息
返回值:
本 API 返回操作结果,注册成功返回 ERROR_NONE,失败则返回 PX_ERROR. -
添加黑白名单高级接口:
PVOID inpFWAdd2bAwListEx (UINT32 uiModId, CPCHAR pcIfname, INT iRule, BOOL bIn, UINT8 pucMac[], CPCHAR pcAddrStart, CPCHAR pcAddrEnd, UINT16 usPortStart, UINT16 usPortEnd, BOOL bBaWFlag, UINT32 uiAutoDelTime, PVOID pvCallbkArg, __ITEM_DEL_CALL_BK pItemDelCallBk);
此函数用于添加黑白名单,其提供了丰富的配置参数:
uiModId:子模块 ID
pcIfname:网卡名称
iRule:对应的规则, MAC/IP/UDP/TCP/…
bIn:TRUE: INPUT FALSE: OUTPUT
pucMac:通信的 MAC 地址数组
pcAddrStart:通信 IP 地址起始, 为 IP 地址字符串
pcAddrEnd:通信 IP 地址结束, 为 IP 地址字符串
usPortStart:通信的本地起始端口号(网络字节序), 仅适用与 UDP/TCP 规则
usPortEnd:通信的本地结束端口号(网络字节序), 仅适用与 UDP/TCP 规则
bBaWFlag:黑名单还是白名单 (TRUE: 白名单 FALSE: 黑名单)
uiAutoDelTime:名单条目自动删除时间(单位:分钟,0 : 永不删除)
pvCallbkArg:条目删除时回调函数参数
pItemDelCallBk:条目删除时回调函数返回值:
如果添加成功,则返回对应的条目句柄,如果添加失败,则返回空。 -
添加 MAC 黑名单名单:
PVOID inpFWAddMacRule2bAwList (UINT32 uiModId, CPCHAR pcIfname, BOOL bIn, UINT8 pucMac[], BOOL bBaWFlag, UINT32 uiAutoDelTime);
此函数用于添加一个 MAC 规则的黑白名单,使用方法同 inpFWAdd2bAwListEx。
-
添加 IP 黑名单名单:
PVOID inpFWAddIpRule2bAwList (UINT32 uiModId, CPCHAR pcIfname, BOOL bIn, UINT8 pucMac[], CPCHAR pcAddrStart, CPCHAR pcAddrEnd, BOOL bBaWFlag, UINT32 uiAutoDelTime);
此函数用于添加一个 IP 规则的黑白名单,使用方法同 inpFWAdd2bAwListEx。
-
获取当前黑白名单个数:
UINT8 inpFWbAwCountGet (UINT32 uiModId, INT32 iRule, BOOL bBaWFlag);
参数:
uiModId:子模块 ID
iRule:规则
bBaWFlag:黑名单还是白名单 (TRUE: 白名单 FALSE: 黑名单)
返回值:
返回当前需要获取对应规则的还白名单个数。 -
删除黑白名单名:
INT32 inpFWDelFromBaWList (PVOID pbAwHandle);
参数:
pbAwHandle:黑白名单添加时返回的句柄
返回:
删除成功则返回 ERROR_NONE,失败返回 PX_ERROR。
注:此接口删除黑白名单时,并不会调用对应的名单回调处理函数。
基于 inpFw 的子模块开发
上文描述了 inpFw 防火墙框架的相关原理,使用方法和 API 等内容,本节简要的要描述一种可以基于 inpFw 开发的一种简单思路,其主要分为如下几步:
-
编写对应的报文处理函数:
这里指的就是注册子模块时,传入的报文处理回调函数。其格式:
typedef INT32 (*__PFUNC_PKT_ANA)(__PPKT_INFO);
其内部实现内容,大致可如下形式:static INT32 __packetHandle (__PPKT_INFO pPktInfo) { // 1. 通过 pPktInfo 获取到自己需要的内容,如整个报文pBuf, // 以太网头pEthHdr,对应的发送端私有信息 pvRemotDevPriv 等 // 2. 通过第一步拿到的内容 ,对当前报文进行对应的分析处理,可以拉黑,或者放入白名单 // 3. 通过 pvRemotDevPriv,对当前的报文的发送方,进行分析判断等相关处理。 // 处理好后,可以将需要保存的跟发送端相关的数据,存放在 pvRemotDevPriv 中。 // 4. 返回处理结果 }
-
注册子模块:
参数上述 API 注册。 -
启动对应网口的防火墙:
参考上述防火墙使用方法。