From ffce784dcec5e2ffee444855e09430770f456d48 Mon Sep 17 00:00:00 2001 From: v2ray Date: Sat, 11 Jun 2016 13:29:33 +0200 Subject: [PATCH 1/5] comments --- transport/config.go | 2 ++ transport/transport.go | 1 + 2 files changed, 3 insertions(+) diff --git a/transport/config.go b/transport/config.go index 967b0b1b7..f96021af8 100644 --- a/transport/config.go +++ b/transport/config.go @@ -1,9 +1,11 @@ package transport +// Config for V2Ray transport layer. type Config struct { ConnectionReuse bool } +// Apply applies this Config. func (this *Config) Apply() error { if this.ConnectionReuse { connectionReuse = true diff --git a/transport/transport.go b/transport/transport.go index ce88dd163..9d5cfc8f2 100644 --- a/transport/transport.go +++ b/transport/transport.go @@ -4,6 +4,7 @@ var ( connectionReuse = true ) +// IsConnectionReusable returns true if V2Ray is trying to reuse TCP connections. func IsConnectionReusable() bool { return connectionReuse } From 09f7e8b61e54451d821451ad2f456554ef1f5575 Mon Sep 17 00:00:00 2001 From: v2ray Date: Sat, 11 Jun 2016 22:52:37 +0200 Subject: [PATCH 2/5] meaningful error message --- proxy/blackhole/config_json.go | 5 +++-- proxy/dokodemo/config_json.go | 3 ++- proxy/freedom/config_json.go | 3 ++- proxy/http/config_json.go | 7 ++++--- proxy/shadowsocks/config_json.go | 3 ++- proxy/socks/config_json.go | 3 ++- proxy/vmess/inbound/config_json.go | 9 +++++---- proxy/vmess/outbound/config_json.go | 5 +++-- shell/point/config_json.go | 14 +++++++------- 9 files changed, 30 insertions(+), 22 deletions(-) diff --git a/proxy/blackhole/config_json.go b/proxy/blackhole/config_json.go index 2bf9696b6..e0050e760 100644 --- a/proxy/blackhole/config_json.go +++ b/proxy/blackhole/config_json.go @@ -4,6 +4,7 @@ package blackhole import ( "encoding/json" + "errors" "github.com/v2ray/v2ray-core/common/loader" "github.com/v2ray/v2ray-core/proxy/internal" @@ -15,7 +16,7 @@ func (this *Config) UnmarshalJSON(data []byte) error { } jsonConfig := new(JSONConfig) if err := json.Unmarshal(data, jsonConfig); err != nil { - return err + return errors.New("Blackhole: Failed to parse config: " + err.Error()) } this.Response = new(NoneResponse) @@ -25,7 +26,7 @@ func (this *Config) UnmarshalJSON(data []byte) error { loader.RegisterCreator("http", func() interface{} { return new(HTTPResponse) }) response, err := loader.Load(jsonConfig.Response) if err != nil { - return err + return errors.New("Blackhole: Failed to parse response config: " + err.Error()) } this.Response = response.(Response) } diff --git a/proxy/dokodemo/config_json.go b/proxy/dokodemo/config_json.go index d395a5842..b84994714 100644 --- a/proxy/dokodemo/config_json.go +++ b/proxy/dokodemo/config_json.go @@ -4,6 +4,7 @@ package dokodemo import ( "encoding/json" + "errors" v2net "github.com/v2ray/v2ray-core/common/net" "github.com/v2ray/v2ray-core/proxy/internal" @@ -18,7 +19,7 @@ func (this *Config) UnmarshalJSON(data []byte) error { } rawConfig := new(DokodemoConfig) if err := json.Unmarshal(data, rawConfig); err != nil { - return err + return errors.New("Dokodemo: Failed to parse config: " + err.Error()) } this.Address = rawConfig.Host.Address this.Port = rawConfig.PortValue diff --git a/proxy/freedom/config_json.go b/proxy/freedom/config_json.go index da8e589c1..461146923 100644 --- a/proxy/freedom/config_json.go +++ b/proxy/freedom/config_json.go @@ -4,6 +4,7 @@ package freedom import ( "encoding/json" + "errors" "strings" "github.com/v2ray/v2ray-core/proxy/internal" @@ -16,7 +17,7 @@ func (this *Config) UnmarshalJSON(data []byte) error { } jsonConfig := new(JsonConfig) if err := json.Unmarshal(data, jsonConfig); err != nil { - return err + return errors.New("Freedom: Failed to parse config: " + err.Error()) } this.DomainStrategy = DomainStrategyAsIs domainStrategy := strings.ToLower(jsonConfig.DomainStrategy) diff --git a/proxy/http/config_json.go b/proxy/http/config_json.go index a77e9973d..7730d86e1 100644 --- a/proxy/http/config_json.go +++ b/proxy/http/config_json.go @@ -5,6 +5,7 @@ package http import ( "crypto/tls" "encoding/json" + "errors" "github.com/v2ray/v2ray-core/proxy/internal" ) @@ -18,7 +19,7 @@ func (this *CertificateConfig) UnmarshalJSON(data []byte) error { } jsonConfig := new(JsonConfig) if err := json.Unmarshal(data, jsonConfig); err != nil { - return err + return errors.New("HTTP: Failed to parse certificate config: " + err.Error()) } cert, err := tls.LoadX509KeyPair(jsonConfig.CertFile, jsonConfig.KeyFile) @@ -38,7 +39,7 @@ func (this *TLSConfig) UnmarshalJSON(data []byte) error { } jsonConfig := new(JsonConfig) if err := json.Unmarshal(data, jsonConfig); err != nil { - return err + return errors.New("HTTP: Failed to parse TLS config: " + err.Error()) } this.Enabled = jsonConfig.Enabled @@ -53,7 +54,7 @@ func (this *Config) UnmarshalJSON(data []byte) error { } jsonConfig := new(JsonConfig) if err := json.Unmarshal(data, jsonConfig); err != nil { - return err + return errors.New("HTTP: Failed to parse config: " + err.Error()) } this.TLSConfig = jsonConfig.Tls diff --git a/proxy/shadowsocks/config_json.go b/proxy/shadowsocks/config_json.go index a62451e94..8ab14c6a4 100644 --- a/proxy/shadowsocks/config_json.go +++ b/proxy/shadowsocks/config_json.go @@ -4,6 +4,7 @@ package shadowsocks import ( "encoding/json" + "errors" "strings" "github.com/v2ray/v2ray-core/common/log" @@ -21,7 +22,7 @@ func (this *Config) UnmarshalJSON(data []byte) error { } jsonConfig := new(JsonConfig) if err := json.Unmarshal(data, jsonConfig); err != nil { - return err + return errors.New("Shadowsocks: Failed to parse config: " + err.Error()) } this.UDP = jsonConfig.UDP diff --git a/proxy/socks/config_json.go b/proxy/socks/config_json.go index e2dbeba87..e0cafcf49 100644 --- a/proxy/socks/config_json.go +++ b/proxy/socks/config_json.go @@ -4,6 +4,7 @@ package socks import ( "encoding/json" + "errors" "github.com/v2ray/v2ray-core/common/log" v2net "github.com/v2ray/v2ray-core/common/net" @@ -30,7 +31,7 @@ func (this *Config) UnmarshalJSON(data []byte) error { rawConfig := new(SocksConfig) if err := json.Unmarshal(data, rawConfig); err != nil { - return err + return errors.New("Socks: Failed to parse config: " + err.Error()) } if rawConfig.AuthMethod == AuthMethodNoAuth { this.AuthType = AuthTypeNoAuth diff --git a/proxy/vmess/inbound/config_json.go b/proxy/vmess/inbound/config_json.go index 79af526cd..0538d235d 100644 --- a/proxy/vmess/inbound/config_json.go +++ b/proxy/vmess/inbound/config_json.go @@ -4,6 +4,7 @@ package inbound import ( "encoding/json" + "errors" "github.com/v2ray/v2ray-core/common/protocol" "github.com/v2ray/v2ray-core/proxy/internal" @@ -15,7 +16,7 @@ func (this *DetourConfig) UnmarshalJSON(data []byte) error { } jsonConfig := new(JsonDetourConfig) if err := json.Unmarshal(data, jsonConfig); err != nil { - return err + return errors.New("VMessIn: Failed to parse detour config: " + err.Error()) } this.ToTag = jsonConfig.ToTag return nil @@ -27,7 +28,7 @@ func (this *FeaturesConfig) UnmarshalJSON(data []byte) error { } jsonConfig := new(JsonFeaturesConfig) if err := json.Unmarshal(data, jsonConfig); err != nil { - return err + return errors.New("VMessIn: Failed to parse features config: " + err.Error()) } this.Detour = jsonConfig.Detour return nil @@ -40,7 +41,7 @@ func (this *DefaultConfig) UnmarshalJSON(data []byte) error { } jsonConfig := new(JsonDefaultConfig) if err := json.Unmarshal(data, jsonConfig); err != nil { - return err + return errors.New("VMessIn: Failed to parse default config: " + err.Error()) } this.AlterIDs = jsonConfig.AlterIDs if this.AlterIDs == 0 { @@ -59,7 +60,7 @@ func (this *Config) UnmarshalJSON(data []byte) error { } jsonConfig := new(JsonConfig) if err := json.Unmarshal(data, jsonConfig); err != nil { - return err + return errors.New("VMessIn: Failed to parse config: " + err.Error()) } this.AllowedUsers = jsonConfig.Users this.Features = jsonConfig.Features // Backward compatibility diff --git a/proxy/vmess/outbound/config_json.go b/proxy/vmess/outbound/config_json.go index 06f23d7ef..5c6370324 100644 --- a/proxy/vmess/outbound/config_json.go +++ b/proxy/vmess/outbound/config_json.go @@ -4,6 +4,7 @@ package outbound import ( "encoding/json" + "errors" "github.com/v2ray/v2ray-core/common/log" "github.com/v2ray/v2ray-core/proxy/internal" @@ -16,10 +17,10 @@ func (this *Config) UnmarshalJSON(data []byte) error { rawOutbound := &RawOutbound{} err := json.Unmarshal(data, rawOutbound) if err != nil { - return err + return errors.New("VMessOut: Failed to parse config: " + err.Error()) } if len(rawOutbound.Receivers) == 0 { - log.Error("VMess: 0 VMess receiver configured.") + log.Error("VMessOut: 0 VMess receiver configured.") return internal.ErrorBadConfiguration } this.Receivers = rawOutbound.Receivers diff --git a/shell/point/config_json.go b/shell/point/config_json.go index 32fbaf777..6c408f35b 100644 --- a/shell/point/config_json.go +++ b/shell/point/config_json.go @@ -34,7 +34,7 @@ func (this *Config) UnmarshalJSON(data []byte) error { } jsonConfig := new(JsonConfig) if err := json.Unmarshal(data, jsonConfig); err != nil { - return err + return errors.New("Point: Failed to parse config: " + err.Error()) } this.Port = jsonConfig.Port this.LogConfig = jsonConfig.LogConfig @@ -65,7 +65,7 @@ func (this *InboundConnectionConfig) UnmarshalJSON(data []byte) error { jsonConfig := new(JsonConfig) if err := json.Unmarshal(data, jsonConfig); err != nil { - return err + return errors.New("Point: Failed to parse inbound config: " + err.Error()) } this.Port = v2net.Port(jsonConfig.Port) this.ListenOn = v2net.AnyIP @@ -89,7 +89,7 @@ func (this *OutboundConnectionConfig) UnmarshalJSON(data []byte) error { } jsonConfig := new(JsonConnectionConfig) if err := json.Unmarshal(data, jsonConfig); err != nil { - return err + return errors.New("Point: Failed to parse outbound config: " + err.Error()) } this.Protocol = jsonConfig.Protocol this.Settings = jsonConfig.Settings @@ -112,7 +112,7 @@ func (this *LogConfig) UnmarshalJSON(data []byte) error { } jsonConfig := new(JsonLogConfig) if err := json.Unmarshal(data, jsonConfig); err != nil { - return err + return errors.New("Point: Failed to parse log config: " + err.Error()) } this.AccessLog = jsonConfig.AccessLog this.ErrorLog = jsonConfig.ErrorLog @@ -141,7 +141,7 @@ func (this *InboundDetourAllocationConfig) UnmarshalJSON(data []byte) error { } jsonConfig := new(JsonInboundDetourAllocationConfig) if err := json.Unmarshal(data, jsonConfig); err != nil { - return err + return errors.New("Point: Failed to parse inbound detour allocation config: " + err.Error()) } this.Strategy = jsonConfig.Strategy this.Concurrency = jsonConfig.Concurrency @@ -171,7 +171,7 @@ func (this *InboundDetourConfig) UnmarshalJSON(data []byte) error { } jsonConfig := new(JsonInboundDetourConfig) if err := json.Unmarshal(data, jsonConfig); err != nil { - return err + return errors.New("Point: Failed to parse inbound detour config: " + err.Error()) } if jsonConfig.PortRange == nil { log.Error("Point: Port range not specified in InboundDetour.") @@ -207,7 +207,7 @@ func (this *OutboundDetourConfig) UnmarshalJSON(data []byte) error { } jsonConfig := new(JsonOutboundDetourConfig) if err := json.Unmarshal(data, jsonConfig); err != nil { - return err + return errors.New("Point: Failed to parse outbound detour config: " + err.Error()) } this.Protocol = jsonConfig.Protocol this.Tag = jsonConfig.Tag From 098982d79a975a0792a4737bc4d69ab713a82e87 Mon Sep 17 00:00:00 2001 From: v2ray Date: Sat, 11 Jun 2016 22:54:23 +0200 Subject: [PATCH 3/5] adjust error level --- common/protocol/raw/client.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/common/protocol/raw/client.go b/common/protocol/raw/client.go index c1bcfc2b9..94f25bed5 100644 --- a/common/protocol/raw/client.go +++ b/common/protocol/raw/client.go @@ -109,12 +109,12 @@ func (this *ClientSession) DecodeResponseHeader(reader io.Reader) (*protocol.Res _, err := io.ReadFull(this.responseReader, buffer.Value[:4]) if err != nil { - log.Error("Raw: Failed to read response header: ", err) + log.Info("Raw: Failed to read response header: ", err) return nil, err } if buffer.Value[0] != this.responseHeader { - log.Warning("Raw: Unexpected response header. Expecting %d, but actually %d", this.responseHeader, buffer.Value[0]) + log.Info("Raw: Unexpected response header. Expecting ", this.responseHeader, " but actually ", buffer.Value[0]) return nil, transport.ErrorCorruptedPacket } @@ -127,7 +127,7 @@ func (this *ClientSession) DecodeResponseHeader(reader io.Reader) (*protocol.Res dataLen := int(buffer.Value[3]) _, err := io.ReadFull(this.responseReader, buffer.Value[:dataLen]) if err != nil { - log.Error("Raw: Failed to read response command: ", err) + log.Info("Raw: Failed to read response command: ", err) return nil, err } data := buffer.Value[:dataLen] From 1c06fc216a32b359f4c4fc4a61c45884f3677bf9 Mon Sep 17 00:00:00 2001 From: v2ray Date: Sun, 12 Jun 2016 01:30:56 +0200 Subject: [PATCH 4/5] allow redirection in dokodemo --- proxy/dokodemo/config.go | 9 +++++---- proxy/dokodemo/config_json.go | 2 ++ proxy/dokodemo/dokodemo.go | 31 ++++++++++++++++++++++++++++++- transport/hub/connection.go | 20 ++++++++++++++++++++ 4 files changed, 57 insertions(+), 5 deletions(-) diff --git a/proxy/dokodemo/config.go b/proxy/dokodemo/config.go index 44d02e288..8c281d298 100644 --- a/proxy/dokodemo/config.go +++ b/proxy/dokodemo/config.go @@ -5,8 +5,9 @@ import ( ) type Config struct { - Address v2net.Address - Port v2net.Port - Network *v2net.NetworkList - Timeout int + FollowRedirect bool + Address v2net.Address + Port v2net.Port + Network *v2net.NetworkList + Timeout int } diff --git a/proxy/dokodemo/config_json.go b/proxy/dokodemo/config_json.go index b84994714..f13e3de51 100644 --- a/proxy/dokodemo/config_json.go +++ b/proxy/dokodemo/config_json.go @@ -16,6 +16,7 @@ func (this *Config) UnmarshalJSON(data []byte) error { PortValue v2net.Port `json:"port"` NetworkList *v2net.NetworkList `json:"network"` TimeoutValue int `json:"timeout"` + Redirect bool `json:"followRedirect"` } rawConfig := new(DokodemoConfig) if err := json.Unmarshal(data, rawConfig); err != nil { @@ -25,6 +26,7 @@ func (this *Config) UnmarshalJSON(data []byte) error { this.Port = rawConfig.PortValue this.Network = rawConfig.NetworkList this.Timeout = rawConfig.TimeoutValue + this.FollowRedirect = rawConfig.Redirect return nil } diff --git a/proxy/dokodemo/dokodemo.go b/proxy/dokodemo/dokodemo.go index 84b352076..ac2387a5b 100644 --- a/proxy/dokodemo/dokodemo.go +++ b/proxy/dokodemo/dokodemo.go @@ -2,6 +2,7 @@ package dokodemo import ( "sync" + "syscall" "github.com/v2ray/v2ray-core/app" "github.com/v2ray/v2ray-core/app/dispatcher" @@ -14,6 +15,8 @@ import ( "github.com/v2ray/v2ray-core/transport/hub" ) +const SO_ORIGINAL_DST = 80 + type DokodemoDoor struct { tcpMutex sync.RWMutex udpMutex sync.RWMutex @@ -129,7 +132,16 @@ func (this *DokodemoDoor) ListenTCP() error { func (this *DokodemoDoor) HandleTCPConnection(conn *hub.Connection) { defer conn.Close() - ray := this.packetDispatcher.DispatchToOutbound(v2net.TCPDestination(this.address, this.port)) + dest := v2net.TCPDestination(this.address, this.port) + if this.config.FollowRedirect { + originalDest := GetOriginalDestination(conn) + if originalDest != nil { + log.Info("Dokodemo: Following redirect to: ", originalDest) + dest = originalDest + } + } + + ray := this.packetDispatcher.DispatchToOutbound(dest) defer ray.InboundOutput().Release() var inputFinish, outputFinish sync.Mutex @@ -160,6 +172,23 @@ func (this *DokodemoDoor) HandleTCPConnection(conn *hub.Connection) { inputFinish.Lock() } +func GetOriginalDestination(conn *hub.Connection) v2net.Destination { + fd, err := conn.SysFd() + if err != nil { + log.Info("Dokodemo: Failed to get original destination: ", err) + return nil + } + + addr, err := syscall.GetsockoptIPv6Mreq(fd, syscall.IPPROTO_IP, SO_ORIGINAL_DST) + if err != nil { + log.Info("Dokodemo: Failed to call getsockopt: ", err) + return nil + } + ip := v2net.IPAddress(addr.Multiaddr[4:8]) + port := uint16(addr.Multiaddr[2])<<8 + uint16(addr.Multiaddr[3]) + return v2net.TCPDestination(ip, v2net.Port(port)) +} + func init() { internal.MustRegisterInboundHandlerCreator("dokodemo-door", func(space app.Space, rawConfig interface{}, meta *proxy.InboundHandlerMeta) (proxy.InboundHandler, error) { diff --git a/transport/hub/connection.go b/transport/hub/connection.go index 0c7c0019e..83f2e236b 100644 --- a/transport/hub/connection.go +++ b/transport/hub/connection.go @@ -1,12 +1,18 @@ package hub import ( + "errors" "net" + "reflect" "time" "github.com/v2ray/v2ray-core/transport" ) +var ( + ErrInvalidConn = errors.New("Invalid Connection.") +) + type ConnectionHandler func(*Connection) type ConnectionManager interface { @@ -73,3 +79,17 @@ func (this *Connection) SetReusable(reusable bool) { func (this *Connection) Reusable() bool { return this.reusable } + +func (this *Connection) SysFd() (int, error) { + cv := reflect.ValueOf(this.conn) + switch ce := cv.Elem(); ce.Kind() { + case reflect.Struct: + netfd := ce.FieldByName("conn").FieldByName("fd") + switch fe := netfd.Elem(); fe.Kind() { + case reflect.Struct: + fd := fe.FieldByName("sysfd") + return int(fd.Int()), nil + } + } + return 0, ErrInvalidConn +} From 679d64657164aad1df7aebae4d4bb5aef62ab1a0 Mon Sep 17 00:00:00 2001 From: v2ray Date: Sun, 12 Jun 2016 01:35:40 +0200 Subject: [PATCH 5/5] only build for linux --- proxy/dokodemo/dokodemo.go | 20 -------------------- proxy/dokodemo/sockopt_linux.go | 30 ++++++++++++++++++++++++++++++ proxy/dokodemo/sockopt_other.go | 12 ++++++++++++ 3 files changed, 42 insertions(+), 20 deletions(-) create mode 100644 proxy/dokodemo/sockopt_linux.go create mode 100644 proxy/dokodemo/sockopt_other.go diff --git a/proxy/dokodemo/dokodemo.go b/proxy/dokodemo/dokodemo.go index ac2387a5b..9848b0c93 100644 --- a/proxy/dokodemo/dokodemo.go +++ b/proxy/dokodemo/dokodemo.go @@ -2,7 +2,6 @@ package dokodemo import ( "sync" - "syscall" "github.com/v2ray/v2ray-core/app" "github.com/v2ray/v2ray-core/app/dispatcher" @@ -15,8 +14,6 @@ import ( "github.com/v2ray/v2ray-core/transport/hub" ) -const SO_ORIGINAL_DST = 80 - type DokodemoDoor struct { tcpMutex sync.RWMutex udpMutex sync.RWMutex @@ -172,23 +169,6 @@ func (this *DokodemoDoor) HandleTCPConnection(conn *hub.Connection) { inputFinish.Lock() } -func GetOriginalDestination(conn *hub.Connection) v2net.Destination { - fd, err := conn.SysFd() - if err != nil { - log.Info("Dokodemo: Failed to get original destination: ", err) - return nil - } - - addr, err := syscall.GetsockoptIPv6Mreq(fd, syscall.IPPROTO_IP, SO_ORIGINAL_DST) - if err != nil { - log.Info("Dokodemo: Failed to call getsockopt: ", err) - return nil - } - ip := v2net.IPAddress(addr.Multiaddr[4:8]) - port := uint16(addr.Multiaddr[2])<<8 + uint16(addr.Multiaddr[3]) - return v2net.TCPDestination(ip, v2net.Port(port)) -} - func init() { internal.MustRegisterInboundHandlerCreator("dokodemo-door", func(space app.Space, rawConfig interface{}, meta *proxy.InboundHandlerMeta) (proxy.InboundHandler, error) { diff --git a/proxy/dokodemo/sockopt_linux.go b/proxy/dokodemo/sockopt_linux.go new file mode 100644 index 000000000..6c329be2f --- /dev/null +++ b/proxy/dokodemo/sockopt_linux.go @@ -0,0 +1,30 @@ +// +build linux + +package dokodemo + +import ( + "syscall" + + "github.com/v2ray/v2ray-core/common/log" + v2net "github.com/v2ray/v2ray-core/common/net" + "github.com/v2ray/v2ray-core/transport/hub" +) + +const SO_ORIGINAL_DST = 80 + +func GetOriginalDestination(conn *hub.Connection) v2net.Destination { + fd, err := conn.SysFd() + if err != nil { + log.Info("Dokodemo: Failed to get original destination: ", err) + return nil + } + + addr, err := syscall.GetsockoptIPv6Mreq(fd, syscall.IPPROTO_IP, SO_ORIGINAL_DST) + if err != nil { + log.Info("Dokodemo: Failed to call getsockopt: ", err) + return nil + } + ip := v2net.IPAddress(addr.Multiaddr[4:8]) + port := uint16(addr.Multiaddr[2])<<8 + uint16(addr.Multiaddr[3]) + return v2net.TCPDestination(ip, v2net.Port(port)) +} diff --git a/proxy/dokodemo/sockopt_other.go b/proxy/dokodemo/sockopt_other.go new file mode 100644 index 000000000..04dedd3d0 --- /dev/null +++ b/proxy/dokodemo/sockopt_other.go @@ -0,0 +1,12 @@ +// +build !linux + +package dokodemo + +import ( + v2net "github.com/v2ray/v2ray-core/common/net" + "github.com/v2ray/v2ray-core/transport/hub" +) + +func GetOriginalDestination(conn *hub.Connection) v2net.Destination { + return nil +}