1 2/* 3 author: derry 4 date:2019/1/10 5*/ 6#include <linux/init.h> 7#include <linux/module.h> 8#include <linux/version.h> 9#include <net/tcp.h> 10#include <linux/netfilter.h> 11#include <net/netfilter/nf_conntrack.h> 12#include <net/netfilter/nf_conntrack_acct.h> 13#include <linux/skbuff.h> 14#include <net/ip.h> 15#include <linux/types.h> 16#include <net/sock.h> 17#include <linux/etherdevice.h> 18#include <linux/cdev.h> 19#include <linux/device.h> 20#include "app_filter.h" 21#include "af_utils.h" 22#include "af_log.h" 23#include "af_client.h" 24#include "af_client_fs.h" 25#include "cJSON.h" 26 27MODULE_LICENSE("GPL"); 28MODULE_AUTHOR("destan19@126.com"); 29MODULE_DESCRIPTION("app filter module"); 30MODULE_VERSION("5.0"); 31struct list_head af_feature_head = LIST_HEAD_INIT(af_feature_head); 32 33DEFINE_RWLOCK(af_feature_lock); 34 35#define feature_list_read_lock() read_lock_bh(&af_feature_lock); 36#define feature_list_read_unlock() read_unlock_bh(&af_feature_lock); 37#define feature_list_write_lock() write_lock_bh(&af_feature_lock); 38#define feature_list_write_unlock() write_unlock_bh(&af_feature_lock); 39 40#define SET_APPID(mark, appid) (mark = appid) 41#define GET_APPID(mark) (mark) 42#define MAX_OAF_NETLINK_MSG_LEN 1024 43 44int __add_app_feature(int appid, char *name, int proto, int src_port, 45 port_info_t dport_info, char *host_url, char *request_url, char *dict) 46{ 47 af_feature_node_t *node = NULL; 48 char *p = dict; 49 char *begin = dict; 50 char pos[32] = {0}; 51 int index = 0; 52 int value = 0; 53 node = kzalloc(sizeof(af_feature_node_t), GFP_KERNEL); 54 if (node == NULL) 55 { 56 printk("malloc feature memory error\n"); 57 return -1; 58 } 59 else 60 { 61 node->app_id = appid; 62 strcpy(node->app_name, name); 63 node->proto = proto; 64 node->dport_info = dport_info; 65 node->sport = src_port; 66 strcpy(node->host_url, host_url); 67 strcpy(node->request_url, request_url); 68 // 00:0a-01:11 69 p = dict; 70 begin = dict; 71 index = 0; 72 value = 0; 73 while (*p++) 74 { 75 if (*p == '|') 76 { 77 memset(pos, 0x0, sizeof(pos)); 78 strncpy(pos, begin, p - begin); 79 k_sscanf(pos, "%d:%x", &index, &value); 80 begin = p + 1; 81 node->pos_info[node->pos_num].pos = index; 82 node->pos_info[node->pos_num].value = value; 83 node->pos_num++; 84 } 85 } 86 87 if (begin != dict) 88 strncpy(pos, begin, p - begin); 89 else 90 strcpy(pos, dict); 91 92 k_sscanf(pos, "%d:%x", &index, &value); 93 node->pos_info[node->pos_num].pos = index; 94 node->pos_info[node->pos_num].value = value; 95 node->pos_num++; 96 feature_list_write_lock(); 97 list_add(&(node->head), &af_feature_head); 98 feature_list_write_unlock(); 99 } 100 return 0; 101} 102int validate_range_value(char *range_str){ 103 if (!range_str) 104 return 0; 105 char *p = range_str; 106 while(*p){ 107 if (*p == ' ' || *p == '!' || *p == '-' || 108 ((*p >= '0') && (*p <= '9'))){ 109 p++; 110 continue; 111 } 112 else{ 113 printk("error, invalid char %x\n", *p); 114 return 0; 115 } 116 } 117 return 1; 118} 119 120int parse_range_value(char *range_str, range_value_t *range){ 121 char pure_range[128] = {0}; 122 if (!validate_range_value(range_str)){ 123 printk("validate range str failed, value = %s\n", range_str); 124 return -1; 125 } 126 k_trim(range_str); 127 if (range_str[0] == '!'){ 128 range->not = 1; 129 strcpy(pure_range, range_str + 1); 130 } 131 else{ 132 range->not = 0; 133 strcpy(pure_range, range_str); 134 } 135 k_trim(pure_range); 136 int start, end; 137 if (strstr(pure_range, "-")){ 138 if (2 != sscanf(pure_range, "%d-%d",&start, &end)) 139 return -1; 140 } 141 else{ 142 if (1 != sscanf(pure_range, "%d", &start)) 143 return -1; 144 end = start; 145 } 146 range->start = start; 147 range->end = end; 148 return 0; 149} 150 151int parse_port_info(char *port_str, port_info_t *info){ 152 char *p = port_str; 153 char *begin = port_str; 154 int param_num = 0; 155 char one_port_buf[128] = {0}; 156 k_trim(port_str); 157 if (strlen(port_str) == 0) 158 return -1; 159 160 while(*p++) { 161 if (*p != '|') 162 continue; 163 memset(one_port_buf, 0x0, sizeof(one_port_buf)); 164 strncpy(one_port_buf, begin, p - begin); 165 if (0 == parse_range_value(one_port_buf, &info->range_list[info->num])){ 166 info->num++; 167 } 168 param_num++; 169 begin = p + 1; 170 } 171 memset(one_port_buf, 0x0, sizeof(one_port_buf)); 172 strncpy(one_port_buf, begin, p - begin); 173 if (0 == parse_range_value(one_port_buf, &info->range_list[info->num])){ 174 info->num++; 175 } 176 return 0; 177} 178 179int af_match_port(port_info_t *info, int port){ 180 int i; 181 int with_not = 0; 182 if (info->num == 0) 183 return 1; 184 for (i = 0; i < info->num; i++){ 185 if (info->range_list[i].not){ 186 with_not = 1; 187 break; 188 } 189 } 190 for (i = 0; i < info->num; i++){ 191 if (with_not){ 192 if (info->range_list[i].not && port >= info->range_list[i].start 193 && port <= info->range_list[i].end){ 194 return 0; 195 } 196 } 197 else{ 198 if (port >= info->range_list[i].start 199 && port <= info->range_list[i].end){ 200 return 1; 201 } 202 } 203 } 204 if (with_not) 205 return 1; 206 else 207 return 0; 208} 209//[tcp;;443;baidu.com;;] 210int add_app_feature(int appid, char *name, char *feature) 211{ 212 char proto_str[16] = {0}; 213 char src_port_str[16] = {0}; 214 port_info_t dport_info; 215 char dst_port_str[16] = {0}; 216 char host_url[32] = {0}; 217 char request_url[128] = {0}; 218 char dict[128] = {0}; 219 int proto = IPPROTO_TCP; 220 char *p = feature; 221 char *begin = feature; 222 int param_num = 0; 223 int dst_port = 0; 224 int src_port = 0; 225 226 if (!name || !feature) 227 { 228 AF_ERROR("error, name or feature is null\n"); 229 return -1; 230 } 231 // tcp;8000;www.sina.com;0:get_name;00:0a-01:11 232 memset(&dport_info, 0x0, sizeof(dport_info)); 233 while (*p++) 234 { 235 if (*p != ';') 236 continue; 237 238 switch (param_num) 239 { 240 241 case AF_PROTO_PARAM_INDEX: 242 strncpy(proto_str, begin, p - begin); 243 break; 244 case AF_SRC_PORT_PARAM_INDEX: 245 strncpy(src_port_str, begin, p - begin); 246 break; 247 case AF_DST_PORT_PARAM_INDEX: 248 strncpy(dst_port_str, begin, p - begin); 249 break; 250 251 case AF_HOST_URL_PARAM_INDEX: 252 strncpy(host_url, begin, p - begin); 253 break; 254 255 case AF_REQUEST_URL_PARAM_INDEX: 256 strncpy(request_url, begin, p - begin); 257 break; 258 } 259 param_num++; 260 begin = p + 1; 261 } 262 if (AF_DICT_PARAM_INDEX != param_num && strlen(feature) > MIN_FEATURE_STR_LEN) 263 { 264 return -1; 265 } 266 strncpy(dict, begin, p - begin); 267 268 if (0 == strcmp(proto_str, "tcp")) 269 proto = IPPROTO_TCP; 270 else if (0 == strcmp(proto_str, "udp")) 271 proto = IPPROTO_UDP; 272 else 273 { 274 AF_DEBUG("proto %s is not support\n", proto_str); 275 return -1; 276 } 277 sscanf(src_port_str, "%d", &src_port); 278// sscanf(dst_port_str, "%d", &dst_port); 279 parse_port_info(dst_port_str, &dport_info); 280 281 __add_app_feature(appid, name, proto, src_port, dport_info, host_url, request_url, dict); 282 return 0; 283} 284 285void af_init_feature(char *feature_str) 286{ 287 int app_id; 288 char app_name[128] = {0}; 289 char feature_buf[MAX_FEATURE_LINE_LEN] = {0}; 290 char *p = feature_str; 291 char *pos = NULL; 292 int len = 0; 293 char *begin = NULL; 294 char feature[MAX_FEATURE_STR_LEN]; 295 296 if (strstr(feature_str, "#")) 297 return; 298 299 k_sscanf(feature_str, "%d%[^:]", &app_id, app_name); 300 while (*p++) 301 { 302 if (*p == '[') 303 { 304 pos = p + 1; 305 continue; 306 } 307 if (*p == ']' && pos != NULL) 308 { 309 len = p - pos; 310 } 311 } 312 313 if (pos && len) 314 strncpy(feature_buf, pos, len); 315 memset(feature, 0x0, sizeof(feature)); 316 p = feature_buf; 317 begin = feature_buf; 318 319 while (*p++) 320 { 321 if (*p == ',') 322 { 323 memset(feature, 0x0, sizeof(feature)); 324 strncpy((char *)feature, begin, p - begin); 325 326 add_app_feature(app_id, app_name, feature); 327 begin = p + 1; 328 } 329 } 330 if (p != begin) 331 { 332 memset(feature, 0x0, sizeof(feature)); 333 strncpy((char *)feature, begin, p - begin); 334 add_app_feature(app_id, app_name, feature); 335 } 336} 337 338void load_feature_buf_from_file(char **config_buf) 339{ 340 struct inode *inode = NULL; 341 struct file *fp = NULL; 342#if LINUX_VERSION_CODE <= KERNEL_VERSION(5, 7, 19) 343 mm_segment_t fs; 344#endif 345 off_t size; 346 fp = filp_open(AF_FEATURE_CONFIG_FILE, O_RDONLY, 0); 347 348 if (IS_ERR(fp)) 349 { 350 return; 351 } 352 353 inode = fp->f_inode; 354 size = inode->i_size; 355 if (size == 0) 356 { 357 return; 358 } 359 *config_buf = (char *)kzalloc(sizeof(char) * size, GFP_KERNEL); 360 if (NULL == *config_buf) 361 { 362 AF_ERROR("alloc buf fail\n"); 363 filp_close(fp, NULL); 364 return; 365 } 366 367#if LINUX_VERSION_CODE <= KERNEL_VERSION(5, 7, 19) 368 fs = get_fs(); 369 set_fs(KERNEL_DS); 370#endif 371// 4.14rc3 vfs_read-->kernel_read 372#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) 373 kernel_read(fp, *config_buf, size, &(fp->f_pos)); 374#else 375 vfs_read(fp, *config_buf, size, &(fp->f_pos)); 376#endif 377 378#if LINUX_VERSION_CODE <= KERNEL_VERSION(5, 7, 19) 379 set_fs(fs); 380#endif 381 filp_close(fp, NULL); 382} 383 384int load_feature_config(void) 385{ 386 char *feature_buf = NULL; 387 char *p; 388 char *begin; 389 char line[MAX_FEATURE_LINE_LEN] = {0}; 390 391 load_feature_buf_from_file(&feature_buf); 392 if (!feature_buf) 393 { 394 return -1; 395 } 396 p = begin = feature_buf; 397 while (*p++) 398 { 399 if (*p == '\n') 400 { 401 if (p - begin < MIN_FEATURE_LINE_LEN || p - begin > MAX_FEATURE_LINE_LEN) 402 { 403 begin = p + 1; 404 continue; 405 } 406 memset(line, 0x0, sizeof(line)); 407 strncpy(line, begin, p - begin); 408 af_init_feature(line); 409 begin = p + 1; 410 } 411 } 412 if (p != begin) 413 { 414 if (p - begin < MIN_FEATURE_LINE_LEN || p - begin > MAX_FEATURE_LINE_LEN) 415 return 0; 416 memset(line, 0x0, sizeof(line)); 417 strncpy(line, begin, p - begin); 418 af_init_feature(line); 419 begin = p + 1; 420 } 421 if (feature_buf) 422 kfree(feature_buf); 423 return 0; 424} 425 426static void af_clean_feature_list(void) 427{ 428 af_feature_node_t *node; 429 feature_list_write_lock(); 430 while (!list_empty(&af_feature_head)) 431 { 432 node = list_first_entry(&af_feature_head, af_feature_node_t, head); 433 list_del(&(node->head)); 434 kfree(node); 435 } 436 feature_list_write_unlock(); 437} 438 439int parse_flow_proto(struct sk_buff *skb, flow_info_t *flow) 440{ 441 struct tcphdr *tcph = NULL; 442 struct udphdr *udph = NULL; 443 struct nf_conn *ct = NULL; 444 struct iphdr *iph = NULL; 445 if (!skb) 446 return -1; 447 iph = ip_hdr(skb); 448 if (!iph) 449 return -1; 450 flow->src = iph->saddr; 451 flow->dst = iph->daddr; 452 flow->l4_protocol = iph->protocol; 453 switch (iph->protocol) 454 { 455 case IPPROTO_TCP: 456 tcph = (struct tcphdr *)(iph + 1); 457 flow->l4_data = skb->data + iph->ihl * 4 + tcph->doff * 4; 458 flow->l4_len = ntohs(iph->tot_len) - iph->ihl * 4 - tcph->doff * 4; 459 flow->dport = htons(tcph->dest); 460 flow->sport = htons(tcph->source); 461 return 0; 462 case IPPROTO_UDP: 463 udph = (struct udphdr *)(iph + 1); 464 flow->l4_data = skb->data + iph->ihl * 4 + 8; 465 flow->l4_len = ntohs(udph->len) - 8; 466 flow->dport = htons(udph->dest); 467 flow->sport = htons(udph->source); 468 return 0; 469 case IPPROTO_ICMP: 470 break; 471 default: 472 return -1; 473 } 474 return -1; 475} 476#define MAX_HOST_LEN 32 477#define MIN_HOST_LEN 4 478 479int dpi_https_proto(flow_info_t *flow) 480{ 481 int i; 482 short url_len = 0; 483 char *p = flow->l4_data; 484 int data_len = flow->l4_len; 485 486 if (NULL == flow) 487 { 488 AF_ERROR("flow is NULL\n"); 489 return -1; 490 } 491 if (NULL == p || data_len == 0) 492 { 493 return -1; 494 } 495 if (!(p[0] == 0x16 && p[1] == 0x03 && p[2] == 0x01)) 496 return -1; 497 498 499 for (i = 0; i < data_len; i++) 500 { 501 if (i + HTTPS_URL_OFFSET >= data_len) 502 { 503 return -1; 504 } 505 506 507 if (p[i] == 0x0 && p[i + 1] == 0x0 && p[i + 2] == 0x0 && p[i + 3] != 0x0) 508 { 509 // 2 bytes 510 memcpy(&url_len, p + i + HTTPS_LEN_OFFSET, 2); 511 512 if (ntohs(url_len) <= MIN_HOST_LEN || ntohs(url_len) > data_len || ntohs(url_len) > MAX_HOST_LEN) 513 { 514 continue; 515 } 516 if (i + HTTPS_URL_OFFSET + ntohs(url_len) < data_len) 517 { 518 flow->https.match = AF_TRUE; 519 flow->https.url_pos = p + i + HTTPS_URL_OFFSET; 520 flow->https.url_len = ntohs(url_len); 521 return 0; 522 } 523 } 524 } 525 return -1; 526} 527 528void dpi_http_proto(flow_info_t *flow) 529{ 530 int i = 0; 531 int start = 0; 532 char *data = NULL; 533 int data_len = 0; 534 if (!flow) 535 { 536 AF_ERROR("flow is null\n"); 537 return; 538 } 539 if (flow->l4_protocol != IPPROTO_TCP) 540 { 541 return; 542 } 543 544 data = flow->l4_data; 545 data_len = flow->l4_len; 546 if (data_len < MIN_HTTP_DATA_LEN) 547 { 548 return; 549 } 550 if (flow->sport != 80 && flow->dport != 80) 551 return; 552 for (i = 0; i < data_len; i++) 553 { 554 if (data[i] == 0x0d && data[i + 1] == 0x0a) 555 { 556 if (0 == memcmp(&data[start], "POST ", 5)) 557 { 558 flow->http.match = AF_TRUE; 559 flow->http.method = HTTP_METHOD_POST; 560 flow->http.url_pos = data + start + 5; 561 flow->http.url_len = i - start - 5; 562 } 563 else if (0 == memcmp(&data[start], "GET ", 4)) 564 { 565 flow->http.match = AF_TRUE; 566 flow->http.method = HTTP_METHOD_GET; 567 flow->http.url_pos = data + start + 4; 568 flow->http.url_len = i - start - 4; 569 } 570 else if (0 == memcmp(&data[start], "Host:", 5)) 571 { 572 flow->http.host_pos = data + start + 6; 573 flow->http.host_len = i - start - 6; 574 } 575 if (data[i + 2] == 0x0d && data[i + 3] == 0x0a) 576 { 577 flow->http.data_pos = data + i + 4; 578 flow->http.data_len = data_len - i - 4; 579 break; 580 } 581 // 0x0d 0x0a 582 start = i + 2; 583 } 584 } 585} 586 587static void dump_http_flow_info(http_proto_t *http) 588{ 589 if (!http) 590 { 591 AF_ERROR("http ptr is NULL\n"); 592 return; 593 } 594 if (!http->match) 595 return; 596 if (http->method == HTTP_METHOD_GET) 597 { 598 printk("Http method: " HTTP_GET_METHOD_STR "\n"); 599 } 600 else if (http->method == HTTP_METHOD_POST) 601 { 602 printk("Http method: " HTTP_POST_METHOD_STR "\n"); 603 } 604 if (http->url_len > 0 && http->url_pos) 605 { 606 dump_str("Request url", http->url_pos, http->url_len); 607 } 608 609 if (http->host_len > 0 && http->host_pos) 610 { 611 dump_str("Host", http->host_pos, http->host_len); 612 } 613 614 printk("--------------------------------------------------------\n\n\n"); 615} 616 617static void dump_https_flow_info(https_proto_t *https) 618{ 619 if (!https) 620 { 621 AF_ERROR("https ptr is NULL\n"); 622 return; 623 } 624 if (!https->match) 625 return; 626 627 if (https->url_len > 0 && https->url_pos) 628 { 629 dump_str("https server name", https->url_pos, https->url_len); 630 } 631 632 printk("--------------------------------------------------------\n\n\n"); 633} 634static void dump_flow_info(flow_info_t *flow) 635{ 636 if (!flow) 637 { 638 AF_ERROR("flow is null\n"); 639 return; 640 } 641 if (flow->l4_len > 0) 642 { 643 AF_LMT_INFO("src=" NIPQUAD_FMT ",dst=" NIPQUAD_FMT ",sport: %d, dport: %d, data_len: %d\n", 644 NIPQUAD(flow->src), NIPQUAD(flow->dst), flow->sport, flow->dport, flow->l4_len); 645 } 646 647 if (flow->l4_protocol == IPPROTO_TCP) 648 { 649 if (AF_TRUE == flow->http.match) 650 { 651 printk("-------------------http protocol-------------------------\n"); 652 printk("protocol:TCP , sport: %-8d, dport: %-8d, data_len: %-8d\n", 653 flow->sport, flow->dport, flow->l4_len); 654 dump_http_flow_info(&flow->http); 655 } 656 if (AF_TRUE == flow->https.match) 657 { 658 printk("-------------------https protocol-------------------------\n"); 659 dump_https_flow_info(&flow->https); 660 } 661 } 662} 663int af_match_by_pos(flow_info_t *flow, af_feature_node_t *node) 664{ 665 int i; 666 unsigned int pos = 0; 667 668 if (!flow || !node) 669 return AF_FALSE; 670 if (node->pos_num > 0) 671 { 672 for (i = 0; i < node->pos_num; i++) 673 { 674 // -1 675 if (node->pos_info[i].pos < 0) 676 { 677 pos = flow->l4_len + node->pos_info[i].pos; 678 } 679 else 680 { 681 pos = node->pos_info[i].pos; 682 } 683 if (pos >= flow->l4_len) 684 { 685 return AF_FALSE; 686 } 687 if (flow->l4_data[pos] != node->pos_info[i].value) 688 { 689 return AF_FALSE; 690 } 691 } 692 AF_DEBUG("match by pos, appid=%d\n", node->app_id); 693 return AF_TRUE; 694 } 695 return AF_FALSE; 696} 697 698int af_match_by_url(flow_info_t *flow, af_feature_node_t *node) 699{ 700 char reg_url_buf[MAX_URL_MATCH_LEN] = {0}; 701 702 if (!flow || !node) 703 return AF_FALSE; 704 // match host or https url 705 if (flow->https.match == AF_TRUE && flow->https.url_pos) 706 { 707 if (flow->https.url_len >= MAX_URL_MATCH_LEN) 708 strncpy(reg_url_buf, flow->https.url_pos, MAX_URL_MATCH_LEN - 1); 709 else 710 strncpy(reg_url_buf, flow->https.url_pos, flow->https.url_len); 711 } 712 else if (flow->http.match == AF_TRUE && flow->http.host_pos) 713 { 714 if (flow->http.host_len >= MAX_URL_MATCH_LEN) 715 strncpy(reg_url_buf, flow->http.host_pos, MAX_URL_MATCH_LEN - 1); 716 else 717 strncpy(reg_url_buf, flow->http.host_pos, flow->http.host_len); 718 } 719 if (strlen(reg_url_buf) > 0 && strlen(node->host_url) > 0 && regexp_match(node->host_url, reg_url_buf)) 720 { 721 AF_DEBUG("match url:%s reg = %s, appid=%d\n", 722 reg_url_buf, node->host_url, node->app_id); 723 return AF_TRUE; 724 } 725 726 // match request url 727 if (flow->http.match == AF_TRUE && flow->http.url_pos) 728 { 729 memset(reg_url_buf, 0x0, sizeof(reg_url_buf)); 730 if (flow->http.url_len >= MAX_URL_MATCH_LEN) 731 strncpy(reg_url_buf, flow->http.url_pos, MAX_URL_MATCH_LEN - 1); 732 else 733 strncpy(reg_url_buf, flow->http.url_pos, flow->http.url_len); 734 if (strlen(reg_url_buf) > 0 && strlen(node->request_url) && regexp_match(node->request_url, reg_url_buf)) 735 { 736 AF_DEBUG("match request:%s reg:%s appid=%d\n", 737 reg_url_buf, node->request_url, node->app_id); 738 return AF_TRUE; 739 } 740 } 741 return AF_FALSE; 742} 743 744int af_match_one(flow_info_t *flow, af_feature_node_t *node) 745{ 746 int ret = AF_FALSE; 747 if (!flow || !node) 748 { 749 AF_ERROR("node or flow is NULL\n"); 750 return AF_FALSE; 751 } 752 if (node->proto > 0 && flow->l4_protocol != node->proto) 753 return AF_FALSE; 754 if (flow->l4_len == 0) 755 return AF_FALSE; 756 757 if (node->sport != 0 && flow->sport != node->sport) 758 { 759 return AF_FALSE; 760 } 761 762 if (!af_match_port(&node->dport_info, flow->dport)){ 763 return AF_FALSE; 764 } 765 766 if (strlen(node->request_url) > 0 || 767 strlen(node->host_url) > 0) 768 { 769 ret = af_match_by_url(flow, node); 770 } 771 else if (node->pos_num > 0) 772 { 773 ret = af_match_by_pos(flow, node); 774 } 775 else 776 { 777 AF_DEBUG("node is empty, match sport:%d,dport:%d, appid = %d\n", 778 node->sport, node->dport, node->app_id); 779 return AF_TRUE; 780 } 781 return ret; 782} 783 784int app_filter_match(flow_info_t *flow) 785{ 786 af_feature_node_t *n, *node; 787 af_client_info_t *client = NULL; 788 feature_list_read_lock(); 789 if (!list_empty(&af_feature_head)) 790 { 791 list_for_each_entry_safe(node, n, &af_feature_head, head) 792 { 793 if (af_match_one(flow, node)) 794 { 795 flow->app_id = node->app_id; 796 strncpy(flow->app_name, node->app_name, sizeof(flow->app_name) - 1); 797 client = find_af_client_by_ip(flow->src); 798 if (!client) 799 { 800 goto EXIT; 801 } 802 if (is_user_match_enable() && !find_af_mac(client->mac)) 803 { 804 goto EXIT; 805 } 806 if (af_get_app_status(node->app_id)) 807 { 808 flow->drop = AF_TRUE; 809 feature_list_read_unlock(); 810 return AF_TRUE; 811 } 812 else 813 { 814 goto EXIT; 815 } 816 } 817 } 818 } 819EXIT: 820 flow->drop = AF_FALSE; 821 feature_list_read_unlock(); 822 return AF_FALSE; 823} 824 825#define NF_DROP_BIT 0x80000000 826 827static int af_get_visit_index(af_client_info_t *node, int app_id) 828{ 829 int i; 830 for (i = 0; i < MAX_RECORD_APP_NUM; i++) 831 { 832 if (node->visit_info[i].app_id == app_id || node->visit_info[i].app_id == 0) 833 { 834 return i; 835 } 836 } 837 // default 0 838 return 0; 839} 840 841int af_update_client_app_info(af_client_info_t *node, int app_id, int drop) 842{ 843 int index = -1; 844 if (!node) 845 return -1; 846 847 index = af_get_visit_index(node, app_id); 848 if (index < 0 || index >= MAX_RECORD_APP_NUM) 849 return 0; 850 node->visit_info[index].total_num++; 851 if (drop) 852 node->visit_info[index].drop_num++; 853 node->visit_info[index].app_id = app_id; 854 node->visit_info[index].latest_time = af_get_timestamp_sec(); 855 node->visit_info[index].latest_action = drop; 856 return 0; 857} 858 859int af_send_msg_to_user(char *pbuf, uint16_t len); 860int af_match_bcast_packet(flow_info_t *f){ 861 if (!f) 862 return 0; 863 if (0 == f->src || 0 == f->dst 864 || 0xffffffff == f->dst || 0 == f->dst) 865 return 1; 866 return 0; 867} 868 869int af_match_local_packet(flow_info_t *f){ 870 if (!f) 871 return 0; 872 if (0x0100007f == f->src || 0x0100007f == f->dst){ 873 return 1; 874 } 875 return 0; 876} 877 878int dpi_main(struct sk_buff *skb, flow_info_t *flow){ 879 dpi_http_proto(flow); 880 dpi_https_proto(flow); 881 if (TEST_MODE()) 882 dump_flow_info(flow); 883 return 0; 884} 885 886void af_get_smac(struct sk_buff *skb, u_int8_t *smac){ 887 struct ethhdr *ethhdr = NULL; 888 ethhdr = eth_hdr(skb); 889 if (ethhdr) 890 memcpy(smac, ethhdr->h_source, ETH_ALEN); 891 else 892 memcpy(smac, &skb->cb[40], ETH_ALEN); 893} 894int is_ipv4_broadcast(uint32_t ip) { 895 896 return (ip & 0x00FFFFFF) == 0x00FFFFFF; 897} 898 899int is_ipv4_multicast(uint32_t ip) { 900 return (ip & 0xF0000000) == 0xE0000000; 901} 902int af_check_bcast_ip(flow_info_t *f) 903{ 904 905 if (0 == f->src || 0 == f->dst) 906 return 1; 907 if (is_ipv4_broadcast(ntohl(f->src)) || is_ipv4_broadcast(ntohl(f->dst))){ 908 return 1; 909 } 910 if (is_ipv4_multicast(ntohl(f->src)) || is_ipv4_multicast(ntohl(f->dst))){ 911 return 1; 912 } 913 914 return 0; 915} 916#define MAC_FMT "%02X:%02X:%02X:%02X:%02X:%02X" 917u_int32_t app_filter_hook_bypass_handle(struct sk_buff *skb, struct net_device *dev){ 918 flow_info_t flow; 919 u_int8_t smac[ETH_ALEN]; 920 af_client_info_t *client = NULL; 921 922 if (!skb || !dev) 923 return NF_ACCEPT; 924 925 if (0 == af_lan_ip || 0 == af_lan_mask) 926 return NF_ACCEPT; 927 if (dev->name && strstr(dev->name, "docker")) 928 return NF_ACCEPT; 929 930 memset((char *)&flow, 0x0, sizeof(flow_info_t)); 931 if (parse_flow_proto(skb, &flow) < 0) 932 return NF_ACCEPT; 933 934 if (af_lan_ip == flow.src || af_lan_ip == flow.dst){ 935 return NF_ACCEPT; 936 } 937 if (af_check_bcast_ip(&flow) || af_match_local_packet(&flow)) 938 return NF_ACCEPT; 939 940 if ((flow.src & af_lan_mask) != (af_lan_ip & af_lan_mask)){ 941 return NF_ACCEPT; 942 } 943 af_get_smac(skb, smac); 944 945 AF_CLIENT_LOCK_W(); 946 client = find_and_add_af_client(smac); 947 if (!client){ 948 AF_CLIENT_UNLOCK_W(); 949 return NF_ACCEPT; 950 } 951 client->update_jiffies = jiffies; 952 AF_CLIENT_UNLOCK_W(); 953 954 if (0 != dpi_main(skb, &flow)) 955 return NF_ACCEPT; 956 957 client->ip = flow.src; 958 app_filter_match(&flow); 959 if (flow.app_id != 0){ 960 af_update_client_app_info(client, flow.app_id, flow.drop); 961 } 962 if (flow.drop) 963 { 964 return NF_DROP; 965 } 966 return NF_ACCEPT; 967} 968 969u_int32_t app_filter_hook_gateway_handle(struct sk_buff *skb, struct net_device *dev){ 970 unsigned long long total_packets = 0; 971 flow_info_t flow; 972 enum ip_conntrack_info ctinfo; 973 struct nf_conn *ct = NULL; 974 struct nf_conn_acct *acct; 975 af_client_info_t *client = NULL; 976 int app_id = 0; 977 int drop = 0; 978 979 memset((char *)&flow, 0x0, sizeof(flow_info_t)); 980 if (parse_flow_proto(skb, &flow) < 0) 981 return NF_ACCEPT; 982 983 ct = nf_ct_get(skb, &ctinfo); 984 if (ct == NULL || !nf_ct_is_confirmed(ct)) 985 return NF_ACCEPT; 986 987 AF_CLIENT_LOCK_R(); 988 client = find_af_client_by_ip(flow.src); 989 if (!client){ 990 AF_CLIENT_UNLOCK_R(); 991 return NF_ACCEPT; 992 } 993 client->update_jiffies = jiffies; 994 AF_CLIENT_UNLOCK_R(); 995 996 if (ct->mark != 0) 997 { 998 app_id = ct->mark & (~NF_DROP_BIT); 999 if (app_id > 1000 && app_id < 9999){ 1000 if (NF_DROP_BIT == (ct->mark & NF_DROP_BIT)) 1001 drop = 1; 1002 AF_CLIENT_LOCK_W(); 1003 af_update_client_app_info(client, app_id, drop); 1004 AF_CLIENT_UNLOCK_W(); 1005 1006 if (drop){ 1007 return NF_DROP; 1008 } 1009 } 1010 } 1011 acct = nf_conn_acct_find(ct); 1012 if(!acct) 1013 return NF_ACCEPT; 1014 total_packets = (unsigned long long)atomic64_read(&acct->counter[IP_CT_DIR_ORIGINAL].packets) 1015 + (unsigned long long)atomic64_read(&acct->counter[IP_CT_DIR_REPLY].packets); 1016 1017 if(total_packets > MAX_DPI_PKT_NUM) 1018 return NF_ACCEPT; 1019 1020 if (0 != dpi_main(skb, &flow)) 1021 return NF_ACCEPT; 1022 1023 app_filter_match(&flow); 1024 1025 if (flow.app_id != 0) 1026 { 1027 ct->mark = flow.app_id; 1028 AF_CLIENT_LOCK_W(); 1029 af_update_client_app_info(client, flow.app_id, flow.drop); 1030 AF_CLIENT_UNLOCK_W(); 1031 AF_LMT_INFO("match %s %pI4(%d)--> %pI4(%d) len = %d, %d\n ", IPPROTO_TCP == flow.l4_protocol ? "tcp" : "udp", 1032 &flow.src, flow.sport, &flow.dst, flow.dport, skb->len, flow.app_id); 1033 } 1034 if (flow.drop) 1035 { 1036 ct->mark |= NF_DROP_BIT; 1037 AF_LMT_INFO("##Drop app %s flow, appid is %d\n", flow.app_name, flow.app_id); 1038 return NF_DROP; 1039 } 1040 return NF_ACCEPT; 1041} 1042 1043 1044#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) 1045static u_int32_t app_filter_hook(void *priv, 1046 struct sk_buff *skb, 1047 const struct nf_hook_state *state) 1048{ 1049#else 1050static u_int32_t app_filter_hook(unsigned int hook, 1051 struct sk_buff *skb, 1052 const struct net_device *in, 1053 const struct net_device *out, 1054 int (*okfn)(struct sk_buff *)) 1055{ 1056#endif 1057 if (!g_oaf_enable) 1058 return NF_ACCEPT; 1059 if (AF_MODE_BYPASS == af_work_mode) 1060 return NF_ACCEPT; 1061 return app_filter_hook_gateway_handle(skb, skb->dev); 1062} 1063 1064#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) 1065static u_int32_t app_filter_by_pass_hook(void *priv, 1066 struct sk_buff *skb, 1067 const struct nf_hook_state *state) 1068{ 1069#else 1070static u_int32_t app_filter_by_pass_hook(unsigned int hook, 1071 struct sk_buff *skb, 1072 const struct net_device *in, 1073 const struct net_device *out, 1074 int (*okfn)(struct sk_buff *)) 1075{ 1076#endif 1077 if (!g_oaf_enable) 1078 return NF_ACCEPT; 1079 if (AF_MODE_GATEWAY == af_work_mode) 1080 return NF_ACCEPT; 1081 return app_filter_hook_bypass_handle(skb, skb->dev); 1082} 1083 1084 1085#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) 1086static struct nf_hook_ops app_filter_ops[] __read_mostly = { 1087 { 1088 .hook = app_filter_hook, 1089 .pf = PF_INET, 1090 .hooknum = NF_INET_FORWARD, 1091 .priority = NF_IP_PRI_MANGLE + 1, 1092 1093 }, 1094 { 1095 .hook = app_filter_by_pass_hook, 1096 .pf = PF_INET, 1097 .hooknum = NF_INET_PRE_ROUTING, 1098 .priority = NF_IP_PRI_MANGLE + 1, 1099 }, 1100}; 1101#else 1102static struct nf_hook_ops app_filter_ops[] __read_mostly = { 1103 { 1104 .hook = app_filter_hook, 1105 .owner = THIS_MODULE, 1106 .pf = PF_INET, 1107 .hooknum = NF_INET_FORWARD, 1108 .priority = NF_IP_PRI_MANGLE + 1, 1109 }, 1110}; 1111#endif 1112 1113 1114struct timer_list oaf_timer; 1115int report_flag = 0; 1116#define OAF_TIMER_INTERVAL 1 1117#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0) 1118static void oaf_timer_func(struct timer_list *t) 1119#else 1120static void oaf_timer_func(unsigned long ptr) 1121#endif 1122{ 1123 static int count = 0; 1124 if (count % 60 == 0) 1125 check_client_expire(); 1126 if (count % 60 == 0 || report_flag) 1127 { 1128 report_flag = 0; 1129 af_visit_info_report(); 1130 } 1131 count++; 1132 mod_timer(&oaf_timer, jiffies + OAF_TIMER_INTERVAL * HZ); 1133} 1134 1135void init_oaf_timer(void) 1136{ 1137#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0) 1138 timer_setup(&oaf_timer, oaf_timer_func, 0); 1139#else 1140 setup_timer(&oaf_timer, oaf_timer_func, OAF_TIMER_INTERVAL * HZ); 1141#endif 1142 mod_timer(&oaf_timer, jiffies + OAF_TIMER_INTERVAL * HZ); 1143 AF_INFO("init oaf timer...ok"); 1144} 1145 1146void fini_oaf_timer(void) 1147{ 1148 del_timer_sync(&oaf_timer); 1149 AF_INFO("del oaf timer...ok"); 1150} 1151 1152static struct sock *oaf_sock = NULL; 1153 1154int af_send_msg_to_user(char *pbuf, uint16_t len) 1155{ 1156 struct sk_buff *nl_skb; 1157 struct nlmsghdr *nlh; 1158 //todo: kmalloc 1159 char msg_buf[MAX_OAF_NL_MSG_LEN] = {0}; 1160 struct af_msg_hdr *hdr = NULL; 1161 char *p_data = NULL; 1162 int ret; 1163 if (len >= MAX_OAF_NL_MSG_LEN) 1164 return -1; 1165 1166 memset(msg_buf, 0x0, sizeof(msg_buf)); 1167 nl_skb = nlmsg_new(len + sizeof(struct af_msg_hdr), GFP_ATOMIC); 1168 if (!nl_skb) 1169 { 1170 return -1; 1171 } 1172 1173 nlh = nlmsg_put(nl_skb, 0, 0, OAF_NETLINK_ID, len + sizeof(struct af_msg_hdr), 0); 1174 if (nlh == NULL) 1175 { 1176 nlmsg_free(nl_skb); 1177 return -1; 1178 } 1179 1180 hdr = (struct af_msg_hdr *)msg_buf; 1181 hdr->magic = 0xa0b0c0d0; 1182 hdr->len = len; 1183 p_data = msg_buf + sizeof(struct af_msg_hdr); 1184 memcpy(p_data, pbuf, len); 1185 memcpy(nlmsg_data(nlh), msg_buf, len + sizeof(struct af_msg_hdr)); 1186 ret = netlink_unicast(oaf_sock, nl_skb, 999, MSG_DONTWAIT); 1187 return ret; 1188} 1189 1190static void oaf_user_msg_handle(af_msg_t *msg) 1191{ 1192 switch (msg->action) 1193 { 1194 case AF_MSG_INIT: 1195 af_client_list_reset_report_num(); 1196 report_flag = 1; 1197 break; 1198 default: 1199 break; 1200 } 1201} 1202static void oaf_msg_rcv(struct sk_buff *skb) 1203{ 1204 struct nlmsghdr *nlh = NULL; 1205 char *umsg = NULL; 1206 void *udata = NULL; 1207 struct af_msg_hdr *af_hdr = NULL; 1208 if (skb->len >= nlmsg_total_size(0)) 1209 { 1210 nlh = nlmsg_hdr(skb); 1211 umsg = NLMSG_DATA(nlh); 1212 af_hdr = (struct af_msg_hdr *)umsg; 1213 if (af_hdr->magic != 0xa0b0c0d0) 1214 return; 1215 if (af_hdr->len <= 0 || af_hdr->len >= MAX_OAF_NETLINK_MSG_LEN) 1216 return; 1217 udata = umsg + sizeof(struct af_msg_hdr); 1218 1219 if (udata) 1220 oaf_user_msg_handle((af_msg_t *)udata); 1221 } 1222} 1223 1224int netlink_oaf_init(void) 1225{ 1226 struct netlink_kernel_cfg nl_cfg = {0}; 1227 nl_cfg.input = oaf_msg_rcv; 1228 oaf_sock = netlink_kernel_create(&init_net, OAF_NETLINK_ID, &nl_cfg); 1229 1230 if (NULL == oaf_sock) 1231 { 1232 AF_ERROR("init oaf netlink failed, id=%d\n", OAF_NETLINK_ID); 1233 return -1; 1234 } 1235 AF_INFO("init oaf netlink ok, id = %d\n", OAF_NETLINK_ID); 1236 return 0; 1237} 1238 1239static int __init app_filter_init(void) 1240{ 1241 if (0 != load_feature_config()) 1242 { 1243 return -1; 1244 } 1245 1246 netlink_oaf_init(); 1247 af_log_init(); 1248 af_register_dev(); 1249 af_mac_list_init(); 1250 af_init_app_status(); 1251 init_af_client_procfs(); 1252 af_client_init(); 1253#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0) 1254 nf_register_net_hooks(&init_net, app_filter_ops, ARRAY_SIZE(app_filter_ops)); 1255#else 1256 nf_register_hooks(app_filter_ops, ARRAY_SIZE(app_filter_ops)); 1257#endif 1258 init_oaf_timer(); 1259 AF_INFO("init app filter ........ok\n"); 1260 return 0; 1261} 1262 1263static void app_filter_fini(void) 1264{ 1265 AF_INFO("app filter module exit\n"); 1266 fini_oaf_timer(); 1267#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0) 1268 nf_unregister_net_hooks(&init_net, app_filter_ops, ARRAY_SIZE(app_filter_ops)); 1269#else 1270 nf_unregister_hooks(app_filter_ops, ARRAY_SIZE(app_filter_ops)); 1271#endif 1272 1273 af_clean_feature_list(); 1274 af_mac_list_clear(); 1275 af_unregister_dev(); 1276 af_log_exit(); 1277 af_client_exit(); 1278 finit_af_client_procfs(); 1279 if (oaf_sock) 1280 netlink_kernel_release(oaf_sock); 1281 return; 1282} 1283 1284module_init(app_filter_init); 1285module_exit(app_filter_fini); 1286