update 2024-04-02 20:33:22

This commit is contained in:
kenzok8 2024-04-02 20:33:22 +08:00
parent 5af0f7787c
commit 2d3894ec2b
5 changed files with 156 additions and 55 deletions

View File

@ -299,7 +299,7 @@ void af_visit_info_report(void)
}
static inline int get_packet_dir(struct net_device *in)
{
if (0 == strncmp(in->name, "br", 2))
if (0 == strncmp(in->name, "br-lan", 6))
{
return PKT_DIR_UP;
}
@ -327,6 +327,7 @@ static u_int32_t af_client_hook(unsigned int hook,
af_client_info_t *nfc = NULL;
int pkt_dir = 0;
struct iphdr *iph = NULL;
unsigned int ip = 0;
// 4.10-->4.11 nfct-->_nfct
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
@ -366,37 +367,36 @@ static u_int32_t af_client_hook(unsigned int hook,
memcpy(smac, &skb->cb[40], ETH_ALEN);
}
iph = ip_hdr(skb);
if (!iph)
{
if (skb->protocol == htons(ETH_P_IP)) {
iph = ip_hdr(skb);
ip = iph->saddr;
} else if (AF_MODE_GATEWAY != af_work_mode)
return NF_ACCEPT;
}
AF_CLIENT_LOCK_W();
nfc = find_af_client(smac);
if (!nfc)
{
if (skb->dev)
AF_DEBUG("from dev:%s [%s] %pI4--->%pI4", skb->dev->name, (iph->protocol == IPPROTO_TCP ? "TCP" : "UDP"),
&iph->saddr, &iph->daddr);
AF_DEBUG("from dev:%s %pI4", skb->dev->name, &ip);
nfc = nf_client_add(smac);
}
if (nfc && nfc->ip != iph->saddr)
if (nfc && ip != 0 && nfc->ip != ip)
{
AF_DEBUG("update node " MAC_FMT " ip %pI4--->%pI4\n", MAC_ARRAY(nfc->mac), &nfc->ip, &iph->saddr);
AF_DEBUG("update node " MAC_FMT " ip %pI4--->%pI4\n", MAC_ARRAY(nfc->mac), &nfc->ip, &ip);
nfc->update_jiffies = jiffies;
nfc->ip = iph->saddr;
nfc->ip = ip;
}
AF_CLIENT_UNLOCK_W();
return NF_ACCEPT;
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 16, 0)
static struct nf_hook_ops af_client_ops[] = {
{
.hook = af_client_hook,
.pf = PF_INET,
.pf = NFPROTO_INET,
.hooknum = NF_INET_FORWARD,
.priority = NF_IP_PRI_FIRST + 1,
},
@ -405,8 +405,19 @@ static struct nf_hook_ops af_client_ops[] = {
static struct nf_hook_ops af_client_ops[] = {
{
.hook = af_client_hook,
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 0)
.owner = THIS_MODULE,
.pf = PF_INET,
#endif
.pf = NFPROTO_IPV4,
.hooknum = NF_INET_FORWARD,
.priority = NF_IP_PRI_FIRST + 1,
},
{
.hook = af_client_hook,
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 0)
.owner = THIS_MODULE,
#endif
.pf = NFPROTO_IPV6,
.hooknum = NF_INET_FORWARD,
.priority = NF_IP_PRI_FIRST + 1,
},
@ -415,12 +426,16 @@ static struct nf_hook_ops af_client_ops[] = {
int af_client_init(void)
{
int err;
nf_client_list_init();
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0)
nf_register_net_hooks(&init_net, af_client_ops, ARRAY_SIZE(af_client_ops));
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 3, 0)
err = nf_register_net_hooks(&init_net, af_client_ops, ARRAY_SIZE(af_client_ops));
#else
nf_register_hooks(af_client_ops, ARRAY_SIZE(af_client_ops));
err = nf_register_hooks(af_client_ops, ARRAY_SIZE(af_client_ops));
#endif
if (err) {
AF_ERROR("oaf register client hooks failed!\n");
}
AF_INFO("init app afclient ........ok\n");
return 0;
@ -428,7 +443,7 @@ int af_client_init(void)
void af_client_exit(void)
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 3, 0)
nf_unregister_net_hooks(&init_net, af_client_ops, ARRAY_SIZE(af_client_ops));
#else
nf_unregister_hooks(af_client_ops, ARRAY_SIZE(af_client_ops));

View File

@ -67,7 +67,9 @@ static struct ctl_table oaf_root_table[] = {
{
.procname = "oaf",
.mode = 0555,
#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 4, 0))
.child = oaf_table,
#endif
},
{}
};
@ -76,7 +78,11 @@ static struct ctl_table_header *oaf_table_header;
static int af_init_log_sysctl(void)
{
#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 4, 0))
oaf_table_header = register_sysctl_table(oaf_root_table);
#else
oaf_table_header = register_sysctl(oaf_root_table->procname, oaf_table);
#endif
if (oaf_table_header == NULL){
printk("init log sysctl...failed\n");
return -ENOMEM;

View File

@ -12,6 +12,7 @@
#include <net/netfilter/nf_conntrack_acct.h>
#include <linux/skbuff.h>
#include <net/ip.h>
#include <uapi/linux/ipv6.h>
#include <linux/types.h>
#include <net/sock.h>
#include <linux/etherdevice.h>
@ -438,33 +439,51 @@ static void af_clean_feature_list(void)
int parse_flow_proto(struct sk_buff *skb, flow_info_t *flow)
{
unsigned char *ipp;
int ipp_len;
struct tcphdr *tcph = NULL;
struct udphdr *udph = NULL;
struct nf_conn *ct = NULL;
struct iphdr *iph = NULL;
struct ipv6hdr *ip6h = NULL;
if (!skb)
return -1;
iph = ip_hdr(skb);
if (!iph)
switch (skb->protocol) {
case htons(ETH_P_IP):
iph = ip_hdr(skb);
flow->src = iph->saddr;
flow->dst = iph->daddr;
flow->l4_protocol = iph->protocol;
ipp = ((unsigned char *)iph) + iph->ihl * 4;
ipp_len = ((unsigned char *)iph) + ntohs(iph->tot_len) - ipp;
break;
case htons(ETH_P_IPV6):
ip6h = ipv6_hdr(skb);
flow->src6 = ip6h->saddr.s6_addr;
flow->dst6 = ip6h->daddr.s6_addr;
flow->l4_protocol = ip6h->nexthdr;
ipp = ((unsigned char *)ip6h) + sizeof(struct ipv6hdr);
ipp_len = ntohs(ip6h->payload_len);
break;
default:
return -1;
flow->src = iph->saddr;
flow->dst = iph->daddr;
flow->l4_protocol = iph->protocol;
switch (iph->protocol)
}
switch (flow->l4_protocol)
{
case IPPROTO_TCP:
tcph = (struct tcphdr *)(iph + 1);
flow->l4_data = skb->data + iph->ihl * 4 + tcph->doff * 4;
flow->l4_len = ntohs(iph->tot_len) - iph->ihl * 4 - tcph->doff * 4;
flow->dport = htons(tcph->dest);
flow->sport = htons(tcph->source);
tcph = (struct tcphdr *)ipp;
flow->l4_len = ipp_len - tcph->doff * 4;
flow->l4_data = ipp + tcph->doff * 4;
flow->dport = ntohs(tcph->dest);
flow->sport = ntohs(tcph->source);
return 0;
case IPPROTO_UDP:
udph = (struct udphdr *)(iph + 1);
flow->l4_data = skb->data + iph->ihl * 4 + 8;
udph = (struct udphdr *)ipp;
flow->l4_len = ntohs(udph->len) - 8;
flow->dport = htons(udph->dest);
flow->sport = htons(udph->source);
flow->l4_data = ipp + 8;
flow->dport = ntohs(udph->dest);
flow->sport = ntohs(udph->source);
return 0;
case IPPROTO_ICMP:
break;
@ -781,10 +800,9 @@ int af_match_one(flow_info_t *flow, af_feature_node_t *node)
return ret;
}
int app_filter_match(flow_info_t *flow)
int app_filter_match(flow_info_t *flow, af_client_info_t *client)
{
af_feature_node_t *n, *node;
af_client_info_t *client = NULL;
feature_list_read_lock();
if (!list_empty(&af_feature_head))
{
@ -794,7 +812,8 @@ int app_filter_match(flow_info_t *flow)
{
flow->app_id = node->app_id;
strncpy(flow->app_name, node->app_name, sizeof(flow->app_name) - 1);
client = find_af_client_by_ip(flow->src);
if (flow->src)
client = find_af_client_by_ip(flow->src);
if (!client)
{
goto EXIT;
@ -929,14 +948,22 @@ u_int32_t app_filter_hook_bypass_handle(struct sk_buff *skb, struct net_device *
memset((char *)&flow, 0x0, sizeof(flow_info_t));
if (parse_flow_proto(skb, &flow) < 0)
return NF_ACCEPT;
if (af_lan_ip == flow.src || af_lan_ip == flow.dst){
return NF_ACCEPT;
}
if (af_check_bcast_ip(&flow) || af_match_local_packet(&flow))
return NF_ACCEPT;
if (flow.src || flow.dst) {
if (af_lan_ip == flow.src || af_lan_ip == flow.dst){
return NF_ACCEPT;
}
if (af_check_bcast_ip(&flow) || af_match_local_packet(&flow))
return NF_ACCEPT;
if ((flow.src & af_lan_mask) != (af_lan_ip & af_lan_mask)){
if ((flow.src & af_lan_mask) != (af_lan_ip & af_lan_mask)){
return NF_ACCEPT;
}
} else if (flow.src6 && flow.dst6) {
if (flow.src6[0] == 0xff || flow.dst6[0] == 0xff) {
return NF_ACCEPT;
}
return NF_DROP;
} else {
return NF_ACCEPT;
}
af_get_smac(skb, smac);
@ -948,13 +975,14 @@ u_int32_t app_filter_hook_bypass_handle(struct sk_buff *skb, struct net_device *
return NF_ACCEPT;
}
client->update_jiffies = jiffies;
if (flow.src)
client->ip = flow.src;
AF_CLIENT_UNLOCK_W();
if (0 != dpi_main(skb, &flow))
return NF_ACCEPT;
client->ip = flow.src;
app_filter_match(&flow);
app_filter_match(&flow, client);
if (flow.app_id != 0){
af_update_client_app_info(client, flow.app_id, flow.drop);
}
@ -968,6 +996,7 @@ u_int32_t app_filter_hook_bypass_handle(struct sk_buff *skb, struct net_device *
u_int32_t app_filter_hook_gateway_handle(struct sk_buff *skb, struct net_device *dev){
unsigned long long total_packets = 0;
flow_info_t flow;
u_int8_t smac[ETH_ALEN];
enum ip_conntrack_info ctinfo;
struct nf_conn *ct = NULL;
struct nf_conn_acct *acct;
@ -975,6 +1004,9 @@ u_int32_t app_filter_hook_gateway_handle(struct sk_buff *skb, struct net_device
int app_id = 0;
int drop = 0;
if (strncmp(dev->name, "br-lan", 6))
return NF_ACCEPT;
memset((char *)&flow, 0x0, sizeof(flow_info_t));
if (parse_flow_proto(skb, &flow) < 0)
return NF_ACCEPT;
@ -983,8 +1015,11 @@ u_int32_t app_filter_hook_gateway_handle(struct sk_buff *skb, struct net_device
if (ct == NULL || !nf_ct_is_confirmed(ct))
return NF_ACCEPT;
if (!flow.src)
af_get_smac(skb, smac);
AF_CLIENT_LOCK_R();
client = find_af_client_by_ip(flow.src);
client = flow.src?find_af_client_by_ip(flow.src):find_af_client(smac);
if (!client){
AF_CLIENT_UNLOCK_R();
return NF_ACCEPT;
@ -1019,7 +1054,7 @@ u_int32_t app_filter_hook_gateway_handle(struct sk_buff *skb, struct net_device
if (0 != dpi_main(skb, &flow))
return NF_ACCEPT;
app_filter_match(&flow);
app_filter_match(&flow, client);
if (flow.app_id != 0)
{
@ -1080,19 +1115,46 @@ static u_int32_t app_filter_by_pass_hook(unsigned int hook,
return app_filter_hook_bypass_handle(skb, skb->dev);
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 16, 0)
static struct nf_hook_ops app_filter_ops[] __read_mostly = {
{
.hook = app_filter_hook,
.pf = PF_INET,
.pf = NFPROTO_INET,
.hooknum = NF_INET_FORWARD,
.priority = NF_IP_PRI_MANGLE + 1,
},
{
.hook = app_filter_by_pass_hook,
.pf = PF_INET,
.pf = NFPROTO_INET,
.hooknum = NF_INET_PRE_ROUTING,
.priority = NF_IP_PRI_MANGLE + 1,
},
};
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)
static struct nf_hook_ops app_filter_ops[] __read_mostly = {
{
.hook = app_filter_hook,
.pf = NFPROTO_IPV4,
.hooknum = NF_INET_FORWARD,
.priority = NF_IP_PRI_MANGLE + 1,
},
{
.hook = app_filter_by_pass_hook,
.pf = NFPROTO_IPV4,
.hooknum = NF_INET_PRE_ROUTING,
.priority = NF_IP_PRI_MANGLE + 1,
},
{
.hook = app_filter_hook,
.pf = NFPROTO_IPV6,
.hooknum = NF_INET_FORWARD,
.priority = NF_IP_PRI_MANGLE + 1,
},
{
.hook = app_filter_by_pass_hook,
.pf = NFPROTO_IPV6,
.hooknum = NF_INET_PRE_ROUTING,
.priority = NF_IP_PRI_MANGLE + 1,
},
@ -1102,7 +1164,14 @@ static struct nf_hook_ops app_filter_ops[] __read_mostly = {
{
.hook = app_filter_hook,
.owner = THIS_MODULE,
.pf = PF_INET,
.pf = NFPROTO_IPV4,
.hooknum = NF_INET_FORWARD,
.priority = NF_IP_PRI_MANGLE + 1,
},
{
.hook = app_filter_hook,
.owner = THIS_MODULE,
.pf = NFPROTO_IPV6,
.hooknum = NF_INET_FORWARD,
.priority = NF_IP_PRI_MANGLE + 1,
},
@ -1247,6 +1316,7 @@ int netlink_oaf_init(void)
static int __init app_filter_init(void)
{
int err;
if (0 != load_feature_config())
{
return -1;
@ -1259,11 +1329,14 @@ static int __init app_filter_init(void)
af_init_app_status();
init_af_client_procfs();
af_client_init();
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0)
nf_register_net_hooks(&init_net, app_filter_ops, ARRAY_SIZE(app_filter_ops));
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 3, 0)
err = nf_register_net_hooks(&init_net, app_filter_ops, ARRAY_SIZE(app_filter_ops));
#else
nf_register_hooks(app_filter_ops, ARRAY_SIZE(app_filter_ops));
err = nf_register_hooks(app_filter_ops, ARRAY_SIZE(app_filter_ops));
#endif
if (err) {
AF_ERROR("oaf register filter hooks failed!\n");
}
init_oaf_timer();
AF_INFO("init app filter ........ok\n");
return 0;
@ -1273,7 +1346,7 @@ static void app_filter_fini(void)
{
AF_INFO("app filter module exit\n");
fini_oaf_timer();
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 3, 0)
nf_unregister_net_hooks(&init_net, app_filter_ops, ARRAY_SIZE(app_filter_ops));
#else
nf_unregister_hooks(app_filter_ops, ARRAY_SIZE(app_filter_ops));

View File

@ -101,6 +101,8 @@ typedef struct flow_info{
struct nf_conn *ct;
u_int32_t src;
u_int32_t dst;
u_int8_t *src6;
u_int8_t *dst6;
int l4_protocol;
u_int16_t sport;
u_int16_t dport;

View File

@ -12,6 +12,7 @@
#include <linux/cdev.h>
#include <linux/vmalloc.h>
#include <linux/device.h>
#include <linux/version.h>
#include "cJSON.h"
#include "app_filter.h"
#include "af_utils.h"
@ -419,7 +420,11 @@ int af_register_dev(void)
goto REGION_OUT;
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 4, 0)
g_af_dev.c = class_create(THIS_MODULE, AF_DEV_NAME);
#else
g_af_dev.c = class_create(AF_DEV_NAME);
#endif
if (IS_ERR_OR_NULL(g_af_dev.c))
{
goto CDEV_OUT;