transport_https.go 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. package dns
  2. import (
  3. "bytes"
  4. "context"
  5. "net"
  6. "net/http"
  7. "net/netip"
  8. "os"
  9. "github.com/sagernet/sing/common"
  10. "github.com/sagernet/sing/common/buf"
  11. M "github.com/sagernet/sing/common/metadata"
  12. N "github.com/sagernet/sing/common/network"
  13. "github.com/sagernet/sing-box/adapter"
  14. C "github.com/sagernet/sing-box/constant"
  15. "golang.org/x/net/dns/dnsmessage"
  16. )
  17. const dnsMimeType = "application/dns-message"
  18. var _ adapter.DNSTransport = (*HTTPSTransport)(nil)
  19. type HTTPSTransport struct {
  20. destination string
  21. transport *http.Transport
  22. }
  23. func NewHTTPSTransport(dialer N.Dialer, destination string) *HTTPSTransport {
  24. return &HTTPSTransport{
  25. destination: destination,
  26. transport: &http.Transport{
  27. ForceAttemptHTTP2: true,
  28. DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
  29. return dialer.DialContext(ctx, network, M.ParseSocksaddr(addr))
  30. },
  31. },
  32. }
  33. }
  34. func (t *HTTPSTransport) Start() error {
  35. return nil
  36. }
  37. func (t *HTTPSTransport) Close() error {
  38. t.transport.CloseIdleConnections()
  39. return nil
  40. }
  41. func (t *HTTPSTransport) Raw() bool {
  42. return true
  43. }
  44. func (t *HTTPSTransport) Exchange(ctx context.Context, message *dnsmessage.Message) (*dnsmessage.Message, error) {
  45. message.ID = 0
  46. _buffer := buf.StackNewSize(1024)
  47. defer common.KeepAlive(_buffer)
  48. buffer := common.Dup(_buffer)
  49. defer buffer.Release()
  50. rawMessage, err := message.AppendPack(buffer.Index(0))
  51. if err != nil {
  52. return nil, err
  53. }
  54. buffer.Truncate(len(rawMessage))
  55. request, err := http.NewRequest(http.MethodPost, t.destination, bytes.NewReader(buffer.Bytes()))
  56. if err != nil {
  57. return nil, err
  58. }
  59. request.WithContext(ctx)
  60. request.Header.Set("content-type", dnsMimeType)
  61. request.Header.Set("accept", dnsMimeType)
  62. client := &http.Client{Transport: t.transport}
  63. response, err := client.Do(request)
  64. if err != nil {
  65. return nil, err
  66. }
  67. defer response.Body.Close()
  68. buffer.FullReset()
  69. _, err = buffer.ReadAllFrom(response.Body)
  70. if err != nil {
  71. return nil, err
  72. }
  73. var responseMessage dnsmessage.Message
  74. err = responseMessage.Unpack(buffer.Bytes())
  75. if err != nil {
  76. return nil, err
  77. }
  78. return &responseMessage, nil
  79. }
  80. func (t *HTTPSTransport) Lookup(ctx context.Context, domain string, strategy C.DomainStrategy) ([]netip.Addr, error) {
  81. return nil, os.ErrInvalid
  82. }