Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v1.1.0-beta #59

Merged
merged 34 commits into from
Dec 25, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
a1b65c1
WIP (agent and collector)
chriskaliX Dec 4, 2022
89f512d
download sync WIP
chriskaliX Dec 4, 2022
8a000f7
testcase update(WIP)
chriskaliX Dec 5, 2022
2e0ef56
agent refactory(WIP)
chriskaliX Dec 5, 2022
eb27140
heartbeat refactory
chriskaliX Dec 6, 2022
55c6d1d
Metric done, transport WIP
chriskaliX Dec 7, 2022
b663bba
Working on grpc, sync stats from Elkeid
chriskaliX Dec 7, 2022
043bd4d
grpc WIP
chriskaliX Dec 8, 2022
db29968
SDK update
chriskaliX Dec 9, 2022
7462b1c
WIP
chriskaliX Dec 11, 2022
38cc004
discovery test
chriskaliX Dec 11, 2022
abc2049
retval patch
chriskaliX Dec 12, 2022
1d2cfab
Resolver WIP
chriskaliX Dec 12, 2022
e210f7a
sip and sport supported in sys_connect
chriskaliX Dec 13, 2022
a872512
ARM compatible
chriskaliX Dec 13, 2022
10c577a
Agent state sync from elkeid WIP
chriskaliX Dec 14, 2022
a15b15d
connect need fix
chriskaliX Dec 14, 2022
a4421b2
FIX
chriskaliX Dec 15, 2022
33e496d
multi fixes for sip/sport missing
chriskaliX Dec 15, 2022
4206dd2
honeypot WIP
chriskaliX Dec 17, 2022
e11930e
clean code, honeypot WIP
chriskaliX Dec 18, 2022
f26866e
bugs fixed, honeypot portscan UDP/ICMP supported
chriskaliX Dec 22, 2022
29e0c2a
patch uprobe(remove)
chriskaliX Dec 22, 2022
12d245c
trival fix
chriskaliX Dec 22, 2022
8374306
BPF prog fix WIP
chriskaliX Dec 22, 2022
1f7f503
inst patch WIP
chriskaliX Dec 22, 2022
1b1ed8d
5.19 issue fix
chriskaliX Dec 22, 2022
1fc4c69
length patch
chriskaliX Dec 22, 2022
46cad29
UDP kernel space ratelmit
chriskaliX Dec 22, 2022
ce553e5
code clean
chriskaliX Dec 23, 2022
39bb12f
code clean
chriskaliX Dec 24, 2022
c7e1014
WIP
chriskaliX Dec 25, 2022
c1be3fb
make ncp a dependent plugin
chriskaliX Dec 25, 2022
e8b74d2
work flow go version
chriskaliX Dec 25, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/co-re.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ on:
branches: [main]

env:
GO_VERSION: "1.17"
GO_VERSION: "1.18"

jobs:
CO-RE:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/non-co-re-daily.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ on:
- cron: "0 0 * * *"

env:
GO_VERSION: "1.17"
GO_VERSION: "1.18"

jobs:
non-CO-RE-ubuntu-latest:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release-driver.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
- name: go env
uses: actions/setup-go@v2
with:
go-version: '1.17'
go-version: '1.18'

- name: llvm env
run: |
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ cert/
# ignore binary
plugin/ebpfdriver/ebpfdriver
plugin/collector/collector
plugin/ncp/ncp

# libbpf test
plugin/ebpfdriver/kern/headers/libbpf
Expand Down
15 changes: 2 additions & 13 deletions SDK/logger/logger.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,6 @@ import (
"github.com/chriskaliX/SDK/transport/client"
)

var _ ILogger = (*zap.SugaredLogger)(nil)

type ILogger interface {
Debug(args ...interface{})
Info(args ...interface{})
Warn(args ...interface{})
Error(args ...interface{})
Fatal(args ...interface{})
Panic(args ...interface{})
}

type Config struct {
// SDK fields
Client *client.Client
Expand All @@ -38,7 +27,7 @@ type Config struct {
RemoteLevel zapcore.LevelEnabler
}

func New(config *Config) *zap.SugaredLogger {
func New(config *Config) *zap.Logger {
var l *zap.Logger
remoteConfig := zap.NewProductionEncoderConfig()
remoteConfig.CallerKey = "source"
Expand Down Expand Up @@ -67,5 +56,5 @@ func New(config *Config) *zap.SugaredLogger {
)
l = zap.New(core, zap.AddCaller())
zap.ReplaceGlobals(l)
return zap.S()
return l
}
13 changes: 5 additions & 8 deletions SDK/sandbox.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"github.com/chriskaliX/SDK/transport/protocol"
"github.com/chriskaliX/SDK/util/hash"
"github.com/nightlyone/lockfile"
"go.uber.org/zap"
)

var _ ISandbox = (*Sandbox)(nil)
Expand All @@ -45,7 +46,7 @@ type ISandbox interface {
type Sandbox struct {
// required fields
Clock clock.IClock
Logger logger.ILogger
Logger *zap.Logger
Client *client.Client
name string
// Optional fields
Expand Down Expand Up @@ -82,11 +83,6 @@ func (s *Sandbox) Init(sconfig *SandboxConfig) error {
sconfig.LogConfig.Clock = s.Clock
sconfig.LogConfig.Client = s.Client
s.Logger = logger.New(sconfig.LogConfig)
// lockfile for plugin
// if err := s.Lockfile(); err != nil {
// zap.S().Errorf("init failed with lockfile %s", err.Error())
// return err
// }
defer s.Logger.Info(fmt.Sprintf("sandbox %s init", s.name))
// Optional fields initialization
if sconfig.Hash {
Expand All @@ -106,11 +102,12 @@ func (s *Sandbox) Run(mfunc func(ISandbox) error) (err error) {
defer s.Logger.Info(fmt.Sprintf("%s is exited", s.name))
s.Logger.Info(fmt.Sprintf("%s run is called", s.name))
if err = mfunc(s); err != nil {
zap.S().Error("sandbox main func failed, %s", err.Error())
return err
}
s.Logger.Info(fmt.Sprintf("%s is running", s.name))
// os.Interrupt for command line
signal.Notify(s.sigs, syscall.SIGTERM)
signal.Notify(s.sigs, syscall.SIGTERM, syscall.SIGTERM, os.Interrupt)
for {
select {
case sig := <-s.sigs:
Expand Down Expand Up @@ -224,7 +221,7 @@ func (s *Sandbox) recvTask() {
default:
task, err := s.Client.ReceiveTask()
if err != nil {
s.Logger.Error(err)
s.Logger.Error(err.Error())
time.Sleep(5 * time.Second)
continue
}
Expand Down
23 changes: 11 additions & 12 deletions SDK/transport/pool/pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,26 +14,20 @@ var BufferPool = NewPool()
type Pool struct {
p1 *sync.Pool
p2 *sync.Pool
p3 *sync.Pool
}

// For plugin ebpfdriver as an example, most of the data sizes are within
// 2048, drop size over 4096 as default
func NewPool() Pool {
return Pool{
p1: &sync.Pool{
New: func() interface{} {
return make([]byte, 2<<10)
},
},
p2: &sync.Pool{
New: func() interface{} {
return make([]byte, 4<<10)
},
},
p1: &sync.Pool{New: func() interface{} { return make([]byte, 2<<10) }},
p2: &sync.Pool{New: func() interface{} { return make([]byte, 4<<10) }},
p3: &sync.Pool{New: func() interface{} { return make([]byte, 8<<10) }},
}
}

func (p Pool) Get(size int64) []byte {
func (p *Pool) Get(size int64) []byte {
if size <= 2<<10 {
return p.p1.Get().([]byte)
} else if size <= 4<<10 {
Expand All @@ -42,13 +36,18 @@ func (p Pool) Get(size int64) []byte {
return make([]byte, size)
}

func (p Pool) Put(b []byte) {
func (p *Pool) Put(b []byte) {
if len(b) <= 2<<10 {
p.p1.Put(b)
return
}
if len(b) <= 4<<10 {
p.p2.Put(b)
return
}
if len(b) <= 8<<10 {
p.p3.Put(b)
return
}
// deprecate []byte over 4096, let GC collects them
}
4 changes: 2 additions & 2 deletions SDK/util/connection/connection.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ type INetRetry interface {
GetMaxDelay() uint
}

func IRetry(netRetry INetRetry, ctx context.Context) (err error) {
func IRetry(ctx context.Context, netRetry INetRetry) (err error) {
var (
maxRetries uint
maxDelay uint
Expand All @@ -45,7 +45,7 @@ func IRetry(netRetry INetRetry, ctx context.Context) (err error) {
return
default:
if maxRetries > 0 && retries >= maxRetries {
err = fmt.Errorf("Abandon %s after %d retries.", netRetry.String(), retries)
err = fmt.Errorf("abandon %s after %d retries.", netRetry.String(), retries)
zap.S().Error(err)
return err
}
Expand Down
79 changes: 45 additions & 34 deletions SDK/util/download.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,39 +6,37 @@ import (
"crypto/sha256"
"encoding/hex"
"errors"
"fmt"
"io"
"io/ioutil"
"net/http"
"os"
"time"

"go.uber.org/zap"
)

func CheckSignature(dst string, sign string) (err error) {
var (
f *os.File
signBytes []byte
)
if f, err = os.Open(dst); err != nil {
return
var downloadTimeout = 10 * time.Minute

func CheckSignature(dst string, sign string) error {
f, err := os.Open(dst)
if err != nil {
return err
}
defer f.Close()
if signBytes, err = hex.DecodeString(sign); err != nil {
return
signBytes, err := hex.DecodeString(sign)
if err != nil {
return err
}
hasher := sha256.New()
// https://pandaychen.github.io/2020/01/01/MAGIC-GO-IO-PACKAGE/
if _, err = io.Copy(hasher, f); err != nil {
return
return err
}
if !bytes.Equal(hasher.Sum(nil), signBytes) {
err = errors.New("signature doesn't match")
return
return err
}
// make it executable
f.Chmod(0o0700)
return
return nil
}

// Download function get the plugin executable file from urls
Expand All @@ -48,50 +46,63 @@ func CheckSignature(dst string, sign string) (err error) {
// memory is always needed
func Download(ctx context.Context, dst string, sha256sum string, urls []string, suffix string) (err error) {
var checksum []byte
// check wheater this already exist
if checksum, err = hex.DecodeString(sha256sum); err != nil {
return
}
hasher := sha256.New()
// extra work, but to simplify
if err = CheckSignature(dst, sha256sum); err == nil {
return
}
// in elkeid, `defer` in loop... emmm, not a best practice I think, but nothing wrong
// In Elkeid v1.9.1, only Timeout is different from DefaultTransport.
// Before v1.9.1 the timeout was controlled by subctx, now it is
// controlled by client itself.
client := &http.Client{
Transport: http.DefaultTransport,
Timeout: downloadTimeout,
}
for _, rawurl := range urls {
var req *http.Request
var resp *http.Response
var buf []byte
subctx, cancel := context.WithTimeout(ctx, time.Minute*3)
subctx, cancel := context.WithCancel(ctx)
defer cancel()
if req, err = http.NewRequestWithContext(subctx, "GET", rawurl, nil); err != nil {
continue
}
if resp, err = http.DefaultClient.Do(req); err != nil {
if resp, err = client.Do(req); err != nil {
continue
}
if !(resp.StatusCode >= 200 && resp.StatusCode < 300) {
err = errors.New("http error: " + resp.Status)
continue
}
defer resp.Body.Close()
if buf, err = ioutil.ReadAll(resp.Body); err != nil {
continue
}
// Set the limitation of download, but I think it would be alright
// since the time limitation is also set. This configration helps
// avoid download too much to fill up the disk even within 10 mins.
resp.Body = http.MaxBytesReader(nil, resp.Body, 512*1024*1024)
hasher.Reset()
hasher.Write(buf)
if !bytes.Equal(hasher.Sum(nil), checksum) {
err = errors.New("checksum doesn't match")
continue
}
br := bytes.NewBuffer(buf)
zap.S().Info("start to decompress to ", dst)
// Before Elkeid v1.9.1, ioutil.ReadAll is used and it may
// lead memory grows rapidly since it reads everything into
// memeory, using io.TeeReader to both read from Reader and
// calculate the hash
// Also the decompress should be updated
r := io.TeeReader(resp.Body, hasher)
switch suffix {
case "tar.gz":
err = DecompressTarGz(dst, br)
err = DecompressTarGz(dst, r)
default:
err = DecompressDefault(dst, br)
err = DecompressDefault(dst, r)
}
resp.Body.Close()
if err != nil {
continue
}
if c := hex.EncodeToString(hasher.Sum(nil)); c != sha256sum {
err = fmt.Errorf("checksum doesn't match: %s vs %s", checksum, sha256sum)
zap.S().Error(err)
} else {
break
}
break
}
return
}
4 changes: 2 additions & 2 deletions agent/Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
CMD_GO ?= go
VERSION ?= 1.0.1
VERSION ?= v1.0.2

# colors
INFO_COLOR = \033[34m[*]\033[0m
Expand All @@ -14,4 +14,4 @@ pre_show:

.PHONY: build_agent
build_agent:
$(CMD_GO) build -ldflags "-X agent/agent.Version='$(VERSION)'" -o hades-agent
$(CMD_GO) build -ldflags "-X agent/agent.Version=$(VERSION)" -o hades-agent
30 changes: 19 additions & 11 deletions agent/agent/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,31 @@ package agent

import (
"context"
"os"
)

const (
Product = "hades-agent"
EnvName = "SPECIFIED_AGENT_ID_HADES"
Version = ""
)

// The only instance of the agent
var Instance = New()
var (
Version string // compile time added
Context, Cancel = context.WithCancel(context.Background())
Workdir, _ = os.Getwd()
ID string
)

type Agent struct {
ID string
Workdir string
Version string
Context context.Context
Cancel context.CancelFunc
Product string
OS string
func init() {
var err error
if Workdir, err = os.Getwd(); err != nil {
Workdir = HADES_PIDPATH
}
// ID init
var ok bool
if ID, ok = os.LookupEnv(EnvName); ok {
return
}
genUUID()
os.WriteFile("machine-id", []byte(ID), 0600)
}
Loading