当前位置: 首页 > 工具软件 > Sysdig Falco > 使用案例 >

Sysdig chisels 开发

夹谷星河
2023-12-01

Chisels

Sysdig 的 chisels 是通过分析sysdig 事件数据流去完成特定动作的小脚本。在Sysdig中,系统事件events 被高效地呈现在了用户空间,所以脚本能够直接被应用到处理事件上。好处如下:

  • 能使用普遍被使用的而不是定制的语言。sysdig的chisels 使用 Lua 脚本语言。
  • Chisels 能很方便地使用众多的Lua库
  • Chisels 在实时系统上工作情况良好,但也能和捕获的文件一起来完成离线的分析工作。

使用

  • 列出可所有使用的chisels
    $ sysdig -cl
  • 输出某个chisel 的详细描述和参数列表,使用 -i 命令行选项
    $ sysdig -i spy_ip
  • 运行某个chisel 工具,使用 -c 选项
    $ sysdig -c topfiles_bytes
  • chisel工具需要参数时,直接在后面补充
    $ sysdig -c spy_ip 192.168.1.157
  • 能够同时运行多个chisel工具
    $ sysdig -c stding -c stdout proc.name=cat
  • chisels 可以和过滤器filters 结合使用
# 不需要对 /dev 的访问
$ sysdig -c topfiles_bytes "not fd.name contains /dev"
# 只包含 /root 路径的访问
$ sysdig -c topfiles_bytes "fd.name contains /root"
# 进程 vi 访问的文件
$ sysdig -c topfiles_bytes "proc.name=vi"
# 用户 loris 访问的文件
$ sysdig -c topfiles_bytes "user.name=loris"

注意:
使用filters时,我们需要注意它是作为sysdig的还是chisels的参数传入

$ sysdig -i lsof
...
Args:
[filter] filter - A sysdig-like filter expression that allows r
                estricting the FD list. E.g. 'proc.name=foo and fd.name contain
                s /etc'.

当作为chisels参数传入时,如上面的lsof,当有多个筛选条件,如sysdig -c lsof "'user.name=phil or proc.name=sshd'",这里是需要双重引号的。
当作为sysdig参数传入,当有多个筛选条件,如:sysdig "fd.rip=54.165.81.189 and fd.port=6666",这时候是可加双引号的
更多规则使用可参考https://sysdig.com/blog/linux-troubleshooting-cheatsheet/#lsof

开发自定义Chisel

Sysdig chisels 使用Lua 语言编写,如果不熟悉,可以参考Programming in LuLua reference manual

Chisels 脚本结构
--[[
Lua 脚本如果要想被sysdig 识别,必须要定义以下几个全局变量
description
short_description
category
args:包含参数的列表,可为空
以上这些参数都会被sysdig识别并添加在chisels信息中(使用 sysdig -cl / sysdig -i chisels_name)
--]]
-- Chisel description
description = "counts how many times the specified system call has been called"
short_description = "syscall count"
category = "misc"

-- Chisel argument list
args =
{
    {
        name = "syscall_name",
        description = "the name of the system call to count",
        argtype = "string"
    },
}

--[[
当需要给chisels传递参数时,用参数信息补充arg 表和增加 on_set_arg()函数。sysdig收集到命令行参数时,接着传入并调用 on_set_arg函数。当有多个参数时,可使用不同的name来区分开来。
--]]
-- Argument notification callback
function on_set_arg(name, val)
    syscallname = val
    return true
end

--[[
chisel 初始化函数,在收到第一个事件前执行。
以下代码使用了chisel.request_field去提取需要的ftype和fdir字段的地址,方便后面根据这两个字段去筛选事件
--]]
-- Initialization callback
function on_init()

    -- Request the fields that we need
  -- 以下变量为userdata类型,猜测存储了c/c++中指针类型数据
    ftype = chisel.request_field("evt.type")
    fdir = chisel.request_field("evt.dir")

  -- set the filter
  -- 通过chisels使用sysdig引擎来优化筛选事件
    chisel.set_filter("evt.type=" .. syscallname .. " and evt.dir = >")

  --[[
  可以通过print()自定义事件通知,可以使用以下定义通知格式
  ""相当于"default"
  chisel.set_event_formatter("")
  --]]

    return true
end

count = 0

-- Event parsing callback
-- 每当一个事件到来都会触发该函数的执行
function on_event()
  count = count + 1
    return true
end

--[[
捕获结束时的动作,一般用于通知操作
结束的情况:
离线捕获中收到最后一个数据包
实时捕获中按下CTRL+C
--]]
-- End of capture callback
function on_capture_end()
    print(syscallname .. " has been called " .. count .. " times")
    return true
end

Chisels API

Chisels 通过以下三种独立的接口与sysdig 交流

  • Callbacks 回调函数的集合
  • sysdig library 与主程交互的函数库
  • evt library 用来从捕获的事件中提取信息
强制的变量

为了能被识别为Chisels,Lua 脚本中必须包含以下全局变量:

  • description: 对该chisel 详细的描述 字符串类型
  • short_description: 简略描述,字符串类型
  • category: chisel 所属的目录,如 IO,net,security,字符串类型
  • args: 描述每一个chisel参数,table表格类型
args =
{
    {
        name = "name1",
        description = "description1",
        argtype = "ipv4"
        optional = false
    },
    {
        name = "name2",
        description = "description2",
        argtype = "string"
        optional = true
    },
}

注意:

  • args 中 optional设为"false",sysdig 命令行的chisel 名字后面必须指定这个参数,否则执行失败
  • args 中的每一个参数都会生成一个对on_set_arg() 的调用
  • args 可为空
  • 参数列表中有不止一个参数时,可用 "" 概括。如 sysdig -c chisel_name "arg1 arg2 arg3"
Callbacks

Callbacks 是sysdig 用来通知chisel 事情发生时的方式。除了on_interval() 需要使用sysdig.set_interval_s() 或者 sysdig.set_interval_ns()注册,大多数callbacks 不需要注册。Callbacks 是可选的,不需要则不用加上。

on_set_arg(name, val)
args 表中的每一个参数都会调用该函数。name 是参数设置的名字,val 是用户在命令行给出的值。
参数无效时会返回false并导致sysdig退出。

on_init()
在所有参数的on_set_arg()都调用后但capture被配置前被调用。通常,用来初始化chisel工具。
chisel 初始化失败返回false并导致sysdig退出

on_capture_start()
在capture配置后、on_set_arg被调用后,但在事件的数据包被捕获之前调用。能在需要询问capture状态时的最终初始化chisel步骤中使用
chisel 初始化失败返回false并导致sysdig退出

on_event()
在没有设置set_filter() 或者通过set_filter()筛选后,每个被捕获的事件到达都会激活该函数。这个函数常用来写核心的chisel逻辑,需要保证代码是高效可用的。在这个回调函数中,开发者可以对evt library访问,从而从正在处理的事件中提取信息。
在指定了格式工具(set_event_formatter)的情况下,返回false会让工具忽略该次事件。

on_capture_end(ts_s,ts_ns,delta)
捕获结束时的动作,一般用于通知操作。结束的情况如下:

  • 离线捕获中收到最后一个数据包
  • 实时捕获中按下CTRL+C
    参数含义如下:
  • ts_s,ts_ns: 最后收到事件的时间戳的秒(以秒的单位表示当前时间)和纳秒部分
  • delta:捕获的第一个包到最后一个包的间隔时间,纳秒表示

on_interval(ts_s,ts_ns,delta)
周期性的超时的回调函数。可以用来以一定频率如每秒一次报告信息。使用chisel.set_interval_s() 或者 chisel.set_interval_ns()配置。参数含义如下:

  • ts_s, ts_ns:函数被调用的时间,秒+纳秒表示
  • delta:被调用的间隔时间
sysdig library

这个库里面的函数可以用来设置全局的sysdig配置

sysdig.end_capture()
这个调用会让sysdig停止接受事件,然后‘makes it initiate the end of capture cleanup’(不太理解),感觉就是准备结束sysdig,开始清理捕获动作的相关环境。

sysdig.get_machine_info()
返回一个带有产生事件的机器的信息的表(table类型),表有以下字段:

  • num_cpus: 机器上的CPU核心的编号
  • memory_size_bytes:机器RAM的大小
  • max_pid:机器允许的最大PID数值
  • hostname:机器主机名
    注意:这个调用对文件捕获也同样有效,因为机器信息存储在跟踪文件(sysdig -w output.scap)上。这种情况下,返回的机器信息是捕获发生的其中一个机器。

sysdig.get_filter()

返回在命令行传递给sysdig的包含filter的字符串
sysdig.get_evtsource_name()
返回包含事件源名字的字符串。跟踪文件名(如果事件来源于一份跟踪文件)或者""(如果是实时捕获)

sysdig.get_output_format()
返回用户在命令行规定的输出格式,返回值可以是"normal"或者"json"

sysdig.is_print()_container_data
返回Boolean类型,表示是否使用了-pc 或者 -pcontainer 选项。

sysdig.get_container_table(filter)
返回sysdig container table
filter可以选择性地作为输入参数传递,用来限制返回的元素。语法与常规sysdig filters相同,但仅限于fd,proc,user和group filter类型。
返回以下值:

  • id:容器id,唯一标识符
  • name:容器名字
  • images:容器镜像
  • type:容器类型(docker,lxc,& libvirt_lxc)
    注意:
    container.id==host 且/或者 container.name == host 表示是主机而不是容器

sysdig.get_thread_table(filter)
返回sysdig process table。filter使用与get_container_table 相同。
返回值过多,建议参考官网资料。

sysdig.is_tty()
返回是否sysdig运行在有ANSI功能的交互终端,能被chisel用来决定是否有可能在屏幕上显示颜色

sysdig.islive()
返回当前的捕获是否实时的,即事件是来自系统还是个跟踪文件

sysdig.run_sysdig(args)
从目前执行的sysdig退出,然后再启动一个新的,参数由args传递。chisel 能用它来运行另一个不同的捕获或者再一次启动sysdig去完成不同的任务(如 保存特定事件到文件中)

sysdig.set_fatfile_dump_mode(mode)
开启/禁用 fatfile 模式。mode 参数是个Boolean值。

sysdig.set_filter(filter)
在解析事件前,将filter过滤器配置到sysdig引擎中。和在命令行中设置filter的作用是一样的,且会覆盖命令行的参数。

sysdig.set_snaplen(snaplen)
设置I/O类型的系统调用(如 read,write,sendto,recvform)的buffers的字节数。

chisel library

这个库里面的函数与设置chisel环境最相关,经常在初始化的时候被调用,例如 on_init()

chisel.exec(chiselname, arg1, arg2, ...)
这个函数能被用来停止正在调用的chisel的执行,转而去运行一个不同的chisel

chisel.request_field(fld_name)
这个函数用来在事件被捕获的时候提取一个filter字段。fld_name 是将要去提取的sysdig filter 字段(sysdig 教程或者sysdig -l 可看所有可用的字段)。函数返回字段的句柄,该句柄能用在 evt.field() 以在on_event()回调函数中获得字段的值。

chisel.set_filter(filter)
设置sysdig 引擎,在chisel的on_event()调用处理事件前使用给出的filter过滤事件。
注意:

  • set_filter 设置的filter 只对当前的chisel有效
  • 每个chisel 只能设置一个,调用两次将会导致第一次被覆盖
  • 应该尽可能地使用filters。sysdig 引擎做了大量优化,所以尽可能地减少到达chisel 的on_event()前的事件能使chisels更高效

chisel.set_event_formatter(format)
配置事件的格式工具。format 变量是一个包含将要打印的字段列表的字符串,符号使用和命令行选项 -p 一致。
默认情况下,chisel 没有事件格式工具,它们可以使用Lua 的print() 函数任意输出。设置了格式工具,可以利用sysdig 的过滤字段系统(filter fields system)去替你格式化地输出信息。"default"或"", sysdig 添加它的默认格式到chisel。on_event() 返回true 的时候才会打印信息,且chisel 的输出不会被命令行-p 选项覆盖。

chisel.set_interval_s(interval)
为当前chisel 设置一个周期性的调用。使用这个函数,需要chisel 包含on_interval()函数,sysdig 引擎会以interval 秒的间隔循环调用

chisel.set_interval_ns(interval)
和set_interval_s 类似,不过更精细的时间设置

evt library

这个库的函数有关于正在被处理的事件,所以只能被 on_event() 函数调用

evt.get_cpuid()
返回捕获到事件的CPU的编号

evt.field(fld)
从事件中提取特定特定字段的值。参数fld是从上一个requet_field()调用中获得的字段句柄。函数返回字段的值,可能是个数字或者字符串。sysdig -lv 命令可以查看每个导出字段的类型。
注意:

  • 如果请求的字段没有被事件导出(例如非I/O事件不会导出fd.name 字段),返回值为 nil (Lua 中表示只有一个值的一种类型)
  • evt.rawarg 字段需要注意。它能用来提取任意系统调用的参数,如 evt.rawarg.res,所以它的类型取决于你询问的字段

evt.get_num()
返回递增的事件编号

evt.get_ts()
返回两个分别代表事件原始时间戳的秒和纳秒部分的时间戳

evt.get_type()
以数字形式返回事件类型。能用来事件过滤。事件类型编码可以在driver/ppm_event_events_public.h的ppm_event_type 枚举中查看
参考资料:
https://github.com/draios/sysdig/wiki/Chisels-User-Guide
https://github.com/draios/sysdig/wiki/Writing-a-Sysdig-Chisel%2C-a-Tutorial
https://github.com/draios/sysdig/wiki/Sysdig-Chisel-API-Reference-Manual

 类似资料: