* Refactor
* Break out common BasicDOSProtector code into separate class.link-sitting
							parent
							
								
									f76cc6036e
								
							
						
					
					
						commit
						75fdd6054d
					
				|  | @ -25,10 +25,7 @@ | ||||||
|  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  */ |  */ | ||||||
| using OpenSim.Framework; | using OpenSim.Framework; | ||||||
| using System.Collections.Generic; |  | ||||||
| using System.IO; | using System.IO; | ||||||
| using System.Reflection; |  | ||||||
| using log4net; |  | ||||||
| 
 | 
 | ||||||
| namespace OpenSim.Framework.Servers.HttpServer | namespace OpenSim.Framework.Servers.HttpServer | ||||||
| { | { | ||||||
|  | @ -40,61 +37,17 @@ namespace OpenSim.Framework.Servers.HttpServer | ||||||
|     /// </remarks> |     /// </remarks> | ||||||
|     public abstract class BaseStreamHandlerBasicDOSProtector : BaseRequestHandler, IStreamedRequestHandler |     public abstract class BaseStreamHandlerBasicDOSProtector : BaseRequestHandler, IStreamedRequestHandler | ||||||
|     { |     { | ||||||
|         private readonly CircularBuffer<int> _generalRequestTimes; |         | ||||||
|         private readonly BasicDosProtectorOptions _options; |         private readonly BasicDosProtectorOptions _options; | ||||||
|         private readonly Dictionary<string, CircularBuffer<int>> _deeperInspection; |         private readonly BasicDOSProtector _dosProtector; | ||||||
|         private readonly Dictionary<string, int> _tempBlocked; |  | ||||||
|         private readonly System.Timers.Timer _forgetTimer; |  | ||||||
|         private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |  | ||||||
|         private readonly System.Threading.ReaderWriterLockSlim _lockSlim = new System.Threading.ReaderWriterLockSlim(); |  | ||||||
| 
 | 
 | ||||||
|         protected BaseStreamHandlerBasicDOSProtector(string httpMethod, string path, BasicDosProtectorOptions options) : this(httpMethod, path, null, null, options) {} |         protected BaseStreamHandlerBasicDOSProtector(string httpMethod, string path, BasicDosProtectorOptions options) : this(httpMethod, path, null, null, options) {} | ||||||
| 
 | 
 | ||||||
|         protected BaseStreamHandlerBasicDOSProtector(string httpMethod, string path, string name, string description, BasicDosProtectorOptions options) |         protected BaseStreamHandlerBasicDOSProtector(string httpMethod, string path, string name, string description, BasicDosProtectorOptions options) | ||||||
|             : base(httpMethod, path, name, description) |             : base(httpMethod, path, name, description) | ||||||
|         { |         { | ||||||
|             _generalRequestTimes = new CircularBuffer<int>(options.MaxRequestsInTimeframe + 1, true); |  | ||||||
|             _generalRequestTimes.Put(0); |  | ||||||
|             _options = options; |             _options = options; | ||||||
|             _deeperInspection = new Dictionary<string, CircularBuffer<int>>(); |             _dosProtector = new BasicDOSProtector(_options); | ||||||
|             _tempBlocked = new Dictionary<string, int>(); |  | ||||||
|             _forgetTimer = new System.Timers.Timer(); |  | ||||||
|             _forgetTimer.Elapsed += delegate |  | ||||||
|             { |  | ||||||
|                 _forgetTimer.Enabled = false; |  | ||||||
| 
 |  | ||||||
|                 List<string> removes = new List<string>(); |  | ||||||
|                 _lockSlim.EnterReadLock(); |  | ||||||
|                 foreach (string str in _tempBlocked.Keys) |  | ||||||
|                 { |  | ||||||
|                     if ( |  | ||||||
|                         Util.EnvironmentTickCountSubtract(Util.EnvironmentTickCount(), |  | ||||||
|                                                           _tempBlocked[str]) > 0) |  | ||||||
|                         removes.Add(str); |  | ||||||
|                 } |  | ||||||
|                 _lockSlim.ExitReadLock(); |  | ||||||
|                 lock (_deeperInspection) |  | ||||||
|                 { |  | ||||||
|                     _lockSlim.EnterWriteLock(); |  | ||||||
|                     for (int i = 0; i < removes.Count; i++) |  | ||||||
|                     { |  | ||||||
|                         _tempBlocked.Remove(removes[i]); |  | ||||||
|                         _deeperInspection.Remove(removes[i]); |  | ||||||
|                     } |  | ||||||
|                     _lockSlim.ExitWriteLock(); |  | ||||||
|                 } |  | ||||||
|                 foreach (string str in removes) |  | ||||||
|                 { |  | ||||||
|                     m_log.InfoFormat("[{0}] client: {1} is no longer blocked.", |  | ||||||
|                                      _options.ReportingName, str); |  | ||||||
|                 } |  | ||||||
|                 _lockSlim.EnterReadLock(); |  | ||||||
|                 if (_tempBlocked.Count > 0) |  | ||||||
|                     _forgetTimer.Enabled = true; |  | ||||||
|                 _lockSlim.ExitReadLock(); |  | ||||||
|             }; |  | ||||||
| 
 |  | ||||||
|             _forgetTimer.Interval = _options.ForgetTimeSpan.TotalMilliseconds; |  | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         public virtual byte[] Handle( |         public virtual byte[] Handle( | ||||||
|  | @ -102,58 +55,13 @@ namespace OpenSim.Framework.Servers.HttpServer | ||||||
|         { |         { | ||||||
|             byte[] result; |             byte[] result; | ||||||
|             RequestsReceived++; |             RequestsReceived++; | ||||||
|             //httpRequest.Headers |  | ||||||
| 
 | 
 | ||||||
|             if (_options.MaxRequestsInTimeframe < 1 || _options.RequestTimeSpan.TotalMilliseconds < 1) |             if (_dosProtector.Process(GetClientString(httpRequest), GetRemoteAddr(httpRequest))) | ||||||
|             { |  | ||||||
|                 result = ProcessRequest(path, request, httpRequest, httpResponse); |                 result = ProcessRequest(path, request, httpRequest, httpResponse); | ||||||
|                 RequestsHandled++; |  | ||||||
|                 return result; |  | ||||||
|                  |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             string clientstring = GetClientString(httpRequest); |  | ||||||
| 
 |  | ||||||
|             _lockSlim.EnterReadLock(); |  | ||||||
|             if (_tempBlocked.ContainsKey(clientstring)) |  | ||||||
|             { |  | ||||||
|                 _lockSlim.ExitReadLock(); |  | ||||||
| 
 |  | ||||||
|                 if (_options.ThrottledAction == ThrottleAction.DoThrottledMethod) |  | ||||||
|                 { |  | ||||||
|                     result = ThrottledRequest(path, request, httpRequest, httpResponse); |  | ||||||
|                     RequestsHandled++; |  | ||||||
|                     return result; |  | ||||||
|                 } |  | ||||||
|             else |             else | ||||||
|                     throw new System.Security.SecurityException("Throttled"); |  | ||||||
|             } |  | ||||||
|             _lockSlim.ExitReadLock(); |  | ||||||
| 
 |  | ||||||
|             _generalRequestTimes.Put(Util.EnvironmentTickCount()); |  | ||||||
| 
 |  | ||||||
|             if (_generalRequestTimes.Size == _generalRequestTimes.Capacity && |  | ||||||
|                 (Util.EnvironmentTickCountSubtract(Util.EnvironmentTickCount(), _generalRequestTimes.Get()) < |  | ||||||
|                  _options.RequestTimeSpan.TotalMilliseconds)) |  | ||||||
|             { |  | ||||||
|                 //Trigger deeper inspection |  | ||||||
|                 if (DeeperInspection(httpRequest)) |  | ||||||
|                 { |  | ||||||
|                     result = ProcessRequest(path, request, httpRequest, httpResponse); |  | ||||||
|                     RequestsHandled++; |  | ||||||
|                     return result; |  | ||||||
|                 } |  | ||||||
|                 if (_options.ThrottledAction == ThrottleAction.DoThrottledMethod) |  | ||||||
|                 { |  | ||||||
|                 result = ThrottledRequest(path, request, httpRequest, httpResponse); |                 result = ThrottledRequest(path, request, httpRequest, httpResponse); | ||||||
|                     RequestsHandled++; |  | ||||||
|                     return result; |  | ||||||
|                 } |  | ||||||
|                 else |  | ||||||
|                     throw new System.Security.SecurityException("Throttled"); |  | ||||||
|             } |  | ||||||
| 
 | 
 | ||||||
|             result =ProcessRequest(path, request, httpRequest, httpResponse); |              | ||||||
|             RequestsHandled++; |             RequestsHandled++; | ||||||
| 
 | 
 | ||||||
|             return result; |             return result; | ||||||
|  | @ -171,43 +79,7 @@ namespace OpenSim.Framework.Servers.HttpServer | ||||||
|             return new byte[0]; |             return new byte[0]; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         private bool DeeperInspection(IOSHttpRequest httpRequest) |  | ||||||
|         { |  | ||||||
|             lock (_deeperInspection) |  | ||||||
|             { |  | ||||||
|                 string clientstring = GetClientString(httpRequest); |  | ||||||
|          |          | ||||||
| 
 |  | ||||||
|                 if (_deeperInspection.ContainsKey(clientstring)) |  | ||||||
|                 { |  | ||||||
|                     _deeperInspection[clientstring].Put(Util.EnvironmentTickCount()); |  | ||||||
|                     if (_deeperInspection[clientstring].Size == _deeperInspection[clientstring].Capacity && |  | ||||||
|                         (Util.EnvironmentTickCountSubtract(Util.EnvironmentTickCount(), _deeperInspection[clientstring].Get()) < |  | ||||||
|                          _options.RequestTimeSpan.TotalMilliseconds)) |  | ||||||
|                     { |  | ||||||
|                         _lockSlim.EnterWriteLock(); |  | ||||||
|                         if (!_tempBlocked.ContainsKey(clientstring)) |  | ||||||
|                             _tempBlocked.Add(clientstring, Util.EnvironmentTickCount() + (int)_options.ForgetTimeSpan.TotalMilliseconds); |  | ||||||
|                         else |  | ||||||
|                             _tempBlocked[clientstring] = Util.EnvironmentTickCount() + (int)_options.ForgetTimeSpan.TotalMilliseconds; |  | ||||||
|                         _lockSlim.ExitWriteLock(); |  | ||||||
| 
 |  | ||||||
|                         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)); |  | ||||||
|                         return false; |  | ||||||
|                     } |  | ||||||
|                     //else |  | ||||||
|                     //   return true; |  | ||||||
|                 } |  | ||||||
|                 else |  | ||||||
|                 { |  | ||||||
|                     _deeperInspection.Add(clientstring, new CircularBuffer<int>(_options.MaxRequestsInTimeframe + 1, true)); |  | ||||||
|                     _deeperInspection[clientstring].Put(Util.EnvironmentTickCount()); |  | ||||||
|                     _forgetTimer.Enabled = true; |  | ||||||
|                 } |  | ||||||
| 
 |  | ||||||
|             } |  | ||||||
|             return true; |  | ||||||
|         } |  | ||||||
|         private string GetRemoteAddr(IOSHttpRequest httpRequest) |         private string GetRemoteAddr(IOSHttpRequest httpRequest) | ||||||
|         { |         { | ||||||
|             string remoteaddr = string.Empty; |             string remoteaddr = string.Empty; | ||||||
|  |  | ||||||
|  | @ -0,0 +1,181 @@ | ||||||
|  | /* | ||||||
|  |  * Copyright (c) Contributors, http://opensimulator.org/ | ||||||
|  |  * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions are met: | ||||||
|  |  *     * Redistributions of source code must retain the above copyright | ||||||
|  |  *       notice, this list of conditions and the following disclaimer. | ||||||
|  |  *     * Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *       notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *       documentation and/or other materials provided with the distribution. | ||||||
|  |  *     * Neither the name of the OpenSimulator Project nor the | ||||||
|  |  *       names of its contributors may be used to endorse or promote products | ||||||
|  |  *       derived from this software without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||||||
|  |  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||||||
|  |  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||||
|  |  * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||||||
|  |  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||||||
|  |  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||||||
|  |  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||||||
|  |  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||||
|  |  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||||||
|  |  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  | using System; | ||||||
|  | using System.Collections.Generic; | ||||||
|  | using System.Reflection; | ||||||
|  | using log4net; | ||||||
|  | 
 | ||||||
|  | namespace OpenSim.Framework.Servers.HttpServer | ||||||
|  | { | ||||||
|  |     | ||||||
|  |     public class BasicDOSProtector | ||||||
|  |     { | ||||||
|  |         public enum ThrottleAction | ||||||
|  |         { | ||||||
|  |             DoThrottledMethod, | ||||||
|  |             DoThrow | ||||||
|  |         } | ||||||
|  |         private readonly CircularBuffer<int> _generalRequestTimes; // General request checker | ||||||
|  |         private readonly BasicDosProtectorOptions _options; | ||||||
|  |         private readonly Dictionary<string, CircularBuffer<int>> _deeperInspection;   // per client request checker | ||||||
|  |         private readonly Dictionary<string, int> _tempBlocked;  // blocked list | ||||||
|  |         private readonly System.Timers.Timer _forgetTimer;  // Cleanup timer | ||||||
|  |         private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||||||
|  |         private readonly System.Threading.ReaderWriterLockSlim _lockSlim = new System.Threading.ReaderWriterLockSlim(); | ||||||
|  |         public BasicDOSProtector(BasicDosProtectorOptions options) | ||||||
|  |         { | ||||||
|  |             _generalRequestTimes = new CircularBuffer<int>(options.MaxRequestsInTimeframe + 1, true); | ||||||
|  |             _generalRequestTimes.Put(0); | ||||||
|  |             _options = options; | ||||||
|  |             _deeperInspection = new Dictionary<string, CircularBuffer<int>>(); | ||||||
|  |             _tempBlocked = new Dictionary<string, int>(); | ||||||
|  |             _forgetTimer = new System.Timers.Timer(); | ||||||
|  |             _forgetTimer.Elapsed += delegate | ||||||
|  |             { | ||||||
|  |                 _forgetTimer.Enabled = false; | ||||||
|  | 
 | ||||||
|  |                 List<string> removes = new List<string>(); | ||||||
|  |                 _lockSlim.EnterReadLock(); | ||||||
|  |                 foreach (string str in _tempBlocked.Keys) | ||||||
|  |                 { | ||||||
|  |                     if ( | ||||||
|  |                         Util.EnvironmentTickCountSubtract(Util.EnvironmentTickCount(), | ||||||
|  |                                                           _tempBlocked[str]) > 0) | ||||||
|  |                         removes.Add(str); | ||||||
|  |                 } | ||||||
|  |                 _lockSlim.ExitReadLock(); | ||||||
|  |                 lock (_deeperInspection) | ||||||
|  |                 { | ||||||
|  |                     _lockSlim.EnterWriteLock(); | ||||||
|  |                     for (int i = 0; i < removes.Count; i++) | ||||||
|  |                     { | ||||||
|  |                         _tempBlocked.Remove(removes[i]); | ||||||
|  |                         _deeperInspection.Remove(removes[i]); | ||||||
|  |                     } | ||||||
|  |                     _lockSlim.ExitWriteLock(); | ||||||
|  |                 } | ||||||
|  |                 foreach (string str in removes) | ||||||
|  |                 { | ||||||
|  |                     m_log.InfoFormat("[{0}] client: {1} is no longer blocked.", | ||||||
|  |                                      _options.ReportingName, str); | ||||||
|  |                 } | ||||||
|  |                 _lockSlim.EnterReadLock(); | ||||||
|  |                 if (_tempBlocked.Count > 0) | ||||||
|  |                     _forgetTimer.Enabled = true; | ||||||
|  |                 _lockSlim.ExitReadLock(); | ||||||
|  |             }; | ||||||
|  | 
 | ||||||
|  |             _forgetTimer.Interval = _options.ForgetTimeSpan.TotalMilliseconds; | ||||||
|  |         } | ||||||
|  |         public bool Process(string key, string endpoint) | ||||||
|  |         { | ||||||
|  |             if (_options.MaxRequestsInTimeframe < 1 || _options.RequestTimeSpan.TotalMilliseconds < 1) | ||||||
|  |                 return true; | ||||||
|  | 
 | ||||||
|  |             string clientstring = key; | ||||||
|  | 
 | ||||||
|  |             _lockSlim.EnterReadLock(); | ||||||
|  |             if (_tempBlocked.ContainsKey(clientstring)) | ||||||
|  |             { | ||||||
|  |                 _lockSlim.ExitReadLock(); | ||||||
|  | 
 | ||||||
|  |                 if (_options.ThrottledAction == ThrottleAction.DoThrottledMethod) | ||||||
|  |                     return false; | ||||||
|  |                 else | ||||||
|  |                     throw new System.Security.SecurityException("Throttled"); | ||||||
|  |             } | ||||||
|  |             _lockSlim.ExitReadLock(); | ||||||
|  | 
 | ||||||
|  |             _generalRequestTimes.Put(Util.EnvironmentTickCount()); | ||||||
|  | 
 | ||||||
|  |             if (_generalRequestTimes.Size == _generalRequestTimes.Capacity && | ||||||
|  |                 (Util.EnvironmentTickCountSubtract(Util.EnvironmentTickCount(), _generalRequestTimes.Get()) < | ||||||
|  |                  _options.RequestTimeSpan.TotalMilliseconds)) | ||||||
|  |             { | ||||||
|  |                 //Trigger deeper inspection | ||||||
|  |                 if (DeeperInspection(key, endpoint)) | ||||||
|  |                     return true; | ||||||
|  |                 if (_options.ThrottledAction == ThrottleAction.DoThrottledMethod) | ||||||
|  |                     return false; | ||||||
|  |                 else | ||||||
|  |                     throw new System.Security.SecurityException("Throttled"); | ||||||
|  |             } | ||||||
|  |             return true; | ||||||
|  |         } | ||||||
|  |         private bool DeeperInspection(string key, string endpoint) | ||||||
|  |         { | ||||||
|  |             lock (_deeperInspection) | ||||||
|  |             { | ||||||
|  |                 string clientstring = key; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |                 if (_deeperInspection.ContainsKey(clientstring)) | ||||||
|  |                 { | ||||||
|  |                     _deeperInspection[clientstring].Put(Util.EnvironmentTickCount()); | ||||||
|  |                     if (_deeperInspection[clientstring].Size == _deeperInspection[clientstring].Capacity && | ||||||
|  |                         (Util.EnvironmentTickCountSubtract(Util.EnvironmentTickCount(), _deeperInspection[clientstring].Get()) < | ||||||
|  |                          _options.RequestTimeSpan.TotalMilliseconds)) | ||||||
|  |                     { | ||||||
|  |                         //Looks like we're over the limit | ||||||
|  |                         _lockSlim.EnterWriteLock(); | ||||||
|  |                         if (!_tempBlocked.ContainsKey(clientstring)) | ||||||
|  |                             _tempBlocked.Add(clientstring, Util.EnvironmentTickCount() + (int)_options.ForgetTimeSpan.TotalMilliseconds); | ||||||
|  |                         else | ||||||
|  |                             _tempBlocked[clientstring] = Util.EnvironmentTickCount() + (int)_options.ForgetTimeSpan.TotalMilliseconds; | ||||||
|  |                         _lockSlim.ExitWriteLock(); | ||||||
|  | 
 | ||||||
|  |                         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, endpoint); | ||||||
|  | 
 | ||||||
|  |                         return false; | ||||||
|  |                     } | ||||||
|  |                     //else | ||||||
|  |                     //   return true; | ||||||
|  |                 } | ||||||
|  |                 else | ||||||
|  |                 { | ||||||
|  |                     _deeperInspection.Add(clientstring, new CircularBuffer<int>(_options.MaxRequestsInTimeframe + 1, true)); | ||||||
|  |                     _deeperInspection[clientstring].Put(Util.EnvironmentTickCount()); | ||||||
|  |                     _forgetTimer.Enabled = true; | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |             } | ||||||
|  |             return true; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     public class BasicDosProtectorOptions | ||||||
|  |     { | ||||||
|  |         public int MaxRequestsInTimeframe; | ||||||
|  |         public TimeSpan RequestTimeSpan; | ||||||
|  |         public TimeSpan ForgetTimeSpan; | ||||||
|  |         public bool AllowXForwardedFor; | ||||||
|  |         public string ReportingName = "BASICDOSPROTECTOR"; | ||||||
|  |         public BasicDOSProtector.ThrottleAction ThrottledAction = BasicDOSProtector.ThrottleAction.DoThrottledMethod; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -25,13 +25,7 @@ | ||||||
|  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| using System; |  | ||||||
| using System.Collections; | using System.Collections; | ||||||
| using System.Collections.Generic; |  | ||||||
| using System.Reflection; |  | ||||||
| using System.Net; |  | ||||||
| using OpenSim.Framework; |  | ||||||
| using log4net; |  | ||||||
| 
 | 
 | ||||||
| namespace OpenSim.Framework.Servers.HttpServer | namespace OpenSim.Framework.Servers.HttpServer | ||||||
| { | { | ||||||
|  | @ -39,145 +33,24 @@ namespace OpenSim.Framework.Servers.HttpServer | ||||||
|     { |     { | ||||||
|         private readonly GenericHTTPMethod _normalMethod; |         private readonly GenericHTTPMethod _normalMethod; | ||||||
|         private readonly GenericHTTPMethod _throttledMethod; |         private readonly GenericHTTPMethod _throttledMethod; | ||||||
|         private readonly CircularBuffer<int> _generalRequestTimes; |        | ||||||
|         private readonly BasicDosProtectorOptions _options; |         private readonly BasicDosProtectorOptions _options; | ||||||
|         private readonly Dictionary<string, CircularBuffer<int>> _deeperInspection; |         private readonly BasicDOSProtector _dosProtector; | ||||||
|         private readonly Dictionary<string, int> _tempBlocked; |  | ||||||
|         private readonly System.Timers.Timer _forgetTimer; |  | ||||||
|         private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |  | ||||||
|         private readonly System.Threading.ReaderWriterLockSlim _lockSlim = new System.Threading.ReaderWriterLockSlim(); |  | ||||||
| 
 | 
 | ||||||
|         public GenericHTTPDOSProtector(GenericHTTPMethod normalMethod, GenericHTTPMethod throttledMethod, BasicDosProtectorOptions options) |         public GenericHTTPDOSProtector(GenericHTTPMethod normalMethod, GenericHTTPMethod throttledMethod, BasicDosProtectorOptions options) | ||||||
|         { |         { | ||||||
|             _normalMethod = normalMethod; |             _normalMethod = normalMethod; | ||||||
|             _throttledMethod = throttledMethod; |             _throttledMethod = throttledMethod; | ||||||
|             _generalRequestTimes = new CircularBuffer<int>(options.MaxRequestsInTimeframe + 1, true); |              | ||||||
|             _generalRequestTimes.Put(0); |  | ||||||
|             _options = options; |             _options = options; | ||||||
|             _deeperInspection = new Dictionary<string, CircularBuffer<int>>(); |             _dosProtector = new BasicDOSProtector(_options); | ||||||
|             _tempBlocked = new Dictionary<string, int>(); |  | ||||||
|             _forgetTimer = new System.Timers.Timer(); |  | ||||||
|             _forgetTimer.Elapsed += delegate |  | ||||||
|             { |  | ||||||
|                 _forgetTimer.Enabled = false; |  | ||||||
| 
 |  | ||||||
|                 List<string> removes = new List<string>(); |  | ||||||
|                 _lockSlim.EnterReadLock(); |  | ||||||
|                 foreach (string str in _tempBlocked.Keys) |  | ||||||
|                 { |  | ||||||
|                     if ( |  | ||||||
|                         Util.EnvironmentTickCountSubtract(Util.EnvironmentTickCount(), |  | ||||||
|                                                           _tempBlocked[str]) > 0) |  | ||||||
|                         removes.Add(str); |  | ||||||
|                 } |  | ||||||
|                 _lockSlim.ExitReadLock(); |  | ||||||
|                 lock (_deeperInspection) |  | ||||||
|                 { |  | ||||||
|                     _lockSlim.EnterWriteLock(); |  | ||||||
|                     for (int i = 0; i < removes.Count; i++) |  | ||||||
|                     { |  | ||||||
|                         _tempBlocked.Remove(removes[i]); |  | ||||||
|                         _deeperInspection.Remove(removes[i]); |  | ||||||
|                     } |  | ||||||
|                     _lockSlim.ExitWriteLock(); |  | ||||||
|                 } |  | ||||||
|                 foreach (string str in removes) |  | ||||||
|                 { |  | ||||||
|                     m_log.InfoFormat("[{0}] client: {1} is no longer blocked.", |  | ||||||
|                                      _options.ReportingName, str); |  | ||||||
|                 } |  | ||||||
|                 _lockSlim.EnterReadLock(); |  | ||||||
|                 if (_tempBlocked.Count > 0) |  | ||||||
|                     _forgetTimer.Enabled = true; |  | ||||||
|                 _lockSlim.ExitReadLock(); |  | ||||||
|             }; |  | ||||||
| 
 |  | ||||||
|             _forgetTimer.Interval = _options.ForgetTimeSpan.TotalMilliseconds; |  | ||||||
|         } |         } | ||||||
|         public Hashtable Process(Hashtable request) |         public Hashtable Process(Hashtable request) | ||||||
|         { |         { | ||||||
|             if (_options.MaxRequestsInTimeframe < 1) |             if (_dosProtector.Process(GetClientString(request), GetRemoteAddr(request))) | ||||||
|                 return _normalMethod(request); |                 return _normalMethod(request); | ||||||
|             if (_options.RequestTimeSpan.TotalMilliseconds < 1) |             else | ||||||
|                 return _normalMethod(request); |  | ||||||
| 
 |  | ||||||
|             string clientstring = GetClientString(request); |  | ||||||
| 
 |  | ||||||
|             _lockSlim.EnterReadLock(); |  | ||||||
|             if (_tempBlocked.ContainsKey(clientstring)) |  | ||||||
|             { |  | ||||||
|                 _lockSlim.ExitReadLock(); |  | ||||||
| 
 |  | ||||||
|                 if (_options.ThrottledAction == ThrottleAction.DoThrottledMethod) |  | ||||||
|                 return _throttledMethod(request); |                 return _throttledMethod(request); | ||||||
|                 else |  | ||||||
|                     throw new System.Security.SecurityException("Throttled"); |  | ||||||
|             } |  | ||||||
|             _lockSlim.ExitReadLock(); |  | ||||||
| 
 |  | ||||||
|             _generalRequestTimes.Put(Util.EnvironmentTickCount()); |  | ||||||
| 
 |  | ||||||
|             if (_generalRequestTimes.Size == _generalRequestTimes.Capacity && |  | ||||||
|                 (Util.EnvironmentTickCountSubtract(Util.EnvironmentTickCount(), _generalRequestTimes.Get()) < |  | ||||||
|                  _options.RequestTimeSpan.TotalMilliseconds)) |  | ||||||
|             { |  | ||||||
|                 //Trigger deeper inspection |  | ||||||
|                 if (DeeperInspection(request)) |  | ||||||
|                     return _normalMethod(request); |  | ||||||
|                 if (_options.ThrottledAction == ThrottleAction.DoThrottledMethod) |  | ||||||
|                     return _throttledMethod(request); |  | ||||||
|                 else |  | ||||||
|                     throw new System.Security.SecurityException("Throttled"); |  | ||||||
|             } |  | ||||||
|             Hashtable resp = null; |  | ||||||
|             try |  | ||||||
|             { |  | ||||||
|                 resp = _normalMethod(request); |  | ||||||
|             } |  | ||||||
|             catch (Exception) |  | ||||||
|             { |  | ||||||
| 
 |  | ||||||
|                 throw; |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             return resp; |  | ||||||
|         } |  | ||||||
|         private bool DeeperInspection(Hashtable request) |  | ||||||
|         { |  | ||||||
|             lock (_deeperInspection) |  | ||||||
|             { |  | ||||||
|                 string clientstring = GetClientString(request); |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|                 if (_deeperInspection.ContainsKey(clientstring)) |  | ||||||
|                 { |  | ||||||
|                     _deeperInspection[clientstring].Put(Util.EnvironmentTickCount()); |  | ||||||
|                     if (_deeperInspection[clientstring].Size == _deeperInspection[clientstring].Capacity && |  | ||||||
|                         (Util.EnvironmentTickCountSubtract(Util.EnvironmentTickCount(), _deeperInspection[clientstring].Get()) < |  | ||||||
|                          _options.RequestTimeSpan.TotalMilliseconds)) |  | ||||||
|                     { |  | ||||||
|                         _lockSlim.EnterWriteLock(); |  | ||||||
|                         if (!_tempBlocked.ContainsKey(clientstring)) |  | ||||||
|                             _tempBlocked.Add(clientstring, Util.EnvironmentTickCount() + (int)_options.ForgetTimeSpan.TotalMilliseconds); |  | ||||||
|                         else |  | ||||||
|                             _tempBlocked[clientstring] = Util.EnvironmentTickCount() + (int)_options.ForgetTimeSpan.TotalMilliseconds; |  | ||||||
|                         _lockSlim.ExitWriteLock(); |  | ||||||
|                          |  | ||||||
|                          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)); |  | ||||||
|                         return false; |  | ||||||
|                     } |  | ||||||
|                     //else |  | ||||||
|                     //   return true; |  | ||||||
|                 } |  | ||||||
|                 else |  | ||||||
|                 { |  | ||||||
|                     _deeperInspection.Add(clientstring, new CircularBuffer<int>(_options.MaxRequestsInTimeframe + 1, true)); |  | ||||||
|                     _deeperInspection[clientstring].Put(Util.EnvironmentTickCount()); |  | ||||||
|                     _forgetTimer.Enabled = true; |  | ||||||
|                 } |  | ||||||
| 
 |  | ||||||
|             } |  | ||||||
|             return true; |  | ||||||
|         } |         } | ||||||
|          |          | ||||||
|         private string GetRemoteAddr(Hashtable request) |         private string GetRemoteAddr(Hashtable request) | ||||||
|  |  | ||||||
|  | @ -25,162 +25,42 @@ | ||||||
|  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| using System; |  | ||||||
| using System.Collections.Generic; |  | ||||||
| using System.Reflection; |  | ||||||
| using System.Net; | using System.Net; | ||||||
| using Nwc.XmlRpc; | using Nwc.XmlRpc; | ||||||
| using OpenSim.Framework; | using OpenSim.Framework; | ||||||
| using log4net; | 
 | ||||||
| 
 | 
 | ||||||
| namespace OpenSim.Framework.Servers.HttpServer | namespace OpenSim.Framework.Servers.HttpServer | ||||||
| { | { | ||||||
|     public enum ThrottleAction |  | ||||||
|     { |  | ||||||
|         DoThrottledMethod, |  | ||||||
|         DoThrow |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     public class XmlRpcBasicDOSProtector |     public class XmlRpcBasicDOSProtector | ||||||
|     { |     { | ||||||
|         private readonly XmlRpcMethod _normalMethod; |         private readonly XmlRpcMethod _normalMethod; | ||||||
|         private readonly XmlRpcMethod _throttledMethod; |         private readonly XmlRpcMethod _throttledMethod; | ||||||
|         private readonly CircularBuffer<int> _generalRequestTimes; // General request checker |         | ||||||
|         private readonly BasicDosProtectorOptions _options; |         private readonly BasicDosProtectorOptions _options; | ||||||
|         private readonly Dictionary<string, CircularBuffer<int>> _deeperInspection;   // per client request checker |         private readonly BasicDOSProtector _dosProtector; | ||||||
|         private readonly Dictionary<string, int> _tempBlocked;  // blocked list |  | ||||||
|         private readonly System.Timers.Timer _forgetTimer;  // Cleanup timer |  | ||||||
|         private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |  | ||||||
|         private readonly System.Threading.ReaderWriterLockSlim _lockSlim = new System.Threading.ReaderWriterLockSlim(); |  | ||||||
| 
 | 
 | ||||||
|         public XmlRpcBasicDOSProtector(XmlRpcMethod normalMethod, XmlRpcMethod throttledMethod,BasicDosProtectorOptions options) |         public XmlRpcBasicDOSProtector(XmlRpcMethod normalMethod, XmlRpcMethod throttledMethod,BasicDosProtectorOptions options) | ||||||
|         { |         { | ||||||
|             _normalMethod = normalMethod; |             _normalMethod = normalMethod; | ||||||
|             _throttledMethod = throttledMethod; |             _throttledMethod = throttledMethod; | ||||||
|             _generalRequestTimes = new CircularBuffer<int>(options.MaxRequestsInTimeframe + 1,true); |             | ||||||
|             _generalRequestTimes.Put(0); |  | ||||||
|             _options = options; |             _options = options; | ||||||
|             _deeperInspection = new Dictionary<string, CircularBuffer<int>>(); |             _dosProtector = new BasicDOSProtector(_options); | ||||||
|             _tempBlocked = new Dictionary<string, int>(); |  | ||||||
|             _forgetTimer = new System.Timers.Timer(); |  | ||||||
|             _forgetTimer.Elapsed += delegate |  | ||||||
|                                         { |  | ||||||
|                                             _forgetTimer.Enabled = false; |  | ||||||
| 
 | 
 | ||||||
|                                             List<string> removes = new List<string>(); |  | ||||||
|                                             _lockSlim.EnterReadLock(); |  | ||||||
|                                             foreach (string str in _tempBlocked.Keys) |  | ||||||
|                                             { |  | ||||||
|                                                 if ( |  | ||||||
|                                                     Util.EnvironmentTickCountSubtract(Util.EnvironmentTickCount(), |  | ||||||
|                                                                                       _tempBlocked[str]) > 0) |  | ||||||
|                                                     removes.Add(str); |  | ||||||
|                                             } |  | ||||||
|                                             _lockSlim.ExitReadLock(); |  | ||||||
|                                             lock (_deeperInspection) |  | ||||||
|                                             { |  | ||||||
|                                                 _lockSlim.EnterWriteLock(); |  | ||||||
|                                                 for (int i = 0; i < removes.Count; i++) |  | ||||||
|                                                 { |  | ||||||
|                                                     _tempBlocked.Remove(removes[i]); |  | ||||||
|                                                     _deeperInspection.Remove(removes[i]); |  | ||||||
|                                                 } |  | ||||||
|                                                 _lockSlim.ExitWriteLock(); |  | ||||||
|                                             } |  | ||||||
|                                             foreach (string str in removes) |  | ||||||
|                                             { |  | ||||||
|                                                 m_log.InfoFormat("[{0}] client: {1} is no longer blocked.", |  | ||||||
|                                                                  _options.ReportingName, str); |  | ||||||
|                                             } |  | ||||||
|                                             _lockSlim.EnterReadLock(); |  | ||||||
|                                             if (_tempBlocked.Count > 0) |  | ||||||
|                                                 _forgetTimer.Enabled = true; |  | ||||||
|                                             _lockSlim.ExitReadLock(); |  | ||||||
|                                         }; |  | ||||||
|                                          |  | ||||||
|             _forgetTimer.Interval = _options.ForgetTimeSpan.TotalMilliseconds; |  | ||||||
|         } |         } | ||||||
|         public XmlRpcResponse Process(XmlRpcRequest request, IPEndPoint client) |         public XmlRpcResponse Process(XmlRpcRequest request, IPEndPoint client) | ||||||
|         { |         { | ||||||
|             // If these are set like this, this is disabled |  | ||||||
|             if (_options.MaxRequestsInTimeframe < 1 || _options.RequestTimeSpan.TotalMilliseconds < 1) |  | ||||||
|                 return _normalMethod(request, client); |  | ||||||
| 
 | 
 | ||||||
|             string clientstring = GetClientString(request, client); |  | ||||||
| 
 |  | ||||||
|             _lockSlim.EnterReadLock(); |  | ||||||
|             if (_tempBlocked.ContainsKey(clientstring)) |  | ||||||
|             { |  | ||||||
|                 _lockSlim.ExitReadLock(); |  | ||||||
| 
 |  | ||||||
|                 if (_options.ThrottledAction == ThrottleAction.DoThrottledMethod) |  | ||||||
|                     return _throttledMethod(request, client); |  | ||||||
|                 else |  | ||||||
|                     throw new System.Security.SecurityException("Throttled"); |  | ||||||
|             } |  | ||||||
|             _lockSlim.ExitReadLock(); |  | ||||||
| 
 |  | ||||||
|             _generalRequestTimes.Put(Util.EnvironmentTickCount()); |  | ||||||
|              |  | ||||||
|             if (_generalRequestTimes.Size == _generalRequestTimes.Capacity && |  | ||||||
|                 (Util.EnvironmentTickCountSubtract(Util.EnvironmentTickCount(), _generalRequestTimes.Get()) < |  | ||||||
|                  _options.RequestTimeSpan.TotalMilliseconds)) |  | ||||||
|             { |  | ||||||
|                 //Trigger deeper inspection |  | ||||||
|                 if (DeeperInspection(request, client)) |  | ||||||
|                     return _normalMethod(request, client); |  | ||||||
|                 if (_options.ThrottledAction == ThrottleAction.DoThrottledMethod) |  | ||||||
|                     return _throttledMethod(request, client); |  | ||||||
|                 else |  | ||||||
|                     throw new System.Security.SecurityException("Throttled"); |  | ||||||
|             } |  | ||||||
|             XmlRpcResponse resp = null; |             XmlRpcResponse resp = null; | ||||||
|             |             if (_dosProtector.Process(GetClientString(request, client), GetEndPoint(request, client))) | ||||||
|                 resp = _normalMethod(request, client); |                 resp = _normalMethod(request, client); | ||||||
|  |             else | ||||||
|  |                 resp = _throttledMethod(request, client); | ||||||
|              |              | ||||||
|             return resp; |             return resp; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         // If the service is getting more hits per expected timeframe then it starts to separate them out by client |  | ||||||
|         private bool DeeperInspection(XmlRpcRequest request, IPEndPoint client) |  | ||||||
|         { |  | ||||||
|             lock (_deeperInspection) |  | ||||||
|             { |  | ||||||
|                 string clientstring = GetClientString(request, client); |  | ||||||
|                  |  | ||||||
| 
 |  | ||||||
|                 if (_deeperInspection.ContainsKey(clientstring)) |  | ||||||
|                 { |  | ||||||
|                     _deeperInspection[clientstring].Put(Util.EnvironmentTickCount()); |  | ||||||
|                     if (_deeperInspection[clientstring].Size == _deeperInspection[clientstring].Capacity && |  | ||||||
|                         (Util.EnvironmentTickCountSubtract(Util.EnvironmentTickCount(), _deeperInspection[clientstring].Get()) < |  | ||||||
|                          _options.RequestTimeSpan.TotalMilliseconds)) |  | ||||||
|                     { |  | ||||||
|                         //Looks like we're over the limit |  | ||||||
|                         _lockSlim.EnterWriteLock(); |  | ||||||
|                         if (!_tempBlocked.ContainsKey(clientstring)) |  | ||||||
|                             _tempBlocked.Add(clientstring, Util.EnvironmentTickCount() + (int)_options.ForgetTimeSpan.TotalMilliseconds); |  | ||||||
|                         else |  | ||||||
|                             _tempBlocked[clientstring] = Util.EnvironmentTickCount() + (int)_options.ForgetTimeSpan.TotalMilliseconds; |  | ||||||
|                         _lockSlim.ExitWriteLock(); |  | ||||||
| 
 |  | ||||||
|                         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, client.Address); |  | ||||||
|                          |  | ||||||
|                         return false; |  | ||||||
|                     } |  | ||||||
|                     //else |  | ||||||
|                      //   return true; |  | ||||||
|                 } |  | ||||||
|                 else |  | ||||||
|                 { |  | ||||||
|                     _deeperInspection.Add(clientstring, new CircularBuffer<int>(_options.MaxRequestsInTimeframe + 1, true)); |  | ||||||
|                     _deeperInspection[clientstring].Put(Util.EnvironmentTickCount()); |  | ||||||
|                     _forgetTimer.Enabled = true; |  | ||||||
|                 } |  | ||||||
| 
 |  | ||||||
|             } |  | ||||||
|             return true; |  | ||||||
|         } |  | ||||||
|         private string GetClientString(XmlRpcRequest request, IPEndPoint client) |         private string GetClientString(XmlRpcRequest request, IPEndPoint client) | ||||||
|         { |         { | ||||||
|             string clientstring; |             string clientstring; | ||||||
|  | @ -197,15 +77,12 @@ namespace OpenSim.Framework.Servers.HttpServer | ||||||
|             return clientstring; |             return clientstring; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         private string GetEndPoint(XmlRpcRequest request, IPEndPoint client) | ||||||
|  |         { | ||||||
|  |              return client.Address.ToString(); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|     public class BasicDosProtectorOptions |  | ||||||
|     { |  | ||||||
|         public int MaxRequestsInTimeframe; |  | ||||||
|         public TimeSpan RequestTimeSpan; |  | ||||||
|         public TimeSpan ForgetTimeSpan; |  | ||||||
|         public bool AllowXForwardedFor; |  | ||||||
|         public string ReportingName = "BASICDOSPROTECTOR"; |  | ||||||
|         public ThrottleAction ThrottledAction = ThrottleAction.DoThrottledMethod; |  | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |      | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -53,10 +53,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends | ||||||
|                                           { |                                           { | ||||||
|                                               AllowXForwardedFor = true, |                                               AllowXForwardedFor = true, | ||||||
|                                               ForgetTimeSpan = TimeSpan.FromMinutes(2), |                                               ForgetTimeSpan = TimeSpan.FromMinutes(2), | ||||||
|                                               MaxRequestsInTimeframe = 5, |                                               MaxRequestsInTimeframe = 20, | ||||||
|                                               ReportingName = "FRIENDSDOSPROTECTOR", |                                               ReportingName = "FRIENDSDOSPROTECTOR", | ||||||
|                                               RequestTimeSpan = TimeSpan.FromSeconds(5), |                                               RequestTimeSpan = TimeSpan.FromSeconds(5), | ||||||
|                                               ThrottledAction = ThrottleAction.DoThrottledMethod |                                               ThrottledAction = BasicDOSProtector.ThrottleAction.DoThrottledMethod | ||||||
|                                           }) |                                           }) | ||||||
|         { |         { | ||||||
|             m_FriendsModule = fmodule; |             m_FriendsModule = fmodule; | ||||||
|  |  | ||||||
|  | @ -173,7 +173,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap | ||||||
|                         MaxRequestsInTimeframe = 4, |                         MaxRequestsInTimeframe = 4, | ||||||
|                         ReportingName = "MAPDOSPROTECTOR", |                         ReportingName = "MAPDOSPROTECTOR", | ||||||
|                         RequestTimeSpan = TimeSpan.FromSeconds(10), |                         RequestTimeSpan = TimeSpan.FromSeconds(10), | ||||||
|                         ThrottledAction = ThrottleAction.DoThrottledMethod |                         ThrottledAction = BasicDOSProtector.ThrottleAction.DoThrottledMethod | ||||||
|                     }).Process); |                     }).Process); | ||||||
|             MainServer.Instance.AddLLSDHandler( |             MainServer.Instance.AddLLSDHandler( | ||||||
|                 "/MAP/MapItems/" + m_scene.RegionInfo.RegionHandle.ToString(), HandleRemoteMapItemRequest); |                 "/MAP/MapItems/" + m_scene.RegionInfo.RegionHandle.ToString(), HandleRemoteMapItemRequest); | ||||||
|  | @ -1094,7 +1094,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap | ||||||
|         { |         { | ||||||
|             Hashtable reply = new Hashtable(); |             Hashtable reply = new Hashtable(); | ||||||
|             int statuscode = 500; |             int statuscode = 500; | ||||||
|             reply["str_response_string"] = "I blocked you! HAHAHAHAHAHAHHAHAH"; |             reply["str_response_string"] = ""; | ||||||
|             reply["int_response_code"] = statuscode; |             reply["int_response_code"] = statuscode; | ||||||
|             reply["content_type"] = "text/plain"; |             reply["content_type"] = "text/plain"; | ||||||
|             return reply; |             return reply; | ||||||
|  |  | ||||||
|  | @ -56,7 +56,7 @@ namespace OpenSim.Server.Handlers.Asset | ||||||
|                                               MaxRequestsInTimeframe = 5, |                                               MaxRequestsInTimeframe = 5, | ||||||
|                                               ReportingName = "ASSETGETDOSPROTECTOR", |                                               ReportingName = "ASSETGETDOSPROTECTOR", | ||||||
|                                               RequestTimeSpan = TimeSpan.FromSeconds(5), |                                               RequestTimeSpan = TimeSpan.FromSeconds(5), | ||||||
|                                               ThrottledAction = ThrottleAction.DoThrottledMethod |                                               ThrottledAction = BasicDOSProtector.ThrottleAction.DoThrottledMethod | ||||||
|                                           }) |                                           }) | ||||||
|         { |         { | ||||||
|             m_AssetService = service; |             m_AssetService = service; | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	 teravus
						teravus