Skip to content

Commit 89b50b8

Browse files
committed
feat: add draft support for trojan
1 parent 6010293 commit 89b50b8

4 files changed

Lines changed: 443 additions & 1 deletion

File tree

tcp/detect.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,3 +172,16 @@ func DetectMinecraft(r io.Reader, _ *Conn) string {
172172
}
173173
return ""
174174
}
175+
176+
func DetectTROJAN(r io.Reader, conn *Conn) string {
177+
var buf = make([]byte, 58)
178+
n, err := r.Read(buf)
179+
if err != nil || n != 58 {
180+
return ""
181+
}
182+
183+
if reflect.DeepEqual(buf[56:58], []byte("\r\n")) {
184+
return "TROJAN"
185+
}
186+
return ""
187+
}

trojan/metadata.go

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
package trojan
2+
3+
import (
4+
"encoding/binary"
5+
"errors"
6+
"fmt"
7+
"io"
8+
"net"
9+
"strconv"
10+
)
11+
12+
type Command byte
13+
14+
type AddressType byte
15+
16+
type Metadata struct {
17+
Command
18+
*Address
19+
}
20+
21+
const (
22+
IPv4 AddressType = 1
23+
DomainName AddressType = 3
24+
IPv6 AddressType = 4
25+
)
26+
27+
type Address struct {
28+
DomainName string
29+
Port int
30+
NetworkType string
31+
net.IP
32+
AddressType
33+
}
34+
35+
func (r *Metadata) ReadFrom(rr io.Reader) error {
36+
byteBuf := [1]byte{}
37+
_, err := io.ReadFull(rr, byteBuf[:])
38+
if err != nil {
39+
return err
40+
}
41+
r.Command = Command(byteBuf[0])
42+
r.Address = new(Address)
43+
err = r.Address.ReadFrom(rr)
44+
if err != nil {
45+
return errors.New("failed to parse address")
46+
}
47+
return nil
48+
}
49+
50+
func (a *Address) ReadFrom(r io.Reader) error {
51+
byteBuf := [1]byte{}
52+
_, err := io.ReadFull(r, byteBuf[:])
53+
if err != nil {
54+
return fmt.Errorf("unable to read ATYP: %w", err)
55+
}
56+
a.AddressType = AddressType(byteBuf[0])
57+
switch a.AddressType {
58+
case IPv4:
59+
var buf [6]byte
60+
_, err := io.ReadFull(r, buf[:])
61+
if err != nil {
62+
return fmt.Errorf("failed to read IPv4: %w", err)
63+
}
64+
a.IP = buf[0:4]
65+
a.Port = int(binary.BigEndian.Uint16(buf[4:6]))
66+
case IPv6:
67+
var buf [18]byte
68+
_, err := io.ReadFull(r, buf[:])
69+
if err != nil {
70+
return fmt.Errorf("failed to read IPv6: %w", err)
71+
}
72+
a.IP = buf[0:16]
73+
a.Port = int(binary.BigEndian.Uint16(buf[16:18]))
74+
case DomainName:
75+
_, err := io.ReadFull(r, byteBuf[:])
76+
length := byteBuf[0]
77+
if err != nil {
78+
return fmt.Errorf("failed to read domain name length: %w", err)
79+
}
80+
buf := make([]byte, length+2)
81+
_, err = io.ReadFull(r, buf)
82+
if err != nil {
83+
return fmt.Errorf("failed to read domain name: %w", err)
84+
}
85+
host := buf[0:length]
86+
if ip := net.ParseIP(string(host)); ip != nil {
87+
a.IP = ip
88+
if ip.To4() != nil {
89+
a.AddressType = IPv4
90+
} else {
91+
a.AddressType = IPv6
92+
}
93+
} else {
94+
a.DomainName = string(host)
95+
}
96+
a.Port = int(binary.BigEndian.Uint16(buf[length : length+2]))
97+
default:
98+
return fmt.Errorf("invalid ATYP %s", strconv.FormatInt(int64(a.AddressType), 10))
99+
}
100+
return nil
101+
}
102+
103+
func (a *Address) WriteTo(w io.Writer) error {
104+
_, err := w.Write([]byte{byte(a.AddressType)})
105+
if err != nil {
106+
return err
107+
}
108+
switch a.AddressType {
109+
case DomainName:
110+
w.Write([]byte{byte(len(a.DomainName))})
111+
_, err = w.Write([]byte(a.DomainName))
112+
case IPv4:
113+
_, err = w.Write(a.IP.To4())
114+
case IPv6:
115+
_, err = w.Write(a.IP.To16())
116+
default:
117+
return fmt.Errorf("invalid ATYP %s", strconv.FormatInt(int64(a.AddressType), 10))
118+
}
119+
if err != nil {
120+
return err
121+
}
122+
port := [2]byte{}
123+
binary.BigEndian.PutUint16(port[:], uint16(a.Port))
124+
_, err = w.Write(port[:])
125+
return err
126+
}

0 commit comments

Comments
 (0)