mirror of https://github.com/bjdgyc/anylink.git
Merge pull request #162 from lanrenwo/audit_https
修复解析https+ip偶发出现sni乱码的BUG
This commit is contained in:
commit
6f7fcfc6ee
|
@ -3,7 +3,6 @@ package handler
|
|||
import (
|
||||
"crypto/md5"
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"time"
|
||||
|
||||
"github.com/bjdgyc/anylink/base"
|
||||
|
@ -109,6 +108,8 @@ func logAudit(cSess *sessdata.ConnSession, pl *sessdata.Payload) {
|
|||
copy(key[:16], ipSrc)
|
||||
copy(key[16:32], ipDst)
|
||||
binary.BigEndian.PutUint16(key[32:34], ipPort)
|
||||
key[34] = byte(accessProto)
|
||||
copy(key[35:51], []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0})
|
||||
|
||||
info := ""
|
||||
nu := utils.NowSec().Unix()
|
||||
|
@ -149,16 +150,20 @@ func logAudit(cSess *sessdata.ConnSession, pl *sessdata.Payload) {
|
|||
case flags & 0x18:
|
||||
// PSH ACK
|
||||
accessProto, info = onTCP(plData)
|
||||
if info != "" {
|
||||
// HTTPS or HTTP
|
||||
if accessProto != acc_proto_tcp {
|
||||
// 提前存储只含ip数据的key, 避免即记录域名又记录一笔IP数据的记录
|
||||
ipKey := make([]byte, 51)
|
||||
copy(ipKey, key)
|
||||
ipS := utils.BytesToString(ipKey)
|
||||
cSess.IpAuditMap.Set(ipS, nu)
|
||||
// 存储含域名的key
|
||||
|
||||
key[34] = byte(accessProto)
|
||||
md5Sum := md5.Sum([]byte(info))
|
||||
copy(key[35:51], hex.EncodeToString(md5Sum[:]))
|
||||
// 存储含域名的key
|
||||
if info != "" {
|
||||
md5Sum := md5.Sum([]byte(info))
|
||||
copy(key[35:51], md5Sum[:])
|
||||
}
|
||||
}
|
||||
case flags & 0x19:
|
||||
// URG
|
||||
|
|
|
@ -9,7 +9,7 @@ import (
|
|||
)
|
||||
|
||||
var tcpParsers = []func([]byte) (uint8, string){
|
||||
sniParser,
|
||||
sniNewParser,
|
||||
httpParser,
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,7 @@ func onTCP(payload []byte) (uint8, string) {
|
|||
}
|
||||
data := payload[ihl:]
|
||||
for _, parser := range tcpParsers {
|
||||
if proto, info := parser(data); info != "" {
|
||||
if proto, info := parser(data); proto != acc_proto_tcp {
|
||||
return proto, info
|
||||
}
|
||||
}
|
||||
|
@ -29,8 +29,7 @@ func onTCP(payload []byte) (uint8, string) {
|
|||
}
|
||||
|
||||
func sniNewParser(b []byte) (uint8, string) {
|
||||
dataSize := len(b)
|
||||
if dataSize < 2 || b[0] != 0x16 || b[1] != 0x03 {
|
||||
if len(b) < 2 || b[0] != 0x16 || b[1] != 0x03 {
|
||||
return acc_proto_tcp, ""
|
||||
}
|
||||
rest := b[5:]
|
||||
|
@ -51,27 +50,27 @@ func sniNewParser(b []byte) (uint8, string) {
|
|||
// Skip over random number
|
||||
current += 4 + 28
|
||||
if current >= restLen {
|
||||
return acc_proto_tcp, ""
|
||||
return acc_proto_https, ""
|
||||
}
|
||||
// Skip over session ID
|
||||
sessionIDLength := int(rest[current])
|
||||
current += 1
|
||||
current += sessionIDLength
|
||||
if current >= restLen {
|
||||
return acc_proto_tcp, ""
|
||||
return acc_proto_https, ""
|
||||
}
|
||||
cipherSuiteLength := (int(rest[current]) << 8) + int(rest[current+1])
|
||||
current += 2
|
||||
current += cipherSuiteLength
|
||||
if current >= restLen {
|
||||
return acc_proto_tcp, ""
|
||||
return acc_proto_https, ""
|
||||
}
|
||||
compressionMethodLength := int(rest[current])
|
||||
current += 1
|
||||
current += compressionMethodLength
|
||||
|
||||
if current >= restLen {
|
||||
return acc_proto_tcp, ""
|
||||
return acc_proto_https, ""
|
||||
}
|
||||
current += 2
|
||||
hostname := ""
|
||||
|
@ -84,27 +83,30 @@ func sniNewParser(b []byte) (uint8, string) {
|
|||
// Skip over number of names as we're assuming there's just one
|
||||
current += 2
|
||||
if current >= restLen {
|
||||
return acc_proto_tcp, ""
|
||||
return acc_proto_https, ""
|
||||
}
|
||||
nameType := rest[current]
|
||||
current += 1
|
||||
if nameType != 0 {
|
||||
return acc_proto_tcp, ""
|
||||
return acc_proto_https, ""
|
||||
}
|
||||
if current+1 >= restLen {
|
||||
return acc_proto_tcp, ""
|
||||
return acc_proto_https, ""
|
||||
}
|
||||
nameLen := (int(rest[current]) << 8) + int(rest[current+1])
|
||||
current += 2
|
||||
if current+nameLen >= restLen {
|
||||
return acc_proto_tcp, ""
|
||||
return acc_proto_https, ""
|
||||
}
|
||||
hostname = string(rest[current : current+nameLen])
|
||||
}
|
||||
current += extensionDataLength
|
||||
}
|
||||
if hostname == "" {
|
||||
return acc_proto_tcp, ""
|
||||
return acc_proto_https, ""
|
||||
}
|
||||
if !validDomainChar(hostname) {
|
||||
return acc_proto_https, ""
|
||||
}
|
||||
return acc_proto_https, hostname
|
||||
}
|
||||
|
@ -150,8 +152,7 @@ func httpNewParser(data []byte) (uint8, string) {
|
|||
}
|
||||
|
||||
func sniParser(data []byte) (uint8, string) {
|
||||
dataSize := len(data)
|
||||
if dataSize < 2 || data[0] != 0x16 || data[1] != 0x03 {
|
||||
if len(data) < 2 || data[0] != 0x16 || data[1] != 0x03 {
|
||||
return acc_proto_tcp, ""
|
||||
}
|
||||
sniRe := regexp.MustCompile("\x00\x00.{4}\x00.{2}([a-z0-9]+([\\-\\.]{1}[a-z0-9]+)*\\.[a-z]{2,6})\x00")
|
||||
|
@ -169,3 +170,15 @@ func httpParser(data []byte) (uint8, string) {
|
|||
}
|
||||
return acc_proto_tcp, ""
|
||||
}
|
||||
|
||||
// 校验域名的合法字符, 处理乱码问题
|
||||
func validDomainChar(addr string) bool {
|
||||
// Allow a-z A-Z . - 0-9
|
||||
for i := 0; i < len(addr); i++ {
|
||||
c := addr[i]
|
||||
if !((c >= 97 && c <= 122) || (c >= 65 && c <= 90) || (c >= 45 && c <= 46) || (c >= 48 && c <= 57)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
|
|
@ -51,22 +51,26 @@ func BenchmarkNewHttpParser(b *testing.B) {
|
|||
func TestNewSniParser(t *testing.T) {
|
||||
ast := assert.New(t)
|
||||
data := handlerTcpPayload(httpsPacket)
|
||||
_, sni := sniNewParser(data)
|
||||
proto, sni := sniNewParser(data)
|
||||
ast.Equal(sni, httpsSni)
|
||||
ast.Equal(int(proto), acc_proto_https)
|
||||
}
|
||||
|
||||
func TestNewHttpParser(t *testing.T) {
|
||||
ast := assert.New(t)
|
||||
// Host
|
||||
data := handlerTcpPayload(httpPacket)
|
||||
_, hostname := httpNewParser(data)
|
||||
proto, hostname := httpNewParser(data)
|
||||
ast.Equal(hostname, httpHost)
|
||||
ast.Equal(int(proto), acc_proto_http)
|
||||
// HOST
|
||||
data = handlerTcpPayload(httpPacket2)
|
||||
_, hostname = httpNewParser(data)
|
||||
proto, hostname = httpNewParser(data)
|
||||
ast.Equal(hostname, httpHost)
|
||||
ast.Equal(int(proto), acc_proto_http)
|
||||
// GET http://www.google.com/index.html HTTP/1.1
|
||||
data = handlerTcpPayload(httpPacket3)
|
||||
_, hostname = httpNewParser(data)
|
||||
proto, hostname = httpNewParser(data)
|
||||
ast.Equal(hostname, httpHost)
|
||||
ast.Equal(int(proto), acc_proto_http)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue