psiphon

package
v0.0.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 20, 2024 License: GPL-3.0 Imports: 80 Imported by: 0

Documentation

Overview

Package psiphon implements the core tunnel functionality of a Psiphon client. The main function is RunForever, which runs a Controller that obtains lists of servers, establishes tunnel connections, and runs local proxies through which tunneled traffic may be sent.

Index

Constants

View Source
const (
	TUNNEL_POOL_SIZE     = 1
	MAX_TUNNEL_POOL_SIZE = 32

	// Psiphon data directory name, relative to config.DataRootDirectory.
	// See config.GetPsiphonDataDirectory().
	PsiphonDataDirectoryName = "ca.psiphon.PsiphonTunnel.tunnel-core"

	// Filename constants, all relative to config.GetPsiphonDataDirectory().
	HomepageFilename        = "homepage"
	NoticesFilename         = "notices"
	OldNoticesFilename      = "notices.1"
	UpgradeDownloadFilename = "upgrade"
)
View Source
const (
	URL_PROXY_TUNNELED_REQUEST_PATH         = "/tunneled/"
	URL_PROXY_TUNNELED_REWRITE_REQUEST_PATH = "/tunneled-rewrite/"
	URL_PROXY_TUNNELED_ICY_REQUEST_PATH     = "/tunneled-icy/"
	URL_PROXY_DIRECT_REQUEST_PATH           = "/direct/"
)
View Source
const (
	MEEK_PROTOCOL_VERSION           = 3
	MEEK_MAX_REQUEST_PAYLOAD_LENGTH = 65536
)
View Source
const (
	MeekModeRelay = iota
	MeekModeObfuscatedRoundTrip
	MeekModePlaintextRoundTrip
)
View Source
const (
	OPEN_DB_RETRIES = 2
)

Variables

This section is empty.

Functions

func ClearReportedPersistentStats

func ClearReportedPersistentStats(stats map[string][][]byte) error

ClearReportedPersistentStats deletes a list of persistent stat records that were successfully reported.

func ClientBPFEnabled

func ClientBPFEnabled() bool

func CloseDataStore

func CloseDataStore()

CloseDataStore closes the singleton datastore instance, if open.

func CountSLOKs

func CountSLOKs() int

CountSLOKs returns the total number of SLOK records.

func CountServerEntries

func CountServerEntries() int

CountServerEntries returns a count of stored server entries. On failure, CountServerEntries returns 0.

func CountUnreportedPersistentStats

func CountUnreportedPersistentStats() int

CountUnreportedPersistentStats returns the number of persistent stat records in StateUnreported.

func CustomTLSDial

func CustomTLSDial(
	ctx context.Context,
	network, addr string,
	config *CustomTLSConfig) (net.Conn, error)

CustomTLSDial dials a new TLS connection using the parameters set in CustomTLSConfig.

The dial aborts if ctx becomes Done before the dial completes.

func DecodeCertificate

func DecodeCertificate(encodedCertificate string) (certificate *x509.Certificate, err error)

func DeleteDialParameters

func DeleteDialParameters(serverIPAddress, networkID string) error

DeleteDialParameters clears any dial parameters associated with the specified server/network ID.

func DeleteNetworkReplayParameters

func DeleteNetworkReplayParameters[R any](networkID, replayID string) error

DeleteNetworkReplayParameters deletes the replay record associated with the specified context and object.

func DeleteSLOKs

func DeleteSLOKs() error

DeleteSLOKs deletes all SLOK records.

func DeleteServerEntry

func DeleteServerEntry(config *Config, ipAddress string)

DeleteServerEntry deletes the specified server entry and associated data.

func DeleteServerEntryAffinity

func DeleteServerEntryAffinity(ipAddress string) error

DeleteServerEntryAffinity clears server affinity if set to the specified server.

func DialTCP

func DialTCP(
	ctx context.Context, addr string, config *DialConfig) (net.Conn, error)

DialTCP creates a new, connected TCPConn.

func DoFileMigration

func DoFileMigration(migration FileMigration) error

DoFileMigration performs the specified file move operation. An error will be returned and the operation will not performed if: a file is expected, but a directory is found; a directory is expected, but a file is found; or a file, or directory, already exists at the target path of the move operation. Note: an attempt is made to redact any file paths from the returned error.

func DoGarbageCollection

func DoGarbageCollection()

func DownloadUpgrade

func DownloadUpgrade(
	ctx context.Context,
	config *Config,
	attempt int,
	handshakeVersion string,
	tunnel *Tunnel,
	untunneledDialConfig *DialConfig) error

DownloadUpgrade performs a resumable download of client upgrade files.

While downloading/resuming, a temporary file is used. Once the download is complete, a notice is issued and the upgrade is available at the destination specified in config.GetUpgradeDownloadFilename().

The upgrade download may be either tunneled or untunneled. As the untunneled case may happen with no handshake request response, the downloader cannot rely on having the upgrade_client_version output from handshake and instead this logic performs a comparison between the config.ClientVersion and the client version recorded in the remote entity's UpgradeDownloadClientVersionHeader. A HEAD request is made to check the version before proceeding with a full download.

NOTE: This code does not check that any existing file at config.GetUpgradeDownloadFilename() is actually the version specified in handshakeVersion.

TODO: This logic requires the outer client to *omit* config.UpgradeDownloadURLs, disabling upgrade downloads, when there's already a downloaded upgrade pending. This is because the outer client currently handles the authenticated package phase, and because the outer client deletes the intermediate files (including config.GetUpgradeDownloadFilename()). So if the outer client does not disable upgrade downloads then the new version will be downloaded repeatedly. Implement a new scheme where tunnel core does the authenticated package phase and tracks the the output by version number so that (a) tunnel core knows when it's not necessary to re-download; (b) newer upgrades will be downloaded even when an older upgrade is still pending install by the outer client.

func ExportExchangePayload

func ExportExchangePayload(config *Config) string

ExportExchangePayload creates a payload for client-to-client server connection info exchange. The payload includes the most recent successful server entry -- the server entry in the affinity position -- and any associated dial parameters, for the current network ID.

ExportExchangePayload is intended to be called when the client is connected, as the affinity server will be the currently connected server and there will be dial parameters for the current network ID.

Only signed server entries will be exchanged. The signature is created by the Psiphon Network and may be verified using the ServerEntrySignaturePublicKey embedded in clients. This signture defends against attacks by rogue clients and man-in-the-middle operatives which could otherwise cause the importer to receive phony server entry values.

Only a subset of dial parameters are exchanged. See the comment for ExchangedDialParameters for more details. When no dial parameters is present the exchange proceeds without dial parameters.

The exchange payload is obfuscated with the ExchangeObfuscationKey embedded in clients. The purpose of this obfuscation is to ensure that plaintext server entry info cannot be trivially exported and displayed or published; or at least require an effort equal to what's required without the export feature.

There is no success notice for exchange ExportExchangePayload (or ImportExchangePayload) as this would potentially leak a user releationship if two users performed and exchange and subseqently submit diagnostic feedback containg import and export logs at almost the same point in time, along with logs showing connections to the same server, with source "EXCHANGED" in the importer case.

Failure notices are logged as, presumably, the event will only appear on one end of the exchange and the error is potentially important diagnostics.

There remains some risk of user linkability from Connecting/ConnectedServer diagnostics and metrics alone, because the appearance of "EXCHANGED" may indicate an exchange event. But there are various degrees of ambiguity in this case in terms of determining the server entry was freshly exchanged; and with likely many users often connecting to any given server in a short time period.

The return value is a payload that may be exchanged with another client; when "", the export failed and a diagnostic notice has been logged.

func FetchCommonRemoteServerList

func FetchCommonRemoteServerList(
	ctx context.Context,
	config *Config,
	attempt int,
	tunnel *Tunnel,
	untunneledDialConfig *DialConfig) error

FetchCommonRemoteServerList downloads the common remote server list from config.RemoteServerListURLs. It validates its digital signature using the public key config.RemoteServerListSignaturePublicKey and parses the data field into ServerEntry records. config.GetRemoteServerListDownloadFilename() is the location to store the download. As the download is resumed after failure, this filename must be unique and persistent.

func FetchObfuscatedServerLists

func FetchObfuscatedServerLists(
	ctx context.Context,
	config *Config,
	attempt int,
	tunnel *Tunnel,
	untunneledDialConfig *DialConfig) error

FetchObfuscatedServerLists downloads the obfuscated remote server lists from config.ObfuscatedServerListRootURLs. It first downloads the OSL registry, and then downloads each seeded OSL advertised in the registry. All downloads are resumable, ETags are used to skip both an unchanged registry or unchanged OSL files, and when an individual download fails, the fetch proceeds if it can. Authenticated package digital signatures are validated using the public key config.RemoteServerListSignaturePublicKey. config.GetObfuscatedServerListDownloadDirectory() is the location to store the downloaded files. As downloads are resumed after failure, this directory must be unique and persistent.

func GetDataStoreMetrics

func GetDataStoreMetrics() string

GetDataStoreMetrics returns a string logging datastore metrics.

func GetEmitDiagnosticNotices

func GetEmitDiagnosticNotices() bool

GetEmitDiagnosticNotices returns the current state of emitting diagnostic notices.

func GetEmitNetworkParameters

func GetEmitNetworkParameters() bool

GetEmitNetworkParameters returns the current state of emitting network parameters.

func GetKeyValue

func GetKeyValue(key string) (string, error)

GetKeyValue retrieves the value for a given key. If not found, it returns an empty string value.

func GetNetworkType

func GetNetworkType(networkID string) string

GetNetworkType returns a network type name, suitable for metrics, which is derived from the network ID.

func GetNotice

func GetNotice(notice []byte) (
	noticeType string, payload map[string]interface{}, err error)

GetNotice receives a JSON encoded object and attempts to parse it as a Notice. The type is returned as a string and the payload as a generic map.

func GetSLOK

func GetSLOK(id []byte) ([]byte, error)

GetSLOK returns a SLOK key for the specified ID. The return value is nil if the SLOK is not found.

func GetSignedServerEntryFields

func GetSignedServerEntryFields(ipAddress string) (protocol.ServerEntryFields, error)

GetSignedServerEntryFields loads, from the datastore, the raw JSON server entry fields for the specified server entry.

The protocol.ServerEntryFields returned by GetSignedServerEntryFields will include all fields required to verify the server entry signature, including new fields added after the current client version, which do not get unmarshaled into protocol.ServerEntry.

func GetTactics

func GetTactics(ctx context.Context, config *Config)

GetTactics attempts to apply tactics, for the current network, to the given config. GetTactics first checks for unexpired stored tactics, which it will immediately return. If no unexpired stored tactics are found, tactics requests are attempted until the input context is cancelled.

Callers may pass in a context that is already done. In this case, stored tactics, when available, are applied but no request will be attempted.

Callers are responsible for ensuring that the input context eventually cancels, and should synchronize GetTactics calls to ensure no unintended concurrent fetch attempts occur.

GetTactics implements a limited workaround for multiprocess datastore synchronization, enabling, for example, SendFeedback in one process to access tactics as long as a Controller is not running in another process; and without blocking the Controller from starting. Accessing tactics is most critical for untunneled network operations; when a Controller is running, a tunnel may be used. See TacticsStorer for more details.

func GetUrlETag

func GetUrlETag(url string) (string, error)

GetUrlETag retrieves a previously stored an ETag for the specfied URL. If not found, it returns an empty string value.

func HandleAlertRequest

func HandleAlertRequest(
	tunnelOwner TunnelOwner, tunnel *Tunnel, request *ssh.Request) (retErr error)

func HandleOSLRequest

func HandleOSLRequest(
	tunnelOwner TunnelOwner, tunnel *Tunnel, request *ssh.Request) (retErr error)

func HandleServerRequest

func HandleServerRequest(
	tunnelOwner TunnelOwner, tunnel *Tunnel, request *ssh.Request)

func HasServerEntries

func HasServerEntries() bool

HasServerEntries returns a bool indicating if the data store contains at least one server entry. This is a faster operation than CountServerEntries. On failure, HasServerEntries returns false.

func ImportEmbeddedServerEntries

func ImportEmbeddedServerEntries(
	ctx context.Context,
	config *Config,
	embeddedServerEntryListFilename string,
	embeddedServerEntryList string) error

ImportEmbeddedServerEntries loads, decodes, and stores a list of server entries. If embeddedServerEntryListFilename is not empty, embeddedServerEntryList will be ignored and the encoded server entry list will be loaded from the specified file. The import process stops early if ctx becomes done; any server entries imported up to that point are retained.

func ImportExchangePayload

func ImportExchangePayload(config *Config, encodedPayload string) bool

ImportExchangePayload imports a payload generated by ExportExchangePayload. The server entry in the payload is promoted to the affinity position so it will be the first candidate in any establishment that begins after the import.

The current network ID. This may not be the same network as the exporter, even if the client-to-client exchange occurs in real time. For example, if the exchange is performed over NFC between two devices, they may be on different mobile or WiFi networks. As mentioned in the comment for ExchangedDialParameters, the exchange dial parameters includes only the most broadly applicable fields.

The return value indicates a successful import. If the import failed, a a diagnostic notice has been logged.

func IsAddressInUseError

func IsAddressInUseError(err error) bool

IsAddressInUseError returns true when the err is due to EADDRINUSE/WSAEADDRINUSE.

func IsInproxyCompatibleNetworkType

func IsInproxyCompatibleNetworkType(networkID string) bool

IsInproxyCompatibleNetworkType indicates if the network type for the given network ID is compatible with in-proxy operation.

func IsTLSConnUsingHTTP2

func IsTLSConnUsingHTTP2(conn net.Conn) bool

func LoadInproxyCommonCompartmentIDs

func LoadInproxyCommonCompartmentIDs() ([]string, error)

LoadInproxyCommonCompartmentIDs returns the list of known, persisted in-proxy common compartment IDs. LoadInproxyCommonCompartmentIDs will return nil, nil when there is no stored list.

func LocalProxyRelay

func LocalProxyRelay(config *Config, proxyType string, localConn, remoteConn net.Conn)

LocalProxyRelay sends to remoteConn bytes received from localConn, and sends to localConn bytes received from remoteConn.

LocalProxyRelay must close localConn in order to interrupt blocking I/O calls when the upstream port forward is closed. remoteConn is also closed before returning.

func MakeCompatibleServerEntry

func MakeCompatibleServerEntry(serverEntry *protocol.ServerEntry) *protocol.ServerEntry

MakeCompatibleServerEntry provides backwards compatibility with old server entries which have a single meekFrontingDomain and not a meekFrontingAddresses array. By copying this one meekFrontingDomain into meekFrontingAddresses, this client effectively uses that single value as legacy clients do.

func MakeDownloadHTTPClient

func MakeDownloadHTTPClient(
	ctx context.Context,
	config *Config,
	tunnel *Tunnel,
	untunneledDialConfig *DialConfig,
	skipVerify,
	disableSystemRootCAs bool,
	frontingSpecs parameters.FrontingSpecs,
	selectedFrontingProviderID func(string)) (*http.Client, bool, func() common.APIParameters, error)

MakeDownloadHTTPClient is a helper that sets up a http.Client for use either untunneled or through a tunnel. True is returned if the http.Client is setup for use through a tunnel; otherwise it is setup for untunneled use. A function is returned which, if non-nil, can be called after each request made with the http.Client completes to retrieve the set of API parameter values applied to the request.

func MakePsiphonUserAgent

func MakePsiphonUserAgent(config *Config) string

MakePsiphonUserAgent constructs a User-Agent value to use for web service requests made by the tunnel-core client. The User-Agent includes useful stats information; it is to be used only for HTTPS requests, where the header cannot be seen by an adversary.

func MakeSessionId

func MakeSessionId() (string, error)

MakeSessionId creates a new session ID. The same session ID is used across multi-tunnel controller runs, where each tunnel has its own ServerContext instance. In server-side stats, we now consider a "session" to be the lifetime of the Controller (e.g., the user's commanded start and stop) and we measure this duration as well as the duration of each tunnel within the session.

func MakeTunneledHTTPClient

func MakeTunneledHTTPClient(
	ctx context.Context,
	config *Config,
	tunnel *Tunnel,
	skipVerify bool,
	disableSystemRootCAs bool,
	frontingSpecs parameters.FrontingSpecs,
	selectedFrontingProviderID func(string)) (*http.Client, func() common.APIParameters, error)

MakeTunneledHTTPClient returns a net/http.Client which is configured to use custom dialing features including tunneled dialing and, optionally, UseTrustedCACertificatesForStockTLS. This http.Client uses stock TLS for HTTPS.

func MakeUntunneledHTTPClient

func MakeUntunneledHTTPClient(
	ctx context.Context,
	config *Config,
	untunneledDialConfig *DialConfig,
	skipVerify bool,
	disableSystemRootCAs bool,
	frontingSpecs parameters.FrontingSpecs,
	selectedFrontingProviderID func(string)) (*http.Client, func() common.APIParameters, error)

MakeUntunneledHTTPClient returns a net/http.Client which is configured to use custom dialing features -- including BindToDevice, etc. A function is returned which, if non-nil, can be called after each request made with the net/http.Client completes to retrieve the set of API parameter values applied to the request.

The context is applied to underlying TCP dials. The caller is responsible for applying the context to requests made with the returned http.Client.

func NewCustomTLSDialer

func NewCustomTLSDialer(config *CustomTLSConfig) common.Dialer

NewCustomTLSDialer creates a new dialer based on CustomTLSDial.

func NewReadCloseSignaller

func NewReadCloseSignaller(
	context context.Context,
	reader io.Reader) *readCloseSignaller

func NewResolver

func NewResolver(config *Config, useBindToDevice bool) *resolver.Resolver

New Resolver creates a new resolver using the specified config. useBindToDevice indicates whether to apply config.BindToDevice, when it exists; set useBindToDevice to false when the resolve doesn't need to be excluded from any VPN routing.

func NewTCPDialer

func NewTCPDialer(config *DialConfig) common.Dialer

NewTCPDialer creates a TCP Dialer.

Note: do not set an UpstreamProxyURL in the config when using NewTCPDialer as a custom dialer for NewProxyAuthTransport (or http.Transport with a ProxyUrl), as that would result in double proxy chaining.

func NewTLSFragmentorConn

func NewTLSFragmentorConn(
	conn net.Conn,
) net.Conn

func NewUDPConn

func NewUDPConn(
	ctx context.Context,
	network string,
	dial bool,
	laddr string,
	raddr string,
	config *DialConfig) (*net.UDPConn, *net.UDPAddr, error)

NewUDPConn resolves raddr and configures a new *net.UDPConn. The UDP socket is created using options in DialConfig, including DeviceBinder. The returned UDPAddr uses DialConfig options IPv6Synthesizer and ResolvedIPCallback.

The network input may be "udp", "udp4", or "udp6". When "udp4" or "udp6" is specified, the raddr host IP address or resolved domain addresses must include IP address of the corresponding type.

If laddr is specified, the UDP socket is bound to that local address. Any laddr host must be an IP address.

If useDial is specified, the UDP socket is "connected" to the raddr remote address; otherwise the UDP socket is "unconnected", and each write (WriteTo) can specify an arbitrary remote address.

The caller should wrap the returned conn with common.WriteTimeoutUDPConn, as appropriate.

The returned conn is not a common.Closer; the caller is expected to wrap this conn with another higher-level conn that provides that interface.

func NoticeActiveAuthorizationIDs

func NoticeActiveAuthorizationIDs(diagnosticID string, activeAuthorizationIDs []string)

NoticeActiveAuthorizationIDs reports the authorizations the server has accepted. Each ID is a base64-encoded accesscontrol.Authorization.ID value.

func NoticeActiveTunnel

func NoticeActiveTunnel(diagnosticID, protocol string, isTCS bool)

NoticeActiveTunnel is a successful connection that is used as an active tunnel for port forwarding

func NoticeApplicationParameters

func NoticeApplicationParameters(keyValues parameters.KeyValues)

NoticeApplicationParameters reports application parameters.

func NoticeAvailableEgressRegions

func NoticeAvailableEgressRegions(regions []string)

NoticeAvailableEgressRegions is what regions are available for egress from. Consecutive reports of the same list of regions are suppressed.

func NoticeBindToDevice

func NoticeBindToDevice(deviceInfo string)

func NoticeBuildInfo

func NoticeBuildInfo()

NoticeBuildInfo reports build version info.

func NoticeBursts

func NoticeBursts(diagnosticID string, burstMetrics common.LogFields)

NoticeBursts reports tunnel data transfer burst metrics.

func NoticeBytesTransferred

func NoticeBytesTransferred(diagnosticID string, sent, received int64)

NoticeBytesTransferred reports how many tunneled bytes have been transferred since the last NoticeBytesTransferred. This is not a diagnostic notice: the user app has requested this notice with EmitBytesTransferred for functionality such as traffic display; and this frequent notice is not intended to be included with feedback. The noticeIsNotDiagnostic flag ensures that these notices are emitted to the host application but not written to the diagnostic file to avoid cluttering it with frequent updates.

func NoticeCandidateServers

func NoticeCandidateServers(
	region string,
	constraints *protocolSelectionConstraints,
	initialCount int,
	count int,
	duration time.Duration)

NoticeCandidateServers is how many possible servers are available for the selected region and protocols

func NoticeClientAddress

func NoticeClientAddress(address string)

NoticeClientAddress is the client's public network address, the IP address and port, as seen by the server and reported to the client in the handshake.

Note: "address" should remain private and not included in diagnostics logs.

func NoticeClientIsLatestVersion

func NoticeClientIsLatestVersion(availableVersion string)

NoticeClientIsLatestVersion reports that an upgrade check was made and the client is already the latest version. availableVersion is the version available for download, if known.

func NoticeClientRegion

func NoticeClientRegion(region string)

NoticeClientRegion is the client's region, as determined by the server and reported to the client in the handshake.

func NoticeClientUpgradeAvailable

func NoticeClientUpgradeAvailable(version string)

NoticeClientUpgradeAvailable is an available client upgrade, as per the handshake. The client should download and install an upgrade.

func NoticeClientUpgradeDownloaded

func NoticeClientUpgradeDownloaded(filename string)

NoticeClientUpgradeDownloaded indicates that a client upgrade download is complete and available at the destination specified.

func NoticeClientUpgradeDownloadedBytes

func NoticeClientUpgradeDownloadedBytes(bytes int64)

NoticeClientUpgradeDownloadedBytes reports client upgrade download progress.

func NoticeCommonLogger

func NoticeCommonLogger(debugLogging bool) common.Logger

NoticeCommonLogger maps the common.Logger interface to the notice facility. This is used to make the notice facility available to other packages that don't import the "psiphon" package.

func NoticeConnectedServer

func NoticeConnectedServer(dialParams *DialParameters)

NoticeConnectedServer reports parameters and details for a single successful connection

func NoticeConnectedServerRegion

func NoticeConnectedServerRegion(serverRegion string)

NoticeConnectedServerRegion reports the region of the connected server

func NoticeConnectingServer

func NoticeConnectingServer(dialParams *DialParameters)

NoticeConnectingServer reports parameters and details for a single connection attempt

func NoticeError

func NoticeError(format string, args ...interface{})

NoticeError is an error message; typically an unrecoverable error condition

func NoticeEstablishTunnelTimeout

func NoticeEstablishTunnelTimeout(timeout time.Duration)

NoticeEstablishTunnelTimeout reports that the configured EstablishTunnelTimeout duration was exceeded.

func NoticeExiting

func NoticeExiting()

NoticeExiting indicates that tunnel-core is exiting imminently.

func NoticeFragmentor

func NoticeFragmentor(diagnosticID string, message string)

func NoticeHoldOffTunnel

func NoticeHoldOffTunnel(diagnosticID string, duration time.Duration)

NoticeHoldOffTunnel reports tunnel hold-offs.

func NoticeHomepages

func NoticeHomepages(urls []string)

NoticeHomepages emits a series of NoticeHomepage, the sponsor homepages. The client should display the sponsor's homepages.

func NoticeHttpProxyPortInUse

func NoticeHttpProxyPortInUse(port int)

NoticeHttpProxyPortInUse is a failure to use the configured LocalHttpProxyPort

func NoticeInfo

func NoticeInfo(format string, args ...interface{})

NoticeInfo is an informational message

func NoticeInproxyOperatorMessage

func NoticeInproxyOperatorMessage(messageJSON string)

NoticeInproxyOperatorMessage emits a message to be displayed to the proxy operator.

func NoticeInproxyProxyActivity

func NoticeInproxyProxyActivity(
	connectingClients int32,
	connectedClients int32,
	bytesUp int64,
	bytesDown int64)

NoticeInproxyProxyActivity reports proxy usage statistics. The stats are for activity since the last NoticeInproxyProxyActivity report.

This is not a diagnostic notice: the user app has requested this notice with EmitproxyActivity for functionality such as traffic display; and this frequent notice is not intended to be included with feedback.

func NoticeInproxyProxyTotalActivity

func NoticeInproxyProxyTotalActivity(
	connectingClients int32,
	connectedClients int32,
	totalBytesUp int64,
	totalBytesDown int64)

NoticeInproxyProxyTotalActivity reports how many proxied bytes have been transferred in total up to this point; in addition to current connection status. This is a diagnostic notice.

func NoticeListeningHttpProxyPort

func NoticeListeningHttpProxyPort(port int)

NoticeListeningHttpProxyPort is the selected port for the listening local HTTP proxy

func NoticeListeningSocksProxyPort

func NoticeListeningSocksProxyPort(port int)

NoticeListeningSocksProxyPort is the selected port for the listening local SOCKS proxy

func NoticeLivenessTest

func NoticeLivenessTest(diagnosticID string, metrics *livenessTestMetrics, success bool)

func NoticeLocalProxyError

func NoticeLocalProxyError(proxyType string, err error)

NoticeLocalProxyError reports a local proxy error message. Repetitive errors for a given proxy type are suppressed.

func NoticeNetworkID

func NoticeNetworkID(networkID string)

func NoticePruneServerEntry

func NoticePruneServerEntry(serverEntryTag string)

func NoticeRemoteServerListResourceDownloaded

func NoticeRemoteServerListResourceDownloaded(url string)

NoticeRemoteServerListResourceDownloaded indicates that a remote server list download completed successfully.

func NoticeRemoteServerListResourceDownloadedBytes

func NoticeRemoteServerListResourceDownloadedBytes(url string, bytes int64, duration time.Duration)

NoticeRemoteServerListResourceDownloadedBytes reports remote server list download progress.

func NoticeRequestedTactics

func NoticeRequestedTactics(dialParams *DialParameters)

NoticeRequestedTactics reports parameters and details for a successful tactics request

func NoticeRequestingTactics

func NoticeRequestingTactics(dialParams *DialParameters)

NoticeRequestingTactics reports parameters and details for a tactics request attempt

func NoticeSLOKSeeded

func NoticeSLOKSeeded(slokID string, duplicate bool)

NoticeSLOKSeeded indicates that the SLOK with the specified ID was received from the Psiphon server. The "duplicate" flags indicates whether the SLOK was previously known.

func NoticeServerAlert

func NoticeServerAlert(alert protocol.AlertRequest)

NoticeServerAlert reports server alerts. Each distinct server alert is reported at most once per session.

func NoticeServerTimestamp

func NoticeServerTimestamp(diagnosticID string, timestamp string)

NoticeServerTimestamp reports server side timestamp as seen in the handshake.

func NoticeSessionId

func NoticeSessionId(sessionId string)

NoticeSessionId is the session ID used across all tunnels established by the controller.

func NoticeSkipServerEntry

func NoticeSkipServerEntry(format string, args ...interface{})

NoticeSkipServerEntry reports a reason for skipping a server entry when preparing dial parameters. To avoid log noise, the server entry diagnosticID is not emitted and each reason is reported at most once per session.

func NoticeSocksProxyPortInUse

func NoticeSocksProxyPortInUse(port int)

NoticeSocksProxyPortInUse is a failure to use the configured LocalSocksProxyPort

func NoticeSplitTunnelRegions

func NoticeSplitTunnelRegions(regions []string)

NoticeSplitTunnelRegions reports that split tunnel is on for the given country codes.

func NoticeTotalBytesTransferred

func NoticeTotalBytesTransferred(diagnosticID string, sent, received int64)

NoticeTotalBytesTransferred reports how many tunneled bytes have been transferred in total up to this point. This is a diagnostic notice.

func NoticeTrafficRateLimits

func NoticeTrafficRateLimits(
	diagnosticID string, upstreamBytesPerSecond, downstreamBytesPerSecond int64)

NoticeTrafficRateLimits reports the tunnel traffic rate limits in place for this client, as reported by the server at the start of the tunnel. Values of 0 indicate no limit. Values of -1 indicate that the server did not report rate limits.

Limitation: any rate limit changes during the lifetime of the tunnel are not reported.

func NoticeTunnels

func NoticeTunnels(count int)

NoticeTunnels is how many active tunnels are available. The client should use this to determine connecting/unexpected disconnect state transitions. When count is 0, the core is disconnected; when count > 1, the core is connected.

func NoticeUntunneled

func NoticeUntunneled(address string)

NoticeUntunneled indicates than an address has been classified as untunneled and is being accessed directly.

Note: "address" should remain private; this notice should only be used for alerting users, not for diagnostics logs.

func NoticeUpstreamProxyError

func NoticeUpstreamProxyError(err error)

NoticeUpstreamProxyError reports an error when connecting to an upstream proxy. The user may have input, for example, an incorrect address or incorrect credentials.

func NoticeUserLog

func NoticeUserLog(message string)

NoticeUserLog is a log message from the outer client user of tunnel-core

func NoticeWarning

func NoticeWarning(format string, args ...interface{})

NoticeWarning is a warning message; typically a recoverable error condition

func OpenDataStore

func OpenDataStore(config *Config) error

OpenDataStore opens and initializes the singleton datastore instance.

Nested Open/CloseDataStore calls are supported: OpenDataStore will succeed when called when the datastore is initialized. Every call to OpenDataStore must be paired with a corresponding call to CloseDataStore to ensure the datastore is closed.

func OpenDataStoreWithoutRetry

func OpenDataStoreWithoutRetry(config *Config) error

OpenDataStoreWithoutRetry performs an OpenDataStore but does not retry or reset the datastore file in case of failures. Use OpenDataStoreWithoutRetry when the datastore is expected to be locked by another process and faster failure is preferred.

func PromoteServerEntry

func PromoteServerEntry(config *Config, ipAddress string) error

PromoteServerEntry sets the server affinity server entry ID to the specified server entry IP address.

func PruneServerEntry

func PruneServerEntry(config *Config, serverEntryTag string)

PruneServerEntry deletes the server entry, along with associated data, corresponding to the specified server entry tag. Pruning is subject to an age check. In the case of an error, a notice is emitted.

func PutBackUnreportedPersistentStats

func PutBackUnreportedPersistentStats(stats map[string][][]byte) error

PutBackUnreportedPersistentStats restores a list of persistent stat records to StateUnreported.

func RecordFailedTunnelStat

func RecordFailedTunnelStat(
	config *Config,
	dialParams *DialParameters,
	livenessTestMetrics *livenessTestMetrics,
	bytesUp int64,
	bytesDown int64,
	tunnelErr error) error

RecordFailedTunnelStat records metrics for a failed tunnel dial, including dial parameters and error condition (tunnelErr). No record is created when tunnelErr is nil.

This uses the same reporting facility, with the same caveats, as RecordRemoteServerListStat.

func RecordRemoteServerListStat

func RecordRemoteServerListStat(
	config *Config,
	tunneled bool,
	url string,
	etag string,
	bytes int64,
	duration time.Duration,
	authenticated bool,
	additionalParameters common.APIParameters) error

RecordRemoteServerListStat records a completed common or OSL remote server list resource download.

The RSL download event could occur when the client is unable to immediately send a status request to a server, so these records are stored in the persistent datastore and reported via subsequent status requests sent to any Psiphon server.

Note that some common event field values may change between the stat recording and reporting, including client geolocation and host_id.

The bytes/duration fields reflect the size and download time for the _last chunk only_ in the case of a resumed download. The purpose of these fields is to calculate rough data transfer rates. Both bytes and duration are included in the log, to allow for filtering out of small transfers which may not produce accurate rate numbers.

Multiple "status" requests may be in flight at once (due to multi-tunnel, asynchronous final status retry, and aggressive status requests for pre-registered tunnels), To avoid duplicate reporting, persistent stats records are "taken-out" by a status request and then "put back" in case the request fails.

Duplicate reporting may also occur when a server receives and processes a status request but the client fails to receive the response.

func RelayCopyBuffer

func RelayCopyBuffer(config *Config, dst io.Writer, src io.Reader) (int64, error)

RelayCopyBuffer performs an io.Copy, optionally using a smaller buffer when config.LimitRelayBufferSizes is set.

func ResetRepetitiveNotices

func ResetRepetitiveNotices()

ResetRepetitiveNotices resets the repetitive notice state, so the next instance of any notice will not be supressed.

func ResumeDownload

func ResumeDownload(
	ctx context.Context,
	httpClient *http.Client,
	downloadURL string,
	userAgent string,
	downloadFilename string,
	ifNoneMatchETag string) (int64, string, error)

ResumeDownload is a reusable helper that downloads requestUrl via the httpClient, storing the result in downloadFilename when the download is complete. Intermediate, partial downloads state is stored in downloadFilename.part and downloadFilename.part.etag. Any existing downloadFilename file will be overwritten.

In the case where the remote object has changed while a partial download is to be resumed, the partial state is reset and resumeDownload fails. The caller must restart the download.

When ifNoneMatchETag is specified, no download is made if the remote object has the same ETag. ifNoneMatchETag has an effect only when no partial download is in progress.

func ScanServerEntries

func ScanServerEntries(callback func(*protocol.ServerEntry) bool) error

ScanServerEntries iterates over all stored server entries, unmarshals each, and passes it to callback for processing. If callback returns false, the iteration is cancelled and an error is returned.

ScanServerEntries may be slow to execute, particularly for older devices and/or very large server lists. Callers should avoid blocking on ScanServerEntries where possible; and use the canel option to interrupt scans that are no longer required.

func SelectTLSProfile

func SelectTLSProfile(
	requireTLS12SessionTickets bool,
	requireTLS13Support bool,
	isFronted bool,
	frontingProviderID string,
	p parameters.ParametersAccessor) (tlsProfile, tlsVersion string, randomizedTLSProfileSeed *prng.Seed, err error)

SelectTLSProfile picks and returns a TLS profile at random from the available candidates along with its version and a newly generated PRNG seed if the profile is randomized, i.e. protocol.TLSProfileIsRandomized is true, which should be used when generating a randomized TLS ClientHello.

func SendFeedback

func SendFeedback(ctx context.Context, config *Config, diagnostics, uploadPath string) error

Encrypt feedback and upload to server. If upload fails the routine will sleep and retry multiple times.

func SetDialParameters

func SetDialParameters(serverIPAddress, networkID string, dialParams *DialParameters) error

SetDialParameters stores dial parameters associated with the specified server/network ID.

func SetEmitDiagnosticNotices

func SetEmitDiagnosticNotices(
	emitDiagnostics bool, emitNetworkParameters bool)

SetEmitDiagnosticNotices toggles whether diagnostic notices are emitted; and whether to include circumvention network parameters in diagnostics.

Diagnostic notices contain potentially sensitive user information; and sensitive circumvention network parameters, when enabled. Only enable this in environments where notices are handled securely (for example, don't include these notices in log files which users could post to public forums).

func SetKeyValue

func SetKeyValue(key, value string) error

SetKeyValue stores a key/value pair.

func SetNetworkReplayParameters

func SetNetworkReplayParameters[R any](networkID, replayID string, replayParams *R) error

SetNetworkReplayParameters stores replay parameters associated with the specified context and object.

Limitation: unlike server dial parameters, the datastore does not prune replay records.

func SetNoticeWriter

func SetNoticeWriter(writer io.Writer)

SetNoticeWriter sets a target writer to receive notices. By default, notices are written to stderr. Notices are newline delimited.

writer specifies an alternate io.Writer where notices are to be written.

Notices are encoded in JSON. Here's an example:

{"data":{"message":"shutdown operate tunnel"},"noticeType":"Info","timestamp":"2006-01-02T15:04:05.999999999Z07:00"}

All notices have the following fields: - "noticeType": the type of notice, which indicates the meaning of the notice along with what's in the data payload. - "data": additional structured data payload. For example, the "ListeningSocksProxyPort" notice type has a "port" integer data in its payload. - "timestamp": UTC timezone, RFC3339Milli format timestamp for notice event

See the Notice* functions for details on each notice meaning and payload.

func SetSLOK

func SetSLOK(id, slok []byte) (bool, error)

SetSLOK stores a SLOK key, referenced by its ID. The bool return value indicates whether the SLOK was already stored.

func SetUrlETag

func SetUrlETag(url, etag string) error

SetUrlETag stores an ETag for the specfied URL. Note: input URL is treated as a string, and is not encoded or decoded or otherwise canonicalized.

func ShuffleAndGetNetworkReplayParameters

func ShuffleAndGetNetworkReplayParameters[C, R any](
	networkID string,
	replayEnabled bool,
	candidates []*C,
	getReplayID func(*C) string,
	isValidReplay func(*C, *R) bool) (*C, *R, error)

ShuffleAndGetNetworkReplayParameters takes a list of candidate objects and selects one. The candidates are considered in random order. The first candidate with a valid replay record is returned, along with its replay parameters. The caller provides isValidReplay which should indicate if replay parameters remain valid; the caller should check for expiry and changes to the underlhying tactics. When no valid replay parameters are found, ShuffleAndGetNetworkReplayParameters returns a candidate and nil replay parameters.

func StoreInproxyCommonCompartmentIDs

func StoreInproxyCommonCompartmentIDs(compartmentIDs []string) error

StoreInproxyCommonCompartmentIDs stores a list of in-proxy common compartment IDs. Clients obtain common compartment IDs from tactics; persisting the IDs enables a scheme whereby existing clients may continue to use common compartment IDs, and access the related in-proxy proxy matches, even after the compartment IDs are de-listed from tactics.

The caller is responsible for merging new and existing compartment IDs into the input list, and trimming the length of the list appropriately.

func StorePersistentStat

func StorePersistentStat(config *Config, statType string, stat []byte) error

StorePersistentStat adds a new persistent stat record, which is set to StateUnreported and is an immediate candidate for reporting.

The stat is a JSON byte array containing fields as required by the Psiphon server API. It's assumed that the JSON value contains enough unique information for the value to function as a key in the key/value datastore.

Only up to PersistentStatsMaxStoreRecords are stored. Once this limit is reached, new records are discarded.

func StoreServerEntries

func StoreServerEntries(
	config *Config,
	serverEntries []protocol.ServerEntryFields,
	replaceIfExists bool) error

StoreServerEntries stores a list of server entries. There is an independent transaction for each entry insert/update.

func StoreServerEntry

func StoreServerEntry(serverEntryFields protocol.ServerEntryFields, replaceIfExists bool) error

StoreServerEntry adds the server entry to the datastore.

When a server entry already exists for a given server, it will be replaced only if replaceIfExists is set or if the the ConfigurationVersion field of the new entry is strictly higher than the existing entry.

If the server entry data is malformed, an alert notice is issued and the entry is skipped; no error is returned.

func StreamingStoreServerEntries

func StreamingStoreServerEntries(
	ctx context.Context,
	config *Config,
	serverEntries *protocol.StreamingServerEntryDecoder,
	replaceIfExists bool) error

StreamingStoreServerEntries stores a list of server entries. There is an independent transaction for each entry insert/update. StreamingStoreServerEntries stops early and returns an error if ctx becomes done; any server entries stored up to that point are retained.

func TakeOutUnreportedPersistentStats

func TakeOutUnreportedPersistentStats(config *Config) (map[string][][]byte, error)

TakeOutUnreportedPersistentStats returns persistent stats records that are in StateUnreported. At least one record, if present, will be returned and then additional records up to PersistentStatsMaxSendBytes. The records are set to StateReporting. If the records are successfully reported, clear them with ClearReportedPersistentStats. If the records are not successfully reported, restore them with PutBackUnreportedPersistentStats.

func TrimError

func TrimError(err error) error

TrimError removes the middle of over-long error message strings

func UntunneledResolveIP

func UntunneledResolveIP(
	ctx context.Context,
	config *Config,
	resolver *resolver.Resolver,
	hostname string,
	frontingProviderID string) ([]net.IP, error)

UntunneledResolveIP is used to resolve domains for untunneled dials, including remote server list and upgrade downloads.

func WaitForNetworkConnectivity

func WaitForNetworkConnectivity(
	ctx context.Context, connectivityChecker NetworkConnectivityChecker) bool

WaitForNetworkConnectivity uses a NetworkConnectivityChecker to periodically check for network connectivity. It returns true if no NetworkConnectivityChecker is provided (waiting is disabled) or when NetworkConnectivityChecker.HasNetworkConnectivity() indicates connectivity. It waits and polls the checker once a second. When the context is done, false is returned immediately.

Types

type Config

type Config struct {

	// DataRootDirectory is the directory in which to store persistent files,
	// which contain information such as server entries. By default, current
	// working directory.
	//
	// Psiphon will assume full control of files under this directory. They may
	// be deleted, moved or overwritten.
	DataRootDirectory string

	// UseNoticeFiles configures notice files for writing. If set, homepages
	// will be written to a file created at config.GetHomePageFilename()
	// and notices will be written to a file created at
	// config.GetNoticesFilename().
	//
	// The homepage file may be read after the Tunnels notice with count of 1.
	//
	// The value of UseNoticeFiles sets the size and frequency at which the
	// notices file, config.GetNoticesFilename(), will be rotated. See the
	// comment for UseNoticeFiles for more details. One rotated older file,
	// config.GetOldNoticesFilename(), is retained.
	//
	// The notice files may be may be read at any time; and should be opened
	// read-only for reading. Diagnostic notices are omitted from the notice
	// files.
	//
	// See comment for setNoticeFiles in notice.go for further details.
	UseNoticeFiles *UseNoticeFiles

	// PropagationChannelId is a string identifier which indicates how the
	// Psiphon client was distributed. This parameter is required. This value
	// is supplied by and depends on the Psiphon Network, and is typically
	// embedded in the client binary.
	PropagationChannelId string

	// SponsorId is a string identifier which indicates who is sponsoring this
	// Psiphon client. One purpose of this value is to determine the home
	// pages for display. This parameter is required. This value is supplied
	// by and depends on the Psiphon Network, and is typically embedded in the
	// client binary.
	SponsorId string

	// ClientVersion is the client version number that the client reports to
	// the server. The version number refers to the host client application,
	// not the core tunnel library. One purpose of this value is to enable
	// automatic updates. This value is supplied by and depends on the Psiphon
	// Network, and is typically embedded in the client binary.
	//
	// Note that sending a ClientPlatform string which includes "windows"
	// (case insensitive) and a ClientVersion of <= 44 will cause an error in
	// processing the response to DoConnectedRequest calls.
	ClientVersion string

	// ClientPlatform is the client platform ("Windows", "Android", etc.) that
	// the client reports to the server.
	ClientPlatform string

	// ClientFeatures is a list of feature names denoting enabled application
	// features. Clients report enabled features to the server for stats
	// purposes.
	ClientFeatures []string

	// EgressRegion is a ISO 3166-1 alpha-2 country code which indicates which
	// country to egress from. For the default, "", the best performing server
	// in any country is selected.
	EgressRegion string

	// SplitTunnelOwnRegion enables split tunnel mode for the client's own
	// country. When enabled, TCP port forward destinations that resolve to
	// the same GeoIP country as the client are connected to directly,
	// untunneled.
	SplitTunnelOwnRegion bool

	// SplitTunnelRegions enables selected split tunnel mode in which the
	// client specifies a list of ISO 3166-1 alpha-2 country codes for which
	// traffic should be untunneled. TCP port forwards destined to any
	// country specified in SplitTunnelRegions will be untunneled, regardless
	// of whether SplitTunnelOwnRegion is on or off.
	SplitTunnelRegions []string

	// ListenInterface specifies which interface to listen on.  If no
	// interface is provided then listen on 127.0.0.1. If 'any' is provided
	// then use 0.0.0.0. If there are multiple IP addresses on an interface
	// use the first IPv4 address.
	ListenInterface string

	// DisableLocalSocksProxy disables running the local SOCKS proxy.
	DisableLocalSocksProxy bool

	// LocalSocksProxyPort specifies a port number for the local SOCKS proxy
	// running at 127.0.0.1. For the default value, 0, the system selects a
	// free port (a notice reporting the selected port is emitted).
	LocalSocksProxyPort int

	// LocalHttpProxyPort specifies a port number for the local HTTP proxy
	// running at 127.0.0.1. For the default value, 0, the system selects a
	// free port (a notice reporting the selected port is emitted).
	LocalHttpProxyPort int

	// DisableLocalHTTPProxy disables running the local HTTP proxy.
	DisableLocalHTTPProxy bool

	// NetworkLatencyMultiplier is a multiplier that is to be applied to
	// default network event timeouts. Set this to tune performance for
	// slow networks.
	// When set, must be >= 1.0.
	NetworkLatencyMultiplier float64

	// LimitTunnelProtocols indicates which protocols to use. Valid values
	// include: "SSH", "OSSH", "TLS-OSSH", "UNFRONTED-MEEK-OSSH",
	// "UNFRONTED-MEEK-HTTPS-OSSH", "UNFRONTED-MEEK-SESSION-TICKET-OSSH",
	// "FRONTED-MEEK-OSSH", "FRONTED-MEEK-HTTP-OSSH", "QUIC-OSSH",
	// "FRONTED-MEEK-QUIC-OSSH", "TAPDANCE-OSSH", and "CONJURE-OSSH".
	// For the default, an empty list, all protocols are used.
	LimitTunnelProtocols []string

	// InitialLimitTunnelProtocols is an optional initial phase of limited
	// protocols for the first InitialLimitTunnelProtocolsCandidateCount
	// candidates; after these candidates, LimitTunnelProtocols applies.
	//
	// For the default, an empty list, InitialLimitTunnelProtocols is off.
	InitialLimitTunnelProtocols []string

	// InitialLimitTunnelProtocolsCandidateCount is the number of candidates
	// to which InitialLimitTunnelProtocols is applied instead of
	// LimitTunnelProtocols.
	//
	// For the default, 0, InitialLimitTunnelProtocols is off.
	InitialLimitTunnelProtocolsCandidateCount int

	// LimitTLSProfiles indicates which TLS profiles to select from. Valid
	// values are listed in protocols.SupportedTLSProfiles.
	// For the default, an empty list, all profiles are candidates for
	// selection.
	LimitTLSProfiles []string

	// LimitQUICVersions indicates which QUIC versions to select from. Valid
	// values are listed in protocols.SupportedQUICVersions.
	// For the default, an empty list, all versions are candidates for
	// selection.
	LimitQUICVersions []string

	// EstablishTunnelTimeoutSeconds specifies a time limit after which to
	// halt the core tunnel controller if no tunnel has been established. The
	// default is parameters.EstablishTunnelTimeout.
	EstablishTunnelTimeoutSeconds *int

	// EstablishTunnelPausePeriodSeconds specifies the delay between attempts
	// to establish tunnels. Briefly pausing allows for network conditions to
	// improve and for asynchronous operations such as fetch remote server
	// list to complete. If omitted, a default value is used. This value is
	// typical overridden for testing.
	EstablishTunnelPausePeriodSeconds *int

	// EstablishTunnelPausePeriodSeconds specifies the grace period, or head
	// start, provided to the affinity server candidate when establishing. The
	// affinity server is the server used for the last established tunnel.
	EstablishTunnelServerAffinityGracePeriodMilliseconds *int

	// ConnectionWorkerPoolSize specifies how many connection attempts to
	// attempt in parallel. If omitted of when 0, a default is used; this is
	// recommended.
	ConnectionWorkerPoolSize int

	// TunnelPoolSize specifies how many tunnels to run in parallel. Port
	// forwards are multiplexed over multiple tunnels. If omitted or when 0,
	// the default is TUNNEL_POOL_SIZE, which is recommended. Any value over
	// MAX_TUNNEL_POOL_SIZE is treated as MAX_TUNNEL_POOL_SIZE.
	TunnelPoolSize int

	// StaggerConnectionWorkersMilliseconds adds a specified delay before
	// making each server candidate available to connection workers. This
	// option is enabled when StaggerConnectionWorkersMilliseconds > 0.
	StaggerConnectionWorkersMilliseconds int

	// LimitIntensiveConnectionWorkers limits the number of concurrent
	// connection workers attempting connections with resource intensive
	// protocols. This option is enabled when LimitIntensiveConnectionWorkers
	// > 0.
	LimitIntensiveConnectionWorkers int

	// LimitMeekBufferSizes selects smaller buffers for meek protocols.
	LimitMeekBufferSizes bool

	// LimitCPUThreads minimizes the number of CPU threads -- and associated
	// overhead -- the are used.
	LimitCPUThreads bool

	// LimitRelayBufferSizes selects smaller buffers for port forward relaying.
	LimitRelayBufferSizes bool

	// IgnoreHandshakeStatsRegexps skips compiling and using stats regexes.
	IgnoreHandshakeStatsRegexps bool

	// UpstreamProxyURL is a URL specifying an upstream proxy to use for all
	// outbound connections. The URL should include proxy type and
	// authentication information, as required. See example URLs here:
	// https://github.com/nandoxscr/popon-core/tree/master/psiphon/upstreamproxy
	UpstreamProxyURL string

	// CustomHeaders is a set of additional arbitrary HTTP headers that are
	// added to all plaintext HTTP requests and requests made through an HTTP
	// upstream proxy when specified by UpstreamProxyURL.
	CustomHeaders http.Header

	// MeekAdditionalHeaders is a set of additional arbitrary HTTP headers
	// that are added to all meek HTTP requests. An additional header is
	// ignored when the header name is already present in a meek request.
	MeekAdditionalHeaders http.Header

	// NetworkConnectivityChecker is an interface that enables tunnel-core to
	// call into the host application to check for network connectivity. See:
	// NetworkConnectivityChecker doc.
	NetworkConnectivityChecker NetworkConnectivityChecker

	// DeviceBinder is an interface that enables tunnel-core to call into the
	// host application to bind sockets to specific devices. See: DeviceBinder
	// doc.
	//
	// When DeviceBinder is set, the "VPN" feature name is automatically added
	// when reporting ClientFeatures.
	DeviceBinder DeviceBinder

	// AllowDefaultDNSResolverWithBindToDevice indicates that it's safe to use
	// the default resolver when DeviceBinder is configured, as the host OS
	// will automatically exclude DNS requests from the VPN.
	AllowDefaultDNSResolverWithBindToDevice bool

	// IPv6Synthesizer is an interface that allows tunnel-core to call into
	// the host application to synthesize IPv6 addresses. See: IPv6Synthesizer
	// doc.
	IPv6Synthesizer IPv6Synthesizer

	// HasIPv6RouteGetter is an interface that allows tunnel-core to call into
	// the host application to determine if the host has an IPv6 route. See:
	// HasIPv6RouteGetter doc.
	HasIPv6RouteGetter HasIPv6RouteGetter

	// DNSServerGetter is an interface that enables tunnel-core to call into
	// the host application to discover the native network DNS server
	// settings. See: DNSServerGetter doc.
	DNSServerGetter DNSServerGetter

	// NetworkIDGetter in an interface that enables tunnel-core to call into
	// the host application to get an identifier for the host's current active
	// network. See: NetworkIDGetter doc.
	NetworkIDGetter NetworkIDGetter

	// NetworkID, when not blank, is used as the identifier for the host's
	// current active network.
	// NetworkID is ignored when NetworkIDGetter is set.
	NetworkID string

	// DisableTactics disables tactics operations including requests, payload
	// handling, and application of parameters.
	DisableTactics bool

	// DisableReplay causes any persisted dial parameters to be ignored when
	// they would otherwise be used for replay.
	DisableReplay bool

	// TargetServerEntry is an encoded server entry. When specified, this
	// server entry is used exclusively and all other known servers are
	// ignored; also, when set, ConnectionWorkerPoolSize is ignored and
	// the pool size is 1.
	TargetServerEntry string

	// DisableApi disables Psiphon server API calls including handshake,
	// connected, status, etc. This is used for special case temporary tunnels
	// (Windows VPN mode).
	DisableApi bool

	// TargetAPIProtocol specifies whether to force use of "ssh" or "web" API
	// protocol. When blank, the default, the optimal API protocol is used.
	// Note that this capability check is not applied before the
	// "CandidateServers" count is emitted.
	//
	// This parameter is intended for testing and debugging only. Not all
	// parameters are supported in the legacy "web" API protocol, including
	// speed test samples.
	TargetAPIProtocol string

	// TargetAPIProtocol specifies whether to use "json" or "cbor" API
	// protocol parameter encodings. When blank, the default is to use "cbor"
	// where supported.
	TargetAPIEncoding string

	// RemoteServerListURLs is list of URLs which specify locations to fetch
	// out-of-band server entries. This facility is used when a tunnel cannot
	// be established to known servers. This value is supplied by and depends
	// on the Psiphon Network, and is typically embedded in the client binary.
	// All URLs must point to the same entity with the same ETag. At least one
	// TransferURL must have OnlyAfterAttempts = 0.
	RemoteServerListURLs parameters.TransferURLs

	// RemoteServerListSignaturePublicKey specifies a public key that's used
	// to authenticate the remote server list payload. This value is supplied
	// by and depends on the Psiphon Network, and is typically embedded in the
	// client binary.
	RemoteServerListSignaturePublicKey string

	// DisableRemoteServerListFetcher disables fetching remote server lists.
	// This is used for special case temporary tunnels.
	DisableRemoteServerListFetcher bool

	// FetchRemoteServerListRetryPeriodMilliseconds specifies the delay before
	// resuming a remote server list download after a failure. If omitted, a
	// default value is used. This value is typical overridden for testing.
	FetchRemoteServerListRetryPeriodMilliseconds *int

	// ObfuscatedServerListRootURLs is a list of URLs which specify root
	// locations from which to fetch obfuscated server list files. This value
	// is supplied by and depends on the Psiphon Network, and is typically
	// embedded in the client binary. All URLs must point to the same entity
	// with the same ETag. At least one DownloadURL must have
	// OnlyAfterAttempts = 0.
	ObfuscatedServerListRootURLs parameters.TransferURLs

	// EnableUpgradeDownload indicates whether to check for and download
	// upgrades. When set, UpgradeDownloadURLs and
	// UpgradeDownloadClientVersionHeader must also be set. ClientPlatform
	// and ClientVersion should also be set.
	EnableUpgradeDownload bool

	// UpgradeDownloadURLs is list of URLs which specify locations from which
	// to download a host client upgrade file, when one is available. The core
	// tunnel controller provides a resumable download facility which
	// downloads this resource and emits a notice when complete. This value is
	// supplied by and depends on the Psiphon Network, and is typically
	// embedded in the client binary. All URLs must point to the same entity
	// with the same ETag. At least one DownloadURL must have
	// OnlyAfterAttempts = 0.
	UpgradeDownloadURLs parameters.TransferURLs

	// UpgradeDownloadClientVersionHeader specifies the HTTP header name for
	// the entity at UpgradeDownloadURLs which specifies the client version
	// (an integer value). A HEAD request may be made to check the version
	// number available at UpgradeDownloadURLs.
	// UpgradeDownloadClientVersionHeader is required when UpgradeDownloadURLs
	// is specified.
	UpgradeDownloadClientVersionHeader string

	// FetchUpgradeRetryPeriodMilliseconds specifies the delay before resuming
	// a client upgrade download after a failure. If omitted, a default value
	// is used. This value is typical overridden for testing.
	FetchUpgradeRetryPeriodMilliseconds *int

	// EnableFeedbackUpload indicates whether to enable uploading feedback
	// data. When set, FeedbackUploadURLs and FeedbackEncryptionPublicKey
	// must also be set.
	EnableFeedbackUpload bool

	// FeedbackUploadURLs is a list of SecureTransferURLs which specify
	// locations where feedback data can be uploaded, pairing with each
	// location a public key with which to encrypt the feedback data. This
	// value is supplied by and depends on the Psiphon Network, and is
	// typically embedded in the client binary. At least one TransferURL must
	// have OnlyAfterAttempts = 0.
	FeedbackUploadURLs parameters.TransferURLs

	// FeedbackEncryptionPublicKey is a default base64-encoded, RSA public key
	// value used to encrypt feedback data. Used when uploading feedback with a
	// TransferURL which has no public key value configured, i.e.
	// B64EncodedPublicKey = "".
	FeedbackEncryptionPublicKey string

	// TrustedCACertificatesFilename specifies a file containing trusted CA
	// certs. When set, this toggles use of the trusted CA certs, specified in
	// TrustedCACertificatesFilename, for tunneled TLS connections that expect
	// server certificates signed with public certificate authorities
	// (currently, only upgrade downloads). This option is used with stock Go
	// TLS in cases where Go may fail to obtain a list of root CAs from the
	// operating system.
	TrustedCACertificatesFilename string

	// DisableSystemRootCAs, when true, disables loading system root CAs when
	// verifying TLS certificates for all remote server list downloads, upgrade
	// downloads, and feedback uploads. Each of these transfers has additional
	// security at the payload level. Verifying TLS certificates is preferred,
	// as an additional security and circumvention layer; set
	// DisableSystemRootCAs only in cases where system root CAs cannot be
	// loaded; for example, if unsupported (iOS < 12) or insufficient memory
	// (VPN extension on iOS < 15).
	DisableSystemRootCAs bool

	// DisablePeriodicSshKeepAlive indicates whether to send an SSH keepalive
	// every 1-2 minutes, when the tunnel is idle. If the SSH keepalive times
	// out, the tunnel is considered to have failed.
	DisablePeriodicSshKeepAlive bool

	// DeviceLocation is the optional, reported location the host device is
	// running in. This input value should be a string representing location
	// geohash. The device location is reported to the server in the connected
	// request and recorded for Psiphon stats.
	DeviceLocation string

	// DeviceRegion is the optional, reported region the host device is
	// running in. This input value should be a ISO 3166-1 alpha-2 country
	// code. The device region is reported to the server in the connected
	// request and recorded for Psiphon stats.
	//
	// When provided, this value may be used, pre-connection, to select
	// performance or circumvention optimization strategies for the given
	// region.
	DeviceRegion string

	// EmitDiagnosticNotices indicates whether to output notices containing
	// detailed information about the Psiphon session. As these notices may
	// contain sensitive information, they should not be insecurely distributed
	// or displayed to users. Default is off.
	EmitDiagnosticNotices bool

	// EmitDiagnosticNetworkParameters indicates whether to include network
	// parameters in diagnostic notices. As these parameters are sensitive
	// circumvention network information, they should not be insecurely
	// distributed or displayed to users. Default is off.
	EmitDiagnosticNetworkParameters bool

	// EmitBytesTransferred indicates whether to emit frequent notices showing
	// bytes sent and received.
	EmitBytesTransferred bool

	// EmitSLOKs indicates whether to emit notices for each seeded SLOK. As
	// this could reveal user browsing activity, it's intended for debugging
	// and testing only.
	EmitSLOKs bool

	// EmitRefractionNetworkingLogs indicates whether to emit gotapdance log
	// messages to stdout. Note that gotapdance log messages do not conform to
	// the Notice format standard. Default is off.
	EmitRefractionNetworkingLogs bool

	// EmitServerAlerts indicates whether to emit notices for server alerts.
	EmitServerAlerts bool

	// EmitClientAddress indicates whether to emit the client's public network
	// address, IP and port, as seen by the server.
	EmitClientAddress bool

	// RateLimits specify throttling configuration for the tunnel.
	RateLimits common.RateLimits

	// PacketTunnelTunDeviceFileDescriptor specifies a tun device file
	// descriptor to use for running a packet tunnel. When this value is > 0,
	// a packet tunnel is established through the server and packets are
	// relayed via the tun device file descriptor. The file descriptor is
	// duped in NewController. When PacketTunnelTunDeviceFileDescriptor is
	// set, TunnelPoolSize must be 1.
	PacketTunnelTunFileDescriptor int

	// PacketTunnelTransparentDNSIPv4Address is the IPv4 address of the DNS
	// server configured by a VPN using a packet tunnel. All DNS packets
	// destined to this DNS server are transparently redirected to the
	// Psiphon server DNS.
	PacketTunnelTransparentDNSIPv4Address string

	// PacketTunnelTransparentDNSIPv6Address is the IPv6 address of the DNS
	// server configured by a VPN using a packet tunnel. All DNS packets
	// destined to this DNS server are transparently redirected to the
	// Psiphon server DNS.
	PacketTunnelTransparentDNSIPv6Address string

	// SessionID specifies a client session ID to use in the Psiphon API. The
	// session ID should be a randomly generated value that is used only for a
	// single session, which is defined as the period between a user starting
	// a Psiphon client and stopping the client.
	//
	// A session ID must be 32 hex digits (lower case). When blank, a random
	// session ID is automatically generated. Supply a session ID when a
	// single client session will cross multiple Controller instances.
	SessionID string

	// Authorizations is a list of encoded, signed access control
	// authorizations that the client has obtained and will present to the
	// server.
	Authorizations []string

	// ServerEntrySignaturePublicKey is a base64-encoded, ed25519 public
	// key value used to verify individual server entry signatures. This value
	// is supplied by and depends on the Psiphon Network, and is typically
	// embedded in the client binary.
	ServerEntrySignaturePublicKey string

	// ExchangeObfuscationKey is a base64-encoded, NaCl secretbox key used to
	// obfuscate server info exchanges between clients.
	// Required for the exchange functionality.
	ExchangeObfuscationKey string

	// MigrateHomepageNoticesFilename migrates a homepage file from the path
	// previously configured with setNoticeFiles to the new path for homepage
	// files under the data root directory. The file specified by this config
	// value will be moved to config.GetHomePageFilename().
	//
	// Note: see comment for config.Commit() for a description of how file
	// migrations are performed.
	//
	// If not set, no migration operation will be performed.
	MigrateHomepageNoticesFilename string

	// MigrateRotatingNoticesFilename migrates notice files from the path
	// previously configured with setNoticeFiles to the new path for notice
	// files under the data root directory.
	//
	// MigrateRotatingNoticesFilename will be moved to
	// config.GetNoticesFilename().
	//
	// MigrateRotatingNoticesFilename.1 will be moved to
	// config.GetOldNoticesFilename().
	//
	// Note: see comment for config.Commit() for a description of how file
	// migrations are performed.
	//
	// If not set, no migration operation will be performed.
	MigrateRotatingNoticesFilename string

	// MigrateDataStoreDirectory indicates the location of the datastore
	// directory, as previously configured with the deprecated
	// DataStoreDirectory config field. Datastore files found in the specified
	// directory will be moved under the data root directory.
	//
	// Note: see comment for config.Commit() for a description of how file
	// migrations are performed.
	MigrateDataStoreDirectory string

	// MigrateRemoteServerListDownloadFilename indicates the location of
	// remote server list download files. The remote server list files found at
	// the specified path will be moved under the data root directory.
	//
	// Note: see comment for config.Commit() for a description of how file
	// migrations are performed.
	MigrateRemoteServerListDownloadFilename string

	// MigrateObfuscatedServerListDownloadDirectory indicates the location of
	// the obfuscated server list downloads directory, as previously configured
	// with ObfuscatedServerListDownloadDirectory. Obfuscated server list
	// download files found in the specified directory will be moved under the
	// data root directory.
	//
	// Warning: if the directory is empty after obfuscated server
	// list files are moved, then it will be deleted.
	//
	// Note: see comment for config.Commit() for a description of how file
	// migrations are performed.
	MigrateObfuscatedServerListDownloadDirectory string

	// MigrateUpgradeDownloadFilename indicates the location of downloaded
	// application upgrade files. Downloaded upgrade files found at the
	// specified path will be moved under the data root directory.
	//
	// Note: see comment for config.Commit() for a description of how file
	// migrations are performed.
	MigrateUpgradeDownloadFilename string

	// DisableTunnels disables establishing a client tunnel. Set
	// DisableTunnels when running a stand-alone in-proxy proxy.
	DisableTunnels bool

	// InproxyEnableProxy enables running an in-proxy proxy.
	InproxyEnableProxy bool

	// InproxyProxySessionPrivateKey specifies a long-term in-proxy proxy
	// private key and corresponding, derived proxy ID to use. If blank, an
	// ephemeral key will be generated.
	InproxyProxySessionPrivateKey string

	// InproxyMaxClients specifies the maximum number of in-proxy clients to
	// be proxied concurrently.
	InproxyMaxClients int

	// InproxyLimitUpstreamBytesPerSecond specifies the upstream byte transfer
	// rate limit for each proxied client. When 0, there is no limit.
	InproxyLimitUpstreamBytesPerSecond int

	// InproxyLimitDownstreamBytesPerSecond specifies the downstream byte
	// transfer rate limit for each proxied client. When 0, there is no limit.
	InproxyLimitDownstreamBytesPerSecond int

	// InproxyProxyPersonalCompartmentIDs specifies the personal compartment
	// IDs used by an in-proxy proxy. Personal compartment IDs are
	// distributed from proxy operators to client users out-of-band and
	// provide a mechanism to allow only certain clients to use a proxy.
	//
	// See InproxyClientPersonalCompartmentIDs comment for limitations.
	InproxyProxyPersonalCompartmentIDs []string

	// InproxyClientPersonalCompartmentIDs specifies the personal compartment
	// IDs used by an in-proxy client. Personal compartment IDs are
	// distributed from proxy operators to client users out-of-band and
	// provide a mechanism to ensure a client uses only a certain proxy for
	// all tunnels connections.
	//
	// When InproxyClientPersonalCompartmentIDs is set, the client will use
	// only in-proxy protocols, ensuring that all connections go through the
	// proxy or proxies with the same personal compartment IDs.
	//
	// Limitations:
	//
	// - While fully functional, the personal pairing mode has a number of
	//   limitations that make the current implementation less suitable for
	//   large scale deployment.
	//
	// - Since the mode requires an in-proxy connection to a proxy, announcing
	//   with the corresponding personal compartment ID, not only must that
	//   proxy be available, but also a broker, and both the client and proxy
	//   must rendezvous at the same broker.
	//
	// - Currently, the client tunnel establishment algorithm does not launch
	//   an untunneled tactics request as long as there is a cached tactics
	//   with a valid TTL. The assumption, in regular mode, is that the
	//   cached tactics will suffice, and any new tactics will be obtained
	//   from any Psiphon server connection. Since broker specs are obtained
	//   solely from tactics, if brokers are removed, reconfigured, or even
	//   if the order is changed, personal mode may fail to connect until
	//   cached tactics expire.
	//
	// - In personal mode, clients and proxies use a simplistic approach to
	//   rendezvous: always select the first broker spec. This works, but is
	//   not robust in terms of load balancing, and fails if the first broker
	//   is unreachable or overloaded. Non-personal in-proxy dials can simply
	//   use any available broker.
	//
	// - The broker matching queues lack compartment ID indexing. For a
	//   handful of common compartment IDs, this is not expected to be an
	//   issue. For personal compartment IDs, this may lead to frequency
	//   near-full scans of the queues when looking for a match.
	//
	// - In personal mode, all establishment candidates must be in-proxy
	//   dials, all using the same broker. Many concurrent, fronted broker
	//   requests may result in CDN rate limiting, requiring some mechanism
	//   to delay or spread the requests, as is currently done only for
	//   batches of proxy announcements.
	//
	InproxyClientPersonalCompartmentIDs []string

	// EmitInproxyProxyActivity indicates whether to emit frequent notices
	// showing proxy connection information and bytes transferred.
	EmitInproxyProxyActivity bool

	// DataStoreDirectory is the directory in which to store the persistent
	// database, which contains information such as server entries. By
	// default, current working directory.
	//
	// Deprecated:
	// Use MigrateDataStoreDirectory. When MigrateDataStoreDirectory
	// is set, this parameter is ignored.
	//
	// DataStoreDirectory has been subsumed by the new data root directory,
	// which is configured with DataRootDirectory. If set, datastore files
	// found in the specified directory will be moved under the data root
	// directory.
	DataStoreDirectory string

	// RemoteServerListDownloadFilename specifies a target filename for
	// storing the remote server list download. Data is stored in co-located
	// files (RemoteServerListDownloadFilename.part*) to allow for resumable
	// downloading.
	//
	// Deprecated:
	// Use MigrateRemoteServerListDownloadFilename. When
	// MigrateRemoteServerListDownloadFilename is set, this parameter is
	// ignored.
	//
	// If set, remote server list download files found at the specified path
	// will be moved under the data root directory.
	RemoteServerListDownloadFilename string

	// ObfuscatedServerListDownloadDirectory specifies a target directory for
	// storing the obfuscated remote server list downloads. Data is stored in
	// co-located files (<OSL filename>.part*) to allow for resumable
	// downloading.
	//
	// Deprecated:
	// Use MigrateObfuscatedServerListDownloadDirectory. When
	// MigrateObfuscatedServerListDownloadDirectory is set, this parameter is
	// ignored.
	//
	// If set, obfuscated server list download files found at the specified path
	// will be moved under the data root directory.
	ObfuscatedServerListDownloadDirectory string

	// UpgradeDownloadFilename is the local target filename for an upgrade
	// download. This parameter is required when UpgradeDownloadURLs (or
	// UpgradeDownloadUrl) is specified. Data is stored in co-located files
	// (UpgradeDownloadFilename.part*) to allow for resumable downloading.
	//
	// Deprecated:
	// Use MigrateUpgradeDownloadFilename. When MigrateUpgradeDownloadFilename
	// is set, this parameter is ignored.
	//
	// If set, upgrade download files found at the specified path will be moved
	// under the data root directory.
	UpgradeDownloadFilename string

	// TunnelProtocol indicates which protocol to use. For the default, "",
	// all protocols are used.
	//
	// Deprecated: Use LimitTunnelProtocols. When LimitTunnelProtocols is not
	// nil, this parameter is ignored.
	TunnelProtocol string

	// Deprecated: Use CustomHeaders. When CustomHeaders is not nil, this
	// parameter is ignored.
	UpstreamProxyCustomHeaders http.Header

	// RemoteServerListUrl is a URL which specifies a location to fetch out-
	// of-band server entries. This facility is used when a tunnel cannot be
	// established to known servers. This value is supplied by and depends on
	// the Psiphon Network, and is typically embedded in the client binary.
	//
	// Deprecated: Use RemoteServerListURLs. When RemoteServerListURLs is not
	// nil, this parameter is ignored.
	RemoteServerListUrl string

	// ObfuscatedServerListRootURL is a URL which specifies the root location
	// from which to fetch obfuscated server list files. This value is
	// supplied by and depends on the Psiphon Network, and is typically
	// embedded in the client binary.
	//
	// Deprecated: Use ObfuscatedServerListRootURLs. When
	// ObfuscatedServerListRootURLs is not nil, this parameter is ignored.
	ObfuscatedServerListRootURL string

	// UpgradeDownloadUrl specifies a URL from which to download a host client
	// upgrade file, when one is available. The core tunnel controller
	// provides a resumable download facility which downloads this resource
	// and emits a notice when complete. This value is supplied by and depends
	// on the Psiphon Network, and is typically embedded in the client binary.
	//
	// Deprecated: Use UpgradeDownloadURLs. When UpgradeDownloadURLs is not
	// nil, this parameter is ignored.
	UpgradeDownloadUrl string

	// TransformHostNameProbability is for testing purposes.
	TransformHostNameProbability *float64

	// FragmentorProbability and associated Fragmentor fields are for testing
	// purposes.
	FragmentorProbability          *float64
	FragmentorLimitProtocols       []string
	FragmentorMinTotalBytes        *int
	FragmentorMaxTotalBytes        *int
	FragmentorMinWriteBytes        *int
	FragmentorMaxWriteBytes        *int
	FragmentorMinDelayMicroseconds *int
	FragmentorMaxDelayMicroseconds *int

	// MeekTrafficShapingProbability and associated fields are for testing
	// purposes.
	MeekTrafficShapingProbability       *float64
	MeekTrafficShapingLimitProtocols    []string
	MeekMinTLSPadding                   *int
	MeekMaxTLSPadding                   *int
	MeekMinLimitRequestPayloadLength    *int
	MeekMaxLimitRequestPayloadLength    *int
	MeekRedialTLSProbability            *float64
	MeekAlternateCookieNameProbability  *float64
	MeekAlternateContentTypeProbability *float64

	// ObfuscatedSSHAlgorithms and associated ObfuscatedSSH fields are for
	// testing purposes. If specified, ObfuscatedSSHAlgorithms must have 4 SSH
	// KEX elements in order: the kex algorithm, cipher, MAC, and server host
	// key algorithm.
	ObfuscatedSSHAlgorithms []string
	ObfuscatedSSHMinPadding *int
	ObfuscatedSSHMaxPadding *int

	// LivenessTestMinUpstreamBytes and other LivenessTest fields are for
	// testing purposes.
	LivenessTestMinUpstreamBytes   *int
	LivenessTestMaxUpstreamBytes   *int
	LivenessTestMinDownstreamBytes *int
	LivenessTestMaxDownstreamBytes *int

	// ReplayCandidateCount and other Replay fields are for testing purposes.
	ReplayCandidateCount                   *int
	ReplayDialParametersTTLSeconds         *int
	ReplayTargetUpstreamBytes              *int
	ReplayTargetDownstreamBytes            *int
	ReplayTargetTunnelDurationSeconds      *int
	ReplayLaterRoundMoveToFrontProbability *float64
	ReplayRetainFailedProbability          *float64
	ReplayIgnoreChangedConfigState         *bool

	// NetworkLatencyMultiplierMin and other NetworkLatencyMultiplier fields are
	// for testing purposes.
	NetworkLatencyMultiplierMin    float64
	NetworkLatencyMultiplierMax    float64
	NetworkLatencyMultiplierLambda float64

	// UseOnlyCustomTLSProfiles and other TLS configuration fields are for
	// testing purposes.
	UseOnlyCustomTLSProfiles              *bool
	CustomTLSProfiles                     protocol.CustomTLSProfiles
	SelectRandomizedTLSProfileProbability *float64
	NoDefaultTLSSessionIDProbability      *float64
	DisableFrontingProviderTLSProfiles    protocol.LabeledTLSProfiles

	// ClientBurstUpstreamTargetBytes and other burst metric fields are for
	// testing purposes.
	ClientBurstUpstreamTargetBytes            *int
	ClientBurstUpstreamDeadlineMilliseconds   *int
	ClientBurstDownstreamTargetBytes          *int
	ClientBurstDownstreamDeadlineMilliseconds *int

	// ApplicationParameters is for testing purposes.
	ApplicationParameters parameters.KeyValues

	// CustomHostNameRegexes and other custom host name fields are for testing
	// purposes.
	CustomHostNameRegexes        []string
	CustomHostNameProbability    *float64
	CustomHostNameLimitProtocols []string

	// ConjureCachedRegistrationTTLSeconds and other Conjure fields are for
	// testing purposes.
	ConjureCachedRegistrationTTLSeconds       *int
	ConjureAPIRegistrarBidirectionalURL       string
	ConjureAPIRegistrarFrontingSpecs          parameters.FrontingSpecs
	ConjureAPIRegistrarMinDelayMilliseconds   *int
	ConjureAPIRegistrarMaxDelayMilliseconds   *int
	ConjureDecoyRegistrarProbability          *float64
	ConjureDecoyRegistrarWidth                *int
	ConjureDecoyRegistrarMinDelayMilliseconds *int
	ConjureDecoyRegistrarMaxDelayMilliseconds *int
	ConjureEnableIPv6Dials                    *bool
	ConjureEnablePortRandomization            *bool
	ConjureEnableRegistrationOverrides        *bool
	ConjureLimitTransports                    protocol.ConjureTransports
	ConjureSTUNServerAddresses                []string
	ConjureDTLSEmptyInitialPacketProbability  *float64

	// HoldOffTunnelMinDurationMilliseconds and other HoldOffTunnel fields are
	// for testing purposes.
	HoldOffTunnelMinDurationMilliseconds *int
	HoldOffTunnelMaxDurationMilliseconds *int
	HoldOffTunnelProtocols               []string
	HoldOffTunnelFrontingProviderIDs     []string
	HoldOffTunnelProbability             *float64

	// RestrictFrontingProviderIDs and other RestrictFrontingProviderIDs fields
	// are for testing purposes.
	RestrictFrontingProviderIDs                  []string
	RestrictFrontingProviderIDsClientProbability *float64

	// HoldOffDirectTunnelMinDurationMilliseconds and other HoldOffDirect
	// fields are for testing purposes.
	HoldOffDirectTunnelMinDurationMilliseconds *int
	HoldOffDirectTunnelMaxDurationMilliseconds *int
	HoldOffDirectTunnelProviderRegions         map[string][]string
	HoldOffDirectTunnelProbability             *float64

	// RestrictDirectProviderRegions and other RestrictDirect fields are for
	// testing purposes.
	RestrictDirectProviderRegions              map[string][]string
	RestrictDirectProviderIDsClientProbability *float64

	// UpstreamProxyAllowAllServerEntrySources is for testing purposes.
	UpstreamProxyAllowAllServerEntrySources *bool

	// LimitTunnelDialPortNumbers is for testing purposes.
	LimitTunnelDialPortNumbers parameters.TunnelProtocolPortLists

	// QUICDisablePathMTUDiscoveryProbability is for testing purposes.
	QUICDisablePathMTUDiscoveryProbability *float64

	// DNSResolverAttemptsPerServer and other DNSResolver fields are for
	// testing purposes.
	DNSResolverAttemptsPerServer                     *int
	DNSResolverAttemptsPerPreferredServer            *int
	DNSResolverRequestTimeoutMilliseconds            *int
	DNSResolverAwaitTimeoutMilliseconds              *int
	DNSResolverPreresolvedIPAddressCIDRs             parameters.LabeledCIDRs
	DNSResolverPreresolvedIPAddressProbability       *float64
	DNSResolverAlternateServers                      []string
	DNSResolverPreferredAlternateServers             []string
	DNSResolverPreferAlternateServerProbability      *float64
	DNSResolverProtocolTransformSpecs                transforms.Specs
	DNSResolverProtocolTransformScopedSpecNames      transforms.ScopedSpecNames
	DNSResolverProtocolTransformProbability          *float64
	DNSResolverIncludeEDNS0Probability               *float64
	DNSResolverCacheExtensionInitialTTLMilliseconds  *int
	DNSResolverCacheExtensionVerifiedTTLMilliseconds *int

	DirectHTTPProtocolTransformSpecs            transforms.Specs
	DirectHTTPProtocolTransformScopedSpecNames  transforms.ScopedSpecNames
	DirectHTTPProtocolTransformProbability      *float64
	FrontedHTTPProtocolTransformSpecs           transforms.Specs
	FrontedHTTPProtocolTransformScopedSpecNames transforms.ScopedSpecNames
	FrontedHTTPProtocolTransformProbability     *float64

	OSSHObfuscatorSeedTransformSpecs           transforms.Specs
	OSSHObfuscatorSeedTransformScopedSpecNames transforms.ScopedSpecNames
	OSSHObfuscatorSeedTransformProbability     *float64

	ObfuscatedQUICNonceTransformSpecs           transforms.Specs
	ObfuscatedQUICNonceTransformScopedSpecNames transforms.ScopedSpecNames
	ObfuscatedQUICNonceTransformProbability     *float64

	// OSSHPrefix parameters are for testing purposes only.
	OSSHPrefixSpecs                     transforms.Specs
	OSSHPrefixScopedSpecNames           transforms.ScopedSpecNames
	OSSHPrefixProbability               *float64
	OSSHPrefixSplitMinDelayMilliseconds *int
	OSSHPrefixSplitMaxDelayMilliseconds *int
	OSSHPrefixEnableFragmentor          *bool

	// TLSTunnelTrafficShapingProbability and associated fields are for testing.
	TLSTunnelTrafficShapingProbability *float64
	TLSTunnelMinTLSPadding             *int
	TLSTunnelMaxTLSPadding             *int

	// TLSFragmentClientHello fields are for testing purposes only.
	TLSFragmentClientHelloProbability    *float64
	TLSFragmentClientHelloLimitProtocols []string

	// AdditionalParameters is used for testing.
	AdditionalParameters string

	// SteeringIP fields are for testing purposes only.
	SteeringIPCacheTTLSeconds *int
	SteeringIPCacheMaxEntries *int
	SteeringIPProbability     *float64

	// The following in-proxy fields are for testing purposes only.
	InproxyAllowProxy                                      *bool
	InproxyAllowClient                                     *bool
	InproxyTunnelProtocolSelectionProbability              *float64
	InproxyBrokerSpecs                                     parameters.InproxyBrokerSpecsValue
	InproxyClientBrokerSpecs                               parameters.InproxyBrokerSpecsValue
	InproxyProxyBrokerSpecs                                parameters.InproxyBrokerSpecsValue
	InproxyReplayBrokerDialParametersTTLSeconds            *int
	InproxyReplayBrokerUpdateFrequencySeconds              *int
	InproxyReplayBrokerDialParametersProbability           *float64
	InproxyReplayBrokerRetainFailedProbability             *float64
	InproxyCommonCompartmentIDs                            parameters.InproxyCompartmentIDsValue
	InproxyMaxCompartmentIDListLength                      *int
	InproxyProxyAnnounceRequestTimeoutMilliseconds         *int
	InproxyProxyAnnounceDelayMilliseconds                  *int
	InproxyProxyAnnounceDelayJitter                        *float64
	InproxyProxyAnswerRequestTimeoutMilliseconds           *int
	InproxyClientOfferRequestTimeoutMilliseconds           *int
	InproxyClientOfferRetryDelayMilliseconds               *int
	InproxyClientOfferRetryJitter                          *float64
	InproxyClientRelayedPacketRequestTimeoutMilliseconds   *int
	InproxyDTLSRandomizationProbability                    *float64
	InproxyDataChannelTrafficShapingProbability            *float64
	InproxyDataChannelTrafficShapingParameters             *parameters.InproxyDataChannelTrafficShapingParametersValue
	InproxySTUNServerAddresses                             []string
	InproxySTUNServerAddressesRFC5780                      []string
	InproxyProxySTUNServerAddresses                        []string
	InproxyProxySTUNServerAddressesRFC5780                 []string
	InproxyClientSTUNServerAddresses                       []string
	InproxyClientSTUNServerAddressesRFC5780                []string
	InproxyClientDiscoverNATProbability                    *float64
	InproxyDisableSTUN                                     *bool
	InproxyDisablePortMapping                              *bool
	InproxyDisableInboundForMobileNetworks                 *bool
	InproxyDisableIPv6ICECandidates                        *bool
	InproxyDiscoverNATTimeoutMilliseconds                  *int
	InproxyWebRTCAnswerTimeoutMilliseconds                 *int
	InproxyProxyWebRTCAwaitDataChannelTimeoutMilliseconds  *int
	InproxyClientWebRTCAwaitDataChannelTimeoutMilliseconds *int
	InproxyProxyDestinationDialTimeoutMilliseconds         *int
	InproxyPsiphonAPIRequestTimeoutMilliseconds            *int
	InproxyProxyTotalActivityNoticePeriodMilliseconds      *int

	InproxySkipAwaitFullyConnected  bool
	InproxyEnableWebRTCDebugLogging bool
	// contains filtered or unexported fields
}

Config is the Psiphon configuration specified by the application. This configuration controls the behavior of the core tunnel functionality.

To distinguish omitted timeout params from explicit 0 value timeout params, corresponding fields are int pointers. nil means no value was supplied and to use the default; a non-nil pointer to 0 means no timeout.

func LoadConfig

func LoadConfig(configJson []byte) (*Config, error)

LoadConfig parses a JSON format Psiphon config JSON string and returns a Config struct populated with config values.

The Config struct may then be programmatically populated with additional values, including callbacks such as DeviceBinder.

Before using the Config, Commit must be called, which will perform further validation and initialize internal data structures.

func (*Config) Commit

func (config *Config) Commit(migrateFromLegacyFields bool) error

Commit validates Config fields finalizes initialization.

Config fields should not be set after calling Config, as any changes may not be reflected in internal data structures.

If migrateFromLegacyFields is set to true, then an attempt to migrate from legacy fields is made.

Migration from legacy fields: Config fields of the naming Migrate* (e.g. MigrateDataStoreDirectory) specify a file migration operation which should be performed. These fields correspond to deprecated fields, which previously could be used to specify where Psiphon stored different sets of persistent files (e.g. MigrateDataStoreDirectory corresponds to the deprecated field DataStoreDirectory).

Psiphon now stores all persistent data under the configurable DataRootDirectory (see Config.DataRootDirectory). The deprecated fields, and corresponding Migrate* fields, are now used to specify the file or directory path where, or under which, persistent files and directories created by previous versions of Psiphon exist, so they can be moved under the DataRootDirectory.

For each migration operation:

  • In the case of directories that could have defaulted to the current working directory, persistent files and directories created by Psiphon are precisely targeted to avoid moving files which were not created by Psiphon.
  • If no file is found at the specified path, or an error is encountered while migrating the file, then an error is logged and execution continues normally.

A sentinel file which signals that file migration has been completed, and should not be attempted again, is created under DataRootDirectory after one full pass through Commit(), regardless of whether file migration succeeds or fails. It is better to not endlessly retry file migrations on each Commit() because file system errors are expected to be rare and persistent files will be re-populated over time.

func (*Config) GetAuthorizations

func (config *Config) GetAuthorizations() []string

GetAuthorizations returns the current client authorizations. The caller must not modify the returned slice.

func (*Config) GetDataStoreDirectory

func (config *Config) GetDataStoreDirectory() string

GetDataStoreDirectory returns the directory in which the persistent database will be stored. Created in Config.Commit(). The persistent database contains information such as server entries.

func (*Config) GetHomePageFilename

func (config *Config) GetHomePageFilename() string

GetHomePageFilename the path where the homepage notices file will be created.

func (*Config) GetNetworkID

func (config *Config) GetNetworkID() string

GetNetworkID returns the current network ID. When NetworkIDGetter is set, this calls into the host application; otherwise, a default value is returned.

func (*Config) GetNoticesFilename

func (config *Config) GetNoticesFilename() string

GetNoticesFilename returns the path where the notices file will be created. When the file is rotated it will be moved to config.GetOldNoticesFilename().

func (*Config) GetObfuscatedServerListDownloadDirectory

func (config *Config) GetObfuscatedServerListDownloadDirectory() string

GetObfuscatedServerListDownloadDirectory returns the directory in which obfuscated remote server list downloads will be stored. Created in Config.Commit().

func (*Config) GetOldNoticesFilename

func (config *Config) GetOldNoticesFilename() string

GetOldNoticeFilename returns the path where the rotated notices file will be created.

func (*Config) GetParameters

func (config *Config) GetParameters() *parameters.Parameters

GetParameters returns the current parameters.Parameters.

func (*Config) GetPsiphonDataDirectory

func (config *Config) GetPsiphonDataDirectory() string

GetPsiphonDataDirectory returns the directory under which all persistent files should be stored. This directory is created under config.DataRootDirectory. The motivation for an additional directory is that config.DataRootDirectory defaults to the current working directory, which may include non-tunnel-core files that should be excluded from directory-spanning operations (e.g. excluding all tunnel-core files from backup).

func (*Config) GetRemoteServerListDownloadFilename

func (config *Config) GetRemoteServerListDownloadFilename() string

GetRemoteServerListDownloadFilename returns the filename where the remote server list download will be stored. Data is stored in co-located files (RemoteServerListDownloadFilename.part*) to allow for resumable downloading.

func (*Config) GetResolver

func (config *Config) GetResolver() *resolver.Resolver

GetResolver returns the current resolver. May return nil.

func (*Config) GetSponsorID

func (config *Config) GetSponsorID() string

GetSponsorID returns the current client sponsor ID.

func (*Config) GetTacticsAppliedReceivers

func (config *Config) GetTacticsAppliedReceivers() []TacticsAppliedReceiver

GetTacticsAppliedReceivers gets the list of registered TacticsAppliedReceivers.

func (*Config) GetUpgradeDownloadFilename

func (config *Config) GetUpgradeDownloadFilename() string

GetUpgradeDownloadFilename specifies the filename where upgrade downloads will be stored. This filename is valid when UpgradeDownloadURLs (or UpgradeDownloadUrl) is specified. Data is stored in co-located files (UpgradeDownloadFilename.part*) to allow for resumable downloading.

func (*Config) IsCommitted

func (config *Config) IsCommitted() bool

IsCommitted checks if Commit was called.

func (*Config) IsSplitTunnelEnabled

func (config *Config) IsSplitTunnelEnabled() bool

IsSplitTunnelEnabled indicates if split tunnel mode is enabled, either for the client's own country, a specified list of countries, or both.

func (*Config) SetDynamicConfig

func (config *Config) SetDynamicConfig(sponsorID string, authorizations []string)

SetDynamicConfig sets the current client sponsor ID and authorizations. Invalid values for sponsor ID are ignored. The caller must not modify the input authorizations slice.

func (*Config) SetParameters

func (config *Config) SetParameters(tag string, skipOnError bool, applyParameters map[string]interface{}) error

SetParameters resets the parameters.Parameters to the default values, applies any config file values, and then applies the input parameters (from tactics, etc.)

Set skipOnError to false when initially applying only config values, as this will validate the values and should fail. Set skipOnError to true when applying tactics to ignore invalid or unknown parameter values from tactics.

In the case of applying tactics, do not call Config.parameters.Set directly as this will not first apply config values.

If there is an error, the existing Config.parameters are left entirely unmodified.

func (*Config) SetResolver

func (config *Config) SetResolver(resolver *resolver.Resolver)

SetResolver sets the current resolver.

func (*Config) SetTacticsAppliedReceivers

func (config *Config) SetTacticsAppliedReceivers(receivers []TacticsAppliedReceiver)

SetTacticsAppliedReceivers registers the list of TacticsAppliedReceivers.

func (*Config) UseUpstreamProxy

func (config *Config) UseUpstreamProxy() bool

UseUpstreamProxy indicates if an upstream proxy has been configured.

type Controller

type Controller struct {
	// contains filtered or unexported fields
}

Controller is a tunnel lifecycle coordinator. It manages lists of servers to connect to; establishes and monitors tunnels; and runs local proxies which route traffic through the tunnels.

func NewController

func NewController(config *Config) (controller *Controller, err error)

NewController initializes a new controller.

func (*Controller) Dial

func (controller *Controller) Dial(
	remoteAddr string, downstreamConn net.Conn) (conn net.Conn, err error)

Dial selects an active tunnel and establishes a port forward connection through the selected tunnel. Failure to connect is considered a port forward failure, for the purpose of monitoring tunnel health.

When split tunnel mode is enabled, the connection may be untunneled, depending on GeoIP classification of the destination.

downstreamConn is an optional parameter which specifies a connection to be explicitly closed when the dialed connection is closed. For instance, this is used to close downstreamConn App<->LocalProxy connections when the related LocalProxy<->SshPortForward connections close.

func (*Controller) DirectDial

func (controller *Controller) DirectDial(remoteAddr string) (conn net.Conn, err error)

DirectDial dials an untunneled TCP connection within the controller run context.

func (*Controller) ExportExchangePayload

func (controller *Controller) ExportExchangePayload() string

ExportExchangePayload creates a payload for client-to-client server connection info exchange. See the comment for psiphon.ExportExchangePayload for more details.

func (*Controller) ImportExchangePayload

func (controller *Controller) ImportExchangePayload(payload string) bool

ImportExchangePayload imports a payload generated by ExportExchangePayload. See the comment for psiphon.ImportExchangePayload for more details about the import.

When the import is successful, a signal is set to trigger a restart any establishment in progress. This will cause the newly imported server entry to be prioritized, which it otherwise would not be in later establishment rounds. The establishment process continues after ImportExchangePayload returns.

If the client already has a connected tunnel, or a tunnel connection is established concurrently with the import, the signal has no effect as the overall goal is establish _any_ connection.

func (*Controller) Run

func (controller *Controller) Run(ctx context.Context)

Run executes the controller. Run exits if a controller component fails or the parent context is canceled.

func (*Controller) SetDynamicConfig

func (controller *Controller) SetDynamicConfig(sponsorID string, authorizations []string)

SetDynamicConfig overrides the sponsor ID and authorizations fields of the Controller config with the input values. The new values will be used in the next tunnel connection.

func (*Controller) SignalComponentFailure

func (controller *Controller) SignalComponentFailure()

SignalComponentFailure notifies the controller that an associated component has failed. This will terminate the controller.

func (*Controller) SignalSeededNewSLOK

func (controller *Controller) SignalSeededNewSLOK()

SignalSeededNewSLOK implements the TunnelOwner interface. This function is called by Tunnel.operateTunnel when the tunnel has received a new, previously unknown SLOK from the server. The Controller triggers an OSL fetch, as the new SLOK may be sufficient to access new OSLs.

func (*Controller) SignalTunnelFailure

func (controller *Controller) SignalTunnelFailure(tunnel *Tunnel)

SignalTunnelFailure implements the TunnelOwner interface. This function is called by Tunnel.operateTunnel when the tunnel has detected that it has failed. The Controller will signal runTunnels to create a new tunnel and/or remove the tunnel from the list of active tunnels.

func (*Controller) TerminateNextActiveTunnel

func (controller *Controller) TerminateNextActiveTunnel()

TerminateNextActiveTunnel terminates the active tunnel, which will initiate establishment of a new tunnel.

type CustomTLSConfig

type CustomTLSConfig struct {

	// Parameters is the active set of parameters.Parameters to use for the TLS
	// dial. Must not be nil.
	Parameters *parameters.Parameters

	// Dial is the network connection dialer. TLS is layered on top of a new
	// network connection created with dialer. Must not be nil.
	Dial common.Dialer

	// DialAddr overrides the "addr" input to Dial when specified
	DialAddr string

	// UseDialAddrSNI specifies whether to always use the dial "addr"
	// host name in the SNI server_name field. When DialAddr is set,
	// its host name is used.
	UseDialAddrSNI bool

	// SNIServerName specifies the value to set in the SNI
	// server_name field. When blank, SNI is omitted. Note that
	// underlying TLS code also automatically omits SNI when
	// the server_name is an IP address.
	// SNIServerName is ignored when UseDialAddrSNI is true.
	SNIServerName string

	// DisableSystemRootCAs, when true, disables loading system root CAs when
	// verifying the server certificate chain. Set DisableSystemRootCAs only in
	// cases where system root CAs cannot be loaded and there is additional
	// security at the payload level; for example, if unsupported (iOS < 12) or
	// insufficient memory (VPN extension on iOS < 15).
	//
	// When DisableSystemRootCAs is set, VerifyServerName, VerifyPins, and
	// VerifyLegacyCertificate must not be set.
	DisableSystemRootCAs bool

	// VerifyServerName specifies a domain name that must appear in the server
	// certificate. When specified, certificate verification checks for
	// VerifyServerName in the server certificate, in place of the dial or SNI
	// hostname.
	VerifyServerName string

	// VerifyPins specifies one or more certificate pin values, one of which must
	// appear in the verified server certificate chain. A pin value is the
	// base64-encoded SHA2 digest of a certificate's public key. When specified,
	// at least one pin must match at least one certificate in the chain, at any
	// position; e.g., the root CA may be pinned, or the server certificate,
	// etc.
	VerifyPins []string

	// VerifyLegacyCertificate is a special case self-signed server
	// certificate case. Ignores IP SANs and basic constraints. No
	// certificate chain. Just checks that the server presented the
	// specified certificate.
	//
	// When VerifyLegacyCertificate is set, none of VerifyServerName, VerifyPins,
	// SkipVerify may be set.
	VerifyLegacyCertificate *x509.Certificate

	// SkipVerify completely disables server certificate verification.
	//
	// When SkipVerify is set, none of VerifyServerName, VerifyPins,
	// VerifyLegacyCertificate may be set.
	SkipVerify bool

	// TLSProfile specifies a particular indistinguishable TLS profile to use for
	// the TLS dial. Setting TLSProfile allows the caller to pin the selection so
	// all TLS connections in a certain context (e.g. a single meek connection)
	// use a consistent value. The value should be selected by calling
	// SelectTLSProfile, which will pick a value at random, subject to
	// compatibility constraints.
	//
	// When TLSProfile is "", a profile is selected at random and
	// DisableFrontingProviderTLSProfiles is ignored.
	TLSProfile string

	// NoDefaultTLSSessionID specifies whether to set a TLS session ID by
	// default, for a new TLS connection that is not resuming a session.
	// When nil, the parameter is set randomly.
	NoDefaultTLSSessionID *bool

	// RandomizedTLSProfileSeed specifies the PRNG seed to use when generating
	// a randomized TLS ClientHello, which applies to TLS profiles where
	// protocol.TLSProfileIsRandomized is true. The PRNG seed allows for
	// optional replay of a particular randomized Client Hello.
	RandomizedTLSProfileSeed *prng.Seed

	// TLSPadding indicates whether to move or add a TLS padding extension to the
	// front of the exension list and apply the specified padding length. Ignored
	// when 0.
	TLSPadding int

	// TrustedCACertificatesFilename specifies a file containing trusted
	// CA certs. See Config.TrustedCACertificatesFilename.
	TrustedCACertificatesFilename string

	// ObfuscatedSessionTicketKey enables obfuscated session tickets
	// using the specified key.
	ObfuscatedSessionTicketKey string

	// PassthroughMessage, when specified, is a 32 byte value that is sent in the
	// ClientHello random value field. The value should be generated using
	// obfuscator.MakeTLSPassthroughMessage.
	PassthroughMessage []byte

	// FragmentClientHello specifies whether to fragment the ClientHello.
	FragmentClientHello bool
	// contains filtered or unexported fields
}

CustomTLSConfig specifies the parameters for a CustomTLSDial, supporting many TLS-related network obfuscation mechanisms.

func (*CustomTLSConfig) EnableClientSessionCache

func (config *CustomTLSConfig) EnableClientSessionCache()

EnableClientSessionCache initializes a cache to use to persist session tickets, enabling TLS session resumability across multiple CustomTLSDial calls or dialers using the same CustomTLSConfig.

type DNSServerGetter

type DNSServerGetter interface {
	GetDNSServers() []string
}

DNSServerGetter defines the interface to the external GetDNSServers provider which calls into the host application to discover the native network DNS server settings.

type DeviceBinder

type DeviceBinder interface {
	BindToDevice(fileDescriptor int) (string, error)
}

DeviceBinder defines the interface to the external BindToDevice provider which calls into the host application to bind sockets to specific devices. This is used for VPN routing exclusion. The string return value should report device information for diagnostics.

type DialConfig

type DialConfig struct {

	// DiagnosticID is the server ID to record in any diagnostics notices.
	DiagnosticID string

	// UpstreamProxyURL specifies a proxy to connect through.
	// E.g., "http://proxyhost:8080"
	//       "socks5://user:password@proxyhost:1080"
	//       "socks4a://proxyhost:1080"
	//       "http://NTDOMAIN\NTUser:password@proxyhost:3375"
	//
	// Certain tunnel protocols require HTTP CONNECT support
	// when a HTTP proxy is specified. If CONNECT is not
	// supported, those protocols will not connect.
	//
	// UpstreamProxyURL is not used by UDPDial.
	UpstreamProxyURL string

	// CustomHeaders is a set of additional arbitrary HTTP headers that are
	// added to all plaintext HTTP requests and requests made through an HTTP
	// upstream proxy when specified by UpstreamProxyURL.
	CustomHeaders http.Header

	// BPFProgramInstructions specifies a BPF program to attach to the dial
	// socket before connecting.
	BPFProgramInstructions []bpf.RawInstruction

	// DeviceBinder, when not nil, is applied when dialing UDP/TCP. See:
	// DeviceBinder doc.
	DeviceBinder DeviceBinder

	// IPv6Synthesizer, when not nil, is applied when dialing UDP/TCP. See:
	// IPv6Synthesizer doc.
	IPv6Synthesizer IPv6Synthesizer

	// ResolveIP is used to resolve destination domains. ResolveIP should
	// return either at least one IP address or an error.
	ResolveIP func(context.Context, string) ([]net.IP, error)

	// ResolvedIPCallback, when set, is called with the IP address that was
	// dialed. This is either the specified IP address in the dial address,
	// or the resolved IP address in the case where the dial address is a
	// domain name.
	// The callback may be invoked by a concurrent goroutine.
	ResolvedIPCallback func(string)

	// TrustedCACertificatesFilename specifies a file containing trusted
	// CA certs. See Config.TrustedCACertificatesFilename.
	TrustedCACertificatesFilename string

	// FragmentorConfig specifies whether to layer a fragmentor.Conn on top
	// of dialed TCP conns, and the fragmentation configuration to use.
	FragmentorConfig *fragmentor.Config

	// UpstreamProxyErrorCallback is called when a dial fails due to an upstream
	// proxy error. As the upstream proxy is user configured, the error message
	// may need to be relayed to the user.
	UpstreamProxyErrorCallback func(error)

	// CustomDialer overrides the dialer created by NewNetDialer/NewTCPDialer.
	// When CustomDialer is set, all other DialConfig parameters are ignored by
	// NewNetDialer/NewTCPDialer. Other DialConfig consumers may still reference
	// other DialConfig parameters; for example MeekConfig still uses
	// TrustedCACertificatesFilename.
	CustomDialer common.Dialer
}

DialConfig contains parameters to determine the behavior of a Psiphon dialer (TCPDial, UDPDial, MeekDial, etc.)

type DialParameters

type DialParameters struct {
	ServerEntry             *protocol.ServerEntry `json:"-"`
	NetworkID               string                `json:"-"`
	IsReplay                bool                  `json:"-"`
	CandidateNumber         int                   `json:"-"`
	EstablishedTunnelsCount int                   `json:"-"`

	IsExchanged bool

	LastUsedTimestamp       time.Time
	LastUsedConfigStateHash []byte
	LastUsedServerEntryHash []byte

	NetworkLatencyMultiplier float64

	TunnelProtocol string

	DirectDialAddress              string
	DialPortNumber                 string
	UpstreamProxyType              string   `json:"-"`
	UpstreamProxyCustomHeaderNames []string `json:"-"`

	BPFProgramName         string
	BPFProgramInstructions []bpf.RawInstruction

	SelectedSSHClientVersion bool
	SSHClientVersion         string
	SSHKEXSeed               *prng.Seed

	ObfuscatorPaddingSeed                   *prng.Seed
	OSSHObfuscatorSeedTransformerParameters *transforms.ObfuscatorSeedTransformerParameters

	OSSHPrefixSpec        *obfuscator.OSSHPrefixSpec
	OSSHPrefixSplitConfig *obfuscator.OSSHPrefixSplitConfig

	FragmentorSeed *prng.Seed

	FrontingProviderID string

	MeekFrontingDialAddress   string
	MeekFrontingHost          string
	MeekDialAddress           string
	MeekTransformedHostName   bool
	MeekSNIServerName         string
	MeekVerifyServerName      string
	MeekVerifyPins            []string
	MeekHostHeader            string
	MeekObfuscatorPaddingSeed *prng.Seed
	MeekResolvedIPAddress     atomic.Value `json:"-"`

	TLSOSSHTransformedSNIServerName bool
	TLSOSSHSNIServerName            string
	TLSOSSHObfuscatorPaddingSeed    *prng.Seed

	SelectedUserAgent bool
	UserAgent         string

	SelectedTLSProfile       bool
	TLSProfile               string
	NoDefaultTLSSessionID    bool
	TLSVersion               string
	RandomizedTLSProfileSeed *prng.Seed
	TLSFragmentClientHello   bool

	QUICVersion                              string
	QUICDialSNIAddress                       string
	QUICClientHelloSeed                      *prng.Seed
	ObfuscatedQUICPaddingSeed                *prng.Seed
	ObfuscatedQUICNonceTransformerParameters *transforms.ObfuscatorSeedTransformerParameters
	QUICDisablePathMTUDiscovery              bool

	ConjureCachedRegistrationTTL        time.Duration
	ConjureAPIRegistration              bool
	ConjureAPIRegistrarBidirectionalURL string
	ConjureAPIRegistrarDelay            time.Duration
	ConjureDecoyRegistration            bool
	ConjureDecoyRegistrarDelay          time.Duration
	ConjureDecoyRegistrarWidth          int
	ConjureTransport                    string
	ConjureSTUNServerAddress            string
	ConjureDTLSEmptyInitialPacket       bool

	LivenessTestSeed *prng.Seed

	APIRequestPaddingSeed *prng.Seed

	HoldOffTunnelDuration time.Duration

	DialConnMetrics          common.MetricsSource       `json:"-"`
	DialConnNoticeMetrics    common.NoticeMetricsSource `json:"-"`
	ObfuscatedSSHConnMetrics common.MetricsSource       `json:"-"`

	DialDuration time.Duration `json:"-"`

	ResolveParameters *resolver.ResolveParameters

	HTTPTransformerParameters *transforms.HTTPTransformerParameters

	SteeringIP string

	InproxySTUNDialParameters   *InproxySTUNDialParameters
	InproxyWebRTCDialParameters *InproxyWebRTCDialParameters
	// contains filtered or unexported fields
}

DialParameters represents a selected protocol and all the related selected protocol attributes, many chosen at random, for a tunnel dial attempt.

DialParameters is used: - to configure dialers - as a persistent record to store successful dial parameters for replay - to report dial stats in notices and Psiphon API calls.

MeekResolvedIPAddress is set asynchronously, as it is not known until the dial process has begun. The atomic.Value will contain a string, initialized to "", and set to the resolved IP address once that part of the dial process has completed.

DialParameters is not safe for concurrent use.

func GetAffinityServerEntryAndDialParameters

func GetAffinityServerEntryAndDialParameters(
	networkID string) (protocol.ServerEntryFields, *DialParameters, error)

GetAffinityServerEntryAndDialParameters fetches the current affinity server entry value and any corresponding dial parameters for the specified network ID. An error is returned when no affinity server is available. The DialParameter output may be nil when a server entry is found but has no dial parameters.

func GetDialParameters

func GetDialParameters(
	config *Config, serverIPAddress, networkID string) (*DialParameters, error)

GetDialParameters fetches any dial parameters associated with the specified server/network ID. Returns nil, nil when no record is found.

func MakeDialParameters

func MakeDialParameters(
	config *Config,
	steeringIPCache *lrucache.Cache,
	upstreamProxyErrorCallback func(error),
	canReplay func(serverEntry *protocol.ServerEntry, replayProtocol string) bool,
	selectProtocol func(serverEntry *protocol.ServerEntry) (string, bool),
	serverEntry *protocol.ServerEntry,
	inproxyClientBrokerClientManager *InproxyBrokerClientManager,
	inproxyClientNATStateManager *InproxyNATStateManager,
	isTactics bool,
	candidateNumber int,
	establishedTunnelsCount int) (*DialParameters, error)

MakeDialParameters creates a new DialParameters for the candidate server entry, including selecting a protocol and all the various protocol attributes. The input selectProtocol is used to comply with any active protocol selection constraints.

When stored dial parameters are available and may be used, MakeDialParameters may replay previous dial parameters in an effort to leverage "known working" values instead of always chosing at random from a large space.

MakeDialParameters will return nil/nil in cases where the candidate server entry should be skipped.

To support replay, the caller must call DialParameters.Succeeded when a successful tunnel is established with the returned DialParameters; and must call DialParameters.Failed when a tunnel dial or activation fails, except when establishment is cancelled.

func (*DialParameters) Failed

func (dialParams *DialParameters) Failed(config *Config)

func (*DialParameters) GetDialConfig

func (dialParams *DialParameters) GetDialConfig() *DialConfig

func (*DialParameters) GetInproxyMetrics

func (dialParams *DialParameters) GetInproxyMetrics() common.LogFields

func (*DialParameters) GetMeekConfig

func (dialParams *DialParameters) GetMeekConfig() *MeekConfig

func (*DialParameters) GetNetworkType

func (dialParams *DialParameters) GetNetworkType() string

func (*DialParameters) GetTLSOSSHConfig

func (dialParams *DialParameters) GetTLSOSSHConfig(config *Config) *TLSTunnelConfig

func (*DialParameters) GetTLSVersionForMetrics

func (dialParams *DialParameters) GetTLSVersionForMetrics() string

func (*DialParameters) Succeeded

func (dialParams *DialParameters) Succeeded()

type ExchangedDialParameters

type ExchangedDialParameters struct {
	TunnelProtocol string
}

ExchangedDialParameters represents the subset of DialParameters that is shared in a client-to-client exchange of server connection info.

The purpose of client-to-client exchange if for one user that can connect to help another user that cannot connect by sharing their connected configuration, including the server entry and dial parameters.

There are two concerns regarding which dial parameter fields are safe to exchange:

  • Unlike signed server entries, there's no independent trust anchor that can certify that the exchange data is valid.

  • While users should only perform the exchange with trusted peers, the user's trust in their peer may be misplaced.

This presents the possibility of attack such as the peer sending dial parameters that could be used to trace/monitor/flag the importer; or sending dial parameters, including dial address and SNI, to cause the peer to appear to connect to a banned service.

To mitigate these risks, only a subset of dial parameters are exchanged. When exchanged dial parameters and imported and used, all unexchanged parameters are generated locally. At this time, only the tunnel protocol is exchanged. We consider tunnel protocol selection one of the key connection success factors.

In addition, the exchange peers may not be on the same network with the same blocking and circumvention characteristics, which is another reason to limit exchanged dial parameter values to broadly applicable fields.

Unlike the exchanged (and otherwise acquired) server entry, ExchangedDialParameters does not use the ServerEntry_Fields_ representation which allows older clients to receive and store new, unknown fields. Such a facility is less useful in this case, since exchanged dial parameters and used immediately and have a short lifespan.

TODO: exchange more dial parameters, such as TLS profile, QUIC version, etc.

func NewExchangedDialParameters

func NewExchangedDialParameters(dialParams *DialParameters) *ExchangedDialParameters

NewExchangedDialParameters creates a new ExchangedDialParameters from a DialParameters, including only the exchanged values. NewExchangedDialParameters assumes the input DialParameters has been initialized and populated by MakeDialParameters.

func (*ExchangedDialParameters) MakeDialParameters

func (dialParams *ExchangedDialParameters) MakeDialParameters(
	config *Config,
	p parameters.ParametersAccessor,
	serverEntry *protocol.ServerEntry) *DialParameters

MakeDialParameters creates a new, partially intitialized DialParameters from the values in ExchangedDialParameters. The returned DialParameters must not be used directly for dialing. It is intended to be stored, and then later fully initialized by MakeDialParameters.

func (*ExchangedDialParameters) Validate

func (dialParams *ExchangedDialParameters) Validate(serverEntry *protocol.ServerEntry) error

Validate checks that the ExchangedDialParameters contains only valid values and is compatible with the specified server entry.

type FileMigration

type FileMigration struct {

	// Name is the name of the migration for logging because file paths are not
	// logged as they may contain sensitive information.
	Name string

	// OldPath is the current location of the file.
	OldPath string

	// NewPath is the location that the file should be moved to.
	NewPath string

	// IsDir should be set to true if the file is a directory.
	IsDir bool
}

FileMigration represents the action of moving a file, or directory, to a new location.

type HasIPv6RouteGetter

type HasIPv6RouteGetter interface {
	// TODO: change to bool return value once gobind supports that type
	HasIPv6Route() int
}

HasIPv6RouteGetter defines the interface to the external HasIPv6Route provider which calls into the host application to determine if the host has an IPv6 route.

type HttpProxy

type HttpProxy struct {
	// contains filtered or unexported fields
}

HttpProxy is a HTTP server that relays HTTP requests through the Psiphon tunnel. It includes support for HTTP CONNECT.

This proxy also offers a "URL proxy" mode that relays requests for HTTP or HTTPS or URLs specified in the proxy request path. This mode relays either through the Psiphon tunnel, or directly.

An example use case for tunneled URL proxy relays is to craft proxied URLs to pass to components that don't support HTTP or SOCKS proxy settings. For example, the Android Media Player (http://developer.android.com/reference/android/media/MediaPlayer.html). To make the Media Player use the Psiphon tunnel, construct a URL such as: "http://127.0.0.1:<proxy-port>/tunneled/<origin media URL>"; and pass this to the player. The <origin media URL> must be escaped in such a way that it can be used inside a URL query.

An example use case for direct, untunneled, relaying is to make use of Go's TLS stack for HTTPS requests in cases where the native TLS stack is lacking (e.g., WinHTTP on Windows XP). The URL for direct relaying is: "http://127.0.0.1:<proxy-port>/direct/<origin URL>". Again, the <origin URL> must be escaped in such a way that it can be used inside a URL query.

An example use case for tunneled relaying with rewriting (/tunneled-rewrite/) is when the content of retrieved files contains URLs that also need to be modified to be tunneled. For example, in iOS 10 the UIWebView media player does not put requests through the NSURLProtocol, so they are not tunneled. Instead, we rewrite those URLs to use the URL proxy, and rewrite retrieved playlist files so they also contain proxied URLs.

The URL proxy offers /tunneled-icy/ which is compatible with both HTTP and ICY protocol resources.

Origin URLs must include the scheme prefix ("http://" or "https://") and must be URL encoded.

func NewHttpProxy

func NewHttpProxy(
	config *Config,
	tunneler Tunneler,
	listenIP string) (proxy *HttpProxy, err error)

NewHttpProxy initializes and runs a new HTTP proxy server.

func (*HttpProxy) Close

func (proxy *HttpProxy) Close()

Close terminates the HTTP server.

func (*HttpProxy) ServeHTTP

func (proxy *HttpProxy) ServeHTTP(responseWriter http.ResponseWriter, request *http.Request)

ServeHTTP receives HTTP requests and proxies them. CONNECT requests are hijacked and all data is relayed. Other HTTP requests are proxied with explicit round trips. In both cases, the tunnel is used for proxied traffic.

Implementation is based on:

https://github.com/justmao945/mallory Copyright (c) 2014 JianjunMao The MIT License (MIT)

https://golang.org/src/pkg/net/http/httputil/reverseproxy.go Copyright 2011 The Go Authors. All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.

type IPv6Synthesizer

type IPv6Synthesizer interface {
	IPv6Synthesize(IPv4Addr string) string
}

IPv6Synthesizer defines the interface to the external IPv6Synthesize provider which calls into the host application to synthesize IPv6 addresses from IPv4 ones. This is used to correctly lookup IPs on DNS64/NAT64 networks.

type InproxyBrokerClientInstance

type InproxyBrokerClientInstance struct {
	// contains filtered or unexported fields
}

InproxyBrokerClientInstance pairs an inproxy.BrokerClient instance with an implementation of the inproxy.BrokerDialCoordinator interface and the associated, underlying broker dial parameters. InproxyBrokerClientInstance implements broker client dial replay.

func NewInproxyBrokerClientInstance

func NewInproxyBrokerClientInstance(
	config *Config,
	brokerClientManager *InproxyBrokerClientManager,
	networkID string,
	isProxy bool) (*InproxyBrokerClientInstance, error)

NewInproxyBrokerClientInstance creates a new InproxyBrokerClientInstance. NewInproxyBrokerClientManager does not perform any network operations; the new InproxyBrokerClientInstance is initialized when used for a round trip.

func (*InproxyBrokerClientInstance) AnnounceDelay

func (b *InproxyBrokerClientInstance) AnnounceDelay() time.Duration

Implements the inproxy.BrokerDialCoordinator interface.

func (*InproxyBrokerClientInstance) AnnounceDelayJitter

func (b *InproxyBrokerClientInstance) AnnounceDelayJitter() float64

Implements the inproxy.BrokerDialCoordinator interface.

func (*InproxyBrokerClientInstance) AnnounceRequestTimeout

func (b *InproxyBrokerClientInstance) AnnounceRequestTimeout() time.Duration

Implements the inproxy.BrokerDialCoordinator interface.

func (*InproxyBrokerClientInstance) AnswerRequestTimeout

func (b *InproxyBrokerClientInstance) AnswerRequestTimeout() time.Duration

Implements the inproxy.BrokerDialCoordinator interface.

func (*InproxyBrokerClientInstance) BrokerClientPrivateKey

func (b *InproxyBrokerClientInstance) BrokerClientPrivateKey() inproxy.SessionPrivateKey

Implements the inproxy.BrokerDialCoordinator interface.

func (*InproxyBrokerClientInstance) BrokerClientRoundTripper

func (b *InproxyBrokerClientInstance) BrokerClientRoundTripper() (inproxy.RoundTripper, error)

Implements the inproxy.BrokerDialCoordinator interface.

func (*InproxyBrokerClientInstance) BrokerClientRoundTripperFailed

func (b *InproxyBrokerClientInstance) BrokerClientRoundTripperFailed(roundTripper inproxy.RoundTripper)

Implements the inproxy.BrokerDialCoordinator interface.

func (*InproxyBrokerClientInstance) BrokerClientRoundTripperSucceeded

func (b *InproxyBrokerClientInstance) BrokerClientRoundTripperSucceeded(roundTripper inproxy.RoundTripper)

Implements the inproxy.BrokerDialCoordinator interface.

func (*InproxyBrokerClientInstance) BrokerPublicKey

Implements the inproxy.BrokerDialCoordinator interface.

func (*InproxyBrokerClientInstance) BrokerRootObfuscationSecret

func (b *InproxyBrokerClientInstance) BrokerRootObfuscationSecret() inproxy.ObfuscationSecret

Implements the inproxy.BrokerDialCoordinator interface.

func (*InproxyBrokerClientInstance) Close

Close closes the broker client round tripped, including closing all underlying network connections, which will interrupt any in-flight round trips.

func (*InproxyBrokerClientInstance) CommonCompartmentIDs

func (b *InproxyBrokerClientInstance) CommonCompartmentIDs() []inproxy.ID

Implements the inproxy.BrokerDialCoordinator interface.

func (*InproxyBrokerClientInstance) NetworkID

func (b *InproxyBrokerClientInstance) NetworkID() string

Implements the inproxy.BrokerDialCoordinator interface.

func (*InproxyBrokerClientInstance) NetworkType

Implements the inproxy.BrokerDialCoordinator interface.

func (*InproxyBrokerClientInstance) OfferRequestTimeout

func (b *InproxyBrokerClientInstance) OfferRequestTimeout() time.Duration

Implements the inproxy.BrokerDialCoordinator interface.

func (*InproxyBrokerClientInstance) OfferRetryDelay

func (b *InproxyBrokerClientInstance) OfferRetryDelay() time.Duration

Implements the inproxy.BrokerDialCoordinator interface.

func (*InproxyBrokerClientInstance) OfferRetryJitter

func (b *InproxyBrokerClientInstance) OfferRetryJitter() float64

Implements the inproxy.BrokerDialCoordinator interface.

func (*InproxyBrokerClientInstance) PersonalCompartmentIDs

func (b *InproxyBrokerClientInstance) PersonalCompartmentIDs() []inproxy.ID

Implements the inproxy.BrokerDialCoordinator interface.

func (*InproxyBrokerClientInstance) RelayedPacketRequestTimeout

func (b *InproxyBrokerClientInstance) RelayedPacketRequestTimeout() time.Duration

Implements the inproxy.BrokerDialCoordinator interface.

func (*InproxyBrokerClientInstance) SessionHandshakeRoundTripTimeout

func (b *InproxyBrokerClientInstance) SessionHandshakeRoundTripTimeout() time.Duration

Implements the inproxy.BrokerDialCoordinator interface.

type InproxyBrokerClientManager

type InproxyBrokerClientManager struct {
	// contains filtered or unexported fields
}

InproxyBrokerClientManager manages an InproxyBrokerClientInstance, an in-proxy broker client, and its associated broker dial parameters, that may be shared by multiple client dials or proxy instances. There is no explicit close operation for the managed InproxyBrokerClientInstance.

Once used, the current InproxyBrokerClientInstance and its broker client is left actively connected to the broker, to minimize transport round trips for additional requests.

The InproxyBrokerClientManager and its components implement a replay system for broker client dials. As one broker client is shared access multiple client in-proxy dials, the broker dial parameters are replayed independently from tunnel dial parameters.

The NewInproxyBrokerClientInstance layer provides a fixed association between a broker client and its broker dial parameters, ensuring that in-proxy success/failure callbacks reference the correct replay parameters when setting or clearing replay.

A new InproxyBrokerClientInstance, including the broker dial parameters and broker client, is instantiated when the active network ID changes, using tactics for the new network.

func NewInproxyBrokerClientManager

func NewInproxyBrokerClientManager(
	config *Config, isProxy bool) *InproxyBrokerClientManager

NewInproxyBrokerClientManager creates a new InproxyBrokerClientManager. NewInproxyBrokerClientManager does not perform any network operations; the managed InproxyBrokerClientInstance is initialized when used for a round trip.

func (*InproxyBrokerClientManager) GetBrokerClient

GetBrokerClient returns the current, shared broker client and its corresponding dial parametrers (for metrics logging). If there is no current broker client, if the network ID differs from the network ID associated with the previous broker client, a new broker client is initialized.

func (*InproxyBrokerClientManager) TacticsApplied

func (b *InproxyBrokerClientManager) TacticsApplied() error

TacticsApplied implements the TacticsAppliedReceiver interface, and is called when tactics have changed, which triggers a broker client reset in order to apply potentially changed parameters.

type InproxyBrokerDialParameters

type InproxyBrokerDialParameters struct {
	LastUsedTimestamp      time.Time
	LastUsedBrokerSpecHash []byte

	NetworkLatencyMultiplier float64

	BrokerTransport string

	DialAddress string

	FrontingProviderID  string
	FrontingDialAddress string
	SNIServerName       string
	TransformedHostName bool
	VerifyServerName    string
	VerifyPins          []string
	HostHeader          string
	ResolvedIPAddress   atomic.Value `json:"-"`

	TLSProfile               string
	TLSVersion               string
	RandomizedTLSProfileSeed *prng.Seed
	NoDefaultTLSSessionID    bool
	TLSFragmentClientHello   bool

	SelectedUserAgent bool
	UserAgent         string

	BPFProgramName         string
	BPFProgramInstructions []bpf.RawInstruction

	FragmentorSeed *prng.Seed

	ResolveParameters *resolver.ResolveParameters
	// contains filtered or unexported fields
}

InproxyBrokerDialParameters represents a selected broker transport and dial paramaters.

InproxyBrokerDialParameters is used to configure dialers; as a persistent record to store successful dial parameters for replay; and to report dial stats in notices and Psiphon API calls.

InproxyBrokerDialParameters is similar to tunnel DialParameters, but is specific to the in-proxy broker dial phase.

func MakeInproxyBrokerDialParameters

func MakeInproxyBrokerDialParameters(
	config *Config,
	p parameters.ParametersAccessor,
	networkID string,
	brokerSpec *parameters.InproxyBrokerSpec) (*InproxyBrokerDialParameters, error)

MakeInproxyBrokerDialParameters creates a new InproxyBrokerDialParameters.

func (*InproxyBrokerDialParameters) GetMetrics

func (brokerDialParams *InproxyBrokerDialParameters) GetMetrics() common.LogFields

GetMetrics implements the common.MetricsSource interface and returns log fields detailing the broker dial parameters.

type InproxyBrokerRoundTripper

type InproxyBrokerRoundTripper struct {
	// contains filtered or unexported fields
}

InproxyBrokerRoundTripper is a broker request round trip transport implemented using MeekConn in MeekModePlaintextRoundTrip mode, utilizing MeekConn's domain fronting capabilities and using persistent and multiplexed connections, via HTTP/2, to support multiple concurrent in-flight round trips.

InproxyBrokerRoundTripper implements the inproxy.RoundTripper interface.

func NewInproxyBrokerRoundTripper

func NewInproxyBrokerRoundTripper(
	p parameters.ParametersAccessor,
	brokerDialParams *InproxyBrokerDialParameters) *InproxyBrokerRoundTripper

NewInproxyBrokerRoundTripper creates a new InproxyBrokerRoundTripper. The initial DialMeek is defered until the first call to RoundTrip, so NewInproxyBrokerRoundTripper does not perform any network operations.

The input brokerDialParams dial parameter and config fields must not modifed after NewInproxyBrokerRoundTripper is called.

func (*InproxyBrokerRoundTripper) Close

func (rt *InproxyBrokerRoundTripper) Close() error

Close interrupts any in-flight request and closes the underlying MeekConn.

func (*InproxyBrokerRoundTripper) RoundTrip

func (rt *InproxyBrokerRoundTripper) RoundTrip(
	ctx context.Context,
	roundTripDelay time.Duration,
	roundTripTimeout time.Duration,
	requestPayload []byte) (_ []byte, retErr error)

RoundTrip transports a request to the broker endpoint and returns a response.

type InproxyNATStateManager

type InproxyNATStateManager struct {
	// contains filtered or unexported fields
}

InproxyNATStateManager manages the NAT-related network topology state for the current network, caching the discovered network NAT type and supported port mapping types, if any.

func NewInproxyNATStateManager

func NewInproxyNATStateManager(config *Config) *InproxyNATStateManager

NewInproxyNATStateManager creates a new InproxyNATStateManager.

func (*InproxyNATStateManager) TacticsApplied

func (s *InproxyNATStateManager) TacticsApplied() error

TacticsApplied implements the TacticsAppliedReceiver interface, and is called when tactics have changed, which triggers a cached NAT state reset in order to apply potentially changed parameters.

type InproxySTUNDialParameters

type InproxySTUNDialParameters struct {
	ResolveParameters        *resolver.ResolveParameters
	STUNServerAddress        string
	STUNServerAddressRFC5780 string

	STUNServerResolvedIPAddress        atomic.Value `json:"-"`
	STUNServerRFC5780ResolvedIPAddress atomic.Value `json:"-"`
}

InproxySTUNDialParameters is a set of STUN dial parameters. InproxySTUNDialParameters is compatible with DialParameters JSON marshaling. For client in-proxy tunnel dials, DialParameters will manage STUN dial parameter selection and replay.

When an instance of InproxySTUNDialParameters is unmarshaled from JSON, Prepare must be called to initialize the instance for use.

func MakeInproxySTUNDialParameters

func MakeInproxySTUNDialParameters(
	config *Config,
	p parameters.ParametersAccessor,
	isProxy bool) (*InproxySTUNDialParameters, error)

MakeInproxySTUNDialParameters generates new STUN dial parameters from the given tactics parameters.

func (*InproxySTUNDialParameters) GetMetrics

func (dialParams *InproxySTUNDialParameters) GetMetrics() common.LogFields

GetMetrics implements the common.MetricsSource interface and returns log fields detailing the STUN dial parameters.

func (*InproxySTUNDialParameters) IsValidClientReplay

func (dialParams *InproxySTUNDialParameters) IsValidClientReplay(
	p parameters.ParametersAccessor) bool

IsValidClientReplay checks that the selected STUN servers remain configured STUN server candidates for in-proxy clients.

func (*InproxySTUNDialParameters) Prepare

func (dialParams *InproxySTUNDialParameters) Prepare()

Prepare initializes an InproxySTUNDialParameters for use. Prepare should be called for any InproxySTUNDialParameters instance unmarshaled from JSON.

type InproxyWebRTCDialInstance

type InproxyWebRTCDialInstance struct {
	// contains filtered or unexported fields
}

InproxyWebRTCDialInstance is the network state and dial parameters for a single WebRTC client or proxy connection.

InproxyWebRTCDialInstance implements the inproxy.WebRTCDialCoordinator interface, which provides the WebRTC dial configuration and support to the in-proxy package.

func NewInproxyWebRTCDialInstance

func NewInproxyWebRTCDialInstance(
	config *Config,
	networkID string,
	isProxy bool,
	natStateManager *InproxyNATStateManager,
	stunDialParameters *InproxySTUNDialParameters,
	webRTCDialParameters *InproxyWebRTCDialParameters) (*InproxyWebRTCDialInstance, error)

NewInproxyWebRTCDialInstance creates a new InproxyWebRTCDialInstance.

The caller provides STUN and WebRTC dial parameters that are either newly generated or replayed. Proxies may optionally pass in nil for either stunDialParameters or webRTCDialParameters, and new parameters will be generated.

func (*InproxyWebRTCDialInstance) BindToDevice

func (w *InproxyWebRTCDialInstance) BindToDevice(fileDescriptor int) error

Implements the inproxy.WebRTCDialCoordinator interface.

func (*InproxyWebRTCDialInstance) ClientRootObfuscationSecret

func (w *InproxyWebRTCDialInstance) ClientRootObfuscationSecret() inproxy.ObfuscationSecret

Implements the inproxy.WebRTCDialCoordinator interface.

func (*InproxyWebRTCDialInstance) DataChannelTrafficShapingParameters

func (w *InproxyWebRTCDialInstance) DataChannelTrafficShapingParameters() *inproxy.DataChannelTrafficShapingParameters

Implements the inproxy.WebRTCDialCoordinator interface.

func (*InproxyWebRTCDialInstance) DisableIPv6ICECandidates

func (w *InproxyWebRTCDialInstance) DisableIPv6ICECandidates() bool

Implements the inproxy.WebRTCDialCoordinator interface.

func (*InproxyWebRTCDialInstance) DisableInboundForMobileNetworks

func (w *InproxyWebRTCDialInstance) DisableInboundForMobileNetworks() bool

Implements the inproxy.WebRTCDialCoordinator interface.

func (*InproxyWebRTCDialInstance) DisablePortMapping

func (w *InproxyWebRTCDialInstance) DisablePortMapping() bool

Implements the inproxy.WebRTCDialCoordinator interface.

func (*InproxyWebRTCDialInstance) DisableSTUN

func (w *InproxyWebRTCDialInstance) DisableSTUN() bool

Implements the inproxy.WebRTCDialCoordinator interface.

func (*InproxyWebRTCDialInstance) DiscoverNAT

func (w *InproxyWebRTCDialInstance) DiscoverNAT() bool

Implements the inproxy.WebRTCDialCoordinator interface.

func (*InproxyWebRTCDialInstance) DiscoverNATTimeout

func (w *InproxyWebRTCDialInstance) DiscoverNATTimeout() time.Duration

Implements the inproxy.WebRTCDialCoordinator interface.

func (*InproxyWebRTCDialInstance) DoDTLSRandomization

func (w *InproxyWebRTCDialInstance) DoDTLSRandomization() bool

Implements the inproxy.WebRTCDialCoordinator interface.

func (*InproxyWebRTCDialInstance) NATType

Implements the inproxy.WebRTCDialCoordinator interface.

func (*InproxyWebRTCDialInstance) NetworkID

func (w *InproxyWebRTCDialInstance) NetworkID() string

Implements the inproxy.WebRTCDialCoordinator interface.

func (*InproxyWebRTCDialInstance) NetworkType

Implements the inproxy.WebRTCDialCoordinator interface.

func (*InproxyWebRTCDialInstance) PortMappingTypes

func (w *InproxyWebRTCDialInstance) PortMappingTypes() inproxy.PortMappingTypes

Implements the inproxy.WebRTCDialCoordinator interface.

func (*InproxyWebRTCDialInstance) ProxyDestinationDialTimeout

func (w *InproxyWebRTCDialInstance) ProxyDestinationDialTimeout() time.Duration

Implements the inproxy.WebRTCDialCoordinator interface.

func (*InproxyWebRTCDialInstance) ProxyUpstreamDial

func (w *InproxyWebRTCDialInstance) ProxyUpstreamDial(
	ctx context.Context, network, address string) (net.Conn, error)

func (*InproxyWebRTCDialInstance) ResolveAddress

func (w *InproxyWebRTCDialInstance) ResolveAddress(ctx context.Context, network, address string) (string, error)

Implements the inproxy.WebRTCDialCoordinator interface.

func (*InproxyWebRTCDialInstance) STUNServerAddress

func (w *InproxyWebRTCDialInstance) STUNServerAddress(RFC5780 bool) string

Implements the inproxy.WebRTCDialCoordinator interface.

func (*InproxyWebRTCDialInstance) STUNServerAddressFailed

func (w *InproxyWebRTCDialInstance) STUNServerAddressFailed(RFC5780 bool, address string)

Implements the inproxy.WebRTCDialCoordinator interface.

func (*InproxyWebRTCDialInstance) STUNServerAddressResolved

func (w *InproxyWebRTCDialInstance) STUNServerAddressResolved(RFC5780 bool) string

Implements the inproxy.WebRTCDialCoordinator interface.

func (*InproxyWebRTCDialInstance) STUNServerAddressSucceeded

func (w *InproxyWebRTCDialInstance) STUNServerAddressSucceeded(RFC5780 bool, address string)

Implements the inproxy.WebRTCDialCoordinator interface.

func (*InproxyWebRTCDialInstance) SetNATType

func (w *InproxyWebRTCDialInstance) SetNATType(natType inproxy.NATType)

Implements the inproxy.WebRTCDialCoordinator interface.

func (*InproxyWebRTCDialInstance) SetPortMappingTypes

func (w *InproxyWebRTCDialInstance) SetPortMappingTypes(portMappingTypes inproxy.PortMappingTypes)

Implements the inproxy.WebRTCDialCoordinator interface.

func (*InproxyWebRTCDialInstance) UDPConn

func (w *InproxyWebRTCDialInstance) UDPConn(
	ctx context.Context, network, remoteAddress string) (net.PacketConn, error)

Implements the inproxy.WebRTCDialCoordinator interface.

func (*InproxyWebRTCDialInstance) UDPListen

Implements the inproxy.WebRTCDialCoordinator interface.

func (*InproxyWebRTCDialInstance) WebRTCAnswerTimeout

func (w *InproxyWebRTCDialInstance) WebRTCAnswerTimeout() time.Duration

Implements the inproxy.WebRTCDialCoordinator interface.

func (*InproxyWebRTCDialInstance) WebRTCAwaitDataChannelTimeout

func (w *InproxyWebRTCDialInstance) WebRTCAwaitDataChannelTimeout() time.Duration

Implements the inproxy.WebRTCDialCoordinator interface.

type InproxyWebRTCDialParameters

type InproxyWebRTCDialParameters struct {
	RootObfuscationSecret               inproxy.ObfuscationSecret
	DataChannelTrafficShapingParameters *inproxy.DataChannelTrafficShapingParameters
	DoDTLSRandomization                 bool
}

InproxyWebRTCDialParameters is a set of WebRTC obfuscation dial parameters. InproxyWebRTCDialParameters is compatible with DialParameters JSON marshaling. For client in-proxy tunnel dials, DialParameters will manage WebRTC dial parameter selection and replay.

func MakeInproxyWebRTCDialParameters

func MakeInproxyWebRTCDialParameters(
	p parameters.ParametersAccessor) (*InproxyWebRTCDialParameters, error)

MakeInproxyWebRTCDialParameters generates new InproxyWebRTCDialParameters.

func (*InproxyWebRTCDialParameters) GetMetrics

func (dialParams *InproxyWebRTCDialParameters) GetMetrics() common.LogFields

GetMetrics implements the common.MetricsSource interface.

type MeekConfig

type MeekConfig struct {

	// DiagnosticID is the server ID to record in any diagnostics notices.
	DiagnosticID string

	// Parameters is the active set of parameters.Parameters to use
	// for the meek dial.
	Parameters *parameters.Parameters

	// Mode selects the mode of operation:
	//
	// MeekModeRelay: encapsulates net.Conn flows in HTTP requests and responses;
	// secures and obfuscates metadata in an encrypted HTTP cookie, making it
	// suitable for non-TLS HTTP and HTTPS with unverifed server certificates;
	// the caller is responsible for securing and obfuscating the net.Conn flows;
	// the origin server should be a meek server; used for the meek tunnel
	// protocols.
	//
	// MeekModeObfuscatedRoundTrip: enables ObfuscatedRoundTrip, which performs
	// HTTP round trips; secures and obfuscates metadata, including the end point
	// (or path), in an encrypted HTTP cookie, making it suitable for non-TLS
	// HTTP and HTTPS with unverifed server certificates; the caller is
	// responsible for securing and obfuscating request/response payloads; the
	// origin server should be a meek server; used for tactics requests.
	//
	// MeekModePlaintextRoundTrip: enables RoundTrip; the MeekConn is an
	// http.RoundTripper; there are no security or obfuscation measures at the
	// HTTP level; TLS and server certificate verification is required; the
	// origin server may be any HTTP(S) server.
	//
	// As with the other modes, MeekModePlaintextRoundTrip supports HTTP/2 with
	// utls, and integration with DialParameters for replay -- which are not
	// otherwise implemented if using just CustomTLSDialer and net.http.
	Mode MeekMode

	// DialAddress is the actual network address to dial to establish a
	// connection to the meek server. This may be either a fronted or
	// direct address. The address must be in the form "host:port",
	// where host may be a domain name or IP address.
	DialAddress string

	// UseQUIC indicates whether to use HTTP/2 over QUIC.
	UseQUIC bool

	// QUICVersion indicates which QUIC version to use.
	QUICVersion string

	// QUICClientHelloSeed is used for randomized QUIC Client Hellos.
	QUICClientHelloSeed *prng.Seed

	// QUICDisablePathMTUDiscovery indicates whether to disable path MTU
	// discovery in the QUIC client.
	QUICDisablePathMTUDiscovery bool

	// UseHTTPS indicates whether to use HTTPS (true) or HTTP (false).
	UseHTTPS bool

	// TLSProfile specifies the value for CustomTLSConfig.TLSProfile for all
	// underlying TLS connections created by this meek connection.
	TLSProfile string

	// TLSFragmentClientHello specifies whether to fragment the TLS Client Hello.
	TLSFragmentClientHello bool

	// LegacyPassthrough indicates that the server expects a legacy passthrough
	// message.
	LegacyPassthrough bool

	// NoDefaultTLSSessionID specifies the value for
	// CustomTLSConfig.NoDefaultTLSSessionID for all underlying TLS connections
	// created by this meek connection.
	NoDefaultTLSSessionID bool

	// RandomizedTLSProfileSeed specifies the value for
	// CustomTLSConfig.RandomizedTLSProfileSeed for all underlying TLS
	// connections created by this meek connection.
	RandomizedTLSProfileSeed *prng.Seed

	// UseObfuscatedSessionTickets indicates whether to use obfuscated session
	// tickets. Assumes UseHTTPS is true. Ignored for MeekModePlaintextRoundTrip.
	UseObfuscatedSessionTickets bool

	// SNIServerName is the value to place in the TLS/QUIC SNI server_name field
	// when HTTPS or QUIC is used.
	SNIServerName string

	// HostHeader is the value to place in the HTTP request Host header.
	HostHeader string

	// TransformedHostName records whether a hostname transformation is
	// in effect. This value is used for stats reporting.
	TransformedHostName bool

	// AddPsiphonFrontingHeader specifies whether to add the
	// X-Psiphon-Fronting-Address custom header.
	AddPsiphonFrontingHeader bool

	// VerifyServerName specifies a domain name that must appear in the server
	// certificate. When blank, server certificate verification is disabled.
	VerifyServerName string

	// VerifyPins specifies one or more certificate pin values, one of which must
	// appear in the verified server certificate chain. A pin value is the
	// base64-encoded SHA2 digest of a certificate's public key. When specified,
	// at least one pin must match at least one certificate in the chain, at any
	// position; e.g., the root CA may be pinned, or the server certificate,
	// etc.
	VerifyPins []string

	// DisableSystemRootCAs, when true, disables loading system root CAs when
	// verifying the server certificate chain. Set DisableSystemRootCAs only in
	// cases where system root CAs cannot be loaded and there is additional
	// security at the payload level; for example, if unsupported (iOS < 12) or
	// insufficient memory (VPN extension on iOS < 15).
	//
	// When DisableSystemRootCAs is set, both VerifyServerName and VerifyPins
	// must not be set.
	DisableSystemRootCAs bool

	// ClientTunnelProtocol is the protocol the client is using. It's included in
	// the meek cookie for optional use by the server, in cases where the server
	// cannot unambiguously determine the tunnel protocol. ClientTunnelProtocol
	// is used when selecting tactics targeted at specific protocols. Ignored for
	// MeekModePlaintextRoundTrip.
	ClientTunnelProtocol string

	// NetworkLatencyMultiplier specifies a custom network latency multiplier to
	// apply to client parameters used by this meek connection.
	NetworkLatencyMultiplier float64

	MeekCookieEncryptionPublicKey string
	MeekObfuscatedKey             string
	MeekObfuscatorPaddingSeed     *prng.Seed

	// HTTPTransformerParameters specifies an HTTP transformer to apply to the
	// meek connection if it uses HTTP.
	HTTPTransformerParameters *transforms.HTTPTransformerParameters

	// AdditionalHeaders is a set of additional arbitrary HTTP headers that
	// are added to all meek HTTP requests. An additional header is ignored
	// when the header name is already present in a meek request.
	AdditionalHeaders http.Header
}

MeekConfig specifies the behavior of a MeekConn.

type MeekConn

type MeekConn struct {
	// contains filtered or unexported fields
}

MeekConn is a network connection that tunnels net.Conn flows over HTTP and supports "domain fronting". Meek sends client->server flow in HTTP request bodies and receives server->client flow in HTTP response bodies. Polling is used to approximate full duplex TCP. MeekConn also offers HTTP round trip modes.

Domain fronting is a network obfuscation technique in which the connection to a web server, typically a CDN, is indistinguishable from any other HTTPS connection to the generic "fronting domain" -- the HTTP Host header is used to route the requests to the actual destination. See https://trac.torproject.org/projects/tor/wiki/doc/meek for more details.

MeekConn also support unfronted operation, in which connections are made without routing through a CDN; and plain HTTP operation, without TLS or QUIC, with connection metadata obfuscated in HTTP cookies.

func DialMeek

func DialMeek(
	ctx context.Context,
	meekConfig *MeekConfig,
	dialConfig *DialConfig) (*MeekConn, error)

DialMeek returns an initialized meek connection. A meek connection is an HTTP session which does not depend on an underlying socket connection (although persistent HTTP connections are used for performance). This function may not wait for the connection to be established before returning.

func (*MeekConn) Close

func (meek *MeekConn) Close() (err error)

Close terminates the meek connection and releases its resources. In in MeekModeRelay, Close waits for the relay goroutine to stop.

func (*MeekConn) GetMetrics

func (meek *MeekConn) GetMetrics() common.LogFields

GetMetrics implements the common.MetricsSource interface.

func (*MeekConn) GetNoticeMetrics

func (meek *MeekConn) GetNoticeMetrics() common.LogFields

GetNoticeMetrics implements the common.NoticeMetricsSource interface.

func (*MeekConn) IsClosed

func (meek *MeekConn) IsClosed() bool

IsClosed implements the Closer interface. The return value indicates whether the MeekConn has been closed.

func (*MeekConn) LocalAddr

func (meek *MeekConn) LocalAddr() net.Addr

LocalAddr is a stub implementation of net.Conn.LocalAddr

func (*MeekConn) ObfuscatedRoundTrip

func (meek *MeekConn) ObfuscatedRoundTrip(
	requestCtx context.Context, endPoint string, requestBody []byte) ([]byte, error)

ObfuscatedRoundTrip makes a request to the meek server and returns the response. A new, obfuscated meek cookie is created for every request. The specified end point is recorded in the cookie and is not exposed as plaintext in the meek traffic. The caller is responsible for securing and obfuscating the request body.

If Close is called before or concurrent with ObfuscatedRoundTrip, or before the response body is read, idle connections may be left open.

func (*MeekConn) Read

func (meek *MeekConn) Read(buffer []byte) (n int, err error)

Read reads data from the connection. net.Conn Deadlines are ignored. net.Conn concurrency semantics are supported.

func (*MeekConn) RemoteAddr

func (meek *MeekConn) RemoteAddr() net.Addr

RemoteAddr is a stub implementation of net.Conn.RemoteAddr

func (*MeekConn) RoundTrip

func (meek *MeekConn) RoundTrip(request *http.Request) (*http.Response, error)

RoundTrip implements the http.RoundTripper interface. RoundTrip may only be used when TLS and server certificate verification are configured. RoundTrip does not implement any security or obfuscation at the HTTP layer.

If Close is called before or concurrent with RoundTrip, or before the response body is read, idle connections may be left open.

func (*MeekConn) SetDeadline

func (meek *MeekConn) SetDeadline(t time.Time) error

SetDeadline is a stub implementation of net.Conn.SetDeadline

func (*MeekConn) SetReadDeadline

func (meek *MeekConn) SetReadDeadline(t time.Time) error

SetReadDeadline is a stub implementation of net.Conn.SetReadDeadline

func (*MeekConn) SetWriteDeadline

func (meek *MeekConn) SetWriteDeadline(t time.Time) error

SetWriteDeadline is a stub implementation of net.Conn.SetWriteDeadline

func (*MeekConn) Write

func (meek *MeekConn) Write(buffer []byte) (n int, err error)

Write writes data to the connection. net.Conn Deadlines are ignored. net.Conn concurrency semantics are supported.

type MeekMode

type MeekMode int

type NetworkConnectivityChecker

type NetworkConnectivityChecker interface {
	// TODO: change to bool return value once gobind supports that type
	HasNetworkConnectivity() int
}

NetworkConnectivityChecker defines the interface to the external HasNetworkConnectivity provider, which call into the host application to check for network connectivity.

type NetworkIDGetter

type NetworkIDGetter interface {
	GetNetworkID() string
}

NetworkIDGetter defines the interface to the external GetNetworkID provider, which returns an identifier for the host's current active network.

The identifier is a string that should indicate the network type and identity; for example "WIFI-<BSSID>" or "MOBILE-<MCC/MNC>". As this network ID is personally identifying, it is only used locally in the client to determine network context and is not sent to the Psiphon server. The identifer will be logged in diagnostics messages; in this case only the substring before the first "-" is logged, so all PII must appear after the first "-".

NetworkIDGetter.GetNetworkID should always return an identifier value, as logic that uses GetNetworkID, including tactics, is intended to proceed regardless of whether an accurate network identifier can be obtained. By convention, the provider should return "UNKNOWN" when an accurate network identifier cannot be obtained. Best-effort is acceptable: e.g., return just "WIFI" when only the type of the network but no details can be determined.

type NoticeReceiver

type NoticeReceiver struct {
	// contains filtered or unexported fields
}

NoticeReceiver consumes a notice input stream and invokes a callback function for each discrete JSON notice object byte sequence.

func NewNoticeConsoleRewriter

func NewNoticeConsoleRewriter(writer io.Writer) *NoticeReceiver

NewNoticeConsoleRewriter consumes JSON-format notice input and parses each notice and rewrites in a more human-readable format more suitable for console output. The data payload field is left as JSON.

func NewNoticeReceiver

func NewNoticeReceiver(callback func([]byte)) *NoticeReceiver

NewNoticeReceiver initializes a new NoticeReceiver

func (*NoticeReceiver) Write

func (receiver *NoticeReceiver) Write(p []byte) (n int, err error)

Write implements io.Writer.

type NoticeWriter

type NoticeWriter struct {
	// contains filtered or unexported fields
}

NoticeWriter implements io.Writer and emits the contents of Write() calls as Notices. This is to transform logger messages, if they can be redirected to an io.Writer, to notices.

func NewNoticeWriter

func NewNoticeWriter(noticeType string) *NoticeWriter

NewNoticeWriter initializes a new NoticeWriter

func (*NoticeWriter) Write

func (writer *NoticeWriter) Write(p []byte) (n int, err error)

Write implements io.Writer.

type PacketTunnelTransport

type PacketTunnelTransport struct {
	// contains filtered or unexported fields
}

PacketTunnelTransport is an integration layer that presents an io.ReadWriteCloser interface to a tun.Client as the transport for relaying packets. The Psiphon client may periodically disconnect from and reconnect to the same or different Psiphon servers. PacketTunnelTransport allows the Psiphon client to substitute new transport channels on-the-fly.

func NewPacketTunnelTransport

func NewPacketTunnelTransport() *PacketTunnelTransport

NewPacketTunnelTransport initializes a PacketTunnelTransport.

func (*PacketTunnelTransport) Close

func (p *PacketTunnelTransport) Close() error

Close implements the io.Closer interface. Any underlying transport channel is closed and any blocking Read/Write calls will be interrupted.

func (*PacketTunnelTransport) Read

func (p *PacketTunnelTransport) Read(data []byte) (int, error)

Read implements the io.Reader interface. It uses the current transport channel to read packet data, or waits for a new transport channel to be established after a failure.

func (*PacketTunnelTransport) UseTunnel

func (p *PacketTunnelTransport) UseTunnel(tunnel *Tunnel)

UseTunnel sets the PacketTunnelTransport to use a new transport channel within the specified tunnel. UseTunnel does not block on the open channel call; it spawns a worker that calls tunnel.DialPacketTunnelChannel and uses the resulting channel. UseTunnel has no effect once Close is called.

Note that a blocked tunnel.DialPacketTunnelChannel with block Close; callers should arrange for DialPacketTunnelChannel to be interrupted when calling Close.

func (*PacketTunnelTransport) Write

func (p *PacketTunnelTransport) Write(data []byte) (int, error)

Write implements the io.Writer interface. It uses the current transport channel to write packet data, or waits for a new transport channel to be established after a failure.

type RefractionNetworkingDialer

type RefractionNetworkingDialer struct {
	// contains filtered or unexported fields
}

RefractionNetworkingDialer implements psiphon/common/refraction.Dialer.

func NewRefractionNetworkingDialer

func NewRefractionNetworkingDialer(config *DialConfig) *RefractionNetworkingDialer

NewRefractionNetworkingDialer creates a new RefractionNetworkingDialer.

func (*RefractionNetworkingDialer) DialContext

func (d *RefractionNetworkingDialer) DialContext(
	ctx context.Context,
	network string,
	laddr string,
	raddr string) (net.Conn, error)

type RemoteServerListFetcher

type RemoteServerListFetcher func(
	ctx context.Context, config *Config, attempt int, tunnel *Tunnel, untunneledDialConfig *DialConfig) error

type ServerContext

type ServerContext struct {
	// contains filtered or unexported fields
}

ServerContext is a utility struct which holds all of the data associated with a Psiphon server connection. In addition to the established tunnel, this includes data and transport mechanisms for Psiphon API requests. Legacy servers offer the Psiphon API through a web service; newer servers offer the Psiphon API through SSH requests made directly through the tunnel's SSH client.

func NewServerContext

func NewServerContext(tunnel *Tunnel) (*ServerContext, error)

NewServerContext makes the tunneled handshake request to the Psiphon server and returns a ServerContext struct for use with subsequent Psiphon server API requests (e.g., periodic connected and status requests).

func (*ServerContext) DoConnectedRequest

func (serverContext *ServerContext) DoConnectedRequest() error

DoConnectedRequest performs the "connected" API request. This request is used for statistics, including unique user counting; reporting the full tunnel establishment duration including the handshake request; and updated fragmentor metrics.

Users are not assigned identifiers. Instead, daily unique users are calculated by having clients submit their last connected timestamp (truncated to an hour, as a privacy measure). As client clocks are unreliable, the server returns new last_connected values for the client to store and send next time it connects.

func (*ServerContext) DoStatusRequest

func (serverContext *ServerContext) DoStatusRequest(tunnel *Tunnel) error

DoStatusRequest makes a "status" API request to the server, sending session stats.

func (*ServerContext) StatsRegexps

func (serverContext *ServerContext) StatsRegexps() *transferstats.Regexps

StatsRegexps gets the Regexps used for the statistics for this tunnel.

type ServerEntryIterator

type ServerEntryIterator struct {
	// contains filtered or unexported fields
}

ServerEntryIterator is used to iterate over stored server entries in rank order.

func NewServerEntryIterator

func NewServerEntryIterator(config *Config) (bool, *ServerEntryIterator, error)

NewServerEntryIterator creates a new ServerEntryIterator.

The boolean return value indicates whether to treat the first server(s) as affinity servers or not. When the server entry selection filter changes such as from a specific region to any region, or when there was no previous filter/iterator, the the first server(s) are arbitrary and should not be given affinity treatment.

NewServerEntryIterator and any returned ServerEntryIterator are not designed for concurrent use as not all related datastore operations are performed in a single transaction.

func NewTacticsServerEntryIterator

func NewTacticsServerEntryIterator(config *Config) (*ServerEntryIterator, error)

func (*ServerEntryIterator) Close

func (iterator *ServerEntryIterator) Close()

Close cleans up resources associated with a ServerEntryIterator.

func (*ServerEntryIterator) Next

func (iterator *ServerEntryIterator) Next() (*protocol.ServerEntry, error)

Next returns the next server entry, by rank, for a ServerEntryIterator. Returns nil with no error when there is no next item.

func (*ServerEntryIterator) Reset

func (iterator *ServerEntryIterator) Reset() error

Reset a NewServerEntryIterator to the start of its cycle. The next call to Next will return the first server entry.

type SocksProxy

type SocksProxy struct {
	// contains filtered or unexported fields
}

SocksProxy is a SOCKS server that accepts local host connections and, for each connection, establishes a port forward through the tunnel SSH client and relays traffic through the port forward.

func NewSocksProxy

func NewSocksProxy(
	config *Config,
	tunneler Tunneler,
	listenIP string) (proxy *SocksProxy, err error)

NewSocksProxy initializes a new SOCKS server. It begins listening for connections, starts a goroutine that runs an accept loop, and returns leaving the accept loop running.

func (*SocksProxy) Close

func (proxy *SocksProxy) Close()

Close terminates the listener and waits for the accept loop goroutine to complete.

type SyncFileWriter

type SyncFileWriter struct {
	// contains filtered or unexported fields
}

SyncFileWriter wraps a file and exposes an io.Writer. At predefined steps, the file is synced (flushed to disk) while writing.

func NewSyncFileWriter

func NewSyncFileWriter(file *os.File) *SyncFileWriter

NewSyncFileWriter creates a SyncFileWriter.

func (*SyncFileWriter) Write

func (writer *SyncFileWriter) Write(p []byte) (n int, err error)

Write implements io.Writer with periodic file syncing.

type TCPConn

type TCPConn struct {
	net.Conn
	// contains filtered or unexported fields
}

TCPConn is a customized TCP connection that supports the Closer interface and which may be created using options in DialConfig, including UpstreamProxyURL, DeviceBinder, IPv6Synthesizer, and ResolvedIPCallback. DeviceBinder is implemented using SO_BINDTODEVICE/IP_BOUND_IF, which requires syscall-level socket code.

func (*TCPConn) Close

func (conn *TCPConn) Close() (err error)

Close terminates a connected TCPConn or interrupts a dialing TCPConn.

func (*TCPConn) CloseWrite

func (conn *TCPConn) CloseWrite() (err error)

CloseWrite calls net.TCPConn.CloseWrite when the underlying conn is a *net.TCPConn.

func (*TCPConn) IsClosed

func (conn *TCPConn) IsClosed() bool

IsClosed implements the Closer iterface. The return value indicates whether the TCPConn has been closed.

type TLSFragmentorConn

type TLSFragmentorConn struct {
	net.Conn
	// contains filtered or unexported fields
}

func (*TLSFragmentorConn) Close

func (c *TLSFragmentorConn) Close() error

func (*TLSFragmentorConn) GetMetrics

func (c *TLSFragmentorConn) GetMetrics() common.LogFields

func (*TLSFragmentorConn) Read

func (c *TLSFragmentorConn) Read(b []byte) (n int, err error)

func (*TLSFragmentorConn) Write

func (c *TLSFragmentorConn) Write(b []byte) (n int, err error)

Write transparently splits the first TLS record containing ClientHello into two fragments and writes them separately to the underlying conn. The second fragment contains the data portion of the SNI extension (i.e. the server name). Write assumes a non-fragmented and complete ClientHello on the first call.

type TLSTunnelConfig

type TLSTunnelConfig struct {

	// CustomTLSConfig is the parameters that will be used to esablish a new
	// TLS connection with CustomTLSDial.
	CustomTLSConfig *CustomTLSConfig

	// UseObfuscatedSessionTickets indicates whether to use obfuscated session
	// tickets.
	UseObfuscatedSessionTickets bool

	ObfuscatedKey         string
	ObfuscatorPaddingSeed *prng.Seed
}

TLSTunnelConfig specifies the behavior of a TLSTunnelConn.

type TLSTunnelConn

type TLSTunnelConn struct {
	net.Conn
	// contains filtered or unexported fields
}

TLSTunnelConn is a network connection that tunnels net.Conn flows over TLS.

func DialTLSTunnel

func DialTLSTunnel(
	ctx context.Context,
	tlsTunnelConfig *TLSTunnelConfig,
	dialConfig *DialConfig,
	tlsOSSHApplyTrafficShaping bool,
	tlsOSSHMinTLSPadding,
	tlsOSSHMaxTLSPadding int,
) (*TLSTunnelConn, error)

DialTLSTunnel returns an initialized tls-tunnel connection.

func (*TLSTunnelConn) GetMetrics

func (conn *TLSTunnelConn) GetMetrics() common.LogFields

func (*TLSTunnelConn) IsClosed

func (conn *TLSTunnelConn) IsClosed() bool

type TacticsAppliedReceiver

type TacticsAppliedReceiver interface {
	TacticsApplied() error
}

TacticsAppliedReceiver specifies the interface for a component that is signaled when tactics are applied. TacticsApplied is invoked when any tactics are applied after initial start up, and then whenever new tactics are received and applied while running.

type TacticsStorer

type TacticsStorer struct {
	// contains filtered or unexported fields
}

TacticsStorer implements tactics.Storer.

Each TacticsStorer datastore operation is wrapped with OpenDataStoreWithoutRetry/CloseDataStore, which enables a limited degree of multiprocess datastore synchronization:

One process runs a Controller. Another process runs a stand-alone operation which accesses tactics via GetTactics. For example, SendFeedback.

When the Controller is running, it holds an exclusive lock on the datastore and TacticsStorer operations in GetTactics in another process will fail. The stand-alone operation should proceed without tactics. In many cases, this is acceptable since any stand-alone operation network traffic will be tunneled.

When the Controller is not running, the TacticsStorer operations in GetTactics in another process will succeed, with no operation holding a datastore lock for longer than the handful of milliseconds required to perform a single datastore operation.

If the Controller is started while the stand-alone operation is in progress, the Controller start will not be blocked for long by the brief TacticsStorer datastore locks; the bolt Open call, in particular, has a 1 second lock aquisition timeout and OpenDataStore will retry when the datastore file is locked.

In this scheme, no attempt is made to detect interleaving datastore writes; that is, if a different process writes tactics in between GetTactics calls to GetTacticsRecord and then SetTacticsRecord. This is because all tactics writes are considered fresh and valid.

Using OpenDataStoreWithoutRetry ensures that the GetTactics attempt in the non-Controller operation will quickly fail if the datastore is locked.

func GetTacticsStorer

func GetTacticsStorer(config *Config) *TacticsStorer

GetTacticsStorer creates a TacticsStorer.

func (*TacticsStorer) GetSpeedTestSamplesRecord

func (t *TacticsStorer) GetSpeedTestSamplesRecord(networkID string) ([]byte, error)

func (*TacticsStorer) GetTacticsRecord

func (t *TacticsStorer) GetTacticsRecord(networkID string) ([]byte, error)

func (*TacticsStorer) SetSpeedTestSamplesRecord

func (t *TacticsStorer) SetSpeedTestSamplesRecord(networkID string, record []byte) error

func (*TacticsStorer) SetTacticsRecord

func (t *TacticsStorer) SetTacticsRecord(networkID string, record []byte) error

type Tunnel

type Tunnel struct {
	// contains filtered or unexported fields
}

Tunnel is a connection to a Psiphon server. An established tunnel includes a network connection to the specified server and an SSH session built on top of that transport.

func ConnectTunnel

func ConnectTunnel(
	ctx context.Context,
	config *Config,
	adjustedEstablishStartTime time.Time,
	dialParams *DialParameters) (*Tunnel, error)

ConnectTunnel first makes a network transport connection to the Psiphon server and then establishes an SSH client session on top of that transport. The SSH server is authenticated using the public key in the server entry. Depending on the server's capabilities, the connection may use plain SSH over TCP, obfuscated SSH over TCP, or obfuscated SSH over HTTP (meek protocol). When requiredProtocol is not blank, that protocol is used. Otherwise, the a random supported protocol is used.

Call Activate on a connected tunnel to complete its establishment before using.

Tunnel establishment is split into two phases: connection, and activation. The Controller will run many ConnectTunnel calls concurrently and then, to avoid unnecessary overhead from making handshake requests and starting operateTunnel from tunnels which may be discarded, call Activate on connected tunnels sequentially as necessary.

func (*Tunnel) Activate

func (tunnel *Tunnel) Activate(
	ctx context.Context, tunnelOwner TunnelOwner) (retErr error)

Activate completes the tunnel establishment, performing the handshake request and starting operateTunnel, the worker that monitors the tunnel and handles periodic management.

func (*Tunnel) AwaitInFlightConnectedRequest

func (tunnel *Tunnel) AwaitInFlightConnectedRequest()

AwaitInFlightConnectedRequest waits for the signal that any in-flight connected request is complete.

AwaitInFlightConnectedRequest may block until the connected request is aborted by terminating the tunnel.

func (*Tunnel) Close

func (tunnel *Tunnel) Close(isDiscarded bool)

Close stops operating the tunnel and closes the underlying connection. Supports multiple and/or concurrent calls to Close(). When isDiscarded is set, operateTunnel will not attempt to send final status requests.

func (*Tunnel) DialPacketTunnelChannel

func (tunnel *Tunnel) DialPacketTunnelChannel() (net.Conn, error)

func (*Tunnel) DialTCPChannel

func (tunnel *Tunnel) DialTCPChannel(
	remoteAddr string,
	alwaysTunneled bool,
	downstreamConn net.Conn) (net.Conn, bool, error)

DialTCPChannel establishes a TCP port forward connection through the tunnel.

When split tunnel mode is enabled, and unless alwaysTunneled is set, the server may reject the port forward and indicate that the client is to make direct, untunneled connection. In this case, the bool return value is true and net.Conn and error are nil.

downstreamConn is an optional parameter which specifies a connection to be explicitly closed when the dialed connection is closed.

func (*Tunnel) IsActivated

func (tunnel *Tunnel) IsActivated() bool

IsActivated returns the tunnel's activated flag.

func (*Tunnel) IsDiscarded

func (tunnel *Tunnel) IsDiscarded() bool

IsDiscarded returns the tunnel's discarded flag.

func (*Tunnel) SendAPIRequest

func (tunnel *Tunnel) SendAPIRequest(
	name string, requestPayload []byte) ([]byte, error)

SendAPIRequest sends an API request as an SSH request through the tunnel. This function blocks awaiting a response. Only one request may be in-flight at once; a concurrent SendAPIRequest will block until an active request receives its response (or the SSH connection is terminated).

func (*Tunnel) SetInFlightConnectedRequest

func (tunnel *Tunnel) SetInFlightConnectedRequest(requestSignal chan struct{}) bool

SetInFlightConnectedRequest checks if a connected request can begin and sets the channel used to signal that the request is complete.

The caller must not initiate a connected request when SetInFlightConnectedRequest returns false. When SetInFlightConnectedRequest returns true, the caller must call SetInFlightConnectedRequest(nil) when the connected request completes.

func (*Tunnel) SignalComponentFailure

func (tunnel *Tunnel) SignalComponentFailure()

SignalComponentFailure notifies the tunnel that an associated component has failed. This will terminate the tunnel.

type TunnelOwner

type TunnelOwner interface {
	SignalSeededNewSLOK()
	SignalTunnelFailure(tunnel *Tunnel)
}

TunnelOwner specifies the interface required by Tunnel to notify its owner when it has failed. The owner may, as in the case of the Controller, remove the tunnel from its list of active tunnels.

type TunneledConn

type TunneledConn struct {
	net.Conn
	// contains filtered or unexported fields
}

TunneledConn implements net.Conn and wraps a port forward connection. It is used to hook into Read and Write to observe I/O errors and report these errors back to the tunnel monitor as port forward failures. TunneledConn optionally tracks a peer connection to be explicitly closed when the TunneledConn is closed.

func (*TunneledConn) Close

func (conn *TunneledConn) Close() error

func (*TunneledConn) Read

func (conn *TunneledConn) Read(buffer []byte) (n int, err error)

func (*TunneledConn) Write

func (conn *TunneledConn) Write(buffer []byte) (n int, err error)

type Tunneler

type Tunneler interface {

	// Dial creates a tunneled connection.
	//
	// When split tunnel mode is enabled, the connection may be untunneled,
	// depending on GeoIP classification of the destination.
	//
	// downstreamConn is an optional parameter which specifies a connection to be
	// explicitly closed when the Dialed connection is closed. For instance, this
	// is used to close downstreamConn App<->LocalProxy connections when the related
	// LocalProxy<->SshPortForward connections close.
	Dial(remoteAddr string, downstreamConn net.Conn) (conn net.Conn, err error)

	DirectDial(remoteAddr string) (conn net.Conn, err error)

	SignalComponentFailure()
}

Tunneler specifies the interface required by components that use tunnels.

type UseNoticeFiles

type UseNoticeFiles struct {
	RotatingFileSize      int
	RotatingSyncFrequency int
}

Config field which specifies if notice files should be used and at which frequency and size they should be rotated.

If either RotatingFileSize or RotatingSyncFrequency are <= 0, default values are used.

See comment for setNoticeFiles in notice.go for further details.

Directories

Path Synopsis
accesscontrol
Package accesscontrol implements an access control authorization scheme based on digital signatures.
Package accesscontrol implements an access control authorization scheme based on digital signatures.
crypto/internal/poly1305
Package poly1305 implements Poly1305 one-time message authentication code as specified in https://cr.yp.to/mac/poly1305-20050329.pdf.
Package poly1305 implements Poly1305 one-time message authentication code as specified in https://cr.yp.to/mac/poly1305-20050329.pdf.
crypto/internal/subtle
Package subtle implements functions that are often useful in cryptographic code but require careful thought to use correctly.
Package subtle implements functions that are often useful in cryptographic code but require careful thought to use correctly.
crypto/nacl/secretbox
Package secretbox encrypts and authenticates small messages.
Package secretbox encrypts and authenticates small messages.
crypto/ssh
Package ssh implements an SSH client and server.
Package ssh implements an SSH client and server.
crypto/ssh/agent
Package agent implements the ssh-agent protocol, and provides both a client and a server.
Package agent implements the ssh-agent protocol, and provides both a client and a server.
crypto/ssh/internal/bcrypt_pbkdf
Package bcrypt_pbkdf implements bcrypt_pbkdf(3) from OpenBSD.
Package bcrypt_pbkdf implements bcrypt_pbkdf(3) from OpenBSD.
crypto/ssh/knownhosts
Package knownhosts implements a parser for the OpenSSH known_hosts host key database, and provides utility functions for writing OpenSSH compliant known_hosts files.
Package knownhosts implements a parser for the OpenSSH known_hosts host key database, and provides utility functions for writing OpenSSH compliant known_hosts files.
crypto/ssh/terminal
Package terminal provides support functions for dealing with terminals, as commonly found on UNIX systems.
Package terminal provides support functions for dealing with terminals, as commonly found on UNIX systems.
crypto/ssh/test
Package test contains integration tests for the github.com/nandoxscr/popon-core/psiphon/common/crypto/ssh package.
Package test contains integration tests for the github.com/nandoxscr/popon-core/psiphon/common/crypto/ssh package.
errors
Package errors provides error wrapping helpers that add inline, single frame stack trace information to error messages.
Package errors provides error wrapping helpers that add inline, single frame stack trace information to error messages.
inproxy
Package inproxy enables 3rd party, ephemeral proxies to help Psiphon clients connect to the Psiphon network.
Package inproxy enables 3rd party, ephemeral proxies to help Psiphon clients connect to the Psiphon network.
monotime
Package monotime provides a fast monotonic clock source.
Package monotime provides a fast monotonic clock source.
osl
Package osl implements the Obfuscated Server List (OSL) mechanism.
Package osl implements the Obfuscated Server List (OSL) mechanism.
packetman
Package packetman implements low-level manipulation of TCP packets, enabling a variety of strategies to evade network censorship.
Package packetman implements low-level manipulation of TCP packets, enabling a variety of strategies to evade network censorship.
parameters
Package parameters implements dynamic, concurrency-safe parameters that determine Psiphon client and server behaviors.
Package parameters implements dynamic, concurrency-safe parameters that determine Psiphon client and server behaviors.
prng
Package prng implements a seeded, unbiased PRNG that is suitable for use cases including obfuscation, network jitter, load balancing.
Package prng implements a seeded, unbiased PRNG that is suitable for use cases including obfuscation, network jitter, load balancing.
quic
Package quic wraps github.com/lucas-clemente/quic-go with net.Listener and net.Conn types that provide a drop-in replacement for net.TCPConn.
Package quic wraps github.com/lucas-clemente/quic-go with net.Listener and net.Conn types that provide a drop-in replacement for net.TCPConn.
regen
Package regen is a library for generating random strings from regular expressions.
Package regen is a library for generating random strings from regular expressions.
resolver
Package resolver implements a DNS stub resolver, or DNS client, which resolves domain names.
Package resolver implements a DNS stub resolver, or DNS client, which resolves domain names.
sss
Package sss implements Shamir's Secret Sharing algorithm over GF(2^8).
Package sss implements Shamir's Secret Sharing algorithm over GF(2^8).
stacktrace
Package stacktrace provides helpers for handling stack trace information.
Package stacktrace provides helpers for handling stack trace information.
tactics
Package tactics provides dynamic Psiphon client configuration based on GeoIP attributes, API parameters, and speed test data.
Package tactics provides dynamic Psiphon client configuration based on GeoIP attributes, API parameters, and speed test data.
transforms
Package transforms provides a mechanism to define and apply string data transformations, with the transformations defined by regular expressions to match data to be transformed, and regular expression generators to specify additional or replacement data.
Package transforms provides a mechanism to define and apply string data transformations, with the transformations defined by regular expressions to match data to be transformed, and regular expression generators to specify additional or replacement data.
tun
Package tun is an IP packet tunnel server and client.
Package tun is an IP packet tunnel server and client.
values
Package values provides a mechanism for specifying and selecting dynamic values employed by the Psiphon client and server.
Package values provides a mechanism for specifying and selecting dynamic values employed by the Psiphon client and server.
wildcard
Package wildcard implements a very simple wildcard matcher which supports only the term '*', which matches any sequence of characters.
Package wildcard implements a very simple wildcard matcher which supports only the term '*', which matches any sequence of characters.
Package server implements the core tunnel functionality of a Psiphon server.
Package server implements the core tunnel functionality of a Psiphon server.
discovery
Package discovery implements the Psiphon discovery algorithms.
Package discovery implements the Psiphon discovery algorithms.
psinet
Package psinet implements psinet database services.
Package psinet implements psinet database services.
Package transferstats counts and keeps track of session stats.
Package transferstats counts and keeps track of session stats.
go-ntlm/ntlm
Package NTLM implements the interfaces used for interacting with NTLMv1 and NTLMv2.
Package NTLM implements the interfaces used for interacting with NTLMv1 and NTLMv2.
go-ntlm/ntlm/md4
Package md4 implements the MD4 hash algorithm as defined in RFC 1320.
Package md4 implements the MD4 hash algorithm as defined in RFC 1320.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL