interface.go 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. package quic
  2. import (
  3. "context"
  4. "errors"
  5. "io"
  6. "net"
  7. "time"
  8. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/prng"
  9. "github.com/Psiphon-Labs/quic-go/internal/handshake"
  10. "github.com/Psiphon-Labs/quic-go/internal/protocol"
  11. "github.com/Psiphon-Labs/quic-go/logging"
  12. )
  13. // The StreamID is the ID of a QUIC stream.
  14. type StreamID = protocol.StreamID
  15. // A VersionNumber is a QUIC version number.
  16. type VersionNumber = protocol.VersionNumber
  17. const (
  18. // VersionDraft29 is IETF QUIC draft-29
  19. VersionDraft29 = protocol.VersionDraft29
  20. // Version1 is RFC 9000
  21. Version1 = protocol.Version1
  22. )
  23. // A Token can be used to verify the ownership of the client address.
  24. type Token struct {
  25. // IsRetryToken encodes how the client received the token. There are two ways:
  26. // * In a Retry packet sent when trying to establish a new connection.
  27. // * In a NEW_TOKEN frame on a previous connection.
  28. IsRetryToken bool
  29. RemoteAddr string
  30. SentTime time.Time
  31. }
  32. // A ClientToken is a token received by the client.
  33. // It can be used to skip address validation on future connection attempts.
  34. type ClientToken struct {
  35. data []byte
  36. }
  37. type TokenStore interface {
  38. // Pop searches for a ClientToken associated with the given key.
  39. // Since tokens are not supposed to be reused, it must remove the token from the cache.
  40. // It returns nil when no token is found.
  41. Pop(key string) (token *ClientToken)
  42. // Put adds a token to the cache with the given key. It might get called
  43. // multiple times in a connection.
  44. Put(key string, token *ClientToken)
  45. }
  46. // Err0RTTRejected is the returned from:
  47. // * Open{Uni}Stream{Sync}
  48. // * Accept{Uni}Stream
  49. // * Stream.Read and Stream.Write
  50. // when the server rejects a 0-RTT connection attempt.
  51. var Err0RTTRejected = errors.New("0-RTT rejected")
  52. // SessionTracingKey can be used to associate a ConnectionTracer with a Session.
  53. // It is set on the Session.Context() context,
  54. // as well as on the context passed to logging.Tracer.NewConnectionTracer.
  55. var SessionTracingKey = sessionTracingCtxKey{}
  56. type sessionTracingCtxKey struct{}
  57. // Stream is the interface implemented by QUIC streams
  58. // In addition to the errors listed on the Session,
  59. // calls to stream functions can return a StreamError if the stream is canceled.
  60. type Stream interface {
  61. ReceiveStream
  62. SendStream
  63. // SetDeadline sets the read and write deadlines associated
  64. // with the connection. It is equivalent to calling both
  65. // SetReadDeadline and SetWriteDeadline.
  66. SetDeadline(t time.Time) error
  67. }
  68. // A ReceiveStream is a unidirectional Receive Stream.
  69. type ReceiveStream interface {
  70. // StreamID returns the stream ID.
  71. StreamID() StreamID
  72. // Read reads data from the stream.
  73. // Read can be made to time out and return a net.Error with Timeout() == true
  74. // after a fixed time limit; see SetDeadline and SetReadDeadline.
  75. // If the stream was canceled by the peer, the error implements the StreamError
  76. // interface, and Canceled() == true.
  77. // If the session was closed due to a timeout, the error satisfies
  78. // the net.Error interface, and Timeout() will be true.
  79. io.Reader
  80. // CancelRead aborts receiving on this stream.
  81. // It will ask the peer to stop transmitting stream data.
  82. // Read will unblock immediately, and future Read calls will fail.
  83. // When called multiple times or after reading the io.EOF it is a no-op.
  84. CancelRead(StreamErrorCode)
  85. // SetReadDeadline sets the deadline for future Read calls and
  86. // any currently-blocked Read call.
  87. // A zero value for t means Read will not time out.
  88. SetReadDeadline(t time.Time) error
  89. }
  90. // A SendStream is a unidirectional Send Stream.
  91. type SendStream interface {
  92. // StreamID returns the stream ID.
  93. StreamID() StreamID
  94. // Write writes data to the stream.
  95. // Write can be made to time out and return a net.Error with Timeout() == true
  96. // after a fixed time limit; see SetDeadline and SetWriteDeadline.
  97. // If the stream was canceled by the peer, the error implements the StreamError
  98. // interface, and Canceled() == true.
  99. // If the session was closed due to a timeout, the error satisfies
  100. // the net.Error interface, and Timeout() will be true.
  101. io.Writer
  102. // Close closes the write-direction of the stream.
  103. // Future calls to Write are not permitted after calling Close.
  104. // It must not be called concurrently with Write.
  105. // It must not be called after calling CancelWrite.
  106. io.Closer
  107. // CancelWrite aborts sending on this stream.
  108. // Data already written, but not yet delivered to the peer is not guaranteed to be delivered reliably.
  109. // Write will unblock immediately, and future calls to Write will fail.
  110. // When called multiple times or after closing the stream it is a no-op.
  111. CancelWrite(StreamErrorCode)
  112. // The context is canceled as soon as the write-side of the stream is closed.
  113. // This happens when Close() or CancelWrite() is called, or when the peer
  114. // cancels the read-side of their stream.
  115. // Warning: This API should not be considered stable and might change soon.
  116. Context() context.Context
  117. // SetWriteDeadline sets the deadline for future Write calls
  118. // and any currently-blocked Write call.
  119. // Even if write times out, it may return n > 0, indicating that
  120. // some of the data was successfully written.
  121. // A zero value for t means Write will not time out.
  122. SetWriteDeadline(t time.Time) error
  123. }
  124. // A Session is a QUIC connection between two peers.
  125. // Calls to the session (and to streams) can return the following types of errors:
  126. // * ApplicationError: for errors triggered by the application running on top of QUIC
  127. // * TransportError: for errors triggered by the QUIC transport (in many cases a misbehaving peer)
  128. // * IdleTimeoutError: when the peer goes away unexpectedly (this is a net.Error timeout error)
  129. // * HandshakeTimeoutError: when the cryptographic handshake takes too long (this is a net.Error timeout error)
  130. // * StatelessResetError: when we receive a stateless reset (this is a net.Error temporary error)
  131. // * VersionNegotiationError: returned by the client, when there's no version overlap between the peers
  132. type Session interface {
  133. // AcceptStream returns the next stream opened by the peer, blocking until one is available.
  134. // If the session was closed due to a timeout, the error satisfies
  135. // the net.Error interface, and Timeout() will be true.
  136. AcceptStream(context.Context) (Stream, error)
  137. // AcceptUniStream returns the next unidirectional stream opened by the peer, blocking until one is available.
  138. // If the session was closed due to a timeout, the error satisfies
  139. // the net.Error interface, and Timeout() will be true.
  140. AcceptUniStream(context.Context) (ReceiveStream, error)
  141. // OpenStream opens a new bidirectional QUIC stream.
  142. // There is no signaling to the peer about new streams:
  143. // The peer can only accept the stream after data has been sent on the stream.
  144. // If the error is non-nil, it satisfies the net.Error interface.
  145. // When reaching the peer's stream limit, err.Temporary() will be true.
  146. // If the session was closed due to a timeout, Timeout() will be true.
  147. OpenStream() (Stream, error)
  148. // OpenStreamSync opens a new bidirectional QUIC stream.
  149. // It blocks until a new stream can be opened.
  150. // If the error is non-nil, it satisfies the net.Error interface.
  151. // If the session was closed due to a timeout, Timeout() will be true.
  152. OpenStreamSync(context.Context) (Stream, error)
  153. // OpenUniStream opens a new outgoing unidirectional QUIC stream.
  154. // If the error is non-nil, it satisfies the net.Error interface.
  155. // When reaching the peer's stream limit, Temporary() will be true.
  156. // If the session was closed due to a timeout, Timeout() will be true.
  157. OpenUniStream() (SendStream, error)
  158. // OpenUniStreamSync opens a new outgoing unidirectional QUIC stream.
  159. // It blocks until a new stream can be opened.
  160. // If the error is non-nil, it satisfies the net.Error interface.
  161. // If the session was closed due to a timeout, Timeout() will be true.
  162. OpenUniStreamSync(context.Context) (SendStream, error)
  163. // LocalAddr returns the local address.
  164. LocalAddr() net.Addr
  165. // RemoteAddr returns the address of the peer.
  166. RemoteAddr() net.Addr
  167. // CloseWithError closes the connection with an error.
  168. // The error string will be sent to the peer.
  169. CloseWithError(ApplicationErrorCode, string) error
  170. // The context is cancelled when the session is closed.
  171. // Warning: This API should not be considered stable and might change soon.
  172. Context() context.Context
  173. // ConnectionState returns basic details about the QUIC connection.
  174. // It blocks until the handshake completes.
  175. // Warning: This API should not be considered stable and might change soon.
  176. ConnectionState() ConnectionState
  177. // SendMessage sends a message as a datagram.
  178. // See https://datatracker.ietf.org/doc/draft-pauly-quic-datagram/.
  179. SendMessage([]byte) error
  180. // ReceiveMessage gets a message received in a datagram.
  181. // See https://datatracker.ietf.org/doc/draft-pauly-quic-datagram/.
  182. ReceiveMessage() ([]byte, error)
  183. }
  184. // An EarlySession is a session that is handshaking.
  185. // Data sent during the handshake is encrypted using the forward secure keys.
  186. // When using client certificates, the client's identity is only verified
  187. // after completion of the handshake.
  188. type EarlySession interface {
  189. Session
  190. // Blocks until the handshake completes (or fails).
  191. // Data sent before completion of the handshake is encrypted with 1-RTT keys.
  192. // Note that the client's identity hasn't been verified yet.
  193. HandshakeComplete() context.Context
  194. NextSession() Session
  195. }
  196. // Config contains all configuration data needed for a QUIC server or client.
  197. type Config struct {
  198. // The QUIC versions that can be negotiated.
  199. // If not set, it uses all versions available.
  200. // Warning: This API should not be considered stable and will change soon.
  201. Versions []VersionNumber
  202. // The length of the connection ID in bytes.
  203. // It can be 0, or any value between 4 and 18.
  204. // If not set, the interpretation depends on where the Config is used:
  205. // If used for dialing an address, a 0 byte connection ID will be used.
  206. // If used for a server, or dialing on a packet conn, a 4 byte connection ID will be used.
  207. // When dialing on a packet conn, the ConnectionIDLength value must be the same for every Dial call.
  208. ConnectionIDLength int
  209. // HandshakeIdleTimeout is the idle timeout before completion of the handshake.
  210. // Specifically, if we don't receive any packet from the peer within this time, the connection attempt is aborted.
  211. // If this value is zero, the timeout is set to 5 seconds.
  212. HandshakeIdleTimeout time.Duration
  213. // MaxIdleTimeout is the maximum duration that may pass without any incoming network activity.
  214. // The actual value for the idle timeout is the minimum of this value and the peer's.
  215. // This value only applies after the handshake has completed.
  216. // If the timeout is exceeded, the connection is closed.
  217. // If this value is zero, the timeout is set to 30 seconds.
  218. MaxIdleTimeout time.Duration
  219. // AcceptToken determines if a Token is accepted.
  220. // It is called with token = nil if the client didn't send a token.
  221. // If not set, a default verification function is used:
  222. // * it verifies that the address matches, and
  223. // * if the token is a retry token, that it was issued within the last 5 seconds
  224. // * else, that it was issued within the last 24 hours.
  225. // This option is only valid for the server.
  226. AcceptToken func(clientAddr net.Addr, token *Token) bool
  227. // The TokenStore stores tokens received from the server.
  228. // Tokens are used to skip address validation on future connection attempts.
  229. // The key used to store tokens is the ServerName from the tls.Config, if set
  230. // otherwise the token is associated with the server's IP address.
  231. TokenStore TokenStore
  232. // InitialStreamReceiveWindow is the initial size of the stream-level flow control window for receiving data.
  233. // If the application is consuming data quickly enough, the flow control auto-tuning algorithm
  234. // will increase the window up to MaxStreamReceiveWindow.
  235. // If this value is zero, it will default to 512 KB.
  236. InitialStreamReceiveWindow uint64
  237. // MaxStreamReceiveWindow is the maximum stream-level flow control window for receiving data.
  238. // If this value is zero, it will default to 6 MB.
  239. MaxStreamReceiveWindow uint64
  240. // InitialConnectionReceiveWindow is the initial size of the stream-level flow control window for receiving data.
  241. // If the application is consuming data quickly enough, the flow control auto-tuning algorithm
  242. // will increase the window up to MaxConnectionReceiveWindow.
  243. // If this value is zero, it will default to 512 KB.
  244. InitialConnectionReceiveWindow uint64
  245. // MaxConnectionReceiveWindow is the connection-level flow control window for receiving data.
  246. // If this value is zero, it will default to 15 MB.
  247. MaxConnectionReceiveWindow uint64
  248. // MaxIncomingStreams is the maximum number of concurrent bidirectional streams that a peer is allowed to open.
  249. // Values above 2^60 are invalid.
  250. // If not set, it will default to 100.
  251. // If set to a negative value, it doesn't allow any bidirectional streams.
  252. MaxIncomingStreams int64
  253. // MaxIncomingUniStreams is the maximum number of concurrent unidirectional streams that a peer is allowed to open.
  254. // Values above 2^60 are invalid.
  255. // If not set, it will default to 100.
  256. // If set to a negative value, it doesn't allow any unidirectional streams.
  257. MaxIncomingUniStreams int64
  258. // The StatelessResetKey is used to generate stateless reset tokens.
  259. // If no key is configured, sending of stateless resets is disabled.
  260. StatelessResetKey []byte
  261. // KeepAlive defines whether this peer will periodically send a packet to keep the connection alive.
  262. KeepAlive bool
  263. // DisablePathMTUDiscovery disables Path MTU Discovery (RFC 8899).
  264. // Packets will then be at most 1252 (IPv4) / 1232 (IPv6) bytes in size.
  265. DisablePathMTUDiscovery bool
  266. // DisableVersionNegotiationPackets disables the sending of Version Negotiation packets.
  267. // This can be useful if version information is exchanged out-of-band.
  268. // It has no effect for a client.
  269. DisableVersionNegotiationPackets bool
  270. // See https://datatracker.ietf.org/doc/draft-ietf-quic-datagram/.
  271. // Datagrams will only be available when both peers enable datagram support.
  272. EnableDatagrams bool
  273. Tracer logging.Tracer
  274. // [Psiphon]
  275. // ClientHelloSeed is used for TLS Client Hello randomization and replay.
  276. ClientHelloSeed *prng.Seed
  277. // [Psiphon]
  278. // GetClientHelloRandom is used by the QUIC client to supply a specific
  279. // value in the TLS Client Hello random field. This is used to send an
  280. // anti-probing message, indistinguishable from random, that proves
  281. // knowlegde of a shared secret key.
  282. GetClientHelloRandom func() ([]byte, error)
  283. // [Psiphon]
  284. // VerifyClientHelloRandom is used by the QUIC server to verify that the
  285. // TLS Client Hello random field, supplied in the Initial packet for a
  286. // new connection, was created using the shared secret key and is not
  287. // replayed.
  288. VerifyClientHelloRandom func(net.Addr, []byte) bool
  289. // [Psiphon]
  290. // ClientMaxPacketSizeAdjustment indicates that the max packet size should
  291. // be reduced by the specified amount. This is used to reserve space for
  292. // packet obfuscation overhead while remaining at or under the 1280
  293. // initial target packet size as well as protocol.MaxPacketBufferSize,
  294. // the maximum packet size under MTU discovery.
  295. ClientMaxPacketSizeAdjustment int
  296. // [Psiphon]
  297. // ServerMaxPacketSizeAdjustment indicates that, for the flow associated
  298. // with the given client address, the max packet size should be reduced
  299. // by the specified amount. This is used to reserve space for packet
  300. // obfuscation overhead while remaining at or under the 1280 target
  301. // packet size. Must be set only for QUIC server configs.
  302. ServerMaxPacketSizeAdjustment func(net.Addr) int
  303. }
  304. // ConnectionState records basic details about a QUIC connection
  305. type ConnectionState struct {
  306. TLS handshake.ConnectionState
  307. SupportsDatagrams bool
  308. }
  309. // A Listener for incoming QUIC connections
  310. type Listener interface {
  311. // Close the server. All active sessions will be closed.
  312. Close() error
  313. // Addr returns the local network addr that the server is listening on.
  314. Addr() net.Addr
  315. // Accept returns new sessions. It should be called in a loop.
  316. Accept(context.Context) (Session, error)
  317. }
  318. // An EarlyListener listens for incoming QUIC connections,
  319. // and returns them before the handshake completes.
  320. type EarlyListener interface {
  321. // Close the server. All active sessions will be closed.
  322. Close() error
  323. // Addr returns the local network addr that the server is listening on.
  324. Addr() net.Addr
  325. // Accept returns new early sessions. It should be called in a loop.
  326. Accept(context.Context) (EarlySession, error)
  327. }