dialer.go 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. package hysteria2
  2. import (
  3. "context"
  4. "sync"
  5. hyClient "github.com/apernet/hysteria/core/v2/client"
  6. hyProtocol "github.com/apernet/hysteria/core/v2/international/protocol"
  7. "github.com/apernet/quic-go/quicvarint"
  8. "github.com/v2fly/v2ray-core/v5/common"
  9. "github.com/v2fly/v2ray-core/v5/common/net"
  10. "github.com/v2fly/v2ray-core/v5/common/session"
  11. "github.com/v2fly/v2ray-core/v5/transport/internet"
  12. "github.com/v2fly/v2ray-core/v5/transport/internet/tls"
  13. )
  14. var RunningClient map[net.Addr](hyClient.Client)
  15. var ClientMutex sync.Mutex
  16. var MBps uint64 = 1000000 / 8 // MByte
  17. func GetClientTLSConfig(streamSettings *internet.MemoryStreamConfig) (*hyClient.TLSConfig, error) {
  18. config := tls.ConfigFromStreamSettings(streamSettings)
  19. if config == nil {
  20. return nil, newError(Hy2MustNeedTLS)
  21. }
  22. tlsConfig := config.GetTLSConfig()
  23. return &hyClient.TLSConfig{
  24. RootCAs: tlsConfig.RootCAs,
  25. ServerName: tlsConfig.ServerName,
  26. InsecureSkipVerify: tlsConfig.InsecureSkipVerify,
  27. VerifyPeerCertificate: tlsConfig.VerifyPeerCertificate,
  28. }, nil
  29. }
  30. func ResolveAddress(dest net.Destination) (net.Addr, error) {
  31. var destAddr *net.UDPAddr
  32. if dest.Address.Family().IsIP() {
  33. destAddr = &net.UDPAddr{
  34. IP: dest.Address.IP(),
  35. Port: int(dest.Port),
  36. }
  37. } else {
  38. addr, err := net.ResolveUDPAddr("udp", dest.NetAddr())
  39. if err != nil {
  40. return nil, err
  41. }
  42. destAddr = addr
  43. }
  44. return destAddr, nil
  45. }
  46. type connFactory struct {
  47. hyClient.ConnFactory
  48. NewFunc func(addr net.Addr) (net.PacketConn, error)
  49. }
  50. func (f *connFactory) New(addr net.Addr) (net.PacketConn, error) {
  51. return f.NewFunc(addr)
  52. }
  53. func NewHyClient(serverAddr net.Addr, streamSettings *internet.MemoryStreamConfig) (hyClient.Client, error) {
  54. tlsConfig, err := GetClientTLSConfig(streamSettings)
  55. if err != nil {
  56. return nil, err
  57. }
  58. config := streamSettings.ProtocolSettings.(*Config)
  59. client, _, err := hyClient.NewClient(&hyClient.Config{
  60. Auth: config.GetPassword(),
  61. TLSConfig: *tlsConfig,
  62. ServerAddr: serverAddr,
  63. ConnFactory: &connFactory{
  64. NewFunc: func(addr net.Addr) (net.PacketConn, error) {
  65. rawConn, err := internet.ListenSystemPacket(context.Background(), &net.UDPAddr{
  66. IP: []byte{0, 0, 0, 0},
  67. Port: 0,
  68. }, streamSettings.SocketSettings)
  69. if err != nil {
  70. return nil, err
  71. }
  72. return rawConn.(*net.UDPConn), nil
  73. },
  74. },
  75. BandwidthConfig: hyClient.BandwidthConfig{MaxTx: config.Congestion.GetUpMbps() * MBps, MaxRx: config.GetCongestion().GetDownMbps() * MBps},
  76. })
  77. if err != nil {
  78. return nil, err
  79. }
  80. return client, nil
  81. }
  82. func CloseHyClient(serverAddr net.Addr) error {
  83. ClientMutex.Lock()
  84. defer ClientMutex.Unlock()
  85. client, found := RunningClient[serverAddr]
  86. if found {
  87. delete(RunningClient, serverAddr)
  88. return client.Close()
  89. }
  90. return nil
  91. }
  92. func GetHyClient(serverAddr net.Addr, streamSettings *internet.MemoryStreamConfig) (hyClient.Client, error) {
  93. var err error
  94. var client hyClient.Client
  95. ClientMutex.Lock()
  96. client, found := RunningClient[serverAddr]
  97. ClientMutex.Unlock()
  98. if !found || !CheckHyClientHealthy(client) {
  99. if found {
  100. // retry
  101. CloseHyClient(serverAddr)
  102. }
  103. client, err = NewHyClient(serverAddr, streamSettings)
  104. if err != nil {
  105. return nil, err
  106. }
  107. ClientMutex.Lock()
  108. RunningClient[serverAddr] = client
  109. ClientMutex.Unlock()
  110. }
  111. return client, nil
  112. }
  113. func CheckHyClientHealthy(client hyClient.Client) bool {
  114. quicConn := client.GetQuicConn()
  115. if quicConn == nil {
  116. return false
  117. }
  118. select {
  119. case <-quicConn.Context().Done():
  120. return false
  121. default:
  122. }
  123. return true
  124. }
  125. func Dial(ctx context.Context, dest net.Destination, streamSettings *internet.MemoryStreamConfig) (internet.Connection, error) {
  126. config := streamSettings.ProtocolSettings.(*Config)
  127. serverAddr, err := ResolveAddress(dest)
  128. if err != nil {
  129. return nil, err
  130. }
  131. client, err := GetHyClient(serverAddr, streamSettings)
  132. if err != nil {
  133. CloseHyClient(serverAddr)
  134. return nil, err
  135. }
  136. quicConn := client.GetQuicConn()
  137. conn := &HyConn{
  138. local: quicConn.LocalAddr(),
  139. remote: quicConn.RemoteAddr(),
  140. }
  141. outbound := session.OutboundFromContext(ctx)
  142. network := net.Network_TCP
  143. if outbound != nil {
  144. network = outbound.Target.Network
  145. conn.Target = outbound.Target
  146. }
  147. if network == net.Network_UDP && config.GetUseUdpExtension() { // only hysteria2 can use udpExtension
  148. conn.IsUDPExtension = true
  149. conn.IsServer = false
  150. conn.ClientUDPSession, err = client.UDP()
  151. if err != nil {
  152. CloseHyClient(serverAddr)
  153. return nil, err
  154. }
  155. return conn, nil
  156. }
  157. conn.stream, err = client.OpenStream()
  158. if err != nil {
  159. CloseHyClient(serverAddr)
  160. return nil, err
  161. }
  162. // write TCP frame type
  163. frameSize := int(quicvarint.Len(hyProtocol.FrameTypeTCPRequest))
  164. buf := make([]byte, frameSize)
  165. hyProtocol.VarintPut(buf, hyProtocol.FrameTypeTCPRequest)
  166. conn.stream.Write(buf)
  167. return conn, nil
  168. }
  169. func init() {
  170. RunningClient = make(map[net.Addr]hyClient.Client)
  171. common.Must(internet.RegisterTransportDialer(protocolName, Dial))
  172. }