kmod-oaf: support ipv6 flow
This commit is contained in:
parent
6f5f537f13
commit
48e2adf536
@ -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,
|
||||
},
|
||||
|
@ -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,
|
||||
},
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user