Friday, 14 October 2016

Renaming Redis Commands and executing Monitor command after renaming.

Renaming commands is one of the important steps to secure your redis instance. It is particularly important to rename commands like
FLUSHDB, FLUSHALL, KEYS, CONFIG, RENAME, MONITOR, SHUTDOWN.

Most of the commands work as expected after renaming. However, the command MONITOR behaves a bit differently.
Here, we have a look at why it behaves differently and what can be done to counter it.

Lets fire up our redis instance on default port 6379 by navigating into redis directory and executing src/redis-server redis.conf




Now, open another command prompt and try to insert some data continuously by executing the below.
while true ; do src/redis-cli set testMonitorKey testMonitorValue ; sleep 1; done


The above will keep on inserting a key in redis. Lets let it run without stopping.

Lets see whether we can use monitor command from redis-cli.
This is done by executing src/redis-cli MONITOR


We can see that the MONITOR command is able to monitor the traffic on the redis instance.
So, monitor command works as expected when it is not renamed.

Now, lets rename the MONITOR command to "EAVESDROP"(or anything else) in redis.conf file.
After that we need to restart the redis server,





Now, lets try to execute monitor command, both original and renamed command(eavesdrop)
src/redis-cli MONITOR
src/redis-cli EAVESDROP


Although MONITOR command gives the error that it is unknown(since we renamed it), it is strange because the terminal waits for the other output!!!
Also, EAVESDROP command just returns OK and does nothing else!!!

One wonders why.
Lets give it another shot.
Lets go inside the redis-shell using redis-cli and execute EAVESDROP and MONITOR separately.


It works!!!! YAY!!!

The issue is that for MONITOR to work properly, both client and server should know that the client has asked for monitoring, so that the client can keep on listening to whatever the server has to feed it.

This can be seen in the redis-cli.c file in redis codebase, that redis-cli listens to MONITOR command.


Now if we rename it at the server, we either need to rename it at the client or send the renamed command to the server and MONITOR command to the client.


When we execute two separate commands like "redis-cli EAVESDROP" and "redis-cli MONITOR", it executes these commands in two separate sessions of redis-cli
Now, when we renamed the MONITOR command to "EAVESDROP", we changed the state at the server but not the client(redis-cli)
When we executed the eavesdrop command, it sent the request to the server to send the data to this client.
However, only after we executed the MONITOR command on redis-cli client, that it was able to listen to it.

But the problem is that the redis-cli shell does not output to a file. What if we have a large number of commands being executed on redis and we want the output to be redirected to a file, so that we can search it easily(or view the tail).
In that case, we should make sure that only one instance of redis-cli should execute both these commands and output it to a file.

This can be done, by creating a file(rename.txt here) and feeding it as input to redis-cli and redirecting the output to an output file.

cat rename.txt 
cat rename.txt | redis-cli > runningCommands.out


Also, in another terminal, look at the output of runningCommands.out using 
tail -f runningCommands.out


So, finally we were able to solve the issue of monitoring the commands in redis-cli after renaming the MONITOR commands. :)