📄 flowps.c
字号:
/** * Printout a score entry * * @param ps_score score entry to printf * * @return FLOW_SUCCESS on success */int flowps_score_print(PS_SCORE *ps_score){ flow_printf(" score: %u start: %u end: %u", ps_score->score, (unsigned int) ps_score->start, (unsigned int) ps_score->ends); return FLOW_SUCCESS;}int flowps_entry_print(SCORE_ENTRY *entry, u_int32_t *address){ char *c_position = "TRACKER_ACTIVE"; u_int32_t i; if(entry->position == TRACKER_SCANNER) c_position = "TRACKER_SCANNER"; flow_printf(",-----------------------------------------------------\n"); flow_printf("| Score entry for %s@%p Flags: %x\n", inet_ntoa(*(struct in_addr *) address), entry, entry->flags); flow_printf("| Alerts: FT: %u ST: %u FS: %u SS: %u", (entry->flags & ALERT_FIXED_TALKER), (entry->flags & ALERT_SLIDING_TALKER), (entry->flags & ALERT_FIXED_SCANNER), (entry->flags & ALERT_SLIDING_SCANNER)); flowps_score_print(&entry->fixed_talker); flow_printf("\n| Position: %s\n", c_position); flow_printf("| Fixed Talker:"); flowps_score_print(&entry->fixed_talker); flow_printf("\n| Sliding Talker:"); flowps_score_print(&entry->sliding_talker); flow_printf("\n| Fixed Scanner:"); flowps_score_print(&entry->fixed_scanner); flow_printf("\n| Sliding Scanner:"); flowps_score_print(&entry->sliding_scanner); flow_printf("\n| Connections Seen: %u", entry->connections_seen); /* as long as we have a postive # of connections, pump out the info */ for(i=0; i < entry->connections_seen && i < FLOWPS_HOSTS_SIZE; i++) { CONN_ENTRY *cp = &entry->last_hosts[i]; if(cp->protocol == 6) { flow_printf("\n| proto: %d %s:%d th_flags: %s", cp->protocol, inet_ntoa(*(struct in_addr*) &cp->ip), cp->port, mktcpflag_str(cp->cflags)); } else { flow_printf("\n| proto: %d %s:%d cflags: %d", cp->protocol, inet_ntoa(*(struct in_addr*) &cp->ip), cp->port, cp->cflags); } } flow_printf("\n`----------------------------------------------------\n"); return 0;}void flowps_stats(PS_TRACKER *pstp){ int dumpall = pstp->config.dumpall; flow_printf("+---[ Flow-portscan Stats ]----------------+\n"); scoreboard_stats(&pstp->table_active, dumpall); scoreboard_stats(&pstp->table_scanner, dumpall); ut_stats(&pstp->unique_tracker, dumpall); server_stats(&pstp->server_stats, dumpall);}/** * Assign TCP penalty points * * have an optional penalty for odd flags combinations on TCP -- * this should probably promote people to the TRACKER_SCANNER * table as well. * * Perhaps we should extend this to non-common ICMP errors as * well. * * S,12 & SYN are the 1 ptrs. * * XMAS w/ ACK is a 5 ptr * * SF+ is a 3 ptr. * * @param flags th_flags * @param base_score base score value for normal initiations * @param score ptr for return value */static INLINE void flowps_tcp_penalty(u_int32_t flags, int base_score, int *score){ if((flags == TH_SYN) || (flags == (TH_SYN|TH_RES1|TH_RES2))) { /* this is the common case for a session initiator */ *score = base_score; } else if((flags & (TH_SYN|TH_FIN|TH_ACK)) == (TH_SYN|TH_FIN|TH_ACK)) { *score = 5; } else if((flags & (TH_SYN|TH_FIN)) == (TH_SYN|TH_FIN)) { *score = 3; } else { *score = 2; }} /** * Get the score and the type of connection this is * * If the score is 0, this is an already existing connection and can * be successfully ignored. * * @param pstp portscan tracker * @param flowp flow to aquire a score for * * @param cur current time * @flags packet related flags that can be used to modify the score * @param score return value for the score * @param type return value for the type of connection * * @return FLOW_SUCCESS on success and sets the score and type */int flowps_get_score(PS_TRACKER *pstp, FLOW *flowp, time_t cur, u_int32_t flags, int *score, TRACKER_POSITION *type){ UT_TYPE unique; u_int32_t hitcount = 1; int base_score; if(!flowp || !score || !type) { return FLOW_ENULL; } /* save off a default base score */ base_score = pstp->config.base_score; *score = pstp->config.base_score; /* run the uniqueness check * * This should be ABOVE the finding code since the unquieness * check is the key to determining if this should accrue more * points. If it's not unique, we can bail out instantly. * */ if(ut_check(&pstp->unique_tracker, &flowp->key, &unique) != FLOW_SUCCESS) {#ifndef WIN32 flow_printf("ut check failed in %s\n", __func__);#else flow_printf("ut check failed in %s(%d)\n", __FILE__, __LINE__);#endif return 0; } if(unique == UT_OLD) { /* bail out if we do not have a reason to further evaluate the * score. The score can only be changed if this flow is truely * a unique (dport+proto+address) */ *score = 0; return FLOW_SUCCESS; } else /* UT_NEW */ { if(flowps_server_watch(pstp,flowp->key.resp_address) == FLOW_SUCCESS) { /* perform the hitcount management */ if(cur < (packet_first_time() + pstp->config.server_learning_time)) { if(server_stats_add_ipv4(&pstp->server_stats, flowp->key.protocol, flowp->key.resp_address, flowp->key.resp_port, &hitcount) != FLOW_SUCCESS) {#ifdef DEBUG flow_printf("Unable to add ipv4 to server stats!\n");#endif /* DEBUG */ } } else { hitcount = server_stats_hitcount_ipv4(&pstp->server_stats, flowp->key.protocol, flowp->key.resp_address, flowp->key.resp_port); if(pstp->config.server_scanner_limit && hitcount < pstp->config.server_scanner_limit) { *type = TRACKER_SCANNER; } } if(pstp->config.server_ignore_limit > 0 && hitcount > pstp->config.server_ignore_limit) { /* this must be a semi-active service -- it's not worth * anything */ if(s_debug > 5) { flow_printf("Happy Server hitcount: %d proto: %d %s:%d\n", hitcount, flowp->key.protocol, inet_ntoa(*(struct in_addr *) &flowp->key.resp_address), flowp->key.resp_port); } base_score = 0; } } /* this IP is not being watched or something like it */ else { hitcount = 1; } } /* * possibly assign penalty points for "bad session initiators */ if(pstp->config.tcp_penalties && flowp->key.protocol == 6) { flowps_tcp_penalty(flags, base_score, score); } else { *score = base_score; } /* @todo switch tables */ return FLOW_SUCCESS;}/** * Expire a fixed scale PS_SCORE * * @param pscp score entry to expire * @param current_time now * @param threshold threshold to slide againt * * @return FLOW_SUCCESS */int flowps_fixed_winadj(PS_SCORE *pscp, time_t current_time, SCORE_THRESHOLD *threshold){ int window_size = threshold->fixed_size; if(pscp->ends <= current_time) { pscp->start = current_time; pscp->score = 0; pscp->ends = current_time + window_size; } return FLOW_SUCCESS;}/** * Expire a sliding scale PS_SCORE * * considerably more complicated than the fixed time window * stuff. This really should be simplified. * * @param pscp score entry to expire * @param current_time current_time * @param threshold threshold to slide againt * * @return FLOW_SUCCESS */int flowps_sliding_winadj(PS_SCORE *pscp, time_t current_time, SCORE_THRESHOLD *threshold){ int diff_SE; /* time from start to end */ int diff_EN; /* time from end to current_time */ int window_size = threshold->sliding_size; int adjustment; float scale = threshold->window_scale; if(pscp->ends > current_time) { /* we're still in the right time frame -- should this * increment the time frame? Seems to make sense but how * often should the window "slide"? */ return FLOW_SUCCESS; } /* we atleast kcurrent_time to expire the score */ pscp->score = 0; if(pscp->ends == 0) { /* new time window, let's just initialize it */ pscp->start = current_time; pscp->ends = current_time + window_size; } else { diff_SE = pscp->ends - pscp->start; /* since we never allow end > current_time, this will always be >=0 */ diff_EN = current_time - pscp->ends; if(diff_EN > (diff_SE * 2)) { /* I've guessed at this one. If the difference between end -> * current_time is much bigger than the previous time window, this is * good enough to start the sliding time frame over * * This could present a weakness in that 1 unique flow every N * scale could still slip past us. It will always be possible * to slow the scan down though. This should really decrease * the amount of benign active talkers. */ pscp->start = current_time; pscp->ends = current_time + window_size; } else { pscp->start = current_time; adjustment = diff_SE + (diff_SE * ((int) scale)); if((adjustment + pscp->ends) > pscp->ends) { pscp->ends += adjustment; } else { /* watching for integer wrap around incase an attacker * causes our scales to wrapidly increase somehow * * We don't watch to make sure that the user doesn't * screw us. */ pscp->ends += window_size; } } } return FLOW_SUCCESS;}/** * Maintain the ring buffer of most recent connections * * @param sep score entry pointer * @param flowp flow pointer * @param cflags connection flags ( often just the th_flags ) * * @return FLOW_SUCCESS on sucess */int flowps_set_last_address(SCORE_ENTRY *sep, FLOW *flowp, u_int8_t cflags){ CONN_ENTRY *conn_entry; if(sep && flowp) { if(sep->last_idx >= FLOWPS_HOSTS_SIZE) { sep->last_idx = 0; } /* find the entry and increment the ring */ conn_entry = &sep->last_hosts[sep->last_idx++]; /* fill out the entry */ conn_entry->port = flowp->key.resp_port; conn_entry->ip = flowp->key.resp_address; conn_entry->protocol = flowp->key.protocol; conn_entry->cflags = cflags; /* increment how many connections this tracker has seen */ sep->connections_seen++; } return FLOW_SUCCESS;}/** * see if flowps is turned on * * * @return 1 if portscan is on */int flowps_enabled(void){ return s_enabled;}/** * Check to see if this IPv4 Address should be ignored by the portscan * tracker. * * This checks both the src and dst lists. * * @param pstp portscan tracker * @param sip pointer to the sip in NETWORK byte order * @param dip pointer to the dip in NETWORK byte order * * @return FLOW_SUCCESS if this ip should be ignored, else it should be used */int flowps_is_ignored_ipv4(PS_TRACKER *pstp, u_int32_t *sip, u_int32_t *dip){ u_int32_t host_sip, host_dip; /**< host ordered addresses */ if(pstp && sip && dip) { if(pstp->config.src_ignore_ipv4) { host_sip = ntohl(*sip); if(ipset_contains(pstp->config.src_ignore_ipv4, &host_sip, NULL, IPV4_FAMILY)) { return FLOW_SUCCESS; } } if(pstp->config.dst_ignore_ipv4) { host_dip = ntohl(*dip); if(ipset_contains(pstp->config.dst_ignore_ipv4, &host_dip, NULL, IPV4_FAMILY)) { return FLOW_SUCCESS; } } return FLOW_DISABLED; } return FLOW_ENULL;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -