glider/proxy/trojan/trojan.go

83 lines
1.5 KiB
Go
Raw Normal View History

2020-04-08 01:09:51 +08:00
// protocol spec:
// https://trojan-gfw.github.io/trojan/protocol
package trojan
import (
"crypto/sha256"
"crypto/tls"
"encoding/hex"
"errors"
"fmt"
2020-04-08 01:09:51 +08:00
"net"
"net/url"
2020-10-08 18:48:23 +08:00
"strings"
2020-04-08 01:09:51 +08:00
"github.com/nadoo/glider/proxy"
)
2020-10-03 20:51:27 +08:00
// Trojan is a base trojan struct.
2020-04-08 01:09:51 +08:00
type Trojan struct {
dialer proxy.Dialer
proxy proxy.Proxy
addr string
pass [56]byte
clearText bool
tlsConfig *tls.Config
2020-04-08 01:09:51 +08:00
serverName string
skipVerify bool
certFile string
keyFile string
2020-04-08 01:09:51 +08:00
}
func init() {
proxy.RegisterDialer("trojan", NewTrojanDialer)
proxy.RegisterServer("trojan", NewTrojanServer)
proxy.RegisterDialer("trojanc", NewClearTextDialer) // cleartext
proxy.RegisterServer("trojanc", NewClearTextServer) // cleartext
2020-04-08 01:09:51 +08:00
}
// NewTrojan returns a trojan proxy.
func NewTrojan(s string, d proxy.Dialer, p proxy.Proxy) (*Trojan, error) {
u, err := url.Parse(s)
if err != nil {
return nil, fmt.Errorf("parse url err: %s", err)
2020-04-08 01:09:51 +08:00
}
query := u.Query()
2020-04-08 01:09:51 +08:00
t := &Trojan{
dialer: d,
proxy: p,
addr: u.Host,
skipVerify: query.Get("skipVerify") == "true",
serverName: query.Get("serverName"),
certFile: query.Get("cert"),
keyFile: query.Get("key"),
}
if t.serverName == "" {
2020-10-08 18:48:23 +08:00
idx := strings.LastIndex(t.addr, ":")
if idx == -1 {
idx = len(t.addr)
t.addr = net.JoinHostPort(t.addr, "443")
}
2020-10-08 18:48:23 +08:00
t.serverName = t.addr[:idx]
2020-04-08 01:09:51 +08:00
}
// pass
pass := u.User.Username()
if pass == "" {
return nil, errors.New("[trojan] password must be specified")
}
2020-04-08 01:09:51 +08:00
hash := sha256.New224()
hash.Write([]byte(pass))
2020-04-08 01:09:51 +08:00
hex.Encode(t.pass[:], hash.Sum(nil))
return t, nil
}