dialer.go 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. package tapdance
  2. import (
  3. "context"
  4. "errors"
  5. "net"
  6. pb "github.com/refraction-networking/gotapdance/protobuf"
  7. )
  8. var sessionsTotal CounterUint64
  9. // Dialer contains options and implements advanced functions for establishing TapDance connection.
  10. type Dialer struct {
  11. SplitFlows bool
  12. // THIS IS REQUIRED TO INTERFACE WITH PSIPHON ANDROID
  13. // we use their dialer to prevent connection loopback into our own proxy
  14. // connection when tunneling the whole device.
  15. TcpDialer func(context.Context, string, string) (net.Conn, error)
  16. DarkDecoy bool
  17. // The type of registrar to use when performing Conjure registrations.
  18. DarkDecoyRegistrar Registrar
  19. // The type of transport to use for Conjure connections.
  20. Transport pb.TransportType
  21. UseProxyHeader bool
  22. V6Support bool // *bool so that it is a nullable type. that can be overridden
  23. Width int
  24. }
  25. // Dial connects to the address on the named network.
  26. //
  27. // The only supported network at this time: "tcp".
  28. // The address has the form "host:port".
  29. // The host must be a literal IP address, or a host name that can be
  30. // resolved to IP addresses.
  31. // To avoid abuse, only certain whitelisted ports are allowed.
  32. //
  33. // Example: Dial("tcp", "golang.org:80")
  34. func Dial(network, address string) (net.Conn, error) {
  35. var d Dialer
  36. return d.Dial(network, address)
  37. }
  38. // Dial connects to the address on the named network.
  39. func (d *Dialer) Dial(network, address string) (net.Conn, error) {
  40. return d.DialContext(context.Background(), network, address)
  41. }
  42. // DialContext connects to the address on the named network using the provided context.
  43. // Long deadline is strongly advised, since tapdance will try multiple decoys.
  44. //
  45. // The only supported network at this time: "tcp".
  46. // The address has the form "host:port".
  47. // The host must be a literal IP address, or a host name that can be
  48. // resolved to IP addresses.
  49. // To avoid abuse, only certain whitelisted ports are allowed.
  50. //
  51. // Example: Dial("tcp", "golang.org:80")
  52. func (d *Dialer) DialContext(ctx context.Context, network, address string) (net.Conn, error) {
  53. if network != "tcp" {
  54. return nil, &net.OpError{Op: "dial", Net: network, Err: net.UnknownNetworkError(network)}
  55. }
  56. if len(address) > 0 {
  57. _, _, err := net.SplitHostPort(address)
  58. if err != nil {
  59. return nil, err
  60. }
  61. }
  62. if d.TcpDialer == nil {
  63. // custom dialer is not set, use default
  64. defaultDialer := net.Dialer{}
  65. d.TcpDialer = defaultDialer.DialContext
  66. }
  67. if !d.SplitFlows {
  68. if !d.DarkDecoy {
  69. flow, err := makeTdFlow(flowBidirectional, nil, address)
  70. if err != nil {
  71. return nil, err
  72. }
  73. flow.tdRaw.TcpDialer = d.TcpDialer
  74. flow.tdRaw.useProxyHeader = d.UseProxyHeader
  75. return flow, flow.DialContext(ctx)
  76. } else {
  77. // _, err := makeTdFlow(flowBidirectional, nil, address)
  78. // if err != nil {
  79. // return nil, err
  80. // }
  81. cjSession := makeConjureSession(address, d.Transport)
  82. cjSession.TcpDialer = d.TcpDialer
  83. cjSession.UseProxyHeader = d.UseProxyHeader
  84. cjSession.Width = uint(d.Width)
  85. if d.V6Support {
  86. cjSession.V6Support = &V6{include: both, support: true}
  87. } else {
  88. cjSession.V6Support = &V6{include: v4, support: false}
  89. }
  90. if len(address) == 0 {
  91. return nil, errors.New("Dark Decoys require target address to be set")
  92. }
  93. return DialConjure(ctx, cjSession, d.DarkDecoyRegistrar)
  94. }
  95. }
  96. return nil, errors.New("SplitFlows are not supported")
  97. }
  98. // DialProxy establishes direct connection to TapDance station proxy.
  99. // Users are expected to send HTTP CONNECT request next.
  100. func (d *Dialer) DialProxy() (net.Conn, error) {
  101. return d.DialProxyContext(context.Background())
  102. }
  103. // DialProxyContext establishes direct connection to TapDance station proxy using the provided context.
  104. // Users are expected to send HTTP CONNECT request next.
  105. func (d *Dialer) DialProxyContext(ctx context.Context) (net.Conn, error) {
  106. return d.DialContext(ctx, "tcp", "")
  107. }