diff --git a/net/address.go b/net/address.go index a5518c9d..f041c95c 100644 --- a/net/address.go +++ b/net/address.go @@ -18,10 +18,12 @@ type Address struct { } func IPAddress(ip []byte, port uint16) Address { + ipCopy := make([]byte, len(ip)) + copy(ipCopy, ip) // TODO: check IP length return Address{ Type: AddrTypeIP, - IP: net.IP(ip), + IP: net.IP(ipCopy), Domain: "", Port: port, } diff --git a/net/freedom/freedom.go b/net/freedom/freedom.go index f721e6c4..3c9e95d8 100644 --- a/net/freedom/freedom.go +++ b/net/freedom/freedom.go @@ -23,6 +23,7 @@ func (vconn *FreedomConnection) Start(ray core.OutboundRay) error { output := ray.OutboundOutput() conn, err := net.Dial("tcp", vconn.dest.String()) if err != nil { + close(output) return log.Error("Failed to open tcp: %s : %v", vconn.dest.String(), err) } log.Debug("Sending outbound tcp: %s", vconn.dest.String()) diff --git a/net/vmess/vmessin.go b/net/vmess/vmessin.go index 6d543736..6c71ac63 100644 --- a/net/vmess/vmessin.go +++ b/net/vmess/vmessin.go @@ -60,36 +60,34 @@ func (handler *VMessInboundHandler) HandleConnection(connection net.Conn) error } log.Debug("Received request for %s", request.Address.String()) - response := vmessio.NewVMessResponse(request) - nBytes, err := connection.Write(response[:]) - if err != nil { - return log.Error("Failed to write VMess response (%d bytes): %v", nBytes, err) - } + ray := handler.vPoint.NewInboundConnectionAccepted(request.Address) + input := ray.InboundInput() + output := ray.InboundOutput() - requestKey := request.RequestKey[:] - requestIV := request.RequestIV[:] - responseKey := md5.Sum(requestKey) - responseIV := md5.Sum(requestIV) + readFinish := make(chan bool) + writeFinish := make(chan bool) - requestReader, err := v2io.NewAesDecryptReader(requestKey, requestIV, connection) - if err != nil { - return log.Error("Failed to create decrypt reader: %v", err) - } + go handleInput(request, connection, input, readFinish) + + responseKey := md5.Sum(request.RequestKey[:]) + responseIV := md5.Sum(request.RequestIV[:]) + response := vmessio.NewVMessResponse(request) responseWriter, err := v2io.NewAesEncryptWriter(responseKey[:], responseIV[:], connection) if err != nil { return log.Error("Failed to create encrypt writer: %v", err) } - ray := handler.vPoint.NewInboundConnectionAccepted(request.Address) - input := ray.InboundInput() - output := ray.InboundOutput() - - readFinish := make(chan bool) - writeFinish := make(chan bool) + // Optimize for small response packet + buffer := make([]byte, 0, 1024) + buffer = append(buffer, response[:]...) + data, open := <-output + if open { + buffer = append(buffer, data...) + } + responseWriter.Write(buffer) - go handler.dumpInput(requestReader, input, readFinish) - go handler.dumpOutput(responseWriter, output, writeFinish) + go handleOutput(request, responseWriter, output, writeFinish) <-writeFinish if tcpConn, ok := connection.(*net.TCPConn); ok { @@ -101,17 +99,22 @@ func (handler *VMessInboundHandler) HandleConnection(connection net.Conn) error return nil } -func (handler *VMessInboundHandler) dumpInput(reader io.Reader, input chan<- []byte, finish chan<- bool) { - v2net.ReaderToChan(input, reader) - close(input) - log.Debug("VMessIn closing input") - finish <- true +func handleInput(request *vmessio.VMessRequest, reader io.Reader, input chan<- []byte, finish chan<- bool) { + defer close(input) + defer close(finish) + + requestReader, err := v2io.NewAesDecryptReader(request.RequestKey[:], request.RequestIV[:], reader) + if err != nil { + log.Error("Failed to create decrypt reader: %v", err) + return + } + + v2net.ReaderToChan(input, requestReader) } -func (handler *VMessInboundHandler) dumpOutput(writer io.Writer, output <-chan []byte, finish chan<- bool) { +func handleOutput(request *vmessio.VMessRequest, writer io.Writer, output <-chan []byte, finish chan<- bool) { v2net.ChanToWriter(writer, output) - log.Debug("VMessOut closing output") - finish <- true + close(finish) } type VMessInboundHandlerFactory struct { diff --git a/net/vmess/vmessout.go b/net/vmess/vmessout.go index 482953f2..81e96e11 100644 --- a/net/vmess/vmessout.go +++ b/net/vmess/vmessout.go @@ -79,8 +79,10 @@ func startCommunicate(request *vmessio.VMessRequest, dest v2net.Address, ray cor close(output) return err } + + log.Debug("VMessOut: Tunneling request for %s", request.Address.String()) + defer conn.Close() - defer close(output) requestFinish := make(chan bool) responseFinish := make(chan bool) @@ -115,23 +117,24 @@ func handleRequest(conn *net.TCPConn, request *vmessio.VMessRequest, input <-cha func handleResponse(conn *net.TCPConn, request *vmessio.VMessRequest, output chan<- []byte, finish chan<- bool) error { defer close(finish) + defer close(output) responseKey := md5.Sum(request.RequestKey[:]) responseIV := md5.Sum(request.RequestIV[:]) - response := vmessio.VMessResponse{} - nBytes, err := conn.Read(response[:]) + decryptResponseReader, err := v2io.NewAesDecryptReader(responseKey[:], responseIV[:], conn) if err != nil { - log.Error("Failed to read VMess response (%d bytes): %v", nBytes, err) + log.Error("Failed to create decrypt reader: %v", err) return err } - log.Debug("Got response %v", response) - // TODO: check response - decryptResponseReader, err := v2io.NewAesDecryptReader(responseKey[:], responseIV[:], conn) + response := vmessio.VMessResponse{} + nBytes, err := decryptResponseReader.Read(response[:]) if err != nil { - log.Error("Failed to create decrypt reader: %v", err) + log.Error("Failed to read VMess response (%d bytes): %v", nBytes, err) return err } + log.Debug("Got response %v", response) + // TODO: check response v2net.ReaderToChan(output, decryptResponseReader) return nil