Browse Source

Close connection more aggressively.

V2Ray 10 years ago
parent
commit
a78dbe7133
5 changed files with 45 additions and 13 deletions
  1. 0 3
      common/io/encryption.go
  2. 30 0
      common/net/timed_io.go
  3. 6 1
      proxy/socks/socks.go
  4. 8 7
      proxy/vmess/vmessin.go
  5. 1 2
      proxy/vmess/vmessout.go

+ 0 - 3
common/io/encryption.go

@@ -27,9 +27,6 @@ func (reader CryptionReader) Read(blocks []byte) (int, error) {
 	if nBytes > 0 {
 		reader.stream.XORKeyStream(blocks[:nBytes], blocks[:nBytes])
 	}
-	if err != nil && err != io.EOF {
-		log.Error("Error reading blocks: %v", err)
-	}
 	return nBytes, err
 }
 

+ 30 - 0
common/net/timed_io.go

@@ -0,0 +1,30 @@
+package net
+
+import (
+	"net"
+	"time"
+)
+
+var (
+	emptyTime time.Time
+)
+
+type TimeOutReader struct {
+	timeout    int
+	connection net.Conn
+}
+
+func NewTimeOutReader(timeout int, connection net.Conn) *TimeOutReader {
+	return &TimeOutReader{
+		timeout:    timeout,
+		connection: connection,
+	}
+}
+
+func (reader *TimeOutReader) Read(p []byte) (n int, err error) {
+	deadline := time.Duration(reader.timeout) * time.Second
+	reader.connection.SetReadDeadline(time.Now().Add(deadline))
+	n, err = reader.connection.Read(p)
+	reader.connection.SetReadDeadline(emptyTime)
+	return
+}

+ 6 - 1
proxy/socks/socks.go

@@ -7,6 +7,7 @@ import (
 	"net"
 	"strconv"
 	"sync"
+	"time"
 
 	"github.com/v2ray/v2ray-core"
 	"github.com/v2ray/v2ray-core/common/log"
@@ -56,6 +57,10 @@ func (server *SocksServer) AcceptConnections(listener net.Listener) {
 		if err != nil {
 			log.Error("Error on accepting socks connection: %v", err)
 		}
+		if tcpConn, ok := connection.(*net.TCPConn); ok {
+			tcpConn.SetKeepAlive(true)
+			tcpConn.SetKeepAlivePeriod(4 * time.Second)
+		}
 		go server.HandleConnection(connection)
 	}
 }
@@ -63,7 +68,7 @@ func (server *SocksServer) AcceptConnections(listener net.Listener) {
 func (server *SocksServer) HandleConnection(connection net.Conn) error {
 	defer connection.Close()
 
-	reader := connection.(io.Reader)
+	reader := v2net.NewTimeOutReader(4, connection)
 
 	auth, auth4, err := protocol.ReadAuthentication(reader)
 	if err != nil && err != protocol.ErrorSocksVersion4 {

+ 8 - 7
proxy/vmess/vmessin.go

@@ -54,6 +54,10 @@ func (handler *VMessInboundHandler) AcceptConnections(listener net.Listener) err
 		if err != nil {
 			return log.Error("Failed to accpet connection: %s", err.Error())
 		}
+		if tcpConn, ok := connection.(*net.TCPConn); ok {
+			tcpConn.SetKeepAlive(true)
+			tcpConn.SetKeepAlivePeriod(4 * time.Second)
+		}
 		go handler.HandleConnection(connection)
 	}
 	return nil
@@ -62,18 +66,15 @@ func (handler *VMessInboundHandler) AcceptConnections(listener net.Listener) err
 func (handler *VMessInboundHandler) HandleConnection(connection net.Conn) error {
 	defer connection.Close()
 
-	reader := protocol.NewVMessRequestReader(handler.clients)
+	connReader := v2net.NewTimeOutReader(4, connection)
+	requestReader := protocol.NewVMessRequestReader(handler.clients)
 
-	// Timeout 4 seconds to prevent DoS attack
-	connection.SetReadDeadline(time.Now().Add(requestReadTimeOut))
-	request, err := reader.Read(connection)
+	request, err := requestReader.Read(connReader)
 	if err != nil {
 		log.Warning("VMessIn: Invalid request from (%s): %v", connection.RemoteAddr().String(), err)
 		return err
 	}
 	log.Debug("VMessIn: Received request for %s", request.Address.String())
-	// Clear read timeout
-	connection.SetReadDeadline(zeroTime)
 
 	ray := handler.vPoint.DispatchToOutbound(v2net.NewTCPPacket(request.Destination()))
 	input := ray.InboundInput()
@@ -82,7 +83,7 @@ func (handler *VMessInboundHandler) HandleConnection(connection net.Conn) error
 	readFinish.Lock()
 	writeFinish.Lock()
 
-	go handleInput(request, connection, input, &readFinish)
+	go handleInput(request, connReader, input, &readFinish)
 
 	responseKey := md5.Sum(request.RequestKey[:])
 	responseIV := md5.Sum(request.RequestIV[:])

+ 1 - 2
proxy/vmess/vmessout.go

@@ -170,8 +170,7 @@ func handleResponse(conn *net.TCPConn, request *protocol.VMessRequest, output ch
 	response := protocol.VMessResponse{}
 	nBytes, err := decryptResponseReader.Read(response[:])
 	if err != nil {
-		log.Error("VMessOut: Failed to read VMess response (%d bytes): %v", nBytes, err)
-		log.Error(InfoTimeNotSync)
+		//log.Error("VMessOut: Failed to read VMess response (%d bytes): %v", nBytes, err)
 		return
 	}
 	if !bytes.Equal(response[:], request.ResponseHeader[:]) {