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

     1  package shadowsocks
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"net"
     7  	"strings"
     8  
     9  	"github.com/Asutorufa/yuhaiin/pkg/net/netapi"
    10  	"github.com/Asutorufa/yuhaiin/pkg/net/proxy/shadowsocks/core"
    11  	"github.com/Asutorufa/yuhaiin/pkg/net/proxy/socks5/tools"
    12  	"github.com/Asutorufa/yuhaiin/pkg/net/proxy/yuubinsya"
    13  	"github.com/Asutorufa/yuhaiin/pkg/protos/node/point"
    14  	"github.com/Asutorufa/yuhaiin/pkg/protos/node/protocol"
    15  )
    16  
    17  // Shadowsocks shadowsocks
    18  type Shadowsocks struct {
    19  	cipher core.Cipher
    20  	p      netapi.Proxy
    21  	netapi.EmptyDispatch
    22  }
    23  
    24  func init() {
    25  	point.RegisterProtocol(NewClient)
    26  }
    27  
    28  func NewClient(config *protocol.Protocol_Shadowsocks) point.WrapProxy {
    29  	c := config.Shadowsocks
    30  	return func(p netapi.Proxy) (netapi.Proxy, error) {
    31  		cipher, err := core.PickCipher(strings.ToUpper(c.Method), nil, c.Password)
    32  		if err != nil {
    33  			return nil, err
    34  		}
    35  
    36  		return &Shadowsocks{cipher: cipher, p: p}, nil
    37  	}
    38  }
    39  
    40  // Conn .
    41  func (s *Shadowsocks) Conn(ctx context.Context, addr netapi.Address) (conn net.Conn, err error) {
    42  	conn, err = s.p.Conn(ctx, addr)
    43  	if err != nil {
    44  		return nil, fmt.Errorf("dial to %s failed: %w", addr, err)
    45  	}
    46  
    47  	if x, ok := conn.(*net.TCPConn); ok {
    48  		_ = x.SetKeepAlive(true)
    49  	}
    50  
    51  	adr := tools.ParseAddr(addr)
    52  	defer adr.Free()
    53  
    54  	conn = s.cipher.StreamConn(conn)
    55  	if _, err = conn.Write(adr.Bytes.Bytes()); err != nil {
    56  		conn.Close()
    57  		return nil, fmt.Errorf("shadowsocks write target failed: %w", err)
    58  	}
    59  	return conn, nil
    60  }
    61  
    62  // PacketConn .
    63  func (s *Shadowsocks) PacketConn(ctx context.Context, tar netapi.Address) (net.PacketConn, error) {
    64  	pc, err := s.p.PacketConn(ctx, tar)
    65  	if err != nil {
    66  		return nil, fmt.Errorf("create packet conn failed")
    67  	}
    68  
    69  	return yuubinsya.NewAuthPacketConn(s.cipher.PacketConn(pc)), nil
    70  }