github.com/Uhtred009/v2ray-core-1@v4.31.2+incompatible/proxy/shadowsocks/server.go (about)

     1  // +build !confonly
     2  
     3  package shadowsocks
     4  
     5  import (
     6  	"context"
     7  	"time"
     8  
     9  	"v2ray.com/core"
    10  	"v2ray.com/core/common"
    11  	"v2ray.com/core/common/buf"
    12  	"v2ray.com/core/common/log"
    13  	"v2ray.com/core/common/net"
    14  	"v2ray.com/core/common/protocol"
    15  	udp_proto "v2ray.com/core/common/protocol/udp"
    16  	"v2ray.com/core/common/session"
    17  	"v2ray.com/core/common/signal"
    18  	"v2ray.com/core/common/task"
    19  	"v2ray.com/core/features/policy"
    20  	"v2ray.com/core/features/routing"
    21  	"v2ray.com/core/transport/internet"
    22  	"v2ray.com/core/transport/internet/udp"
    23  )
    24  
    25  type Server struct {
    26  	config        *ServerConfig
    27  	user          *protocol.MemoryUser
    28  	policyManager policy.Manager
    29  }
    30  
    31  // NewServer create a new Shadowsocks server.
    32  func NewServer(ctx context.Context, config *ServerConfig) (*Server, error) {
    33  	if config.GetUser() == nil {
    34  		return nil, newError("user is not specified")
    35  	}
    36  
    37  	mUser, err := config.User.ToMemoryUser()
    38  	if err != nil {
    39  		return nil, newError("failed to parse user account").Base(err)
    40  	}
    41  
    42  	v := core.MustFromContext(ctx)
    43  	s := &Server{
    44  		config:        config,
    45  		user:          mUser,
    46  		policyManager: v.GetFeature(policy.ManagerType()).(policy.Manager),
    47  	}
    48  
    49  	return s, nil
    50  }
    51  
    52  func (s *Server) Network() []net.Network {
    53  	list := s.config.Network
    54  	if len(list) == 0 {
    55  		list = append(list, net.Network_TCP)
    56  	}
    57  	if s.config.UdpEnabled {
    58  		list = append(list, net.Network_UDP)
    59  	}
    60  	return list
    61  }
    62  
    63  func (s *Server) Process(ctx context.Context, network net.Network, conn internet.Connection, dispatcher routing.Dispatcher) error {
    64  	switch network {
    65  	case net.Network_TCP:
    66  		return s.handleConnection(ctx, conn, dispatcher)
    67  	case net.Network_UDP:
    68  		return s.handlerUDPPayload(ctx, conn, dispatcher)
    69  	default:
    70  		return newError("unknown network: ", network)
    71  	}
    72  }
    73  
    74  func (s *Server) handlerUDPPayload(ctx context.Context, conn internet.Connection, dispatcher routing.Dispatcher) error {
    75  	udpServer := udp.NewDispatcher(dispatcher, func(ctx context.Context, packet *udp_proto.Packet) {
    76  		request := protocol.RequestHeaderFromContext(ctx)
    77  		if request == nil {
    78  			return
    79  		}
    80  
    81  		payload := packet.Payload
    82  		data, err := EncodeUDPPacket(request, payload.Bytes())
    83  		payload.Release()
    84  		if err != nil {
    85  			newError("failed to encode UDP packet").Base(err).AtWarning().WriteToLog(session.ExportIDToError(ctx))
    86  			return
    87  		}
    88  		defer data.Release()
    89  
    90  		conn.Write(data.Bytes())
    91  	})
    92  
    93  	inbound := session.InboundFromContext(ctx)
    94  	if inbound == nil {
    95  		panic("no inbound metadata")
    96  	}
    97  	inbound.User = s.user
    98  
    99  	reader := buf.NewPacketReader(conn)
   100  	for {
   101  		mpayload, err := reader.ReadMultiBuffer()
   102  		if err != nil {
   103  			break
   104  		}
   105  
   106  		for _, payload := range mpayload {
   107  			request, data, err := DecodeUDPPacket(s.user, payload)
   108  			if err != nil {
   109  				if inbound := session.InboundFromContext(ctx); inbound != nil && inbound.Source.IsValid() {
   110  					newError("dropping invalid UDP packet from: ", inbound.Source).Base(err).WriteToLog(session.ExportIDToError(ctx))
   111  					log.Record(&log.AccessMessage{
   112  						From:   inbound.Source,
   113  						To:     "",
   114  						Status: log.AccessRejected,
   115  						Reason: err,
   116  					})
   117  				}
   118  				payload.Release()
   119  				continue
   120  			}
   121  
   122  			currentPacketCtx := ctx
   123  			dest := request.Destination()
   124  			if inbound.Source.IsValid() {
   125  				currentPacketCtx = log.ContextWithAccessMessage(ctx, &log.AccessMessage{
   126  					From:   inbound.Source,
   127  					To:     dest,
   128  					Status: log.AccessAccepted,
   129  					Reason: "",
   130  					Email:  request.User.Email,
   131  				})
   132  			}
   133  			newError("tunnelling request to ", dest).WriteToLog(session.ExportIDToError(currentPacketCtx))
   134  
   135  			currentPacketCtx = protocol.ContextWithRequestHeader(currentPacketCtx, request)
   136  			udpServer.Dispatch(currentPacketCtx, dest, data)
   137  		}
   138  	}
   139  
   140  	return nil
   141  }
   142  
   143  func (s *Server) handleConnection(ctx context.Context, conn internet.Connection, dispatcher routing.Dispatcher) error {
   144  	sessionPolicy := s.policyManager.ForLevel(s.user.Level)
   145  	conn.SetReadDeadline(time.Now().Add(sessionPolicy.Timeouts.Handshake))
   146  
   147  	bufferedReader := buf.BufferedReader{Reader: buf.NewReader(conn)}
   148  	request, bodyReader, err := ReadTCPSession(s.user, &bufferedReader)
   149  	if err != nil {
   150  		log.Record(&log.AccessMessage{
   151  			From:   conn.RemoteAddr(),
   152  			To:     "",
   153  			Status: log.AccessRejected,
   154  			Reason: err,
   155  		})
   156  		return newError("failed to create request from: ", conn.RemoteAddr()).Base(err)
   157  	}
   158  	conn.SetReadDeadline(time.Time{})
   159  
   160  	inbound := session.InboundFromContext(ctx)
   161  	if inbound == nil {
   162  		panic("no inbound metadata")
   163  	}
   164  	inbound.User = s.user
   165  
   166  	dest := request.Destination()
   167  	ctx = log.ContextWithAccessMessage(ctx, &log.AccessMessage{
   168  		From:   conn.RemoteAddr(),
   169  		To:     dest,
   170  		Status: log.AccessAccepted,
   171  		Reason: "",
   172  		Email:  request.User.Email,
   173  	})
   174  	newError("tunnelling request to ", dest).WriteToLog(session.ExportIDToError(ctx))
   175  
   176  	ctx, cancel := context.WithCancel(ctx)
   177  	timer := signal.CancelAfterInactivity(ctx, cancel, sessionPolicy.Timeouts.ConnectionIdle)
   178  
   179  	ctx = policy.ContextWithBufferPolicy(ctx, sessionPolicy.Buffer)
   180  	link, err := dispatcher.Dispatch(ctx, dest)
   181  	if err != nil {
   182  		return err
   183  	}
   184  
   185  	responseDone := func() error {
   186  		defer timer.SetTimeout(sessionPolicy.Timeouts.UplinkOnly)
   187  
   188  		bufferedWriter := buf.NewBufferedWriter(buf.NewWriter(conn))
   189  		responseWriter, err := WriteTCPResponse(request, bufferedWriter)
   190  		if err != nil {
   191  			return newError("failed to write response").Base(err)
   192  		}
   193  
   194  		{
   195  			payload, err := link.Reader.ReadMultiBuffer()
   196  			if err != nil {
   197  				return err
   198  			}
   199  			if err := responseWriter.WriteMultiBuffer(payload); err != nil {
   200  				return err
   201  			}
   202  		}
   203  
   204  		if err := bufferedWriter.SetBuffered(false); err != nil {
   205  			return err
   206  		}
   207  
   208  		if err := buf.Copy(link.Reader, responseWriter, buf.UpdateActivity(timer)); err != nil {
   209  			return newError("failed to transport all TCP response").Base(err)
   210  		}
   211  
   212  		return nil
   213  	}
   214  
   215  	requestDone := func() error {
   216  		defer timer.SetTimeout(sessionPolicy.Timeouts.DownlinkOnly)
   217  
   218  		if err := buf.Copy(bodyReader, link.Writer, buf.UpdateActivity(timer)); err != nil {
   219  			return newError("failed to transport all TCP request").Base(err)
   220  		}
   221  
   222  		return nil
   223  	}
   224  
   225  	var requestDoneAndCloseWriter = task.OnSuccess(requestDone, task.Close(link.Writer))
   226  	if err := task.Run(ctx, requestDoneAndCloseWriter, responseDone); err != nil {
   227  		common.Interrupt(link.Reader)
   228  		common.Interrupt(link.Writer)
   229  		return newError("connection ends").Base(err)
   230  	}
   231  
   232  	return nil
   233  }
   234  
   235  func init() {
   236  	common.Must(common.RegisterConfig((*ServerConfig)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
   237  		return NewServer(ctx, config.(*ServerConfig))
   238  	}))
   239  }