From 84286de8a495581c3e034b07a7923fe843990a25 Mon Sep 17 00:00:00 2001 From: lanrenwo Date: Wed, 19 Oct 2022 11:23:17 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E8=A7=A3=E6=9E=90https+i?= =?UTF-8?q?p=E5=81=B6=E5=8F=91=E5=87=BA=E7=8E=B0sni=E4=B9=B1=E7=A0=81?= =?UTF-8?q?=E7=9A=84BUG?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/handler/payload_access_audit.go | 17 +++++++--- server/handler/payload_tcp_parser.go | 43 +++++++++++++++++--------- server/handler/payload_test.go | 12 ++++--- 3 files changed, 48 insertions(+), 24 deletions(-) diff --git a/server/handler/payload_access_audit.go b/server/handler/payload_access_audit.go index 0ad9ea4..25ca7b3 100644 --- a/server/handler/payload_access_audit.go +++ b/server/handler/payload_access_audit.go @@ -3,7 +3,6 @@ package handler import ( "crypto/md5" "encoding/binary" - "encoding/hex" "time" "github.com/bjdgyc/anylink/base" @@ -109,6 +108,7 @@ 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) info := "" nu := utils.NowSec().Unix() @@ -149,16 +149,23 @@ 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[:]) + } + } else { + // 清空数据, 碰到使用上一个域名信息的问题 + copy(key[35:51], []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}) } case flags & 0x19: // URG diff --git a/server/handler/payload_tcp_parser.go b/server/handler/payload_tcp_parser.go index b2e92bf..cd0e581 100644 --- a/server/handler/payload_tcp_parser.go +++ b/server/handler/payload_tcp_parser.go @@ -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 +} diff --git a/server/handler/payload_test.go b/server/handler/payload_test.go index f36a08c..fc5358b 100644 --- a/server/handler/payload_test.go +++ b/server/handler/payload_test.go @@ -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) } From 28489dcbc623527f0be10ac31903991c402087ad Mon Sep 17 00:00:00 2001 From: lanrenwo Date: Wed, 19 Oct 2022 11:53:31 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E9=87=8D=E7=BD=AEgetByte51=E5=80=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/handler/payload_access_audit.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/server/handler/payload_access_audit.go b/server/handler/payload_access_audit.go index 25ca7b3..4697c87 100644 --- a/server/handler/payload_access_audit.go +++ b/server/handler/payload_access_audit.go @@ -109,6 +109,7 @@ func logAudit(cSess *sessdata.ConnSession, pl *sessdata.Payload) { 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() @@ -163,9 +164,6 @@ func logAudit(cSess *sessdata.ConnSession, pl *sessdata.Payload) { md5Sum := md5.Sum([]byte(info)) copy(key[35:51], md5Sum[:]) } - } else { - // 清空数据, 碰到使用上一个域名信息的问题 - copy(key[35:51], []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}) } case flags & 0x19: // URG