diff --git a/README.md b/README.md index 87c369067..c3cff8385 100644 --- a/README.md +++ b/README.md @@ -64,7 +64,7 @@ Trojan-Go支持并且兼容Trojan-GFW的绝大多数功能,包括但不限于 - 基于gRPC的API支持,支持动态用户管理和流量速度限制 -- 服务端支持处理Trojan协议明文(TCP明文传输),以适应前置nginx等服务器的场景 +- 可插拔传输层,可将TLS替换为其他协议或明文传输。同时有完整的Shadowsocks混淆插件支持。 ## 图形界面客户端 @@ -337,6 +337,38 @@ Trojan-Go的客户端内建一个简单实用的路由模块用以方便实现 所需要的geoip.dat和geosite.dat已经包含在release的压缩包中。它们来自v2ray的[domain-list-community](https://github.com/v2ray/domain-list-community)和[geoip](https://github.com/v2ray/geoip)。 +完整的选项说明参见[Trojan-Go 文档](https://p4gefau1t.github.io/trojan-go)。 + +## 混淆插件 + +Trojan-Go支持可插拔的传输层插件,并支持Shadowsocks SIP003标准的混淆插件。下面是使用v2ray-plugin的一个例子: + +**此配置并不安全,仅用作演示** + +服务端配置: + +```json +"transport_plugin": { + "enabled": true, + "type": "shadowsocks", + "command": "./v2ray-plugin", + "arg": ["-server", "-host", "www.baidu.com"] +} +``` + +客户端配置: + +```json +"transport_plugin": { + "enabled": true, + "type": "shadowsocks", + "command": "./v2ray-plugin", + "arg": ["-host", "www.baidu.com"] +} +``` + +完整的选项说明参见[Trojan-Go 文档](https://p4gefau1t.github.io/trojan-go)。 + ## 构建 确保你的Go版本 >= 1.14,推荐使用snap安装Go保持与上游同步。 diff --git a/common/common.go b/common/common.go index 8c3e2c5d6..00537a655 100644 --- a/common/common.go +++ b/common/common.go @@ -11,7 +11,7 @@ import ( ) const ( - Version = "v0.5.1" + Version = "v0.6.0" ) type Runnable interface { diff --git a/common/net.go b/common/net.go index 9a501286f..dcad5ecaa 100644 --- a/common/net.go +++ b/common/net.go @@ -175,3 +175,14 @@ func HumanFriendlyTraffic(bytes uint64) string { } return fmt.Sprintf("%.2f GiB", float32(bytes)/GiB) } + +func PickPort(network string, host string) int { + l, err := net.Listen(network, host+":0") + Must(err) + defer l.Close() + _, port, err := net.SplitHostPort(l.Addr().String()) + Must(err) + p, err := strconv.ParseInt(port, 10, 32) + Must(err) + return int(p) +} diff --git a/conf/conf.go b/conf/conf.go index 53cf693b5..d92151c35 100644 --- a/conf/conf.go +++ b/conf/conf.go @@ -4,6 +4,7 @@ import ( "crypto/tls" "crypto/x509" "io" + "os/exec" "github.com/p4gefau1t/trojan-go/common" utls "github.com/refraction-networking/utls" @@ -46,7 +47,6 @@ type TLSConfig struct { ALPN []string `json:"alpn"` Curves string `json:"curves"` Fingerprint string `json:"fingerprint"` - ServePlainText bool `json:"serve_plain_text"` KeyLogPath string `json:"key_log"` ClientHelloID *utls.ClientHelloID @@ -153,30 +153,42 @@ type APIConfig struct { APIAddress *common.Address } +type TransportPluginConfig struct { + Enabled bool `json:"enabled"` + Type string `json:"type"` + Command string `json:"command"` + PluginOption string `json:"plugin_option"` + Arg []string `json:"arg"` + Env []string `json:"env"` + + Cmd *exec.Cmd +} + type GlobalConfig struct { - RunType RunType `json:"run_type"` - LogLevel int `json:"log_level"` - LogFile string `json:"log_file"` - LocalHost string `json:"local_addr"` - LocalPort int `json:"local_port"` - TargetHost string `json:"target_addr"` - TargetPort int `json:"target_port"` - RemoteHost string `json:"remote_addr"` - RemotePort int `json:"remote_port"` - BufferSize int `json:"buffer_size"` - DisableHTTPCheck bool `json:"disable_http_check"` - Passwords []string `json:"password"` - DNS []string `json:"dns"` - TLS TLSConfig `json:"ssl"` - TCP TCPConfig `json:"tcp"` - MySQL MySQLConfig `json:"mysql"` - Redis RedisConfig `json:"redis"` - Mux MuxConfig `json:"mux"` - Router RouterConfig `json:"router"` - Websocket WebsocketConfig `json:"websocket"` - API APIConfig `json:"api"` - ForwardProxy ForwardProxyConfig `json:"forward_proxy"` - Compression CompressionConfig `json:"compression"` + RunType RunType `json:"run_type"` + LogLevel int `json:"log_level"` + LogFile string `json:"log_file"` + LocalHost string `json:"local_addr"` + LocalPort int `json:"local_port"` + TargetHost string `json:"target_addr"` + TargetPort int `json:"target_port"` + RemoteHost string `json:"remote_addr"` + RemotePort int `json:"remote_port"` + BufferSize int `json:"buffer_size"` + DisableHTTPCheck bool `json:"disable_http_check"` + Passwords []string `json:"password"` + DNS []string `json:"dns"` + TLS TLSConfig `json:"ssl"` + TCP TCPConfig `json:"tcp"` + MySQL MySQLConfig `json:"mysql"` + Redis RedisConfig `json:"redis"` + Mux MuxConfig `json:"mux"` + Router RouterConfig `json:"router"` + Websocket WebsocketConfig `json:"websocket"` + API APIConfig `json:"api"` + ForwardProxy ForwardProxyConfig `json:"forward_proxy"` + Compression CompressionConfig `json:"compression"` + TransportPlugin TransportPluginConfig `json:"transport_plugin"` LocalAddress *common.Address RemoteAddress *common.Address diff --git a/conf/parse.go b/conf/parse.go index 3355f27d0..51f3bbfd5 100644 --- a/conf/parse.go +++ b/conf/parse.go @@ -11,6 +11,8 @@ import ( "net" "net/http" "os" + "os/exec" + "strconv" "strings" "github.com/p4gefau1t/trojan-go/common" @@ -313,13 +315,6 @@ func loadCommonConfig(config *GlobalConfig) error { } func loadClientConfig(config *GlobalConfig) error { - if config.TLS.SNI == "" { - log.Warn("SNI is unspecified, using remote_addr as SNI") - config.TLS.SNI = config.RemoteHost - } - if err := loadCert(&config.TLS); err != nil { - return err - } //forward proxy settings if config.ForwardProxy.Enabled { log.Info("Forward proxy enabled") @@ -327,13 +322,58 @@ func loadClientConfig(config *GlobalConfig) error { log.Debug("Forward proxy", config.ForwardProxy.ProxyAddress.String()) } - if config.Websocket.Enabled && config.Websocket.DoubleTLS { - if config.Websocket.TLS.CertPath == "" { - log.Warn("Empty double TLS settings, using default ssl settings") - config.Websocket.TLS = config.TLS - } else { - if err := loadCert(&config.Websocket.TLS); err != nil { - return err + if config.TransportPlugin.Enabled { + log.Warn("Trojan-Go will use transport plugin and work in plain text mode") + switch config.TransportPlugin.Type { + case "plaintext": + // do nothing + case "shadowsocks": + pluginHost := "127.0.0.1" + pluginPort := common.PickPort("tcp", pluginHost) + config.TransportPlugin.Env = append( + config.TransportPlugin.Env, + "SS_LOCAL_HOST="+pluginHost, + "SS_LOCAL_PORT="+strconv.FormatInt(int64(pluginPort), 10), + "SS_REMOTE_HOST="+config.RemoteHost, + "SS_REMOTE_PORT="+strconv.FormatInt(int64(config.RemotePort), 10), + "SS_PLUGIN_OPTIONS="+config.TransportPlugin.PluginOption, + ) + config.RemoteHost = pluginHost + config.RemotePort = pluginPort + config.RemoteAddress = common.NewAddress(config.RemoteHost, config.RemotePort, "tcp") + log.Debug("New remote address", config.RemoteAddress.String()) + log.Debug("Plugin env", config.TransportPlugin.Env) + + cmd := exec.Command(config.TransportPlugin.Command, config.TransportPlugin.Arg...) + cmd.Env = append(cmd.Env, config.TransportPlugin.Env...) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stdout + config.TransportPlugin.Cmd = cmd + case "other": + cmd := exec.Command(config.TransportPlugin.Command, config.TransportPlugin.Arg...) + cmd.Env = append(cmd.Env, config.TransportPlugin.Env...) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stdout + config.TransportPlugin.Cmd = cmd + default: + return common.NewError("Invalid plugin type: " + config.TransportPlugin.Type) + } + } else { + if config.TLS.SNI == "" { + log.Warn("SNI is unspecified, using remote_addr as SNI") + config.TLS.SNI = config.RemoteHost + } + if err := loadCert(&config.TLS); err != nil { + return err + } + if config.Websocket.Enabled && config.Websocket.DoubleTLS { + if config.Websocket.TLS.CertPath == "" { + log.Warn("Empty double TLS settings, using default ssl settings") + config.Websocket.TLS = config.TLS + } else { + if err := loadCert(&config.Websocket.TLS); err != nil { + return err + } } } } @@ -354,35 +394,70 @@ func loadServerConfig(config *GlobalConfig) error { resp.Body.Close() } - //tls settings - if config.TLS.ServePlainText { - log.Warn("Server will now use plain text. TLS config is ignored") + // transport plugin settings + if config.TransportPlugin.Enabled { + log.Warn("Trojan-Go will use transport plugin and work in plain text mode") + switch config.TransportPlugin.Type { + case "shadowsocks": + trojanHost := "127.0.0.1" + trojanPort := common.PickPort("tcp", trojanHost) + config.TransportPlugin.Env = append( + config.TransportPlugin.Env, + "SS_REMOTE_HOST="+config.LocalHost, + "SS_REMOTE_PORT="+strconv.FormatInt(int64(config.LocalPort), 10), + "SS_LOCAL_HOST="+trojanHost, + "SS_LOCAL_PORT="+strconv.FormatInt(int64(trojanPort), 10), + "SS_PLUGIN_OPTIONS="+config.TransportPlugin.PluginOption, + ) + + config.LocalHost = trojanHost + config.LocalPort = trojanPort + config.LocalAddress = common.NewAddress(config.LocalHost, config.LocalPort, "tcp") + log.Debug("New local address", config.RemoteAddress.String()) + log.Debug("Plugin env", config.TransportPlugin.Env) + + cmd := exec.Command(config.TransportPlugin.Command, config.TransportPlugin.Arg...) + cmd.Env = append(cmd.Env, config.TransportPlugin.Env...) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stdout + config.TransportPlugin.Cmd = cmd + case "other": + cmd := exec.Command(config.TransportPlugin.Command, config.TransportPlugin.Arg...) + cmd.Env = append(cmd.Env, config.TransportPlugin.Env...) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stdout + config.TransportPlugin.Cmd = cmd + case "plaintext": + // do nothing + default: + return common.NewError("Invalid plugin type: " + config.TransportPlugin.Type) + } } else { if err := loadCertAndKey(&config.TLS); err != nil { return err } - if config.TLS.SNI == "" { - log.Warn("Empty SNI field. Server will not verify the SNI in client hello request") - config.TLS.VerifyHostName = false - } - - if config.TLS.HTTPResponseFileName != "" { - payload, err := ioutil.ReadFile(config.TLS.HTTPResponseFileName) - if err != nil { - return common.NewError("Failed to load http response file").Base(err) - } - config.TLS.HTTPResponse = payload - } - } - - - if config.Websocket.Enabled && config.Websocket.DoubleTLS { - if config.Websocket.TLS.CertPath == "" { - log.Warn("Empty double TLS settings, using global TLS settings") - config.Websocket.TLS = config.TLS - } - if err := loadCertAndKey(&config.Websocket.TLS); err != nil { - return err + // tls settings + if config.TLS.SNI == "" { + log.Warn("Empty SNI field. Server will not verify the SNI in client hello request") + config.TLS.VerifyHostName = false + } + + if config.TLS.HTTPResponseFileName != "" { + payload, err := ioutil.ReadFile(config.TLS.HTTPResponseFileName) + if err != nil { + return common.NewError("Failed to load http response file").Base(err) + } + config.TLS.HTTPResponse = payload + } + + if config.Websocket.Enabled && config.Websocket.DoubleTLS { + if config.Websocket.TLS.CertPath == "" { + log.Warn("Empty double TLS settings, using global TLS settings") + config.Websocket.TLS = config.TLS + } + if err := loadCertAndKey(&config.Websocket.TLS); err != nil { + return err + } } } diff --git a/docs/config.toml b/docs/config.toml index 46f500dce..f500bd8a6 100755 --- a/docs/config.toml +++ b/docs/config.toml @@ -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.5.1" + version = "0.6.0" # Documentation repository section # documentation repository (set edit link to documentation repository) diff --git a/docs/content/advance/plugin.md b/docs/content/advance/plugin.md new file mode 100644 index 000000000..d903dfe11 --- /dev/null +++ b/docs/content/advance/plugin.md @@ -0,0 +1,53 @@ +--- +title: "使用Shadowsocks插件/可插拔传输层" +draft: false +weight: 7 +--- + +### 注意,Trojan-GFW版本不支持这个特性 + +Trojan-Go支持可插拔的传输层。原则上,Trojan-Go可以使用任何有TCP隧道功能的软件作为传输层,如v2ray、shadowsocks、kcp等。同时,Trojan-Go也兼容Shadowsocks的SIP003插件标准,如GoQuiet,v2ray-plugin等。也可以使用Tor的传输层插件,如obfs4,meek等。 + +你可以使用这些插件,替换Trojan-Go的TLS传输层。 + +开启可插拔传输层插件后,Trojan-Go客户端将会把**流量明文**直接传输给客户端本地的插件处理。由客户端插件负责进行加密和混淆,并将流量传输给服务端的插件。服务端的插件接收到流量,进行解密和解析,将**流量明文**传输给服务端本地的Trojan-Go服务端。 + +你可以使用任何插件对流量进行加密和混淆,只需添加"transport_plugin"选项,并指定插件的可执行文件的路径,并做好配置即可。 + +我们更建议**自行设计协议并开发相应插件**。因为目前现有的所有插件无法对接Trojan-Go的对抗主动探测的特性,而且部分插件并无加密能力。如果你对开发插件有兴趣,欢迎在"实现细节和开发指南"一节中查看插件设计的指南。 + +例如,可以使用符合SIP003标准的v2ray-plugin,下面是一个例子: + +**这个配置中使用了websocket明文传输未经加密的trojan协议,存在安全隐患。这个配置仅作为演示使用。** + +**不要在任何情况下使用这个配置穿透GFW。** + +服务端配置: + +```json +...(省略) +"transport_plugin": { + "enabled": true, + "type": "shadowsocks", + "command": "./v2ray-plugin", + "arg": ["-server", "-host", "www.baidu.com"] +} +``` + +客户端配置: + +```json +...(省略) +"transport_plugin": { + "enabled": true, + "type": "shadowsocks", + "command": "./v2ray-plugin", + "arg": ["-host", "www.baidu.com"] +} +``` + +注意,v2ray-plugin插件需要指定```-server```参数来区分客户端和服务端。更多关于该插件详细的说明,参考v2ray-plugin的文档。 + +启动Trojan-Go后,你可以看到v2ray-plugin启动的输出。插件将回把流量伪装为websocket流量并传输。 + +非SIP003标准的插件可能需要不同的配置,你可以指定```type```为"other",并自行指定插件地址,插件启动参数、环境变量。 diff --git a/docs/content/basic/full-config.md b/docs/content/basic/full-config.md index 48c8a1bd6..2787c3b19 100644 --- a/docs/content/basic/full-config.md +++ b/docs/content/basic/full-config.md @@ -76,8 +76,8 @@ weight: 30 "block": [], "default_policy": "proxy", "domain_strategy": "as_is", - "geoip": "./geoip.dat", - "geosite": "./geosite.dat" + "geoip": "geoip.dat", + "geosite": "geosite.dat" }, "websocket": { "enabled": false, @@ -99,6 +99,14 @@ weight: 30 "key_log": "" } }, + "transport_plugin": { + "enabled": false, + "type": "", + "command": "", + "plugin_option": "", + "arg": [], + "env": [] + }, "forward_proxy": { "enabled": false, "proxy_addr": "", @@ -276,6 +284,26 @@ Websocket传输是trojan-go的特性。在**正常的直接连接代理节点** ```obfuscation_password```指定混淆密码。用于混淆内层连接以避免遭到CDN运营商识别。如果需要使用混淆,服务端和客户端必须设置相同的密码。这个选项对性能有一定影响,请自行斟酌安全性和性能的平衡。 +### ```transport_plugin```传输层插件选项 + +```enabled```是否启用传输层插件替代TLS传输。一旦启用传输层插件支持,trojan-go将会把**未经TLS加密的trojan协议流量明文传输给插件**,以允许用户对流量进行自定义的混淆和加密。 + +```type```插件类型。目前支持的类型有 + +- "shadowsocks",支持符合[SIP003](https://github.com/shadowsocks/shadowsocks-org/issues/28)标准的shadowsocks混淆插件。trojan-go将在启动时按照SIP003标准替换环境变量并修改自身配置(```remote_addr/remote_port/local_addr/local_port```),使插件与远端直接通讯,而trojan-go仅监听/连接插件。 + +- "plaintext",使用明文传输。选择此项,trojan-go不会修改任何地址配置(```remote_addr/remote_port/local_addr/local_port```),也不会启动```command```中插件,仅移除最底层的TLS传输层并使用TCP明文传输。此选项目的为支持nginx接管TLS并进行分流,以及高级用户进行调试测试。**请勿直接使用明文传输模式穿透防火墙。** + +- "other",其他插件。选择此项,trojan-go不会修改任何地址配置(```remote_addr/remote_port/local_addr/local_port```),但会启动```command```中插件并传入参数和环境变量。 + +```command```传输层插件可执行文件的路径。trojan-go将在启动时一并执行它。 + +```arg```传输层插件启动参数。这是一个列表,例如```["-config", "test.json"]```。 + +```env```传输层插件环境变量。这是一个列表,例如```["VAR1=foo", "VAR2=bar"]```。 + +```option```传输层插件配置(SIP003)。例如```"obfs=http;obfs-host=www.baidu.com"```。 + ### ```tcp```选项 ```no_delay```TCP封包是否直接发出而不等待缓冲区填满。 diff --git a/docs/content/developer/plugin.md b/docs/content/developer/plugin.md new file mode 100644 index 000000000..e8ce04c7e --- /dev/null +++ b/docs/content/developer/plugin.md @@ -0,0 +1,37 @@ +--- +title: "可插拔传输层插件开发" +draft: false +weight: 150 +--- + +Trojan-Go鼓励开发传输层插件,以丰富协议类型,增加与GFW对抗的战略纵深。 + +插件与Trojan-Go基于TCP Socket通讯,与Trojan-Go本身不存在任何耦合关系,你可以使用任何你喜欢的语言和设计模式进行开发。我们建议的参照[SIP003](https://github.com/shadowsocks/shadowsocks-org/issues/28)标准进行开发。如此开发的插件可以同时用于Trojan-Go和Shadowsocks。 + +Trojan-Go开启插件功能后,仅使用TCP进行传输(明文)。你的插件只需要处理入站的TCP请求即可。你可以将这些TCP流量转换成任何你喜欢的流量格式,如QUIC,HTTP,甚至是ICMP。 + +Trojan-Go插件设计原则,与Shadowsocks略有不同: + +1. 插件本身可以对传输内容进行加密,混淆和完整性校验,以及可以抵抗重放攻击。 + +2. 插件应该伪造一种已有的、常见的服务(记做X服务),及其流量,在此基础上嵌入自己的加密内容。 + +3. 服务端的插件,在检验到内容被篡改/遭到重放时,**必须将此连接交由Trojan-Go处理**。具体步骤是,将已读入和未读入的内容一并发送给Trojan-Go,并建立双向连接,而不是直接断开。Trojan-Go将与一个真实的X服务器建立连接,使攻击者直接与真实的X服务器进行交互。 + +解释如下: + +第一点原则,是由于Trojan协议本身并不加密。将TLS替换为传输层插件后,将**完全信任插件的安全性**。 + +第二点原则,是继承Trojan的精神。最适合隐藏一棵树的地方,是森林。 + +第三点原则,是为了充分利用Trojan-Go的抗主动探测特性。即使GFW对你的服务器进行主动探测,你的服务器也可以表现得与X服务一致,而不存在其他特征。 + +为了方便理解,举一个例子。 + +1. 假设你的插件伪装的是MySQL流量。防火墙通过流量嗅探,发现你的MySQL流量大得异常,决定主动连接你的服务器进行主动探测。 + +2. 防火墙连接到你的服务器并发送探测载荷,你的Trojan-Go服务端插件,经过校验,发现这个异常连接不是代理流量,于是将这个连接交由Trojan-Go处理。 + +3. Trojan-Go发现这个连接异常,将这个连接重定向到一个真正的MySQL服务器上。于是,防火墙开始与一个真正的MySQL服务器进行交互,发现其行为与真实MySQL服务器无异,无法对服务器进行封禁。 + +另外,即使你的协议协议和插件不能满足原则2和原则3,甚至不能很好满足原则1,我们同样鼓励开发。因为GFW仅仅针对流行的协议进行审计和封锁,此类协议(土制密码学/土制协议)只要不公开发表,同样能保持非常强健的生命力。 diff --git a/go.mod b/go.mod index 1f835e05f..fbf0bf0f2 100644 --- a/go.mod +++ b/go.mod @@ -11,24 +11,24 @@ require ( github.com/mattn/go-sqlite3 v2.0.3+incompatible // indirect github.com/mediocregopher/radix/v3 v3.5.1 github.com/miekg/dns v1.1.29 // indirect - github.com/onsi/ginkgo v1.10.1 // indirect - github.com/onsi/gomega v1.7.0 // indirect + github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect + github.com/onsi/ginkgo v1.12.3 // indirect github.com/patrickmn/go-cache v2.1.0+incompatible github.com/proullon/ramsql v0.0.0-20181213202341-817cee58a244 - github.com/refraction-networking/utls v0.0.0-20190909200633-43c36d3c1f57 + github.com/refraction-networking/utls v0.0.0-20200601200209-ada0bb9b38a0 github.com/smartystreets/goconvey v1.6.4 github.com/xtaci/smux v1.5.15-0.20200523091831-637399ad4398 github.com/ziutek/mymysql v1.5.4 // indirect go.starlark.net v0.0.0-20200519165436-0aa95694c768 // indirect - golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37 - golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2 - golang.org/x/sys v0.0.0-20200523222454-059865788121 + golang.org/x/crypto v0.0.0-20200602180216-279210d13fed + golang.org/x/net v0.0.0-20200602114024-627f9648deb9 + golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980 golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1 google.golang.org/grpc v1.29.1 google.golang.org/protobuf v1.24.0 - gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect + gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect gopkg.in/square/go-jose.v2 v2.5.1 // indirect - v2ray.com/core v4.19.1+incompatible + v2ray.com/core v0.0.0-20190603071532-16e9d39fff74 ) -replace v2ray.com/core => github.com/v2ray/v2ray-core v4.23.1+incompatible +replace v2ray.com/core => github.com/v2ray/v2ray-core v0.0.0-20200603100350-6b5d2fed91c0 diff --git a/go.sum b/go.sum index 9fe831588..bb3400ce3 100644 --- a/go.sum +++ b/go.sum @@ -53,7 +53,6 @@ github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f/go.mod github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/cenkalti/backoff/v4 v4.0.0 h1:6VeaLF9aI+MAUQ95106HwWzYZgJJpZ4stumjj6RFYAU= github.com/cenkalti/backoff/v4 v4.0.0/go.mod h1:eEew/i+1Q6OrCDZh3WiXYv3+nJwBASZ8Bog/87DQnVg= github.com/cenkalti/backoff/v4 v4.0.2 h1:JIufpQLbh4DkbQoii76ItQIUFzevQSqOLZca4eamEDs= github.com/cenkalti/backoff/v4 v4.0.2/go.mod h1:eEew/i+1Q6OrCDZh3WiXYv3+nJwBASZ8Bog/87DQnVg= @@ -83,8 +82,9 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/exoscale/egoscale v0.18.1/go.mod h1:Z7OOdzzTOz1Q1PjQXumlz9Wn/CddH0zSYdCF3rnBKXE= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= -github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-acme/lego/v3 v3.5.0 h1:/0+NJQK+hNwRznhCi+19lbEa4xufhe7wJZOVd5j486s= github.com/go-acme/lego/v3 v3.5.0/go.mod h1:TXodhTGOiWEqXDdgrzBoCtJ5R4L9lfOE68CTM0KGkT0= @@ -124,13 +124,10 @@ github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0 h1:oOuy+ugB+P/kBdUnG5QaMXSIyJ1q38wWSojYCb3z5VQ= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1 h1:ZFgWrT+bLgsYPirOnRfKLYJLvssAegOj/hgyMFdJZe0= github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db h1:woRePGFeVFfLKN/pOkfl+p/TAqKOfFu+7KPlMVpok/w= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= @@ -163,7 +160,6 @@ github.com/grpc-ecosystem/grpc-gateway v1.8.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df/go.mod h1:QMZY7/J/KSQEhKWFeDesPjMj+wCHReeknARU3wqlyN4= @@ -181,7 +177,6 @@ github.com/kolo/xmlrpc v0.0.0-20190717152603-07c4ee3fd181/go.mod h1:o03bZfuBwAXH github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= @@ -202,7 +197,6 @@ github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5 github.com/mediocregopher/radix/v3 v3.5.1 h1:IOYgQUMA380N4khaL5eNT4v/P2LnHa8b0wnVdwZMFsY= github.com/mediocregopher/radix/v3 v3.5.1/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i4n7wVopoX3x7Bv8= github.com/miekg/dns v1.1.4/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= -github.com/miekg/dns v1.1.27 h1:aEH/kqUzUxGJ/UHcEKdJY+ugH6WEzsEBBSPa8zuy1aM= github.com/miekg/dns v1.1.27/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= github.com/miekg/dns v1.1.29 h1:xHBEhR+t5RzcFJjBLJlax2daXOrTYtr9z4WdKEfWFzg= github.com/miekg/dns v1.1.29/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= @@ -216,20 +210,24 @@ github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3Rllmb github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/namedotcom/go v0.0.0-20180403034216-08470befbe04/go.mod h1:5sN+Lt1CaY4wsPvgQH/jsuJi4XO2ssZbdsIizr4CVC8= github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms= +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/nrdcg/auroradns v1.0.1/go.mod h1:y4pc0i9QXYlFCWrhWrUSIETnZgrf4KuwjDIWmmXo3JI= github.com/nrdcg/dnspod-go v0.4.0/go.mod h1:vZSoFSFeQVm2gWLMkyX61LZ8HI3BaqtHZWgPTGKr6KQ= github.com/nrdcg/goinwx v0.6.1/go.mod h1:XPiut7enlbEdntAqalBIqcYcTEVhpv/dKWgDCX2SwKQ= github.com/nrdcg/namesilo v0.2.1/go.mod h1:lwMvfQTyYq+BbjJd30ylEG4GPSS6PII0Tia4rRpRiyw= +github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.10.1 h1:q/mM8GF/n0shIN8SaAZ0V+jnLPzen6WIVZdiwrRlMlo= -github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/gomega v1.4.3 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.12.3 h1:+RYp9QczoWz9zfUyLP/5SLXQVhfr6gZOoKGfQqHuLZQ= +github.com/onsi/ginkgo v1.12.3/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.7.0 h1:XPnZz8VVBHjVsy1vzJmRwIcSwiUO+JFfrv/xGiigmME= -github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= github.com/oracle/oci-go-sdk v7.0.0+incompatible/go.mod h1:VQb79nF8Z2cwLkLS35ukwStZIg5F66tcBccjip/j888= github.com/ovh/go-ovh v0.0.0-20181109152953-ba5adb4cf014/go.mod h1:joRatxRJaZBsY3JAOEMcoOp05CnZzsx4scTxi95DHyQ= @@ -259,8 +257,9 @@ github.com/proullon/ramsql v0.0.0-20181213202341-817cee58a244 h1:fdX2U+a2Rmc4BjR github.com/proullon/ramsql v0.0.0-20181213202341-817cee58a244/go.mod h1:jG8oAQG0ZPHPyxg5QlMERS31airDC+ZuqiAe8DUvFVo= github.com/rainycape/memcache v0.0.0-20150622160815-1031fa0ce2f2/go.mod h1:7tZKcyumwBO6qip7RNQ5r77yrssm9bfCowcLEBcU5IA= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -github.com/refraction-networking/utls v0.0.0-20190909200633-43c36d3c1f57 h1:SL1K0QAuC1b54KoY1pjPWe6kSlsFHwK9/oC960fKrTY= 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/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= @@ -286,8 +285,8 @@ github.com/timewasted/linode v0.0.0-20160829202747-37e84520dcf7/go.mod h1:imsgLp github.com/transip/gotransip v0.0.0-20190812104329-6d8d9179b66f/go.mod h1:i0f4R4o2HM0m3DZYQWsj6/MEowD57VzoH0v3d7igeFY= github.com/uber-go/atomic v1.3.2/go.mod h1:/Ct5t2lcmbJ4OSe/waGBoaVvVqtO0bmtfVNex1PFV8g= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/v2ray/v2ray-core v4.23.1+incompatible h1:kqV93r0dFBcYAJp/XAXfUqlhsyt/Hxy8bcs2t9LHlgg= -github.com/v2ray/v2ray-core v4.23.1+incompatible/go.mod h1:LtoljHM69/Tx4Niy/2vqWP8R2HPqS64NiaJaGkktn+Q= +github.com/v2ray/v2ray-core v0.0.0-20200603100350-6b5d2fed91c0 h1:beJRvss6cKPj/Qy8RLI/O8EKYaxaKlsXBjsXgmNqSUQ= +github.com/v2ray/v2ray-core v0.0.0-20200603100350-6b5d2fed91c0/go.mod h1:6qvbJidjCnQWxyTc9SBD/cLCtN4qLs2neS/VzwSTnTY= github.com/vultr/govultr v0.1.4/go.mod h1:9H008Uxr/C4vFNGLqKx232C206GL0PBHzOP0809bGNA= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= @@ -302,7 +301,6 @@ go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -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= go.starlark.net v0.0.0-20200519165436-0aa95694c768 h1:p1NBjkIS2bHXntFxS9zhyFmZ9VKtazqNnsn5r7okSTo= go.starlark.net v0.0.0-20200519165436-0aa95694c768/go.mod h1:nmDLcffg48OtT/PSW0Hg7FvpRQsQh5OSqIylirxKC7o= @@ -316,9 +314,10 @@ golang.org/x/crypto v0.0.0-20190418165655-df01cb2cc480/go.mod h1:WFFai1msRO1wXaE golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191029031824-8986dd9e96cf/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37 h1:cg5LA/zNPRzIXIWSCxQW10Rvpy94aQh3LT/ShoCpkHw= -golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/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= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -373,8 +372,9 @@ golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2 h1:eDrdRpKgkcCqKZQwyZRyeFZgfqt37SL7Kv3tok06cKE= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200602114024-627f9648deb9 h1:pNX+40auqi2JqRfOP1akLGtYcn15TUbkhwuCO3foqqM= +golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -406,9 +406,12 @@ golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191002063906-3421d5a6bb1c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -418,8 +421,9 @@ golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121 h1:rITEj+UZHYC927n8GT97eC3zrpzXdb/voyeOuVKS46o= -golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/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.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -428,7 +432,6 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190921001708-c4c64cad1fd0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 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= @@ -503,7 +506,6 @@ google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvx google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200305110556-506484158171 h1:xes2Q2k+d/+YNXVw0FpZkIDJiaux4OVrRKXRAzH6A0U= google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= @@ -524,9 +526,7 @@ google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLY google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0 h1:qdOKuR/EIArgaWNjetjgTzgVTAZ+S/WXVrq9HW9zimw= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0 h1:cJv5/xdbk1NnMPR1VP9+HU6gupuG9MLBoH1r6RHZ2MY= google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= @@ -534,12 +534,10 @@ google.golang.org/protobuf v1.24.0 h1:UhZDfRO8JRQru4/+LlLE0BRKGF8L+PICnvYZmx/fEG google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/h2non/gock.v1 v1.0.15/go.mod h1:sX4zAkdYX1TRGJ2JY156cFspQn4yRWn6p9EMdODlynE= gopkg.in/ini.v1 v1.42.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= @@ -547,7 +545,6 @@ gopkg.in/ini.v1 v1.51.1/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ns1/ns1-go.v2 v2.0.0-20190730140822-b51389932cbc/go.mod h1:VV+3haRsgDiVLxyifmMBrBIuCWFBPYKbRssXB9z67Hw= gopkg.in/resty.v1 v1.9.1/go.mod h1:vo52Hzryw9PnPHcJfPsBiFW62XhNx5OczbV9y+IMpgc= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= -gopkg.in/square/go-jose.v2 v2.3.1 h1:SK5KegNXmKmqE342YYN2qPHEnUYeoMiXXl1poUlI+o4= gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/square/go-jose.v2 v2.5.1 h1:7odma5RETjNHWJnR32wx8t+Io4djHE1PqxCFx3iiZ2w= gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= @@ -555,8 +552,10 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkep gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= h12.io/socks v1.0.0/go.mod h1:MdYbo5/eB9ka7u5dzW2Qh0iSyJENwB3KI5H5ngenFGA= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/proxy/client/app.go b/proxy/client/app.go index ded4616d7..b4e4efbd0 100644 --- a/proxy/client/app.go +++ b/proxy/client/app.go @@ -33,8 +33,9 @@ func (m *AppManager) OpenAppConn(req *protocol.Request) (protocol.ConnSession, e outboundConn, err = trojan.NewOutboundConnSession(req, transport, m.config, m.auth) } if err != nil { - return nil, common.NewError("Fail to start conn session").Base(err) + return nil, common.NewError("Fail to open conn session").Base(err) } + log.Info("Tunneling to", req) return outboundConn, nil } diff --git a/proxy/client/client.go b/proxy/client/client.go index 381033113..afd4af4fb 100644 --- a/proxy/client/client.go +++ b/proxy/client/client.go @@ -50,14 +50,14 @@ func (c *Client) handleSocksConn(conn io.ReadWriteCloser) { defer inboundConn.Close() if req.Command == protocol.Associate { - //setting up the bind address to respond - //listenUDP() will handle the incoming udp packets + // setting up the bind address to respond + // listenUDP() will handle the incoming udp packets localIP, err := c.config.LocalAddress.ResolveIP() if err != nil { log.Error(common.NewError("Invalid local address").Base(err)) return } - //bind port and IP + // bind port and IP req.IP = localIP req.Port = c.config.LocalAddress.Port if localIP.To4() != nil { @@ -66,7 +66,7 @@ func (c *Client) handleSocksConn(conn io.ReadWriteCloser) { req.AddressType = common.IPv6 } - //notify listenUDP to get ready for relaying udp packets + // notify listenUDP to get ready for relaying udp packets c.associated.Signal() log.Debug("UDP associated to", req) if err := inboundConn.(protocol.NeedRespond).Respond(); err != nil { @@ -74,7 +74,6 @@ func (c *Client) handleSocksConn(conn io.ReadWriteCloser) { return } - //stop relaying UDP once TCP connection is closed var buf [1]byte _, err = rwc.Read(buf[:]) log.Debug(common.NewError("UDP conn ends").Base(err)) @@ -91,7 +90,6 @@ func (c *Client) handleSocksConn(conn io.ReadWriteCloser) { log.Error(err) return } - log.Info("Conn tunneling to", req) log.Debug("Policy", policy) if policy == router.Bypass { outboundConn, err := direct.NewOutboundConnSession(c.ctx, req, c.config) @@ -99,11 +97,11 @@ func (c *Client) handleSocksConn(conn io.ReadWriteCloser) { log.Error(err) return } - log.Info("[Bypass] conn to", req) + log.Info("[Bypass]", req) proxy.RelayConn(c.ctx, inboundConn, outboundConn, c.config.BufferSize) return } else if policy == router.Block { - log.Info("[Block] conn to", req) + log.Info("[Block]", req) return } outboundConn, err := c.appMan.OpenAppConn(req) @@ -125,7 +123,7 @@ func (c *Client) handleHTTPConn(conn io.ReadWriteCloser) { return } - if inboundConn != nil { //CONNECT requests + if inboundConn != nil { // CONNECT requests defer inboundConn.Close() if err := inboundConn.(protocol.NeedRespond).Respond(); err != nil { @@ -144,11 +142,11 @@ func (c *Client) handleHTTPConn(conn io.ReadWriteCloser) { log.Error(err) return } - log.Info("[Bypass] conn to", req) + log.Info("[Bypass]", req) proxy.RelayConn(c.ctx, inboundConn, outboundConn, c.config.BufferSize) return } else if policy == router.Block { - log.Info("[Block] conn to", req) + log.Info("[Block]", req) return } @@ -158,7 +156,6 @@ func (c *Client) handleHTTPConn(conn io.ReadWriteCloser) { return } defer outboundConn.Close() - log.Info("Conn tunneling to", req) proxy.RelayConn(c.ctx, inboundConn, outboundConn, c.config.BufferSize) } else { //GET/POST requests defer inboundPacket.Close() @@ -212,10 +209,14 @@ func (c *Client) handleHTTPConn(conn io.ReadWriteCloser) { for { n, err := outboundConn.Read(buf[:]) if err != nil { - log.Debug(err) - return + if err == io.ErrShortBuffer { + log.Debug("Short buffer") + } else { + log.Error(err) + return + } } - if _, err = inboundPacket.WritePacket(nil, buf[0:n]); err != nil { + if _, err = inboundPacket.WritePacket(nil, buf[:n]); err != nil { log.Debug(err) return } @@ -308,7 +309,18 @@ func (c *Client) listenTCP(errChan chan error) { func (c *Client) Run() error { log.Info("Trojan-Go client is listening on", c.config.LocalAddress.String()) - errChan := make(chan error, 3) + errChan := make(chan error, 4) + if c.config.TransportPlugin.Enabled && c.config.TransportPlugin.Cmd != nil { + go func() { + log.Info("Initiating plugin...") + select { + case errChan <- c.config.TransportPlugin.Cmd.Run(): + case <-c.ctx.Done(): + c.config.TransportPlugin.Cmd.Process.Kill() + log.Info("Plugin killed") + } + }() + } go c.listenUDP(errChan) go c.listenTCP(errChan) if c.config.API.Enabled { diff --git a/proxy/client/mux.go b/proxy/client/mux.go index 139a00852..ce6a43c3f 100644 --- a/proxy/client/mux.go +++ b/proxy/client/mux.go @@ -2,6 +2,7 @@ package client import ( "context" + "fmt" "io" "math/rand" "sync" @@ -49,7 +50,7 @@ stick2: func (rwc *smuxStickyReadWriteCloser) Close() error { const maxPaddingLength = 512 - padding := [maxPaddingLength + 8]byte{0, 0, 'A', 'B', 'C', 'D', 'E', 'F'} + padding := [maxPaddingLength + 8]byte{'A', 'B', 'C', 'D', 'E', 'F'} // for debugging buf := rwc.stickToPayload(nil) rwc.Write(append(buf, padding[:rand.Intn(maxPaddingLength)]...)) return rwc.ReadWriteCloser.Close() @@ -62,13 +63,13 @@ func (rwc *smuxStickyReadWriteCloser) Write(p []byte) (int, error) { // THE CONTENT OF THE BUFFER MIGHT CHANGE // NEVER STORE THE POINTER TO HEADER, COPY THE HEADER INSTEAD case 0: - //cmdSYN + // cmdSYN header := make([]byte, 8) copy(header, p) rwc.synQueue <- header return 8, nil case 1: - //cmdFIN + // cmdFIN header := make([]byte, 8) copy(header, p) rwc.finQueue <- header @@ -142,7 +143,7 @@ func (m *MuxManager) newMuxClient() (*muxClientInfo, error) { smuxConfig.KeepAliveDisabled = true client, err := smux.Client(smuxRWC, smuxConfig) common.Must(err) - log.Info("Mux TLS tunnel established, client id:", id) + log.Info(fmt.Sprintf("Mux TLS tunnel established with mux client %x", id)) return &muxClientInfo{ client: client, id: id, @@ -157,7 +158,7 @@ func (m *MuxManager) pickMuxClient() (*muxClientInfo, error) { for _, info := range m.muxPool { if info.client.IsClosed() { delete(m.muxPool, info.id) - log.Info("Mux client", info.id, "is dead") + log.Info(fmt.Sprintf("Mux client %x is closed", info.id)) continue } if info.client.NumStreams() < m.config.Mux.Concurrency || m.config.Mux.Concurrency <= 0 { @@ -192,10 +193,10 @@ func (m *MuxManager) DialToServer() (io.ReadWriteCloser, error) { defer m.Unlock() delete(m.muxPool, info.id) info.client.Close() - log.Warn("Somthing wrong with mux client", info.id, ", closing") + log.Warn(common.NewError(fmt.Sprintf("Somthing wrong with mux client %x, closing", info.id)).Base(err)) return nil, err } - log.Info("New mux conn established with client", info.id) + log.Info(fmt.Sprintf("New mux stream established with mux client %x", info.id)) info.lastActiveTime = time.Now() return stream, nil } @@ -217,21 +218,24 @@ func (m *MuxManager) checkAndCloseIdleMuxClient() { for id, info := range m.muxPool { if info.client.IsClosed() { delete(m.muxPool, id) - log.Info("Mux", id, "is dead") + log.Info("Mux client", id, "is dead") } else if info.client.NumStreams() == 0 && time.Now().Sub(info.lastActiveTime) > muxIdleDuration { info.client.Close() delete(m.muxPool, id) - log.Info("Mux", id, "is closed due to inactive") + log.Info("Mux client", id, "is closed due to inactive") } } log.Debug("Current mux pool clients: ", len(m.muxPool)) + for i, c := range m.muxPool { + log.Debug(fmt.Sprintf(" Client %x: %d/%d", i, c.client.NumStreams(), m.config.Mux.Concurrency)) + } m.Unlock() case <-m.ctx.Done(): log.Debug("Shutting down mux manager..") m.Lock() for id, info := range m.muxPool { info.client.Close() - log.Info("Mux client", id, "closed") + log.Debug("Mux client", id, "closed") } m.Unlock() return diff --git a/proxy/client/tls.go b/proxy/client/tls.go index a21aae0b9..98172ed08 100644 --- a/proxy/client/tls.go +++ b/proxy/client/tls.go @@ -342,13 +342,13 @@ func (m *TLSManager) dialTLSWithFakeFingerprint() (*utls.UConn, error) { m.fingerprintsLock.Lock() workingFingerprint = "" m.fingerprintsLock.Unlock() - log.Error(common.NewError("Failed to set working fingerprint").Base(err)) + log.Error(common.NewError("Failed to apply working fingerprint").Base(err)) } else { protocol.SetRandomizedTimeout(tlsConn) err = tlsConn.Handshake() protocol.CancelTimeout(tlsConn) if err != nil { - log.Debug("Working hello id failed, err:", err) + log.Error("Working hello id is no longer working, err:", err) } else { return tlsConn, nil } @@ -369,7 +369,7 @@ func (m *TLSManager) dialTLSWithFakeFingerprint() (*utls.UConn, error) { tlsConn := utls.UClient(tcpConn, utlsConfig, utls.HelloCustom) if err := tlsConn.ApplyPreset(spec); err != nil { - log.Error(common.NewError("Failed to set " + name + " fingerprint").Base(err)) + log.Error(common.NewError("Failed to apply fingerprint:" + name).Base(err)) continue } @@ -377,11 +377,11 @@ func (m *TLSManager) dialTLSWithFakeFingerprint() (*utls.UConn, error) { err = tlsConn.Handshake() protocol.CancelTimeout(tlsConn) if err != nil { - log.Debug("Fingerprint", name, "failed, err:", err) + log.Info("Handshaking with fingerprint:", name, "failed:", err) continue // on tls Dial error keep trying } - log.Debug("Avaliable hello id found:", name) + log.Info("Avaliable hello id found:", name) m.fingerprintsLock.Lock() m.workingFingerprint = name m.fingerprintsLock.Unlock() @@ -391,9 +391,13 @@ func (m *TLSManager) dialTLSWithFakeFingerprint() (*utls.UConn, error) { } func (m *TLSManager) DialToServer() (io.ReadWriteCloser, error) { + if m.config.TransportPlugin.Enabled { + // plain text + return m.dialTCP() + } var transport net.Conn if m.config.TLS.Fingerprint != "" { - //use utls fingerprints + // use utls fingerprints tlsConn, err := m.dialTLSWithFakeFingerprint() if err != nil { return nil, err @@ -401,7 +405,7 @@ func (m *TLSManager) DialToServer() (io.ReadWriteCloser, error) { m.printConnInfo(tlsConn) transport = tlsConn } else { - //normal golang tls + // default golang tls library tcpConn, err := m.dialTCP() if err != nil { return nil, err diff --git a/proxy/proxy.go b/proxy/proxy.go index 3999dee72..36256b4da 100644 --- a/proxy/proxy.go +++ b/proxy/proxy.go @@ -3,6 +3,7 @@ package proxy import ( "context" "io" + "net" "github.com/p4gefau1t/trojan-go/common" "github.com/p4gefau1t/trojan-go/conf" @@ -32,6 +33,9 @@ func RelayConn(ctx context.Context, a, b io.ReadWriter, bufferSize int) { select { case err := <-errChan: if err != nil { + if err == io.EOF { + return + } log.Debug(common.NewError("Conn relaying ends").Base(err)) } case <-ctx.Done(): @@ -63,7 +67,13 @@ func RelayPacket(ctx context.Context, a, b protocol.PacketReadWriter) { go copyPacket(b, a) select { case err := <-errChan: - log.Debug(common.NewError("Packet relaying ends").Base(err)) + if err, ok := err.(net.Error); ok && err.Timeout() { + return + } + if err == io.EOF { + return + } + log.Error(common.NewError("Packet relaying ends").Base(err)) case <-ctx.Done(): return } @@ -99,10 +109,10 @@ func RelayPacketWithRouter(ctx context.Context, from protocol.PacketReadWriter, } to, found := table[policy] if !found { - log.Debug("policy not found, skiped:", policy) + log.Debug("Policy not found, skiped:", policy) continue } - log.Debug("udp packet ", req, "routing policy:", policy) + log.Debug("UDP packet ", req, "routing policy:", policy) _, err = to.WritePacket(req, packet) if err != nil { errChan <- err @@ -117,7 +127,13 @@ func RelayPacketWithRouter(ctx context.Context, from protocol.PacketReadWriter, go copyToDst() select { case err := <-errChan: - log.Debug(common.NewError("Packet relaying with router ends").Base(err)) + if err, ok := err.(net.Error); ok && err.Timeout() { + return + } + if err == io.EOF { + return + } + log.Error(common.NewError("Packet relaying with router ends").Base(err)) case <-ctx.Done(): return } @@ -148,7 +164,7 @@ func RegisterAPI(t conf.RunType, r APIRunner) { func RunAPIService(t conf.RunType, ctx context.Context, config *conf.GlobalConfig, auth stat.Authenticator) error { r, ok := apis[t] if !ok { - return common.NewError("API module for" + string(t) + "not found") + return common.NewError("API module for type " + string(t) + " not found") } return r(ctx, config, auth) } diff --git a/proxy/server/server.go b/proxy/server/server.go index 0b46779c8..2eba81188 100644 --- a/proxy/server/server.go +++ b/proxy/server/server.go @@ -160,7 +160,7 @@ func (s *Server) ListenTCP(errChan chan error) { } log.Info("Conn accepted from", conn.RemoteAddr()) go func(conn net.Conn) { - if s.config.TLS.ServePlainText { + if s.config.TransportPlugin.Enabled { s.handleConn(conn) return } @@ -229,13 +229,24 @@ func (s *Server) ListenTCP(errChan chan error) { } func (s *Server) Run() error { - errChan := make(chan error, 2) + errChan := make(chan error, 3) if s.config.API.Enabled { log.Info("API enabled") go func() { errChan <- proxy.RunAPIService(conf.Server, s.ctx, s.config, s.auth) }() } + if s.config.TransportPlugin.Enabled && s.config.TransportPlugin.Cmd != nil { + go func() { + log.Info("Initiating plugin...") + select { + case errChan <- s.config.TransportPlugin.Cmd.Run(): + case <-s.ctx.Done(): + s.config.TransportPlugin.Cmd.Process.Kill() + log.Info("Plugin killed") + } + }() + } go s.ListenTCP(errChan) select { case <-s.ctx.Done(): diff --git a/test/proxy_test.go b/test/proxy_test.go index e5f9f1fa2..20c8ce2b7 100644 --- a/test/proxy_test.go +++ b/test/proxy_test.go @@ -10,6 +10,8 @@ import ( "io/ioutil" "net" "os" + "os/exec" + "strconv" "sync" "testing" "time" @@ -128,6 +130,10 @@ func getPasswords(password string) []string { func getBasicServerConfig() *conf.GlobalConfig { config := &conf.GlobalConfig{ + LocalHost: "0.0.0.0", + LocalPort: 4445, + RemoteHost: "127.0.0.1", + RemotePort: 10080, LocalAddress: common.NewAddress("0.0.0.0", 4445, "tcp"), RemoteAddress: common.NewAddress("127.0.0.1", 10080, "tcp"), TLS: getTLSConfig(), @@ -140,6 +146,10 @@ func getBasicServerConfig() *conf.GlobalConfig { func getBasicClientConfig() *conf.GlobalConfig { config := &conf.GlobalConfig{ + LocalHost: "0.0.0.0", + LocalPort: 4444, + RemoteHost: "127.0.0.1", + RemotePort: 4445, LocalAddress: common.NewAddress("0.0.0.0", 4444, "tcp"), RemoteAddress: common.NewAddress("127.0.0.1", 4445, "tcp"), TLS: getTLSConfig(), @@ -234,6 +244,58 @@ func addDNSConfig(config *conf.GlobalConfig) *conf.GlobalConfig { return config } +func addServerPluginConfig(config *conf.GlobalConfig) *conf.GlobalConfig { + config.TransportPlugin.Enabled = true + config.TransportPlugin.Command = "v2ray-plugin" + config.TransportPlugin.Arg = []string{"-server"} + + trojanHost := "127.0.0.1" + trojanPort := common.PickPort("tcp", trojanHost) + config.TransportPlugin.Env = append( + config.TransportPlugin.Env, + "SS_REMOTE_HOST="+config.LocalHost, + "SS_REMOTE_PORT="+strconv.FormatInt(int64(config.LocalPort), 10), + "SS_LOCAL_HOST="+trojanHost, + "SS_LOCAL_PORT="+strconv.FormatInt(int64(trojanPort), 10), + ) + + config.LocalHost = trojanHost + config.LocalPort = trojanPort + config.LocalAddress = common.NewAddress(config.LocalHost, config.LocalPort, "tcp") + + cmd := exec.Command(config.TransportPlugin.Command, config.TransportPlugin.Arg...) + cmd.Env = append(cmd.Env, config.TransportPlugin.Env...) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stdout + config.TransportPlugin.Cmd = cmd + return config +} + +func addClientPluginConfig(config *conf.GlobalConfig) *conf.GlobalConfig { + config.TransportPlugin.Enabled = true + config.TransportPlugin.Command = "v2ray-plugin" + pluginHost := "127.0.0.1" + pluginPort := common.PickPort("tcp", pluginHost) + config.TransportPlugin.Env = append( + config.TransportPlugin.Env, + "SS_LOCAL_HOST="+pluginHost, + "SS_LOCAL_PORT="+strconv.FormatInt(int64(pluginPort), 10), + "SS_REMOTE_HOST="+config.RemoteHost, + "SS_REMOTE_PORT="+strconv.FormatInt(int64(config.RemotePort), 10), + ) + + config.RemoteHost = pluginHost + config.RemotePort = pluginPort + config.RemoteAddress = common.NewAddress(config.RemoteHost, config.RemotePort, "tcp") + + cmd := exec.Command(config.TransportPlugin.Command, config.TransportPlugin.Arg...) + cmd.Env = append(cmd.Env, config.TransportPlugin.Env...) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stdout + config.TransportPlugin.Cmd = cmd + return config +} + func RunClient(ctx context.Context, config *conf.GlobalConfig) { c := client.Client{} r, err := c.Build(config) @@ -552,3 +614,9 @@ func TestDNS(t *testing.T) { conn.Close() cancel() } + +func TestPlugin(t *testing.T) { + serverConfig := addServerPluginConfig(getBasicServerConfig()) + clientConfig := addClientPluginConfig(getBasicClientConfig()) + CheckClientServer(t, clientConfig, serverConfig) +}