add trojan support
This commit is contained in:
@@ -39,6 +39,8 @@ func String2Proxy(link string) proxy.Proxy {
|
||||
data, err = proxy.ParseVmessLink(link)
|
||||
} else if strings.HasPrefix(link, "ss://") {
|
||||
data, err = proxy.ParseSSLink(link)
|
||||
} else if strings.HasPrefix(link, "trojan://") {
|
||||
data, err = proxy.ParseTrojanLink(link)
|
||||
}
|
||||
if err != nil {
|
||||
return nil
|
||||
|
||||
147
pkg/proxy/trojan.go
Normal file
147
pkg/proxy/trojan.go
Normal file
@@ -0,0 +1,147 @@
|
||||
package proxy
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"math/rand"
|
||||
"net"
|
||||
"net/url"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrorNotTrojanink = errors.New("not a correct trojan link")
|
||||
)
|
||||
|
||||
type Trojan struct {
|
||||
Base
|
||||
Password string `yaml:"password" json:"password"`
|
||||
ALPN []string `yaml:"alpn,omitempty" json:"alpn,omitempty"`
|
||||
SNI string `yaml:"sni,omitempty" json:"sni,omitempty"`
|
||||
SkipCertVerify bool `yaml:"skip-cert-verify,omitempty" json:"skip-cert-verify,omitempty"`
|
||||
UDP bool `yaml:"udp,omitempty" json:"udp,omitempty"`
|
||||
}
|
||||
|
||||
/**
|
||||
- name: "trojan"
|
||||
type: trojan
|
||||
server: server
|
||||
port: 443
|
||||
password: yourpsk
|
||||
# udp: true
|
||||
# sni: example.com # aka server name
|
||||
# alpn:
|
||||
# - h2
|
||||
# - http/1.1
|
||||
# skip-cert-verify: true
|
||||
*/
|
||||
|
||||
func (t Trojan) Identifier() string {
|
||||
return net.JoinHostPort(t.Server, strconv.Itoa(t.Port)) + t.Password
|
||||
}
|
||||
|
||||
func (t Trojan) String() string {
|
||||
data, err := json.Marshal(t)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return string(data)
|
||||
}
|
||||
|
||||
func (t Trojan) ToClash() string {
|
||||
data, err := json.Marshal(t)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return "- " + string(data)
|
||||
}
|
||||
|
||||
func (t Trojan) ToSurge() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (t Trojan) Clone() Proxy {
|
||||
return &t
|
||||
}
|
||||
|
||||
func ParseTrojanLink(link string) (*Trojan, error) {
|
||||
if !strings.HasPrefix(link, "trojan://") || !strings.HasPrefix(link, "trojan-go://") {
|
||||
return nil, ErrorNotSSRLink
|
||||
}
|
||||
|
||||
/**
|
||||
trojan-go://
|
||||
$(trojan-password)
|
||||
@
|
||||
trojan-host
|
||||
:
|
||||
port
|
||||
/?
|
||||
sni=$(tls-sni.com)&
|
||||
type=$(original|ws|h2|h2+ws)&
|
||||
host=$(websocket-host.com)&
|
||||
path=$(/websocket/path)&
|
||||
encryption=$(ss;aes-256-gcm;ss-password)&
|
||||
plugin=$(...)
|
||||
#$(descriptive-text)
|
||||
*/
|
||||
|
||||
uri, err := url.Parse(link)
|
||||
if err != nil {
|
||||
return nil, ErrorNotSSLink
|
||||
}
|
||||
|
||||
password := uri.User.Username()
|
||||
password, _ = url.QueryUnescape(password)
|
||||
|
||||
server := uri.Hostname()
|
||||
port, _ := strconv.Atoi(uri.Port())
|
||||
|
||||
moreInfos := uri.Query()
|
||||
sni := moreInfos.Get("sni")
|
||||
sni, _ = url.QueryUnescape(sni)
|
||||
transformType := moreInfos.Get("type")
|
||||
transformType, _ = url.QueryUnescape(transformType)
|
||||
host := moreInfos.Get("host")
|
||||
host, _ = url.QueryUnescape(host)
|
||||
path := moreInfos.Get("path")
|
||||
path, _ = url.QueryUnescape(path)
|
||||
|
||||
alpn := make([]string, 0)
|
||||
if transformType == "h2" {
|
||||
alpn = append(alpn, "h2")
|
||||
}
|
||||
|
||||
if port == 0 {
|
||||
return nil, ErrorNotTrojanink
|
||||
}
|
||||
|
||||
return &Trojan{
|
||||
Base: Base{
|
||||
Name: strconv.Itoa(rand.Int()),
|
||||
Server: server,
|
||||
Port: port,
|
||||
Type: "trojan",
|
||||
},
|
||||
Password: password,
|
||||
ALPN: alpn,
|
||||
UDP: true,
|
||||
SNI: host,
|
||||
SkipCertVerify: true,
|
||||
}, nil
|
||||
}
|
||||
|
||||
var (
|
||||
trojanPlainRe = regexp.MustCompile("trojan(-go)?://([A-Za-z0-9+/_&?=@:%.-])+")
|
||||
)
|
||||
|
||||
func GrepTrojanLinkFromString(text string) []string {
|
||||
results := make([]string, 0)
|
||||
texts := strings.Split(text, "trojan://")
|
||||
for _, text := range texts {
|
||||
results = append(results, ssPlainRe.FindAllString("trojan://"+text, -1)...)
|
||||
}
|
||||
return results
|
||||
}
|
||||
Reference in New Issue
Block a user