interface.go 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414
  1. package quic
  2. import (
  3. "context"
  4. "errors"
  5. "io"
  6. "net"
  7. "time"
  8. tls "github.com/Psiphon-Labs/psiphon-tls"
  9. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/prng"
  10. "github.com/Psiphon-Labs/quic-go/internal/handshake"
  11. "github.com/Psiphon-Labs/quic-go/internal/protocol"
  12. "github.com/Psiphon-Labs/quic-go/logging"
  13. )
  14. // The StreamID is the ID of a QUIC stream.
  15. type StreamID = protocol.StreamID
  16. // A Version is a QUIC version number.
  17. type Version = protocol.Version
  18. const (
  19. // Version1 is RFC 9000
  20. Version1 = protocol.Version1
  21. // Version2 is RFC 9369
  22. Version2 = protocol.Version2
  23. )
  24. // A ClientToken is a token received by the client.
  25. // It can be used to skip address validation on future connection attempts.
  26. type ClientToken struct {
  27. data []byte
  28. }
  29. type TokenStore interface {
  30. // Pop searches for a ClientToken associated with the given key.
  31. // Since tokens are not supposed to be reused, it must remove the token from the cache.
  32. // It returns nil when no token is found.
  33. Pop(key string) (token *ClientToken)
  34. // Put adds a token to the cache with the given key. It might get called
  35. // multiple times in a connection.
  36. Put(key string, token *ClientToken)
  37. }
  38. // Err0RTTRejected is the returned from:
  39. // * Open{Uni}Stream{Sync}
  40. // * Accept{Uni}Stream
  41. // * Stream.Read and Stream.Write
  42. // when the server rejects a 0-RTT connection attempt.
  43. var Err0RTTRejected = errors.New("0-RTT rejected")
  44. // ConnectionTracingKey can be used to associate a ConnectionTracer with a Connection.
  45. // It is set on the Connection.Context() context,
  46. // as well as on the context passed to logging.Tracer.NewConnectionTracer.
  47. // Deprecated: Applications can set their own tracing key using Transport.ConnContext.
  48. var ConnectionTracingKey = connTracingCtxKey{}
  49. // ConnectionTracingID is the type of the context value saved under the ConnectionTracingKey.
  50. // Deprecated: Applications can set their own tracing key using Transport.ConnContext.
  51. type ConnectionTracingID uint64
  52. type connTracingCtxKey struct{}
  53. // QUICVersionContextKey can be used to find out the QUIC version of a TLS handshake from the
  54. // context returned by tls.Config.ClientHelloInfo.Context.
  55. var QUICVersionContextKey = handshake.QUICVersionContextKey
  56. // Stream is the interface implemented by QUIC streams
  57. // In addition to the errors listed on the Connection,
  58. // calls to stream functions can return a StreamError if the stream is canceled.
  59. type Stream interface {
  60. ReceiveStream
  61. SendStream
  62. // SetDeadline sets the read and write deadlines associated
  63. // with the connection. It is equivalent to calling both
  64. // SetReadDeadline and SetWriteDeadline.
  65. SetDeadline(t time.Time) error
  66. }
  67. // A ReceiveStream is a unidirectional Receive Stream.
  68. type ReceiveStream interface {
  69. // StreamID returns the stream ID.
  70. StreamID() StreamID
  71. // Read reads data from the stream.
  72. // Read can be made to time out and return a net.Error with Timeout() == true
  73. // after a fixed time limit; see SetDeadline and SetReadDeadline.
  74. // If the stream was canceled by the peer, the error is a StreamError and
  75. // Remote == true.
  76. // If the connection was closed due to a timeout, the error satisfies
  77. // the net.Error interface, and Timeout() will be true.
  78. io.Reader
  79. // CancelRead aborts receiving on this stream.
  80. // It will ask the peer to stop transmitting stream data.
  81. // Read will unblock immediately, and future Read calls will fail.
  82. // When called multiple times or after reading the io.EOF it is a no-op.
  83. CancelRead(StreamErrorCode)
  84. // SetReadDeadline sets the deadline for future Read calls and
  85. // any currently-blocked Read call.
  86. // A zero value for t means Read will not time out.
  87. SetReadDeadline(t time.Time) error
  88. }
  89. // A SendStream is a unidirectional Send Stream.
  90. type SendStream interface {
  91. // StreamID returns the stream ID.
  92. StreamID() StreamID
  93. // Write writes data to the stream.
  94. // Write can be made to time out and return a net.Error with Timeout() == true
  95. // after a fixed time limit; see SetDeadline and SetWriteDeadline.
  96. // If the stream was canceled by the peer, the error is a StreamError and
  97. // Remote == true.
  98. // If the connection was closed due to a timeout, the error satisfies
  99. // the net.Error interface, and Timeout() will be true.
  100. io.Writer
  101. // Close closes the write-direction of the stream.
  102. // Future calls to Write are not permitted after calling Close.
  103. // It must not be called concurrently with Write.
  104. // It must not be called after calling CancelWrite.
  105. io.Closer
  106. // CancelWrite aborts sending on this stream.
  107. // Data already written, but not yet delivered to the peer is not guaranteed to be delivered reliably.
  108. // Write will unblock immediately, and future calls to Write will fail.
  109. // When called multiple times it is a no-op.
  110. // When called after Close, it aborts delivery. Note that there is no guarantee if
  111. // the peer will receive the FIN or the reset first.
  112. CancelWrite(StreamErrorCode)
  113. // The Context is canceled as soon as the write-side of the stream is closed.
  114. // This happens when Close() or CancelWrite() is called, or when the peer
  115. // cancels the read-side of their stream.
  116. // The cancellation cause is set to the error that caused the stream to
  117. // close, or `context.Canceled` in case the stream is closed without error.
  118. Context() context.Context
  119. // SetWriteDeadline sets the deadline for future Write calls
  120. // and any currently-blocked Write call.
  121. // Even if write times out, it may return n > 0, indicating that
  122. // some data was successfully written.
  123. // A zero value for t means Write will not time out.
  124. SetWriteDeadline(t time.Time) error
  125. }
  126. // A Connection is a QUIC connection between two peers.
  127. // Calls to the connection (and to streams) can return the following types of errors:
  128. // * ApplicationError: for errors triggered by the application running on top of QUIC
  129. // * TransportError: for errors triggered by the QUIC transport (in many cases a misbehaving peer)
  130. // * IdleTimeoutError: when the peer goes away unexpectedly (this is a net.Error timeout error)
  131. // * HandshakeTimeoutError: when the cryptographic handshake takes too long (this is a net.Error timeout error)
  132. // * StatelessResetError: when we receive a stateless reset
  133. // * VersionNegotiationError: returned by the client, when there's no version overlap between the peers
  134. type Connection interface {
  135. // AcceptStream returns the next stream opened by the peer, blocking until one is available.
  136. // If the connection was closed due to a timeout, the error satisfies
  137. // the net.Error interface, and Timeout() will be true.
  138. AcceptStream(context.Context) (Stream, error)
  139. // AcceptUniStream returns the next unidirectional stream opened by the peer, blocking until one is available.
  140. // If the connection was closed due to a timeout, the error satisfies
  141. // the net.Error interface, and Timeout() will be true.
  142. AcceptUniStream(context.Context) (ReceiveStream, error)
  143. // OpenStream opens a new bidirectional QUIC stream.
  144. // There is no signaling to the peer about new streams:
  145. // The peer can only accept the stream after data has been sent on the stream,
  146. // or the stream has been reset or closed.
  147. // When reaching the peer's stream limit, it is not possible to open a new stream until the
  148. // peer raises the stream limit. In that case, a StreamLimitReachedError is returned.
  149. OpenStream() (Stream, error)
  150. // OpenStreamSync opens a new bidirectional QUIC stream.
  151. // It blocks until a new stream can be opened.
  152. // There is no signaling to the peer about new streams:
  153. // The peer can only accept the stream after data has been sent on the stream,
  154. // or the stream has been reset or closed.
  155. OpenStreamSync(context.Context) (Stream, error)
  156. // OpenUniStream opens a new outgoing unidirectional QUIC stream.
  157. // There is no signaling to the peer about new streams:
  158. // The peer can only accept the stream after data has been sent on the stream,
  159. // or the stream has been reset or closed.
  160. // When reaching the peer's stream limit, it is not possible to open a new stream until the
  161. // peer raises the stream limit. In that case, a StreamLimitReachedError is returned.
  162. OpenUniStream() (SendStream, error)
  163. // OpenUniStreamSync opens a new outgoing unidirectional QUIC stream.
  164. // It blocks until a new stream can be opened.
  165. // There is no signaling to the peer about new streams:
  166. // The peer can only accept the stream after data has been sent on the stream,
  167. // or the stream has been reset or closed.
  168. OpenUniStreamSync(context.Context) (SendStream, error)
  169. // LocalAddr returns the local address.
  170. LocalAddr() net.Addr
  171. // RemoteAddr returns the address of the peer.
  172. RemoteAddr() net.Addr
  173. // CloseWithError closes the connection with an error.
  174. // The error string will be sent to the peer.
  175. CloseWithError(ApplicationErrorCode, string) error
  176. // Context returns a context that is cancelled when the connection is closed.
  177. // The cancellation cause is set to the error that caused the connection to
  178. // close, or `context.Canceled` in case the listener is closed first.
  179. Context() context.Context
  180. // ConnectionState returns basic details about the QUIC connection.
  181. // Warning: This API should not be considered stable and might change soon.
  182. ConnectionState() ConnectionState
  183. // [Psiphon]
  184. // TLSConnectionMetrics returns metrics of interest about the connection
  185. // that are not available from ConnectionState.
  186. TLSConnectionMetrics() tls.ConnectionMetrics
  187. // SendDatagram sends a message using a QUIC datagram, as specified in RFC 9221.
  188. // There is no delivery guarantee for DATAGRAM frames, they are not retransmitted if lost.
  189. // The payload of the datagram needs to fit into a single QUIC packet.
  190. // In addition, a datagram may be dropped before being sent out if the available packet size suddenly decreases.
  191. // If the payload is too large to be sent at the current time, a DatagramTooLargeError is returned.
  192. SendDatagram(payload []byte) error
  193. // ReceiveDatagram gets a message received in a datagram, as specified in RFC 9221.
  194. ReceiveDatagram(context.Context) ([]byte, error)
  195. }
  196. // An EarlyConnection is a connection that is handshaking.
  197. // Data sent during the handshake is encrypted using the forward secure keys.
  198. // When using client certificates, the client's identity is only verified
  199. // after completion of the handshake.
  200. type EarlyConnection interface {
  201. Connection
  202. // HandshakeComplete blocks until the handshake completes (or fails).
  203. // For the client, data sent before completion of the handshake is encrypted with 0-RTT keys.
  204. // For the server, data sent before completion of the handshake is encrypted with 1-RTT keys,
  205. // however the client's identity is only verified once the handshake completes.
  206. HandshakeComplete() <-chan struct{}
  207. NextConnection(context.Context) (Connection, error)
  208. }
  209. // StatelessResetKey is a key used to derive stateless reset tokens.
  210. type StatelessResetKey [32]byte
  211. // TokenGeneratorKey is a key used to encrypt session resumption tokens.
  212. type TokenGeneratorKey = handshake.TokenProtectorKey
  213. // A ConnectionID is a QUIC Connection ID, as defined in RFC 9000.
  214. // It is not able to handle QUIC Connection IDs longer than 20 bytes,
  215. // as they are allowed by RFC 8999.
  216. type ConnectionID = protocol.ConnectionID
  217. // ConnectionIDFromBytes interprets b as a Connection ID. It panics if b is
  218. // longer than 20 bytes.
  219. func ConnectionIDFromBytes(b []byte) ConnectionID {
  220. return protocol.ParseConnectionID(b)
  221. }
  222. // A ConnectionIDGenerator is an interface that allows clients to implement their own format
  223. // for the Connection IDs that servers/clients use as SrcConnectionID in QUIC packets.
  224. //
  225. // Connection IDs generated by an implementation should always produce IDs of constant size.
  226. type ConnectionIDGenerator interface {
  227. // GenerateConnectionID generates a new ConnectionID.
  228. // Generated ConnectionIDs should be unique and observers should not be able to correlate two ConnectionIDs.
  229. GenerateConnectionID() (ConnectionID, error)
  230. // ConnectionIDLen tells what is the length of the ConnectionIDs generated by the implementation of
  231. // this interface.
  232. // Effectively, this means that implementations of ConnectionIDGenerator must always return constant-size
  233. // connection IDs. Valid lengths are between 0 and 20 and calls to GenerateConnectionID.
  234. // 0-length ConnectionsIDs can be used when an endpoint (server or client) does not require multiplexing connections
  235. // in the presence of a connection migration environment.
  236. ConnectionIDLen() int
  237. }
  238. // Config contains all configuration data needed for a QUIC server or client.
  239. type Config struct {
  240. // GetConfigForClient is called for incoming connections.
  241. // If the error is not nil, the connection attempt is refused.
  242. GetConfigForClient func(info *ClientHelloInfo) (*Config, error)
  243. // The QUIC versions that can be negotiated.
  244. // If not set, it uses all versions available.
  245. Versions []Version
  246. // HandshakeIdleTimeout is the idle timeout before completion of the handshake.
  247. // If we don't receive any packet from the peer within this time, the connection attempt is aborted.
  248. // Additionally, if the handshake doesn't complete in twice this time, the connection attempt is also aborted.
  249. // If this value is zero, the timeout is set to 5 seconds.
  250. HandshakeIdleTimeout time.Duration
  251. // MaxIdleTimeout is the maximum duration that may pass without any incoming network activity.
  252. // The actual value for the idle timeout is the minimum of this value and the peer's.
  253. // This value only applies after the handshake has completed.
  254. // If the timeout is exceeded, the connection is closed.
  255. // If this value is zero, the timeout is set to 30 seconds.
  256. MaxIdleTimeout time.Duration
  257. // The TokenStore stores tokens received from the server.
  258. // Tokens are used to skip address validation on future connection attempts.
  259. // The key used to store tokens is the ServerName from the tls.Config, if set
  260. // otherwise the token is associated with the server's IP address.
  261. TokenStore TokenStore
  262. // InitialStreamReceiveWindow is the initial size of the stream-level flow control window for receiving data.
  263. // If the application is consuming data quickly enough, the flow control auto-tuning algorithm
  264. // will increase the window up to MaxStreamReceiveWindow.
  265. // If this value is zero, it will default to 512 KB.
  266. // Values larger than the maximum varint (quicvarint.Max) will be clipped to that value.
  267. InitialStreamReceiveWindow uint64
  268. // MaxStreamReceiveWindow is the maximum stream-level flow control window for receiving data.
  269. // If this value is zero, it will default to 6 MB.
  270. // Values larger than the maximum varint (quicvarint.Max) will be clipped to that value.
  271. MaxStreamReceiveWindow uint64
  272. // InitialConnectionReceiveWindow is the initial size of the stream-level flow control window for receiving data.
  273. // If the application is consuming data quickly enough, the flow control auto-tuning algorithm
  274. // will increase the window up to MaxConnectionReceiveWindow.
  275. // If this value is zero, it will default to 512 KB.
  276. // Values larger than the maximum varint (quicvarint.Max) will be clipped to that value.
  277. InitialConnectionReceiveWindow uint64
  278. // MaxConnectionReceiveWindow is the connection-level flow control window for receiving data.
  279. // If this value is zero, it will default to 15 MB.
  280. // Values larger than the maximum varint (quicvarint.Max) will be clipped to that value.
  281. MaxConnectionReceiveWindow uint64
  282. // AllowConnectionWindowIncrease is called every time the connection flow controller attempts
  283. // to increase the connection flow control window.
  284. // If set, the caller can prevent an increase of the window. Typically, it would do so to
  285. // limit the memory usage.
  286. // To avoid deadlocks, it is not valid to call other functions on the connection or on streams
  287. // in this callback.
  288. AllowConnectionWindowIncrease func(conn Connection, delta uint64) bool
  289. // MaxIncomingStreams is the maximum number of concurrent bidirectional streams that a peer is allowed to open.
  290. // If not set, it will default to 100.
  291. // If set to a negative value, it doesn't allow any bidirectional streams.
  292. // Values larger than 2^60 will be clipped to that value.
  293. MaxIncomingStreams int64
  294. // MaxIncomingUniStreams is the maximum number of concurrent unidirectional streams that a peer is allowed to open.
  295. // If not set, it will default to 100.
  296. // If set to a negative value, it doesn't allow any unidirectional streams.
  297. // Values larger than 2^60 will be clipped to that value.
  298. MaxIncomingUniStreams int64
  299. // KeepAlivePeriod defines whether this peer will periodically send a packet to keep the connection alive.
  300. // If set to 0, then no keep alive is sent. Otherwise, the keep alive is sent on that period (or at most
  301. // every half of MaxIdleTimeout, whichever is smaller).
  302. KeepAlivePeriod time.Duration
  303. // InitialPacketSize is the initial size of packets sent.
  304. // It is usually not necessary to manually set this value,
  305. // since Path MTU discovery very quickly finds the path's MTU.
  306. // If set too high, the path might not support packets that large, leading to a timeout of the QUIC handshake.
  307. // Values below 1200 are invalid.
  308. InitialPacketSize uint16
  309. // DisablePathMTUDiscovery disables Path MTU Discovery (RFC 8899).
  310. // This allows the sending of QUIC packets that fully utilize the available MTU of the path.
  311. // Path MTU discovery is only available on systems that allow setting of the Don't Fragment (DF) bit.
  312. DisablePathMTUDiscovery bool
  313. // Allow0RTT allows the application to decide if a 0-RTT connection attempt should be accepted.
  314. // Only valid for the server.
  315. Allow0RTT bool
  316. // Enable QUIC datagram support (RFC 9221).
  317. EnableDatagrams bool
  318. Tracer func(context.Context, logging.Perspective, ConnectionID) *logging.ConnectionTracer
  319. // [Psiphon]
  320. // ClientHelloSeed is used for TLS Client Hello randomization and replay.
  321. ClientHelloSeed *prng.Seed
  322. // [Psiphon]
  323. // GetClientHelloRandom is used by the QUIC client to supply a specific
  324. // value in the TLS Client Hello random field. This is used to send an
  325. // anti-probing message, indistinguishable from random, that proves
  326. // knowlegde of a shared secret key.
  327. GetClientHelloRandom func() ([]byte, error)
  328. // [Psiphon]
  329. // VerifyClientHelloRandom is used by the QUIC server to verify that the
  330. // TLS Client Hello random field, supplied in the Initial packet for a
  331. // new connection, was created using the shared secret key and is not
  332. // replayed.
  333. VerifyClientHelloRandom func(net.Addr, []byte) bool
  334. // [Psiphon]
  335. // ClientMaxPacketSizeAdjustment indicates that the max packet size should
  336. // be reduced by the specified amount. This is used to reserve space for
  337. // packet obfuscation overhead while remaining at or under the 1280
  338. // initial target packet size as well as protocol.MaxPacketBufferSize,
  339. // the maximum packet size under MTU discovery.
  340. ClientMaxPacketSizeAdjustment int
  341. // [Psiphon]
  342. // ServerMaxPacketSizeAdjustment indicates that, for the flow associated
  343. // with the given client address, the max packet size should be reduced
  344. // by the specified amount. This is used to reserve space for packet
  345. // obfuscation overhead while remaining at or under the 1280 target
  346. // packet size. Must be set only for QUIC server configs.
  347. ServerMaxPacketSizeAdjustment func(net.Addr) int
  348. }
  349. // ClientHelloInfo contains information about an incoming connection attempt.
  350. type ClientHelloInfo struct {
  351. // RemoteAddr is the remote address on the Initial packet.
  352. // Unless AddrVerified is set, the address is not yet verified, and could be a spoofed IP address.
  353. RemoteAddr net.Addr
  354. // AddrVerified says if the remote address was verified using QUIC's Retry mechanism.
  355. // Note that the Retry mechanism costs one network roundtrip,
  356. // and is not performed unless Transport.MaxUnvalidatedHandshakes is surpassed.
  357. AddrVerified bool
  358. }
  359. // ConnectionState records basic details about a QUIC connection
  360. type ConnectionState struct {
  361. // TLS contains information about the TLS connection state, incl. the tls.ConnectionState.
  362. TLS tls.ConnectionState
  363. // SupportsDatagrams indicates whether the peer advertised support for QUIC datagrams (RFC 9221).
  364. // When true, datagrams can be sent using the Connection's SendDatagram method.
  365. // This is a unilateral declaration by the peer - receiving datagrams is only possible if
  366. // datagram support was enabled locally via Config.EnableDatagrams.
  367. SupportsDatagrams bool
  368. // Used0RTT says if 0-RTT resumption was used.
  369. Used0RTT bool
  370. // Version is the QUIC version of the QUIC connection.
  371. Version Version
  372. // GSO says if generic segmentation offload is used
  373. GSO bool
  374. // [Psiphon]
  375. TLSMetrics tls.ConnectionMetrics
  376. }