Search code examples
.netiisiis-8

Request Rate Limiting in IIS by url


In my application I want to limit the request to the login page of my website to be processed by server and if the request increases by specific number then IIS should block that ip address for some time. I have gone through IIS 'IP Address and Domain Restrictions' feature but I want to block the request if the request comes for the login page not for any other page and operation on my website. How can we achieve this using IIS?


Solution

  • IIS IP restriction can only be used for site level. You can't set dynamic IP restriction for specific controller or folder. So it is recommended to use custom httpmodule instead. You could add a filter to this code so that the httpmodule will only authenticate the hit number to your login page.

    CS1

    public class UrlReWrite : IHttpModule
            {
    
                private int rowCount = Convert.ToInt32(ConfigurationManager.AppSettings["HttpRowCount"]);
    
                private int httpTime = Convert.ToInt32(ConfigurationManager.AppSettings["HttpTime"]);
                public void Init(HttpApplication application)
                {
                    application.BeginRequest += (new
                       EventHandler(this.Application_BeginRequest));
                    application.EndRequest += (new
                       EventHandler(this.Application_EndRequest));
                }
                private void Application_BeginRequest(Object source, EventArgs e)
                {
                    HttpApplication Application = (HttpApplication)source;
                    HttpContext ctx = Application.Context;
    
                    string isIp = ctx.Request.UserHostAddress;
                    if (ctx.Application["time"] == null)
                    {
                        ctx.Application["time"] = DateTime.Now;
                    }
                    else
                    {
                        DateTime isTime = (DateTime)ctx.Application["time"];
                        int timeTract = Convert.ToInt32(DateTime.Now.Subtract(isTime).Minutes.ToString());
                        if (timeTract > (httpTime - 1))
                        {
                            ctx.Application["time"] = null;
                            ctx.Application["myip"] = null;
                        }
                    }
                    if (ctx.Application["myip"] != null && ctx.Application["myip"] is CartIp)
                    {
                        CartIp cartIp = (CartIp)ctx.Application["myip"];
                        cartIp.Insert(isIp);
                        ctx.Application["myip"] = cartIp;
                        if (cartIp.GetCount(isIp) > rowCount)
                        {
                            ctx.Response.Clear();
                            ctx.Response.Close();
                        }
                    }
                    else
                    {
                        CartIp cartIp = new CartIp();
                        cartIp.Insert(isIp);
                        HttpContext.Current.Application["myip"] = cartIp;
                    }
                }
                private void Application_EndRequest(Object source, EventArgs e)
                {
                }
                public void Dispose()
                {
                }
            }
        }
    

    class2.cs

    [Serializable]
        public class ListIp
        {
            private string ip;
            private int count;
    
            public string IP
            {
                get { return ip; }
                set { ip = value; }
            }
    
            public int Count
            {
                get { return count; }
                set { count = value; }
            }
        }
        [Serializable]
        public class CartIp
        {
            public CartIp()
            {
                if (_listIp == null)
                {
                    _listIp = new List<ListIp>();
                }
            }
            private List<ListIp> _listIp;
            public List<ListIp> _ListIp
            {
                get { return _listIp; }
                set { _listIp = value; }
            }
    
            public void Insert(string ip)
            {
                int indexof = ItemLastInfo(ip);
                if (indexof == -1)
                {
    
                    ListIp item = new ListIp();
                    item.IP = ip;
                    _listIp.Add(item);
                }
                else
                {
                    _listIp[indexof].Count += 1;
                }
            }
    
        public int ItemLastInfo(string ip)
        {
            int index = 0;
            foreach (ListIp item in _ListIp)
            {
                if (item.IP == ip)
                {
                    return index;
                }
                index += 1;
            }
            return -1;
        }
        /// <summary>
        /// get number of IP address
        /// </summary>
        /// <param name="ip"></param>
        /// <returns></returns>
        public int GetCount(string ip)
        {
            foreach (ListIp item in _ListIp)
            {
                if (item.IP == ip)
                {
                    return item.Count;
                }
            }
            return -1;
        }
    }
    

    web.config

    <appSettings>
    <add key="HttpRowCount" value="100"/>
    <add key="HttpTime" value="10"/>
    </appSettings>
    

    You only need to create a class library. Then copy and modify these code to achieve your requirement. Finally, you need to copy the release dll to bin folder and import it via IIS manager->site node->modules->add managed module.

    https://www.cnblogs.com/Fooo/archive/2013/01/27/2878820.html