github.com/Asutorufa/yuhaiin@v0.3.6-0.20240502055049-7984da7023a0/pkg/net/proxy/shadowsocksr/client.go (about)

     1  package shadowsocksr
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"net"
     7  
     8  	"github.com/Asutorufa/yuhaiin/pkg/net/netapi"
     9  	"github.com/Asutorufa/yuhaiin/pkg/net/proxy/shadowsocksr/cipher"
    10  	"github.com/Asutorufa/yuhaiin/pkg/net/proxy/shadowsocksr/obfs"
    11  	"github.com/Asutorufa/yuhaiin/pkg/net/proxy/shadowsocksr/protocol"
    12  	"github.com/Asutorufa/yuhaiin/pkg/net/proxy/socks5/tools"
    13  	"github.com/Asutorufa/yuhaiin/pkg/net/proxy/yuubinsya"
    14  	"github.com/Asutorufa/yuhaiin/pkg/protos/node/point"
    15  	protocols "github.com/Asutorufa/yuhaiin/pkg/protos/node/protocol"
    16  )
    17  
    18  var _ netapi.Proxy = (*Shadowsocksr)(nil)
    19  
    20  type Shadowsocksr struct {
    21  	netapi.EmptyDispatch
    22  
    23  	protocol *protocol.Protocol
    24  	obfs     *obfs.Obfs
    25  	cipher   *cipher.Cipher
    26  	dial     netapi.Proxy
    27  }
    28  
    29  func init() {
    30  	point.RegisterProtocol(NewClient)
    31  }
    32  
    33  func NewClient(config *protocols.Protocol_Shadowsocksr) point.WrapProxy {
    34  	c := config.Shadowsocksr
    35  	return func(p netapi.Proxy) (netapi.Proxy, error) {
    36  		cipher, err := cipher.NewCipher(c.Method, c.Password)
    37  		if err != nil {
    38  			return nil, fmt.Errorf("new cipher failed: %w", err)
    39  		}
    40  
    41  		obfs := &obfs.Obfs{
    42  			Name:   c.Obfs,
    43  			Host:   c.Server,
    44  			Port:   c.Port,
    45  			Param:  c.Obfsparam,
    46  			Cipher: cipher,
    47  		}
    48  
    49  		protocol := &protocol.Protocol{
    50  			Name:         c.Protocol,
    51  			Auth:         protocol.NewAuth(),
    52  			Param:        c.Protoparam,
    53  			TcpMss:       1460,
    54  			Cipher:       cipher,
    55  			ObfsOverhead: obfs.Overhead(),
    56  		}
    57  
    58  		return &Shadowsocksr{protocol: protocol, obfs: obfs, cipher: cipher, dial: p}, nil
    59  	}
    60  }
    61  
    62  func (s *Shadowsocksr) Conn(ctx context.Context, addr netapi.Address) (net.Conn, error) {
    63  	c, err := s.dial.Conn(ctx, addr)
    64  	if err != nil {
    65  		return nil, fmt.Errorf("get conn failed: %w", err)
    66  	}
    67  	// obfsServerInfo.SetHeadLen(b, 30)
    68  	// protocolServerInfo.SetHeadLen(b, 30)
    69  	obfs, err := s.obfs.Stream(c)
    70  	if err != nil {
    71  		c.Close()
    72  		return nil, fmt.Errorf("obfs stream failed: %w", err)
    73  	}
    74  	cipher := s.cipher.StreamConn(obfs)
    75  
    76  	var iv []byte
    77  	if z, ok := cipher.(interface{ WriteIV() ([]byte, error) }); ok {
    78  		iv, err = z.WriteIV()
    79  		if err != nil {
    80  			c.Close()
    81  			return nil, fmt.Errorf("get write iv failed: %w", err)
    82  		}
    83  	}
    84  
    85  	conn, err := s.protocol.Stream(cipher, iv)
    86  	if err != nil {
    87  		c.Close()
    88  		return nil, fmt.Errorf("protocol stream failed: %w", err)
    89  	}
    90  
    91  	adr := tools.ParseAddr(addr)
    92  	defer adr.Free()
    93  
    94  	if _, err := conn.Write(adr.Bytes.Bytes()); err != nil {
    95  		_ = conn.Close()
    96  		return nil, fmt.Errorf("write target failed: %w", err)
    97  	}
    98  
    99  	return conn, nil
   100  }
   101  
   102  func (s *Shadowsocksr) PacketConn(ctx context.Context, addr netapi.Address) (net.PacketConn, error) {
   103  	c, err := s.dial.PacketConn(ctx, addr)
   104  	if err != nil {
   105  		return nil, fmt.Errorf("get packet conn failed: %w", err)
   106  	}
   107  	cipher := s.cipher.PacketConn(c)
   108  	proto, err := s.protocol.Packet(cipher)
   109  	if err != nil {
   110  		c.Close()
   111  		return nil, fmt.Errorf("protocol packet failed: %w", err)
   112  	}
   113  
   114  	return yuubinsya.NewAuthPacketConn(proto), nil
   115  }