优化审计日志异步写入

This commit is contained in:
lanrenwo 2022-11-01 14:17:35 +08:00
parent 6fdc0e54d5
commit 890ff5753f
3 changed files with 55 additions and 87 deletions

View File

@ -16,9 +16,7 @@ func payloadIn(cSess *sessdata.ConnSession, pl *sessdata.Payload) bool {
return false return false
} }
if base.Cfg.AuditInterval >= 0 { if base.Cfg.AuditInterval >= 0 {
cSess.IpAuditPool.JobQueue <- func() { auditPayload.Add(cSess.Username, pl)
logAudit(cSess, pl)
}
} }
} }

View File

@ -9,6 +9,7 @@ import (
"github.com/bjdgyc/anylink/dbdata" "github.com/bjdgyc/anylink/dbdata"
"github.com/bjdgyc/anylink/pkg/utils" "github.com/bjdgyc/anylink/pkg/utils"
"github.com/bjdgyc/anylink/sessdata" "github.com/bjdgyc/anylink/sessdata"
"github.com/ivpusic/grpool"
"github.com/songgao/water/waterutil" "github.com/songgao/water/waterutil"
) )
@ -19,33 +20,49 @@ const (
acc_proto_http acc_proto_http
) )
var (
logAuditSink *LogSink
auditPayload *AuditPayload
)
// 审计日志
type AuditPayload struct {
Pool *grpool.Pool
IpAuditMap utils.IMaps
}
// 保存批量的审计日志 // 保存批量的审计日志
type LogBatch struct { type LogBatch struct {
Logs []dbdata.AccessAudit Logs []dbdata.AccessAudit
} }
// 日志池 // 批量日志池
type LogSink struct { type LogSink struct {
logChan chan dbdata.AccessAudit logChan chan dbdata.AccessAudit
autoCommitChan chan *LogBatch // 超时通知 autoCommitChan chan *LogBatch // 超时通知
} }
var logAuditSink *LogSink func (p *AuditPayload) Add(userName string, pl *sessdata.Payload) {
bPlData := getByteFull()
// 写入日志通道 copy(*bPlData, pl.Data)
func logAuditWrite(aa dbdata.AccessAudit) { p.Pool.JobQueue <- func() {
logAuditSink.logChan <- aa logAudit(userName, bPlData)
}
} }
// 批量写入数据表 // 开启批量写入数据功能
func logAuditBatch() { func logAuditBatch() {
if base.Cfg.AuditInterval < 0 { if base.Cfg.AuditInterval < 0 {
return return
} }
logAuditSink = &LogSink{ logAuditSink = &LogSink{
logChan: make(chan dbdata.AccessAudit, 1000), logChan: make(chan dbdata.AccessAudit, 5000),
autoCommitChan: make(chan *LogBatch, 10), autoCommitChan: make(chan *LogBatch, 10),
} }
auditPayload = &AuditPayload{
Pool: grpool.NewPool(10, 500),
IpAuditMap: utils.NewMap("cmap", 0),
}
var ( var (
limit = 100 // 超过上限批量写入数据表 limit = 100 // 超过上限批量写入数据表
logAudit dbdata.AccessAudit logAudit dbdata.AccessAudit
@ -53,6 +70,7 @@ func logAuditBatch() {
commitTimer *time.Timer // 超时自动提交 commitTimer *time.Timer // 超时自动提交
timeOutBatch *LogBatch timeOutBatch *LogBatch
) )
for { for {
select { select {
case logAudit = <-logAuditSink.logChan: case logAudit = <-logAuditSink.logChan:
@ -85,8 +103,11 @@ func logAuditBatch() {
} }
// 解析IP包的数据 // 解析IP包的数据
func logAudit(cSess *sessdata.ConnSession, pl *sessdata.Payload) { func logAudit(userName string, bPlData *[]byte) {
ipProto := waterutil.IPv4Protocol(pl.Data) defer putByte(bPlData)
plData := *bPlData
ipProto := waterutil.IPv4Protocol(plData)
// 访问协议 // 访问协议
var accessProto uint8 var accessProto uint8
// 只统计 tcp和udp 的访问 // 只统计 tcp和udp 的访问
@ -99,9 +120,9 @@ func logAudit(cSess *sessdata.ConnSession, pl *sessdata.Payload) {
return return
} }
ipSrc := waterutil.IPv4Source(pl.Data) ipSrc := waterutil.IPv4Source(plData)
ipDst := waterutil.IPv4Destination(pl.Data) ipDst := waterutil.IPv4Destination(plData)
ipPort := waterutil.IPv4DestinationPort(pl.Data) ipPort := waterutil.IPv4DestinationPort(plData)
b := getByte51() b := getByte51()
key := *b key := *b
@ -114,49 +135,19 @@ func logAudit(cSess *sessdata.ConnSession, pl *sessdata.Payload) {
info := "" info := ""
nu := utils.NowSec().Unix() nu := utils.NowSec().Unix()
if ipProto == waterutil.TCP { if ipProto == waterutil.TCP {
plData := waterutil.IPv4Payload(pl.Data) tcpPlData := waterutil.IPv4Payload(plData)
if len(plData) < 14 { // 24 (ACK PSH)
if len(tcpPlData) < 14 || tcpPlData[13] != 24 {
return return
} }
flags := plData[13] accessProto, info = onTCP(tcpPlData)
switch flags {
case flags & 0x20:
// URG
return
case flags & 0x14:
// RST ACK
return
case flags & 0x12:
// SYN ACK
return
case flags & 0x11:
// Client FIN
return
case flags & 0x10:
// ACK
return
case flags & 0x08:
// PSH
return
case flags & 0x04:
// RST
return
case flags & 0x02:
// SYN
return
case flags & 0x01:
// FIN
return
case flags & 0x18:
// PSH ACK
accessProto, info = onTCP(plData)
// HTTPS or HTTP // HTTPS or HTTP
if accessProto != acc_proto_tcp { if accessProto != acc_proto_tcp {
// 提前存储只含ip数据的key, 避免即记录域名又记录一笔IP数据的记录 // 提前存储只含ip数据的key, 避免即记录域名又记录一笔IP数据的记录
ipKey := make([]byte, 51) ipKey := make([]byte, 51)
copy(ipKey, key) copy(ipKey, key)
ipS := utils.BytesToString(ipKey) ipS := utils.BytesToString(ipKey)
cSess.IpAuditMap.Set(ipS, nu) auditPayload.IpAuditMap.Set(ipS, nu)
key[34] = byte(accessProto) key[34] = byte(accessProto)
// 存储含域名的key // 存储含域名的key
@ -165,28 +156,21 @@ func logAudit(cSess *sessdata.ConnSession, pl *sessdata.Payload) {
copy(key[35:51], md5Sum[:]) copy(key[35:51], md5Sum[:])
} }
} }
case flags & 0x19:
// URG
return
case flags & 0xC2:
// SYN-ECE-CWR
return
}
} }
s := utils.BytesToString(key) s := utils.BytesToString(key)
// 判断已经存在,并且没有过期 // 判断已经存在,并且没有过期
v, ok := cSess.IpAuditMap.Get(s) v, ok := auditPayload.IpAuditMap.Get(s)
if ok && nu-v.(int64) < int64(base.Cfg.AuditInterval) { if ok && nu-v.(int64) < int64(base.Cfg.AuditInterval) {
// 回收byte对象 // 回收byte对象
putByte51(b) putByte51(b)
return return
} }
cSess.IpAuditMap.Set(s, nu) auditPayload.IpAuditMap.Set(s, nu)
audit := dbdata.AccessAudit{ audit := dbdata.AccessAudit{
Username: cSess.Username, Username: userName,
Protocol: uint8(ipProto), Protocol: uint8(ipProto),
Src: ipSrc.String(), Src: ipSrc.String(),
Dst: ipDst.String(), Dst: ipDst.String(),
@ -195,5 +179,5 @@ func logAudit(cSess *sessdata.ConnSession, pl *sessdata.Payload) {
AccessProto: accessProto, AccessProto: accessProto,
Info: info, Info: info,
} }
logAuditWrite(audit) logAuditSink.logChan <- audit
} }

View File

@ -12,9 +12,7 @@ import (
"github.com/bjdgyc/anylink/base" "github.com/bjdgyc/anylink/base"
"github.com/bjdgyc/anylink/dbdata" "github.com/bjdgyc/anylink/dbdata"
"github.com/bjdgyc/anylink/pkg/utils"
mapset "github.com/deckarep/golang-set" mapset "github.com/deckarep/golang-set"
"github.com/ivpusic/grpool"
atomic2 "go.uber.org/atomic" atomic2 "go.uber.org/atomic"
) )
@ -52,8 +50,6 @@ type ConnSession struct {
PayloadIn chan *Payload PayloadIn chan *Payload
PayloadOutCstp chan *Payload // Cstp的数据 PayloadOutCstp chan *Payload // Cstp的数据
PayloadOutDtls chan *Payload // Dtls的数据 PayloadOutDtls chan *Payload // Dtls的数据
IpAuditMap utils.IMaps // 审计的ip数据
IpAuditPool *grpool.Pool // 审计的IP包解析池
// dSess *DtlsSession // dSess *DtlsSession
dSess *atomic.Value dSess *atomic.Value
} }
@ -206,12 +202,6 @@ func (s *Session) NewConn() *ConnSession {
dSess: &atomic.Value{}, dSess: &atomic.Value{},
} }
// ip 审计
if base.Cfg.AuditInterval >= 0 {
cSess.IpAuditMap = utils.NewMap("cmap", 0)
cSess.IpAuditPool = grpool.NewPool(1, 600)
}
dSess := &DtlsSession{ dSess := &DtlsSession{
isActive: -1, isActive: -1,
} }
@ -244,10 +234,6 @@ func (cs *ConnSession) Close() {
cs.Sess.LastLogin = time.Now() cs.Sess.LastLogin = time.Now()
cs.Sess.CSess = nil cs.Sess.CSess = nil
if cs.IpAuditPool != nil {
cs.IpAuditPool.Release()
}
dSess := cs.GetDtlsSession() dSess := cs.GetDtlsSession()
if dSess != nil { if dSess != nil {
dSess.Close() dSess.Close()