aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Framework/Servers/HttpServer/GenericHTTPBasicDOSProtector.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Framework/Servers/HttpServer/GenericHTTPBasicDOSProtector.cs')
-rw-r--r--OpenSim/Framework/Servers/HttpServer/GenericHTTPBasicDOSProtector.cs143
1 files changed, 8 insertions, 135 deletions
diff --git a/OpenSim/Framework/Servers/HttpServer/GenericHTTPBasicDOSProtector.cs b/OpenSim/Framework/Servers/HttpServer/GenericHTTPBasicDOSProtector.cs
index 5fc999a..39c98b4 100644
--- a/OpenSim/Framework/Servers/HttpServer/GenericHTTPBasicDOSProtector.cs
+++ b/OpenSim/Framework/Servers/HttpServer/GenericHTTPBasicDOSProtector.cs
@@ -25,13 +25,7 @@
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28using System;
29using System.Collections; 28using System.Collections;
30using System.Collections.Generic;
31using System.Reflection;
32using System.Net;
33using OpenSim.Framework;
34using log4net;
35 29
36namespace OpenSim.Framework.Servers.HttpServer 30namespace OpenSim.Framework.Servers.HttpServer
37{ 31{
@@ -39,147 +33,26 @@ namespace OpenSim.Framework.Servers.HttpServer
39 { 33 {
40 private readonly GenericHTTPMethod _normalMethod; 34 private readonly GenericHTTPMethod _normalMethod;
41 private readonly GenericHTTPMethod _throttledMethod; 35 private readonly GenericHTTPMethod _throttledMethod;
42 private readonly CircularBuffer<int> _generalRequestTimes; 36
43 private readonly BasicDosProtectorOptions _options; 37 private readonly BasicDosProtectorOptions _options;
44 private readonly Dictionary<string, CircularBuffer<int>> _deeperInspection; 38 private readonly BasicDOSProtector _dosProtector;
45 private readonly Dictionary<string, int> _tempBlocked;
46 private readonly System.Timers.Timer _forgetTimer;
47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48 private readonly System.Threading.ReaderWriterLockSlim _lockSlim = new System.Threading.ReaderWriterLockSlim();
49 39
50 public GenericHTTPDOSProtector(GenericHTTPMethod normalMethod, GenericHTTPMethod throttledMethod, BasicDosProtectorOptions options) 40 public GenericHTTPDOSProtector(GenericHTTPMethod normalMethod, GenericHTTPMethod throttledMethod, BasicDosProtectorOptions options)
51 { 41 {
52 _normalMethod = normalMethod; 42 _normalMethod = normalMethod;
53 _throttledMethod = throttledMethod; 43 _throttledMethod = throttledMethod;
54 _generalRequestTimes = new CircularBuffer<int>(options.MaxRequestsInTimeframe + 1, true); 44
55 _generalRequestTimes.Put(0);
56 _options = options; 45 _options = options;
57 _deeperInspection = new Dictionary<string, CircularBuffer<int>>(); 46 _dosProtector = new BasicDOSProtector(_options);
58 _tempBlocked = new Dictionary<string, int>();
59 _forgetTimer = new System.Timers.Timer();
60 _forgetTimer.Elapsed += delegate
61 {
62 _forgetTimer.Enabled = false;
63
64 List<string> removes = new List<string>();
65 _lockSlim.EnterReadLock();
66 foreach (string str in _tempBlocked.Keys)
67 {
68 if (
69 Util.EnvironmentTickCountSubtract(Util.EnvironmentTickCount(),
70 _tempBlocked[str]) > 0)
71 removes.Add(str);
72 }
73 _lockSlim.ExitReadLock();
74 lock (_deeperInspection)
75 {
76 _lockSlim.EnterWriteLock();
77 for (int i = 0; i < removes.Count; i++)
78 {
79 _tempBlocked.Remove(removes[i]);
80 _deeperInspection.Remove(removes[i]);
81 }
82 _lockSlim.ExitWriteLock();
83 }
84 foreach (string str in removes)
85 {
86 m_log.InfoFormat("[{0}] client: {1} is no longer blocked.",
87 _options.ReportingName, str);
88 }
89 _lockSlim.EnterReadLock();
90 if (_tempBlocked.Count > 0)
91 _forgetTimer.Enabled = true;
92 _lockSlim.ExitReadLock();
93 };
94
95 _forgetTimer.Interval = _options.ForgetTimeSpan.TotalMilliseconds;
96 } 47 }
97 public Hashtable Process(Hashtable request) 48 public Hashtable Process(Hashtable request)
98 { 49 {
99 if (_options.MaxRequestsInTimeframe < 1) 50 if (_dosProtector.Process(GetClientString(request), GetRemoteAddr(request)))
100 return _normalMethod(request); 51 return _normalMethod(request);
101 if (_options.RequestTimeSpan.TotalMilliseconds < 1) 52 else
102 return _normalMethod(request); 53 return _throttledMethod(request);
103
104 string clientstring = GetClientString(request);
105
106 _lockSlim.EnterReadLock();
107 if (_tempBlocked.ContainsKey(clientstring))
108 {
109 _lockSlim.ExitReadLock();
110
111 if (_options.ThrottledAction == ThrottleAction.DoThrottledMethod)
112 return _throttledMethod(request);
113 else
114 throw new System.Security.SecurityException("Throttled");
115 }
116 _lockSlim.ExitReadLock();
117
118 _generalRequestTimes.Put(Util.EnvironmentTickCount());
119
120 if (_generalRequestTimes.Size == _generalRequestTimes.Capacity &&
121 (Util.EnvironmentTickCountSubtract(Util.EnvironmentTickCount(), _generalRequestTimes.Get()) <
122 _options.RequestTimeSpan.TotalMilliseconds))
123 {
124 //Trigger deeper inspection
125 if (DeeperInspection(request))
126 return _normalMethod(request);
127 if (_options.ThrottledAction == ThrottleAction.DoThrottledMethod)
128 return _throttledMethod(request);
129 else
130 throw new System.Security.SecurityException("Throttled");
131 }
132 Hashtable resp = null;
133 try
134 {
135 resp = _normalMethod(request);
136 }
137 catch (Exception)
138 {
139
140 throw;
141 }
142
143 return resp;
144 }
145 private bool DeeperInspection(Hashtable request)
146 {
147 lock (_deeperInspection)
148 {
149 string clientstring = GetClientString(request);
150
151
152 if (_deeperInspection.ContainsKey(clientstring))
153 {
154 _deeperInspection[clientstring].Put(Util.EnvironmentTickCount());
155 if (_deeperInspection[clientstring].Size == _deeperInspection[clientstring].Capacity &&
156 (Util.EnvironmentTickCountSubtract(Util.EnvironmentTickCount(), _deeperInspection[clientstring].Get()) <
157 _options.RequestTimeSpan.TotalMilliseconds))
158 {
159 _lockSlim.EnterWriteLock();
160 if (!_tempBlocked.ContainsKey(clientstring))
161 _tempBlocked.Add(clientstring, Util.EnvironmentTickCount() + (int)_options.ForgetTimeSpan.TotalMilliseconds);
162 else
163 _tempBlocked[clientstring] = Util.EnvironmentTickCount() + (int)_options.ForgetTimeSpan.TotalMilliseconds;
164 _lockSlim.ExitWriteLock();
165
166 m_log.WarnFormat("[{0}]: client: {1} is blocked for {2} milliseconds, X-ForwardedForAllowed status is {3}, endpoint:{4}", _options.ReportingName, clientstring, _options.ForgetTimeSpan.TotalMilliseconds, _options.AllowXForwardedFor, GetRemoteAddr(request));
167 return false;
168 }
169 //else
170 // return true;
171 }
172 else
173 {
174 _deeperInspection.Add(clientstring, new CircularBuffer<int>(_options.MaxRequestsInTimeframe + 1, true));
175 _deeperInspection[clientstring].Put(Util.EnvironmentTickCount());
176 _forgetTimer.Enabled = true;
177 }
178
179 }
180 return true;
181 } 54 }
182 55
183 private string GetRemoteAddr(Hashtable request) 56 private string GetRemoteAddr(Hashtable request)
184 { 57 {
185 string remoteaddr = ""; 58 string remoteaddr = "";