fix ss fallback, redirector nil interface

This commit is contained in:
Page Fault
2020-06-21 04:22:54 +00:00
parent 3e196db29d
commit f906f21cef
8 changed files with 222 additions and 12 deletions
+20 -2
View File
@@ -2,14 +2,31 @@ package custom
import (
"context"
"strings"
"github.com/p4gefau1t/trojan-go/common"
"github.com/p4gefau1t/trojan-go/config"
"github.com/p4gefau1t/trojan-go/proxy"
"github.com/p4gefau1t/trojan-go/tunnel"
"gopkg.in/yaml.v2"
"strings"
)
func convert(i interface{}) interface{} {
switch x := i.(type) {
case map[interface{}]interface{}:
m2 := map[string]interface{}{}
for k, v := range x {
m2[k.(string)] = convert(v)
}
return m2
case []interface{}:
for i, v := range x {
x[i] = convert(v)
}
}
return i
}
func buildNodes(ctx context.Context, nodeConfigList []NodeConfig) (map[string]*proxy.Node, error) {
nodes := make(map[string]*proxy.Node)
for _, nodeCfg := range nodeConfigList {
@@ -18,10 +35,11 @@ func buildNodes(ctx context.Context, nodeConfigList []NodeConfig) (map[string]*p
return nil, common.NewError("invalid protocol name:" + nodeCfg.Protocol)
}
data, err := yaml.Marshal(nodeCfg.Config)
common.Must(err)
nodeContext, err := config.WithYAMLConfig(ctx, data)
if err != nil {
return nil, common.NewError("failed to parse config data for " + nodeCfg.Tag + " with protocol" + nodeCfg.Protocol).Base(err)
}
nodeContext, err := config.WithYAMLConfig(ctx, data)
node := &proxy.Node{
Name: nodeCfg.Protocol,
Next: make(map[string]*proxy.Node),
+2 -1
View File
@@ -4,6 +4,7 @@ import (
"context"
"io"
"net"
"reflect"
"github.com/p4gefau1t/trojan-go/common"
"github.com/p4gefau1t/trojan-go/log"
@@ -42,7 +43,7 @@ func (r *Redirector) worker() {
if redirection.Dial == nil {
redirection.Dial = defaultDial
}
if redirection.RedirectTo == nil {
if reflect.ValueOf(redirection.RedirectTo).IsNil() {
log.Error("nil redirection addr")
return
}
+175 -3
View File
@@ -8,7 +8,7 @@ import (
"testing"
)
func TestCustom(t *testing.T) {
func TestCustom1(t *testing.T) {
serverPort := common.PickPort("tcp", "127.0.0.1")
socksPort := common.PickPort("tcp", "127.0.0.1")
clientData := fmt.Sprintf(`
@@ -48,7 +48,7 @@ outbound:
tag: trojan
config:
password:
- 12345678
- "12345678"
path:
-
@@ -83,7 +83,7 @@ inbound:
config:
disable-http-check: true
password:
- 12345678
- "12345678"
- protocol: mux
tag: mux
@@ -119,3 +119,175 @@ outbound:
t.Fail()
}
}
func TestCustom2(t *testing.T) {
serverPort := common.PickPort("tcp", "127.0.0.1")
socksPort := common.PickPort("tcp", "127.0.0.1")
clientData := fmt.Sprintf(`
run-type: custom
log-level: 0
inbound:
node:
- protocol: transport
tag: transport
config:
local-addr: 127.0.0.1
local-port: %d
- protocol: socks
tag: socks
path:
-
- transport
- socks
outbound:
node:
- protocol: transport
tag: transport
config:
remote-addr: 127.0.0.1
remote-port: %d
- protocol: tls
tag: tls
config:
ssl:
sni: localhost
key: server.key
cert: server.crt
- protocol: trojan
tag: trojan
config:
password:
- "12345678"
- protocol: shadowsocks
tag: shadowsocks
config:
remote-addr: 127.0.0.1
remote-port: 80
shadowsocks:
enabled: true
password: "12345678"
- protocol: websocket
tag: websocket
config:
websocket:
hostname: localhost
path: /ws
path:
-
- transport
- tls
- websocket
- shadowsocks
- trojan
`, socksPort, serverPort)
serverData := fmt.Sprintf(`
run-type: custom
log-level: 0
inbound:
node:
- protocol: transport
tag: transport
config:
local-addr: 127.0.0.1
local-port: %d
remote-addr: 127.0.0.1
remote-port: %s
- protocol: tls
tag: tls
config:
ssl:
sni: localhost
key: server.key
cert: server.crt
- protocol: trojan
tag: trojan
config:
disable-http-check: true
password:
- "12345678"
- protocol: trojan
tag: trojan2
config:
disable-http-check: true
password:
- "12345678"
- protocol: websocket
tag: websocket
config:
websocket:
enabled: true
hostname: localhost
path: /ws
- protocol: mux
tag: mux
- protocol: simplesocks
tag: simplesocks
- protocol: shadowsocks
tag: shadowsocks
config:
remote-addr: 127.0.0.1
remote-port: 80
shadowsocks:
enabled: true
password: "12345678"
- protocol: shadowsocks
tag: shadowsocks2
config:
remote-addr: 127.0.0.1
remote-port: 80
shadowsocks:
enabled: true
password: "12345678"
path:
-
- transport
- tls
- shadowsocks
- trojan
-
- transport
- tls
- websocket
- shadowsocks2
- trojan2
-
- transport
- tls
- shadowsocks
- trojan
- mux
- simplesocks
outbound:
node:
- protocol: freedom
tag: freedom
path:
-
- freedom
`, serverPort, util.HTTPPort)
if !CheckClientServer(clientData, serverData, socksPort) {
t.Fail()
}
}
+2 -2
View File
@@ -85,11 +85,11 @@ func init() {
}
func CheckClientServer(clientData, serverData string, socksPort int) (ok bool) {
server, err := proxy.NewProxyFromConfigData([]byte(clientData), false)
server, err := proxy.NewProxyFromConfigData([]byte(serverData), false)
common.Must(err)
go server.Run()
client, err := proxy.NewProxyFromConfigData([]byte(serverData), false)
client, err := proxy.NewProxyFromConfigData([]byte(clientData), false)
common.Must(err)
go client.Run()
+2 -2
View File
@@ -9,8 +9,8 @@ type ShadowsocksConfig struct {
}
type Config struct {
RemoteHost string `json:"remote_addr", yaml:"remote-addr"`
RemotePort int `json:"remote_port", yaml:"remote-port"`
RemoteHost string `json:"remote_addr" yaml:"remote-addr"`
RemotePort int `json:"remote_port" yaml:"remote-port"`
Shadowsocks ShadowsocksConfig `json,yaml:"shadowsocks"`
}
+7
View File
@@ -32,6 +32,7 @@ func (s *Server) AcceptConn(overlay tunnel.Tunnel) (tunnel.Conn, error) {
testConn := s.Cipher.StreamConn(rewindConn)
if _, err := testConn.Read(buf[:]); err != nil {
// we are under attack
log.Error(common.NewError("shadowsocks failed to decrypt").Base(err))
rewindConn.Rewind()
rewindConn.StopBuffering()
s.Redirect(&redirector.Redirection{
@@ -63,6 +64,12 @@ func NewServer(ctx context.Context, underlay tunnel.Server) (*Server, error) {
if err != nil {
return nil, common.NewError("invalid shadowsocks cipher").Base(err)
}
if cfg.RemoteHost == "" {
return nil, common.NewError("invalid shadowsocks redirection address")
}
if cfg.RemotePort == 0 {
return nil, common.NewError("invalid shadowsocks redirection port")
}
log.Debug("shadowsocks client created")
return &Server{
underlay: underlay,
+4 -2
View File
@@ -6,11 +6,12 @@ import (
"crypto/tls"
"crypto/x509"
"encoding/pem"
"github.com/p4gefau1t/trojan-go/tunnel/tls/fingerprint"
"github.com/p4gefau1t/trojan-go/tunnel/transport"
"io"
"io/ioutil"
"github.com/p4gefau1t/trojan-go/tunnel/tls/fingerprint"
"github.com/p4gefau1t/trojan-go/tunnel/transport"
"net"
"net/http"
"os"
@@ -139,6 +140,7 @@ func (s *Server) acceptLoop() {
} else {
if !s.nextHTTP {
// there is no websocket layer waiting for connections, redirect it
log.Error("incoming http request, but no websocket server is listening")
s.redir.Redirect(&redirector.Redirection{
InboundConn: rewindConn,
RedirectTo: s.fallbackAddress,
+10
View File
@@ -66,6 +66,7 @@ func (s *Server) AcceptConn(tunnel.Tunnel) (tunnel.Conn, error) {
req, err := http.ReadRequest(rw.Reader)
if err != nil {
log.Debug("invalid http request")
rewindConn.Rewind()
rewindConn.StopBuffering()
s.redir.Redirect(&redirector.Redirection{
@@ -75,6 +76,7 @@ func (s *Server) AcceptConn(tunnel.Tunnel) (tunnel.Conn, error) {
return nil, common.NewError("not a valid http request: " + conn.RemoteAddr().String()).Base(err)
}
if strings.ToLower(req.Header.Get("Upgrade")) != "websocket" || req.URL.Path != s.path {
log.Debug("invalid http websocket handshake request")
rewindConn.Rewind()
rewindConn.StopBuffering()
s.redir.Redirect(&redirector.Redirection{
@@ -145,6 +147,14 @@ func NewServer(ctx context.Context, underlay tunnel.Server) (*Server, error) {
return nil, common.NewError("websocket path must start with \"/\"")
}
}
if cfg.RemoteHost == "" {
log.Warn("empty websocket redirection hostname")
cfg.RemoteHost = cfg.Websocket.Hostname
}
if cfg.RemotePort == 0 {
log.Warn("empty websocket redirection port")
cfg.RemotePort = 80
}
ctx, cancel := context.WithCancel(ctx)
log.Debug("websocket server created")
return &Server{