00001
00002
00003 #ifdef HAVE_CONFIG_H
00004 #include "config.h"
00005 #endif
00006
00007
00008 #include "flowps.h"
00009 #include "scoreboard.h"
00010 #include "unique_tracker.h"
00011 #include "server_stats.h"
00012 #include "packet_time.h"
00013 #include "util_net.h"
00014
00015
00016 #ifndef TH_FIN
00017
00018 #define TH_FIN 0x01
00019 #define TH_SYN 0x02
00020 #define TH_RST 0x04
00021 #define TH_PUSH 0x08
00022 #define TH_ACK 0x10
00023 #define TH_URG 0x20
00024 #define TH_RES2 0x40
00025 #define TH_RES1 0x80
00026
00027
00028 #endif
00029
00030 #define FLOWPS_NC 1000000
00031
00032 static int s_debug = 0;
00033 static int s_enabled = 0;
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050 int flowps_mkthreshold(SCORE_THRESHOLD *thr,
00051 int fixed_size, u_int32_t fixed_limit,
00052 int sliding_size, u_int32_t sliding_limit,
00053 float window_scale)
00054 {
00055 if(!thr)
00056 return FLOW_ENULL;
00057
00058 if(fixed_size < 0)
00059 fixed_size = 0;
00060
00061 if(sliding_size < 0)
00062 sliding_size = 0;
00063
00064 thr->fixed_size = fixed_size;
00065 thr->sliding_size = sliding_size;
00066 thr->window_scale = window_scale;
00067 thr->fixed = fixed_limit;
00068 thr->sliding = sliding_limit;
00069
00070 return FLOW_SUCCESS;
00071 }
00072
00073
00074
00075
00076
00077
00078
00079
00080 int flowps_mkconfig(PS_CONFIG *configp,
00081 int sb_memcap_talker,
00082 int sb_rows_talker,
00083 int sb_memcap_scanner,
00084 int sb_rows_scanner,
00085 int ut_memcap,
00086 int ut_rows,
00087 int server_memcap,
00088 int server_rows,
00089 int server_learning_time,
00090 int tcp_penalties,
00091 u_int32_t server_ignore_limit,
00092 u_int32_t server_scanner_limit,
00093 int base_score,
00094 int alert_once,
00095 FLOWPS_OUTPUT output_mode)
00096 {
00097 if(!configp)
00098 return FLOW_ENULL;
00099
00100 memset(configp, 0, sizeof(PS_CONFIG));
00101
00102 configp->sb_memcap_total = sb_memcap_scanner + sb_memcap_talker;
00103 configp->sb_memcap_scanner = sb_memcap_scanner;
00104 configp->sb_memcap_talker = sb_memcap_talker;
00105
00106 configp->sb_rows_talker = sb_rows_talker;
00107 configp->sb_rows_scanner = sb_rows_scanner;
00108
00109 configp->tcp_penalties = tcp_penalties;
00110
00111 configp->ut_memcap = ut_memcap;
00112 configp->ut_rows = ut_rows;
00113
00114
00115 configp->server_memcap = server_memcap;
00116 configp->server_rows = server_rows;
00117 configp->server_learning_time = server_learning_time;
00118 configp->server_ignore_limit = server_ignore_limit;
00119 configp->server_scanner_limit = server_scanner_limit;
00120 configp->base_score = base_score;
00121 configp->alert_once = alert_once;
00122 configp->output_mode = output_mode;
00123 configp->dumpall = 0;
00124 return FLOW_SUCCESS;
00125 }
00126
00127
00128
00129
00130
00131
00132
00133
00134 int flowps_server_stats_enabled(PS_TRACKER *trackerp)
00135 {
00136 if(trackerp->config.server_watchnet_ipv4)
00137 return FLOW_SUCCESS;
00138
00139 return FLOW_DISABLED;
00140
00141 }
00142
00143
00144
00145
00146
00147
00148
00149
00150 int flowps_server_watch(PS_TRACKER *trackerp, u_int32_t address)
00151 {
00152 FLOWASSERT(trackerp != NULL);
00153
00154 if(trackerp->config.server_watchnet_ipv4 == NULL)
00155 return FLOW_DISABLED;
00156
00157 if(server_stats_contains(&trackerp->server_stats,address) == FLOW_SUCCESS)
00158 return FLOW_SUCCESS;
00159
00160
00161 return FLOW_DISABLED;
00162 }
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174 int flowps_init(PS_TRACKER *trackerp, PS_CONFIG *configp)
00175 {
00176 int ret;
00177
00178 if(!trackerp || !configp)
00179 return FLOW_ENULL;
00180
00181
00182 memcpy(&trackerp->config, configp, sizeof(PS_CONFIG));
00183
00184 ret = scoreboard_init(&trackerp->table_active,
00185 "Active Talkers",
00186 TRACKER_ACTIVE,
00187 trackerp->config.sb_rows_talker,
00188 trackerp->config.sb_memcap_talker);
00189
00190 if(ret != FLOW_SUCCESS)
00191 {
00192 return ret;
00193 }
00194
00195 ret = scoreboard_init(&trackerp->table_scanner,
00196 "Portscanners",
00197 TRACKER_SCANNER,
00198 trackerp->config.sb_rows_scanner,
00199 trackerp->config.sb_memcap_scanner);
00200
00201 if(ret != FLOW_SUCCESS)
00202 {
00203 scoreboard_destroy(&trackerp->table_active);
00204 return ret;
00205 }
00206
00207
00208 ret = ut_init(&trackerp->unique_tracker,trackerp->config.ut_rows, trackerp->config.ut_memcap);
00209
00210 if(ret != FLOW_SUCCESS)
00211 {
00212 scoreboard_destroy(&trackerp->table_active);
00213 scoreboard_destroy(&trackerp->table_scanner);
00214 return ret;
00215 }
00216
00217
00218 if(flowps_server_stats_enabled(trackerp) == FLOW_SUCCESS)
00219 {
00220 ret = server_stats_init(&trackerp->server_stats,
00221 trackerp->config.server_watchnet_ipv4,
00222 trackerp->config.server_rows,
00223 trackerp->config.server_memcap);
00224
00225 if(ret != FLOW_SUCCESS)
00226 {
00227 scoreboard_destroy(&trackerp->table_active);
00228 scoreboard_destroy(&trackerp->table_scanner);
00229 ut_destroy(&trackerp->unique_tracker);
00230 return ret;
00231 }
00232 }
00233
00234 s_enabled = 1;
00235
00236 return FLOW_SUCCESS;
00237 }
00238
00239 int flowps_destroy(PS_TRACKER *trackerp)
00240 {
00241 if(!trackerp)
00242 return FLOW_ENULL;
00243
00244 scoreboard_destroy(&trackerp->table_scanner);
00245 scoreboard_destroy(&trackerp->table_active);
00246 ut_destroy(&trackerp->unique_tracker);
00247
00248 return FLOW_SUCCESS;
00249 }
00250
00251
00252
00253
00254
00255
00256
00257
00258 static INLINE void flowps_reset_alert_flags(u_int32_t type,
00259 u_int32_t *alert_flags,
00260 u_int32_t *score)
00261 {
00262 if(((*alert_flags) & type))
00263 {
00264 *alert_flags &= ~type;
00265 *score = 0;
00266 }
00267 }
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281 int flowps_score_entry(PS_TRACKER *pstp, SCORE_ENTRY *sep, int score,
00282 TRACKER_POSITION tr_pos,
00283 int alert_once,
00284 u_int32_t *alert_flags)
00285 {
00286
00287
00288 if(!pstp || !sep || !alert_flags)
00289 {
00290 return FLOW_ENULL;
00291 }
00292
00293 *alert_flags = 0;
00294
00295 if(alert_once == 0)
00296 {
00297
00298
00299 flowps_reset_alert_flags(ALERT_FIXED_TALKER,
00300 &sep->flags,
00301 &sep->fixed_talker.score);
00302
00303 flowps_reset_alert_flags(ALERT_SLIDING_TALKER,
00304 &sep->flags,
00305 &sep->sliding_talker.score);
00306
00307 flowps_reset_alert_flags(ALERT_FIXED_SCANNER,
00308 &sep->flags,
00309 &sep->fixed_scanner.score);
00310
00311 flowps_reset_alert_flags(ALERT_SLIDING_SCANNER,
00312 &sep->flags,
00313 &sep->sliding_scanner.score);
00314 }
00315
00316 FLOWASSERT((tr_pos == TRACKER_SCANNER) || (tr_pos == TRACKER_ACTIVE));
00317
00318 switch(tr_pos)
00319 {
00320 case TRACKER_SCANNER:
00321 sep->fixed_scanner.score += score;
00322 sep->sliding_scanner.score += score;
00323
00324
00325 break;
00326 case TRACKER_ACTIVE:
00327 sep->fixed_talker.score += score;
00328 sep->sliding_talker.score += score;
00329 break;
00330 }
00331
00332
00333 if(pstp->config.limit_talker.fixed &&
00334 pstp->config.limit_talker.fixed <= sep->fixed_talker.score)
00335 {
00336 *alert_flags |= ALERT_FIXED_TALKER;
00337 }
00338
00339 if(pstp->config.limit_talker.sliding &&
00340 pstp->config.limit_talker.sliding <= sep->sliding_talker.score)
00341 {
00342 *alert_flags |= ALERT_SLIDING_TALKER;
00343 }
00344
00345 if(pstp->config.limit_scanner.fixed &&
00346 pstp->config.limit_scanner.fixed <= sep->fixed_scanner.score)
00347 {
00348 *alert_flags |= ALERT_FIXED_SCANNER;
00349 }
00350
00351 if(pstp->config.limit_scanner.sliding &&
00352 pstp->config.limit_scanner.sliding <= sep->sliding_scanner.score)
00353 {
00354 *alert_flags |= ALERT_SLIDING_SCANNER;
00355 }
00356
00357
00358
00359
00360
00361 if(alert_once)
00362 {
00363 *alert_flags &= ~sep->flags;
00364 }
00365
00366 return FLOW_SUCCESS;
00367 }
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382 int flowps_find_entry(PS_TRACKER *trackerp, u_int32_t *address, SCORE_ENTRY **sepp)
00383 {
00384 int ret;
00385
00386 if(!trackerp || !sepp || !address)
00387 {
00388 return FLOW_ENULL;
00389 }
00390
00391 ret = scoreboard_find(&trackerp->table_active, address, sepp);
00392
00393 if(ret == FLOW_NOTFOUND)
00394 {
00395
00396
00397
00398 ret = scoreboard_find(&trackerp->table_scanner, address, sepp);
00399 }
00400
00401 return ret;
00402 }
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426 int flowps_add_entry(PS_TRACKER *trackerp,
00427 TRACKER_POSITION position,
00428 u_int32_t *address,
00429 SCORE_ENTRY **sepp)
00430 {
00431 int ret;
00432
00433 if(position == TRACKER_ACTIVE)
00434 {
00435 ret = scoreboard_add(&trackerp->table_active, address, sepp);
00436 }
00437 else
00438 {
00439 ret = scoreboard_add(&trackerp->table_scanner, address, sepp);
00440 }
00441
00442 if(ret == FLOW_SUCCESS)
00443 {
00444 (*sepp)->position = position;
00445 }
00446
00447 return ret;
00448 }
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458 int flowps_score_print(PS_SCORE *ps_score)
00459 {
00460 flow_printf(" score: %u start: %u end: %u",
00461 ps_score->score,
00462 (unsigned int) ps_score->start,
00463 (unsigned int) ps_score->ends);
00464
00465 return FLOW_SUCCESS;
00466 }
00467
00468
00469 int flowps_entry_print(SCORE_ENTRY *entry, u_int32_t *address)
00470 {
00471 char *c_position = "TRACKER_ACTIVE";
00472 u_int32_t i;
00473 if(entry->position == TRACKER_SCANNER)
00474 c_position = "TRACKER_SCANNER";
00475
00476 flow_printf(",-----------------------------------------------------\n");
00477 flow_printf("| Score entry for %s@%p Flags: %x\n",
00478 inet_ntoa(*(struct in_addr *) address), entry, entry->flags);
00479
00480
00481 flow_printf("| Alerts: FT: %u ST: %u FS: %u SS: %u",
00482 (entry->flags & ALERT_FIXED_TALKER),
00483 (entry->flags & ALERT_SLIDING_TALKER),
00484 (entry->flags & ALERT_FIXED_SCANNER),
00485 (entry->flags & ALERT_SLIDING_SCANNER));
00486
00487 flowps_score_print(&entry->fixed_talker);
00488
00489 flow_printf("\n| Position: %s\n", c_position);
00490 flow_printf("| Fixed Talker:");
00491 flowps_score_print(&entry->fixed_talker);
00492
00493 flow_printf("\n| Sliding Talker:");
00494 flowps_score_print(&entry->sliding_talker);
00495
00496 flow_printf("\n| Fixed Scanner:");
00497 flowps_score_print(&entry->fixed_scanner);
00498
00499 flow_printf("\n| Sliding Scanner:");
00500 flowps_score_print(&entry->sliding_scanner);
00501
00502 flow_printf("\n| Connections Seen: %u", entry->connections_seen);
00503
00504
00505 for(i=0; i < entry->connections_seen && i < FLOWPS_HOSTS_SIZE; i++)
00506 {
00507 CONN_ENTRY *cp = &entry->last_hosts[i];
00508 if(cp->protocol == 6)
00509 {
00510 flow_printf("\n| proto: %d %s:%d th_flags: %s",
00511 cp->protocol,
00512 inet_ntoa(*(struct in_addr*) &cp->ip),
00513 cp->port,
00514 mktcpflag_str(cp->cflags));
00515 }
00516 else
00517 {
00518 flow_printf("\n| proto: %d %s:%d cflags: %d",
00519 cp->protocol,
00520 inet_ntoa(*(struct in_addr*) &cp->ip),
00521 cp->port,
00522 cp->cflags);
00523
00524 }
00525 }
00526 flow_printf("\n`----------------------------------------------------\n");
00527
00528 return 0;
00529 }
00530
00531 void flowps_stats(PS_TRACKER *pstp)
00532 {
00533 int dumpall = pstp->config.dumpall;
00534
00535 flow_printf("+---[ Flow-portscan Stats ]----------------+\n");
00536 scoreboard_stats(&pstp->table_active, dumpall);
00537 scoreboard_stats(&pstp->table_scanner, dumpall);
00538 ut_stats(&pstp->unique_tracker, dumpall);
00539 server_stats(&pstp->server_stats, dumpall);
00540 }
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563 static INLINE void flowps_tcp_penalty(u_int32_t flags, int base_score, int *score)
00564 {
00565 if((flags == TH_SYN) || (flags == (TH_SYN|TH_RES1|TH_RES2)))
00566 {
00567
00568 *score = base_score;
00569 }
00570 else if((flags & (TH_SYN|TH_FIN|TH_ACK)) == (TH_SYN|TH_FIN|TH_ACK))
00571 {
00572 *score = 5;
00573 }
00574 else if((flags & (TH_SYN|TH_FIN)) == (TH_SYN|TH_FIN))
00575 {
00576 *score = 3;
00577 }
00578 else
00579 {
00580 *score = 2;
00581 }
00582 }
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600 int flowps_get_score(PS_TRACKER *pstp, FLOW *flowp,
00601 time_t cur, u_int32_t flags,
00602 int *score, TRACKER_POSITION *type)
00603 {
00604 UT_TYPE unique;
00605 u_int32_t hitcount = 1;
00606 int base_score;
00607
00608
00609 if(!flowp || !score || !type)
00610 {
00611 return FLOW_ENULL;
00612 }
00613
00614
00615 base_score = pstp->config.base_score;
00616 *score = pstp->config.base_score;
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626 if(ut_check(&pstp->unique_tracker, &flowp->key, &unique) != FLOW_SUCCESS)
00627 {
00628 #ifndef WIN32
00629 flow_printf("ut check failed in %s\n", __func__);
00630 #else
00631 flow_printf("ut check failed in %s(%d)\n", __FILE__, __LINE__);
00632 #endif
00633 return 0;
00634 }
00635
00636
00637 if(unique == UT_OLD)
00638 {
00639
00640
00641
00642
00643 *score = 0;
00644 return FLOW_SUCCESS;
00645 }
00646 else
00647 {
00648 if(flowps_server_watch(pstp,flowp->key.resp_address) == FLOW_SUCCESS)
00649 {
00650
00651 if(cur < (packet_first_time() + pstp->config.server_learning_time))
00652 {
00653 if(server_stats_add_ipv4(&pstp->server_stats,
00654 flowp->key.protocol,
00655 flowp->key.resp_address,
00656 flowp->key.resp_port,
00657 &hitcount) != FLOW_SUCCESS)
00658 {
00659 #ifdef DEBUG
00660 flow_printf("Unable to add ipv4 to server stats!\n");
00661 #endif
00662 }
00663
00664 }
00665 else
00666 {
00667 hitcount = server_stats_hitcount_ipv4(&pstp->server_stats,
00668 flowp->key.protocol,
00669 flowp->key.resp_address,
00670 flowp->key.resp_port);
00671
00672 if(pstp->config.server_scanner_limit &&
00673 hitcount < pstp->config.server_scanner_limit)
00674 {
00675 *type = TRACKER_SCANNER;
00676 }
00677 }
00678
00679 if(pstp->config.server_ignore_limit > 0 &&
00680 hitcount > pstp->config.server_ignore_limit)
00681 {
00682
00683
00684
00685 if(s_debug > 5)
00686 {
00687 flow_printf("Happy Server hitcount: %d proto: %d %s:%d\n",
00688 hitcount,
00689 flowp->key.protocol,
00690 inet_ntoa(*(struct in_addr *) &flowp->key.resp_address),
00691 flowp->key.resp_port);
00692 }
00693
00694 base_score = 0;
00695 }
00696
00697 }
00698 else
00699 {
00700 hitcount = 1;
00701 }
00702 }
00703
00704
00705
00706
00707 if(pstp->config.tcp_penalties && flowp->key.protocol == 6)
00708 {
00709 flowps_tcp_penalty(flags, base_score, score);
00710 }
00711 else
00712 {
00713 *score = base_score;
00714 }
00715
00716
00717 return FLOW_SUCCESS;
00718 }
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729 int flowps_fixed_winadj(PS_SCORE *pscp, time_t current_time,
00730 SCORE_THRESHOLD *threshold)
00731 {
00732 int window_size = threshold->fixed_size;
00733
00734 if(pscp->ends <= current_time)
00735 {
00736 pscp->start = current_time;
00737 pscp->score = 0;
00738 pscp->ends = current_time + window_size;
00739 }
00740
00741 return FLOW_SUCCESS;
00742 }
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756 int flowps_sliding_winadj(PS_SCORE *pscp, time_t current_time,
00757 SCORE_THRESHOLD *threshold)
00758 {
00759 int diff_SE;
00760 int diff_EN;
00761 int window_size = threshold->sliding_size;
00762 int adjustment;
00763 float scale = threshold->window_scale;
00764
00765 if(pscp->ends > current_time)
00766 {
00767
00768
00769
00770
00771 return FLOW_SUCCESS;
00772 }
00773
00774
00775 pscp->score = 0;
00776
00777 if(pscp->ends == 0)
00778 {
00779
00780 pscp->start = current_time;
00781 pscp->ends = current_time + window_size;
00782 }
00783 else
00784 {
00785 diff_SE = pscp->ends - pscp->start;
00786
00787
00788 diff_EN = current_time - pscp->ends;
00789
00790 if(diff_EN > (diff_SE * 2))
00791 {
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801 pscp->start = current_time;
00802 pscp->ends = current_time + window_size;
00803 }
00804 else
00805 {
00806 pscp->start = current_time;
00807 adjustment = diff_SE + (diff_SE * scale);
00808
00809 if((adjustment + pscp->ends) > pscp->ends)
00810 {
00811 pscp->ends += adjustment;
00812 }
00813 else
00814 {
00815
00816
00817
00818
00819
00820
00821 pscp->ends += window_size;
00822
00823 }
00824 }
00825 }
00826
00827 return FLOW_SUCCESS;
00828 }
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839 int flowps_set_last_address(SCORE_ENTRY *sep, FLOW *flowp, u_int8_t cflags)
00840 {
00841 CONN_ENTRY *conn_entry;
00842
00843 if(sep && flowp)
00844 {
00845 if(sep->last_idx >= FLOWPS_HOSTS_SIZE)
00846 {
00847 sep->last_idx = 0;
00848 }
00849
00850
00851 conn_entry = &sep->last_hosts[sep->last_idx++];
00852
00853
00854 conn_entry->port = flowp->key.resp_port;
00855 conn_entry->ip = flowp->key.resp_address;
00856 conn_entry->protocol = flowp->key.protocol;
00857 conn_entry->cflags = cflags;
00858
00859 sep->connections_seen++;
00860 }
00861
00862 return FLOW_SUCCESS;
00863 }
00864
00865
00866
00867
00868
00869
00870
00871 int flowps_enabled(void)
00872 {
00873 return s_enabled;
00874 }
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889 int flowps_is_ignored_ipv4(PS_TRACKER *pstp, u_int32_t *sip, u_int32_t *dip)
00890 {
00891 u_int32_t host_sip, host_dip;
00892
00893 if(pstp && sip && dip)
00894 {
00895 if(pstp->config.src_ignore_ipv4)
00896 {
00897 host_sip = ntohl(*sip);
00898
00899 if(ipset_contains(pstp->config.src_ignore_ipv4,
00900 &host_sip, IPV4_FAMILY))
00901 {
00902 return FLOW_SUCCESS;
00903 }
00904 }
00905
00906 if(pstp->config.dst_ignore_ipv4)
00907 {
00908 host_dip = ntohl(*dip);
00909
00910 if(ipset_contains(pstp->config.dst_ignore_ipv4,
00911 &host_dip, IPV4_FAMILY))
00912 {
00913 return FLOW_SUCCESS;
00914 }
00915 }
00916
00917 return FLOW_DISABLED;
00918 }
00919
00920 return FLOW_ENULL;
00921 }