diff --git a/common/errors/errors.go b/common/errors/errors.go deleted file mode 100644 index 0d19b69b8..000000000 --- a/common/errors/errors.go +++ /dev/null @@ -1,133 +0,0 @@ -package errors - -import ( - "fmt" -) - -func HasCode(err error, code int) bool { - if errWithCode, ok := err.(ErrorWithCode); ok { - return errWithCode.Code() == code - } - return false -} - -type ErrorWithCode interface { - error - Code() int -} - -type ErrorCode int - -func (code ErrorCode) Code() int { - return int(code) -} - -func (code ErrorCode) Prefix() string { - return fmt.Sprintf("[Error 0x%04X] ", code.Code()) -} - -type AuthenticationError struct { - ErrorCode - AuthDetail interface{} -} - -func NewAuthenticationError(detail interface{}) AuthenticationError { - return AuthenticationError{ - ErrorCode: 1, - AuthDetail: detail, - } -} - -func (err AuthenticationError) Error() string { - return fmt.Sprintf("%sInvalid auth %v", err.Prefix(), err.AuthDetail) -} - -type ProtocolVersionError struct { - ErrorCode - Version int -} - -func NewProtocolVersionError(version int) ProtocolVersionError { - return ProtocolVersionError{ - ErrorCode: 2, - Version: version, - } -} - -func (err ProtocolVersionError) Error() string { - return fmt.Sprintf("%sInvalid version %d", err.Prefix(), err.Version) -} - -type CorruptedPacketError struct { - ErrorCode -} - -var corruptedPacketErrorInstance = CorruptedPacketError{ErrorCode: 3} - -func NewCorruptedPacketError() CorruptedPacketError { - return corruptedPacketErrorInstance -} - -func (err CorruptedPacketError) Error() string { - return err.Prefix() + "Corrupted packet." -} - -type IPFormatError struct { - ErrorCode - IP []byte -} - -func NewIPFormatError(ip []byte) IPFormatError { - return IPFormatError{ - ErrorCode: 4, - IP: ip, - } -} - -func (err IPFormatError) Error() string { - return fmt.Sprintf("%sInvalid IP %v", err.Prefix(), err.IP) -} - -type ConfigurationError struct { - ErrorCode -} - -var configurationErrorInstance = ConfigurationError{ErrorCode: 5} - -func NewConfigurationError() ConfigurationError { - return configurationErrorInstance -} - -func (r ConfigurationError) Error() string { - return r.Prefix() + "Invalid configuration." -} - -type InvalidOperationError struct { - ErrorCode - Operation string -} - -func NewInvalidOperationError(operation string) InvalidOperationError { - return InvalidOperationError{ - ErrorCode: 6, - Operation: operation, - } -} - -func (r InvalidOperationError) Error() string { - return r.Prefix() + "Invalid operation: " + r.Operation -} - -type BadConfigurationError struct { - ErrorCode -} - -var badConfigurationErrorInstance = BadConfigurationError{ErrorCode: 6} - -func NewBadConfigurationError() BadConfigurationError { - return badConfigurationErrorInstance -} - -func (r BadConfigurationError) Error() string { - return r.Prefix() + "Bad configuration." -} diff --git a/common/errors/errors_test.go b/common/errors/errors_test.go deleted file mode 100644 index 5228f8bc1..000000000 --- a/common/errors/errors_test.go +++ /dev/null @@ -1,23 +0,0 @@ -package errors_test - -import ( - "testing" - - "github.com/v2ray/v2ray-core/common/errors" - "github.com/v2ray/v2ray-core/testing/unit" -) - -type MockError struct { - errors.ErrorCode -} - -func (err MockError) Error() string { - return "This is a fake error." -} - -func TestHasCode(t *testing.T) { - assert := unit.Assert(t) - - err := MockError{ErrorCode: 101} - assert.Error(err).HasCode(101) -} diff --git a/common/net/address.go b/common/net/address.go index f344a2228..14b1bc164 100644 --- a/common/net/address.go +++ b/common/net/address.go @@ -4,7 +4,6 @@ import ( "net" "strconv" - "github.com/v2ray/v2ray-core/common/errors" "github.com/v2ray/v2ray-core/common/log" ) @@ -42,7 +41,7 @@ func IPAddress(ip []byte, port uint16) Address { }, } default: - log.Error(errors.NewIPFormatError(ip).Error()) + log.Error("Invalid IP format: %v", ip) return nil } } diff --git a/config/errors.go b/config/errors.go new file mode 100644 index 000000000..e6f1057ee --- /dev/null +++ b/config/errors.go @@ -0,0 +1,9 @@ +package config + +import ( + "errors" +) + +var ( + BadConfiguration = errors.New("Bad configuration.") +) diff --git a/point.go b/point.go index dbb74f3ce..1364b7dd8 100644 --- a/point.go +++ b/point.go @@ -1,7 +1,6 @@ package core import ( - "github.com/v2ray/v2ray-core/common/errors" "github.com/v2ray/v2ray-core/common/log" v2net "github.com/v2ray/v2ray-core/common/net" "github.com/v2ray/v2ray-core/common/retry" @@ -41,7 +40,7 @@ func NewPoint(pConfig config.PointConfig) (*Point, error) { ichFactory, ok := inboundFactories[pConfig.InboundConfig().Protocol()] if !ok { log.Error("Unknown inbound connection handler factory %s", pConfig.InboundConfig().Protocol()) - return nil, errors.NewBadConfigurationError() + return nil, config.BadConfiguration } ichConfig := pConfig.InboundConfig().Settings(config.TypeInbound) ich, err := ichFactory.Create(vpoint, ichConfig) @@ -54,7 +53,7 @@ func NewPoint(pConfig config.PointConfig) (*Point, error) { ochFactory, ok := outboundFactories[pConfig.OutboundConfig().Protocol()] if !ok { log.Error("Unknown outbound connection handler factory %s", pConfig.OutboundConfig().Protocol()) - return nil, errors.NewBadConfigurationError() + return nil, config.BadConfiguration } ochConfig := pConfig.OutboundConfig().Settings(config.TypeOutbound) och, err := ochFactory.Create(vpoint, ochConfig) @@ -88,7 +87,7 @@ type OutboundConnectionHandler interface { func (vp *Point) Start() error { if vp.port <= 0 { log.Error("Invalid port %d", vp.port) - return errors.NewBadConfigurationError() + return config.BadConfiguration } return retry.Timed(100 /* times */, 100 /* ms */).On(func() error { diff --git a/proxy/errors.go b/proxy/errors.go new file mode 100644 index 000000000..4eb105696 --- /dev/null +++ b/proxy/errors.go @@ -0,0 +1,10 @@ +package proxy + +import ( + "errors" +) + +var ( + InvalidAuthentication = errors.New("Invalid authentication.") + InvalidProtocolVersion = errors.New("Invalid protocol version.") +) diff --git a/proxy/socks/protocol/socks.go b/proxy/socks/protocol/socks.go index d6a34b069..38d8a0070 100644 --- a/proxy/socks/protocol/socks.go +++ b/proxy/socks/protocol/socks.go @@ -5,9 +5,10 @@ import ( "io" "github.com/v2ray/v2ray-core/common/alloc" - "github.com/v2ray/v2ray-core/common/errors" "github.com/v2ray/v2ray-core/common/log" v2net "github.com/v2ray/v2ray-core/common/net" + "github.com/v2ray/v2ray-core/proxy" + "github.com/v2ray/v2ray-core/transport" ) const ( @@ -49,7 +50,7 @@ func ReadAuthentication(reader io.Reader) (auth Socks5AuthenticationRequest, aut } if nBytes < 2 { log.Info("Socks expected 2 bytes read, but only %d bytes read", nBytes) - err = errors.NewCorruptedPacketError() + err = transport.CorruptedPacket return } @@ -58,26 +59,27 @@ func ReadAuthentication(reader io.Reader) (auth Socks5AuthenticationRequest, aut auth4.Command = buffer.Value[1] auth4.Port = binary.BigEndian.Uint16(buffer.Value[2:4]) copy(auth4.IP[:], buffer.Value[4:8]) - err = NewSocksVersion4Error() + err = Socks4Downgrade return } auth.version = buffer.Value[0] if auth.version != socksVersion { - err = errors.NewProtocolVersionError(int(auth.version)) + log.Warning("Unknown protocol version %d", auth.version) + err = proxy.InvalidProtocolVersion return } auth.nMethods = buffer.Value[1] if auth.nMethods <= 0 { log.Info("Zero length of authentication methods") - err = errors.NewCorruptedPacketError() + err = transport.CorruptedPacket return } if nBytes-2 != int(auth.nMethods) { log.Info("Unmatching number of auth methods, expecting %d, but got %d", auth.nMethods, nBytes) - err = errors.NewCorruptedPacketError() + err = transport.CorruptedPacket return } copy(auth.authMethods[:], buffer.Value[2:nBytes]) @@ -194,7 +196,7 @@ func ReadRequest(reader io.Reader) (request *Socks5Request, err error) { return } if nBytes < 4 { - err = errors.NewCorruptedPacketError() + err = transport.CorruptedPacket return } request = &Socks5Request{ @@ -210,7 +212,7 @@ func ReadRequest(reader io.Reader) (request *Socks5Request, err error) { return } if nBytes != 4 { - err = errors.NewCorruptedPacketError() + err = transport.CorruptedPacket return } case AddrTypeDomain: @@ -226,7 +228,7 @@ func ReadRequest(reader io.Reader) (request *Socks5Request, err error) { if nBytes != int(domainLength) { log.Info("Unable to read domain with %d bytes, expecting %d bytes", nBytes, domainLength) - err = errors.NewCorruptedPacketError() + err = transport.CorruptedPacket return } request.Domain = string(buffer.Value[:domainLength]) @@ -236,12 +238,12 @@ func ReadRequest(reader io.Reader) (request *Socks5Request, err error) { return } if nBytes != 16 { - err = errors.NewCorruptedPacketError() + err = transport.CorruptedPacket return } default: log.Info("Unexpected address type %d", request.AddrType) - err = errors.NewCorruptedPacketError() + err = transport.CorruptedPacket return } @@ -250,7 +252,7 @@ func ReadRequest(reader io.Reader) (request *Socks5Request, err error) { return } if nBytes != 2 { - err = errors.NewCorruptedPacketError() + err = transport.CorruptedPacket return } diff --git a/proxy/socks/protocol/socks4.go b/proxy/socks/protocol/socks4.go index 0b5fa841d..a1c42217b 100644 --- a/proxy/socks/protocol/socks4.go +++ b/proxy/socks/protocol/socks4.go @@ -1,23 +1,14 @@ package protocol import ( + "errors" + "github.com/v2ray/v2ray-core/common/alloc" - "github.com/v2ray/v2ray-core/common/errors" ) -type SocksVersion4Error struct { - errors.ErrorCode -} - -var socksVersion4ErrorInstance = SocksVersion4Error{ErrorCode: 1000} - -func NewSocksVersion4Error() SocksVersion4Error { - return socksVersion4ErrorInstance -} - -func (err SocksVersion4Error) Error() string { - return err.Prefix() + "Request is socks version 4." -} +var ( + Socks4Downgrade = errors.New("Downgraded to Socks 4.") +) type Socks4AuthenticationRequest struct { Version byte diff --git a/proxy/socks/protocol/socks4_test.go b/proxy/socks/protocol/socks4_test.go index eb45aecba..41119d556 100644 --- a/proxy/socks/protocol/socks4_test.go +++ b/proxy/socks/protocol/socks4_test.go @@ -18,7 +18,7 @@ func TestSocks4AuthenticationRequestRead(t *testing.T) { 0x72, 0x72, 0x72, 0x72, } _, request4, err := ReadAuthentication(bytes.NewReader(rawRequest)) - assert.Error(err).HasCode(1000) + assert.Error(err).Equals(Socks4Downgrade) assert.Byte(request4.Version).Named("Version").Equals(0x04) assert.Byte(request4.Command).Named("Command").Equals(0x01) assert.Uint16(request4.Port).Named("Port").Equals(53) diff --git a/proxy/socks/socks.go b/proxy/socks/socks.go index 29bd0a28c..35d8001e7 100644 --- a/proxy/socks/socks.go +++ b/proxy/socks/socks.go @@ -1,6 +1,7 @@ package socks import ( + "errors" "io" "net" "strconv" @@ -9,13 +10,18 @@ import ( "github.com/v2ray/v2ray-core" "github.com/v2ray/v2ray-core/common/alloc" - "github.com/v2ray/v2ray-core/common/errors" "github.com/v2ray/v2ray-core/common/log" v2net "github.com/v2ray/v2ray-core/common/net" + "github.com/v2ray/v2ray-core/proxy" jsonconfig "github.com/v2ray/v2ray-core/proxy/socks/config/json" "github.com/v2ray/v2ray-core/proxy/socks/protocol" ) +var ( + UnsupportedSocksCommand = errors.New("Unsupported socks command.") + UnsupportedAuthMethod = errors.New("Unsupported auth method.") +) + // SocksServer is a SOCKS 5 proxy server type SocksServer struct { accepting bool @@ -61,12 +67,12 @@ func (server *SocksServer) HandleConnection(connection net.Conn) error { reader := v2net.NewTimeOutReader(120, connection) auth, auth4, err := protocol.ReadAuthentication(reader) - if err != nil && !errors.HasCode(err, 1000) { + if err != nil && err != protocol.Socks4Downgrade { log.Error("Socks failed to read authentication: %v", err) return err } - if err != nil && errors.HasCode(err, 1000) { + if err != nil && err == protocol.Socks4Downgrade { return server.handleSocks4(reader, connection, auth4) } else { return server.handleSocks5(reader, connection, auth) @@ -87,7 +93,7 @@ func (server *SocksServer) handleSocks5(reader *v2net.TimeOutReader, writer io.W return err } log.Warning("Socks client doesn't support allowed any auth methods.") - return errors.NewInvalidOperationError("Unsupported auth methods.") + return UnsupportedAuthMethod } authResponse := protocol.NewAuthenticationResponse(expectedAuthMethod) @@ -113,9 +119,8 @@ func (server *SocksServer) handleSocks5(reader *v2net.TimeOutReader, writer io.W return err } if status != byte(0) { - err = errors.NewAuthenticationError(upRequest.AuthDetail()) - log.Warning(err.Error()) - return err + log.Warning("Invalid user account: %s", upRequest.AuthDetail()) + return proxy.InvalidAuthentication } } @@ -143,7 +148,7 @@ func (server *SocksServer) handleSocks5(reader *v2net.TimeOutReader, writer io.W return err } log.Warning("Unsupported socks command %d", request.Command) - return errors.NewInvalidOperationError("Socks command " + strconv.Itoa(int(request.Command))) + return UnsupportedSocksCommand } response.Error = protocol.ErrorSuccess @@ -228,7 +233,8 @@ func (server *SocksServer) handleSocks4(reader io.Reader, writer io.Writer, auth responseBuffer.Release() if result == protocol.Socks4RequestRejected { - return errors.NewInvalidOperationError("Socks4 command " + strconv.Itoa(int(auth.Command))) + log.Warning("Unsupported socks 4 command %d", auth.Command) + return UnsupportedSocksCommand } dest := v2net.NewTCPDestination(v2net.IPAddress(auth.IP[:], auth.Port)) diff --git a/proxy/vmess/protocol/vmess.go b/proxy/vmess/protocol/vmess.go index cb8545295..4d2d11e76 100644 --- a/proxy/vmess/protocol/vmess.go +++ b/proxy/vmess/protocol/vmess.go @@ -9,10 +9,12 @@ import ( "io" "time" - "github.com/v2ray/v2ray-core/common/errors" v2io "github.com/v2ray/v2ray-core/common/io" + "github.com/v2ray/v2ray-core/common/log" v2net "github.com/v2ray/v2ray-core/common/net" + "github.com/v2ray/v2ray-core/proxy" "github.com/v2ray/v2ray-core/proxy/vmess/protocol/user" + "github.com/v2ray/v2ray-core/transport" ) const ( @@ -73,7 +75,7 @@ func (r *VMessRequestReader) Read(reader io.Reader) (*VMessRequest, error) { userId, timeSec, valid := r.vUserSet.GetUser(buffer[:nBytes]) if !valid { - return nil, errors.NewAuthenticationError(buffer[:nBytes]) + return nil, proxy.InvalidAuthentication } aesCipher, err := aes.NewCipher(userId.CmdKey()) @@ -99,7 +101,8 @@ func (r *VMessRequestReader) Read(reader io.Reader) (*VMessRequest, error) { } if request.Version != Version { - return nil, errors.NewProtocolVersionError(int(request.Version)) + log.Warning("Invalid protocol version %d", request.Version) + return nil, proxy.InvalidProtocolVersion } request.RequestIV = buffer[1:17] // 16 bytes @@ -149,7 +152,7 @@ func (r *VMessRequestReader) Read(reader io.Reader) (*VMessRequest, error) { expectedHash := binary.BigEndian.Uint32(buffer[bufferLen : bufferLen+4]) if actualHash != expectedHash { - return nil, errors.NewCorruptedPacketError() + return nil, transport.CorruptedPacket } return request, nil diff --git a/testing/unit/errorsubject.go b/testing/unit/errorsubject.go index 7c6dae549..e4612a225 100644 --- a/testing/unit/errorsubject.go +++ b/testing/unit/errorsubject.go @@ -1,11 +1,5 @@ package unit -import ( - "fmt" - - "github.com/v2ray/v2ray-core/common/errors" -) - type ErrorSubject struct { *Subject value error @@ -42,9 +36,3 @@ func (subject *ErrorSubject) IsNil() { subject.FailWithMessage("Not true that " + subject.DisplayString() + " is nil.") } } - -func (subject *ErrorSubject) HasCode(code int) { - if !errors.HasCode(subject.value, code) { - subject.FailWithMessage(fmt.Sprintf("Not ture that %s has error code 0x%04X.", subject.DisplayString(), code)) - } -} diff --git a/transport/errors.go b/transport/errors.go new file mode 100644 index 000000000..557d730c0 --- /dev/null +++ b/transport/errors.go @@ -0,0 +1,9 @@ +package transport + +import ( + "errors" +) + +var ( + CorruptedPacket = errors.New("Packet is corrupted.") +)