Mercurial > syslog2iptables
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 |