dialParameters.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. /*
  2. * Copyright (c) 2023, Psiphon Inc.
  3. * All rights reserved.
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. *
  18. */
  19. package inproxy
  20. import (
  21. "context"
  22. "net"
  23. "time"
  24. )
  25. // RoundTripper provides a request/response round trip network transport with
  26. // blocking circumvention capabilities. A typical implementation is domain
  27. // fronted HTTPS. RoundTripper is used by clients and proxies to make
  28. // requests to brokers.
  29. type RoundTripper interface {
  30. RoundTrip(ctx context.Context, requestPayload []byte) (responsePayload []byte, err error)
  31. }
  32. // DialParameters provides in-proxy dial parameters and configuration, used by
  33. // both clients and proxies, and an interface for signaling when parameters
  34. // are successful or not, to facilitate replay of successful parameters.
  35. //
  36. // Each DialParameters should provide values selected in the context of a
  37. // single network, as identified by a network ID. A distinct DialParameters
  38. // should be created for each client in-proxy dial, with new or replayed
  39. // parameters selected as appropriate. One proxy run uses a single
  40. // DialParameters for all proxied connections. The proxy should be restarted
  41. // with a new DialParameters when the underlying network changes.
  42. type DialParameters interface {
  43. // CommonCompartmentIDs is the list of common, Psiphon-managed, in-proxy
  44. // compartment IDs known to a client. These IDs are delivered through
  45. // tactics, or embedded in OSLs.
  46. //
  47. // At most MaxCompartmentIDs may be sent to a broker; if necessary, the
  48. // provider may return a subset of known compartment IDs and replay when
  49. // the overall dial is a success; and/or retain only the most recently
  50. // discovered compartment IDs.
  51. //
  52. // CommonCompartmentIDs is not called for proxies.
  53. CommonCompartmentIDs() []ID
  54. // PersonalCompartmentIDs are compartment IDs distributed from proxy
  55. // operators to client users out-of-band and provide optional access
  56. // control. For example, a proxy operator may want to provide access only
  57. // to certain users, and/or users want to use only a proxy run by a
  58. // certain operator.
  59. //
  60. // At most MaxCompartmentIDs may be sent to a broker; for typical use
  61. // cases, both clients and proxies will specify a single personal
  62. // compartment ID.
  63. PersonalCompartmentIDs() []ID
  64. // Returns the network ID for the network this DialParameters is
  65. // associated with. For a single DialParameters, the NetworkID value
  66. // should not change. Replay-facilitating calls, Succeeded/Failed, all
  67. // assume the network and network ID remain static. The network ID value
  68. // is used by in-proxy dials to track internal state that depends on the
  69. // current network; this includes the port mapping types supported by the
  70. // network.
  71. NetworkID() string
  72. // Returns the network type for the current network, or NetworkTypeUnknown
  73. // if unknown.
  74. NetworkType() NetworkType
  75. // BrokerClientPrivateKey is the client or proxy's private key to be used
  76. // in the secure session established with a broker. Clients should
  77. // generate ephemeral keys; this is done automatically when a zero-value
  78. // SessionPrivateKey is returned. Proxies may generate, persist, and
  79. // long-lived keys to enable traffic attribution to a proxy, identified
  80. // by a proxy ID, the corresponding public key.
  81. BrokerClientPrivateKey() SessionPrivateKey
  82. // BrokerPublicKey is the public key for the broker selected by the
  83. // provider and reachable via BrokerClientRoundTripper. The broker is
  84. // authenticated in the secure session.
  85. BrokerPublicKey() SessionPublicKey
  86. // BrokerRootObfuscationSecret is the root obfuscation secret for the
  87. // broker and used in the secure session.
  88. BrokerRootObfuscationSecret() ObfuscationSecret
  89. // BrokerClientRoundTripper returns a RoundTripper to use for broker
  90. // requests. The provider handles selecting a broker and broker
  91. // addressing, as well as providing a round trip network transport with
  92. // blocking circumvention capabilities. A typical implementation is
  93. // domain fronted HTTPS. The RoundTripper should offer persistent network
  94. // connections and request multiplexing, for example with HTTP/2, so that
  95. // a single connection can be used for many concurrent requests.
  96. //
  97. // Clients and proxies make round trips to establish a secure session with
  98. // the broker, on top of the provided transport, and to exchange API
  99. // requests with the broker.
  100. BrokerClientRoundTripper() (RoundTripper, error)
  101. // BrokerClientRoundTripperSucceeded is called after a successful round
  102. // trip using the specified RoundTripper. This signal is used to set
  103. // replay for the round tripper's successful dial parameters.
  104. // BrokerClientRoundTripperSucceeded is called once per successful round
  105. // trip; the provider can choose to set replay only once.
  106. BrokerClientRoundTripperSucceeded(roundTripper RoundTripper)
  107. // BrokerClientRoundTripperSucceeded is called after a failed round trip
  108. // using the specified RoundTripper. This signal is used to clear replay
  109. // for the round tripper's unsuccessful dial parameters. The provider
  110. // will arrange for a new RoundTripper to be returned from the next
  111. // BrokerClientRoundTripper call, discarding the current RoundTripper
  112. // after closing its network resources.
  113. BrokerClientRoundTripperFailed(roundTripper RoundTripper)
  114. // ClientRootObfuscationSecret is the root obfuscation secret generated by
  115. // or replayed by the client, which will be used to drive and replay
  116. // obfuscation operations for the WebRTC dial, including any DTLS
  117. // randomization. The proxy receives the same root obfuscation secret,
  118. // relayed by the broker, and so the client's selection drives
  119. // obfuscation/replay on both sides.
  120. ClientRootObfuscationSecret() ObfuscationSecret
  121. // DoDTLSRandomization indicates whether to perform DTLS ClientHello
  122. // randomization. DoDTLSRandomization is specified by clients, which may
  123. // use a weighted coin flip or a replay to determine the value.
  124. DoDTLSRandomization() bool
  125. // STUNServerAddress selects a STUN server to use for this dial. When
  126. // RFC5780 is true, the STUN server must support RFC5780 NAT discovery;
  127. // otherwise, only basic STUN bind operation support is required. Clients
  128. // and proxies will receive a list of STUN server candidates via tactics,
  129. // and select a candidate at random or replay for each dial. If
  130. // STUNServerAddress returns "", STUN operations are skipped but the dial
  131. // may still succeed if a port mapping can be established.
  132. STUNServerAddress(RFC5780 bool) string
  133. // STUNServerAddressSucceeded is called after a successful STUN operation
  134. // with the STUN server specified by the address. This signal is used to
  135. // set replay for successful STUN servers. STUNServerAddressSucceeded
  136. // will be called when the STUN opertion succeeds, regardless of the
  137. // outcome of the rest of the dial. RFC5780 is true when the STUN server
  138. // was used for NAT discovery.
  139. STUNServerAddressSucceeded(RFC5780 bool, address string)
  140. // STUNServerAddressFailed is called after a failed STUN operation and is
  141. // used to clear replay for the specified STUN server.
  142. STUNServerAddressFailed(RFC5780 bool, address string)
  143. // DiscoverNAT indicates whether a client dial should start with NAT
  144. // discovery. Discovering and reporting the client NAT type will assist
  145. // in broker matching. However, RFC5780 NAT discovery can slow down a
  146. // dial and potentially looks like atypical network traffic. Client NAT
  147. // discovery is controlled by tactics and may be disabled or set to run
  148. // with a small probability. Discovered NAT types and portmapping types
  149. // may be cached and used with future dials via SetNATType/NATType and
  150. // SetPortMappingTypes/PortMappingTypes.
  151. //
  152. // Proxies always perform NAT discovery on start up, since that doesn't
  153. // delay a client dial.
  154. DiscoverNAT() bool
  155. // DisableSTUN indicates whether to skip STUN operations.
  156. DisableSTUN() bool
  157. // DisableSTUN indicates whether to skip port mapping operations.
  158. DisablePortMapping() bool
  159. // DisableInboundForMobleNetworks indicates that all attempts to set up
  160. // inbound operations -- including STUN and port mapping -- should be
  161. // skipped when the network type is NetworkTypeMobile. This skips
  162. // operations that can slow down dials and and unlikely to succeed on
  163. // most mobile networks with CGNAT.
  164. DisableInboundForMobleNetworks() bool
  165. // NATType returns any persisted NAT type for the current network, as set
  166. // by SetNATType. When NATTypeUnknown is returned, NAT discovery may be
  167. // run.
  168. NATType() NATType
  169. // SetNATType is called when the NAT type for the current network has been
  170. // discovered. The provider should persist this value, associated with
  171. // the current network ID and with a reasonable TTL, so the value can be
  172. // reused in subsequent dials without having to re-run NAT discovery.
  173. SetNATType(t NATType)
  174. // PortMappingTypes returns any persisted, supported port mapping types
  175. // for the current network, as set by SetPortMappingTypes. When an empty
  176. // list is returned port mapping discovery may be run. A list containing
  177. // only PortMappingTypeNone indicates that no supported port mapping
  178. // types were discovered.
  179. PortMappingTypes() PortMappingTypes
  180. // SetPortMappingTypes is called with the supported port mapping types
  181. // discovered for the current network. The provider should persist this
  182. // value, associated with the current network ID and with a reasonable
  183. // TTL, so the value can be reused in subsequent dials without having to
  184. // re-run port mapping discovery.
  185. SetPortMappingTypes(t PortMappingTypes)
  186. // ResolveAddress resolves a domain and returns its IP address. Clients
  187. // and proxies may use this to hook into the Psiphon custom resolver. The
  188. // provider adds the custom resolver tactics and network ID parameters
  189. // required by psiphon/common.Resolver.
  190. ResolveAddress(ctx context.Context, address string) (string, error)
  191. // UDPListen dials a local UDP socket. The socket should be bound to a
  192. // specific interface as required for VPN modes, and set a write timeout
  193. // to mitigate the issue documented in psiphon/common.WriteTimeoutUDPConn.
  194. UDPListen() (net.PacketConn, error)
  195. // BindToDevice binds a socket, specified by the file descriptor, to an
  196. // interface that isn't routed through a VPN when Psiphon is running in
  197. // VPN mode. BindToDevice is used in cases where a custom dialer cannot
  198. // be used, and UDPListen cannot be called.
  199. BindToDevice(fileDescriptor int) error
  200. DiscoverNATTimeout() time.Duration
  201. OfferRequestTimeout() time.Duration
  202. OfferRetryDelay() time.Duration
  203. OfferRetryJitter() float64
  204. AnnounceRequestTimeout() time.Duration
  205. AnnounceRetryDelay() time.Duration
  206. AnnounceRetryJitter() float64
  207. WebRTCAnswerTimeout() time.Duration
  208. AnswerRequestTimeout() time.Duration
  209. ProxyClientConnectTimeout() time.Duration
  210. ProxyDestinationDialTimeout() time.Duration
  211. }