diff --git a/analyzer/tcp/trojan.go b/analyzer/tcp/trojan.go index cf8c307..a91983b 100644 --- a/analyzer/tcp/trojan.go +++ b/analyzer/tcp/trojan.go @@ -13,10 +13,11 @@ var ccsPattern = []byte{20, 3, 3, 0, 1, 1} // TrojanAnalyzer uses length-based heuristics to detect Trojan traffic based on // its "TLS-in-TLS" nature. The heuristics are trained using a decision tree with -// about 2000 samples. This is highly experimental and is known to have significant -// false positives (about 9% false positives & 3% false negatives). -// We do NOT recommend directly blocking all positive connections, as this is likely -// to break many normal TLS connections. +// about 20k Trojan samples and 30k non-Trojan samples. The tree is then converted +// to code using a custom tool and inlined here (isTrojanSeq function). +// Accuracy: 1% false positive rate, 10% false negative rate. +// We do NOT recommend directly blocking all positive connections, as this may +// break legitimate TLS connections. type TrojanAnalyzer struct{} func (a *TrojanAnalyzer) Name() string { @@ -36,7 +37,7 @@ type trojanStream struct { first bool count bool rev bool - seq [3]int + seq [4]int seqIndex int } @@ -73,16 +74,12 @@ func (s *trojanStream) Feed(rev, start, end bool, skip int, data []byte) (u *ana } else { // Different direction, bump the index s.seqIndex += 1 - if s.seqIndex == 3 { - // Time to evaluate - yes := s.seq[0] >= 180 && - s.seq[1] <= 11000 && - s.seq[2] >= 40 + if s.seqIndex == 4 { return &analyzer.PropUpdate{ Type: analyzer.PropUpdateReplace, M: analyzer.PropMap{ "seq": s.seq, - "yes": yes, + "yes": isTrojanSeq(s.seq), }, }, true } @@ -97,3 +94,424 @@ func (s *trojanStream) Feed(rev, start, end bool, skip int, data []byte) (u *ana func (s *trojanStream) Close(limited bool) *analyzer.PropUpdate { return nil } + +func isTrojanSeq(seq [4]int) bool { + length1 := seq[0] + length2 := seq[1] + length3 := seq[2] + length4 := seq[3] + + if length2 <= 2431 { + if length2 <= 157 { + if length1 <= 156 { + if length3 <= 108 { + return false + } else { + return false + } + } else { + if length1 <= 892 { + if length3 <= 40 { + return false + } else { + if length3 <= 788 { + if length4 <= 185 { + if length1 <= 411 { + return true + } else { + return false + } + } else { + if length2 <= 112 { + return false + } else { + return true + } + } + } else { + if length3 <= 1346 { + if length1 <= 418 { + return false + } else { + return true + } + } else { + return false + } + } + } + } else { + if length2 <= 120 { + if length2 <= 63 { + return false + } else { + if length4 <= 653 { + return false + } else { + return false + } + } + } else { + return false + } + } + } + } else { + if length1 <= 206 { + if length1 <= 185 { + if length1 <= 171 { + return false + } else { + if length4 <= 211 { + return false + } else { + return false + } + } + } else { + if length2 <= 251 { + return true + } else { + return false + } + } + } else { + if length2 <= 286 { + if length1 <= 1123 { + if length3 <= 70 { + return false + } else { + if length1 <= 659 { + if length3 <= 370 { + return true + } else { + return false + } + } else { + if length4 <= 272 { + return false + } else { + return true + } + } + } + } else { + if length4 <= 537 { + if length2 <= 276 { + if length3 <= 1877 { + return false + } else { + return false + } + } else { + return false + } + } else { + if length1 <= 1466 { + if length1 <= 1435 { + return false + } else { + return true + } + } else { + if length2 <= 193 { + return false + } else { + return false + } + } + } + } + } else { + if length1 <= 284 { + if length1 <= 277 { + if length2 <= 726 { + return false + } else { + if length2 <= 768 { + return true + } else { + return false + } + } + } else { + if length2 <= 782 { + if length4 <= 783 { + return true + } else { + return false + } + } else { + return false + } + } + } else { + if length2 <= 492 { + if length2 <= 396 { + if length2 <= 322 { + return false + } else { + return false + } + } else { + if length4 <= 971 { + return false + } else { + return true + } + } + } else { + if length2 <= 2128 { + if length2 <= 1418 { + return false + } else { + return false + } + } else { + if length3 <= 103 { + return false + } else { + return false + } + } + } + } + } + } + } + } else { + if length2 <= 6232 { + if length3 <= 85 { + if length2 <= 3599 { + return false + } else { + if length1 <= 613 { + return false + } else { + return false + } + } + } else { + if length3 <= 220 { + if length4 <= 1173 { + if length1 <= 874 { + if length4 <= 337 { + if length4 <= 68 { + return true + } else { + return true + } + } else { + if length1 <= 667 { + return true + } else { + return true + } + } + } else { + if length3 <= 108 { + if length1 <= 1930 { + return true + } else { + return true + } + } else { + if length2 <= 5383 { + return false + } else { + return true + } + } + } + } else { + return false + } + } else { + if length1 <= 664 { + if length3 <= 411 { + if length3 <= 383 { + if length4 <= 346 { + return true + } else { + return false + } + } else { + if length1 <= 445 { + return true + } else { + return false + } + } + } else { + if length2 <= 3708 { + if length4 <= 307 { + return true + } else { + return false + } + } else { + if length2 <= 4656 { + return false + } else { + return false + } + } + } + } else { + if length1 <= 1055 { + if length3 <= 580 { + if length1 <= 724 { + return true + } else { + return false + } + } else { + if length1 <= 678 { + return false + } else { + return true + } + } + } else { + if length2 <= 5352 { + if length3 <= 1586 { + return false + } else { + return false + } + } else { + if length4 <= 2173 { + return true + } else { + return false + } + } + } + } + } + } + } else { + if length2 <= 9408 { + if length1 <= 670 { + if length4 <= 76 { + if length3 <= 175 { + return true + } else { + return true + } + } else { + if length2 <= 9072 { + if length3 <= 314 { + if length3 <= 179 { + return false + } else { + return false + } + } else { + if length4 <= 708 { + return false + } else { + return false + } + } + } else { + return true + } + } + } else { + if length1 <= 795 { + if length2 <= 6334 { + if length2 <= 6288 { + return true + } else { + return false + } + } else { + if length4 <= 6404 { + if length2 <= 8194 { + return true + } else { + return true + } + } else { + if length2 <= 8924 { + return false + } else { + return true + } + } + } + } else { + if length3 <= 732 { + if length1 <= 1397 { + if length3 <= 179 { + return false + } else { + return false + } + } else { + if length1 <= 1976 { + return false + } else { + return false + } + } + } else { + if length1 <= 2840 { + if length1 <= 2591 { + return false + } else { + return true + } + } else { + return false + } + } + } + } + } else { + if length4 <= 30 { + return false + } else { + if length2 <= 13314 { + if length4 <= 1786 { + if length2 <= 13018 { + if length4 <= 869 { + return false + } else { + return false + } + } else { + return true + } + } else { + if length3 <= 775 { + return false + } else { + return false + } + } + } else { + if length4 <= 73 { + return false + } else { + if length3 <= 640 { + if length3 <= 237 { + return false + } else { + return false + } + } else { + if length2 <= 43804 { + return false + } else { + return false + } + } + } + } + } + } + } + } +}