| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242 |
- /*
- * Copyright (c) 2023, Psiphon Inc.
- * All rights reserved.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
- package inproxy
- import (
- "context"
- "net"
- "time"
- )
- // RoundTripper provides a request/response round trip network transport with
- // blocking circumvention capabilities. A typical implementation is domain
- // fronted HTTPS. RoundTripper is used by clients and proxies to make
- // requests to brokers.
- type RoundTripper interface {
- RoundTrip(ctx context.Context, requestPayload []byte) (responsePayload []byte, err error)
- }
- // DialParameters provides in-proxy dial parameters and configuration, used by
- // both clients and proxies, and an interface for signaling when parameters
- // are successful or not, to facilitate replay of successful parameters.
- //
- // Each DialParameters should provide values selected in the context of a
- // single network, as identified by a network ID. A distinct DialParameters
- // should be created for each client in-proxy dial, with new or replayed
- // parameters selected as appropriate. One proxy run uses a single
- // DialParameters for all proxied connections. The proxy should be restarted
- // with a new DialParameters when the underlying network changes.
- type DialParameters interface {
- // CommonCompartmentIDs is the list of common, Psiphon-managed, in-proxy
- // compartment IDs known to a client. These IDs are delivered through
- // tactics, or embedded in OSLs.
- //
- // At most MaxCompartmentIDs may be sent to a broker; if necessary, the
- // provider may return a subset of known compartment IDs and replay when
- // the overall dial is a success; and/or retain only the most recently
- // discovered compartment IDs.
- //
- // CommonCompartmentIDs is not called for proxies.
- CommonCompartmentIDs() []ID
- // PersonalCompartmentIDs are compartment IDs distributed from proxy
- // operators to client users out-of-band and provide optional access
- // control. For example, a proxy operator may want to provide access only
- // to certain users, and/or users want to use only a proxy run by a
- // certain operator.
- //
- // At most MaxCompartmentIDs may be sent to a broker; for typical use
- // cases, both clients and proxies will specify a single personal
- // compartment ID.
- PersonalCompartmentIDs() []ID
- // Returns the network ID for the network this DialParameters is
- // associated with. For a single DialParameters, the NetworkID value
- // should not change. Replay-facilitating calls, Succeeded/Failed, all
- // assume the network and network ID remain static. The network ID value
- // is used by in-proxy dials to track internal state that depends on the
- // current network; this includes the port mapping types supported by the
- // network.
- NetworkID() string
- // Returns the network type for the current network, or NetworkTypeUnknown
- // if unknown.
- NetworkType() NetworkType
- // BrokerClientPrivateKey is the client or proxy's private key to be used
- // in the secure session established with a broker. Clients should
- // generate ephemeral keys; this is done automatically when a zero-value
- // SessionPrivateKey is returned. Proxies may generate, persist, and
- // long-lived keys to enable traffic attribution to a proxy, identified
- // by a proxy ID, the corresponding public key.
- BrokerClientPrivateKey() SessionPrivateKey
- // BrokerPublicKey is the public key for the broker selected by the
- // provider and reachable via BrokerClientRoundTripper. The broker is
- // authenticated in the secure session.
- BrokerPublicKey() SessionPublicKey
- // BrokerRootObfuscationSecret is the root obfuscation secret for the
- // broker and used in the secure session.
- BrokerRootObfuscationSecret() ObfuscationSecret
- // BrokerClientRoundTripper returns a RoundTripper to use for broker
- // requests. The provider handles selecting a broker and broker
- // addressing, as well as providing a round trip network transport with
- // blocking circumvention capabilities. A typical implementation is
- // domain fronted HTTPS. The RoundTripper should offer persistent network
- // connections and request multiplexing, for example with HTTP/2, so that
- // a single connection can be used for many concurrent requests.
- //
- // Clients and proxies make round trips to establish a secure session with
- // the broker, on top of the provided transport, and to exchange API
- // requests with the broker.
- BrokerClientRoundTripper() (RoundTripper, error)
- // BrokerClientRoundTripperSucceeded is called after a successful round
- // trip using the specified RoundTripper. This signal is used to set
- // replay for the round tripper's successful dial parameters.
- // BrokerClientRoundTripperSucceeded is called once per successful round
- // trip; the provider can choose to set replay only once.
- BrokerClientRoundTripperSucceeded(roundTripper RoundTripper)
- // BrokerClientRoundTripperSucceeded is called after a failed round trip
- // using the specified RoundTripper. This signal is used to clear replay
- // for the round tripper's unsuccessful dial parameters. The provider
- // will arrange for a new RoundTripper to be returned from the next
- // BrokerClientRoundTripper call, discarding the current RoundTripper
- // after closing its network resources.
- BrokerClientRoundTripperFailed(roundTripper RoundTripper)
- // ClientRootObfuscationSecret is the root obfuscation secret generated by
- // or replayed by the client, which will be used to drive and replay
- // obfuscation operations for the WebRTC dial, including any DTLS
- // randomization. The proxy receives the same root obfuscation secret,
- // relayed by the broker, and so the client's selection drives
- // obfuscation/replay on both sides.
- ClientRootObfuscationSecret() ObfuscationSecret
- // DoDTLSRandomization indicates whether to perform DTLS ClientHello
- // randomization. DoDTLSRandomization is specified by clients, which may
- // use a weighted coin flip or a replay to determine the value.
- DoDTLSRandomization() bool
- // STUNServerAddress selects a STUN server to use for this dial. When
- // RFC5780 is true, the STUN server must support RFC5780 NAT discovery;
- // otherwise, only basic STUN bind operation support is required. Clients
- // and proxies will receive a list of STUN server candidates via tactics,
- // and select a candidate at random or replay for each dial. If
- // STUNServerAddress returns "", STUN operations are skipped but the dial
- // may still succeed if a port mapping can be established.
- STUNServerAddress(RFC5780 bool) string
- // STUNServerAddressSucceeded is called after a successful STUN operation
- // with the STUN server specified by the address. This signal is used to
- // set replay for successful STUN servers. STUNServerAddressSucceeded
- // will be called when the STUN opertion succeeds, regardless of the
- // outcome of the rest of the dial. RFC5780 is true when the STUN server
- // was used for NAT discovery.
- STUNServerAddressSucceeded(RFC5780 bool, address string)
- // STUNServerAddressFailed is called after a failed STUN operation and is
- // used to clear replay for the specified STUN server.
- STUNServerAddressFailed(RFC5780 bool, address string)
- // DiscoverNAT indicates whether a client dial should start with NAT
- // discovery. Discovering and reporting the client NAT type will assist
- // in broker matching. However, RFC5780 NAT discovery can slow down a
- // dial and potentially looks like atypical network traffic. Client NAT
- // discovery is controlled by tactics and may be disabled or set to run
- // with a small probability. Discovered NAT types and portmapping types
- // may be cached and used with future dials via SetNATType/NATType and
- // SetPortMappingTypes/PortMappingTypes.
- //
- // Proxies always perform NAT discovery on start up, since that doesn't
- // delay a client dial.
- DiscoverNAT() bool
- // DisableSTUN indicates whether to skip STUN operations.
- DisableSTUN() bool
- // DisableSTUN indicates whether to skip port mapping operations.
- DisablePortMapping() bool
- // DisableInboundForMobleNetworks indicates that all attempts to set up
- // inbound operations -- including STUN and port mapping -- should be
- // skipped when the network type is NetworkTypeMobile. This skips
- // operations that can slow down dials and and unlikely to succeed on
- // most mobile networks with CGNAT.
- DisableInboundForMobleNetworks() bool
- // NATType returns any persisted NAT type for the current network, as set
- // by SetNATType. When NATTypeUnknown is returned, NAT discovery may be
- // run.
- NATType() NATType
- // SetNATType is called when the NAT type for the current network has been
- // discovered. The provider should persist this value, associated with
- // the current network ID and with a reasonable TTL, so the value can be
- // reused in subsequent dials without having to re-run NAT discovery.
- SetNATType(t NATType)
- // PortMappingTypes returns any persisted, supported port mapping types
- // for the current network, as set by SetPortMappingTypes. When an empty
- // list is returned port mapping discovery may be run. A list containing
- // only PortMappingTypeNone indicates that no supported port mapping
- // types were discovered.
- PortMappingTypes() PortMappingTypes
- // SetPortMappingTypes is called with the supported port mapping types
- // discovered for the current network. The provider should persist this
- // value, associated with the current network ID and with a reasonable
- // TTL, so the value can be reused in subsequent dials without having to
- // re-run port mapping discovery.
- SetPortMappingTypes(t PortMappingTypes)
- // ResolveAddress resolves a domain and returns its IP address. Clients
- // and proxies may use this to hook into the Psiphon custom resolver. The
- // provider adds the custom resolver tactics and network ID parameters
- // required by psiphon/common.Resolver.
- ResolveAddress(ctx context.Context, address string) (string, error)
- // UDPListen dials a local UDP socket. The socket should be bound to a
- // specific interface as required for VPN modes, and set a write timeout
- // to mitigate the issue documented in psiphon/common.WriteTimeoutUDPConn.
- UDPListen() (net.PacketConn, error)
- // BindToDevice binds a socket, specified by the file descriptor, to an
- // interface that isn't routed through a VPN when Psiphon is running in
- // VPN mode. BindToDevice is used in cases where a custom dialer cannot
- // be used, and UDPListen cannot be called.
- BindToDevice(fileDescriptor int) error
- DiscoverNATTimeout() time.Duration
- OfferRequestTimeout() time.Duration
- OfferRetryDelay() time.Duration
- OfferRetryJitter() float64
- AnnounceRequestTimeout() time.Duration
- AnnounceRetryDelay() time.Duration
- AnnounceRetryJitter() float64
- WebRTCAnswerTimeout() time.Duration
- AnswerRequestTimeout() time.Duration
- ProxyClientConnectTimeout() time.Duration
- ProxyDestinationDialTimeout() time.Duration
- }
|