github.com/xmplusdev/xmcore@v1.8.11-0.20240412132628-5518b55526af/proxy/shadowsocks/protocol.go (about)

     1  package shadowsocks
     2  
     3  import (
     4  	"crypto/hmac"
     5  	"crypto/rand"
     6  	"crypto/sha256"
     7  	"errors"
     8  	"hash/crc32"
     9  	"io"
    10  
    11  	"github.com/xmplusdev/xmcore/common"
    12  	"github.com/xmplusdev/xmcore/common/buf"
    13  	"github.com/xmplusdev/xmcore/common/crypto"
    14  	"github.com/xmplusdev/xmcore/common/drain"
    15  	"github.com/xmplusdev/xmcore/common/net"
    16  	"github.com/xmplusdev/xmcore/common/protocol"
    17  )
    18  
    19  const (
    20  	Version = 1
    21  )
    22  
    23  var addrParser = protocol.NewAddressParser(
    24  	protocol.AddressFamilyByte(0x01, net.AddressFamilyIPv4),
    25  	protocol.AddressFamilyByte(0x04, net.AddressFamilyIPv6),
    26  	protocol.AddressFamilyByte(0x03, net.AddressFamilyDomain),
    27  	protocol.WithAddressTypeParser(func(b byte) byte {
    28  		return b & 0x0F
    29  	}),
    30  )
    31  
    32  type FullReader struct {
    33  	reader io.Reader
    34  	buffer []byte
    35  }
    36  
    37  func (r *FullReader) Read(p []byte) (n int, err error) {
    38  	if r.buffer != nil {
    39  		n := copy(p, r.buffer)
    40  		if n == len(r.buffer) {
    41  			r.buffer = nil
    42  		} else {
    43  			r.buffer = r.buffer[n:]
    44  		}
    45  		if n == len(p) {
    46  			return n, nil
    47  		} else {
    48  			m, err := r.reader.Read(p[n:])
    49  			return n + m, err
    50  		}
    51  	}
    52  	return r.reader.Read(p)
    53  }
    54  
    55  // ReadTCPSession reads a Shadowsocks TCP session from the given reader, returns its header and remaining parts.
    56  func ReadTCPSession(validator *Validator, reader io.Reader) (*protocol.RequestHeader, buf.Reader, error) {
    57  	behaviorSeed := validator.GetBehaviorSeed()
    58  	drainer, errDrain := drain.NewBehaviorSeedLimitedDrainer(int64(behaviorSeed), 16+38, 3266, 64)
    59  
    60  	if errDrain != nil {
    61  		return nil, nil, newError("failed to initialize drainer").Base(errDrain)
    62  	}
    63  
    64  	var r buf.Reader
    65  	buffer := buf.New()
    66  	defer buffer.Release()
    67  
    68  	if _, err := buffer.ReadFullFrom(reader, 50); err != nil {
    69  		drainer.AcknowledgeReceive(int(buffer.Len()))
    70  		return nil, nil, drain.WithError(drainer, reader, newError("failed to read 50 bytes").Base(err))
    71  	}
    72  
    73  	bs := buffer.Bytes()
    74  	user, aead, _, ivLen, err := validator.Get(bs, protocol.RequestCommandTCP)
    75  
    76  	switch err {
    77  	case ErrNotFound:
    78  		drainer.AcknowledgeReceive(int(buffer.Len()))
    79  		return nil, nil, drain.WithError(drainer, reader, newError("failed to match an user").Base(err))
    80  	case ErrIVNotUnique:
    81  		drainer.AcknowledgeReceive(int(buffer.Len()))
    82  		return nil, nil, drain.WithError(drainer, reader, newError("failed iv check").Base(err))
    83  	default:
    84  		reader = &FullReader{reader, bs[ivLen:]}
    85  		drainer.AcknowledgeReceive(int(ivLen))
    86  
    87  		if aead != nil {
    88  			auth := &crypto.AEADAuthenticator{
    89  				AEAD:           aead,
    90  				NonceGenerator: crypto.GenerateAEADNonceWithSize(aead.NonceSize()),
    91  			}
    92  			r = crypto.NewAuthenticationReader(auth, &crypto.AEADChunkSizeParser{
    93  				Auth: auth,
    94  			}, reader, protocol.TransferTypeStream, nil)
    95  		} else {
    96  			account := user.Account.(*MemoryAccount)
    97  			iv := append([]byte(nil), buffer.BytesTo(ivLen)...)
    98  			r, err = account.Cipher.NewDecryptionReader(account.Key, iv, reader)
    99  			if err != nil {
   100  				return nil, nil, drain.WithError(drainer, reader, newError("failed to initialize decoding stream").Base(err).AtError())
   101  			}
   102  		}
   103  	}
   104  
   105  	br := &buf.BufferedReader{Reader: r}
   106  
   107  	request := &protocol.RequestHeader{
   108  		Version: Version,
   109  		User:    user,
   110  		Command: protocol.RequestCommandTCP,
   111  	}
   112  
   113  	buffer.Clear()
   114  
   115  	addr, port, err := addrParser.ReadAddressPort(buffer, br)
   116  	if err != nil {
   117  		drainer.AcknowledgeReceive(int(buffer.Len()))
   118  		return nil, nil, drain.WithError(drainer, reader, newError("failed to read address").Base(err))
   119  	}
   120  
   121  	request.Address = addr
   122  	request.Port = port
   123  
   124  	if request.Address == nil {
   125  		drainer.AcknowledgeReceive(int(buffer.Len()))
   126  		return nil, nil, drain.WithError(drainer, reader, newError("invalid remote address."))
   127  	}
   128  
   129  	return request, br, nil
   130  }
   131  
   132  // WriteTCPRequest writes Shadowsocks request into the given writer, and returns a writer for body.
   133  func WriteTCPRequest(request *protocol.RequestHeader, writer io.Writer) (buf.Writer, error) {
   134  	user := request.User
   135  	account := user.Account.(*MemoryAccount)
   136  
   137  	var iv []byte
   138  	if account.Cipher.IVSize() > 0 {
   139  		iv = make([]byte, account.Cipher.IVSize())
   140  		common.Must2(rand.Read(iv))
   141  		if ivError := account.CheckIV(iv); ivError != nil {
   142  			return nil, newError("failed to mark outgoing iv").Base(ivError)
   143  		}
   144  		if err := buf.WriteAllBytes(writer, iv, nil); err != nil {
   145  			return nil, newError("failed to write IV")
   146  		}
   147  	}
   148  
   149  	w, err := account.Cipher.NewEncryptionWriter(account.Key, iv, writer)
   150  	if err != nil {
   151  		return nil, newError("failed to create encoding stream").Base(err).AtError()
   152  	}
   153  
   154  	header := buf.New()
   155  
   156  	if err := addrParser.WriteAddressPort(header, request.Address, request.Port); err != nil {
   157  		return nil, newError("failed to write address").Base(err)
   158  	}
   159  
   160  	if err := w.WriteMultiBuffer(buf.MultiBuffer{header}); err != nil {
   161  		return nil, newError("failed to write header").Base(err)
   162  	}
   163  
   164  	return w, nil
   165  }
   166  
   167  func ReadTCPResponse(user *protocol.MemoryUser, reader io.Reader) (buf.Reader, error) {
   168  	account := user.Account.(*MemoryAccount)
   169  
   170  	hashkdf := hmac.New(sha256.New, []byte("SSBSKDF"))
   171  	hashkdf.Write(account.Key)
   172  
   173  	behaviorSeed := crc32.ChecksumIEEE(hashkdf.Sum(nil))
   174  
   175  	drainer, err := drain.NewBehaviorSeedLimitedDrainer(int64(behaviorSeed), 16+38, 3266, 64)
   176  	if err != nil {
   177  		return nil, newError("failed to initialize drainer").Base(err)
   178  	}
   179  
   180  	var iv []byte
   181  	if account.Cipher.IVSize() > 0 {
   182  		iv = make([]byte, account.Cipher.IVSize())
   183  		if n, err := io.ReadFull(reader, iv); err != nil {
   184  			return nil, newError("failed to read IV").Base(err)
   185  		} else { // nolint: golint
   186  			drainer.AcknowledgeReceive(n)
   187  		}
   188  	}
   189  
   190  	if ivError := account.CheckIV(iv); ivError != nil {
   191  		return nil, drain.WithError(drainer, reader, newError("failed iv check").Base(ivError))
   192  	}
   193  
   194  	return account.Cipher.NewDecryptionReader(account.Key, iv, reader)
   195  }
   196  
   197  func WriteTCPResponse(request *protocol.RequestHeader, writer io.Writer) (buf.Writer, error) {
   198  	user := request.User
   199  	account := user.Account.(*MemoryAccount)
   200  
   201  	var iv []byte
   202  	if account.Cipher.IVSize() > 0 {
   203  		iv = make([]byte, account.Cipher.IVSize())
   204  		common.Must2(rand.Read(iv))
   205  		if ivError := account.CheckIV(iv); ivError != nil {
   206  			return nil, newError("failed to mark outgoing iv").Base(ivError)
   207  		}
   208  		if err := buf.WriteAllBytes(writer, iv, nil); err != nil {
   209  			return nil, newError("failed to write IV.").Base(err)
   210  		}
   211  	}
   212  
   213  	return account.Cipher.NewEncryptionWriter(account.Key, iv, writer)
   214  }
   215  
   216  func EncodeUDPPacket(request *protocol.RequestHeader, payload []byte) (*buf.Buffer, error) {
   217  	user := request.User
   218  	account := user.Account.(*MemoryAccount)
   219  
   220  	buffer := buf.New()
   221  	ivLen := account.Cipher.IVSize()
   222  	if ivLen > 0 {
   223  		common.Must2(buffer.ReadFullFrom(rand.Reader, ivLen))
   224  	}
   225  
   226  	if err := addrParser.WriteAddressPort(buffer, request.Address, request.Port); err != nil {
   227  		return nil, newError("failed to write address").Base(err)
   228  	}
   229  
   230  	buffer.Write(payload)
   231  
   232  	if err := account.Cipher.EncodePacket(account.Key, buffer); err != nil {
   233  		return nil, newError("failed to encrypt UDP payload").Base(err)
   234  	}
   235  
   236  	return buffer, nil
   237  }
   238  
   239  func DecodeUDPPacket(validator *Validator, payload *buf.Buffer) (*protocol.RequestHeader, *buf.Buffer, error) {
   240  	rawPayload := payload.Bytes()
   241  	user, _, d, _, err := validator.Get(rawPayload, protocol.RequestCommandUDP)
   242  
   243  	if errors.Is(err, ErrIVNotUnique) {
   244  		return nil, nil, newError("failed iv check").Base(err)
   245  	}
   246  
   247  	if errors.Is(err, ErrNotFound) {
   248  		return nil, nil, newError("failed to match an user").Base(err)
   249  	}
   250  
   251  	if err != nil {
   252  		return nil, nil, newError("unexpected error").Base(err)
   253  	}
   254  
   255  	account, ok := user.Account.(*MemoryAccount)
   256  	if !ok {
   257  		return nil, nil, newError("expected MemoryAccount returned from validator")
   258  	}
   259  
   260  	if account.Cipher.IsAEAD() {
   261  		payload.Clear()
   262  		payload.Write(d)
   263  	} else {
   264  		if account.Cipher.IVSize() > 0 {
   265  			iv := make([]byte, account.Cipher.IVSize())
   266  			copy(iv, payload.BytesTo(account.Cipher.IVSize()))
   267  		}
   268  		if err = account.Cipher.DecodePacket(account.Key, payload); err != nil {
   269  			return nil, nil, newError("failed to decrypt UDP payload").Base(err)
   270  		}
   271  	}
   272  
   273  	payload.SetByte(0, payload.Byte(0)&0x0F)
   274  
   275  	addr, port, err := addrParser.ReadAddressPort(nil, payload)
   276  	if err != nil {
   277  		return nil, nil, newError("failed to parse address").Base(err)
   278  	}
   279  
   280  	request := &protocol.RequestHeader{
   281  		Version: Version,
   282  		User:    user,
   283  		Command: protocol.RequestCommandUDP,
   284  		Address: addr,
   285  		Port:    port,
   286  	}
   287  
   288  	return request, payload, nil
   289  }
   290  
   291  type UDPReader struct {
   292  	Reader io.Reader
   293  	User   *protocol.MemoryUser
   294  }
   295  
   296  func (v *UDPReader) ReadMultiBuffer() (buf.MultiBuffer, error) {
   297  	buffer := buf.New()
   298  	_, err := buffer.ReadFrom(v.Reader)
   299  	if err != nil {
   300  		buffer.Release()
   301  		return nil, err
   302  	}
   303  	validator := new(Validator)
   304  	validator.Add(v.User)
   305  
   306  	u, payload, err := DecodeUDPPacket(validator, buffer)
   307  	if err != nil {
   308  		buffer.Release()
   309  		return nil, err
   310  	}
   311  	dest := u.Destination()
   312  	payload.UDP = &dest
   313  	return buf.MultiBuffer{payload}, nil
   314  }
   315  
   316  type UDPWriter struct {
   317  	Writer  io.Writer
   318  	Request *protocol.RequestHeader
   319  }
   320  
   321  func (w *UDPWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
   322  	for {
   323  		mb2, b := buf.SplitFirst(mb)
   324  		mb = mb2
   325  		if b == nil {
   326  			break
   327  		}
   328  		request := w.Request
   329  		if b.UDP != nil {
   330  			request = &protocol.RequestHeader{
   331  				User:    w.Request.User,
   332  				Address: b.UDP.Address,
   333  				Port:    b.UDP.Port,
   334  			}
   335  		}
   336  		packet, err := EncodeUDPPacket(request, b.Bytes())
   337  		b.Release()
   338  		if err != nil {
   339  			buf.ReleaseMulti(mb)
   340  			return err
   341  		}
   342  		_, err = w.Writer.Write(packet.Bytes())
   343  		packet.Release()
   344  		if err != nil {
   345  			buf.ReleaseMulti(mb)
   346  			return err
   347  		}
   348  	}
   349  	return nil
   350  }