github.com/v2fly/v2ray-core/v4@v4.45.2/proxy/shadowsocks/server.go (about)

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