kmod-oaf: support ipv6 flow

This commit is contained in:
jjm2473 2024-03-14 21:07:25 +08:00 committed by sbwml
parent 6f5f537f13
commit 48e2adf536
3 changed files with 81 additions and 44 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,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,
},

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>
@ -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,
},

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;