Merge pull request #116 from lanrenwo/dev

在审计日志的页面增加详情和访问协议
This commit is contained in:
bjdgyc 2022-07-15 15:47:04 +08:00 committed by GitHub
commit 1dceffc327
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 146 additions and 28 deletions

View File

@ -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 {

View File

@ -1,7 +1,9 @@
package handler
import (
"crypto/md5"
"encoding/binary"
"encoding/hex"
"github.com/bjdgyc/anylink/base"
"github.com/bjdgyc/anylink/dbdata"
@ -10,6 +12,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 +114,14 @@ func logAudit(cSess *sessdata.ConnSession, pl *sessdata.Payload) {
}
ipProto := waterutil.IPv4Protocol(pl.Data)
// 访问协议
var accessProto uint8
// 只统计 tcp和udp 的访问
switch ipProto {
case waterutil.TCP:
accessProto = acc_proto_tcp
case waterutil.UDP:
accessProto = acc_proto_udp
default:
return
}
@ -117,12 +130,21 @@ func logAudit(cSess *sessdata.ConnSession, pl *sessdata.Payload) {
ipDst := waterutil.IPv4Destination(pl.Data)
ipPort := waterutil.IPv4DestinationPort(pl.Data)
b := getByte34()
b := getByte51()
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 != "" {
md5Sum := md5.Sum([]byte(info))
copy(key[35:51], hex.EncodeToString(md5Sum[:]))
}
s := utils.BytesToString(key)
nu := utils.NowSec().Unix()
@ -130,19 +152,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)
putByte51(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)

View File

@ -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, ""
}

View File

@ -87,3 +87,25 @@ func putByte34(b *[]byte) {
*b = (*b)[:34]
byte34Pool.Put(b)
}
type BufferPool struct {
sync.Pool
}
// 长度 51 小对象
var byte51Pool = sync.Pool{
New: func() interface{} {
b := make([]byte, 51)
return &b
},
}
func getByte51() *[]byte {
b := byte51Pool.Get().(*[]byte)
return b
}
func putByte51(b *[]byte) {
*b = (*b)[:51]
byte51Pool.Put(b)
}

View File

@ -16,39 +16,50 @@
<el-table-column
prop="username"
label="用户名">
</el-table-column>
<el-table-column
prop="protocol"
label="协议">
label="用户名"
width="120">
</el-table-column>
<el-table-column
prop="src"
label="源IP地址">
label="源IP地址"
width="140">
</el-table-column>
<el-table-column
prop="dst"
label="目的IP地址">
label="目的IP地址"
width="140">
</el-table-column>
<el-table-column
prop="dst_port"
label="目的端口">
label="目的端口"
width="85">
</el-table-column>
<el-table-column
prop="access_proto"
label="访问协议"
width="85"
:formatter="protoFormat">
</el-table-column>
<el-table-column
prop="info"
label="详情">
</el-table-column>
<el-table-column
prop="created_at"
label="创建时间"
width="150"
:formatter="tableDateFormat">
</el-table-column>
<el-table-column
label="操作"
width="150">
width="100">
<template slot-scope="scope">
<el-popconfirm
class="m-left-10"
@ -89,7 +100,7 @@ export default {
mixins: [],
created() {
this.$emit('update:route_path', this.$route.path)
this.$emit('update:route_name', ['基础信息', 'IP审计'])
this.$emit('update:route_name', ['基础信息', '审计日志'])
},
mounted() {
this.getData(1)
@ -99,6 +110,7 @@ export default {
tableData: [],
count: 10,
nowIndex: 0,
accessProtoArr:["", "UDP", "TCP", "HTTPS", "HTTP"],
}
},
methods: {
@ -136,6 +148,16 @@ export default {
console.log(error);
});
},
protoFormat(row) {
var access_proto = row.access_proto
if (row.access_proto == 0) {
switch (row.protocol) {
case 6: access_proto = 2; break;
case 17: access_proto = 1; break;
}
}
return this.accessProtoArr[access_proto]
},
},
}
</script>