mirror of
https://github.com/p4gefau1t/trojan-go.git
synced 2024-04-21 12:21:34 +00:00
add shadowsocks aead
This commit is contained in:
+1
-1
@@ -11,7 +11,7 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
Version = "v0.6.1"
|
||||
Version = "v0.7.0"
|
||||
)
|
||||
|
||||
type Runnable interface {
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@ enableMissingTranslationPlaceholders = false
|
||||
# Source Code repository section
|
||||
description = "An unidentifiable mechanism that helps you bypass GFW. "
|
||||
github_repository = "https://github.com/p4gefau1t/trojan-go"
|
||||
version = "0.6.1"
|
||||
version = "0.7.0"
|
||||
|
||||
# Documentation repository section
|
||||
# documentation repository (set edit link to documentation repository)
|
||||
|
||||
@@ -8,6 +8,7 @@ require (
|
||||
github.com/golang/protobuf v1.3.2
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
|
||||
github.com/refraction-networking/utls v0.0.0-20200601200209-ada0bb9b38a0
|
||||
github.com/shadowsocks/go-shadowsocks2 v0.1.0
|
||||
github.com/smartystreets/goconvey v1.6.4
|
||||
github.com/xtaci/smux v1.5.15-0.20200523091831-637399ad4398
|
||||
golang.org/x/crypto v0.0.0-20200602180216-279210d13fed
|
||||
|
||||
@@ -2,14 +2,19 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/LiamHaworth/go-tproxy v0.0.0-20190726054950-ef7efd7f24ed h1:eqa6queieK8SvoszxCu0WwH7lSVeL4/N/f1JwOMw1G4=
|
||||
github.com/LiamHaworth/go-tproxy v0.0.0-20190726054950-ef7efd7f24ed/go.mod h1:rA52xkgZwql9LRZXWb2arHEFP6qSR48KY2xOfWzEciQ=
|
||||
github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da h1:KjTM2ks9d14ZYCvmHS9iAKVt9AyzRSqNU1qabPih5BY=
|
||||
github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da/go.mod h1:eHEWzANqSiWQsof+nXEI9bUVUyV6F53Fp89EuCh2EAA=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
|
||||
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.2.0 h1:28o5sBqPkBsMGnC6b4MvE2TzSr5/AT4c/1fLqVGIwlk=
|
||||
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
@@ -20,12 +25,15 @@ github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfV
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/miekg/dns v1.1.4 h1:rCMZsU2ScVSYcAsOXgmC6+AKOK+6pmQTOcw03nfwYV0=
|
||||
github.com/miekg/dns v1.1.4/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/refraction-networking/utls v0.0.0-20190909200633-43c36d3c1f57/go.mod h1:tz9gX959MEFfFN5whTIocCLUG57WiILqtdVxI8c6Wj0=
|
||||
github.com/refraction-networking/utls v0.0.0-20200601200209-ada0bb9b38a0 h1:vIkvetWOJZSADSKCF9MLTsQNW2httdBmYz47dQQteP8=
|
||||
github.com/refraction-networking/utls v0.0.0-20200601200209-ada0bb9b38a0/go.mod h1:tz9gX959MEFfFN5whTIocCLUG57WiILqtdVxI8c6Wj0=
|
||||
github.com/shadowsocks/go-shadowsocks2 v0.1.0 h1:jQhkjAmMuOTQ7B04bnrRJ5IAoZEwoaXXkKspE7rQ6ck=
|
||||
github.com/shadowsocks/go-shadowsocks2 v0.1.0/go.mod h1:/0aFGbhK8mtOX4J/6kTJsPLZlEs9KnzKoWCOCvjd7vk=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
|
||||
@@ -37,6 +45,7 @@ github.com/xtaci/smux v1.5.15-0.20200523091831-637399ad4398/go.mod h1:OMlQbT5vcg
|
||||
go.starlark.net v0.0.0-20190919145610-979af19b165c h1:WR7X1xgXJlXhQBdorVc9Db3RhwG+J/kp6bLuMyJjfVw=
|
||||
go.starlark.net v0.0.0-20190919145610-979af19b165c/go.mod h1:c1/X6cHgvdXj6pUlmWKMkuqRnW4K8x2vwt6JAaaircg=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191029031824-8986dd9e96cf/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200602180216-279210d13fed h1:g4KENRiCMEx58Q7/ecwfT0N2o8z35Fnbsjig/Alf2T4=
|
||||
golang.org/x/crypto v0.0.0-20200602180216-279210d13fed/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
@@ -45,11 +54,13 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980 h1:OjiUf46hAmXblsZdnoSXsEUSKU8r1UEzcL5RVZ4gO9Y=
|
||||
golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1 h1:NusfzzA6yGQ+ua51ck7E3omNUX/JuqbFSaRGqU8CcLI=
|
||||
golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
@@ -58,7 +69,9 @@ golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20180831171423-11092d34479b h1:lohp5blsw53GBXtLyLNaTXPXS9pJ1tiTw61ZHUoE9Qw=
|
||||
google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/grpc v1.24.0 h1:vb/1TCsVn3DcJlQ0Gs1yB1pKI6Do2/QNwxdKqmc/b0s=
|
||||
google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"github.com/p4gefau1t/trojan-go/tunnel"
|
||||
"github.com/p4gefau1t/trojan-go/tunnel/mux"
|
||||
"github.com/p4gefau1t/trojan-go/tunnel/router"
|
||||
"github.com/p4gefau1t/trojan-go/tunnel/shadowsocks"
|
||||
"github.com/p4gefau1t/trojan-go/tunnel/simplesocks"
|
||||
"github.com/p4gefau1t/trojan-go/tunnel/socks"
|
||||
"github.com/p4gefau1t/trojan-go/tunnel/transport"
|
||||
@@ -17,16 +18,19 @@ import (
|
||||
const Name = "CLIENT"
|
||||
|
||||
// GenerateClientTree generate general outbound protocol stack
|
||||
func GenerateClientTree(isMux bool, isWebsocket bool, isRouter bool) []string {
|
||||
func GenerateClientTree(muxEnabled bool, wsEnabled bool, ssEnabled bool, routerEnabled bool) []string {
|
||||
clientStack := []string{transport.Name}
|
||||
if isWebsocket {
|
||||
if wsEnabled {
|
||||
clientStack = append(clientStack, websocket.Name)
|
||||
}
|
||||
if ssEnabled {
|
||||
clientStack = append(clientStack, shadowsocks.Name)
|
||||
}
|
||||
clientStack = append(clientStack, trojan.Name)
|
||||
if isMux {
|
||||
if muxEnabled {
|
||||
clientStack = append(clientStack, []string{mux.Name, simplesocks.Name}...)
|
||||
}
|
||||
if isRouter {
|
||||
if routerEnabled {
|
||||
clientStack = append(clientStack, router.Name)
|
||||
}
|
||||
return clientStack
|
||||
@@ -36,7 +40,7 @@ func init() {
|
||||
proxy.RegisterProxyCreator(Name, func(ctx context.Context) (*proxy.Proxy, error) {
|
||||
cfg := config.FromContext(ctx, Name).(*Config)
|
||||
serverStack := []string{socks.Name}
|
||||
clientStack := GenerateClientTree(cfg.Mux.Enabled, cfg.Websocket.Enabled, cfg.Router.Enabled)
|
||||
clientStack := GenerateClientTree(cfg.Mux.Enabled, cfg.Websocket.Enabled, cfg.Shadowsocks.Enabled, cfg.Router.Enabled)
|
||||
c, err := proxy.CreateClientStack(ctx, clientStack)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -14,10 +14,15 @@ type RouterConfig struct {
|
||||
Enabled bool `json,yaml:"enabled"`
|
||||
}
|
||||
|
||||
type ShadowsocksConfig struct {
|
||||
Enabled bool `json,yaml:"enabled"`
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
Mux MuxConfig `json,yaml:"mux"`
|
||||
Websocket WebsocketConfig `json,yaml:"websocket"`
|
||||
Router RouterConfig `json,yaml:"router"`
|
||||
Mux MuxConfig `json,yaml:"mux"`
|
||||
Websocket WebsocketConfig `json,yaml:"websocket"`
|
||||
Router RouterConfig `json,yaml:"router"`
|
||||
Shadowsocks ShadowsocksConfig `json,yaml:"shadowsocks"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
|
||||
@@ -15,7 +15,7 @@ func init() {
|
||||
proxy.RegisterProxyCreator(Name, func(ctx context.Context) (*proxy.Proxy, error) {
|
||||
cfg := config.FromContext(ctx, Name).(*client.Config)
|
||||
serverStack := []string{dokodemo.Name}
|
||||
clientStack := client.GenerateClientTree(cfg.Mux.Enabled, cfg.Websocket.Enabled, cfg.Router.Enabled)
|
||||
clientStack := client.GenerateClientTree(cfg.Mux.Enabled, cfg.Websocket.Enabled, cfg.Shadowsocks.Enabled, cfg.Router.Enabled)
|
||||
c, err := proxy.CreateClientStack(ctx, clientStack)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
+3
-1
@@ -1,3 +1,5 @@
|
||||
// +build linux darwin
|
||||
|
||||
package nat
|
||||
|
||||
import (
|
||||
@@ -15,7 +17,7 @@ func init() {
|
||||
proxy.RegisterProxyCreator(Name, func(ctx context.Context) (*proxy.Proxy, error) {
|
||||
cfg := config.FromContext(ctx, Name).(*client.Config)
|
||||
serverStack := []string{tproxy.Name}
|
||||
clientStack := client.GenerateClientTree(cfg.Mux.Enabled, cfg.Websocket.Enabled, false)
|
||||
clientStack := client.GenerateClientTree(cfg.Mux.Enabled, cfg.Websocket.Enabled, cfg.Shadowsocks.Enabled, false)
|
||||
c, err := proxy.CreateClientStack(ctx, clientStack)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
+12
-7
@@ -21,16 +21,21 @@ func (o *Option) Handle() error {
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
isJSON := false
|
||||
if strings.HasSuffix(*o.path, ".json") {
|
||||
if err := RunProxy(data, true); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
isJSON = true
|
||||
} else if strings.HasSuffix(*o.path, ".yaml") {
|
||||
if err := RunProxy(data, false); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
isJSON = false
|
||||
} else {
|
||||
log.Fatal("unknown file suffix", *o.path)
|
||||
log.Fatal("unsupported filename suffix", *o.path, ". use .yaml or .json instead.")
|
||||
}
|
||||
proxy, err := NewProxyFromConfigData(data, isJSON)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
err = proxy.Run()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
+5
-12
@@ -154,31 +154,24 @@ func RegisterProxyCreator(name string, creator Creator) {
|
||||
creators[name] = creator
|
||||
}
|
||||
|
||||
func RunProxy(data []byte, isJSON bool) error {
|
||||
func NewProxyFromConfigData(data []byte, isJSON bool) (*Proxy, error) {
|
||||
ctx := context.Background()
|
||||
var err error
|
||||
if isJSON {
|
||||
ctx, err = config.WithJSONConfig(context.Background(), data)
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
ctx, err = config.WithYAMLConfig(context.Background(), data)
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
cfg := config.FromContext(ctx, Name).(*Config)
|
||||
create, ok := creators[strings.ToUpper(cfg.RunType)]
|
||||
if !ok {
|
||||
return common.NewError("unknown type " + cfg.RunType)
|
||||
return nil, common.NewError("unknown proxy type: " + cfg.RunType)
|
||||
}
|
||||
proxy, err := create(ctx)
|
||||
if err != nil {
|
||||
return common.NewError("failed to create proxy instance").Base(err)
|
||||
}
|
||||
if err := proxy.Run(); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
return nil
|
||||
return create(ctx)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"github.com/p4gefau1t/trojan-go/config"
|
||||
"github.com/p4gefau1t/trojan-go/proxy/client"
|
||||
)
|
||||
|
||||
func init() {
|
||||
config.RegisterConfigCreator(Name, func() interface{} {
|
||||
return new(client.Config)
|
||||
})
|
||||
}
|
||||
+29
-41
@@ -2,9 +2,12 @@ package server
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/p4gefau1t/trojan-go/config"
|
||||
"github.com/p4gefau1t/trojan-go/proxy"
|
||||
"github.com/p4gefau1t/trojan-go/proxy/client"
|
||||
"github.com/p4gefau1t/trojan-go/tunnel/mux"
|
||||
"github.com/p4gefau1t/trojan-go/tunnel/raw"
|
||||
"github.com/p4gefau1t/trojan-go/tunnel/shadowsocks"
|
||||
"github.com/p4gefau1t/trojan-go/tunnel/simplesocks"
|
||||
"github.com/p4gefau1t/trojan-go/tunnel/transport"
|
||||
"github.com/p4gefau1t/trojan-go/tunnel/trojan"
|
||||
@@ -16,53 +19,38 @@ const Name = "SERVER"
|
||||
func init() {
|
||||
proxy.RegisterProxyCreator(Name, func(ctx context.Context) (*proxy.Proxy, error) {
|
||||
clientStack := []string{raw.Name}
|
||||
serverTree := &proxy.Node{
|
||||
Name: transport.Name,
|
||||
Next: []*proxy.Node{
|
||||
{
|
||||
Name: trojan.Name,
|
||||
IsEndpoint: true,
|
||||
Next: []*proxy.Node{
|
||||
{
|
||||
Name: mux.Name,
|
||||
Next: []*proxy.Node{
|
||||
{
|
||||
Name: simplesocks.Name,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: websocket.Name,
|
||||
Next: []*proxy.Node{
|
||||
{
|
||||
Name: trojan.Name,
|
||||
IsEndpoint: true,
|
||||
Next: []*proxy.Node{
|
||||
{
|
||||
Name: mux.Name,
|
||||
Next: []*proxy.Node{
|
||||
{
|
||||
Name: simplesocks.Name,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
c, err := proxy.CreateClientStack(ctx, clientStack)
|
||||
cfg := config.FromContext(ctx, Name).(*client.Config)
|
||||
s, err := transport.NewServer(ctx, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s, err := proxy.CreateServersStacksTree(ctx, serverTree)
|
||||
root := &proxy.Node{
|
||||
Name: transport.Name,
|
||||
Next: make(map[string]*proxy.Node),
|
||||
IsEndpoint: false,
|
||||
Context: ctx,
|
||||
Server: s,
|
||||
}
|
||||
|
||||
root.BuildNext(trojan.Name).BuildNext(mux.Name).BuildNext(simplesocks.Name).IsEndpoint = true
|
||||
root.BuildNext(trojan.Name).IsEndpoint = true
|
||||
|
||||
wsSubTree := root.BuildNext(websocket.Name)
|
||||
if cfg.Shadowsocks.Enabled {
|
||||
wsSubTree = wsSubTree.BuildNext(shadowsocks.Name)
|
||||
}
|
||||
wsSubTree.BuildNext(trojan.Name).BuildNext(mux.Name).BuildNext(simplesocks.Name).IsEndpoint = true
|
||||
wsSubTree.BuildNext(trojan.Name).IsEndpoint = true
|
||||
|
||||
serverList := proxy.FindAllEndpoints(root)
|
||||
clientList, err := proxy.CreateClientStack(ctx, clientStack)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return proxy.NewProxy(ctx, s, c), nil
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return proxy.NewProxy(ctx, serverList, clientList), nil
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
+33
-1
@@ -2,16 +2,48 @@ package proxy
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/p4gefau1t/trojan-go/log"
|
||||
"github.com/p4gefau1t/trojan-go/tunnel"
|
||||
)
|
||||
|
||||
type Node struct {
|
||||
Name string
|
||||
Next []*Node
|
||||
Next map[string]*Node
|
||||
IsEndpoint bool
|
||||
context.Context
|
||||
tunnel.Server
|
||||
}
|
||||
|
||||
func (n *Node) BuildNext(name string) *Node {
|
||||
if next, found := n.Next[name]; found {
|
||||
return next
|
||||
}
|
||||
t, err := tunnel.GetTunnel(name)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
s, err := t.NewServer(n.Context, n.Server)
|
||||
newNode := &Node{
|
||||
Name: name,
|
||||
Next: make(map[string]*Node),
|
||||
Context: n.Context,
|
||||
Server: s,
|
||||
}
|
||||
n.Next[name] = newNode
|
||||
return newNode
|
||||
}
|
||||
|
||||
func FindAllEndpoints(root *Node) []tunnel.Server {
|
||||
list := make([]tunnel.Server, 0)
|
||||
if root.IsEndpoint || len(root.Next) == 0 {
|
||||
list = append(list, root.Server)
|
||||
}
|
||||
for _, next := range root.Next {
|
||||
list = append(list, FindAllEndpoints(next)...)
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
func buildServerStacksTree(ctx context.Context, current *Node, parent *Node) ([]tunnel.Server, error) {
|
||||
t, err := tunnel.GetTunnel(current.Name)
|
||||
if err != nil {
|
||||
|
||||
@@ -20,7 +20,7 @@ import (
|
||||
netproxy "golang.org/x/net/proxy"
|
||||
)
|
||||
|
||||
var cert string = `
|
||||
var cert = `
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDZTCCAk0CFFphZh018B5iAD9F5fV4y0AlD0LxMA0GCSqGSIb3DQEBCwUAMG8x
|
||||
CzAJBgNVBAYTAlVTMQ0wCwYDVQQIDARNYXJzMRMwEQYDVQQHDAppVHJhbnN3YXJw
|
||||
@@ -44,7 +44,7 @@ Haz8uKI4EciU
|
||||
-----END CERTIFICATE-----
|
||||
`
|
||||
|
||||
var key string = `
|
||||
var key = `
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpAIBAAKCAQEAml44fThYMkCcT627o7ibEs7mq2WOhImjDwYijYJ1684BatrC
|
||||
sHJNcw8PJGTuP+tgGdngmALjA3l+RipjaE/UK4FJrAjruphA/hOCjZfWqk8KBR4q
|
||||
@@ -98,12 +98,17 @@ websocket:
|
||||
enabled: true
|
||||
path: /ws
|
||||
hostname: 127.0.0.1
|
||||
shadowsocks:
|
||||
enabled: true
|
||||
method: AEAD_CHACHA20_POLY1305
|
||||
password: 12345678
|
||||
mux:
|
||||
enabled: true
|
||||
`, socksPort, serverPort)
|
||||
go func() {
|
||||
err := proxy.RunProxy([]byte(clientData), false)
|
||||
proxy, err := proxy.NewProxyFromConfigData([]byte(clientData), false)
|
||||
common.Must(err)
|
||||
common.Must(proxy.Run())
|
||||
}()
|
||||
|
||||
serverData := fmt.Sprintf(`
|
||||
@@ -118,15 +123,20 @@ ssl:
|
||||
verify-hostname: false
|
||||
key: server.key
|
||||
cert: server.crt
|
||||
sni: "localhost"
|
||||
sni: localhost
|
||||
shadowsocks:
|
||||
enabled: true
|
||||
method: AEAD_CHACHA20_POLY1305
|
||||
password: 12345678
|
||||
websocket:
|
||||
enabled: true
|
||||
path: /ws
|
||||
hostname: 127.0.0.1
|
||||
`, serverPort, util.HTTPPort)
|
||||
go func() {
|
||||
err := proxy.RunProxy([]byte(serverData), false)
|
||||
proxy, err := proxy.NewProxyFromConfigData([]byte(serverData), false)
|
||||
common.Must(err)
|
||||
common.Must(proxy.Run())
|
||||
}()
|
||||
|
||||
time.Sleep(time.Second * 2)
|
||||
@@ -168,12 +178,17 @@ websocket:
|
||||
enabled: true
|
||||
path: /ws
|
||||
hostname: 127.0.0.1
|
||||
shadowsocks:
|
||||
enabled: true
|
||||
method: AEAD_CHACHA20_POLY1305
|
||||
password: 12345678
|
||||
mux:
|
||||
enabled: true
|
||||
`, clientPort, serverPort, targetPort)
|
||||
go func() {
|
||||
err := proxy.RunProxy([]byte(clientData), false)
|
||||
proxy, err := proxy.NewProxyFromConfigData([]byte(clientData), false)
|
||||
common.Must(err)
|
||||
common.Must(proxy.Run())
|
||||
}()
|
||||
|
||||
serverData := fmt.Sprintf(`
|
||||
@@ -193,10 +208,15 @@ websocket:
|
||||
enabled: true
|
||||
path: /ws
|
||||
hostname: 127.0.0.1
|
||||
shadowsocks:
|
||||
enabled: true
|
||||
method: AEAD_CHACHA20_POLY1305
|
||||
password: 12345678
|
||||
`, serverPort, util.HTTPPort)
|
||||
go func() {
|
||||
err := proxy.RunProxy([]byte(serverData), false)
|
||||
proxy, err := proxy.NewProxyFromConfigData([]byte(serverData), false)
|
||||
common.Must(err)
|
||||
common.Must(proxy.Run())
|
||||
}()
|
||||
|
||||
time.Sleep(time.Second * 2)
|
||||
|
||||
@@ -94,7 +94,7 @@ func (c *Client) newMuxClient() (*smuxClientInfo, error) {
|
||||
// The mutex should be locked when this function is called
|
||||
id := generateMuxID()
|
||||
if _, found := c.clientPool[id]; found {
|
||||
return nil, common.NewError("Duplicated id")
|
||||
return nil, common.NewError("duplicated id")
|
||||
}
|
||||
|
||||
fakeAddr := &tunnel.Address{
|
||||
@@ -129,7 +129,7 @@ func (c *Client) DialConn(addr *tunnel.Address, _ tunnel.Tunnel) (tunnel.Conn, e
|
||||
rwc, err := info.client.Open()
|
||||
info.lastActiveTime = time.Now()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, common.NewError("mux failed to open stream from client").Base(err)
|
||||
}
|
||||
return &Conn{
|
||||
rwc: rwc,
|
||||
|
||||
@@ -197,6 +197,7 @@ func (c *Client) DialPacket(overlay tunnel.Tunnel) (tunnel.PacketConn, error) {
|
||||
}
|
||||
ctx, cancel := context.WithCancel(c.Context)
|
||||
return &PacketConn{
|
||||
Client: c,
|
||||
PacketConn: direct,
|
||||
proxy: proxy,
|
||||
CancelFunc: cancel,
|
||||
|
||||
@@ -6,9 +6,11 @@ import (
|
||||
"github.com/p4gefau1t/trojan-go/config"
|
||||
"github.com/p4gefau1t/trojan-go/test/util"
|
||||
"github.com/p4gefau1t/trojan-go/tunnel"
|
||||
"net"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
type MockClient struct{}
|
||||
@@ -18,13 +20,53 @@ func (m *MockClient) DialConn(address *tunnel.Address, t tunnel.Tunnel) (tunnel.
|
||||
}
|
||||
|
||||
func (m *MockClient) DialPacket(t tunnel.Tunnel) (tunnel.PacketConn, error) {
|
||||
return nil, common.NewError("mockproxy")
|
||||
//return nil, common.NewError("mockproxy")
|
||||
return MockPacketConn{}, nil
|
||||
}
|
||||
|
||||
func (m MockClient) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type MockPacketConn struct {
|
||||
}
|
||||
|
||||
func (m MockPacketConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (m MockPacketConn) WriteTo(p []byte, addr net.Addr) (n int, err error) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (m MockPacketConn) Close() error {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (m MockPacketConn) LocalAddr() net.Addr {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (m MockPacketConn) SetDeadline(t time.Time) error {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (m MockPacketConn) SetReadDeadline(t time.Time) error {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (m MockPacketConn) SetWriteDeadline(t time.Time) error {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (m MockPacketConn) WriteWithMetadata(bytes []byte, metadata *tunnel.Metadata) (int, error) {
|
||||
return 0, common.NewError("mockproxy")
|
||||
}
|
||||
|
||||
func (m MockPacketConn) ReadWithMetadata(bytes []byte) (int, *tunnel.Metadata, error) {
|
||||
return 0, nil, common.NewError("mockproxy")
|
||||
}
|
||||
|
||||
func TestRouter(t *testing.T) {
|
||||
data := `
|
||||
router:
|
||||
@@ -90,4 +132,18 @@ router:
|
||||
if err != nil {
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
packet, err := client.DialPacket(nil)
|
||||
common.Must(err)
|
||||
buf := [10]byte{}
|
||||
_, err = packet.WriteWithMetadata(buf[:], &tunnel.Metadata{
|
||||
Address: &tunnel.Address{
|
||||
AddressType: tunnel.DomainName,
|
||||
DomainName: "proxyfull",
|
||||
Port: port,
|
||||
},
|
||||
})
|
||||
if err.Error() != "mockproxy" {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
package shadowsocks
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/p4gefau1t/trojan-go/common"
|
||||
"github.com/p4gefau1t/trojan-go/config"
|
||||
"github.com/p4gefau1t/trojan-go/log"
|
||||
"github.com/p4gefau1t/trojan-go/tunnel"
|
||||
"github.com/p4gefau1t/trojan-go/tunnel/transport"
|
||||
"github.com/shadowsocks/go-shadowsocks2/core"
|
||||
)
|
||||
|
||||
type Client struct {
|
||||
underlay tunnel.Client
|
||||
core.Cipher
|
||||
}
|
||||
|
||||
func (c *Client) DialConn(address *tunnel.Address, tunnel tunnel.Tunnel) (tunnel.Conn, error) {
|
||||
conn, err := c.underlay.DialConn(address, tunnel)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &transport.Conn{
|
||||
Conn: c.Cipher.StreamConn(conn),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *Client) DialPacket(tunnel tunnel.Tunnel) (tunnel.PacketConn, error) {
|
||||
panic("not supported")
|
||||
}
|
||||
|
||||
func (c *Client) Close() error {
|
||||
return c.underlay.Close()
|
||||
}
|
||||
|
||||
func NewClient(ctx context.Context, underlay tunnel.Client) (*Client, error) {
|
||||
cfg := config.FromContext(ctx, Name).(*Config)
|
||||
cipher, err := core.PickCipher(cfg.Shadowsocks.Method, nil, cfg.Shadowsocks.Password)
|
||||
if err != nil {
|
||||
return nil, common.NewError("invalid shadowsocks cipher").Base(err)
|
||||
}
|
||||
log.Info("shadowsocks client created")
|
||||
return &Client{
|
||||
underlay: underlay,
|
||||
Cipher: cipher,
|
||||
}, nil
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package shadowsocks
|
||||
|
||||
import "github.com/p4gefau1t/trojan-go/config"
|
||||
|
||||
type ShadowsocksConfig struct {
|
||||
Enabled bool `json,yaml:"enabled"`
|
||||
Method string `json,yaml:"method"`
|
||||
Password string `json,yaml:"password"`
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
Shadowsocks ShadowsocksConfig `json,yaml:"shadowsocks"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
config.RegisterConfigCreator(Name, func() interface{} {
|
||||
return new(Config)
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package shadowsocks
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/p4gefau1t/trojan-go/common"
|
||||
"github.com/p4gefau1t/trojan-go/config"
|
||||
"github.com/p4gefau1t/trojan-go/log"
|
||||
"github.com/p4gefau1t/trojan-go/tunnel"
|
||||
"github.com/p4gefau1t/trojan-go/tunnel/transport"
|
||||
"github.com/shadowsocks/go-shadowsocks2/core"
|
||||
)
|
||||
|
||||
type Server struct {
|
||||
underlay tunnel.Server
|
||||
core.Cipher
|
||||
}
|
||||
|
||||
func (s *Server) AcceptConn(overlay tunnel.Tunnel) (tunnel.Conn, error) {
|
||||
conn, err := s.underlay.AcceptConn(overlay)
|
||||
if err != nil {
|
||||
return nil, common.NewError("shadowsocks failed to accept connection from underlying tunnel")
|
||||
}
|
||||
return &transport.Conn{
|
||||
Conn: s.Cipher.StreamConn(conn),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Server) AcceptPacket(t tunnel.Tunnel) (tunnel.PacketConn, error) {
|
||||
panic("not supported")
|
||||
}
|
||||
|
||||
func (s *Server) Close() error {
|
||||
return s.underlay.Close()
|
||||
}
|
||||
|
||||
func NewServer(ctx context.Context, underlay tunnel.Server) (*Server, error) {
|
||||
cfg := config.FromContext(ctx, Name).(*Config)
|
||||
cipher, err := core.PickCipher(cfg.Shadowsocks.Method, nil, cfg.Shadowsocks.Password)
|
||||
if err != nil {
|
||||
return nil, common.NewError("invalid shadowsocks cipher").Base(err)
|
||||
}
|
||||
log.Info("shadowsocks client created")
|
||||
return &Server{
|
||||
underlay: underlay,
|
||||
Cipher: cipher,
|
||||
}, nil
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package shadowsocks
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/p4gefau1t/trojan-go/common"
|
||||
"github.com/p4gefau1t/trojan-go/config"
|
||||
"github.com/p4gefau1t/trojan-go/test/util"
|
||||
"github.com/p4gefau1t/trojan-go/tunnel"
|
||||
"github.com/p4gefau1t/trojan-go/tunnel/raw"
|
||||
"net"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestShadowsocks(t *testing.T) {
|
||||
cfg := &Config{
|
||||
Shadowsocks: ShadowsocksConfig{
|
||||
Enabled: true,
|
||||
Method: "AES-128-GCM",
|
||||
Password: "password",
|
||||
},
|
||||
}
|
||||
ctx := config.WithConfig(context.Background(), Name, cfg)
|
||||
port := common.PickPort("tcp", "127.0.0.1")
|
||||
addr := &tunnel.Address{
|
||||
AddressType: tunnel.IPv4,
|
||||
IP: net.ParseIP("127.0.0.1"),
|
||||
Port: port,
|
||||
}
|
||||
tcpServer, err := raw.NewServer(addr)
|
||||
common.Must(err)
|
||||
tcpClient := &raw.FixedClient{
|
||||
FixedAddr: addr,
|
||||
}
|
||||
c, err := NewClient(ctx, tcpClient)
|
||||
common.Must(err)
|
||||
s, err := NewServer(ctx, tcpServer)
|
||||
common.Must(err)
|
||||
conn1, err := c.DialConn(nil, nil)
|
||||
common.Must(err)
|
||||
conn2, err := s.AcceptConn(nil)
|
||||
common.Must(err)
|
||||
util.CheckConn(conn1, conn2)
|
||||
}
|
||||
@@ -1 +1,26 @@
|
||||
package shadowsocks
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/p4gefau1t/trojan-go/tunnel"
|
||||
)
|
||||
|
||||
const Name = "SHADOWSOCKS"
|
||||
|
||||
type Tunnel struct{}
|
||||
|
||||
func (t *Tunnel) Name() string {
|
||||
return Name
|
||||
}
|
||||
|
||||
func (t *Tunnel) NewClient(ctx context.Context, client tunnel.Client) (tunnel.Client, error) {
|
||||
return NewClient(ctx, client)
|
||||
}
|
||||
|
||||
func (t *Tunnel) NewServer(ctx context.Context, server tunnel.Server) (tunnel.Server, error) {
|
||||
return NewServer(ctx, server)
|
||||
}
|
||||
|
||||
func init() {
|
||||
tunnel.RegisterTunnel(Name, &Tunnel{})
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// +build linux darwin
|
||||
|
||||
package tproxy
|
||||
|
||||
import (
|
||||
|
||||
@@ -6,12 +6,10 @@ import (
|
||||
"github.com/p4gefau1t/trojan-go/tunnel"
|
||||
)
|
||||
|
||||
// Conn is the TLS connections
|
||||
type Conn struct {
|
||||
net.Conn
|
||||
}
|
||||
|
||||
// Metadata implements tunnel.Conn. We don't need and metadata here
|
||||
func (c *Conn) Metadata() *tunnel.Metadata {
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user