glider/proxy/trojan/trojan.go

86 lines
1.8 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 {
2020-10-11 19:53:38 +08:00
dialer proxy.Dialer
proxy proxy.Proxy
addr string
pass [56]byte
withTLS bool
tlsConfig *tls.Config
2020-04-08 01:09:51 +08:00
serverName string
skipVerify bool
2020-10-11 19:53:38 +08:00
certFile string
keyFile string
fallback string
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,
2020-10-11 19:53:38 +08:00
withTLS: true,
skipVerify: query.Get("skipVerify") == "true",
serverName: query.Get("serverName"),
certFile: query.Get("cert"),
keyFile: query.Get("key"),
fallback: query.Get("fallback"),
}
2021-04-19 10:39:40 +08:00
if _, port, _ := net.SplitHostPort(t.addr); port == "" {
t.addr = net.JoinHostPort(t.addr, "443")
}
if t.serverName == "" {
t.serverName = t.addr[:strings.LastIndex(t.addr, ":")]
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
}
2022-02-15 21:34:55 +08:00
func init() {
proxy.AddUsage("trojan", `
Trojan client scheme:
trojan://pass@host:port[?serverName=SERVERNAME][&skipVerify=true][&cert=PATH]
trojanc://pass@host:port (cleartext, without TLS)
Trojan server scheme:
trojan://pass@host:port?cert=PATH&key=PATH[&fallback=127.0.0.1]
trojanc://pass@host:port[?fallback=127.0.0.1] (cleartext, without TLS)
`)
}