Files
kyanos/agent/agent_test.go
2025-01-13 01:00:21 +08:00

1220 lines
39 KiB
Go

package agent_test
import (
"fmt"
ac "kyanos/agent/common"
"kyanos/agent/compatible"
"kyanos/agent/conn"
"kyanos/bpf"
"kyanos/common"
"os"
"testing"
"time"
"github.com/cilium/ebpf/link"
"github.com/stretchr/testify/assert"
)
var customAgentOptions ac.AgentOptions = ac.AgentOptions{}
func TestMain(m *testing.M) {
// call flag.Parse() here if TestMain uses flags]
customAgentOptions = ac.AgentOptions{}
retCode := m.Run()
tearDown()
os.Exit(retCode)
}
func tearDown() {
// Do something here.
time.Sleep(1 * time.Second)
fmt.Println("teardown!")
}
func TestConnectSyscall(t *testing.T) {
connEventList := make([]bpf.AgentConnEvtT, 0)
agentStopper := make(chan os.Signal, 1)
StartAgent(
[]bpf.AttachBpfProgFunction{
bpf.AttachSyscallConnectEntry,
bpf.AttachSyscallConnectExit,
},
&connEventList,
nil,
nil,
nil,
agentStopper)
defer func() {
agentStopper <- MySignal{}
}()
fmt.Println("Start Send Http Request")
sendTestHttpRequest(t, SendTestHttpRequestOptions{disableKeepAlived: true, targetUrl: "http://www.baidu.com"})
time.Sleep(1 * time.Second)
if len(connEventList) == 0 {
t.Fatalf("no conn event!")
}
connectEvent := findInterestedConnEvent(t, connEventList, FindInterestedConnEventOptions{
findByRemotePort: true,
findByConnType: true,
remotePort: 80,
connType: bpf.AgentConnTypeTKConnect,
throw: true})[0]
AssertConnEvent(t, connectEvent, ConnEventAssertions{
expectPid: uint32(os.Getpid()),
expectRemotePort: 80,
expectLocalAddrFamily: common.AF_INET,
expectRemoteFamily: common.AF_INET,
expectReadBytes: 0,
expectWriteBytes: 0,
expectLocalPort: -1,
expectConnEventType: bpf.AgentConnTypeTKConnect,
})
}
func TestCloseSyscall(t *testing.T) {
connEventList := make([]bpf.AgentConnEvtT, 0)
agentStopper := make(chan os.Signal, 1)
StartAgent(
[]bpf.AttachBpfProgFunction{
bpf.AttachSyscallConnectEntry,
bpf.AttachSyscallConnectExit,
bpf.AttachSyscallCloseEntry,
bpf.AttachSyscallCloseExit},
&connEventList,
nil,
nil,
nil, agentStopper)
defer func() {
agentStopper <- MySignal{}
}()
fmt.Println("Start Send Http Request")
sendTestHttpRequest(t, SendTestHttpRequestOptions{disableKeepAlived: true, targetUrl: "http://www.baidu.com"})
time.Sleep(1 * time.Second)
if len(connEventList) == 0 {
t.Fatalf("no conn event!")
}
connectEvent := findInterestedConnEvent(t, connEventList, FindInterestedConnEventOptions{
findByRemotePort: true,
findByConnType: true,
remotePort: 80,
connType: bpf.AgentConnTypeTKClose,
throw: true})[0]
AssertConnEvent(t, connectEvent, ConnEventAssertions{
expectPid: uint32(os.Getpid()),
expectRemotePort: 80,
expectLocalAddrFamily: common.AF_INET,
expectRemoteFamily: common.AF_INET,
expectReadBytesPredicator: func(u uint64) bool { return u == 0 },
expectWriteBytesPredicator: func(u uint64) bool { return u == 0 },
expectLocalPort: -1,
expectConnEventType: bpf.AgentConnTypeTKClose,
})
}
func TestAccept(t *testing.T) {
StartEchoTcpServerAndWait()
connEventList := make([]bpf.AgentConnEvtT, 0)
agentStopper := make(chan os.Signal, 1)
StartAgent(
[]bpf.AttachBpfProgFunction{
bpf.AttachSyscallAcceptEntry,
bpf.AttachSyscallAcceptExit,
},
&connEventList,
nil,
nil,
nil, agentStopper)
defer func() {
agentStopper <- MySignal{}
}()
// ip, _ := common.GetIPAddrByInterfaceName("eth0")
ip := "127.0.0.1"
WriteToEchoTcpServerAndReadResponse(WriteToEchoServerOptions{
t: t,
server: ip + ":" + fmt.Sprint(echoTcpServerPort),
message: "hello\n",
readResponse: true,
writeSyscall: Write,
readSyscall: Read,
})
time.Sleep(1 * time.Second)
if len(connEventList) == 0 {
t.Fatalf("no conn event!")
}
connectEvent := findInterestedConnEvent(t, connEventList, FindInterestedConnEventOptions{
findByLocalPort: true,
findByConnType: true,
localPort: uint16(echoTcpServerPort),
connType: bpf.AgentConnTypeTKConnect,
throw: true})[0]
AssertConnEvent(t, connectEvent, ConnEventAssertions{
expectPid: uint32(os.Getpid()),
expectRemotePort: -1,
expectLocalAddrFamily: common.AF_INET,
expectRemoteFamily: common.AF_INET,
expectReadBytesPredicator: func(u uint64) bool { return u == 0 },
expectWriteBytesPredicator: func(u uint64) bool { return u == 0 },
expectLocalPort: echoTcpServerPort,
expectConnEventType: bpf.AgentConnTypeTKConnect,
})
}
func TestExistedConn(t *testing.T) {
StartEchoTcpServerAndWait()
ip := "127.0.0.1"
sendMsg := "GET TestRead\n"
connection := WriteToEchoTcpServerAndReadResponse(WriteToEchoServerOptions{
t: t,
server: ip + ":" + fmt.Sprint(echoTcpServerPort),
message: sendMsg,
readResponse: true,
writeSyscall: Write,
readSyscall: Read,
keepConnection: true,
})
// established conn and write data before start kyanos
connEventList := make([]bpf.AgentConnEvtT, 0)
syscallEventList := make([]bpf.SyscallEventData, 0)
kernEventList := make([]bpf.AgentKernEvt, 0)
var connManager *conn.ConnManager = conn.InitConnManager()
agentStopper := make(chan os.Signal)
StartAgent(
nil,
&connEventList,
&syscallEventList,
&kernEventList,
func(cm *conn.ConnManager) {
*connManager = *cm
}, agentStopper)
defer func() {
agentStopper <- MySignal{}
}()
// then write data
WriteToEchoTcpServerAndReadResponse(WriteToEchoServerOptions{
t: t,
server: ip + ":" + fmt.Sprint(echoTcpServerPort),
message: sendMsg,
readResponse: true,
writeSyscall: Write,
readSyscall: Read,
keepConnection: true,
existedConnection: connection,
})
WriteToEchoTcpServerAndReadResponse(WriteToEchoServerOptions{
t: t,
server: ip + ":" + fmt.Sprint(echoTcpServerPort),
message: sendMsg,
readResponse: true,
writeSyscall: Write,
readSyscall: Read,
keepConnection: true,
existedConnection: connection,
})
time.Sleep(1500 * time.Millisecond)
assert.True(t, len(syscallEventList) > 0)
assert.True(t, len(connEventList) > 0)
assert.True(t, len(kernEventList) > 0)
assert.True(t, len(findInterestedKernEvents(t, kernEventList, FindInterestedKernEventOptions{
connEventList: connEventList,
findByStep: true,
step: bpf.AgentStepTIP_OUT,
})) > 0)
assert.True(t, len(findInterestedKernEvents(t, kernEventList, FindInterestedKernEventOptions{
connEventList: connEventList,
findByStep: true,
step: bpf.AgentStepTQDISC_OUT,
})) > 0)
assert.True(t, len(findInterestedKernEvents(t, kernEventList, FindInterestedKernEventOptions{
connEventList: connEventList,
findByStep: true,
step: bpf.AgentStepTDEV_OUT,
})) > 0)
assert.True(t, len(findInterestedKernEvents(t, kernEventList, FindInterestedKernEventOptions{
connEventList: connEventList,
findByStep: true,
step: bpf.AgentStepTDEV_IN,
})) > 0)
assert.True(t, len(findInterestedKernEvents(t, kernEventList, FindInterestedKernEventOptions{
connEventList: connEventList,
findByStep: true,
step: bpf.AgentStepTIP_IN,
})) > 0)
assert.True(t, len(findInterestedKernEvents(t, kernEventList, FindInterestedKernEventOptions{
connEventList: connEventList,
findByStep: true,
step: bpf.AgentStepTTCP_IN,
})) > 0)
assert.True(t, len(findInterestedKernEvents(t, kernEventList, FindInterestedKernEventOptions{
connEventList: connEventList,
findByStep: true,
step: bpf.AgentStepTUSER_COPY,
})) > 0)
}
func TestRead(t *testing.T) {
StartEchoTcpServerAndWait()
connEventList := make([]bpf.AgentConnEvtT, 0)
syscallEventList := make([]bpf.SyscallEventData, 0)
agentStopper := make(chan os.Signal)
var connManager *conn.ConnManager = conn.InitConnManager()
StartAgent(
[]bpf.AttachBpfProgFunction{
bpf.AttachSyscallConnectEntry,
bpf.AttachSyscallConnectExit,
bpf.AttachSyscallReadEntry,
bpf.AttachSyscallReadExit,
bpf.AttachKProbeSecuritySocketRecvmsgEntry,
},
&connEventList,
&syscallEventList,
nil,
func(cm *conn.ConnManager) {
*connManager = *cm
}, agentStopper)
defer func() {
agentStopper <- MySignal{}
}()
ip := "127.0.0.1"
sendMsg := "GET TestRead\n"
WriteToEchoTcpServerAndReadResponse(WriteToEchoServerOptions{
t: t,
server: ip + ":" + fmt.Sprint(echoTcpServerPort),
message: sendMsg,
readResponse: true,
writeSyscall: Write,
readSyscall: Read,
})
time.Sleep(500 * time.Millisecond)
assert.NotEmpty(t, syscallEventList)
syscallEvents := findInterestedSyscallEvents(t, syscallEventList, FindInterestedSyscallEventOptions{
findByRemotePort: true,
remotePort: uint16(echoTcpServerPort),
connEventList: connEventList,
})
syscallEvent := syscallEvents[0]
conn := connManager.FindConnection4Exactly(syscallEvent.SyscallEvent.Ke.ConnIdS.TgidFd)
AssertSyscallEventData(t, syscallEvent, SyscallDataEventAssertConditions{
KernDataEventAssertConditions: KernDataEventAssertConditions{
direct: Ingress,
pid: uint64(os.Getpid()),
fd: uint32(conn.TgidFd),
funcName: "syscall",
ignoreFuncName: true,
dataLen: uint32(len(sendMsg)),
seq: 1,
step: bpf.AgentStepTSYSCALL_IN,
tsAssertFunction: func(u uint64) bool { return u > 0 },
},
bufSizeAssertFunction: func(u uint32) bool { return u == uint32(len(sendMsg)) },
bufAssertFunction: func(b []byte) bool { return string(b) == sendMsg },
})
}
func TestRecvFrom(t *testing.T) {
StartEchoTcpServerAndWait()
connEventList := make([]bpf.AgentConnEvtT, 0)
syscallEventList := make([]bpf.SyscallEventData, 0)
var connManager *conn.ConnManager = conn.InitConnManager()
agentStopper := make(chan os.Signal, 1)
StartAgent(
[]bpf.AttachBpfProgFunction{
bpf.AttachSyscallConnectEntry,
bpf.AttachSyscallConnectExit,
bpf.AttachSyscallRecvfromEntry,
bpf.AttachSyscallRecvfromExit,
bpf.AttachKProbeSecuritySocketRecvmsgEntry,
},
&connEventList,
&syscallEventList,
nil,
func(cm *conn.ConnManager) {
*connManager = *cm
}, agentStopper)
defer func() {
agentStopper <- MySignal{}
}()
ip := "127.0.0.1"
sendMsg := "GET TestRecvFrom\n"
WriteToEchoTcpServerAndReadResponse(WriteToEchoServerOptions{
t: t,
server: ip + ":" + fmt.Sprint(echoTcpServerPort),
message: sendMsg,
readResponse: true,
writeSyscall: Write,
readSyscall: RecvFrom,
})
time.Sleep(500 * time.Millisecond)
assert.NotEmpty(t, syscallEventList)
syscallEvents := findInterestedSyscallEvents(t, syscallEventList, FindInterestedSyscallEventOptions{
findByRemotePort: true,
remotePort: uint16(echoTcpServerPort),
connEventList: connEventList,
})
syscallEvent := syscallEvents[0]
conn := connManager.FindConnection4Exactly(syscallEvent.SyscallEvent.Ke.ConnIdS.TgidFd)
AssertSyscallEventData(t, syscallEvent, SyscallDataEventAssertConditions{
KernDataEventAssertConditions: KernDataEventAssertConditions{
direct: Ingress,
pid: uint64(os.Getpid()),
fd: uint32(conn.TgidFd),
funcName: "syscall",
ignoreFuncName: true,
dataLen: uint32(len(sendMsg)),
seq: 1,
step: bpf.AgentStepTSYSCALL_IN,
tsAssertFunction: func(u uint64) bool { return u > 0 },
},
bufSizeAssertFunction: func(u uint32) bool { return u == uint32(len(sendMsg)) },
bufAssertFunction: func(b []byte) bool { return string(b) == sendMsg },
})
}
func TestReadv(t *testing.T) {
StartEchoTcpServerAndWait()
connEventList := make([]bpf.AgentConnEvtT, 0)
agentStopper := make(chan os.Signal, 1)
syscallEventList := make([]bpf.SyscallEventData, 0)
var connManager *conn.ConnManager = conn.InitConnManager()
StartAgent(
[]bpf.AttachBpfProgFunction{
bpf.AttachSyscallConnectEntry,
bpf.AttachSyscallConnectExit,
bpf.AttachSyscallReadvEntry,
bpf.AttachSyscallReadvExit,
bpf.AttachKProbeSecuritySocketRecvmsgEntry,
},
&connEventList,
&syscallEventList,
nil,
func(cm *conn.ConnManager) {
*connManager = *cm
}, agentStopper)
defer func() {
agentStopper <- MySignal{}
}()
ip := "127.0.0.1"
sendMsg := "GET TestReadv\n"
readBufSizeSlice := []int{len(sendMsg) / 2, len(sendMsg) - len(sendMsg)/2}
WriteToEchoTcpServerAndReadResponse(WriteToEchoServerOptions{
t: t,
server: ip + ":" + fmt.Sprint(echoTcpServerPort),
message: sendMsg,
readResponse: true,
writeSyscall: Write,
readSyscall: Readv,
readBufSizeSlice: readBufSizeSlice,
})
time.Sleep(500 * time.Millisecond)
assert.NotEmpty(t, syscallEventList)
syscallEvents := findInterestedSyscallEvents(t, syscallEventList, FindInterestedSyscallEventOptions{
findByRemotePort: true,
remotePort: uint16(echoTcpServerPort),
connEventList: connEventList,
})
assert.Equal(t, len(readBufSizeSlice), len(syscallEvents))
conn := connManager.FindConnection4Exactly(syscallEvents[0].SyscallEvent.Ke.ConnIdS.TgidFd)
seq := uint64(1)
for index, syscallEvent := range syscallEvents {
AssertSyscallEventData(t, syscallEvent, SyscallDataEventAssertConditions{
KernDataEventAssertConditions: KernDataEventAssertConditions{
direct: Ingress,
pid: uint64(os.Getpid()),
fd: uint32(conn.TgidFd),
funcName: "syscall",
ignoreFuncName: true,
dataLen: uint32(readBufSizeSlice[index]),
seq: seq,
step: bpf.AgentStepTSYSCALL_IN,
tsAssertFunction: func(u uint64) bool { return u > 0 },
},
bufSizeAssertFunction: func(u uint32) bool { return u == uint32(readBufSizeSlice[index]) },
bufAssertFunction: func(b []byte) bool { return string(b) == sendMsg[seq-1:int(seq)-1+readBufSizeSlice[index]] },
})
seq += uint64(readBufSizeSlice[index])
}
}
func TestRecvmsg(t *testing.T) {
StartEchoTcpServerAndWait()
connEventList := make([]bpf.AgentConnEvtT, 0)
syscallEventList := make([]bpf.SyscallEventData, 0)
agentStopper := make(chan os.Signal, 1)
var connManager *conn.ConnManager = conn.InitConnManager()
StartAgent(
[]bpf.AttachBpfProgFunction{
bpf.AttachSyscallConnectEntry,
bpf.AttachSyscallConnectExit,
bpf.AttachSyscallRecvMsgEntry,
bpf.AttachSyscallRecvMsgExit,
bpf.AttachKProbeSecuritySocketRecvmsgEntry,
},
&connEventList,
&syscallEventList,
nil,
func(cm *conn.ConnManager) {
*connManager = *cm
}, agentStopper)
defer func() {
agentStopper <- MySignal{}
}()
ip := "127.0.0.1"
sendMsg := "GET TestRecvmsg\n"
readBufSizeSlice := []int{len(sendMsg) / 2, len(sendMsg) - len(sendMsg)/2}
WriteToEchoTcpServerAndReadResponse(WriteToEchoServerOptions{
t: t,
server: ip + ":" + fmt.Sprint(echoTcpServerPort),
message: sendMsg,
readResponse: true,
writeSyscall: Write,
readSyscall: Recvmsg,
readBufSizeSlice: readBufSizeSlice,
})
time.Sleep(500 * time.Millisecond)
assert.NotEmpty(t, syscallEventList)
syscallEvents := findInterestedSyscallEvents(t, syscallEventList, FindInterestedSyscallEventOptions{
findByRemotePort: true,
remotePort: uint16(echoTcpServerPort),
connEventList: connEventList,
})
assert.Equal(t, len(readBufSizeSlice), len(syscallEvents))
conn := connManager.FindConnection4Exactly(syscallEvents[0].SyscallEvent.Ke.ConnIdS.TgidFd)
seq := uint64(1)
for index, syscallEvent := range syscallEvents {
AssertSyscallEventData(t, syscallEvent, SyscallDataEventAssertConditions{
KernDataEventAssertConditions: KernDataEventAssertConditions{
direct: Ingress,
pid: uint64(os.Getpid()),
fd: uint32(conn.TgidFd),
ignoreFuncName: true,
funcName: "syscall",
dataLen: uint32(readBufSizeSlice[index]),
seq: seq,
step: bpf.AgentStepTSYSCALL_IN,
tsAssertFunction: func(u uint64) bool { return u > 0 },
},
bufSizeAssertFunction: func(u uint32) bool { return u == uint32(readBufSizeSlice[index]) },
bufAssertFunction: func(b []byte) bool { return string(b) == sendMsg[seq-1:int(seq)-1+readBufSizeSlice[index]] },
})
seq += uint64(readBufSizeSlice[index])
}
}
func TestSslRead(t *testing.T) {
connEventList := make([]bpf.AgentConnEvtT, 0)
syscallEventList := make([]bpf.SyscallEventData, 0)
sslEventList := make([]bpf.SslData, 0)
var connManager *conn.ConnManager = conn.InitConnManager()
agentStopper := make(chan os.Signal, 1)
StartAgent0(
[]bpf.AttachBpfProgFunction{
bpf.AttachSyscallConnectEntry,
bpf.AttachSyscallConnectExit,
bpf.AttachKProbeSecuritySocketSendmsgEntry,
},
&connEventList,
&syscallEventList,
&sslEventList,
nil,
func(cm *conn.ConnManager) {
*connManager = *cm
}, agentStopper, false)
defer func() {
agentStopper <- MySignal{}
}()
_, cmd, _ := curlHTTPSRequest("https://www.baidu.com:443", "GET", nil, "")
time.Sleep(500 * time.Millisecond)
assert.NotEmpty(t, sslEventList)
syscallEvents := findInterestedSslEvents(t, sslEventList, FindInterestedSyscallEventOptions{
findByRemotePort: true,
remotePort: 443,
connEventList: connEventList,
findByPid: true,
pid: cmd.Process.Pid,
findByStep: true,
step: bpf.AgentStepTSSL_IN,
})
sslEvent := syscallEvents[0]
conn := connManager.FindConnection4Exactly(sslEvent.SslEventHeader.Ke.ConnIdS.TgidFd)
AssertSslEventData(t, sslEvent, SyscallDataEventAssertConditions{
KernDataEventAssertConditions: KernDataEventAssertConditions{
direct: Egress,
pid: uint64(cmd.Process.Pid),
fd: uint32(conn.TgidFd),
ignoreFuncName: true,
ignoreDataLen: true,
seq: 1,
step: bpf.AgentStepTSSL_OUT,
tsAssertFunction: func(u uint64) bool { return u > 0 },
},
bufSizeAssertFunction: func(u uint32) bool { return u > 0 },
})
}
func TestSslEventsCanRelatedToKernEvents(t *testing.T) {
connEventList := make([]bpf.AgentConnEvtT, 0)
syscallEventList := make([]bpf.SyscallEventData, 0)
sslEventList := make([]bpf.SslData, 0)
kernEventList := make([]bpf.AgentKernEvt, 0)
var connManager *conn.ConnManager = conn.InitConnManager()
agentStopper := make(chan os.Signal, 1)
StartAgent0(
[]bpf.AttachBpfProgFunction{
bpf.AttachSyscallConnectEntry,
bpf.AttachSyscallConnectExit,
bpf.AttachSyscallRecvfromEntry,
bpf.AttachSyscallRecvfromExit,
bpf.AttachSyscallReadEntry,
bpf.AttachSyscallReadExit,
bpf.AttachSyscallWriteEntry,
bpf.AttachSyscallWriteExit,
bpf.AttachKProbeSecuritySocketSendmsgEntry,
bpf.AttachKProbeSecuritySocketRecvmsgEntry,
func() (link.Link, error) {
return ApplyKernelVersionFunctions(t, bpf.AgentStepTDEV_IN)
},
func() (link.Link, error) {
return ApplyKernelVersionFunctions(t, bpf.AgentStepTUSER_COPY)
},
func() (link.Link, error) {
return ApplyKernelVersionFunctions(t, bpf.AgentStepTIP_IN)
},
func() (link.Link, error) {
return ApplyKernelVersionFunctions(t, bpf.AgentStepTTCP_IN)
},
func() (link.Link, error) {
return ApplyKernelVersionFunctions(t, bpf.AgentStepTIP_OUT)
},
func() (link.Link, error) {
return ApplyKernelVersionFunctions(t, bpf.AgentStepTDEV_OUT)
},
func() (link.Link, error) {
return ApplyKernelVersionFunctions(t, bpf.AgentStepTQDISC_OUT)
},
},
&connEventList,
&syscallEventList,
&sslEventList,
&kernEventList,
func(cm *conn.ConnManager) {
*connManager = *cm
}, agentStopper, false)
defer func() {
agentStopper <- MySignal{}
}()
_, cmd, _ := curlHTTPSRequest("https://www.baidu.com:443", "GET", nil, "")
time.Sleep(500 * time.Millisecond)
sslEvents := findInterestedSslEvents(t, sslEventList, FindInterestedSyscallEventOptions{
findByRemotePort: true,
remotePort: 443,
connEventList: connEventList,
findByPid: true,
pid: cmd.Process.Pid,
findByStep: true,
step: bpf.AgentStepTSSL_OUT,
})
assert.True(t, len(sslEvents) > 0)
sslEvent := sslEvents[0]
conn := connManager.FindConnection4Exactly(sslEvent.SslEventHeader.Ke.ConnIdS.TgidFd)
se := conn.StreamEvents
sslOutEvents := se.FindSslEventsBySeqAndLen(bpf.AgentStepTSSL_OUT, 1, 1000)
assert.True(t, len(sslOutEvents) > 0)
sslInEvents := se.FindSslEventsBySeqAndLen(bpf.AgentStepTSSL_IN, 1, 10000)
assert.True(t, len(sslInEvents) > 0)
kernSeq := sslInEvents[0].KernSeq
kernLen := sslInEvents[0].KernLen
devinEvents := se.FindEventsBySeqAndLen(bpf.AgentStepTDEV_IN, kernSeq, kernLen)
assert.True(t, len(devinEvents) > 0)
ipinEvents := se.FindEventsBySeqAndLen(bpf.AgentStepTIP_IN, kernSeq, kernLen)
assert.True(t, len(ipinEvents) > 0)
usercopyEvents := se.FindEventsBySeqAndLen(bpf.AgentStepTUSER_COPY, kernSeq, kernLen)
assert.True(t, len(usercopyEvents) > 0)
syscallInEvents := se.FindEventsBySeqAndLen(bpf.AgentStepTSYSCALL_IN, kernSeq, kernLen)
assert.True(t, len(syscallInEvents) > 0)
}
func TestSslWrite(t *testing.T) {
connEventList := make([]bpf.AgentConnEvtT, 0)
syscallEventList := make([]bpf.SyscallEventData, 0)
sslEventList := make([]bpf.SslData, 0)
var connManager *conn.ConnManager = conn.InitConnManager()
agentStopper := make(chan os.Signal, 1)
StartAgent0(
[]bpf.AttachBpfProgFunction{
bpf.AttachSyscallConnectEntry,
bpf.AttachSyscallConnectExit,
bpf.AttachKProbeSecuritySocketSendmsgEntry,
},
&connEventList,
&syscallEventList,
&sslEventList,
nil,
func(cm *conn.ConnManager) {
*connManager = *cm
}, agentStopper, false)
defer func() {
agentStopper <- MySignal{}
}()
_, cmd, _ := curlHTTPSRequest("https://www.baidu.com:443", "GET", nil, "")
time.Sleep(500 * time.Millisecond)
assert.NotEmpty(t, sslEventList)
syscallEvents := findInterestedSslEvents(t, sslEventList, FindInterestedSyscallEventOptions{
findByRemotePort: true,
remotePort: 443,
connEventList: connEventList,
findByPid: true,
pid: cmd.Process.Pid,
findByStep: true,
step: bpf.AgentStepTSSL_OUT,
})
sslEvent := syscallEvents[0]
conn := connManager.FindConnection4Exactly(sslEvent.SslEventHeader.Ke.ConnIdS.TgidFd)
AssertSslEventData(t, sslEvent, SyscallDataEventAssertConditions{
KernDataEventAssertConditions: KernDataEventAssertConditions{
direct: Egress,
pid: uint64(cmd.Process.Pid),
fd: uint32(conn.TgidFd),
ignoreFuncName: true,
ignoreDataLen: true,
seq: 1,
step: bpf.AgentStepTSSL_OUT,
tsAssertFunction: func(u uint64) bool { return u > 0 },
},
bufSizeAssertFunction: func(u uint32) bool { return u > 0 },
})
}
func TestWrite(t *testing.T) {
StartEchoTcpServerAndWait()
connEventList := make([]bpf.AgentConnEvtT, 0)
syscallEventList := make([]bpf.SyscallEventData, 0)
var connManager *conn.ConnManager = conn.InitConnManager()
agentStopper := make(chan os.Signal, 1)
StartAgent(
[]bpf.AttachBpfProgFunction{
bpf.AttachSyscallConnectEntry,
bpf.AttachSyscallConnectExit,
bpf.AttachSyscallWriteEntry,
bpf.AttachSyscallWriteExit,
bpf.AttachKProbeSecuritySocketSendmsgEntry,
},
&connEventList,
&syscallEventList,
nil,
func(cm *conn.ConnManager) {
*connManager = *cm
}, agentStopper)
defer func() {
agentStopper <- MySignal{}
}()
ip := "127.0.0.1"
sendMsg := "GET TestWrite\n"
WriteToEchoTcpServerAndReadResponse(WriteToEchoServerOptions{
t: t,
server: ip + ":" + fmt.Sprint(echoTcpServerPort),
message: sendMsg,
readResponse: true,
writeSyscall: Write,
readSyscall: Read,
})
time.Sleep(500 * time.Millisecond)
assert.NotEmpty(t, syscallEventList)
syscallEvents := findInterestedSyscallEvents(t, syscallEventList, FindInterestedSyscallEventOptions{
findByRemotePort: true,
remotePort: uint16(echoTcpServerPort),
connEventList: connEventList,
})
syscallEvent := syscallEvents[0]
conn := connManager.FindConnection4Exactly(syscallEvent.SyscallEvent.Ke.ConnIdS.TgidFd)
AssertSyscallEventData(t, syscallEvent, SyscallDataEventAssertConditions{
KernDataEventAssertConditions: KernDataEventAssertConditions{
direct: Egress,
pid: uint64(os.Getpid()),
fd: uint32(conn.TgidFd),
funcName: "syscall",
ignoreFuncName: true,
dataLen: uint32(len(sendMsg)),
seq: 1,
step: bpf.AgentStepTSYSCALL_OUT,
tsAssertFunction: func(u uint64) bool { return u > 0 },
},
bufSizeAssertFunction: func(u uint32) bool { return u == uint32(len(sendMsg)) },
bufAssertFunction: func(b []byte) bool { return string(b) == sendMsg },
})
}
func TestSendto(t *testing.T) {
StartEchoTcpServerAndWait()
connEventList := make([]bpf.AgentConnEvtT, 0)
syscallEventList := make([]bpf.SyscallEventData, 0)
var connManager *conn.ConnManager = conn.InitConnManager()
agentStopper := make(chan os.Signal, 1)
StartAgent(
[]bpf.AttachBpfProgFunction{
bpf.AttachSyscallConnectEntry,
bpf.AttachSyscallConnectExit,
bpf.AttachSyscallSendtoEntry,
bpf.AttachSyscallSendtoExit,
bpf.AttachKProbeSecuritySocketSendmsgEntry,
},
&connEventList,
&syscallEventList,
nil,
func(cm *conn.ConnManager) {
*connManager = *cm
}, agentStopper)
defer func() {
agentStopper <- MySignal{}
}()
ip := "127.0.0.1"
sendMsg := "GET TestSendto\n"
WriteToEchoTcpServerAndReadResponse(WriteToEchoServerOptions{
t: t,
server: ip + ":" + fmt.Sprint(echoTcpServerPort),
message: sendMsg,
readResponse: true,
writeSyscall: SentTo,
readSyscall: Read,
})
time.Sleep(500 * time.Millisecond)
assert.NotEmpty(t, syscallEventList)
syscallEvents := findInterestedSyscallEvents(t, syscallEventList, FindInterestedSyscallEventOptions{
findByRemotePort: true,
remotePort: uint16(echoTcpServerPort),
connEventList: connEventList,
})
syscallEvent := syscallEvents[0]
conn := connManager.FindConnection4Exactly(syscallEvent.SyscallEvent.Ke.ConnIdS.TgidFd)
AssertSyscallEventData(t, syscallEvent, SyscallDataEventAssertConditions{
KernDataEventAssertConditions: KernDataEventAssertConditions{
direct: Egress,
pid: uint64(os.Getpid()),
fd: uint32(conn.TgidFd),
funcName: "syscall",
ignoreFuncName: true,
dataLen: uint32(len(sendMsg)),
seq: 1,
step: bpf.AgentStepTSYSCALL_OUT,
tsAssertFunction: func(u uint64) bool { return u > 0 },
},
bufSizeAssertFunction: func(u uint32) bool { return u == uint32(len(sendMsg)) },
bufAssertFunction: func(b []byte) bool { return string(b) == sendMsg },
})
}
func TestWritev(t *testing.T) {
StartEchoTcpServerAndWait()
connEventList := make([]bpf.AgentConnEvtT, 0)
syscallEventList := make([]bpf.SyscallEventData, 0)
agentStopper := make(chan os.Signal, 1)
var connManager *conn.ConnManager = conn.InitConnManager()
StartAgent(
[]bpf.AttachBpfProgFunction{
bpf.AttachSyscallConnectEntry,
bpf.AttachSyscallConnectExit,
bpf.AttachSyscallWritevEntry,
bpf.AttachSyscallWritevExit,
bpf.AttachKProbeSecuritySocketSendmsgEntry,
},
&connEventList,
&syscallEventList,
nil,
func(cm *conn.ConnManager) {
*connManager = *cm
}, agentStopper)
defer func() {
agentStopper <- MySignal{}
}()
ip := "127.0.0.1"
sendMessages := []string{"GET writevhellohellohellohello\n", "abchellohellohellohello\n"}
WriteToEchoTcpServerAndReadResponse(WriteToEchoServerOptions{
t: t,
server: ip + ":" + fmt.Sprint(echoTcpServerPort),
messageSlice: sendMessages,
readResponse: true,
writeSyscall: Writev,
readSyscall: Read,
})
time.Sleep(500 * time.Millisecond)
assert.NotEmpty(t, syscallEventList)
syscallEvents := findInterestedSyscallEvents(t, syscallEventList, FindInterestedSyscallEventOptions{
findByRemotePort: true,
remotePort: uint16(echoTcpServerPort),
connEventList: connEventList,
})
assert.Equal(t, 2, len(syscallEvents))
conn := connManager.FindConnection4Exactly(syscallEvents[0].SyscallEvent.Ke.ConnIdS.TgidFd)
seq := uint64(1)
for index, syscallEvent := range syscallEvents {
AssertSyscallEventData(t, syscallEvent, SyscallDataEventAssertConditions{
KernDataEventAssertConditions: KernDataEventAssertConditions{
direct: Egress,
pid: uint64(os.Getpid()),
fd: uint32(conn.TgidFd),
funcName: "syscall",
ignoreFuncName: true,
dataLen: uint32(len(sendMessages[index])),
seq: seq,
step: bpf.AgentStepTSYSCALL_OUT,
tsAssertFunction: func(u uint64) bool { return u > 0 },
},
bufSizeAssertFunction: func(u uint32) bool { return u == uint32(len(sendMessages[index])) },
bufAssertFunction: func(b []byte) bool { return string(b) == sendMessages[index] },
})
seq += uint64(len(sendMessages[index]))
}
}
func TestSendMsg(t *testing.T) {
StartEchoTcpServerAndWait()
connEventList := make([]bpf.AgentConnEvtT, 0)
syscallEventList := make([]bpf.SyscallEventData, 0)
var connManager *conn.ConnManager = conn.InitConnManager()
agentStopper := make(chan os.Signal, 1)
StartAgent(
[]bpf.AttachBpfProgFunction{
bpf.AttachSyscallConnectEntry,
bpf.AttachSyscallConnectExit,
bpf.AttachSyscallSendMsgEntry,
bpf.AttachSyscallSendMsgExit,
bpf.AttachKProbeSecuritySocketSendmsgEntry,
},
&connEventList,
&syscallEventList,
nil,
func(cm *conn.ConnManager) {
*connManager = *cm
}, agentStopper)
defer func() {
agentStopper <- MySignal{}
}()
ip := "127.0.0.1"
sendMessages := []string{"GET sendmsghellohellohellohello\n", "aabchellohellohellohello\n"}
WriteToEchoTcpServerAndReadResponse(WriteToEchoServerOptions{
t: t,
server: ip + ":" + fmt.Sprint(echoTcpServerPort),
messageSlice: sendMessages,
readResponse: true,
writeSyscall: Sendmsg,
readSyscall: Read,
})
time.Sleep(500 * time.Millisecond)
assert.NotEmpty(t, syscallEventList)
syscallEvents := findInterestedSyscallEvents(t, syscallEventList, FindInterestedSyscallEventOptions{
findByRemotePort: true,
remotePort: uint16(echoTcpServerPort),
connEventList: connEventList,
})
assert.Equal(t, 2, len(syscallEvents))
conn := connManager.FindConnection4Exactly(syscallEvents[0].SyscallEvent.Ke.ConnIdS.TgidFd)
seq := uint64(1)
for index, syscallEvent := range syscallEvents {
AssertSyscallEventData(t, syscallEvent, SyscallDataEventAssertConditions{
KernDataEventAssertConditions: KernDataEventAssertConditions{direct: Egress,
pid: uint64(os.Getpid()),
fd: uint32(conn.TgidFd),
ignoreFuncName: true,
funcName: "syscall",
dataLen: uint32(len(sendMessages[index])),
seq: seq,
step: bpf.AgentStepTSYSCALL_OUT,
tsAssertFunction: func(u uint64) bool { return u > 0 },
},
bufSizeAssertFunction: func(u uint32) bool { return u == uint32(len(sendMessages[index])) },
bufAssertFunction: func(b []byte) bool { return string(b) == sendMessages[index] },
})
seq += uint64(len(sendMessages[index]))
}
}
func TestIpXmit(t *testing.T) {
options := KernTestWithTcpEchoServerOptions{
t,
[]bpf.AttachBpfProgFunction{
bpf.AttachSyscallConnectEntry,
bpf.AttachSyscallConnectExit,
bpf.AttachSyscallWriteEntry,
bpf.AttachSyscallWriteExit,
bpf.AttachKProbeSecuritySocketSendmsgEntry,
func() (link.Link, error) {
return ApplyKernelVersionFunctions(t, bpf.AgentStepTIP_OUT)
},
},
"GET TestIpXmit\n", Write, Read,
FindInterestedKernEventOptions{
findDataLenGtZeroEvent: true,
findByDirect: true,
direct: Egress,
}, KernDataEventAssertConditions{
direct: Egress,
pid: uint64(os.Getpid()),
funcName: "ip_queue_xmit",
ignoreFuncName: true,
seq: 1,
step: bpf.AgentStepTIP_OUT,
tsAssertFunction: func(u uint64) bool { return u > 0 },
},
}
KernTestWithTcpEchoServer(options)
}
func TestDevQueueXmit(t *testing.T) {
options := KernTestWithTcpEchoServerOptions{t, []bpf.AttachBpfProgFunction{
bpf.AttachSyscallConnectEntry,
bpf.AttachSyscallConnectExit,
bpf.AttachSyscallWriteEntry,
bpf.AttachSyscallWriteExit,
bpf.AttachKProbeSecuritySocketSendmsgEntry,
func() (link.Link, error) {
return ApplyKernelVersionFunctions(t, bpf.AgentStepTIP_OUT)
},
func() (link.Link, error) {
return ApplyKernelVersionFunctions(t, bpf.AgentStepTQDISC_OUT)
},
}, "GET DevQueueXmit\n", Write, Read,
FindInterestedKernEventOptions{
findDataLenGtZeroEvent: true,
findByDirect: true,
direct: Egress,
findByStep: true,
step: bpf.AgentStepTQDISC_OUT,
}, KernDataEventAssertConditions{
direct: Egress,
pid: uint64(os.Getpid()),
funcName: "dev_queue_xmit",
ignoreFuncName: true,
seq: 1,
step: bpf.AgentStepTQDISC_OUT,
tsAssertFunction: func(u uint64) bool { return u > 0 },
},
}
KernTestWithTcpEchoServer(options)
}
func TestDevHardStartXmit(t *testing.T) {
options := KernTestWithTcpEchoServerOptions{
t, []bpf.AttachBpfProgFunction{
bpf.AttachSyscallConnectEntry,
bpf.AttachSyscallConnectExit,
bpf.AttachSyscallWriteEntry,
bpf.AttachSyscallWriteExit,
bpf.AttachKProbeSecuritySocketSendmsgEntry,
func() (link.Link, error) {
return ApplyKernelVersionFunctions(t, bpf.AgentStepTIP_OUT)
},
func() (link.Link, error) {
return ApplyKernelVersionFunctions(t, bpf.AgentStepTDEV_OUT)
},
}, "GET DevHardStartXmit\n", Write, Read,
FindInterestedKernEventOptions{
findDataLenGtZeroEvent: true,
findByDirect: true,
direct: Egress,
findByStep: true,
step: bpf.AgentStepTDEV_OUT,
}, KernDataEventAssertConditions{
direct: Egress,
pid: uint64(os.Getpid()),
funcName: "dev_hard_start",
ignoreFuncName: true,
seq: 1,
step: bpf.AgentStepTDEV_OUT,
tsAssertFunction: func(u uint64) bool { return u > 0 },
},
}
KernTestWithTcpEchoServer(options)
}
func TestTracepointNetifReceiveSkb(t *testing.T) {
curVersion := compatible.GetCurrentKernelVersion()
delete(curVersion.Capabilities, compatible.SupportXDP)
compatible.KernelVersionsMap.Put(curVersion.Version, curVersion)
KernRcvTestWithHTTP(t, []bpf.AttachBpfProgFunction{
bpf.AttachSyscallConnectEntry,
bpf.AttachSyscallConnectExit,
bpf.AttachSyscallRecvfromEntry,
bpf.AttachSyscallRecvfromExit,
bpf.AttachSyscallReadEntry,
bpf.AttachSyscallReadExit,
bpf.AttachSyscallWriteEntry,
bpf.AttachSyscallWriteExit,
bpf.AttachKProbeSecuritySocketSendmsgEntry,
bpf.AttachKProbeSecuritySocketRecvmsgEntry,
bpf.AttachTracepointNetifReceiveSkb,
},
FindInterestedKernEventOptions{
findDataLenGtZeroEvent: true,
findByDirect: true,
direct: Ingress,
findByStep: true,
step: bpf.AgentStepTDEV_IN,
}, KernDataEventAssertConditions{
direct: Ingress,
pid: uint64(os.Getpid()),
funcName: "netif_receive_skb",
ignoreFuncName: true,
seq: 1,
step: bpf.AgentStepTDEV_IN,
ignoreDataLen: true,
dataLenAssertFunc: func(u uint32) bool { return u > 10 },
tsAssertFunction: func(u uint64) bool { return u > 0 },
})
curVersion.Capabilities[compatible.SupportXDP] = true
compatible.KernelVersionsMap.Put(curVersion.Version, curVersion)
time.Sleep(1 * time.Second)
}
func TestIpRcvCore(t *testing.T) {
KernRcvTestWithHTTP(t, []bpf.AttachBpfProgFunction{
bpf.AttachSyscallConnectEntry,
bpf.AttachSyscallConnectExit,
bpf.AttachSyscallRecvfromEntry,
bpf.AttachSyscallRecvfromExit,
bpf.AttachSyscallReadEntry,
bpf.AttachSyscallReadExit,
bpf.AttachSyscallWriteEntry,
bpf.AttachSyscallWriteExit,
bpf.AttachKProbeSecuritySocketSendmsgEntry,
bpf.AttachKProbeSecuritySocketRecvmsgEntry,
func() (link.Link, error) {
return ApplyKernelVersionFunctions(t, bpf.AgentStepTDEV_IN)
},
func() (link.Link, error) {
return ApplyKernelVersionFunctions(t, bpf.AgentStepTIP_IN)
},
},
FindInterestedKernEventOptions{
findDataLenGtZeroEvent: true,
findByDirect: true,
direct: Ingress,
findByStep: true,
step: bpf.AgentStepTIP_IN,
}, KernDataEventAssertConditions{
direct: Ingress,
pid: uint64(os.Getpid()),
funcName: "ip_rcv_core",
ignoreFuncName: true,
seq: 1,
step: bpf.AgentStepTIP_IN,
ignoreDataLen: true,
dataLenAssertFunc: func(u uint32) bool { return u > 10 },
tsAssertFunction: func(u uint64) bool { return u > 0 },
})
time.Sleep(1 * time.Second)
}
func TestTcpV4DoRcv(t *testing.T) {
KernRcvTestWithHTTP(t, []bpf.AttachBpfProgFunction{
bpf.AttachSyscallConnectEntry,
bpf.AttachSyscallConnectExit,
bpf.AttachSyscallRecvfromEntry,
bpf.AttachSyscallRecvfromExit,
bpf.AttachSyscallReadEntry,
bpf.AttachSyscallReadExit,
bpf.AttachSyscallWriteEntry,
bpf.AttachSyscallWriteExit,
bpf.AttachKProbeSecuritySocketSendmsgEntry,
bpf.AttachKProbeSecuritySocketRecvmsgEntry,
func() (link.Link, error) {
return ApplyKernelVersionFunctions(t, bpf.AgentStepTDEV_IN)
},
func() (link.Link, error) {
return ApplyKernelVersionFunctions(t, bpf.AgentStepTTCP_IN)
},
},
FindInterestedKernEventOptions{
findDataLenGtZeroEvent: true,
findByDirect: true,
direct: Ingress,
findByStep: true,
step: bpf.AgentStepTTCP_IN,
}, KernDataEventAssertConditions{
direct: Ingress,
pid: uint64(os.Getpid()),
funcName: "tcp_v4_do_rcv",
ignoreFuncName: true,
seq: 1,
step: bpf.AgentStepTTCP_IN,
ignoreDataLen: true,
dataLenAssertFunc: func(u uint32) bool { return u > 10 },
tsAssertFunction: func(u uint64) bool { return u > 0 },
})
time.Sleep(1 * time.Second)
}
func TestSkbCopyDatagramIter(t *testing.T) {
KernRcvTestWithHTTP(t, []bpf.AttachBpfProgFunction{
bpf.AttachSyscallConnectEntry,
bpf.AttachSyscallConnectExit,
bpf.AttachSyscallRecvfromEntry,
bpf.AttachSyscallRecvfromExit,
bpf.AttachSyscallReadEntry,
bpf.AttachSyscallReadExit,
bpf.AttachSyscallWriteEntry,
bpf.AttachSyscallWriteExit,
bpf.AttachKProbeSecuritySocketSendmsgEntry,
bpf.AttachKProbeSecuritySocketRecvmsgEntry,
func() (link.Link, error) {
return ApplyKernelVersionFunctions(t, bpf.AgentStepTDEV_IN)
},
func() (link.Link, error) {
return ApplyKernelVersionFunctions(t, bpf.AgentStepTUSER_COPY)
},
},
FindInterestedKernEventOptions{
findDataLenGtZeroEvent: true,
findByDirect: true,
direct: Ingress,
findByStep: true,
step: bpf.AgentStepTUSER_COPY,
}, KernDataEventAssertConditions{
direct: Ingress,
pid: uint64(os.Getpid()),
funcName: "skb_copy_datagr",
ignoreFuncName: true,
seq: 1,
step: bpf.AgentStepTUSER_COPY,
ignoreDataLen: true,
dataLenAssertFunc: func(u uint32) bool { return u > 10 },
tsAssertFunction: func(u uint64) bool { return u > 0 },
})
time.Sleep(1 * time.Second)
}