Skip to content

Commit

Permalink
feat: Trojan analyzer based on github.com/XTLS/Trojan-killer
Browse files Browse the repository at this point in the history
  • Loading branch information
tobyxdd committed Jan 21, 2024
1 parent 00d88d7 commit 1041d5f
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 0 deletions.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ Linux that's in many ways more powerful than the real thing. It's cyber sovereig
- HTTP, TLS, DNS, SSH, and many more to come
- "Fully encrypted traffic" detection for Shadowsocks,
etc. (https://gfw.report/publications/usenixsecurity23/data/paper/paper.pdf)
- Trojan (proxy protocol) detection based on Trojan-killer (https://github.com/XTLS/Trojan-killer)
- [WIP] Machine learning based traffic classification
- Flow-based multicore load balancing
- Connection offloading
Expand Down Expand Up @@ -90,6 +91,10 @@ to [Expr Language Definition](https://expr-lang.org/docs/language-definition).
action: block
expr: fet != nil && fet.yes

- name: block trojan
action: block
expr: trojan != nil && trojan.yes

- name: v2ex dns poisoning
action: modify
modifier:
Expand Down
5 changes: 5 additions & 0 deletions README.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ OpenGFW 是一个 Linux 上灵活、易用、开源的 [GFW](https://zh.wikipedi
- 完整的 IP/TCP 重组,各种协议解析器
- HTTP, TLS, DNS, SSH, 更多协议正在开发中
- Shadowsocks 等 "全加密流量" 检测 (https://gfw.report/publications/usenixsecurity23/data/paper/paper.pdf)
- 基于 Trojan-killer 的 Trojan 检测 (https://github.com/XTLS/Trojan-killer)
- [开发中] 基于机器学习的流量分类
- 基于流的多核负载均衡
- 连接 offloading
Expand Down Expand Up @@ -85,6 +86,10 @@ workers:
action: block
expr: fet != nil && fet.yes

- name: block trojan
action: block
expr: trojan != nil && trojan.yes

- name: v2ex dns poisoning
action: modify
modifier:
Expand Down
91 changes: 91 additions & 0 deletions analyzer/tcp/trojan.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package tcp

import (
"bytes"

"github.com/apernet/OpenGFW/analyzer"
)

var _ analyzer.TCPAnalyzer = (*TrojanAnalyzer)(nil)

// CCS stands for "Change Cipher Spec"
var trojanCCS = []byte{20, 3, 3, 0, 1, 1}

const (
trojanUpLB = 650
trojanUpUB = 1000
trojanDownLB1 = 170
trojanDownUB1 = 180
trojanDownLB2 = 3000
trojanDownUB2 = 7500
)

// TrojanAnalyzer uses a very simple packet length based check to determine
// if a TLS connection is actually the Trojan proxy protocol.
// The algorithm is from the following project, with small modifications:
// https://github.com/XTLS/Trojan-killer
// Warning: Experimental only. This method is known to have significant false positives and false negatives.
type TrojanAnalyzer struct{}

func (a *TrojanAnalyzer) Name() string {
return "trojan"
}

func (a *TrojanAnalyzer) Limit() int {
return 16384
}

func (a *TrojanAnalyzer) NewTCP(info analyzer.TCPInfo, logger analyzer.Logger) analyzer.TCPStream {
return newTrojanStream(logger)
}

type trojanStream struct {
logger analyzer.Logger
active bool
upCount int
downCount int
}

func newTrojanStream(logger analyzer.Logger) *trojanStream {
return &trojanStream{logger: logger}
}

func (s *trojanStream) Feed(rev, start, end bool, skip int, data []byte) (u *analyzer.PropUpdate, done bool) {
if skip != 0 {
return nil, true
}
if len(data) == 0 {
return nil, false
}
if !rev && !s.active && len(data) >= 6 && bytes.Equal(data[:6], trojanCCS) {
// Client CCS encountered, start counting
s.active = true
}
if s.active {
if rev {
// Down direction
s.downCount += len(data)
} else {
// Up direction
if s.upCount >= trojanUpLB && s.upCount <= trojanUpUB &&
((s.downCount >= trojanDownLB1 && s.downCount <= trojanDownUB1) ||
(s.downCount >= trojanDownLB2 && s.downCount <= trojanDownUB2)) {
return &analyzer.PropUpdate{
Type: analyzer.PropUpdateReplace,
M: analyzer.PropMap{
"up": s.upCount,
"down": s.downCount,
"yes": true,
},
}, true
}
s.upCount += len(data)
}
}
// Give up when either direction is over the limit
return nil, s.upCount > trojanUpUB || s.downCount > trojanDownUB2
}

func (s *trojanStream) Close(limited bool) *analyzer.PropUpdate {
return nil
}
1 change: 1 addition & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ var analyzers = []analyzer.Analyzer{
&tcp.HTTPAnalyzer{},
&tcp.SSHAnalyzer{},
&tcp.TLSAnalyzer{},
&tcp.TrojanAnalyzer{},
&udp.DNSAnalyzer{},
}

Expand Down

0 comments on commit 1041d5f

Please sign in to comment.