Bläddra i källkod

fix shadowsocks udp ota

v2ray 9 år sedan
förälder
incheckning
be10ca7e09
3 ändrade filer med 69 tillägg och 17 borttagningar
  1. 29 9
      proxy/shadowsocks/protocol.go
  2. 36 2
      proxy/shadowsocks/protocol_test.go
  3. 4 6
      proxy/shadowsocks/shadowsocks.go

+ 29 - 9
proxy/shadowsocks/protocol.go

@@ -17,12 +17,13 @@ const (
 )
 
 type Request struct {
-	Address v2net.Address
-	Port    v2net.Port
-	OTA     bool
+	Address    v2net.Address
+	Port       v2net.Port
+	OTA        bool
+	UDPPayload *alloc.Buffer
 }
 
-func ReadRequest(reader io.Reader, auth *Authenticator) (*Request, error) {
+func ReadRequest(reader io.Reader, auth *Authenticator, udp bool) (*Request, error) {
 	buffer := alloc.NewSmallBuffer()
 	defer buffer.Release()
 
@@ -85,14 +86,33 @@ func ReadRequest(reader io.Reader, auth *Authenticator) (*Request, error) {
 	request.Port = v2net.PortFromBytes(buffer.Value[lenBuffer : lenBuffer+2])
 	lenBuffer += 2
 
-	if request.OTA {
-		authBytes := buffer.Value[lenBuffer : lenBuffer+AuthSize]
-		_, err = io.ReadFull(reader, authBytes)
+	var authBytes []byte
+
+	if udp {
+		nBytes, err := reader.Read(buffer.Value[lenBuffer:])
 		if err != nil {
-			log.Error("Shadowsocks: Failed to read OTA: ", err)
-			return nil, transport.CorruptedPacket
+			log.Error("Shadowsocks: Failed to read UDP payload: ", err)
+		}
+		buffer.Slice(0, lenBuffer+nBytes)
+		if request.OTA {
+			authBytes = buffer.Value[lenBuffer+nBytes-AuthSize:]
+			request.UDPPayload = alloc.NewSmallBuffer().Clear().Append(buffer.Value[lenBuffer : lenBuffer+nBytes-AuthSize])
+			lenBuffer = lenBuffer + nBytes - AuthSize
+		} else {
+			request.UDPPayload = alloc.NewSmallBuffer().Clear().Append(buffer.Value[lenBuffer:])
 		}
+	} else {
+		if request.OTA {
+			authBytes = buffer.Value[lenBuffer : lenBuffer+AuthSize]
+			_, err = io.ReadFull(reader, authBytes)
+			if err != nil {
+				log.Error("Shadowsocks: Failed to read OTA: ", err)
+				return nil, transport.CorruptedPacket
+			}
+		}
+	}
 
+	if request.OTA {
 		actualAuth := auth.Authenticate(nil, buffer.Value[0:lenBuffer])
 		if !serial.BytesLiteral(actualAuth).Equals(serial.BytesLiteral(authBytes)) {
 			log.Error("Shadowsocks: Invalid OTA: ", actualAuth)

+ 36 - 2
proxy/shadowsocks/protocol_test.go

@@ -17,7 +17,7 @@ func TestNormalRequestParsing(t *testing.T) {
 	buffer := alloc.NewSmallBuffer().Clear()
 	buffer.AppendBytes(1, 127, 0, 0, 1, 0, 80)
 
-	request, err := ReadRequest(buffer, nil)
+	request, err := ReadRequest(buffer, nil, false)
 	assert.Error(err).IsNil()
 	netassert.Address(request.Address).Equals(v2net.IPAddress([]byte{127, 0, 0, 1}))
 	netassert.Port(request.Port).Equals(v2net.Port(80))
@@ -33,8 +33,42 @@ func TestOTARequest(t *testing.T) {
 	auth := NewAuthenticator(HeaderKeyGenerator(
 		[]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5},
 		[]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5}))
-	request, err := ReadRequest(buffer, auth)
+	request, err := ReadRequest(buffer, auth, false)
 	assert.Error(err).IsNil()
 	netassert.Address(request.Address).Equals(v2net.DomainAddress("www.v2ray.com"))
 	assert.Bool(request.OTA).IsTrue()
 }
+
+func TestUDPRequestParsing(t *testing.T) {
+	v2testing.Current(t)
+
+	buffer := alloc.NewSmallBuffer().Clear()
+	buffer.AppendBytes(1, 127, 0, 0, 1, 0, 80, 1, 2, 3, 4, 5, 6)
+
+	request, err := ReadRequest(buffer, nil, true)
+	assert.Error(err).IsNil()
+	netassert.Address(request.Address).Equals(v2net.IPAddress([]byte{127, 0, 0, 1}))
+	netassert.Port(request.Port).Equals(v2net.Port(80))
+	assert.Bool(request.OTA).IsFalse()
+	assert.Bytes(request.UDPPayload.Value).Equals([]byte{1, 2, 3, 4, 5, 6})
+}
+
+func TestUDPRequestWithOTA(t *testing.T) {
+	v2testing.Current(t)
+
+	buffer := alloc.NewSmallBuffer().Clear()
+	buffer.AppendBytes(
+		0x13, 13, 119, 119, 119, 46, 118, 50, 114, 97, 121, 46, 99, 111, 109, 0, 0,
+		1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0,
+		58, 32, 223, 30, 57, 199, 50, 139, 143, 101)
+
+	auth := NewAuthenticator(HeaderKeyGenerator(
+		[]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5},
+		[]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5}))
+	request, err := ReadRequest(buffer, auth, true)
+	assert.Error(err).IsNil()
+	netassert.Address(request.Address).Equals(v2net.DomainAddress("www.v2ray.com"))
+	assert.Bool(request.OTA).IsTrue()
+	assert.Bytes(request.UDPPayload.Value).Equals([]byte{
+		1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0})
+}

+ 4 - 6
proxy/shadowsocks/shadowsocks.go

@@ -85,14 +85,12 @@ func (this *Shadowsocks) handlerUDPPayload(payload *alloc.Buffer, dest v2net.Des
 		return
 	}
 
-	request, err := ReadRequest(reader, NewAuthenticator(HeaderKeyGenerator(key, iv)))
+	request, err := ReadRequest(reader, NewAuthenticator(HeaderKeyGenerator(key, iv)), true)
 	if err != nil {
 		return
 	}
 
-	buffer, _ := v2io.ReadFrom(reader, nil)
-
-	packet := v2net.NewPacket(v2net.TCPDestination(request.Address, request.Port), buffer, false)
+	packet := v2net.NewPacket(v2net.TCPDestination(request.Address, request.Port), request.UDPPayload, false)
 	ray := this.space.PacketDispatcher().DispatchToOutbound(packet)
 	close(ray.InboundInput())
 
@@ -126,7 +124,7 @@ func (this *Shadowsocks) handlerUDPPayload(payload *alloc.Buffer, dest v2net.Des
 
 		if request.OTA {
 			respAuth := NewAuthenticator(HeaderKeyGenerator(key, respIv))
-			respAuth.Authenticate(buffer.Value, buffer.Value[this.config.Cipher.IVSize():])
+			respAuth.Authenticate(response.Value, response.Value[this.config.Cipher.IVSize():])
 		}
 
 		this.udpHub.WriteTo(response.Value, dest)
@@ -155,7 +153,7 @@ func (this *Shadowsocks) handleConnection(conn *hub.TCPConn) {
 		return
 	}
 
-	request, err := ReadRequest(reader, NewAuthenticator(HeaderKeyGenerator(iv, key)))
+	request, err := ReadRequest(reader, NewAuthenticator(HeaderKeyGenerator(iv, key)), false)
 	if err != nil {
 		return
 	}