瀏覽代碼

sample socks proxy

V2Ray 10 年之前
父節點
當前提交
262eb4f985

+ 13 - 7
io/socks/socks.go

@@ -5,6 +5,7 @@ import (
 	"encoding/binary"
 	"fmt"
 	"io"
+  _ "log"
 
 	v2net "github.com/v2ray/v2ray-core/net"
 )
@@ -25,7 +26,7 @@ type Socks5AuthenticationRequest struct {
 }
 
 func (request *Socks5AuthenticationRequest) HasAuthMethod(method byte) bool {
-	for i := byte(0); i < request.nMethods; i++ {
+  for i := 0; i < int(request.nMethods); i++ {
 		if request.authMethods[i] == method {
 			return true
 		}
@@ -140,17 +141,22 @@ func ReadRequest(reader io.Reader) (request *Socks5Request, err error) {
 			return
 		}
 	case AddrTypeDomain:
-		buffer = make([]byte, 257)
-		nBytes, err = reader.Read(buffer)
+		buffer = make([]byte, 256)
+    nBytes, err = reader.Read(buffer[0:1])
+    if err != nil {
+      return
+    }
+    domainLength := buffer[0]
+		nBytes, err = reader.Read(buffer[:domainLength])
 		if err != nil {
 			return
 		}
-		domainLength := buffer[0]
-		if nBytes != int(domainLength)+1 {
-			err = fmt.Errorf("Unable to read domain")
+		
+		if nBytes != int(domainLength) {
+			err = fmt.Errorf("Unable to read domain with %d bytes, expecting %d bytes", nBytes, domainLength)
 			return
 		}
-		request.Domain = string(buffer[1 : domainLength+1])
+		request.Domain = string(buffer[:domainLength])
 	case AddrTypeIPv6:
 		nBytes, err = reader.Read(request.IPv6[:])
 		if err != nil {

+ 6 - 1
net/freedom/freedom.go

@@ -1,8 +1,9 @@
-package tcp
+package freedom
 
 import (
 	"io"
 	"net"
+  "log"
 
 	"github.com/v2ray/v2ray-core"
 	v2net "github.com/v2ray/v2ray-core/net"
@@ -25,8 +26,10 @@ func (vconn *VFreeConnection) Start(vRay core.OutboundVRay) error {
 	output := vRay.OutboundOutput()
 	conn, err := net.Dial("tcp", vconn.dest.String())
 	if err != nil {
+    log.Print(err)
 		return err
 	}
+  log.Print("Working on tcp:" + vconn.dest.String())
 
 	finish := make(chan bool, 2)
 	go vconn.DumpInput(conn, input, finish)
@@ -51,9 +54,11 @@ func (vconn *VFreeConnection) DumpOutput(conn net.Conn, output chan<- []byte, fi
 		buffer := make([]byte, 128)
 		nBytes, err := conn.Read(buffer)
 		if err == io.EOF {
+      close(output)
 			finish <- true
 			break
 		}
+    log.Print(buffer[:nBytes])
 		output <- buffer[:nBytes]
 	}
 }

+ 13 - 0
net/freedom/freedomfactory.go

@@ -0,0 +1,13 @@
+package freedom
+
+import (
+	"github.com/v2ray/v2ray-core"
+  v2net "github.com/v2ray/v2ray-core/net"
+)
+
+type FreedomFactory struct {
+}
+
+func (factory FreedomFactory) Create(vp *core.VPoint, dest v2net.VAddress) (core.OutboundConnectionHandler, error) {
+	return NewVFreeConnection(vp, dest), nil
+}

+ 32 - 4
net/socks/socks.go

@@ -3,7 +3,9 @@ package socks
 import (
 	"errors"
 	"io"
+  "log"
 	"net"
+  "strconv"
 
 	"github.com/v2ray/v2ray-core"
 	socksio "github.com/v2ray/v2ray-core/io/socks"
@@ -26,8 +28,8 @@ func NewSocksServer(vp *core.VPoint) *SocksServer {
 	return server
 }
 
-func (server *SocksServer) Listen(port uint8) error {
-	listener, err := net.Listen("tcp", ":"+string(port))
+func (server *SocksServer) Listen(port uint16) error {
+	listener, err := net.Listen("tcp", ":"+strconv.Itoa(int(port)))
 	if err != nil {
 		return err
 	}
@@ -40,6 +42,7 @@ func (server *SocksServer) AcceptConnections(listener net.Listener) error {
 	for server.accepting {
 		connection, err := listener.Accept()
 		if err != nil {
+      log.Print(err)
 			return err
 		}
 		go server.HandleConnection(connection)
@@ -52,10 +55,14 @@ func (server *SocksServer) HandleConnection(connection net.Conn) error {
 
 	auth, err := socksio.ReadAuthentication(connection)
 	if err != nil {
+    log.Print(err)
 		return err
 	}
+  log.Print(auth)
 
-	if auth.HasAuthMethod(socksio.AuthNotRequired) {
+	if !auth.HasAuthMethod(socksio.AuthNotRequired) {
+    // TODO send response with FF
+    log.Print(ErrorAuthenticationFailed)
 		return ErrorAuthenticationFailed
 	}
 
@@ -64,15 +71,33 @@ func (server *SocksServer) HandleConnection(connection net.Conn) error {
 
 	request, err := socksio.ReadRequest(connection)
 	if err != nil {
+    log.Print(err)
 		return err
 	}
+  
+  response := socksio.NewSocks5Response()
 
 	if request.Command == socksio.CmdBind || request.Command == socksio.CmdUdpAssociate {
 		response := socksio.NewSocks5Response()
 		response.Error = socksio.ErrorCommandNotSupported
 		socksio.WriteResponse(connection, response)
+    log.Print(ErrorCommandNotSupported)
 		return ErrorCommandNotSupported
 	}
+  
+  response.Error = socksio.ErrorSuccess
+  response.Port = request.Port
+  response.AddrType = request.AddrType
+  switch response.AddrType {
+    case socksio.AddrTypeIPv4:
+    copy(response.IPv4[:], request.IPv4[:])
+    case socksio.AddrTypeIPv6:
+    copy(response.IPv6[:], request.IPv6[:])
+    case socksio.AddrTypeDomain:
+    response.Domain = request.Domain
+  }
+  socksio.WriteResponse(connection, response)
+  
 
 	ray := server.vPoint.NewInboundConnectionAccepted(request.Destination())
 	input := ray.InboundInput()
@@ -90,7 +115,9 @@ func (server *SocksServer) dumpInput(conn net.Conn, input chan<- []byte, finish
 	for {
 		buffer := make([]byte, 256)
 		nBytes, err := conn.Read(buffer)
+    log.Printf("Reading %d bytes, with error %v", nBytes, err)
 		if err == io.EOF {
+      close(input)
 			finish <- true
 			break
 		}
@@ -105,7 +132,8 @@ func (server *SocksServer) dumpOutput(conn net.Conn, output <-chan []byte, finis
 			finish <- true
 			break
 		}
-		conn.Write(buffer)
+		nBytes, _ := conn.Write(buffer)
+    log.Printf("Writing %d bytes", nBytes)
 	}
 }
 

+ 39 - 0
net/socks/socks_test.go

@@ -0,0 +1,39 @@
+package socks
+
+import (
+	"bytes"
+	"testing"
+
+	"github.com/v2ray/v2ray-core"
+	"github.com/v2ray/v2ray-core/testing/mocks"
+	"github.com/v2ray/v2ray-core/testing/unit"
+)
+
+func TestSocksTcpConnect(t *testing.T) {
+	t.Skip("Not ready yet.")
+
+	assert := unit.Assert(t)
+
+	port := 12384
+
+	uuid := "2418d087-648d-4990-86e8-19dca1d006d3"
+	vid, err := core.UUIDToVID(uuid)
+	assert.Error(err).IsNil()
+
+	config := VConfig{
+		port,
+		[]core.VUser{VUser{vid}},
+		"",
+		[]core.VNext{}}
+
+	och := new(FakeOutboundConnectionHandler)
+	och.Data2Send = bytes.NewBuffer(make([]byte, 1024))
+	och.Data2Return = []byte("The data to be returned to socks server.")
+
+	vpoint, err := NewVPoint(&config, SocksServerFactory{}, och)
+	assert.Error(err).IsNil()
+
+	err = vpoint.Start()
+	assert.Error(err).IsNil()
+
+}

+ 2 - 2
net/socks/socksfactory.go

@@ -7,6 +7,6 @@ import (
 type SocksServerFactory struct {
 }
 
-func (factory *SocksServerFactory) Create(vp *core.VPoint) *SocksServer {
-	return NewSocksServer(vp)
+func (factory SocksServerFactory) Create(vp *core.VPoint) (core.InboundConnectionHandler, error) {
+	return NewSocksServer(vp), nil
 }

+ 5 - 1
net/vdest.go

@@ -50,7 +50,11 @@ func (addr VAddress) String() string {
 	var host string
 	switch addr.Type {
 	case AddrTypeIP:
-		host = addr.IP.String()
+    host = addr.IP.String()
+    if len(addr.IP) == net.IPv6len {
+      host = "[" + host + "]"
+    }
+		
 	case AddrTypeDomain:
 		host = addr.Domain
 	default:

+ 37 - 0
release/server/socks/main.go

@@ -0,0 +1,37 @@
+package main
+
+import (
+  "log"
+  
+  "github.com/v2ray/v2ray-core"
+  "github.com/v2ray/v2ray-core/net/freedom"
+  "github.com/v2ray/v2ray-core/net/socks"
+)
+
+func main() {
+  port := uint16(8888)
+  
+  uuid := "2418d087-648d-4990-86e8-19dca1d006d3"
+	vid, err := core.UUIDToVID(uuid)
+  if err != nil {
+    log.Fatal(err)
+  }
+
+	config := core.VConfig{
+		port,
+		[]core.VUser{core.VUser{vid}},
+		"",
+		[]core.VNext{}}
+
+	vpoint, err := core.NewVPoint(&config, socks.SocksServerFactory{}, freedom.FreedomFactory{})
+  if err != nil {
+    log.Fatal(err)
+  }
+  err = vpoint.Start()
+  if err != nil {
+    log.Fatal(err)
+  }
+  
+  finish := make(chan bool)
+  <-finish
+}

+ 33 - 0
testing/mocks/fakeoutboundhandler.go

@@ -0,0 +1,33 @@
+package mocks
+
+import (
+	"bytes"
+
+	"github.com/v2ray/v2ray-core"
+	v2net "github.com/v2ray/v2ray-core/net"
+)
+
+type FakeOutboundConnectionHandler struct {
+	Data2Send   bytes.Buffer
+	Data2Return []byte
+	Destination v2net.VAddress
+}
+
+func (handler *FakeOutboundConnectionHandler) Start(ray core.OutboundVRay) error {
+	input := ray.OutboundInput()
+	output := ray.OutboundOutput()
+
+	output <- handler.Data2Return
+	for {
+		data, open := <-input
+		if !open {
+			break
+		}
+		handler.Data2Send.Write(data)
+	}
+	return nil
+}
+
+func (handler *FakeOutboundConnectionHandler) Create(vPoint *core.VPoint, dest v2net.VAddress) (core.OutboundConnectionHandler, error) {
+	return handler, nil
+}

+ 4 - 16
vpoint.go

@@ -16,7 +16,7 @@ type VPoint struct {
 
 // NewVPoint returns a new VPoint server based on given configuration.
 // The server is not started at this point.
-func NewVPoint(config *VConfig) (*VPoint, error) {
+func NewVPoint(config *VConfig, ichFactory InboundConnectionHandlerFactory, ochFactory OutboundConnectionHandlerFactory) (*VPoint, error) {
 	var vpoint = new(VPoint)
 	vpoint.Config = *config
 	vpoint.UserSet = NewVUserSet()
@@ -24,6 +24,9 @@ func NewVPoint(config *VConfig) (*VPoint, error) {
 	for _, user := range vpoint.Config.AllowedClients {
 		vpoint.UserSet.AddUser(user)
 	}
+  
+  vpoint.ichFactory = ichFactory
+  vpoint.ochFactory = ochFactory
 
 	return vpoint, nil
 }
@@ -59,21 +62,6 @@ func (vp *VPoint) Start() error {
 }
 
 func (vp *VPoint) NewInboundConnectionAccepted(destination v2net.VAddress) InboundVRay {
-	/*
-	  vNextLen := len(vp.Config.VNextList)
-	  if vNextLen > 0 {
-	    vNextIndex := rand.Intn(vNextLen)
-	    vNext := vp.Config.VNextList[vNextIndex]
-	    vNextUser := dest.User
-	    vNextUserLen := len(vNext.Users)
-	    if vNextUserLen > 0 {
-	      vNextUserIndex = rand.Intn(vNextUserLen)
-	      vNextUser = vNext.Users[vNextUserIndex]
-	    }
-	    newDest := VDestination{"tcp", vNext.ServerAddress, vNextUser}
-	    dest = newDest
-	  }*/
-
 	ray := NewVRay()
 	// TODO: handle error
 	och, _ := vp.ochFactory.Create(vp, destination)