comparison src/syslogconfig.cpp @ 58:b45dddebe8fc

Add exponential increase in penalty for repeat offenders
author Carl Byington <carl@five-ten-sg.com>
date Tue, 10 Jun 2014 08:48:53 -0700
parents 206448c00b55
children f133196b8591
comparison
equal deleted inserted replaced
57:c95acc20f7ed 58:b45dddebe8fc
30 const char *token_slash; 30 const char *token_slash;
31 const char *token_threshold; 31 const char *token_threshold;
32 string_set all_strings;// owns all the strings, only modified by the config loader thread 32 string_set all_strings;// owns all the strings, only modified by the config loader thread
33 recorder_map recorders; // all the recorders are named 33 recorder_map recorders; // all the recorders are named
34 const int maxlen = 1000; // used for snprintf buffers 34 const int maxlen = 1000; // used for snprintf buffers
35 const int scale_max = 500000;
35 36
36 37
37 //////////////////////////////////////////////// 38 ////////////////////////////////////////////////
38 // 39 //
39 40
40 IPR::IPR() { 41 IPR::IPR() {
41 reference_count = 0; 42 reference_count = 0;
43 daily_timer = 86400;
42 } 44 }
43 45
44 IPR* IPR::find(const char* name) { 46 IPR* IPR::find(const char* name) {
45 recorder_map::iterator m = recorders.find(name); 47 recorder_map::iterator m = recorders.find(name);
46 if (m == recorders.end()) recorders[name] = new IPR; 48 if (m == recorders.end()) recorders[name] = new IPR;
60 } 62 }
61 63
62 64
63 void IPR::add(int ip, int amount, CONTEXT &con, const char *file_name, int pattern_index, const char *message) { 65 void IPR::add(int ip, int amount, CONTEXT &con, const char *file_name, int pattern_index, const char *message) {
64 if (con.looking(ip)) { 66 if (con.looking(ip)) {
67 ip_buckets::iterator j = repeat_offenders.find(ip);
68 int scale = (j == repeat_offenders.end()) ? 1 : (*j).second.count;
69 amount *= scale;
70
65 ip_buckets::iterator i = violations.find(ip); 71 ip_buckets::iterator i = violations.find(ip);
66 if (i == violations.end()) { 72 if (i == violations.end()) {
67 bucket b; 73 bucket b;
68 b.count = amount; 74 b.count = amount;
69 b.latch = (con.get_threshold() <= b.count); 75 b.blocked = (con.get_threshold() <= b.count);
70 violations[ip] = b; 76 violations[ip] = b;
71 if (b.latch) { 77 if (b.blocked) {
72 update(ip, true, file_name, pattern_index, message); 78 update(ip, true, scale, file_name, pattern_index, message);
73 changed(con, ip, true); 79 changed(con, ip, true);
74 } 80 }
75 } 81 }
76 else { 82 else {
77 bucket &b = (*i).second; 83 bucket &b = (*i).second;
78 if (b.count < (INT_MAX-amount)) { 84 if (b.count < (INT_MAX-amount)) {
79 int t = con.get_threshold();
80 int c = b.count;
81 b.count += amount; 85 b.count += amount;
82 if ((!b.latch) && (c < t) && (t <= b.count)) { 86 if ((!b.blocked) && (con.get_threshold() <= b.count)) {
83 b.latch = true; 87 b.blocked = true;
84 update(ip, true, file_name, pattern_index, message); 88 update(ip, true, scale, file_name, pattern_index, message);
85 changed(con, ip, true); 89 changed(con, ip, true);
86 } 90 }
87 } 91 }
88 } 92 }
89 } 93 }
93 void IPR::leak(int amount, CONTEXT &con) { 97 void IPR::leak(int amount, CONTEXT &con) {
94 for (ip_buckets::iterator i=violations.begin(); i!=violations.end(); ) { 98 for (ip_buckets::iterator i=violations.begin(); i!=violations.end(); ) {
95 int ip = (*i).first; 99 int ip = (*i).first;
96 bucket &b = (*i).second; 100 bucket &b = (*i).second;
97 if (b.count <= amount) { 101 if (b.count <= amount) {
98 if (b.latch) { 102 if (b.blocked) {
99 update(ip, false, NULL, 0, NULL); 103 update(ip, false, 0, NULL, 0, NULL);
100 changed(con, ip, false); 104 changed(con, ip, false);
101 } 105 }
102 violations.erase(i++); 106 violations.erase(i++);
103 } 107 }
104 else { 108 else {
105 b.count -= amount; 109 b.count -= amount;
106 i++; 110 i++;
107 } 111 }
108 } 112 }
113 daily_timer -= amount;
114 if (daily_timer < 0) {
115 daily_timer = 86400;
116 for (ip_buckets::iterator j=repeat_offenders.begin(); j!=repeat_offenders.end(); ) {
117 int ip = (*j).first;
118 bucket &b = (*j).second;
119 b.count = b.count * 2 / 3;
120 if (b.count <= 2) {
121 repeat_offenders.erase(j++);
122 char buf[maxlen];
123 in_addr ad;
124 ad.s_addr = htonl(ip);
125 snprintf(buf, maxlen, "removing %s from repeat offenders", inet_ntoa(ad));
126 my_syslog(buf);
127 }
128 else {
129 j++;
130 }
131 }
132 }
109 } 133 }
110 134
111 135
112 void IPR::free_all(CONTEXT &con) { 136 void IPR::free_all(CONTEXT &con) {
113 if (debug_syslog > 2) { 137 if (debug_syslog > 2) {
114 my_syslog("syslog2iptables shutting down"); 138 my_syslog("syslog2iptables shutting down");
115 } 139 }
116 for (ip_buckets::iterator i=violations.begin(); i!=violations.end(); i++) { 140 for (ip_buckets::iterator i=violations.begin(); i!=violations.end(); i++) {
117 int ip = (*i).first; 141 int ip = (*i).first;
118 bucket &b = (*i).second; 142 bucket &b = (*i).second;
119 if (b.latch) { 143 if (b.blocked) {
120 update(ip, false, NULL, 0, NULL); 144 update(ip, false, 0, NULL, 0, NULL);
121 changed(con, ip, false); 145 changed(con, ip, false);
122 } 146 }
123 } 147 }
124 violations.clear(); 148 violations.clear();
125 } 149 }
126 150
127 151
128 void IPR::update(int ip, bool added, const char *file_name, int pattern_index, const char *message) { 152 void IPR::update(int ip, bool added, int scale, const char *file_name, int pattern_index, const char *message) {
129 if (debug_syslog > 2) { 153 if (debug_syslog > 2) {
130 char buf[maxlen]; 154 char buf[maxlen];
131 in_addr ad; 155 in_addr ad;
132 ad.s_addr = htonl(ip); 156 ad.s_addr = htonl(ip);
133 if (added) { 157 if (added) {
134 if (message) snprintf(buf, maxlen, "dropping traffic from/to %s based on %s in %s", inet_ntoa(ad), message, file_name); 158 if (message) snprintf(buf, maxlen, "dropping traffic from/to %s based on %s in %s, scale %d", inet_ntoa(ad), message, file_name, scale);
135 else snprintf(buf, maxlen, "dropping traffic from/to %s based on pattern match %d in %s", inet_ntoa(ad), pattern_index, file_name); 159 else snprintf(buf, maxlen, "dropping traffic from/to %s based on pattern match %d in %s", inet_ntoa(ad), pattern_index, file_name);
136 } 160 ip_buckets::iterator j = repeat_offenders.find(ip);
137 else snprintf(buf, maxlen, "allowing traffic from/to %s", inet_ntoa(ad)); 161 if (j == repeat_offenders.end()) {
162 bucket b;
163 b.count = 2;
164 b.blocked = true; // unused
165 repeat_offenders[ip] = b;
166 }
167 else {
168 bucket &b = (*j).second;
169 if (b.count < scale_max) b.count = b.count * 3 / 2;
170 }
171 }
172 else snprintf(buf, maxlen, "allowing traffic from/to %s", inet_ntoa(ad));
138 my_syslog(buf); 173 my_syslog(buf);
139 } 174 }
140 } 175 }
141 176
142 177