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 (
|
import (
|
||||||
"crypto/md5"
|
"crypto/md5"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"encoding/hex"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/bjdgyc/anylink/base"
|
"github.com/bjdgyc/anylink/base"
|
||||||
|
@ -109,6 +108,8 @@ func logAudit(cSess *sessdata.ConnSession, pl *sessdata.Payload) {
|
||||||
copy(key[:16], ipSrc)
|
copy(key[:16], ipSrc)
|
||||||
copy(key[16:32], ipDst)
|
copy(key[16:32], ipDst)
|
||||||
binary.BigEndian.PutUint16(key[32:34], ipPort)
|
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 := ""
|
info := ""
|
||||||
nu := utils.NowSec().Unix()
|
nu := utils.NowSec().Unix()
|
||||||
|
@ -149,16 +150,20 @@ func logAudit(cSess *sessdata.ConnSession, pl *sessdata.Payload) {
|
||||||
case flags & 0x18:
|
case flags & 0x18:
|
||||||
// PSH ACK
|
// PSH ACK
|
||||||
accessProto, info = onTCP(plData)
|
accessProto, info = onTCP(plData)
|
||||||
if info != "" {
|
// HTTPS or HTTP
|
||||||
|
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)
|
cSess.IpAuditMap.Set(ipS, nu)
|
||||||
// 存储含域名的key
|
|
||||||
key[34] = byte(accessProto)
|
key[34] = byte(accessProto)
|
||||||
|
// 存储含域名的key
|
||||||
|
if info != "" {
|
||||||
md5Sum := md5.Sum([]byte(info))
|
md5Sum := md5.Sum([]byte(info))
|
||||||
copy(key[35:51], hex.EncodeToString(md5Sum[:]))
|
copy(key[35:51], md5Sum[:])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
case flags & 0x19:
|
case flags & 0x19:
|
||||||
// URG
|
// URG
|
||||||
|
|
|
@ -9,7 +9,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var tcpParsers = []func([]byte) (uint8, string){
|
var tcpParsers = []func([]byte) (uint8, string){
|
||||||
sniParser,
|
sniNewParser,
|
||||||
httpParser,
|
httpParser,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ func onTCP(payload []byte) (uint8, string) {
|
||||||
}
|
}
|
||||||
data := payload[ihl:]
|
data := payload[ihl:]
|
||||||
for _, parser := range tcpParsers {
|
for _, parser := range tcpParsers {
|
||||||
if proto, info := parser(data); info != "" {
|
if proto, info := parser(data); proto != acc_proto_tcp {
|
||||||
return proto, info
|
return proto, info
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,8 +29,7 @@ func onTCP(payload []byte) (uint8, string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func sniNewParser(b []byte) (uint8, string) {
|
func sniNewParser(b []byte) (uint8, string) {
|
||||||
dataSize := len(b)
|
if len(b) < 2 || b[0] != 0x16 || b[1] != 0x03 {
|
||||||
if dataSize < 2 || b[0] != 0x16 || b[1] != 0x03 {
|
|
||||||
return acc_proto_tcp, ""
|
return acc_proto_tcp, ""
|
||||||
}
|
}
|
||||||
rest := b[5:]
|
rest := b[5:]
|
||||||
|
@ -51,27 +50,27 @@ func sniNewParser(b []byte) (uint8, string) {
|
||||||
// Skip over random number
|
// Skip over random number
|
||||||
current += 4 + 28
|
current += 4 + 28
|
||||||
if current >= restLen {
|
if current >= restLen {
|
||||||
return acc_proto_tcp, ""
|
return acc_proto_https, ""
|
||||||
}
|
}
|
||||||
// Skip over session ID
|
// Skip over session ID
|
||||||
sessionIDLength := int(rest[current])
|
sessionIDLength := int(rest[current])
|
||||||
current += 1
|
current += 1
|
||||||
current += sessionIDLength
|
current += sessionIDLength
|
||||||
if current >= restLen {
|
if current >= restLen {
|
||||||
return acc_proto_tcp, ""
|
return acc_proto_https, ""
|
||||||
}
|
}
|
||||||
cipherSuiteLength := (int(rest[current]) << 8) + int(rest[current+1])
|
cipherSuiteLength := (int(rest[current]) << 8) + int(rest[current+1])
|
||||||
current += 2
|
current += 2
|
||||||
current += cipherSuiteLength
|
current += cipherSuiteLength
|
||||||
if current >= restLen {
|
if current >= restLen {
|
||||||
return acc_proto_tcp, ""
|
return acc_proto_https, ""
|
||||||
}
|
}
|
||||||
compressionMethodLength := int(rest[current])
|
compressionMethodLength := int(rest[current])
|
||||||
current += 1
|
current += 1
|
||||||
current += compressionMethodLength
|
current += compressionMethodLength
|
||||||
|
|
||||||
if current >= restLen {
|
if current >= restLen {
|
||||||
return acc_proto_tcp, ""
|
return acc_proto_https, ""
|
||||||
}
|
}
|
||||||
current += 2
|
current += 2
|
||||||
hostname := ""
|
hostname := ""
|
||||||
|
@ -84,27 +83,30 @@ func sniNewParser(b []byte) (uint8, string) {
|
||||||
// Skip over number of names as we're assuming there's just one
|
// Skip over number of names as we're assuming there's just one
|
||||||
current += 2
|
current += 2
|
||||||
if current >= restLen {
|
if current >= restLen {
|
||||||
return acc_proto_tcp, ""
|
return acc_proto_https, ""
|
||||||
}
|
}
|
||||||
nameType := rest[current]
|
nameType := rest[current]
|
||||||
current += 1
|
current += 1
|
||||||
if nameType != 0 {
|
if nameType != 0 {
|
||||||
return acc_proto_tcp, ""
|
return acc_proto_https, ""
|
||||||
}
|
}
|
||||||
if current+1 >= restLen {
|
if current+1 >= restLen {
|
||||||
return acc_proto_tcp, ""
|
return acc_proto_https, ""
|
||||||
}
|
}
|
||||||
nameLen := (int(rest[current]) << 8) + int(rest[current+1])
|
nameLen := (int(rest[current]) << 8) + int(rest[current+1])
|
||||||
current += 2
|
current += 2
|
||||||
if current+nameLen >= restLen {
|
if current+nameLen >= restLen {
|
||||||
return acc_proto_tcp, ""
|
return acc_proto_https, ""
|
||||||
}
|
}
|
||||||
hostname = string(rest[current : current+nameLen])
|
hostname = string(rest[current : current+nameLen])
|
||||||
}
|
}
|
||||||
current += extensionDataLength
|
current += extensionDataLength
|
||||||
}
|
}
|
||||||
if hostname == "" {
|
if hostname == "" {
|
||||||
return acc_proto_tcp, ""
|
return acc_proto_https, ""
|
||||||
|
}
|
||||||
|
if !validDomainChar(hostname) {
|
||||||
|
return acc_proto_https, ""
|
||||||
}
|
}
|
||||||
return acc_proto_https, hostname
|
return acc_proto_https, hostname
|
||||||
}
|
}
|
||||||
|
@ -150,8 +152,7 @@ func httpNewParser(data []byte) (uint8, string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func sniParser(data []byte) (uint8, string) {
|
func sniParser(data []byte) (uint8, string) {
|
||||||
dataSize := len(data)
|
if len(data) < 2 || data[0] != 0x16 || data[1] != 0x03 {
|
||||||
if dataSize < 2 || data[0] != 0x16 || data[1] != 0x03 {
|
|
||||||
return acc_proto_tcp, ""
|
return acc_proto_tcp, ""
|
||||||
}
|
}
|
||||||
sniRe := regexp.MustCompile("\x00\x00.{4}\x00.{2}([a-z0-9]+([\\-\\.]{1}[a-z0-9]+)*\\.[a-z]{2,6})\x00")
|
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, ""
|
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) {
|
func TestNewSniParser(t *testing.T) {
|
||||||
ast := assert.New(t)
|
ast := assert.New(t)
|
||||||
data := handlerTcpPayload(httpsPacket)
|
data := handlerTcpPayload(httpsPacket)
|
||||||
_, sni := sniNewParser(data)
|
proto, sni := sniNewParser(data)
|
||||||
ast.Equal(sni, httpsSni)
|
ast.Equal(sni, httpsSni)
|
||||||
|
ast.Equal(int(proto), acc_proto_https)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewHttpParser(t *testing.T) {
|
func TestNewHttpParser(t *testing.T) {
|
||||||
ast := assert.New(t)
|
ast := assert.New(t)
|
||||||
// Host
|
// Host
|
||||||
data := handlerTcpPayload(httpPacket)
|
data := handlerTcpPayload(httpPacket)
|
||||||
_, hostname := httpNewParser(data)
|
proto, hostname := httpNewParser(data)
|
||||||
ast.Equal(hostname, httpHost)
|
ast.Equal(hostname, httpHost)
|
||||||
|
ast.Equal(int(proto), acc_proto_http)
|
||||||
// HOST
|
// HOST
|
||||||
data = handlerTcpPayload(httpPacket2)
|
data = handlerTcpPayload(httpPacket2)
|
||||||
_, hostname = httpNewParser(data)
|
proto, hostname = httpNewParser(data)
|
||||||
ast.Equal(hostname, httpHost)
|
ast.Equal(hostname, httpHost)
|
||||||
|
ast.Equal(int(proto), acc_proto_http)
|
||||||
// GET http://www.google.com/index.html HTTP/1.1
|
// GET http://www.google.com/index.html HTTP/1.1
|
||||||
data = handlerTcpPayload(httpPacket3)
|
data = handlerTcpPayload(httpPacket3)
|
||||||
_, hostname = httpNewParser(data)
|
proto, hostname = httpNewParser(data)
|
||||||
ast.Equal(hostname, httpHost)
|
ast.Equal(hostname, httpHost)
|
||||||
|
ast.Equal(int(proto), acc_proto_http)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue