mirror of
https://github.com/nadoo/glider.git
synced 2025-02-23 17:35:40 +08:00
83 lines
1.5 KiB
Go
83 lines
1.5 KiB
Go
// protocol spec:
|
|
// https://trojan-gfw.github.io/trojan/protocol
|
|
|
|
package trojan
|
|
|
|
import (
|
|
"crypto/sha256"
|
|
"crypto/tls"
|
|
"encoding/hex"
|
|
"errors"
|
|
"fmt"
|
|
"net"
|
|
"net/url"
|
|
"strings"
|
|
|
|
"github.com/nadoo/glider/proxy"
|
|
)
|
|
|
|
// Trojan is a base trojan struct.
|
|
type Trojan struct {
|
|
dialer proxy.Dialer
|
|
proxy proxy.Proxy
|
|
addr string
|
|
pass [56]byte
|
|
|
|
clearText bool
|
|
|
|
tlsConfig *tls.Config
|
|
|
|
serverName string
|
|
skipVerify bool
|
|
|
|
certFile string
|
|
keyFile string
|
|
}
|
|
|
|
func init() {
|
|
proxy.RegisterDialer("trojan", NewTrojanDialer)
|
|
proxy.RegisterServer("trojan", NewTrojanServer)
|
|
proxy.RegisterDialer("trojanc", NewClearTextDialer) // cleartext
|
|
proxy.RegisterServer("trojanc", NewClearTextServer) // cleartext
|
|
}
|
|
|
|
// 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)
|
|
}
|
|
|
|
query := u.Query()
|
|
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 == "" {
|
|
idx := strings.LastIndex(t.addr, ":")
|
|
if idx == -1 {
|
|
idx = len(t.addr)
|
|
t.addr = net.JoinHostPort(t.addr, "443")
|
|
}
|
|
t.serverName = t.addr[:idx]
|
|
}
|
|
|
|
// pass
|
|
pass := u.User.Username()
|
|
if pass == "" {
|
|
return nil, errors.New("[trojan] password must be specified")
|
|
}
|
|
|
|
hash := sha256.New224()
|
|
hash.Write([]byte(pass))
|
|
hex.Encode(t.pass[:], hash.Sum(nil))
|
|
|
|
return t, nil
|
|
}
|