예제 #1
0
func (handler *OutboundConnectionHandler) Dispatch(packet v2net.Packet, ray core.OutboundRay) error {
	input := ray.OutboundInput()
	output := ray.OutboundOutput()

	handler.Destination = packet.Destination()
	if packet.Chunk() != nil {
		handler.Data2Send.Write(packet.Chunk().Value)
	}

	go func() {
		for {
			data, open := <-input
			if !open {
				break
			}
			handler.Data2Send.Write(data.Value)
			data.Release()
		}
		response := alloc.NewBuffer()
		response.Clear()
		response.Append(handler.Data2Return)
		output <- response
		close(output)
	}()

	return nil
}
예제 #2
0
func (handler *OutboundConnectionHandler) Dispatch(packet v2net.Packet, ray core.OutboundRay) error {
	input := ray.OutboundInput()
	output := ray.OutboundOutput()

	handler.Destination = packet.Destination()
	if packet.Chunk() != nil {
		handler.Data2Send.Write(packet.Chunk())
	}

	go func() {
		for {
			data, open := <-input
			if !open {
				break
			}
			handler.Data2Send.Write(data)
		}
		dataCopy := make([]byte, len(handler.Data2Return))
		copy(dataCopy, handler.Data2Return)
		output <- dataCopy
		close(output)
	}()

	return nil
}
예제 #3
0
func (this *VMessOutboundHandler) Dispatch(firstPacket v2net.Packet, ray ray.OutboundRay) error {
	vNextAddress, vNextUser := this.receiverManager.PickReceiver()

	command := protocol.CmdTCP
	if firstPacket.Destination().IsUDP() {
		command = protocol.CmdUDP
	}
	request := &protocol.VMessRequest{
		Version: protocol.Version,
		User:    vNextUser,
		Command: command,
		Address: firstPacket.Destination().Address(),
		Port:    firstPacket.Destination().Port(),
	}
	if command == protocol.CmdUDP {
		request.Option |= protocol.OptionChunk
	}

	buffer := alloc.NewSmallBuffer()
	defer buffer.Release()                      // Buffer is released after communication finishes.
	io.ReadFull(rand.Reader, buffer.Value[:33]) // 16 + 16 + 1
	request.RequestIV = buffer.Value[:16]
	request.RequestKey = buffer.Value[16:32]
	request.ResponseHeader = buffer.Value[32]

	return this.startCommunicate(request, vNextAddress, ray, firstPacket)
}
예제 #4
0
func (this *OutboundConnectionHandler) Dispatch(packet v2net.Packet, ray ray.OutboundRay) error {
	input := ray.OutboundInput()
	output := ray.OutboundOutput()

	this.Destination = packet.Destination()
	if packet.Chunk() != nil {
		this.ConnOutput.Write(packet.Chunk().Value)
		packet.Chunk().Release()
	}

	if packet.MoreChunks() {
		writeFinish := &sync.Mutex{}

		writeFinish.Lock()

		go func() {
			v2io.ChanToRawWriter(this.ConnOutput, input)
			writeFinish.Unlock()
		}()

		writeFinish.Lock()
	}

	v2io.RawReaderToChan(output, this.ConnInput)
	close(output)

	return nil
}
예제 #5
0
func (this *FreedomConnection) Dispatch(firstPacket v2net.Packet, ray ray.OutboundRay) error {
	conn, err := net.Dial(firstPacket.Destination().Network(), firstPacket.Destination().Address().String())
	log.Info("Freedom: Opening connection to %s", firstPacket.Destination().String())
	if err != nil {
		close(ray.OutboundOutput())
		log.Error("Freedom: Failed to open connection: %s : %v", firstPacket.Destination().String(), err)
		return err
	}

	input := ray.OutboundInput()
	output := ray.OutboundOutput()
	var readMutex, writeMutex sync.Mutex
	readMutex.Lock()
	writeMutex.Lock()

	if chunk := firstPacket.Chunk(); chunk != nil {
		conn.Write(chunk.Value)
		chunk.Release()
	}

	if !firstPacket.MoreChunks() {
		writeMutex.Unlock()
	} else {
		go func() {
			v2net.ChanToWriter(conn, input)
			writeMutex.Unlock()
		}()
	}

	go func() {
		defer readMutex.Unlock()
		defer close(output)

		response, err := v2net.ReadFrom(conn, nil)
		log.Info("Freedom receives %d bytes from %s", response.Len(), conn.RemoteAddr().String())
		if response.Len() > 0 {
			output <- response
		} else {
			response.Release()
		}
		if err != nil {
			return
		}
		if firstPacket.Destination().IsUDP() {
			return
		}

		v2net.ReaderToChan(output, conn)
	}()

	writeMutex.Lock()
	if tcpConn, ok := conn.(*net.TCPConn); ok {
		tcpConn.CloseWrite()
	}
	readMutex.Lock()
	conn.Close()

	return nil
}
예제 #6
0
func (handler *OutboundConnectionHandler) Create(point *core.Point, packet v2net.Packet) (core.OutboundConnectionHandler, error) {
	handler.Destination = packet.Destination()
	if packet.Chunk() != nil {
		handler.Data2Send.Write(packet.Chunk())
	}

	return handler, nil
}
예제 #7
0
func (this *FreedomConnection) Dispatch(firstPacket v2net.Packet, ray ray.OutboundRay) error {
	log.Info("Freedom: Opening connection to ", firstPacket.Destination())

	var conn net.Conn
	err := retry.Timed(5, 100).On(func() error {
		rawConn, err := dialer.Dial(firstPacket.Destination())
		if err != nil {
			return err
		}
		conn = rawConn
		return nil
	})
	if err != nil {
		close(ray.OutboundOutput())
		log.Error("Freedom: Failed to open connection to ", firstPacket.Destination(), ": ", err)
		return err
	}
	defer conn.Close()

	input := ray.OutboundInput()
	output := ray.OutboundOutput()
	var readMutex, writeMutex sync.Mutex
	readMutex.Lock()
	writeMutex.Lock()

	if chunk := firstPacket.Chunk(); chunk != nil {
		conn.Write(chunk.Value)
		chunk.Release()
	}

	if !firstPacket.MoreChunks() {
		writeMutex.Unlock()
	} else {
		go func() {
			v2io.ChanToRawWriter(conn, input)
			writeMutex.Unlock()
		}()
	}

	go func() {
		defer readMutex.Unlock()
		defer close(output)

		var reader io.Reader = conn

		if firstPacket.Destination().IsUDP() {
			reader = v2net.NewTimeOutReader(16 /* seconds */, conn)
		}

		v2io.RawReaderToChan(output, reader)
	}()

	writeMutex.Lock()
	if tcpConn, ok := conn.(*net.TCPConn); ok {
		tcpConn.CloseWrite()
	}
	readMutex.Lock()

	return nil
}
예제 #8
0
func (this *UDPServer) Dispatch(source v2net.Destination, packet v2net.Packet, callback UDPResponseCallback) {
	destString := source.String() + "-" + packet.Destination().String()
	if this.locateExistingAndDispatch(destString, packet) {
		return
	}

	this.Lock()
	inboundRay := this.packetDispatcher.DispatchToOutbound(v2net.NewPacket(packet.Destination(), packet.Chunk(), true))
	this.conns[destString] = &connEntry{
		inboundRay: inboundRay,
		callback:   callback,
	}
	this.Unlock()
	go this.handleConnection(destString, inboundRay, source, callback)
}
예제 #9
0
// Dispatches a Packet to an OutboundConnection.
// The packet will be passed through the router (if configured), and then sent to an outbound
// connection with matching tag.
func (this *Point) DispatchToOutbound(context app.Context, packet v2net.Packet) ray.InboundRay {
	direct := ray.NewRay()
	dest := packet.Destination()

	dispatcher := this.och

	if this.router != nil {
		if tag, err := this.router.TakeDetour(dest); err == nil {
			if handler, found := this.odh[tag]; found {
				dispatcher = handler
			}
		}
	}

	go this.FilterPacketAndDispatch(packet, direct, dispatcher)
	return direct
}
예제 #10
0
func (this *Point) DispatchToOutbound(packet v2net.Packet) ray.InboundRay {
	direct := ray.NewRay()
	dest := packet.Destination()

	if this.router != nil {
		tag, err := this.router.TakeDetour(dest)
		if err == nil {
			handler, found := this.odh[tag]
			if found {
				go handler.Dispatch(packet, direct)
				return direct
			}
		}
	}

	go this.och.Dispatch(packet, direct)
	return direct
}
예제 #11
0
func (this *VMessOutboundHandler) Dispatch(firstPacket v2net.Packet, ray ray.OutboundRay) error {
	vNextAddress, vNextUser := this.receiverManager.PickReceiver()

	command := proto.RequestCommandTCP
	if firstPacket.Destination().IsUDP() {
		command = proto.RequestCommandUDP
	}
	request := &proto.RequestHeader{
		Version: raw.Version,
		User:    vNextUser,
		Command: command,
		Address: firstPacket.Destination().Address(),
		Port:    firstPacket.Destination().Port(),
	}
	if command == proto.RequestCommandUDP {
		request.Option |= proto.RequestOptionChunkStream
	}

	return this.startCommunicate(request, vNextAddress, ray, firstPacket)
}
예제 #12
0
// Dispatches a Packet to an OutboundConnection.
// The packet will be passed through the router (if configured), and then sent to an outbound
// connection with matching tag.
func (this *Point) DispatchToOutbound(context app.Context, packet v2net.Packet) ray.InboundRay {
	direct := ray.NewRay()
	dest := packet.Destination()

	dispatcher := this.och

	if this.router != nil {
		if tag, err := this.router.TakeDetour(dest); err == nil {
			if handler, found := this.odh[tag]; found {
				log.Info("Point: Taking detour [", tag, "] for [", dest, "]", tag, dest)
				dispatcher = handler
			} else {
				log.Warning("Point: Unable to find routing destination: ", tag)
			}
		}
	}

	go this.FilterPacketAndDispatch(packet, direct, dispatcher)
	return direct
}
예제 #13
0
func (this *Point) FilterPacketAndDispatch(packet v2net.Packet, link ray.OutboundRay, dispatcher proxy.OutboundConnectionHandler) {
	// Filter empty packets
	chunk := packet.Chunk()
	moreChunks := packet.MoreChunks()
	changed := false
	for chunk == nil && moreChunks {
		changed = true
		chunk, moreChunks = <-link.OutboundInput()
	}
	if chunk == nil && !moreChunks {
		close(link.OutboundOutput())
		return
	}

	if changed {
		packet = v2net.NewPacket(packet.Destination(), chunk, moreChunks)
	}

	dispatcher.Dispatch(packet, link)
}
예제 #14
0
func (handler *VMessOutboundHandler) Dispatch(firstPacket v2net.Packet, ray core.OutboundRay) error {
	vNextList := handler.vNextList
	if firstPacket.Destination().IsUDP() {
		vNextList = handler.vNextListUDP
	}
	vNextAddress, vNextUser := pickVNext(vNextList)

	command := protocol.CmdTCP
	if firstPacket.Destination().IsUDP() {
		command = protocol.CmdUDP
	}
	request := &protocol.VMessRequest{
		Version: protocol.Version,
		UserId:  vNextUser.Id,
		Command: command,
		Address: firstPacket.Destination().Address(),
	}

	buffer := make([]byte, 36) // 16 + 16 + 4
	rand.Read(buffer)
	request.RequestIV = buffer[:16]
	request.RequestKey = buffer[16:32]
	request.ResponseHeader = buffer[32:]

	go startCommunicate(request, vNextAddress, ray, firstPacket)
	return nil
}
예제 #15
0
func (vconn *FreedomConnection) Dispatch(firstPacket v2net.Packet, ray core.OutboundRay) error {
	conn, err := net.Dial(firstPacket.Destination().Network(), firstPacket.Destination().Address().String())
	log.Info("Freedom: Opening connection to %s", firstPacket.Destination().String())
	if err != nil {
		if ray != nil {
			close(ray.OutboundOutput())
		}
		return log.Error("Freedom: Failed to open connection: %s : %v", firstPacket.Destination().String(), err)
	}

	input := ray.OutboundInput()
	output := ray.OutboundOutput()
	var readMutex, writeMutex sync.Mutex
	readMutex.Lock()
	writeMutex.Lock()

	if chunk := firstPacket.Chunk(); chunk != nil {
		conn.Write(chunk.Value)
		chunk.Release()
	}

	if !firstPacket.MoreChunks() {
		writeMutex.Unlock()
	} else {
		go dumpInput(conn, input, &writeMutex)
	}

	go dumpOutput(conn, output, &readMutex, firstPacket.Destination().IsUDP())

	go func() {
		writeMutex.Lock()
		if tcpConn, ok := conn.(*net.TCPConn); ok {
			tcpConn.CloseWrite()
		}
		readMutex.Lock()
		conn.Close()
	}()

	return nil
}
예제 #16
0
func (handler *VMessOutboundHandler) Dispatch(firstPacket v2net.Packet, ray ray.OutboundRay) error {
	vNextList := handler.vNextList
	if firstPacket.Destination().IsUDP() {
		vNextList = handler.vNextListUDP
	}
	vNextAddress, vNextUser := pickVNext(vNextList)

	command := protocol.CmdTCP
	if firstPacket.Destination().IsUDP() {
		command = protocol.CmdUDP
	}
	request := &protocol.VMessRequest{
		Version: protocol.Version,
		User:    vNextUser,
		Command: command,
		Address: firstPacket.Destination().Address(),
	}

	buffer := alloc.NewSmallBuffer()
	defer buffer.Release()
	v2net.ReadAllBytes(rand.Reader, buffer.Value[:36]) // 16 + 16 + 4
	request.RequestIV = buffer.Value[:16]
	request.RequestKey = buffer.Value[16:32]
	request.ResponseHeader = buffer.Value[32:36]

	return startCommunicate(request, vNextAddress, ray, firstPacket)
}
예제 #17
0
func (handler *OutboundConnectionHandler) Create(point *core.Point, config []byte, packet v2net.Packet) (core.OutboundConnectionHandler, error) {
	handler.Destination = packet.Destination()
	return handler, nil
}
예제 #18
0
func (this *FreedomConnection) Dispatch(firstPacket v2net.Packet, ray ray.OutboundRay) error {
	log.Info("Freedom: Opening connection to ", firstPacket.Destination())

	var conn net.Conn
	err := retry.Timed(5, 100).On(func() error {
		rawConn, err := dialer.Dial(firstPacket.Destination())
		if err != nil {
			return err
		}
		conn = rawConn
		return nil
	})
	if err != nil {
		close(ray.OutboundOutput())
		log.Error("Freedom: Failed to open connection to ", firstPacket.Destination(), ": ", err)
		return err
	}
	defer conn.Close()

	input := ray.OutboundInput()
	output := ray.OutboundOutput()
	var readMutex, writeMutex sync.Mutex
	readMutex.Lock()
	writeMutex.Lock()

	if chunk := firstPacket.Chunk(); chunk != nil {
		conn.Write(chunk.Value)
		chunk.Release()
	}

	if !firstPacket.MoreChunks() {
		writeMutex.Unlock()
	} else {
		go func() {
			v2net.ChanToWriter(conn, input)
			writeMutex.Unlock()
		}()
	}

	go func() {
		defer readMutex.Unlock()
		defer close(output)

		response, err := v2net.ReadFrom(conn, nil)
		log.Info("Freedom receives ", response.Len(), " bytes from ", conn.RemoteAddr())
		if response.Len() > 0 {
			output <- response
		} else {
			response.Release()
		}
		if err != nil {
			return
		}
		if firstPacket.Destination().IsUDP() {
			return
		}

		v2net.ReaderToChan(output, conn)
	}()

	if this.space.HasDnsCache() {
		if firstPacket.Destination().Address().IsDomain() {
			domain := firstPacket.Destination().Address().Domain()
			addr := conn.RemoteAddr()
			switch typedAddr := addr.(type) {
			case *net.TCPAddr:
				this.space.DnsCache().Add(domain, typedAddr.IP)
			case *net.UDPAddr:
				this.space.DnsCache().Add(domain, typedAddr.IP)
			}
		}
	}

	writeMutex.Lock()
	if tcpConn, ok := conn.(*net.TCPConn); ok {
		tcpConn.CloseWrite()
	}
	readMutex.Lock()

	return nil
}