Hacker Anti-brush Attack Solution (String)

“This is the fifth day of my participation in the Gwen Challenge in November. Check out the details: The Last Gwen Challenge in 2021.”

The scene of a hacking attack

Hackers in the Internet in order to attack your server, indiscriminate destination attack your interface, in a short period of time is usually concurrent endless loop of a large number of requests to your interface, so that the server resources exhausted, resulting in your system down.

This attack has two serious consequences:

  1. For inserting database interface: there will be a large number of repeated data, even garbage data will burst the database.
  2. For query interfaces: Hackers generally attack slow query interfaces, for example, slow query interfaces for 1s. As long as hackers launch attacks, the system will be dragged down and database queries will be blocked.

Principle of anti-brush attack technology

For an interface, the access frequency control is adopted. When an IP address frequently accesses the interface in a short period of time, it needs to be recorded and identified, and even the corresponding IP address is added to the blacklist. Such high concurrent requests are usually realized by Redis + Lua.

  1. When a user invokes an interface, the user’s IP address is recorded and an INCR counter command is sent to Redis.
  2. Set the expire time of the counter to 30 seconds
  3. If an IP address has more than 10 requests within 30 seconds, it is considered abnormal

Step 1: Write an anti-brush script for Lua

-- Sets the counter for the request IP of an interface, such as when IP127.0. 01.When requesting a commodity interface, key=product:127.0. 01.
local times = redis.call('incr',KEYS[1] -- Sets a timeout for the key of an IP when it is first requested.if times == 1 then
    redis.call('expire',KEYS[1], ARGV[1]) end -- tonumber is to convert a string to a number -- for example, an IP address30Within seconds, the number of requests is greater than10, it returns0, otherwise return1
if times > tonumber(ARGV[2]) then
    return 0
end
return 1
Copy the code

Step 2: Run the Lua anti-brush script

Run this command in Linux

[root@iZbp1bunl8t8qf63wqsy0iZ src]# ./redis-cli --eval ./my/limit.lua producapi:127.0. 01. , 30 10
(integer) 1
[root@iZbp1bunl8t8qf63wqsy0iZ src]# ./redis-cli --eval ./my/limit.lua producapi:127.0. 01. , 30 10
(integer) 1
[root@iZbp1bunl8t8qf63wqsy0iZ src]# ./redis-cli --eval ./my/limit.lua producapi:127.0. 01. , 30 10
(integer) 1
[root@iZbp1bunl8t8qf63wqsy0iZ src]# ./redis-cli --eval ./my/limit.lua producapi:127.0. 01. , 30 10
(integer) 1
[root@iZbp1bunl8t8qf63wqsy0iZ src]# ./redis-cli --eval ./my/limit.lua producapi:127.0. 01. , 30 10
(integer) 1
[root@iZbp1bunl8t8qf63wqsy0iZ src]# ./redis-cli --eval ./my/limit.lua producapi:127.0. 01. , 30 10
(integer) 1
[root@iZbp1bunl8t8qf63wqsy0iZ src]# ./redis-cli --eval ./my/limit.lua producapi:127.0. 01. , 30 10
(integer) 1
[root@iZbp1bunl8t8qf63wqsy0iZ src]# ./redis-cli --eval ./my/limit.lua producapi:127.0. 01. , 30 10
(integer) 1
[root@iZbp1bunl8t8qf63wqsy0iZ src]# ./redis-cli --eval ./my/limit.lua producapi:127.0. 01. , 30 10
(integer) 1
[root@iZbp1bunl8t8qf63wqsy0iZ src]# ./redis-cli --eval ./my/limit.lua producapi:127.0. 01. , 30 10
(integer) 1
[root@iZbp1bunl8t8qf63wqsy0iZ src]# ./redis-cli --eval ./my/limit.lua producapi:127.0. 01. , 30 10
(integer) 0
[root@iZbp1bunl8t8qf63wqsy0iZ src]# ./redis-cli --eval ./my/limit.lua producapi:127.0. 01. , 30 10
(integer) 0
[root@iZbp1bunl8t8qf63wqsy0iZ src]# 
Copy the code

SpringBoot+Redis+ Lua to achieve anti-brush hacker attacks

Step 1: Write a Lua file and store it in Resources/Lua

Set the counter for the request IP of an interface, for example, when IP127. 0. 01.When requesting a commodity interface, key=product:127.0. 01.
local times = redis.call('incr',KEYS[1] -- Sets a timeout for the key of an IP when it is first requested.if times == 1 then
    redis.call('expire',KEYS[1], ARGV[1]) end -- tonumber is to convert a string to a number, -- for example, an IP address30Within seconds, the number of requests is greater than10, it returns0, otherwise return1
if times > tonumber(ARGV[2]) then
    return 0
end
return 1

Copy the code

Step 2: Create a Lua script object

Create a Lua script object and inject it into the IOC container

@Bean
public DefaultRedisScript<Long> limitScript(a) {
    DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();
    redisScript.setScriptSource(new ResourceScriptSource(new ClassPathResource("lua/limit.lua")));
    redisScript.setResultType(Long.class);
    return redisScript;
}
Copy the code

Step 3: SpringBoot executes the Lua script


@Resource
private DefaultRedisScript<Long> limitScript;

@Resource
private StringRedisTemplate stringRedisTemplate;

@GetMapping(value = "/productlist")
public String productList(HttpServletRequest request) {
    // Get the requested IP address
    String ip = IpUtils.getIpAddr(request);
    // Set the key of redis
    List<String> keys = Arrays.asList("pruductAPI:" + ip);
    The execute method takes 3 arguments. The first argument is a Lua script object, the second argument is a key list, and the third argument is an array of Lua parameters
    //30 means 30 seconds, and 10 means more than 10 requests, which means the same IP address can not be more than 10 requests in 30 seconds
    Long n = this.stringRedisTemplate.execute(this.limitScript, keys, "30"."10");
    String result="";
    // Invalid request
    if (n == 0) {
        result= "Illegal request";
    } else {
        result= "Return to list of items";
    }
    log.info("IP ={} request result: {}", ip,result);
    return result;
}
Copy the code

SMS verification code anti-brush scenario

Authentication is required in scenarios such as login and password change. You need to enter your mobile phone number and click Send SMS verification code. After receiving the SMS verification code, you can log in by filling in the verification code.

To save SMS costs, you can only send SMS messages once within 60 seconds from the same mobile phone number.

[root@iZbp1bunl8t8qf63wqsy0iZ src]# ./redis-cli --eval ./my/limit.lua login:captcha:10086 , 60 1
(integer) 1
[root@iZbp1bunl8t8qf63wqsy0iZ src]# ./redis-cli --eval ./my/limit.lua login:captcha:10086 , 60 1
(integer) 0
[root@iZbp1bunl8t8qf63wqsy0iZ src]# ./redis-cli --eval ./my/limit.lua login:captcha:10086 , 60 1
(integer) 0
Copy the code

You only need to modify the input parameter.

    Long n = this.stringRedisTemplate.execute(this.limitScript, keys, "60"."1");
Copy the code

Redis distributed cache family

  • Redis Distributed Cache (1) – Redis Installation (Linux and Docker)
  • Redis Distributed cache (ii) – RDB and AOF
  • SpringBoot integrates Mybatis-Plus,Redis and Swagger
  • Redis distributed cache (4) – SpringCache integrates redis
  • Redis Distributed Cache (5) — Common command (String)
  • Redis Distributed Cache (6) — Article read volume PV Solution (String)
  • Redis Distributed Cache (7) — Distributed Global ID Solution (String)
  • Redis Distributed Cache (8) — Highly Concurrent atomic Operations (Redis+Lua)
  • The article continues to be updated…