| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236 | package socksimport (	"context"	"io"	"time"	"v2ray.com/core"	"v2ray.com/core/common"	"v2ray.com/core/common/buf"	"v2ray.com/core/common/log"	"v2ray.com/core/common/net"	"v2ray.com/core/common/protocol"	"v2ray.com/core/common/session"	"v2ray.com/core/common/signal"	"v2ray.com/core/common/task"	"v2ray.com/core/transport/internet"	"v2ray.com/core/transport/internet/udp"	"v2ray.com/core/transport/pipe")// Server is a SOCKS 5 proxy servertype Server struct {	config *ServerConfig	v      *core.Instance}// NewServer creates a new Server object.func NewServer(ctx context.Context, config *ServerConfig) (*Server, error) {	s := &Server{		config: config,		v:      core.MustFromContext(ctx),	}	return s, nil}func (s *Server) policy() core.Policy {	config := s.config	p := s.v.PolicyManager().ForLevel(config.UserLevel)	if config.Timeout > 0 && config.UserLevel == 0 {		p.Timeouts.ConnectionIdle = time.Duration(config.Timeout) * time.Second	}	return p}// Network implements proxy.Inbound.func (s *Server) Network() net.NetworkList {	list := net.NetworkList{		Network: []net.Network{net.Network_TCP},	}	if s.config.UdpEnabled {		list.Network = append(list.Network, net.Network_UDP)	}	return list}// Process implements proxy.Inbound.func (s *Server) Process(ctx context.Context, network net.Network, conn internet.Connection, dispatcher core.Dispatcher) error {	switch network {	case net.Network_TCP:		return s.processTCP(ctx, conn, dispatcher)	case net.Network_UDP:		return s.handleUDPPayload(ctx, conn, dispatcher)	default:		return newError("unknown network: ", network)	}}func (s *Server) processTCP(ctx context.Context, conn internet.Connection, dispatcher core.Dispatcher) error {	plcy := s.policy()	if err := conn.SetReadDeadline(time.Now().Add(plcy.Timeouts.Handshake)); err != nil {		newError("failed to set deadline").Base(err).WriteToLog(session.ExportIDToError(ctx))	}	inbound := session.InboundFromContext(ctx)	if inbound == nil || !inbound.Gateway.IsValid() {		return newError("inbound gateway not specified")	}	svrSession := &ServerSession{		config: s.config,		port:   inbound.Gateway.Port,	}	reader := &buf.BufferedReader{Reader: buf.NewReader(conn)}	request, err := svrSession.Handshake(reader, conn)	if err != nil {		if inbound != nil && inbound.Source.IsValid() {			log.Record(&log.AccessMessage{				From:   inbound.Source,				To:     "",				Status: log.AccessRejected,				Reason: err,			})		}		return newError("failed to read request").Base(err)	}	if err := conn.SetReadDeadline(time.Time{}); err != nil {		newError("failed to clear deadline").Base(err).WriteToLog(session.ExportIDToError(ctx))	}	if request.Command == protocol.RequestCommandTCP {		dest := request.Destination()		newError("TCP Connect request to ", dest).WriteToLog(session.ExportIDToError(ctx))		if inbound != nil && inbound.Source.IsValid() {			log.Record(&log.AccessMessage{				From:   inbound.Source,				To:     dest,				Status: log.AccessAccepted,				Reason: "",			})		}		return s.transport(ctx, reader, conn, dest, dispatcher)	}	if request.Command == protocol.RequestCommandUDP {		return s.handleUDP(conn)	}	return nil}func (*Server) handleUDP(c io.Reader) error {	// The TCP connection closes after this method returns. We need to wait until	// the client closes it.	return common.Error2(io.Copy(buf.DiscardBytes, c))}func (s *Server) transport(ctx context.Context, reader io.Reader, writer io.Writer, dest net.Destination, dispatcher core.Dispatcher) error {	ctx, cancel := context.WithCancel(ctx)	timer := signal.CancelAfterInactivity(ctx, cancel, s.policy().Timeouts.ConnectionIdle)	plcy := s.policy()	ctx = core.ContextWithBufferPolicy(ctx, plcy.Buffer)	link, err := dispatcher.Dispatch(ctx, dest)	if err != nil {		return err	}	requestDone := func() error {		defer timer.SetTimeout(plcy.Timeouts.DownlinkOnly)		if err := buf.Copy(buf.NewReader(reader), link.Writer, buf.UpdateActivity(timer)); err != nil {			return newError("failed to transport all TCP request").Base(err)		}		return nil	}	responseDone := func() error {		defer timer.SetTimeout(plcy.Timeouts.UplinkOnly)		v2writer := buf.NewWriter(writer)		if err := buf.Copy(link.Reader, v2writer, buf.UpdateActivity(timer)); err != nil {			return newError("failed to transport all TCP response").Base(err)		}		return nil	}	var requestDonePost = task.Single(requestDone, task.OnSuccess(task.Close(link.Writer)))	if err := task.Run(task.WithContext(ctx), task.Parallel(requestDonePost, responseDone))(); err != nil {		pipe.CloseError(link.Reader)		pipe.CloseError(link.Writer)		return newError("connection ends").Base(err)	}	return nil}func (s *Server) handleUDPPayload(ctx context.Context, conn internet.Connection, dispatcher core.Dispatcher) error {	udpServer := udp.NewDispatcher(dispatcher, func(ctx context.Context, payload *buf.Buffer) {		newError("writing back UDP response with ", payload.Len(), " bytes").AtDebug().WriteToLog(session.ExportIDToError(ctx))		request := protocol.RequestHeaderFromContext(ctx)		if request == nil {			return		}		udpMessage, err := EncodeUDPPacket(request, payload.Bytes())		payload.Release()		defer udpMessage.Release()		if err != nil {			newError("failed to write UDP response").AtWarning().Base(err).WriteToLog(session.ExportIDToError(ctx))		}		conn.Write(udpMessage.Bytes()) // nolint: errcheck	})	if inbound := session.InboundFromContext(ctx); inbound != nil && inbound.Source.IsValid() {		newError("client UDP connection from ", inbound.Source).WriteToLog(session.ExportIDToError(ctx))	}	reader := buf.NewReader(conn)	for {		mpayload, err := reader.ReadMultiBuffer()		if err != nil {			return err		}		for _, payload := range mpayload {			request, err := DecodeUDPPacket(payload)			if err != nil {				newError("failed to parse UDP request").Base(err).WriteToLog(session.ExportIDToError(ctx))				payload.Release()				continue			}			if payload.IsEmpty() {				payload.Release()				continue			}			newError("send packet to ", request.Destination(), " with ", payload.Len(), " bytes").AtDebug().WriteToLog(session.ExportIDToError(ctx))			if inbound := session.InboundFromContext(ctx); inbound != nil && inbound.Source.IsValid() {				log.Record(&log.AccessMessage{					From:   inbound.Source,					To:     request.Destination(),					Status: log.AccessAccepted,					Reason: "",				})			}			ctx = protocol.ContextWithRequestHeader(ctx, request)			udpServer.Dispatch(ctx, request.Destination(), payload)		}	}}func init() {	common.Must(common.RegisterConfig((*ServerConfig)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {		return NewServer(ctx, config.(*ServerConfig))	}))}
 |