代碼路徑
git訪問方式:https://gitee.com/yuewguo/url_filter.git
svn訪問方式:svn://gitee.com/yuewguo/url_filtergit
1、自定義內核模塊
static int UF_init(void) //安裝模塊入口
{
int ret = 0;
/* netfilter-hook */
ret = UF_NF_hook(); // 註冊netfilter處理函數
if (0 != ret)
{
printk(KERN_EMERG"register hook fail!rn");
return ret;
}
/* syscall */
ret = UF_setsyscall();// 註冊中斷處理函數,用於接收用戶態配置
UF_rule_init();// 初始化用戶配置結構
printk(KERN_EMERG"install urlfilter succ!rn");
return 0;
}
static void UF_exit(void) //卸載模塊入口
{
printk(KERN_EMERG"uninstall urlfilter succ!rn");
UF_NF_unhook();// 卸載註冊netfilter處理函數
UF_resetsyscall();// 還原中斷中斷處理函數
UF_rule_exit();// 刪除用戶配置
return ;
}
module_init(UF_init);
module_exit(UF_exit);框架
2、Netfilter處理函數
netfilter處理框架以下圖(轉自網上):
須要注意的是,netfilter對外提供的hook點僅針對正向收包,應答報文不通過hook的業務點。
若是須要在應答流程中添加hook點須要自行修改netfilter代碼。
struct nf_hook_ops UF_NF_hookfunc[] = {
{
.hook = UF_forward_entry,
.owner = THIS_MODULE,
.pf = NFPROTO_IPV4,
.hooknum = NF_INET_PRE_ROUTING,
.priority = NF_IP_PRI_FIRST,
},
{
.hook = UF_forward_entry,
.owner = THIS_MODULE,
.pf = NFPROTO_IPV4,
.hooknum = NF_INET_LOCAL_IN,
.priority = NF_IP_PRI_FIRST,
},
{
.hook = UF_forward_entry,
.owner = THIS_MODULE,
.pf = NFPROTO_IPV4,
.hooknum = NF_INET_FORWARD,
.priority = NF_IP_PRI_FIRST,
},
{
.hook = UF_forward_entry,
.owner = THIS_MODULE,
.pf = NFPROTO_IPV4,
.hooknum = NF_INET_LOCAL_OUT,
.priority = NF_IP_PRI_FIRST,
},
{
.hook = UF_forward_entry,
.owner = THIS_MODULE,
.pf = NFPROTO_IPV4,
.hooknum = NF_INET_POST_ROUTING,
.priority = NF_IP_PRI_FIRST,
},
};
int UF_NF_hook(void) // 接上文
{
printk(KERN_EMERG"Register Netfilter Hookrn");
nf_register_hooks(UF_NF_hookfunc, ARRAY_SIZE(UF_NF_hookfunc)); // 註冊netfilter處理函數
return 0;
}
UF_forward_entry
// 這塊代碼很簡單,僅實現了簡易的URL過濾功能,有興趣能夠自行補充其餘功能。svn
3、命令行與內核交互
(1)內核部分
UF_setsyscall功能:改寫系統223號中斷,做爲模塊用戶態和內核態的通訊通道。
/* setup __NR_urlfilter 223*/
int UF_setsyscall(void)
{
entry = get_sys_call_table();
if (NULL == entry)
{
printk(KERN_EMERG"get_sys_call_table failrn");
return -1;
}
urlfilter_old = (unsigned long *)(entry[__NR_urlfilter]);
disable_write_protection();
entry[__NR_urlfilter] = (unsigned long *)UF_syscall; // 用戶態觸發223中斷,UF_syscall會被執行
enable_write_protection();
return 0;
}函數
/* UF_syscall */
// 中斷函數的入數個數能夠自定義,用戶態調用時保持一致便可。
// 須要注意的是,內核態和用戶態的指針不能直接用,須要用copy_from_user和copy_to_user進行轉換。
asmlinkage long UF_syscall(unsigned int optcode,
void *input, unsigned int inputlen,
void *output, unsigned int outputlen) //中斷函數的入參
{
// ...
return ret;
}
(2)用戶態部分
syscall(__NR_urlfilter, opt, input, inputlen, output, outputlen);
// __NR_urlfilter 爲中斷號
// opt, input, inputlen, output, outputlen 爲中斷函數的入參,見上文
2020.5.27 合肥url