Redis from source

Simple setup

yum --enablerepo=remi install redis

systemctl enable redis
systemctl start redis

 cd /tmp
 wget https://pecl.php.net/get/redis-4.3.0.tgz
 tar xzvf redis-4.3.0.tgz
 phpize
 cd redis-4.3.0/
 phpize
   ./configure
   make
   make test
   make install
   php -m | grep redis

 nano /etc/php.d/redis.ini
extension=redis.so

   php -m | grep redis


   systemctl restart httpd php-fpm

 

nano /etc/redis/redis.conf

  • daemonize yes
  • supervised systemd
  • # save 3600 1
    # save 300 100
    # save 60 10000
  • dir /var/lib/redis
  • maxmemory 1024mb (or 512mb)
  • maxmemory-policy allkeys-lfu
  • appendonly yes

redis-cli PING

tail /var/log/redis/redis.log

nano /var/www/html/resource.php

<?php

$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$redis->auth('REDIS_PASSWORD');

$max_calls_limit  = 7;
$time_period      = 10;
$total_user_calls = 0;

if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
    $user_ip_address = $_SERVER['HTTP_CLIENT_IP'];
} elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
    $user_ip_address = $_SERVER['HTTP_X_FORWARDED_FOR'];
} else {
    $user_ip_address = $_SERVER['REMOTE_ADDR'];
}

if (!$redis->exists($user_ip_address)) {
    $redis->set($user_ip_address, 1);
    $redis->expire($user_ip_address, $time_period);
    $total_user_calls = 1;
} else {
    $redis->INCR($user_ip_address);
    $total_user_calls = $redis->get($user_ip_address);
    if ($total_user_calls > $max_calls_limit) {
echo "Hey, " . $user_ip_address . ", You've already reached your requests limit. Total requests "
                         . $total_user_calls . " Allowed requests " . $max_calls_limit;
        exit();
}
}

?>

 

curl http://localhost/resource.php?[1-20]

 

 

 

Unmounting

systemctl stop redis.service

systemctl mask redis.service

 systemctl disable redis.service

yum remove redis

 

Installation

cd /usr/local/src
 wget http://download.redis.io/releases/redis-5.0.0.tar.gz
tar xf redis-5.0.0.tar.gz
 cd redis-5.0.0
 make
 make test
 make install
 groupadd redis

adduser --system -g redis --no-create-home redis

 

 

Next create the /var/lib/redis directory which will store the redis databases:

mkdir -p /var/lib/redis

Give the redis user and group ownership over the directory:

chown redis: /var/lib/redis

Set the correct permissions with:

chmod 770 /var/lib/redis

Step 4. Creating Redis Configuration

Now that Redis is installed and intial setup has been completed on your CentOS 7 VPS, you’ll need to create the configuration file.

First, create the /etc/redis directory with:

mkdir /etc/redis

Next copy the default configuration file by running:

cp /usr/local/src/redis-5.0.0/redis.conf /etc/redis/

Open the file with your preferred text editor (we’ll be using nano):

nano /etc/redis/redis.conf

Search for the supervised directive and change it to “systemd”:

# If you run Redis from upstart or systemd, Redis can interact with your
# supervision tree. Options:
#   supervised no      - no supervision interaction
#   supervised upstart - signal upstart by putting Redis into SIGSTOP mode
#   supervised systemd - signal systemd by writing READY=1 to $NOTIFY_SOCKET
#   supervised auto    - detect upstart or systemd method based on
#                        UPSTART_JOB or NOTIFY_SOCKET environment variables
# Note: these supervision methods only signal "process is ready."
#       They do not enable continuous liveness pings back to your supervisor.

supervised systemd

Search for the dir directive and set it to /var/lib/redis:

# The working directory.
#
# The DB will be written inside this directory, with the filename specified
# above using the 'dbfilename' configuration directive.
#
# The Append Only File will also be created inside this directory.
#
# Note that you must specify a directory here, not a file name.
dir /var/lib/redis

Once done, save and close the file.

Step 5. Creating a Redis Systemd Unit File

Now that Redis is installed and configured, the last step is to create a systemd unit file so that you can manage the Redis servis as a regular systemd service.

Open your text editor and create the follwing file:

nano /etc/systemd/system/redis.service

Then add the following content to it:

[Unit]
Description=Redis Data Store
After=network.target

[Service]
User=redis
Group=redis
ExecStart=/usr/local/bin/redis-server /etc/redis/redis.conf
ExecStop=/usr/local/bin/redis-cli shutdown
Restart=always

[Install]
WantedBy=multi-user.target

Save and close the file. Enable and start the Redis service with:

systemctl enable redis
systemctl start redis

To check that the Redis service has no errors, run:

systemctl status redis

 

ln -s /usr/local/bin/redis-cli /usr/bin/redis-cli

redis-cli PING

systemctl restart redis.service

tail /var/log/redis/redis.log

reboot

 

USEFUL COMMANDS

 

Performing an LRU simulation

Redis is often used as a cache with LRU eviction. Depending on the number of keys and the amount of memory allocated for the cache (specified via the maxmemory directive), the amount of cache hits and misses will change. Sometimes, simulating the rate of hits is very useful to correctly provision your cache.

The CLI has a special mode where it performs a simulation of GET and SET operations, using an 80-20% power law distribution in the requests pattern. This means that 20% of keys will be requested 80% of times, which is a common distribution in caching scenarios.

Theoretically, given the distribution of the requests and the Redis memory overhead, it should be possible to compute the hit rate analytically with with a mathematical formula. However, Redis can be configured with different LRU settings (number of samples) and LRU's implementation, which is approximated in Redis, changes a lot between different versions. Similarly the amount of memory per key may change between versions. That is why this tool was built: its main motivation was for testing the quality of Redis' LRU implementation, but now is also useful in for testing how a given version behaves with the settings you had in mind for your deployment.

In order to use this mode, you need to specify the amount of keys in the test. You also need to configure a maxmemory setting that makes sense as a first try.

IMPORTANT NOTE: Configuring the maxmemory setting in the Redis configuration is crucial: if there is no cap to the maximum memory usage, the hit will eventually be 100% since all the keys can be stored in memory. Or if you specify too many keys and no maximum memory, eventually all the computer RAM will be used. It is also needed to configure an appropriate maxmemory policy, most of the times what you want is allkeys-lru.

In the following example I configured a memory limit of 100MB, and an LRU simulation using 10 million keys.

WARNING: the test uses pipelining and will stress the server, don't use it with production instances.

$ ./redis-cli --lru-test 10000000
156000 Gets/sec | Hits: 4552 (2.92%) | Misses: 151448 (97.08%)
153750 Gets/sec | Hits: 12906 (8.39%) | Misses: 140844 (91.61%)
159250 Gets/sec | Hits: 21811 (13.70%) | Misses: 137439 (86.30%)
151000 Gets/sec | Hits: 27615 (18.29%) | Misses: 123385 (81.71%)
145000 Gets/sec | Hits: 32791 (22.61%) | Misses: 112209 (77.39%)
157750 Gets/sec | Hits: 42178 (26.74%) | Misses: 115572 (73.26%)
154500 Gets/sec | Hits: 47418 (30.69%) | Misses: 107082 (69.31%)
151250 Gets/sec | Hits: 51636 (34.14%) | Misses: 99614 (65.86%)

The program shows stats every second. As you see, in the first seconds the cache starts to be populated. The misses rate later stabilizes into the actual figure we can expect in the long time:

120750 Gets/sec | Hits: 48774 (40.39%) | Misses: 71976 (59.61%)
122500 Gets/sec | Hits: 49052 (40.04%) | Misses: 73448 (59.96%)
127000 Gets/sec | Hits: 50870 (40.06%) | Misses: 76130 (59.94%)
124250 Gets/sec | Hits: 50147 (40.36%) | Misses: 74103 (59.64%)

A miss rage of 59% may not be acceptable for our use case. So we know that 100MB of memory is not enough. Let's try with half gigabyte. After a few minutes we'll see the output stabilize to the following figures:

140000 Gets/sec | Hits: 135376 (96.70%) | Misses: 4624 (3.30%)
141250 Gets/sec | Hits: 136523 (96.65%) | Misses: 4727 (3.35%)
140250 Gets/sec | Hits: 135457 (96.58%) | Misses: 4793 (3.42%)
140500 Gets/sec | Hits: 135947 (96.76%) | Misses: 4553 (3.24%)

So we know that with 500MB we are going well enough for our number of keys (10 millions) and distribution (80-20 style).

 

redis-server --version

gives you the version.

redis-cli
INFO

 

 

redis-cli --stat

 

redis-cli
127.0.0.1:6379> config get repl*

 

curl http://localhost/resource.php?[1-20]

 

resource.php

<?php
    try {             
            $redis = new Redis();
            $redis->connect('127.0.0.1', 6379);

            $username = $_SERVER['PHP_AUTH_USER'];
            $password = $_SERVER['PHP_AUTH_PW'];

            $key = $username;

            $allowed_requests_per_period = 5;
            $time_frame_in_seconds       = 10;

            $total_requests = 0;

            if ($redis->exists($key)) {
                $redis->INCR($key);                  
                $total_requests = $redis->get($key);                    

                if ($total_requests > $allowed_requests_per_period) {
                   echo "Hey, " . $username . ", You've already reached your requests limit. Total requests "
                         . $total_requests . " Allowed requests " . $allowed_requests_per_period;
                   exit();                   
                }                

            } else {               
                $redis->set($key, 1);
                $redis->expire($key, $time_frame_in_seconds);
                $total_requests = 1;       
            }

            echo "ok, total requests " . $total_requests;            

        } catch (Exception $e) {
            echo $e->getMessage();
        }
?>

 

 

either shorten version

try {
 $redis = new Redis();
            $redis->connect('127.0.0.1', 6379);

            $username = $_SERVER['PHP_AUTH_USER'];
            $password = $_SERVER['PHP_AUTH_PW'];

            $key = $username;

            $allowed_requests_per_period = 12;
            $time_frame_in_seconds       = 10;

            $total_requests = 0;

            if ($redis->exists($key)) {
                $redis->INCR($key);                  
                $total_requests = $redis->get($key);                    

                if ($total_requests > $allowed_requests_per_period) {
                   exit();                   
                }                

            } else {               
                $redis->set($key, 1);
                $redis->expire($key, $time_frame_in_seconds);
                $total_requests = 1;       
            }
}
catch (Exception $e)
{
          
        }

 

 MORE STABLE version

$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$redis->auth('REDIS_PASSWORD');

$max_calls_limit  = 7;
$time_period      = 10;
$total_user_calls = 0;

if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
    $user_ip_address = $_SERVER['HTTP_CLIENT_IP'];
} elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
    $user_ip_address = $_SERVER['HTTP_X_FORWARDED_FOR'];
} else {
    $user_ip_address = $_SERVER['REMOTE_ADDR'];
}

if (!$redis->exists($user_ip_address)) {
    $redis->set($user_ip_address, 1);
    $redis->expire($user_ip_address, $time_period);
    $total_user_calls = 1;
} else {
    $redis->INCR($user_ip_address);
    $total_user_calls = $redis->get($user_ip_address);
    if ($total_user_calls > $max_calls_limit) {
        
        exit();
    }
}

 

 

COMPLETE TUTORIAL

Redis Rate-Limiter

  1. Install the Redis package by typing:

    sudo yum install redis
  2. Once the installation is completed, start the Redis service and enable it to start automatically on boot with:

    sudo systemctl start redissudo systemctl enable redis
    Created symlink from /etc/systemd/system/multi-user.target.wants/redis.service to /usr/lib/systemd/system/redis.service.

    To check the status of the service enter the following command:

    sudo systemctl status redis

    You should see something like the following:

    ● redis.service - Redis persistent key-value database
    Loaded: loaded (/usr/lib/systemd/system/redis.service; enabled; vendor preset: disabled)
    Drop-In: /etc/systemd/system/redis.service.d
            └─limit.conf
    Active: active (running) since Sat 2018-11-24 15:21:55 PST; 40s ago
    Main PID: 2157 (redis-server)
    CGroup: /system.slice/redis.service
            └─2157 /usr/bin/redis-server 127.0.0.1:6379

 

Configure Redis

  1. Open the Redis configuration file in your favorite editor:

    $ sudo nano /etc/redis.conf
    
  2. Set the desired memory capacity for your application.

    maxmemory 512mb
    

    By default, when maxmemory is reached, Redis will stop writing new data. If you want Redis to write new data by removing old data automatically, you have to tell Redis how to remove it. The allkeys-lru eviction policy is a good choice for most users. Add the following line:

    maxmemory-policy allkeys-lru
    

    Learn more about eviction methods here.

  3. Set the save-to-disk policy.

    By default, Redis will save its in-memory data on disk after a specified period or a specified number of write operations against the DB. The default settings are:

    save 900 1
    save 300 10
    save 60 10000
    

    That means saving will occur:

  • after 900 sec (15 min) if at least 1 key changed
  • after 300 sec (5 min) if at least 10 keys changed
  • after 60 sec if at least 10000 keys changed

    With the default settings above, Redis will load the saved data into memory every time it restarts. So your previous in-memory data will be restored. If you don't need this feature, you can disable it entirely by commenting out those lines:

    # save 900 1
    # save 300 10
    # save 60 10000
    

    If you decide to keep this feature, you should upgrade the server to a bigger plan or add an appropriate Linux swap file to ensure that Redis's memory is double the maxmemory declared above. Otherwise, in the worst-case scenario, when the maxmemory is reached, the saving process can cause your server to run out of memory.

  1. Save and close the configuration file, then restart Redis to apply the changes.

    $ sudo systemctl restart redis.service 
    

3. Fine-Tune the System

Check the Redis log file:

tail /var/log/redis/redis.log

 

 |    `-._`-._        _.-'_.-'    |
  `-._    `-._`-.__.-'_.-'    _.-'
      `-._    `-.__.-'    _.-'
          `-._        _.-'
              `-.__.-'

4681:M 28 Feb 19:16:48.584 # Server started, Redis version 3.2.12
4681:M 28 Feb 19:16:48.584 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled.
4681:M 28 Feb 19:16:48.584 * DB loaded from disk: 0.000 seconds
4681:M 28 Feb 19:16:48.584 * The server is now ready to accept connections on port 6379

 

To fix that warning, you need to disable transparent hugepages at boot time before starting the Redis service.

Create a new script file:

nano /usr/bin/disable-transparent-hugepage

Paste the following text into the file:

#!/bin/bash
echo never > /sys/kernel/mm/transparent_hugepage/enabled
exit 0

Save and close the file, then make it runnable and owned by the root account:

chown root:root /usr/bin/disable-transparent-hugepage
chmod 770 /usr/bin/disable-transparent-hugepage

Next, create the configuration file for the systemd service that will call the script at boot time:

nano /etc/systemd/system/disable-transparent-hugepage.service

Paste the following text into the file:

[Unit]
Description=Disable Transparent Huge Pages (THP) for Redis.
Before=redis.service

[Service]
Type=exec
ExecStart=/usr/bin/disable-transparent-hugepage

[Install]
WantedBy=multi-user.target

Save and close the file, then enable the service:

systemctl enable disable-transparent-hugepage.service

4. Verify the Setup

  1. Restart the Redis server:

    reboot
    
  2. After the server restarts, check the Redis log file to ensure there are not any warnings:

    tail /var/log/redis/redis.log
    
  3. Use the redis-cli program to connect to Redis through the default loopback IP 127.0.0.1 and port 6379.

    $ redis-cli -h 127.0.0.1 -p 6379
    

    If the connection succeeds, you will see the Redis command prompt:

    127.0.0.1:6379> 
    
  4. Enter some Redis commands to ensure it works:

    set testkey testvalue
    get testkey
    exit
    

    If you see the following result, then Redis is working correctly.

    127.0.0.1:6379> set testkey testvalue
    OK
    127.0.0.1:6379> get testkey
    "testvalue"
    127.0.0.1:6379> exit
    

5. (Optional) Configure Redis for Private Network Access

If you set up a production environment with multiple servers for your application, the application servers need access to the Redis server. It's recommended to use a private network for safety.

Configure the private network

  1. Follow this guide to enable and configure a private network for this Redis server and the application servers that need to communicate with Redis.
  2. Update the firewalld service to allow incoming connections from the private network:

    $ sudo firewall-cmd --permanent --zone=trusted --change-interface=ens7
    

    iptables -A INPUT -s 10.22.96.3 -p tcp --dport 6379 -j ACCEPT

    
    
  3. Create a systemd service to delay the Redis start-up until the private interface is up and IP address is assigned.

    $ sudo nano /etc/systemd/system/redis.service.d/wait-for-ips.conf
    

    Paste the following text into the file, then save and close it:

    [Unit]
    After=network-online.target
    Wants=network-online.target
    
  4. Edit the Redis configuration file.

    $ sudo nano /etc/redis.conf
    
  5. Add the private IP address that Redis should bind to. For example, if Redis should bind to both the internal loopback (127.0.0.1) and a private IP address (192.168.0.100):

    bind 127.0.0.1 private_ip
    
  6. Save and close the configuration file.

  7. Restart Redis to apply the changes.

    $ sudo systemctl restart redis.service 
    

 

 

Test the private network

  1. Connect to one of your application servers on your private network via SSH.
  2. Assuming the application server is also CentOS 8, temporarily install Redis to get the redis-cli software.

    $ sudo dnf install redis
    
  3. Use the redis-cli program to connect to the Redis server.

    $ redis-cli -h 192.168.0.100 -p 6379
    

    If the connection succeeds, you will see the Redis command prompt:

    192.168.0.100:6379> 
    
  4. Enter some Redis commands to ensure it works:

    set testkey testvalue
    get testkey
    exit
    
  5. If you see the following result, then Redis is working correctly.

    127.0.0.1:6379> set testkey testvalue
    OK
    127.0.0.1:6379> get testkey
    "testvalue"
    127.0.0.1:6379> exit
    
  6. Uninstall the redis package on the application server.

 

Use the redis-cli program to connect to the Redis server.

$ redis-cli -h ip.add.re.ss -p 6379

 

iptables -A INPUT -s 10.22.96.3 -p tcp --dport 6379 -j ACCEPT

 

(probably, the decision to fix staled keys be refreshed) https://www.digitalocean.com/community/tutorials/how-to-set-up-a-redis-s...

Persistence Options

Redis provides two options for disk persistence:

  • Point-in-time snapshots of the dataset, made at specified intervals (RDB).
  • Append-only logs of all the write operations performed by the server (AOF).

Each option has its own pros and cons which are detailed in the Redis documentation. For the greatest level of data safety, consider running both persistence methods.

Because the Point-in-time snapshot persistence is enabled by default, you only need to set up AOF persistence:

  1. Make sure that the following values are set for the appendonly and appendfsync settings in redis.conf:

File: /etc/redis.conf

1
2
appendonly yes
appendfsync everysec
  1. Restart Redis:
sudo systemctl restart redis

 

 

Search for the supervised directive and change it to “systemd”:

# If you run Redis from upstart or systemd, Redis can interact with your

# supervision tree. Options:

#   supervised no      - no supervision interaction

#   supervised upstart - signal upstart by putting Redis into SIGSTOP mode

#   supervised systemd - signal systemd by writing READY=1 to $NOTIFY_SOCKET

#   supervised auto    - detect upstart or systemd method based on

#                        UPSTART_JOB or NOTIFY_SOCKET environment variables

# Note: these supervision methods only signal "process is ready."

#       They do not enable continuous liveness pings back to your supervisor.

 

supervised systemd

Search for the dir directive and set it to /var/lib/redis:

# The working directory.

#

# The DB will be written inside this directory, with the filename specified

# above using the 'dbfilename' configuration directive.

#

# The Append Only File will also be created inside this directory.

#

# Note that you must specify a directory here, not a file name.

dir /var/lib/redis

Once done, save and close the file.

Renaming Dangerous Commands

The other security feature built into Redis allows you to rename or completely disable certain commands that are considered dangerous. When run by unauthorized users, such commands can be used to reconfigure, destroy, or otherwise wipe your data. Some of the commands that are known to be dangerous include:

  • FLUSHDB
  • FLUSHALL
  • KEYS
  • PEXPIRE
  • DEL
  • CONFIG
  • SHUTDOWN
  • BGREWRITEAOF
  • BGSAVE
  • SAVE
  • SPOP
  • SREM RENAME DEBUG

 

nano  /etc/redis.conf

# It is also possible to completely kill a command by renaming it into

# an empty string:

#

rename-command FLUSHDB ""

rename-command FLUSHALL ""

rename-command DEBUG ""

rename-command SHUTDOWN SHUTDOWN_MENOT

rename-command CONFIG ASC12_CONFIG

 

systemctl restart redis.service

 

redis-cli

config get requirepass

Output

(error) ERR unknown command 'config'

 

Use Redis as a Rate Limiter

 

Introduction

Rate limiting is a method of limiting resource usage in your server. For instance, if you're running an API (Application Programming Interface), you may put a cap limiting the number of requests a user can make on your server within a specific timeframe. Controlling the rate of requests made in your web application reduces the risk of DoS (Denial of Service) attack. This allows you to enforce a fair usage policy for your application. In a large-scale web application, limiting operations from exceeding certain constraints also allows you to save huge costs on bandwidth and resource usage.

Prerequisites

To follow along with this guide, ensure you have the following:

1. Install Redis Extension

Log in to your Vultr Ubuntu cloud server and install the php-redis extension. This module allows you to use the Redis Library in PHP code.

$ sudo apt install -y php-redis

Restart the Apache server to load the new configuration.

$ sudo systemctl restart httpd

2. Create a PHP Resource

Create a PHP resource in the root directory of your server.

$ sudo nano /var/www/html/resource.php

Then, add the information below to the file.

<?php 
    try {             
            $redis = new Redis(); 
            $redis->connect('127.0.0.1', 6379); 

            $username = $_SERVER['PHP_AUTH_USER']; 
            $password = $_SERVER['PHP_AUTH_PW'];

            $key = $username;

            $allowed_requests_per_period = 3;
            $time_frame_in_seconds       = 10;

            $total_requests = 0;

            if ($redis->exists($key)) {
                $redis->INCR($key);                  
                $total_requests = $redis->get($key);                    

                if ($total_requests > $allowed_requests_per_period) {
                   echo "Hey, " . $username . ", You've already reached your requests limit. Total requests " 
                         . $total_requests . " Allowed requests " . $allowed_requests_per_period;
                   exit();                   
                }                

            } else {               
                $redis->set($key, 1); 
                $redis->expire($key, $time_frame_in_seconds); 
                $total_requests = 1;       
            } 

            echo "ok, total requests " . $total_requests;            

        } catch (Exception $e) {
            echo $e->getMessage();
        }
?>

When you finish editing the file, save and close it by pressing CTRL + X, Y then ENTER.

The /var/www/html/resource.php code explained:

$redis = new Redis(); 
$redis->connect('127.0.0.1', 6379); 

You've used the above code to connect to a Redis server on your localhost via port 6379.

$username = $_SERVER['PHP_AUTH_USER']; 
$password = $_SERVER['PHP_AUTH_PW'];

When you've configured PHP to run as an Apache module, the $_SERVER['PHP_AUTH_USER'] and $_SERVER['PHP_AUTH_PW'] variables assign the HTTP Basic Authentication credentials to the $username and $password variables respectively.

$key = $username;

Because you might have many users accessing your web resource, creating a Redis key with the $username variable retrieved from the $_SERVER['PHP_AUTH_USER'] variable allows you to track the traffic of each user independently.

$allowed_requests_per_period = 3;
$time_frame_in_seconds       = 10;

The two variables above allow you to limit your web resource requests depending on the set usage policy in your application. This example limits users to 3 requests in 10 seconds. Adjust these values depending on your needs.

$total_requests = 0;

You've initialized the total requests made by a user using the $total_requests variable.

if ($redis->exists($key)) {
     $redis->INCR($key);                  
     $total_requests = $redis->get($key);                    

     if ($total_requests > $allowed_requests_per_period) {
         echo "You've already reached your requests limit. Total requests " 
         . $total_requests . " Allowed requests " . $allowed_requests_per_period;
         exit();                   
     }                

 } else {               
     $redis->set($key, 1); 
     $redis->expire($key, $time_frame_in_seconds); 
     $total_requests = 1;       
 } 

The code above checks for the existence of the $key variable on the Redis server. If the key exists, you are incrementing it by 1 using the $redis->INCR($key) command. If the key does not exist, you are setting a new key with a default value of 1 using the $redis->set($key, 1) command as well as the expiration period defined by the $time_frame_in_seconds variable. Next, you are accessing the current count of the $key key using the $redis->get($key). Once the value is retrieved, you're assigning it to the $total_requests variable.

Then, you're using the PHP logic if...else syntax to evaluate if the client has exceeded the total requests allowed during the period defined. If the limit is exceeded, you're raising an error to the user.

echo "ok, total requests " . $total_requests; 

Towards the bottom of the file, you're echoing the number of requests made by the user if they've not exceeded their limit.

3. Test the Redis Rate Limiter

Open a command prompt on your server and use the curl command to query the /var/www/html/resource.php web resource that you have created above. The dummy query string ?[1-20] at the end of the http://localhost/resource.php URL allows you to access the resource 20 times to see if the script will be rate-limited by the Redis server.

$ curl http://localhost/resource.php?[1-20]

After running the above code, you should get the below output.

[1/20]: http://localhost/resource.php?1 --> <stdout>
--_curl_--http://localhost/resource.php?1
ok, total requests 1
[2/20]: http://localhost/resource.php?2 --> <stdout>
--_curl_--http://localhost/resource.php?2
ok, total requests 2
[3/20]: http://localhost/resource.php?3 --> <stdout>
--_curl_--http://localhost/resource.php?3
ok, total requests 3
[4/20]: http://localhost/resource.php?4 --> <stdout>
--_curl_--http://localhost/resource.php?4
Hey, , You've already reached your requests limit. Total requests 4 Allowed requests 3
[5/20]: http://localhost/resource.php?5 --> <stdout>
--_curl_--http://localhost/resource.php?5
Hey, , You've already reached your requests limit. Total requests 5 Allowed requests 3
...

Notice that the first three requests are accepted. However, the PHP script started throwing a rate-limit error beginning at the fourth request.

Private Network

ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 137.220.55.24  netmask 255.255.254.0  broadcast 137.220.55.255
        inet6 2001:19f0:b001:652:5400:3ff:fe36:121c  prefixlen 64  scopeid 0x0<global>
        inet6 fe80::5400:3ff:fe36:121c  prefixlen 64  scopeid 0x20<link>
        ether 56:00:03:36:12:1c  txqueuelen 1000  (Ethernet)
        RX packets 569  bytes 54267 (52.9 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 446  bytes 86970 (84.9 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

eth1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1450
        inet 10.22.96.3  netmask 255.255.240.0  broadcast 10.22.111.255
        inet6 fe80::5800:3ff:fe36:121c  prefixlen 64  scopeid 0x20<link>
        ether 5a:00:03:36:12:1c  txqueuelen 1000  (Ethernet)
        RX packets 3  bytes 390 (390.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 81  bytes 12702 (12.4 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

 

nano /etc/sysconfig/network-scripts/ifcfg-eth1


# Private network: net603b78f8af125
DEVICE=eth1
ONBOOT=yes
BOOTPROTO=static
IPADDR=10.22.96.3
NETMASK=255.255.240.0
MTU=1450

 

ifup eth1

service network restart

 

 

Configure Redis

In this step, we're going to configure our Redis Server installation on the CentOS 7 server.

Edit the Redis configuration file '/etc/redis.conf' using vim editor.

vim /etc/redis.conf

Now change 'bind' address with your internal IP address. If you're running as a cluster, you can change with the private IP address. It's recommended to run the Redis Server on private internal IP address.

bind 127.0.0.1

 

The Network security for redis server is related with the 'bind' configuration on the redis configuration 'redis.conf'. It's recommended to use the internal private network for your Redis installation and don't use the public.

On the 'bind' section, change the IP address with your own internal network IP address.

bind INTERNAL-IP-ADDRESS

Save and close.

And now the redis service will run under the 'INTERNAL-IP-ADDRESS'.

 

Now change the 'daemonize' value to 'yes', because we will run the Redis service as a daemon.

daemonize yes

Since we're using the CentOS 7 server and systemd, so we need to change the 'supervised' line configuration to 'systemd'.

supervised systemd

Save and close.

Now restart the redis service.

systemctl restart redis

The basic configuration of the Redis Server has been completed. Now connect to the Redis Server using the redis-cli command as below.

redis-cli

Run the ping command below.

ping
ping "Hello Redis"

If your installation is correct, you will get the 'PONG' reply and the message that you write after the command.

redis-cli
127.0.0.1:6379> ping
PONG
127.0.0.1:6379> ping "Hello Redis"
"Hello Redis"
127.0.0.1:6379>

 

 

Password Authentication

The password authentication for Redis will give you access control to your Redis server. This is a little layer of security that will enhance your Redis server security, and it is not yet enabled by default installation.

To enable the Password Authentication for Rediser server, you will need to uncomment the 'requirepass' section on the 'redis.conf' file and type your strong password after it.

requirepass hakase-labs321@#$

Change the 'hakase-labs321@#$' with your strong password. And now the password authentication for Redis has been enabled.

3. Disabling Dangerous Redis Command

Redis provides a feature for disabling some specific Redis command. This feature can be used to rename or disable some of the dangerous commands such as 'FLUSHALL' for erasing all data, 'CONFIG' command to setup configuration parameter through the Redis CLI, etc.

To change or disable the Redis command, you can use the 'rename-command' option. Edit the redis configuration file 'redis.conf' and add some configurations below.

# rename-command COMMAND "CUSTOM"
rename-command CONFIG "REDISCONFIG"
rename-command FLUSHALL "DELITALL"

Save and close.

Once all is complete, restart the redis service using the systemctl command below.

systemctl restart redis

And the basic Redis security for securing Redis installation has been applied to our host.

 

 

Delete default or currently selected database (usually `0) with

redis-cli flushdb

Clear SPECIFIC

Delete specific redis database with (e.g. 8 as my target database):

redis-cli -n 8 flushdb 

Clear ALL

Delete all redis databases with

redis-cli flushall
Tags: