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 }