From 8837a07facae58fc97899b4b4bc3c4845e28c00e Mon Sep 17 00:00:00 2001 From: lanrenwo Date: Thu, 14 Jul 2022 19:02:43 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=AE=A1=E8=AE=A1=E6=97=A5?= =?UTF-8?q?=E5=BF=97=E7=9A=84http/https=E5=9F=9F=E5=90=8D=E4=BF=A1?= =?UTF-8?q?=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/dbdata/tables.go | 18 ++++++----- server/handler/payload.go | 37 ++++++++++++++++----- server/handler/payload_tcp_parser.go | 48 ++++++++++++++++++++++++++++ server/handler/pool.go | 22 +++++++++++++ 4 files changed, 109 insertions(+), 16 deletions(-) create mode 100644 server/handler/payload_tcp_parser.go diff --git a/server/dbdata/tables.go b/server/dbdata/tables.go index 4ba03cd..cd69572 100644 --- a/server/dbdata/tables.go +++ b/server/dbdata/tables.go @@ -59,14 +59,16 @@ type Setting struct { } type AccessAudit struct { - Id int `json:"id" xorm:"pk autoincr not null"` - Username string `json:"username" xorm:"varchar(60) not null"` - Protocol uint8 `json:"protocol" xorm:"not null"` - Src string `json:"src" xorm:"varchar(60) not null"` - SrcPort uint16 `json:"src_port" xorm:"not null"` - Dst string `json:"dst" xorm:"varchar(60) not null"` - DstPort uint16 `json:"dst_port" xorm:"not null"` - CreatedAt time.Time `json:"created_at" xorm:"DateTime"` + Id int `json:"id" xorm:"pk autoincr not null"` + Username string `json:"username" xorm:"varchar(60) not null"` + Protocol uint8 `json:"protocol" xorm:"not null"` + Src string `json:"src" xorm:"varchar(60) not null"` + SrcPort uint16 `json:"src_port" xorm:"not null"` + Dst string `json:"dst" xorm:"varchar(60) not null"` + DstPort uint16 `json:"dst_port" xorm:"not null"` + AccessProto uint8 `json:"access_proto" xorm:"not null"` // 访问协议 + Info string `json:"info" xorm:"varchar(255) not null"` // 详情 + CreatedAt time.Time `json:"created_at" xorm:"DateTime"` } type Policy struct { diff --git a/server/handler/payload.go b/server/handler/payload.go index acc27d6..ab2b387 100644 --- a/server/handler/payload.go +++ b/server/handler/payload.go @@ -10,6 +10,13 @@ import ( "github.com/songgao/water/waterutil" ) +const ( + acc_proto_udp = iota + 1 + acc_proto_tcp + acc_proto_https + acc_proto_http +) + func payloadIn(cSess *sessdata.ConnSession, pl *sessdata.Payload) bool { if pl.LType == sessdata.LTypeIPData && pl.PType == 0x00 { // 进行Acl规则判断 @@ -105,10 +112,13 @@ func logAudit(cSess *sessdata.ConnSession, pl *sessdata.Payload) { } ipProto := waterutil.IPv4Protocol(pl.Data) + // 访问协议 + var accessProto uint8 = acc_proto_tcp // 只统计 tcp和udp 的访问 switch ipProto { case waterutil.TCP: case waterutil.UDP: + accessProto = acc_proto_udp default: return } @@ -117,12 +127,21 @@ func logAudit(cSess *sessdata.ConnSession, pl *sessdata.Payload) { ipDst := waterutil.IPv4Destination(pl.Data) ipPort := waterutil.IPv4DestinationPort(pl.Data) - b := getByte34() + b := getByte290() key := *b copy(key[:16], ipSrc) copy(key[16:32], ipDst) binary.BigEndian.PutUint16(key[32:34], ipPort) + info := "" + if ipProto == waterutil.TCP { + accessProto, info = onTCP(waterutil.IPv4Payload(pl.Data)) + } + key[34] = byte(accessProto) + if info != "" { + copy(key[35:35+len(info)], info) + } + s := utils.BytesToString(key) nu := utils.NowSec().Unix() @@ -130,19 +149,21 @@ func logAudit(cSess *sessdata.ConnSession, pl *sessdata.Payload) { v, ok := cSess.IpAuditMap[s] if ok && nu-v < int64(base.Cfg.AuditInterval) { // 回收byte对象 - putByte34(b) + putByte290(b) return } cSess.IpAuditMap[s] = nu audit := dbdata.AccessAudit{ - Username: cSess.Sess.Username, - Protocol: uint8(ipProto), - Src: ipSrc.String(), - Dst: ipDst.String(), - DstPort: ipPort, - CreatedAt: utils.NowSec(), + Username: cSess.Sess.Username, + Protocol: uint8(ipProto), + Src: ipSrc.String(), + Dst: ipDst.String(), + DstPort: ipPort, + CreatedAt: utils.NowSec(), + AccessProto: accessProto, + Info: info, } _ = dbdata.Add(audit) diff --git a/server/handler/payload_tcp_parser.go b/server/handler/payload_tcp_parser.go new file mode 100644 index 0000000..a7681c4 --- /dev/null +++ b/server/handler/payload_tcp_parser.go @@ -0,0 +1,48 @@ +package handler + +import ( + "bufio" + "bytes" + "net/http" + "regexp" +) + +var tcpParsers = []func([]byte) (uint8, string){ + sniParser, + httpParser, +} + +var ( + sniRe = regexp.MustCompile("\x00\x00.{4}\x00.{2}([a-z0-9]+([\\-\\.]{1}[a-z0-9]+)*\\.[a-z]{2,6})\x00") +) + +func onTCP(payload []byte) (uint8, string) { + ihl := (payload[12] & 0xf0) >> 2 + data := payload[ihl:] + for _, parser := range tcpParsers { + if proto, info := parser(data); info != "" { + return proto, info + } + } + return acc_proto_tcp, "" +} + +func sniParser(data []byte) (uint8, string) { + dataSize := len(data) + if dataSize < 2 || data[0] != 0x16 || data[1] != 0x03 { + return acc_proto_tcp, "" + } + m := sniRe.FindSubmatch(data) + if len(m) < 2 { + return acc_proto_tcp, "" + } + host := string(m[1]) + return acc_proto_https, host +} + +func httpParser(data []byte) (uint8, string) { + if req, err := http.ReadRequest(bufio.NewReader(bytes.NewReader(data))); err == nil { + return acc_proto_http, req.Host + } + return acc_proto_tcp, "" +} diff --git a/server/handler/pool.go b/server/handler/pool.go index a9e04c5..c56b305 100644 --- a/server/handler/pool.go +++ b/server/handler/pool.go @@ -87,3 +87,25 @@ func putByte34(b *[]byte) { *b = (*b)[:34] byte34Pool.Put(b) } + +type BufferPool struct { + sync.Pool +} + +// 长度 290 对象 +var byte290Pool = sync.Pool{ + New: func() interface{} { + b := make([]byte, 290) + return &b + }, +} + +func getByte290() *[]byte { + b := byte290Pool.Get().(*[]byte) + return b +} + +func putByte290(b *[]byte) { + *b = (*b)[:290] + byte290Pool.Put(b) +}