diff --git a/plugin/business/pangu-http/pangu_http.cpp b/plugin/business/pangu-http/pangu_http.cpp new file mode 100644 index 0000000..076a075 --- /dev/null +++ b/plugin/business/pangu-http/pangu_http.cpp @@ -0,0 +1,67 @@ +enum HttpActionType +{ + kActionBypass = 0x00, + kActionMonitor = 0x01, + kActionBlock = 0x10, + kActionDrop = 0x20, + kActionRedirect = 0x30, + kActionRateLimit = 0x40, + kActionReplace = 0x50, + kActionWhiteList = 0x80, + kActionMax = 0xff +}; + +Maat_feather_t init_maat(const char* profile, const char* section,int max_thread, void* logger) +{ + Maat_feather_t target; + int maat_json_switch=0,maat_stat_on=0,maat_perf_on=0; + int ret=0,scan_detail=0,effect_interval=60; + char table_info[MAX_PATH_LEN]={0},inc_cfg_dir[MAX_PATH_LEN]={0},ful_cfg_dir[MAX_PATH_LEN]={0}; + char json_cfg_file[MAX_PATH_LEN]={0},maat_stat_file[MAX_PATH_LEN]={0}; + const char* instance_name="soq"; + MESA_load_profile_int_def(profile, section,"MAAT_JSON_SWITCH", &(maat_json_switch),0); + MESA_load_profile_int_def(profile, section,"STAT_SWITCH", &(maat_stat_on),1); + MESA_load_profile_int_def(profile, section,"PERF_SWITCH", &(maat_perf_on),1); + + MESA_load_profile_string_def(profile,section,"TABLE_INFO",table_info, sizeof(table_info),""); + MESA_load_profile_string_def(profile,section,"INC_CFG_DIR",inc_cfg_dir, sizeof(inc_cfg_dir),""); + MESA_load_profile_string_def(profile,section,"FULL_CFG_DIR",ful_cfg_dir, sizeof(ful_cfg_dir),""); + MESA_load_profile_string_def(profile,section,"JSON_CFG_FILE",json_cfg_file, sizeof(json_cfg_file),""); + MESA_load_profile_string_def(profile,section,"STAT_FILE",maat_stat_file, sizeof(maat_stat_file),""); + MESA_load_profile_int_def(profile,section,"EFFECT_INTERVAL_S", &(effect_interval),60); + + effect_interval*=1000;//convert s to ms + assert(strlen(inc_cfg_dir)!=0&&strlen(ful_cfg_dir)!=0); + + target=Maat_feather(max_thread,table_info, logger); + Maat_set_feather_opt(target,MAAT_OPT_INSTANCE_NAME,instance_name, strlen(instance_name)+1); + if(maat_json_switch==1) + { + Maat_set_feather_opt(target, MAAT_OPT_JSON_FILE_PATH, json_cfg_file, strlen(json_cfg_file)+1); + } + else + { + Maat_set_feather_opt(target, MAAT_OPT_FULL_CFG_DIR, ful_cfg_dir, strlen(ful_cfg_dir)+1); + Maat_set_feather_opt(target, MAAT_OPT_INC_CFG_DIR, inc_cfg_dir, strlen(inc_cfg_dir)+1); + } + if(maat_stat_on) + { + Maat_set_feather_opt(target, MAAT_OPT_STAT_FILE_PATH, maat_stat_file, strlen(maat_stat_file)+1); + Maat_set_feather_opt(target, MAAT_OPT_STAT_ON, NULL, 0); + if(maat_perf_on) + { + Maat_set_feather_opt(target, MAAT_OPT_PERF_ON, NULL, 0); + } + } + + Maat_set_feather_opt(target, MAAT_OPT_EFFECT_INVERVAL_MS, &effect_interval, sizeof(effect_interval)); + //t1 or t2 do not care hit position. + Maat_set_feather_opt(target, MAAT_OPT_SCAN_DETAIL, &scan_detail, sizeof(scan_detail)); + ret=Maat_initiate_feather(target); + if(ret<0) + { + return NULL; + } + return target; +} + diff --git a/plugin/business/pangu-http/pangu_logger.cpp b/plugin/business/pangu-http/pangu_logger.cpp new file mode 100644 index 0000000..7d39fe7 --- /dev/null +++ b/plugin/business/pangu-http/pangu_logger.cpp @@ -0,0 +1,162 @@ +#include "tfe_utils.h" +#include "cJSON.h" + +#include +#include +#include +#include +#include +#include + + + +struct json_spec +{ + int json_type; + const char *name; +}; + +struct pangu_logger +{ + char local_ip_str[TFE_SYMBOL_MAX]; + int entry_id; + + unsigned int local_ip_nr; + void* global_logger; + rd_kafka_t *kafka_handle; + rd_kafka_topic_t* kafka_topic; + + char brokerlist[TFE_STRING_MAX]; + struct json_spec opt2json[LOG_OPT_MAX]; + const char* topic_name; + + void* local_logger; + + unsigned long long send_cnt; + unsigned long long random_drop; + unsigned long long user_abort; + char local_log_path[TFE_STRING_MAX]; +}; + + + +unsigned int get_ip_by_eth_name(const char *ifname) +{ + int sockfd; + struct ifreq ifr; + unsigned int ip; + + sockfd = socket(AF_INET, SOCK_DGRAM, 0); + if (-1 == sockfd) + { + goto error; + } + + strcpy(ifr.ifr_name,ifname); + if (ioctl(sockfd, SIOCGIFADDR, &ifr) < 0) + { + goto error; + } + + ip = ((struct sockaddr_in*)&(ifr.ifr_addr))->sin_addr.s_addr; + close(sockfd); + return ip; + +error: + close(sockfd); + return INADDR_NONE; +} + + + +rd_kafka_t * create_kafka_handle(const char* brokerlist) +{ + int i = 0; + char kafka_errstr[1024]; + rd_kafka_t *handle=NULL; + rd_kafka_conf_t *rdkafka_conf = NULL; + + rdkafka_conf = rd_kafka_conf_new(); + rd_kafka_conf_set(rdkafka_conf, "queue.buffering.max.messages", "1000000", kafka_errstr, sizeof(kafka_errstr)); + rd_kafka_conf_set(rdkafka_conf, "topic.metadata.refresh.interval.ms", "600000",kafka_errstr, sizeof(kafka_errstr)); + rd_kafka_conf_set(rdkafka_conf, "security.protocol", "MG", kafka_errstr, sizeof(kafka_errstr)); + + //The conf object is freed by this function and must not be used or destroyed by the application sub-sequently. + handle = rd_kafka_new(RD_KAFKA_PRODUCER, rdkafka_conf, kafka_errstr, sizeof(kafka_errstr)); + rdkafka_conf=NULL; + if (handle==NULL) + { + return NULL; + } + if (rd_kafka_brokers_add(handle, brokerlist) == 0) + { + rd_kafka_destroy(handle); + return NULL; + } + return handle; +} + + + +struct pangu_logger* pangu_logger_init(const char* profile, const char* section, void* logger) +{ + int ret=-1,i=0; + char addr_string[TFE_SYMBOL_MAX]={0},local_msg_dir[TFE_STRING_MAX]={0}; + char nic_name[64]={0}; + unsigned int ip_buff[TFE_SYMBOL_MAX]; + + struct pangu_logger* instance=ALLOC(struct pangu_logger,1); + instance->global_logger=logger; + + instance->opt2json[LOG_OPT_HTTP_C2S_ISN] = {cJSON_Number,"isn"}; + instance->opt2json[LOG_OPT_HTTP_PROXY_FLAG] = {cJSON_Number,"proxy_flag"}; + instance->opt2json[LOG_OPT_HTTP_URL] = {cJSON_String,"url"}; + instance->opt2json[LOG_OPT_HTTP_COOKIE] = {cJSON_String,"cookie"}; + instance->opt2json[LOG_OPT_HTTP_REFERER] = {cJSON_String,"referer"}; + instance->opt2json[LOG_OPT_HTTP_UA] = {cJSON_String,"user_agent"}; + instance->opt2json[LOG_OPT_HTTP_REQ_LINE] = {cJSON_String,"req_line"}; + instance->opt2json[LOG_OPT_HTTP_RES_LINE] = {cJSON_String,"res_line"}; + instance->opt2json[LOG_OPT_HTTP_SET_COOKIE] = {cJSON_String,"set_cookie"}; + instance->opt2json[LOG_OPT_HTTP_CONTENT_TYPE] = {cJSON_String,"content_type"}; + instance->opt2json[LOG_OPT_HTTP_CONTENT_LEN] = {cJSON_String,"content_len"}; + + TFE_LOG_ERROR(logger,"Pangu log is inititating from %s section %s.", profile, section); + + MESA_load_profile_string_def(profile, section, "NIC_NAME",nic_name,sizeof(nic_name),"eth0"); + instance->local_ip_nr=get_ip_by_eth_name(nic_name); + if(instance->local_ip_nr==INADDR_NONE) + { + TFE_LOG_ERROR(logger, "%s get NIC_NAME: %s error.", __FUNCTION__, nic_name); + goto error_out; + } + inet_ntop(AF_INET,&(instance->local_ip_nr),instance->local_ip_str,sizeof(instance->local_ip_str)); + + MESA_load_profile_int_def(profile, section, "ENTRANCE_ID",&(instance->entry_id),0); + + ret=MESA_load_profile_string_def(profile, section,"KAFKA_BROKERLIST", instance->brokerlist, sizeof(instance->brokerlist), NULL); + if(ret<0) + { + TFE_LOG_ERROR(logger,"Pangu log init failed, no brokerlist in profile %s section %s.", profile, section); + goto error_out; + } + instance->kafka_handle=create_kafka_handle(instance->brokerlist); + if(instance->kafka_handle==NULL) + { + TFE_LOG_ERROR(logger,"Pangu log init failed. Cannot create lafka handle with brokerlist: %s.", instance->brokerlist); + goto error_out; + } + instance->topic_name="PXY_HTTP_LOG"; + instance->kafka_topic = rd_kafka_topic_new(instance->kafka_handle,instance->topic_name, NULL); + + return instance; + +error_out: + free(instance); + return NULL; +} +int pangu_send_log(struct pangu_logger* logger, const pangu_log* log_msg,struct opt_unit* log_opt,int opt_num) +{ + +} + + diff --git a/plugin/business/pangu-http/pangu_logger.h b/plugin/business/pangu-http/pangu_logger.h new file mode 100644 index 0000000..0f20366 --- /dev/null +++ b/plugin/business/pangu-http/pangu_logger.h @@ -0,0 +1,88 @@ +#pragma once + +#include "tfe_stream.h" +#include + +enum pangu_log_opt +{ + //Shared log options + LOG_OPT_SCENE_FILE=1, //IP pcap/Mail content + LOG_OPT_STREAM_INFO, // data is a struct stream_info *, size =8 + LOG_OPT_MAAT_RULE, //duplicate option is allowed. + + //Following are options for the respective protocol + + LOG_OPT_HTTP_REQ_LINE, + LOG_OPT_HTTP_REQ_HDR, + LOG_OPT_HTTP_REQ_BODY, + LOG_OPT_HTTP_RES_LINE, + LOG_OPT_HTTP_RES_HDR, + LOG_OPT_HTTP_RES_BODY, + LOG_OPT_HTTP_URL, + LOG_OPT_HTTP_C2S_ISN, //size=4 + LOG_OPT_HTTP_PROXY_FLAG, //size=4 ,0 or 1 + LOG_OPT_HTTP_SEQ, //size=4 + LOG_OPT_HTTP_COOKIE, + LOG_OPT_HTTP_REFERER, + LOG_OPT_HTTP_UA, + LOG_OPT_HTTP_SET_COOKIE, + LOG_OPT_HTTP_CONTENT_LEN, + LOG_OPT_HTTP_CONTENT_TYPE, + LOG_OPT_HTTP_USER_DEFINE, //key:value+ '\0' ,e.g. "Server:nginx" + + LOG_OPT_MAIL_PROTO,//string:"pop3","smtp" or "imap4" + LOG_OPT_MAIL_FROM, + LOG_OPT_MAIL_TO, + LOG_OPT_MAIL_SUBJECT, + LOG_OPT_MAIL_EML, + + LOG_OPT_DNS_RD, //Shared with FD and JC + LOG_OPT_DNS_QTYPE, //Shared with FD and JC + LOG_OPT_DNS_QCLASS, //Shared with FD and JC + LOG_OPT_DNS_OPCODE, //Shared with FD and JC + LOG_OPT_DNS_QNAME, //Shared with FD and JC + LOG_OPT_DNS_CHEAT_TYPE, //Only in FD + LOG_OPT_DNS_CHEAT_RCODE, //Only in FD + LOG_OPT_DNS_CHEAT_STRATEGY, //Only in FD + LOG_OPT_DNS_CHEAT_RECORD, //Only in FD + LOG_OPT_DNS_CHEAT_TTL, //Only in FD + LOG_OPT_DNS_QR, //Only in JC + LOG_OPT_DNS_RA, //Only in JC + LOG_OPT_DNS_RR, //Only in JC + LOG_OPT_DNS_TTL, //Only in JC + LOG_OPT_DNS_DNS_SUB, //Only in JC, size=sizeof(int) 0-DNS,1-DNSSEC + + LOG_OPT_FTP_URL, + + + LOG_OPT_MAX +}; + + +typedef enum _soq_action +{ + SOQ_ACTION_BLOCK, + SOQ_ACTION_MONITOR, + SOQ_ACTION_CONTINUE, + SOQ_ACTION_ABORT +}soq_action_t; + +struct opt_unit +{ + enum pangu_log_opt opt_type; + int opt_len; + const void* opt_value; +}; + +struct pangu_log +{ + const struct tfe_stream *stream; + const Maat_rule_t*result; + int result_num; +}; +struct pangu_logger* logger; + +//return 0 if SUCCESS, otherwise return -1 +int pangu_send_log(struct pangu_logger* logger, const pangu_log* log_msg, struct opt_unit* log_opt, int opt_num); +#endif +