Django运维系统基础功能之---web远程ssh终端录像回放

背景

趁着昨天实现了基础的运维系统功能,那就趁着劲还在!继续补充一个web远程ssh终端录像回放功能。

一、思路

网上找了一下大家实现webssh录像回放的方案,度娘搜的文章统一都是—用asciinema!仔细看了相关技术文档之后确实阿!我一开始以为需要视频文件。没想到,asciinema用特定的格式文件就可以实现视频流。(在写asciinemaweb技术的时候有个大坑- -.琢磨我两个小时,待会说具体问题)

asciinema实际就是 通过系统输出的信息,将信息写成asciinema特定的格式文件,包含header与data两大部分(也是待会从文章中讲解两部分的结构)。它就能解析成视频。所以我们在昨天的功能逻辑之上:
1.连接ssh成功后,构造头部内容写入文件中
2.将开头两条输出信息以特定的格式写入文件中
3.将线程监听回来的所有输出信息以特定的格式写入文件中
其中2.3已经包含了我们webssh所有的输出信息了,已经足以构成录像回放
4.创建html页面展示回访列表

二、实现

先说明一下asciinema文件的格式。
头部:

    header = {
        "version": 2,  #(asciinema)版本
        "width": 160, #(asciinema)回放时的宽度
        "height": 48, #(asciinema)回放时的高度
        "timestamp": date, #(asciinema)时间戳 用于播放
        "env": {"SHELL": "/bin/bash",  #(asciinema)使用的shell类型
        "TERM": "xterm-256color"}, #(asciinema)终端颜色
        "title": "video"  #(asciinema)标题
    }

data:

[0.00699162483215332, "o", "Last login: Thu May  7 18:42:13 2020 from 192.168.254.1\r\r\n"]
[0.1905069351196289, "o", "[root@leestudy ~]# "]  #第一个字段为时间戳,第二个字段“o”为输出,“i”为输入,第三个字段为“(o)输出信息/(i)输入信息”

1.连接ssh成功后写入header

            sshsession = client.get_transport().open_session()
            sshsession.get_pty()
            sshsession.invoke_shell()

            asciinemadir = settings.BASE_DIR + '/static/asciinemadir/' #定义一个存放文件的目录(喜欢的也可以保存在数据库)
            if not os.path.isdir(asciinemadir):
                os.makedirs(asciinemadir)
            starttime=time.strftime("%Y%m%d%H%M%S") #用于记录开始时间
            filena =ip+starttime         #文件名,用ip+开始时间为文件名
            date=time.time()             #开始时间戳
            print(date)
            header = {
                "version": 2,
                "width": 160,
                "height": 48,
                "timestamp": date,   #开始时间戳
                "env": {"SHELL": "/bin/bash",
                "TERM": "xterm-256color"},
                "title": "video"
            }

            writedata= open(asciinemadir + filena, 'w') #打开文件
            writedata.write(json.dumps(header) + '\n')  #将header写入文件

2.将开头两条输出信息以特定的格式写入文件中

            for i in range(2):
                messa = sshsession.recv(1024)
                request.websocket.send(messa)  
                demessa = messa.decode('utf-8')
                iodata = [time.time() - date, 'o', f'{demessa}'] #构造格式
                writedata.write(json.dumps(iodata)+'\n') #写入文件

3.将线程监听回来的所有输出信息以特定的格式写入文件中

            def srecv():
                while True:
                    sshmess = sshsession.recv(2048)
                    if not len(sshmess):
                        print('退出监听发送循环,并关闭写入文件')
                        writedata.close()   #如果不再监听通道,则关闭文件
                        break
                    request.websocket.send(sshmess)
                    print('ssh回复的信息:' + sshmess.decode('utf-8'))
                    print(len(sshmess))
                    desshmess = sshmess.decode('utf-8')
                    iodata2 = [time.time() - date, 'o', f'{desshmess}']#构造格式
                    writedata.write(json.dumps(iodata2) + '\n')#写进文件

4.创建html页面展示回访列表
在创建html前需要创建一个新的表用于存放录像列表的信息
models下:

class video(models.Model):
    hostaddress = models.CharField(max_length=255)
    username = models.CharField(max_length=255)
    filename = models.CharField(max_length=255)
    starttime = models.CharField(max_length=255)
    overtime = models.CharField(max_length=255)

然后进行数据库记录与迁移(python manage.py makemigrations与python manage.py migrate)

接着在关闭websocket时创建一条数据,并且在关闭websocket时也关闭文件
判断是否关闭只要用try异常机制即可.

        except:
            addvideolist = models.video()
            addvideolist.hostaddress = ip
            addvideolist.username = request.session['username']
            addvideolist.filename = filena
            addvideolist.starttime = starttime
            addvideolist.overtime = time.strftime("%Y%m%d%H%M%S")
            addvideolist.save()
            writedata.close()
            print('中断websocket,关闭文件写入')

接着创建html页面展示回放:
(坑了我两个小时的就是这个asciinemaplayer的js文件,在网上找了很多的asciinemaplayerjs文件,统统都不行!解析不出来!(解坑前根本不知道是JS的问题!)连官方下载的demo都解析不出来,全是在比较大型的网站下的- -.然后我看了下官网(https://asciinema.org/)里面的展示都可以解析的啊!demo都一毛一样!然后索性找了一个demo的首页,点开F12直接找它的js算了!!结果一引用,成了。我靠!!也不知道是不是我的问题)最后给上jshttps://asciinema.org/js/asciinema-player-e90dd959bf7df7e1608c08ac419fca67.js?vsn=d

现在视图中创建页面函数:

def Videotape(request):
    videolist = models.video.objects.all()
    return render(request, 'html/Videotape.html', locals())

然后再编写html页面
直接把html贴出来吧!(引用了AdminLte模板)

{% extends 'base.html' %}
{% load static %}
{% block title %}录像{% endblock %}
{% block css %}
     <link rel="stylesheet" href="{% static 'adminlet-2.4.10/bower_components/datatables.net-bs/css/dataTables.bootstrap.css' %}">
    <link rel="stylesheet" href="{% static 'asciinemaplayer/asciinema-player.css' %}">
{% endblock %}

<!-- 顶部内容  -->
{% block breadcrumb %}
    <!-- Content Header (Page header) -->
    <section class="content-header">
      <h1></h1>
    </section>
{% endblock %}

<!-- 身体内容  -->
{% block content %}

    <!-- playvideo模态框 -->
<div class="modal fade bs-example-modeal-lg" id="playvideo" tabindex="-1" role="dialog" aria-labelledby="playvideoLabel">
  <div class="modal-dialog modal-lg" role="document">
    <div class="modal-content">
      <div class="modal-header">
        <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
        <h4 class="modal-title" id="addhostlLabel">录像播放</h4>
      </div>
      {% csrf_token %}
      <div class="modal-body">
          <div class="modal-body" id="play">
      </div>


      </div>

      <div class="modal-footer">

      </div>
    </div>
  </div>
</div>




    <!-- datatable -->
      <div class="box box-default">

        <div class="box-header with-border">
          <h3 class="box-title">录像列表</h3>
        </div>

        <div class="box-body">
    <table id="Videolist" class="display" style="width:100%">
                    <thead>
            <tr>
              <th>主机地址</th>
              <th>操作人</th>
              <th>录像文件名</th>
              <th>开始时间</th>
              <th>结束时间</th>
              <th>操作</th>
            </tr>
            </thead>
            <tbody>
          {% for videoli in videolist %}
              <tr>
              <td>{{ videoli.hostaddress }}</td>
              <td>{{ videoli.username }}</td>
              <td>{{ videoli.filename }}</td>
              <td>{{ videoli.starttime }}</td>
              <td>{{ videoli.overtime }}</td>
              <td><input type="button" value="查看录像" style="float: left" class="btn btn-success" onclick="play('{{videoli.filename}}')"/></td>
              </tr>
            {% endfor %}
            </tbody>
    </table>
        </div>
      </div>





{% endblock %}

<!-- JS内容  -->
{% block script %}
<script src="{% static 'adminlet-2.4.10/bower_components/datatables.net/js/jquery.dataTables.min.js' %}"></script>
<script src="{% static 'adminlet-2.4.10/bower_components/datatables.net-bs/js/dataTables.bootstrap.min.js' %}"></script>
<script src="{% static 'asciinemaplayer/asciinema-player-e90dd959bf7df7e1608c08ac419fca67.js' %}"></script>
    <script type="text/javascript">
    //datatable配置
    $(document).ready(function() {
    $('#Videolist').DataTable({

       language: {
           "sProcessing": "处理中...",
           "sLengthMenu": "显示 _MENU_ 项结果",
           "sZeroRecords": "没有匹配结果",
           "sInfo": "显示第 _START_ 至 _END_ 项结果,共 _TOTAL_ 项",
           "sInfoEmpty": "显示第 0 至 0 项结果,共 0 项",
           "sInfoFiltered": "(由 _MAX_ 项结果过滤)",
           "sInfoPostFix": "",
           "sSearch": "搜索:",
           "sUrl": "",
           "sEmptyTable": "表中数据为空",
           "sLoadingRecords": "载入中...",
           "sInfoThousands": ",",
           "oPaginate": {
               "sFirst": "首页",
               "sPrevious": "上页",
               "sNext": "下页",
               "sLast": "末页"
           },
           "oAria": {
               "sSortAscending": ": 以升序排列此列",
               "sSortDescending": ": 以降序排列此列"
           }
       },
          "paging": true,       <!-- 允许分页 -->
          "lengthChange": true, <!-- 允许改变每页显示的行数 -->
          "searching": true,    <!-- 允许内容搜索 -->
          "ordering": true,     <!-- 允许排序 -->
          "info": true,         <!-- 显示信息 -->
          "autoWidth": false

    });
} );



// 播放录像
function play(file) {
  $('#play').html(
    '<asciinema-player id="play" src="/static/asciinemadir/'+file+'"></asciinema-player>'
  )
  $('#playvideo').modal('show');
}

    </script>
{% endblock %}

5.最终效果
在这里插入图片描述

结束

好啦,Django运维系统基础功能之—web远程ssh终端录像回放的功能就先到这里咯。后面的功能再慢慢补充吧~

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
Python-Django 是一个流行的 Web 开发框架,而多功能 Web 应用渗透测试系统则是指的一个系统能够对各种不同类型的 Web 应用进行渗透测试,同时还具备多种功能Python-Django 的优势在于其简单易用、灵活性高以及开发效率高。使用 Python-Django 开发一个多功能 Web 应用渗透测试系统具备以下几个方面的优势: 1. 强大的渗透测试功能Python-Django 可以实现对 Web 应用中可能存在的漏洞进行渗透测试,比如 SQL 注入、跨站脚本攻击等,提供了一系列的工具和库来实现这些功能。 2. 可扩展性:Python-Django 框架本身就具备良好的可扩展性,可以根据实际需求添加新的功能或模块,满足不同用户的要求。 3. 用户权限管理:Web 应用渗透测试系统需要具备用户权限管理的功能,以便不同用户可以根据其角色进行权限管理和操作。Python-Django 提供了丰富的用户认证和授权机制,可以很方便地实现用户权限管理。 4. 数据库支持:Web 应用渗透测试系统需要对各种渗透测试数据进行存储和管理,Python-Django 提供了对多种数据库的支持,如 MySQL、SQLite、PostgreSQL 等,可以根据实际需要选择合适的数据库。 综上所述,使用 Python-Django 开发一个多功能Web 应用渗透测试系统可以实现强大的渗透测试功能,具备良好的可扩展性和用户权限管理,并提供了丰富的数据库支持。这将使得渗透测试人员可以更加高效和便捷地进行各种类型的渗透测试工作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值