aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Framework/Servers/HttpServer/BaseStreamHandlerBasicDOSProtector.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Framework/Servers/HttpServer/BaseStreamHandlerBasicDOSProtector.cs')
-rw-r--r--OpenSim/Framework/Servers/HttpServer/BaseStreamHandlerBasicDOSProtector.cs144
1 files changed, 8 insertions, 136 deletions
diff --git a/OpenSim/Framework/Servers/HttpServer/BaseStreamHandlerBasicDOSProtector.cs b/OpenSim/Framework/Servers/HttpServer/BaseStreamHandlerBasicDOSProtector.cs
index 8fc9a8a..9b8b8c2 100644
--- a/OpenSim/Framework/Servers/HttpServer/BaseStreamHandlerBasicDOSProtector.cs
+++ b/OpenSim/Framework/Servers/HttpServer/BaseStreamHandlerBasicDOSProtector.cs
@@ -25,10 +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 */
27using OpenSim.Framework; 27using OpenSim.Framework;
28using System.Collections.Generic;
29using System.IO; 28using System.IO;
30using System.Reflection;
31using log4net;
32 29
33namespace OpenSim.Framework.Servers.HttpServer 30namespace OpenSim.Framework.Servers.HttpServer
34{ 31{
@@ -40,61 +37,17 @@ namespace OpenSim.Framework.Servers.HttpServer
40 /// </remarks> 37 /// </remarks>
41 public abstract class BaseStreamHandlerBasicDOSProtector : BaseRequestHandler, IStreamedRequestHandler 38 public abstract class BaseStreamHandlerBasicDOSProtector : BaseRequestHandler, IStreamedRequestHandler
42 { 39 {
43 private readonly CircularBuffer<int> _generalRequestTimes; 40
44 private readonly BasicDosProtectorOptions _options; 41 private readonly BasicDosProtectorOptions _options;
45 private readonly Dictionary<string, CircularBuffer<int>> _deeperInspection; 42 private readonly BasicDOSProtector _dosProtector;
46 private readonly Dictionary<string, int> _tempBlocked;
47 private readonly System.Timers.Timer _forgetTimer;
48 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
49 private readonly System.Threading.ReaderWriterLockSlim _lockSlim = new System.Threading.ReaderWriterLockSlim();
50 43
51 protected BaseStreamHandlerBasicDOSProtector(string httpMethod, string path, BasicDosProtectorOptions options) : this(httpMethod, path, null, null, options) {} 44 protected BaseStreamHandlerBasicDOSProtector(string httpMethod, string path, BasicDosProtectorOptions options) : this(httpMethod, path, null, null, options) {}
52 45
53 protected BaseStreamHandlerBasicDOSProtector(string httpMethod, string path, string name, string description, BasicDosProtectorOptions options) 46 protected BaseStreamHandlerBasicDOSProtector(string httpMethod, string path, string name, string description, BasicDosProtectorOptions options)
54 : base(httpMethod, path, name, description) 47 : base(httpMethod, path, name, description)
55 { 48 {
56 _generalRequestTimes = new CircularBuffer<int>(options.MaxRequestsInTimeframe + 1, true);
57 _generalRequestTimes.Put(0);
58 _options = options; 49 _options = options;
59 _deeperInspection = new Dictionary<string, CircularBuffer<int>>(); 50 _dosProtector = new BasicDOSProtector(_options);
60 _tempBlocked = new Dictionary<string, int>();
61 _forgetTimer = new System.Timers.Timer();
62 _forgetTimer.Elapsed += delegate
63 {
64 _forgetTimer.Enabled = false;
65
66 List<string> removes = new List<string>();
67 _lockSlim.EnterReadLock();
68 foreach (string str in _tempBlocked.Keys)
69 {
70 if (
71 Util.EnvironmentTickCountSubtract(Util.EnvironmentTickCount(),
72 _tempBlocked[str]) > 0)
73 removes.Add(str);
74 }
75 _lockSlim.ExitReadLock();
76 lock (_deeperInspection)
77 {
78 _lockSlim.EnterWriteLock();
79 for (int i = 0; i < removes.Count; i++)
80 {
81 _tempBlocked.Remove(removes[i]);
82 _deeperInspection.Remove(removes[i]);
83 }
84 _lockSlim.ExitWriteLock();
85 }
86 foreach (string str in removes)
87 {
88 m_log.InfoFormat("[{0}] client: {1} is no longer blocked.",
89 _options.ReportingName, str);
90 }
91 _lockSlim.EnterReadLock();
92 if (_tempBlocked.Count > 0)
93 _forgetTimer.Enabled = true;
94 _lockSlim.ExitReadLock();
95 };
96
97 _forgetTimer.Interval = _options.ForgetTimeSpan.TotalMilliseconds;
98 } 51 }
99 52
100 public virtual byte[] Handle( 53 public virtual byte[] Handle(
@@ -102,58 +55,13 @@ namespace OpenSim.Framework.Servers.HttpServer
102 { 55 {
103 byte[] result; 56 byte[] result;
104 RequestsReceived++; 57 RequestsReceived++;
105 //httpRequest.Headers
106 58
107 if (_options.MaxRequestsInTimeframe < 1 || _options.RequestTimeSpan.TotalMilliseconds < 1) 59 if (_dosProtector.Process(GetClientString(httpRequest), GetRemoteAddr(httpRequest)))
108 {
109 result = ProcessRequest(path, request, httpRequest, httpResponse); 60 result = ProcessRequest(path, request, httpRequest, httpResponse);
110 RequestsHandled++; 61 else
111 return result; 62 result = ThrottledRequest(path, request, httpRequest, httpResponse);
112
113 }
114
115 string clientstring = GetClientString(httpRequest);
116
117 _lockSlim.EnterReadLock();
118 if (_tempBlocked.ContainsKey(clientstring))
119 {
120 _lockSlim.ExitReadLock();
121
122 if (_options.ThrottledAction == ThrottleAction.DoThrottledMethod)
123 {
124 result = ThrottledRequest(path, request, httpRequest, httpResponse);
125 RequestsHandled++;
126 return result;
127 }
128 else
129 throw new System.Security.SecurityException("Throttled");
130 }
131 _lockSlim.ExitReadLock();
132
133 _generalRequestTimes.Put(Util.EnvironmentTickCount());
134 63
135 if (_generalRequestTimes.Size == _generalRequestTimes.Capacity && 64
136 (Util.EnvironmentTickCountSubtract(Util.EnvironmentTickCount(), _generalRequestTimes.Get()) <
137 _options.RequestTimeSpan.TotalMilliseconds))
138 {
139 //Trigger deeper inspection
140 if (DeeperInspection(httpRequest))
141 {
142 result = ProcessRequest(path, request, httpRequest, httpResponse);
143 RequestsHandled++;
144 return result;
145 }
146 if (_options.ThrottledAction == ThrottleAction.DoThrottledMethod)
147 {
148 result = ThrottledRequest(path, request, httpRequest, httpResponse);
149 RequestsHandled++;
150 return result;
151 }
152 else
153 throw new System.Security.SecurityException("Throttled");
154 }
155
156 result =ProcessRequest(path, request, httpRequest, httpResponse);
157 RequestsHandled++; 65 RequestsHandled++;
158 66
159 return result; 67 return result;
@@ -171,43 +79,7 @@ namespace OpenSim.Framework.Servers.HttpServer
171 return new byte[0]; 79 return new byte[0];
172 } 80 }
173 81
174 private bool DeeperInspection(IOSHttpRequest httpRequest) 82
175 {
176 lock (_deeperInspection)
177 {
178 string clientstring = GetClientString(httpRequest);
179
180
181 if (_deeperInspection.ContainsKey(clientstring))
182 {
183 _deeperInspection[clientstring].Put(Util.EnvironmentTickCount());
184 if (_deeperInspection[clientstring].Size == _deeperInspection[clientstring].Capacity &&
185 (Util.EnvironmentTickCountSubtract(Util.EnvironmentTickCount(), _deeperInspection[clientstring].Get()) <
186 _options.RequestTimeSpan.TotalMilliseconds))
187 {
188 _lockSlim.EnterWriteLock();
189 if (!_tempBlocked.ContainsKey(clientstring))
190 _tempBlocked.Add(clientstring, Util.EnvironmentTickCount() + (int)_options.ForgetTimeSpan.TotalMilliseconds);
191 else
192 _tempBlocked[clientstring] = Util.EnvironmentTickCount() + (int)_options.ForgetTimeSpan.TotalMilliseconds;
193 _lockSlim.ExitWriteLock();
194
195 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(httpRequest));
196 return false;
197 }
198 //else
199 // return true;
200 }
201 else
202 {
203 _deeperInspection.Add(clientstring, new CircularBuffer<int>(_options.MaxRequestsInTimeframe + 1, true));
204 _deeperInspection[clientstring].Put(Util.EnvironmentTickCount());
205 _forgetTimer.Enabled = true;
206 }
207
208 }
209 return true;
210 }
211 private string GetRemoteAddr(IOSHttpRequest httpRequest) 83 private string GetRemoteAddr(IOSHttpRequest httpRequest)
212 { 84 {
213 string remoteaddr = string.Empty; 85 string remoteaddr = string.Empty;