From 48e2adf536c169b6aeca61c4194691b6aca816c4 Mon Sep 17 00:00:00 2001 From: jjm2473 <1129525450@qq.com> Date: Thu, 14 Mar 2024 21:07:25 +0800 Subject: [PATCH] kmod-oaf: support ipv6 flow --- oaf/src/af_client.c | 24 +++++------ oaf/src/app_filter.c | 99 ++++++++++++++++++++++++++++++-------------- oaf/src/app_filter.h | 2 + 3 files changed, 81 insertions(+), 44 deletions(-) diff --git a/oaf/src/af_client.c b/oaf/src/af_client.c index 971446d..8f80cd9 100755 --- a/oaf/src/af_client.c +++ b/oaf/src/af_client.c @@ -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,26 +367,25 @@ 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(); @@ -396,7 +396,7 @@ static u_int32_t af_client_hook(unsigned int hook, 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, }, @@ -406,7 +406,7 @@ static struct nf_hook_ops af_client_ops[] = { { .hook = af_client_hook, .owner = THIS_MODULE, - .pf = PF_INET, + .pf = NFPROTO_INET, .hooknum = NF_INET_FORWARD, .priority = NF_IP_PRI_FIRST + 1, }, diff --git a/oaf/src/app_filter.c b/oaf/src/app_filter.c index 81f498c..7d25906 100755 --- a/oaf/src/app_filter.c +++ b/oaf/src/app_filter.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -472,33 +473,51 @@ static unsigned char *read_skb(struct sk_buff *skb, unsigned int from, unsigned 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; @@ -815,10 +834,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)) { @@ -828,7 +846,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; @@ -964,14 +983,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); @@ -983,6 +1010,8 @@ 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 (skb_is_nonlinear(skb)) { @@ -994,8 +1023,7 @@ u_int32_t app_filter_hook_bypass_handle(struct sk_buff *skb, struct net_device * if (0 != dpi_main(skb, &flow)) goto 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); } @@ -1016,6 +1044,7 @@ accept: 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; @@ -1024,6 +1053,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; @@ -1032,8 +1064,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; @@ -1073,7 +1108,7 @@ u_int32_t app_filter_hook_gateway_handle(struct sk_buff *skb, struct net_device if (0 != dpi_main(skb, &flow)) goto accept; - app_filter_match(&flow); + app_filter_match(&flow, client); if (flow.app_id != 0) { @@ -1146,14 +1181,14 @@ static u_int32_t app_filter_by_pass_hook(unsigned int hook, 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, }, @@ -1163,7 +1198,7 @@ static struct nf_hook_ops app_filter_ops[] __read_mostly = { { .hook = app_filter_hook, .owner = THIS_MODULE, - .pf = PF_INET, + .pf = NFPROTO_INET, .hooknum = NF_INET_FORWARD, .priority = NF_IP_PRI_MANGLE + 1, }, diff --git a/oaf/src/app_filter.h b/oaf/src/app_filter.h index 2577fea..5897ebb 100755 --- a/oaf/src/app_filter.h +++ b/oaf/src/app_filter.h @@ -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;