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 }