1/* 2 * Copyright (c) 2018, Psiphon Inc. 3 * All rights reserved. 4 * 5 * This program is free software: you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation, either version 3 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 * 18 */ 19 20/* 21Package parameters implements dynamic, concurrency-safe parameters that 22determine Psiphon client and server behaviors. 23 24Parameters include network timeouts, probabilities for actions, lists of 25protocols, etc. Parameters are initialized with reasonable defaults. New 26values may be applied, allowing the client or server to customize its 27parameters from both a config file and tactics data. Sane minimum values are 28enforced. 29 30Parameters may be read and updated concurrently. The read mechanism offers a 31snapshot so that related parameters, such as two Ints representing a range; or 32a more complex series of related parameters; may be read in an atomic and 33consistent way. For example: 34 35 p := params.Get() 36 min := p.Int("Min") 37 max := p.Int("Max") 38 p = nil 39 40For long-running operations, it is recommended to set any pointer to the 41snapshot to nil to allow garbage collection of old snaphots in cases where the 42parameters change. 43 44In general, parameters should be read as close to the point of use as possible 45to ensure that dynamic changes to the parameter values take effect. 46 47For duration parameters, time.ParseDuration-compatible string values are 48supported when applying new values. This allows specifying durations as, for 49example, "100ms" or "24h". 50 51Values read from the parameters are not deep copies and must be treated as 52read-only. 53*/ 54package parameters 55 56import ( 57 "encoding/json" 58 "net/http" 59 "reflect" 60 "sync/atomic" 61 "time" 62 63 "github.com/ooni/psiphon/oopsi/github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common" 64 "github.com/ooni/psiphon/oopsi/github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/errors" 65 "github.com/ooni/psiphon/oopsi/github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/obfuscator" 66 "github.com/ooni/psiphon/oopsi/github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/prng" 67 "github.com/ooni/psiphon/oopsi/github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/protocol" 68 "github.com/ooni/psiphon/oopsi/golang.org/x/net/bpf" 69) 70 71const ( 72 NetworkLatencyMultiplier = "NetworkLatencyMultiplier" 73 NetworkLatencyMultiplierMin = "NetworkLatencyMultiplierMin" 74 NetworkLatencyMultiplierMax = "NetworkLatencyMultiplierMax" 75 NetworkLatencyMultiplierLambda = "NetworkLatencyMultiplierLambda" 76 TacticsWaitPeriod = "TacticsWaitPeriod" 77 TacticsRetryPeriod = "TacticsRetryPeriod" 78 TacticsRetryPeriodJitter = "TacticsRetryPeriodJitter" 79 TacticsTimeout = "TacticsTimeout" 80 ConnectionWorkerPoolSize = "ConnectionWorkerPoolSize" 81 TunnelPoolSize = "TunnelPoolSize" 82 TunnelConnectTimeout = "TunnelConnectTimeout" 83 EstablishTunnelTimeout = "EstablishTunnelTimeout" 84 EstablishTunnelWorkTime = "EstablishTunnelWorkTime" 85 EstablishTunnelPausePeriod = "EstablishTunnelPausePeriod" 86 EstablishTunnelPausePeriodJitter = "EstablishTunnelPausePeriodJitter" 87 EstablishTunnelServerAffinityGracePeriod = "EstablishTunnelServerAffinityGracePeriod" 88 StaggerConnectionWorkersPeriod = "StaggerConnectionWorkersPeriod" 89 StaggerConnectionWorkersJitter = "StaggerConnectionWorkersJitter" 90 LimitIntensiveConnectionWorkers = "LimitIntensiveConnectionWorkers" 91 UpstreamProxyErrorMinWaitDuration = "UpstreamProxyErrorMinWaitDuration" 92 UpstreamProxyErrorMaxWaitDuration = "UpstreamProxyErrorMaxWaitDuration" 93 IgnoreHandshakeStatsRegexps = "IgnoreHandshakeStatsRegexps" 94 PrioritizeTunnelProtocolsProbability = "PrioritizeTunnelProtocolsProbability" 95 PrioritizeTunnelProtocols = "PrioritizeTunnelProtocols" 96 PrioritizeTunnelProtocolsCandidateCount = "PrioritizeTunnelProtocolsCandidateCount" 97 InitialLimitTunnelProtocolsProbability = "InitialLimitTunnelProtocolsProbability" 98 InitialLimitTunnelProtocols = "InitialLimitTunnelProtocols" 99 InitialLimitTunnelProtocolsCandidateCount = "InitialLimitTunnelProtocolsCandidateCount" 100 LimitTunnelProtocolsProbability = "LimitTunnelProtocolsProbability" 101 LimitTunnelProtocols = "LimitTunnelProtocols" 102 LimitTLSProfilesProbability = "LimitTLSProfilesProbability" 103 LimitTLSProfiles = "LimitTLSProfiles" 104 UseOnlyCustomTLSProfiles = "UseOnlyCustomTLSProfiles" 105 CustomTLSProfiles = "CustomTLSProfiles" 106 SelectRandomizedTLSProfileProbability = "SelectRandomizedTLSProfileProbability" 107 NoDefaultTLSSessionIDProbability = "NoDefaultTLSSessionIDProbability" 108 DisableFrontingProviderTLSProfiles = "DisableFrontingProviderTLSProfiles" 109 LimitQUICVersionsProbability = "LimitQUICVersionsProbability" 110 LimitQUICVersions = "LimitQUICVersions" 111 DisableFrontingProviderQUICVersions = "DisableFrontingProviderQUICVersions" 112 FragmentorProbability = "FragmentorProbability" 113 FragmentorLimitProtocols = "FragmentorLimitProtocols" 114 FragmentorMinTotalBytes = "FragmentorMinTotalBytes" 115 FragmentorMaxTotalBytes = "FragmentorMaxTotalBytes" 116 FragmentorMinWriteBytes = "FragmentorMinWriteBytes" 117 FragmentorMaxWriteBytes = "FragmentorMaxWriteBytes" 118 FragmentorMinDelay = "FragmentorMinDelay" 119 FragmentorMaxDelay = "FragmentorMaxDelay" 120 FragmentorDownstreamProbability = "FragmentorDownstreamProbability" 121 FragmentorDownstreamLimitProtocols = "FragmentorDownstreamLimitProtocols" 122 FragmentorDownstreamMinTotalBytes = "FragmentorDownstreamMinTotalBytes" 123 FragmentorDownstreamMaxTotalBytes = "FragmentorDownstreamMaxTotalBytes" 124 FragmentorDownstreamMinWriteBytes = "FragmentorDownstreamMinWriteBytes" 125 FragmentorDownstreamMaxWriteBytes = "FragmentorDownstreamMaxWriteBytes" 126 FragmentorDownstreamMinDelay = "FragmentorDownstreamMinDelay" 127 FragmentorDownstreamMaxDelay = "FragmentorDownstreamMaxDelay" 128 ObfuscatedSSHMinPadding = "ObfuscatedSSHMinPadding" 129 ObfuscatedSSHMaxPadding = "ObfuscatedSSHMaxPadding" 130 TunnelOperateShutdownTimeout = "TunnelOperateShutdownTimeout" 131 TunnelPortForwardDialTimeout = "TunnelPortForwardDialTimeout" 132 PacketTunnelReadTimeout = "PacketTunnelReadTimeout" 133 TunnelRateLimits = "TunnelRateLimits" 134 AdditionalCustomHeaders = "AdditionalCustomHeaders" 135 SpeedTestPaddingMinBytes = "SpeedTestPaddingMinBytes" 136 SpeedTestPaddingMaxBytes = "SpeedTestPaddingMaxBytes" 137 SpeedTestMaxSampleCount = "SpeedTestMaxSampleCount" 138 SSHKeepAliveSpeedTestSampleProbability = "SSHKeepAliveSpeedTestSampleProbability" 139 SSHKeepAlivePaddingMinBytes = "SSHKeepAlivePaddingMinBytes" 140 SSHKeepAlivePaddingMaxBytes = "SSHKeepAlivePaddingMaxBytes" 141 SSHKeepAlivePeriodMin = "SSHKeepAlivePeriodMin" 142 SSHKeepAlivePeriodMax = "SSHKeepAlivePeriodMax" 143 SSHKeepAlivePeriodicTimeout = "SSHKeepAlivePeriodicTimeout" 144 SSHKeepAlivePeriodicInactivePeriod = "SSHKeepAlivePeriodicInactivePeriod" 145 SSHKeepAliveProbeTimeout = "SSHKeepAliveProbeTimeout" 146 SSHKeepAliveProbeInactivePeriod = "SSHKeepAliveProbeInactivePeriod" 147 SSHKeepAliveNetworkConnectivityPollingPeriod = "SSHKeepAliveNetworkConnectivityPollingPeriod" 148 SSHKeepAliveResetOnFailureProbability = "SSHKeepAliveResetOnFailureProbability" 149 HTTPProxyOriginServerTimeout = "HTTPProxyOriginServerTimeout" 150 HTTPProxyMaxIdleConnectionsPerHost = "HTTPProxyMaxIdleConnectionsPerHost" 151 FetchRemoteServerListTimeout = "FetchRemoteServerListTimeout" 152 FetchRemoteServerListRetryPeriod = "FetchRemoteServerListRetryPeriod" 153 FetchRemoteServerListStalePeriod = "FetchRemoteServerListStalePeriod" 154 RemoteServerListSignaturePublicKey = "RemoteServerListSignaturePublicKey" 155 RemoteServerListURLs = "RemoteServerListURLs" 156 ObfuscatedServerListRootURLs = "ObfuscatedServerListRootURLs" 157 PsiphonAPIRequestTimeout = "PsiphonAPIRequestTimeout" 158 PsiphonAPIStatusRequestPeriodMin = "PsiphonAPIStatusRequestPeriodMin" 159 PsiphonAPIStatusRequestPeriodMax = "PsiphonAPIStatusRequestPeriodMax" 160 PsiphonAPIStatusRequestShortPeriodMin = "PsiphonAPIStatusRequestShortPeriodMin" 161 PsiphonAPIStatusRequestShortPeriodMax = "PsiphonAPIStatusRequestShortPeriodMax" 162 PsiphonAPIStatusRequestPaddingMinBytes = "PsiphonAPIStatusRequestPaddingMinBytes" 163 PsiphonAPIStatusRequestPaddingMaxBytes = "PsiphonAPIStatusRequestPaddingMaxBytes" 164 PsiphonAPIPersistentStatsMaxCount = "PsiphonAPIPersistentStatsMaxCount" 165 PsiphonAPIConnectedRequestPeriod = "PsiphonAPIConnectedRequestPeriod" 166 PsiphonAPIConnectedRequestRetryPeriod = "PsiphonAPIConnectedRequestRetryPeriod" 167 FetchSplitTunnelRoutesTimeout = "FetchSplitTunnelRoutesTimeout" 168 SplitTunnelRoutesURLFormat = "SplitTunnelRoutesURLFormat" 169 SplitTunnelRoutesSignaturePublicKey = "SplitTunnelRoutesSignaturePublicKey" 170 SplitTunnelDNSServer = "SplitTunnelDNSServer" 171 SplitTunnelClassificationTTL = "SplitTunnelClassificationTTL" 172 SplitTunnelClassificationMaxEntries = "SplitTunnelClassificationMaxEntries" 173 FetchUpgradeTimeout = "FetchUpgradeTimeout" 174 FetchUpgradeRetryPeriod = "FetchUpgradeRetryPeriod" 175 FetchUpgradeStalePeriod = "FetchUpgradeStalePeriod" 176 UpgradeDownloadURLs = "UpgradeDownloadURLs" 177 UpgradeDownloadClientVersionHeader = "UpgradeDownloadClientVersionHeader" 178 TotalBytesTransferredNoticePeriod = "TotalBytesTransferredNoticePeriod" 179 TotalBytesTransferredEmitMemoryMetrics = "TotalBytesTransferredEmitMemoryMetrics" 180 MeekDialDomainsOnly = "MeekDialDomainsOnly" 181 MeekLimitBufferSizes = "MeekLimitBufferSizes" 182 MeekCookieMaxPadding = "MeekCookieMaxPadding" 183 MeekFullReceiveBufferLength = "MeekFullReceiveBufferLength" 184 MeekReadPayloadChunkLength = "MeekReadPayloadChunkLength" 185 MeekLimitedFullReceiveBufferLength = "MeekLimitedFullReceiveBufferLength" 186 MeekLimitedReadPayloadChunkLength = "MeekLimitedReadPayloadChunkLength" 187 MeekMinPollInterval = "MeekMinPollInterval" 188 MeekMinPollIntervalJitter = "MeekMinPollIntervalJitter" 189 MeekMaxPollInterval = "MeekMaxPollInterval" 190 MeekMaxPollIntervalJitter = "MeekMaxPollIntervalJitter" 191 MeekPollIntervalMultiplier = "MeekPollIntervalMultiplier" 192 MeekPollIntervalJitter = "MeekPollIntervalJitter" 193 MeekApplyPollIntervalMultiplierProbability = "MeekApplyPollIntervalMultiplierProbability" 194 MeekRoundTripRetryDeadline = "MeekRoundTripRetryDeadline" 195 MeekRoundTripRetryMinDelay = "MeekRoundTripRetryMinDelay" 196 MeekRoundTripRetryMaxDelay = "MeekRoundTripRetryMaxDelay" 197 MeekRoundTripRetryMultiplier = "MeekRoundTripRetryMultiplier" 198 MeekRoundTripTimeout = "MeekRoundTripTimeout" 199 MeekTrafficShapingProbability = "MeekTrafficShapingProbability" 200 MeekTrafficShapingLimitProtocols = "MeekTrafficShapingLimitProtocols" 201 MeekMinTLSPadding = "MeekMinTLSPadding" 202 MeekMaxTLSPadding = "MeekMaxTLSPadding" 203 MeekMinLimitRequestPayloadLength = "MeekMinLimitRequestPayloadLength" 204 MeekMaxLimitRequestPayloadLength = "MeekMaxLimitRequestPayloadLength" 205 MeekRedialTLSProbability = "MeekRedialTLSProbability" 206 TransformHostNameProbability = "TransformHostNameProbability" 207 PickUserAgentProbability = "PickUserAgentProbability" 208 LivenessTestMinUpstreamBytes = "LivenessTestMinUpstreamBytes" 209 LivenessTestMaxUpstreamBytes = "LivenessTestMaxUpstreamBytes" 210 LivenessTestMinDownstreamBytes = "LivenessTestMinDownstreamBytes" 211 LivenessTestMaxDownstreamBytes = "LivenessTestMaxDownstreamBytes" 212 ReplayCandidateCount = "ReplayCandidateCount" 213 ReplayDialParametersTTL = "ReplayDialParametersTTL" 214 ReplayTargetUpstreamBytes = "ReplayTargetUpstreamBytes" 215 ReplayTargetDownstreamBytes = "ReplayTargetDownstreamBytes" 216 ReplayTargetTunnelDuration = "ReplayTargetTunnelDuration" 217 ReplayBPF = "ReplayBPF" 218 ReplaySSH = "ReplaySSH" 219 ReplayObfuscatorPadding = "ReplayObfuscatorPadding" 220 ReplayFragmentor = "ReplayFragmentor" 221 ReplayTLSProfile = "ReplayTLSProfile" 222 ReplayRandomizedTLSProfile = "ReplayRandomizedTLSProfile" 223 ReplayFronting = "ReplayFronting" 224 ReplayHostname = "ReplayHostname" 225 ReplayQUICVersion = "ReplayQUICVersion" 226 ReplayObfuscatedQUIC = "ReplayObfuscatedQUIC" 227 ReplayConjureRegistration = "ReplayConjureRegistration" 228 ReplayConjureTransport = "ReplayConjureTransport" 229 ReplayLivenessTest = "ReplayLivenessTest" 230 ReplayUserAgent = "ReplayUserAgent" 231 ReplayAPIRequestPadding = "ReplayAPIRequestPadding" 232 ReplayLaterRoundMoveToFrontProbability = "ReplayLaterRoundMoveToFrontProbability" 233 ReplayRetainFailedProbability = "ReplayRetainFailedProbability" 234 APIRequestUpstreamPaddingMinBytes = "APIRequestUpstreamPaddingMinBytes" 235 APIRequestUpstreamPaddingMaxBytes = "APIRequestUpstreamPaddingMaxBytes" 236 APIRequestDownstreamPaddingMinBytes = "APIRequestDownstreamPaddingMinBytes" 237 APIRequestDownstreamPaddingMaxBytes = "APIRequestDownstreamPaddingMaxBytes" 238 PersistentStatsMaxStoreRecords = "PersistentStatsMaxStoreRecords" 239 PersistentStatsMaxSendBytes = "PersistentStatsMaxSendBytes" 240 RecordRemoteServerListPersistentStatsProbability = "RecordRemoteServerListPersistentStatsProbability" 241 RecordFailedTunnelPersistentStatsProbability = "RecordFailedTunnelPersistentStatsProbability" 242 ServerEntryMinimumAgeForPruning = "ServerEntryMinimumAgeForPruning" 243 ApplicationParametersProbability = "ApplicationParametersProbability" 244 ApplicationParameters = "ApplicationParameters" 245 BPFServerTCPProgram = "BPFServerTCPProgram" 246 BPFServerTCPProbability = "BPFServerTCPProbability" 247 BPFClientTCPProgram = "BPFClientTCPProgram" 248 BPFClientTCPProbability = "BPFClientTCPProbability" 249 ServerPacketManipulationSpecs = "ServerPacketManipulationSpecs" 250 ServerProtocolPacketManipulations = "ServerProtocolPacketManipulations" 251 ServerPacketManipulationProbability = "ServerPacketManipulationProbability" 252 FeedbackUploadURLs = "FeedbackUploadURLs" 253 FeedbackEncryptionPublicKey = "FeedbackEncryptionPublicKey" 254 FeedbackTacticsWaitPeriod = "FeedbackTacticsWaitPeriod" 255 FeedbackUploadMaxAttempts = "FeedbackUploadMaxAttempts" 256 FeedbackUploadRetryMinDelaySeconds = "FeedbackUploadRetryMinDelaySeconds" 257 FeedbackUploadRetryMaxDelaySeconds = "FeedbackUploadRetryMaxDelaySeconds" 258 FeedbackUploadTimeoutSeconds = "FeedbackUploadTimeoutSeconds" 259 ServerReplayPacketManipulation = "ServerReplayPacketManipulation" 260 ServerReplayFragmentor = "ServerReplayFragmentor" 261 ServerReplayUnknownGeoIP = "ServerReplayUnknownGeoIP" 262 ServerReplayTTL = "ServerReplayTTL" 263 ServerReplayTargetWaitDuration = "ServerReplayTargetWaitDuration" 264 ServerReplayTargetTunnelDuration = "ServerReplayTargetTunnelDuration" 265 ServerReplayTargetUpstreamBytes = "ServerReplayTargetUpstreamBytes" 266 ServerReplayTargetDownstreamBytes = "ServerReplayTargetDownstreamBytes" 267 ServerReplayFailedCountThreshold = "ServerReplayFailedCountThreshold" 268 ServerBurstUpstreamDeadline = "ServerBurstUpstreamDeadline" 269 ServerBurstUpstreamTargetBytes = "ServerBurstUpstreamTargetBytes" 270 ServerBurstDownstreamDeadline = "ServerBurstDownstreamDeadline" 271 ServerBurstDownstreamTargetBytes = "ServerBurstDownstreamTargetBytes" 272 ClientBurstUpstreamDeadline = "ClientBurstUpstreamDeadline" 273 ClientBurstUpstreamTargetBytes = "ClientBurstUpstreamTargetBytes" 274 ClientBurstDownstreamDeadline = "ClientBurstDownstreamDeadline" 275 ClientBurstDownstreamTargetBytes = "ClientBurstDownstreamTargetBytes" 276 ConjureCachedRegistrationTTL = "ConjureCachedRegistrationTTL" 277 ConjureAPIRegistrarURL = "ConjureAPIRegistrarURL" 278 ConjureAPIRegistrarFrontingSpecs = "ConjureAPIRegistrarFrontingSpecs" 279 ConjureAPIRegistrarMinDelay = "ConjureAPIRegistrarMinDelay" 280 ConjureAPIRegistrarMaxDelay = "ConjureAPIRegistrarMaxDelay" 281 ConjureDecoyRegistrarProbability = "ConjureDecoyRegistrarProbability" 282 ConjureDecoyRegistrarWidth = "ConjureDecoyRegistrarWidth" 283 ConjureDecoyRegistrarMinDelay = "ConjureDecoyRegistrarMinDelay" 284 ConjureDecoyRegistrarMaxDelay = "ConjureDecoyRegistrarMaxDelay" 285 ConjureTransportObfs4Probability = "ConjureTransportObfs4Probability" 286 CustomHostNameRegexes = "CustomHostNameRegexes" 287 CustomHostNameProbability = "CustomHostNameProbability" 288 CustomHostNameLimitProtocols = "CustomHostNameLimitProtocols" 289) 290 291const ( 292 useNetworkLatencyMultiplier = 1 293 serverSideOnly = 2 294) 295 296// defaultParameters specifies the type, default value, and minimum value for 297// all dynamically configurable client and server parameters. 298// 299// Do not change the names or types of existing values, as that can break 300// client logic or cause parameters to not be applied. 301// 302// Minimum values are a fail-safe for cases where lower values would break the 303// client logic. For example, setting a ConnectionWorkerPoolSize of 0 would 304// make the client never connect. 305var defaultParameters = map[string]struct { 306 value interface{} 307 minimum interface{} 308 flags int32 309}{ 310 // NetworkLatencyMultiplier defaults to 0, meaning off. But when set, it 311 // must be a multiplier >= 1. 312 313 NetworkLatencyMultiplier: {value: 0.0, minimum: 1.0}, 314 NetworkLatencyMultiplierMin: {value: 1.0, minimum: 1.0}, 315 NetworkLatencyMultiplierMax: {value: 3.0, minimum: 1.0}, 316 NetworkLatencyMultiplierLambda: {value: 2.0, minimum: 0.001}, 317 318 TacticsWaitPeriod: {value: 10 * time.Second, minimum: 0 * time.Second, flags: useNetworkLatencyMultiplier}, 319 TacticsRetryPeriod: {value: 5 * time.Second, minimum: 1 * time.Millisecond}, 320 TacticsRetryPeriodJitter: {value: 0.3, minimum: 0.0}, 321 TacticsTimeout: {value: 2 * time.Minute, minimum: 1 * time.Second, flags: useNetworkLatencyMultiplier}, 322 323 ConnectionWorkerPoolSize: {value: 10, minimum: 1}, 324 TunnelPoolSize: {value: 1, minimum: 1}, 325 TunnelConnectTimeout: {value: 20 * time.Second, minimum: 1 * time.Second, flags: useNetworkLatencyMultiplier}, 326 EstablishTunnelTimeout: {value: 300 * time.Second, minimum: time.Duration(0)}, 327 EstablishTunnelWorkTime: {value: 60 * time.Second, minimum: 1 * time.Second}, 328 EstablishTunnelPausePeriod: {value: 5 * time.Second, minimum: 1 * time.Millisecond}, 329 EstablishTunnelPausePeriodJitter: {value: 0.1, minimum: 0.0}, 330 EstablishTunnelServerAffinityGracePeriod: {value: 1 * time.Second, minimum: time.Duration(0), flags: useNetworkLatencyMultiplier}, 331 StaggerConnectionWorkersPeriod: {value: time.Duration(0), minimum: time.Duration(0)}, 332 StaggerConnectionWorkersJitter: {value: 0.1, minimum: 0.0}, 333 LimitIntensiveConnectionWorkers: {value: 0, minimum: 0}, 334 UpstreamProxyErrorMinWaitDuration: {value: 10 * time.Second, minimum: time.Duration(0)}, 335 UpstreamProxyErrorMaxWaitDuration: {value: 30 * time.Second, minimum: time.Duration(0)}, 336 IgnoreHandshakeStatsRegexps: {value: false}, 337 TunnelOperateShutdownTimeout: {value: 1 * time.Second, minimum: 1 * time.Millisecond, flags: useNetworkLatencyMultiplier}, 338 TunnelPortForwardDialTimeout: {value: 10 * time.Second, minimum: 1 * time.Millisecond, flags: useNetworkLatencyMultiplier}, 339 PacketTunnelReadTimeout: {value: 10 * time.Second, minimum: 1 * time.Millisecond, flags: useNetworkLatencyMultiplier}, 340 TunnelRateLimits: {value: common.RateLimits{}}, 341 342 // PrioritizeTunnelProtocols parameters are obsoleted by InitialLimitTunnelProtocols. 343 // TODO: remove once no longer required for older clients. 344 PrioritizeTunnelProtocolsProbability: {value: 1.0, minimum: 0.0}, 345 PrioritizeTunnelProtocols: {value: protocol.TunnelProtocols{}}, 346 PrioritizeTunnelProtocolsCandidateCount: {value: 10, minimum: 0}, 347 348 InitialLimitTunnelProtocolsProbability: {value: 1.0, minimum: 0.0}, 349 InitialLimitTunnelProtocols: {value: protocol.TunnelProtocols{}}, 350 InitialLimitTunnelProtocolsCandidateCount: {value: 0, minimum: 0}, 351 352 LimitTunnelProtocolsProbability: {value: 1.0, minimum: 0.0}, 353 LimitTunnelProtocols: {value: protocol.TunnelProtocols{}}, 354 355 LimitTLSProfilesProbability: {value: 1.0, minimum: 0.0}, 356 LimitTLSProfiles: {value: protocol.TLSProfiles{}}, 357 UseOnlyCustomTLSProfiles: {value: false}, 358 CustomTLSProfiles: {value: protocol.CustomTLSProfiles{}}, 359 SelectRandomizedTLSProfileProbability: {value: 0.25, minimum: 0.0}, 360 NoDefaultTLSSessionIDProbability: {value: 0.5, minimum: 0.0}, 361 DisableFrontingProviderTLSProfiles: {value: protocol.LabeledTLSProfiles{}}, 362 363 LimitQUICVersionsProbability: {value: 1.0, minimum: 0.0}, 364 LimitQUICVersions: {value: protocol.QUICVersions{}}, 365 DisableFrontingProviderQUICVersions: {value: protocol.LabeledQUICVersions{}}, 366 367 FragmentorProbability: {value: 0.5, minimum: 0.0}, 368 FragmentorLimitProtocols: {value: protocol.TunnelProtocols{}}, 369 FragmentorMinTotalBytes: {value: 0, minimum: 0}, 370 FragmentorMaxTotalBytes: {value: 0, minimum: 0}, 371 FragmentorMinWriteBytes: {value: 1, minimum: 1}, 372 FragmentorMaxWriteBytes: {value: 1500, minimum: 1}, 373 FragmentorMinDelay: {value: time.Duration(0), minimum: time.Duration(0)}, 374 FragmentorMaxDelay: {value: 10 * time.Millisecond, minimum: time.Duration(0)}, 375 FragmentorDownstreamProbability: {value: 0.5, minimum: 0.0, flags: serverSideOnly}, 376 FragmentorDownstreamLimitProtocols: {value: protocol.TunnelProtocols{}, flags: serverSideOnly}, 377 FragmentorDownstreamMinTotalBytes: {value: 0, minimum: 0, flags: serverSideOnly}, 378 FragmentorDownstreamMaxTotalBytes: {value: 0, minimum: 0, flags: serverSideOnly}, 379 FragmentorDownstreamMinWriteBytes: {value: 1, minimum: 1, flags: serverSideOnly}, 380 FragmentorDownstreamMaxWriteBytes: {value: 1500, minimum: 1, flags: serverSideOnly}, 381 FragmentorDownstreamMinDelay: {value: time.Duration(0), minimum: time.Duration(0), flags: serverSideOnly}, 382 FragmentorDownstreamMaxDelay: {value: 10 * time.Millisecond, minimum: time.Duration(0), flags: serverSideOnly}, 383 384 // The Psiphon server will reject obfuscated SSH seed messages with 385 // padding greater than OBFUSCATE_MAX_PADDING. 386 // obfuscator.NewClientObfuscator will ignore invalid min/max padding 387 // configurations. 388 389 ObfuscatedSSHMinPadding: {value: 0, minimum: 0}, 390 ObfuscatedSSHMaxPadding: {value: obfuscator.OBFUSCATE_MAX_PADDING, minimum: 0}, 391 392 AdditionalCustomHeaders: {value: make(http.Header)}, 393 394 // Speed test and SSH keep alive padding is intended to frustrate 395 // fingerprinting and should not exceed ~1 IP packet size. 396 // 397 // Currently, each serialized speed test sample, populated with real 398 // values, is approximately 100 bytes. All SpeedTestMaxSampleCount samples 399 // are loaded into memory are sent as API inputs. 400 401 SpeedTestPaddingMinBytes: {value: 0, minimum: 0}, 402 SpeedTestPaddingMaxBytes: {value: 256, minimum: 0}, 403 SpeedTestMaxSampleCount: {value: 25, minimum: 1}, 404 405 // The Psiphon server times out inactive tunnels after 5 minutes, so this 406 // is a soft max for SSHKeepAlivePeriodMax. 407 408 SSHKeepAliveSpeedTestSampleProbability: {value: 0.5, minimum: 0.0}, 409 SSHKeepAlivePaddingMinBytes: {value: 0, minimum: 0}, 410 SSHKeepAlivePaddingMaxBytes: {value: 256, minimum: 0}, 411 SSHKeepAlivePeriodMin: {value: 1 * time.Minute, minimum: 1 * time.Second}, 412 SSHKeepAlivePeriodMax: {value: 2 * time.Minute, minimum: 1 * time.Second}, 413 SSHKeepAlivePeriodicTimeout: {value: 30 * time.Second, minimum: 1 * time.Second, flags: useNetworkLatencyMultiplier}, 414 SSHKeepAlivePeriodicInactivePeriod: {value: 10 * time.Second, minimum: 1 * time.Second}, 415 SSHKeepAliveProbeTimeout: {value: 5 * time.Second, minimum: 1 * time.Second, flags: useNetworkLatencyMultiplier}, 416 SSHKeepAliveProbeInactivePeriod: {value: 10 * time.Second, minimum: 1 * time.Second}, 417 SSHKeepAliveNetworkConnectivityPollingPeriod: {value: 500 * time.Millisecond, minimum: 1 * time.Millisecond}, 418 SSHKeepAliveResetOnFailureProbability: {value: 0.0, minimum: 0.0}, 419 420 HTTPProxyOriginServerTimeout: {value: 15 * time.Second, minimum: time.Duration(0), flags: useNetworkLatencyMultiplier}, 421 HTTPProxyMaxIdleConnectionsPerHost: {value: 50, minimum: 0}, 422 423 FetchRemoteServerListTimeout: {value: 30 * time.Second, minimum: 1 * time.Second, flags: useNetworkLatencyMultiplier}, 424 FetchRemoteServerListRetryPeriod: {value: 30 * time.Second, minimum: 1 * time.Millisecond}, 425 FetchRemoteServerListStalePeriod: {value: 6 * time.Hour, minimum: 1 * time.Hour}, 426 RemoteServerListSignaturePublicKey: {value: ""}, 427 RemoteServerListURLs: {value: TransferURLs{}}, 428 ObfuscatedServerListRootURLs: {value: TransferURLs{}}, 429 430 PsiphonAPIRequestTimeout: {value: 20 * time.Second, minimum: 1 * time.Second, flags: useNetworkLatencyMultiplier}, 431 432 PsiphonAPIStatusRequestPeriodMin: {value: 5 * time.Minute, minimum: 1 * time.Second}, 433 PsiphonAPIStatusRequestPeriodMax: {value: 10 * time.Minute, minimum: 1 * time.Second}, 434 PsiphonAPIStatusRequestShortPeriodMin: {value: 5 * time.Second, minimum: 1 * time.Second}, 435 PsiphonAPIStatusRequestShortPeriodMax: {value: 10 * time.Second, minimum: 1 * time.Second}, 436 // PsiphonAPIPersistentStatsMaxCount parameter is obsoleted by PersistentStatsMaxSendBytes. 437 // TODO: remove once no longer required for older clients. 438 PsiphonAPIPersistentStatsMaxCount: {value: 100, minimum: 1}, 439 // PsiphonAPIStatusRequestPadding parameters are obsoleted by APIRequestUp/DownstreamPadding. 440 // TODO: remove once no longer required for older clients. 441 PsiphonAPIStatusRequestPaddingMinBytes: {value: 0, minimum: 0}, 442 PsiphonAPIStatusRequestPaddingMaxBytes: {value: 256, minimum: 0}, 443 444 PsiphonAPIConnectedRequestRetryPeriod: {value: 5 * time.Second, minimum: 1 * time.Millisecond}, 445 446 // FetchSplitTunnelRoutesTimeout, SplitTunnelRoutesURLFormat, 447 // SplitTunnelRoutesSignaturePublicKey and SplitTunnelDNSServer are obsoleted 448 // by the server-assisted split tunnel implementation. 449 // TODO: remove once no longer required for older clients. 450 FetchSplitTunnelRoutesTimeout: {value: 60 * time.Second, minimum: 1 * time.Second, flags: useNetworkLatencyMultiplier}, 451 SplitTunnelRoutesURLFormat: {value: ""}, 452 SplitTunnelRoutesSignaturePublicKey: {value: ""}, 453 SplitTunnelDNSServer: {value: ""}, 454 455 SplitTunnelClassificationTTL: {value: 24 * time.Hour, minimum: 0 * time.Second}, 456 SplitTunnelClassificationMaxEntries: {value: 65536, minimum: 0}, 457 458 FetchUpgradeTimeout: {value: 60 * time.Second, minimum: 1 * time.Second, flags: useNetworkLatencyMultiplier}, 459 FetchUpgradeRetryPeriod: {value: 30 * time.Second, minimum: 1 * time.Millisecond}, 460 FetchUpgradeStalePeriod: {value: 6 * time.Hour, minimum: 1 * time.Hour}, 461 UpgradeDownloadURLs: {value: TransferURLs{}}, 462 UpgradeDownloadClientVersionHeader: {value: ""}, 463 464 TotalBytesTransferredNoticePeriod: {value: 5 * time.Minute, minimum: 1 * time.Second}, 465 TotalBytesTransferredEmitMemoryMetrics: {value: true}, 466 467 // The meek server times out inactive sessions after 45 seconds, so this 468 // is a soft max for MeekMaxPollInterval, MeekRoundTripTimeout, and 469 // MeekRoundTripRetryDeadline. 470 // 471 // MeekCookieMaxPadding cannot exceed common.OBFUSCATE_SEED_LENGTH. 472 // 473 // MeekMinTLSPadding/MeekMinTLSPadding are subject to TLS server limitations. 474 // 475 // MeekMinLimitRequestPayloadLength/MeekMaxLimitRequestPayloadLength 476 // cannot exceed server.MEEK_MAX_REQUEST_PAYLOAD_LENGTH. 477 478 MeekDialDomainsOnly: {value: false}, 479 MeekLimitBufferSizes: {value: false}, 480 MeekCookieMaxPadding: {value: 256, minimum: 0}, 481 MeekFullReceiveBufferLength: {value: 4194304, minimum: 1024}, 482 MeekReadPayloadChunkLength: {value: 65536, minimum: 1024}, 483 MeekLimitedFullReceiveBufferLength: {value: 131072, minimum: 1024}, 484 MeekLimitedReadPayloadChunkLength: {value: 4096, minimum: 1024}, 485 MeekMinPollInterval: {value: 100 * time.Millisecond, minimum: 1 * time.Millisecond}, 486 MeekMinPollIntervalJitter: {value: 0.3, minimum: 0.0}, 487 MeekMaxPollInterval: {value: 5 * time.Second, minimum: 1 * time.Millisecond}, 488 MeekMaxPollIntervalJitter: {value: 0.1, minimum: 0.0}, 489 MeekPollIntervalMultiplier: {value: 1.5, minimum: 0.0}, 490 MeekPollIntervalJitter: {value: 0.1, minimum: 0.0}, 491 MeekApplyPollIntervalMultiplierProbability: {value: 0.5}, 492 MeekRoundTripRetryDeadline: {value: 5 * time.Second, minimum: 1 * time.Millisecond, flags: useNetworkLatencyMultiplier}, 493 MeekRoundTripRetryMinDelay: {value: 50 * time.Millisecond, minimum: time.Duration(0)}, 494 MeekRoundTripRetryMaxDelay: {value: 1 * time.Second, minimum: time.Duration(0)}, 495 MeekRoundTripRetryMultiplier: {value: 2.0, minimum: 0.0}, 496 MeekRoundTripTimeout: {value: 20 * time.Second, minimum: 1 * time.Second, flags: useNetworkLatencyMultiplier}, 497 498 MeekTrafficShapingProbability: {value: 1.0, minimum: 0.0}, 499 MeekTrafficShapingLimitProtocols: {value: protocol.TunnelProtocols{}}, 500 MeekMinTLSPadding: {value: 0, minimum: 0}, 501 MeekMaxTLSPadding: {value: 0, minimum: 0}, 502 MeekMinLimitRequestPayloadLength: {value: 65536, minimum: 1}, 503 MeekMaxLimitRequestPayloadLength: {value: 65536, minimum: 1}, 504 MeekRedialTLSProbability: {value: 0.0, minimum: 0.0}, 505 506 TransformHostNameProbability: {value: 0.5, minimum: 0.0}, 507 PickUserAgentProbability: {value: 0.5, minimum: 0.0}, 508 509 LivenessTestMinUpstreamBytes: {value: 0, minimum: 0}, 510 LivenessTestMaxUpstreamBytes: {value: 0, minimum: 0}, 511 LivenessTestMinDownstreamBytes: {value: 0, minimum: 0}, 512 LivenessTestMaxDownstreamBytes: {value: 0, minimum: 0}, 513 514 ReplayCandidateCount: {value: 10, minimum: -1}, 515 ReplayDialParametersTTL: {value: 24 * time.Hour, minimum: time.Duration(0)}, 516 ReplayTargetUpstreamBytes: {value: 0, minimum: 0}, 517 ReplayTargetDownstreamBytes: {value: 0, minimum: 0}, 518 ReplayTargetTunnelDuration: {value: 1 * time.Second, minimum: time.Duration(0)}, 519 ReplayBPF: {value: true}, 520 ReplaySSH: {value: true}, 521 ReplayObfuscatorPadding: {value: true}, 522 ReplayFragmentor: {value: true}, 523 ReplayTLSProfile: {value: true}, 524 ReplayRandomizedTLSProfile: {value: true}, 525 ReplayFronting: {value: true}, 526 ReplayHostname: {value: true}, 527 ReplayQUICVersion: {value: true}, 528 ReplayObfuscatedQUIC: {value: true}, 529 ReplayConjureRegistration: {value: true}, 530 ReplayConjureTransport: {value: true}, 531 ReplayLivenessTest: {value: true}, 532 ReplayUserAgent: {value: true}, 533 ReplayAPIRequestPadding: {value: true}, 534 ReplayLaterRoundMoveToFrontProbability: {value: 0.0, minimum: 0.0}, 535 ReplayRetainFailedProbability: {value: 0.5, minimum: 0.0}, 536 537 APIRequestUpstreamPaddingMinBytes: {value: 0, minimum: 0}, 538 APIRequestUpstreamPaddingMaxBytes: {value: 1024, minimum: 0}, 539 APIRequestDownstreamPaddingMinBytes: {value: 0, minimum: 0}, 540 APIRequestDownstreamPaddingMaxBytes: {value: 1024, minimum: 0}, 541 542 PersistentStatsMaxStoreRecords: {value: 200, minimum: 1}, 543 PersistentStatsMaxSendBytes: {value: 65536, minimum: 1}, 544 RecordRemoteServerListPersistentStatsProbability: {value: 1.0, minimum: 0.0}, 545 RecordFailedTunnelPersistentStatsProbability: {value: 0.0, minimum: 0.0}, 546 547 ServerEntryMinimumAgeForPruning: {value: 7 * 24 * time.Hour, minimum: 24 * time.Hour}, 548 549 ApplicationParametersProbability: {value: 1.0, minimum: 0.0}, 550 ApplicationParameters: {value: KeyValues{}}, 551 552 BPFServerTCPProgram: {value: (*BPFProgramSpec)(nil), flags: serverSideOnly}, 553 BPFServerTCPProbability: {value: 0.5, minimum: 0.0, flags: serverSideOnly}, 554 BPFClientTCPProgram: {value: (*BPFProgramSpec)(nil)}, 555 BPFClientTCPProbability: {value: 0.5, minimum: 0.0}, 556 557 ServerPacketManipulationSpecs: {value: PacketManipulationSpecs{}, flags: serverSideOnly}, 558 ServerProtocolPacketManipulations: {value: make(ProtocolPacketManipulations), flags: serverSideOnly}, 559 ServerPacketManipulationProbability: {value: 0.5, minimum: 0.0, flags: serverSideOnly}, 560 561 FeedbackUploadURLs: {value: TransferURLs{}}, 562 FeedbackEncryptionPublicKey: {value: ""}, 563 FeedbackTacticsWaitPeriod: {value: 5 * time.Second, minimum: 0 * time.Second, flags: useNetworkLatencyMultiplier}, 564 FeedbackUploadMaxAttempts: {value: 5, minimum: 0}, 565 FeedbackUploadRetryMinDelaySeconds: {value: 1 * time.Minute, minimum: time.Duration(0), flags: useNetworkLatencyMultiplier}, 566 FeedbackUploadRetryMaxDelaySeconds: {value: 5 * time.Minute, minimum: 1 * time.Second, flags: useNetworkLatencyMultiplier}, 567 FeedbackUploadTimeoutSeconds: {value: 30 * time.Second, minimum: 0 * time.Second, flags: useNetworkLatencyMultiplier}, 568 569 ServerReplayPacketManipulation: {value: true, flags: serverSideOnly}, 570 ServerReplayFragmentor: {value: true, flags: serverSideOnly}, 571 ServerReplayUnknownGeoIP: {value: false, flags: serverSideOnly}, 572 ServerReplayTTL: {value: time.Duration(0), minimum: time.Duration(0), flags: serverSideOnly}, 573 ServerReplayTargetWaitDuration: {value: time.Duration(0), minimum: time.Duration(0), flags: serverSideOnly}, 574 ServerReplayTargetTunnelDuration: {value: time.Duration(0), minimum: time.Duration(0), flags: serverSideOnly}, 575 ServerReplayTargetUpstreamBytes: {value: 0, minimum: 0, flags: serverSideOnly}, 576 ServerReplayTargetDownstreamBytes: {value: 0, minimum: 0, flags: serverSideOnly}, 577 ServerReplayFailedCountThreshold: {value: 0, minimum: 0, flags: serverSideOnly}, 578 579 ServerBurstUpstreamTargetBytes: {value: 0, minimum: 0, flags: serverSideOnly}, 580 ServerBurstUpstreamDeadline: {value: time.Duration(0), minimum: time.Duration(0), flags: serverSideOnly}, 581 ServerBurstDownstreamTargetBytes: {value: 0, minimum: 0, flags: serverSideOnly}, 582 ServerBurstDownstreamDeadline: {value: time.Duration(0), minimum: time.Duration(0), flags: serverSideOnly}, 583 ClientBurstUpstreamTargetBytes: {value: 0, minimum: 0}, 584 ClientBurstUpstreamDeadline: {value: time.Duration(0), minimum: time.Duration(0)}, 585 ClientBurstDownstreamTargetBytes: {value: 0, minimum: 0}, 586 ClientBurstDownstreamDeadline: {value: time.Duration(0), minimum: time.Duration(0)}, 587 588 ConjureCachedRegistrationTTL: {value: time.Duration(0), minimum: time.Duration(0)}, 589 ConjureAPIRegistrarURL: {value: ""}, 590 ConjureAPIRegistrarFrontingSpecs: {value: FrontingSpecs{}}, 591 ConjureAPIRegistrarMinDelay: {value: time.Duration(0), minimum: time.Duration(0)}, 592 ConjureAPIRegistrarMaxDelay: {value: time.Duration(0), minimum: time.Duration(0)}, 593 ConjureDecoyRegistrarProbability: {value: 0.0, minimum: 0.0}, 594 ConjureDecoyRegistrarWidth: {value: 5, minimum: 0}, 595 ConjureDecoyRegistrarMinDelay: {value: time.Duration(0), minimum: time.Duration(0)}, 596 ConjureDecoyRegistrarMaxDelay: {value: time.Duration(0), minimum: time.Duration(0)}, 597 598 ConjureTransportObfs4Probability: {value: 0.0, minimum: 0.0}, 599 600 CustomHostNameRegexes: {value: RegexStrings{}}, 601 CustomHostNameProbability: {value: 0.0, minimum: 0.0}, 602 CustomHostNameLimitProtocols: {value: protocol.TunnelProtocols{}}, 603} 604 605// IsServerSideOnly indicates if the parameter specified by name is used 606// server-side only. 607func IsServerSideOnly(name string) bool { 608 defaultParameter, ok := defaultParameters[name] 609 return ok && (defaultParameter.flags&serverSideOnly) != 0 610} 611 612// Parameters is a set of parameters. To use the parameters, call Get. To 613// apply new values to the parameters, call Set. 614type Parameters struct { 615 getValueLogger func(error) 616 snapshot atomic.Value 617} 618 619// NewParameters initializes a new Parameters with the default parameter 620// values. 621// 622// getValueLogger is optional, and is used to report runtime errors with 623// getValue; see comment in getValue. 624func NewParameters( 625 getValueLogger func(error)) (*Parameters, error) { 626 627 parameters := &Parameters{ 628 getValueLogger: getValueLogger, 629 } 630 631 _, err := parameters.Set("", false) 632 if err != nil { 633 return nil, errors.Trace(err) 634 } 635 636 return parameters, nil 637} 638 639func makeDefaultParameters() (map[string]interface{}, error) { 640 641 parameters := make(map[string]interface{}) 642 643 for name, defaults := range defaultParameters { 644 645 if defaults.value == nil { 646 return nil, errors.Tracef("default parameter missing value: %s", name) 647 } 648 649 if defaults.minimum != nil && 650 reflect.TypeOf(defaults.value) != reflect.TypeOf(defaults.minimum) { 651 652 return nil, errors.Tracef("default parameter value and minimum type mismatch: %s", name) 653 } 654 655 _, isDuration := defaults.value.(time.Duration) 656 if defaults.flags&useNetworkLatencyMultiplier != 0 && !isDuration { 657 return nil, errors.Tracef("default non-duration parameter uses multipler: %s", name) 658 } 659 660 parameters[name] = defaults.value 661 } 662 663 return parameters, nil 664} 665 666// Set replaces the current parameters. First, a set of parameters are 667// initialized using the default values. Then, each applyParameters is applied 668// in turn, with the later instances having precedence. 669// 670// When skipOnError is true, unknown or invalid parameters in any 671// applyParameters are skipped instead of aborting with an error. 672// 673// For protocol.TunnelProtocols and protocol.TLSProfiles type values, when 674// skipOnError is true the values are filtered instead of validated, so 675// only known tunnel protocols and TLS profiles are retained. 676// 677// When an error is returned, the previous parameters remain completely 678// unmodified. 679// 680// For use in logging, Set returns a count of the number of parameters applied 681// from each applyParameters. 682func (p *Parameters) Set( 683 tag string, skipOnError bool, applyParameters ...map[string]interface{}) ([]int, error) { 684 685 makeTypedValue := func(templateValue, value interface{}) (interface{}, error) { 686 687 // Accept strings such as "1h" for duration parameters. 688 689 switch templateValue.(type) { 690 case time.Duration: 691 if s, ok := value.(string); ok { 692 if d, err := time.ParseDuration(s); err == nil { 693 value = d 694 } 695 } 696 } 697 698 // A JSON remarshal resolves cases where applyParameters is a 699 // result of unmarshal-into-interface, in which case non-scalar 700 // values will not have the expected types; see: 701 // https://github.com/ooni/psiphon/oopsi/golang.org/pkg/encoding/json/#Unmarshal. This remarshal 702 // also results in a deep copy. 703 704 marshaledValue, err := json.Marshal(value) 705 if err != nil { 706 return nil, errors.Trace(err) 707 } 708 709 newValuePtr := reflect.New(reflect.TypeOf(templateValue)) 710 711 err = json.Unmarshal(marshaledValue, newValuePtr.Interface()) 712 if err != nil { 713 return nil, errors.Trace(err) 714 } 715 716 return newValuePtr.Elem().Interface(), nil 717 } 718 719 getAppliedValue := func( 720 name string, 721 parameters map[string]interface{}, 722 applyParameters []map[string]interface{}) (interface{}, error) { 723 724 templateValue := parameters[name] 725 if templateValue == nil { 726 return nil, errors.Tracef("unknown parameter: %s", name) 727 } 728 729 value := templateValue 730 for i := len(applyParameters) - 1; i >= 0; i-- { 731 if v := applyParameters[i][name]; v != nil { 732 value = v 733 break 734 } 735 } 736 737 return makeTypedValue(templateValue, value) 738 } 739 740 var counts []int 741 742 parameters, err := makeDefaultParameters() 743 if err != nil { 744 return nil, errors.Trace(err) 745 } 746 747 // Special case: TLSProfiles/LabeledTLSProfiles may reference 748 // CustomTLSProfiles names. Inspect the CustomTLSProfiles parameter and 749 // extract its names. Do not call Get().CustomTLSProfilesNames() as 750 // CustomTLSProfiles may not yet be validated. 751 752 customTLSProfilesValue, err := getAppliedValue( 753 CustomTLSProfiles, parameters, applyParameters) 754 if err != nil { 755 return nil, errors.Trace(err) 756 } 757 customTLSProfiles, _ := customTLSProfilesValue.(protocol.CustomTLSProfiles) 758 customTLSProfileNames := make([]string, len(customTLSProfiles)) 759 for i, profile := range customTLSProfiles { 760 customTLSProfileNames[i] = profile.Name 761 } 762 763 // Special case: PacketManipulations will reference PacketManipulationSpecs. 764 765 serverPacketManipulationSpecsValue, err := getAppliedValue( 766 ServerPacketManipulationSpecs, parameters, applyParameters) 767 if err != nil { 768 return nil, errors.Trace(err) 769 } 770 serverPacketManipulationSpecs, _ := 771 serverPacketManipulationSpecsValue.(PacketManipulationSpecs) 772 773 for i := 0; i < len(applyParameters); i++ { 774 775 count := 0 776 777 for name, value := range applyParameters[i] { 778 779 templateValue, ok := parameters[name] 780 if !ok { 781 if skipOnError { 782 continue 783 } 784 return nil, errors.Tracef("unknown parameter: %s", name) 785 } 786 787 newValue, err := makeTypedValue(templateValue, value) 788 if err != nil { 789 if skipOnError { 790 continue 791 } 792 return nil, errors.Tracef( 793 "unmarshal parameter %s failed: %v", name, err) 794 } 795 796 // Perform type-specific validation for some cases. 797 798 // TODO: require RemoteServerListSignaturePublicKey when 799 // RemoteServerListURLs is set? 800 801 switch v := newValue.(type) { 802 case TransferURLs: 803 err := v.DecodeAndValidate() 804 if err != nil { 805 if skipOnError { 806 continue 807 } 808 return nil, errors.Trace(err) 809 } 810 case protocol.TunnelProtocols: 811 if skipOnError { 812 newValue = v.PruneInvalid() 813 } else { 814 err := v.Validate() 815 if err != nil { 816 return nil, errors.Trace(err) 817 } 818 } 819 case protocol.TLSProfiles: 820 if skipOnError { 821 newValue = v.PruneInvalid(customTLSProfileNames) 822 } else { 823 err := v.Validate(customTLSProfileNames) 824 if err != nil { 825 return nil, errors.Trace(err) 826 } 827 } 828 case protocol.LabeledTLSProfiles: 829 830 if skipOnError { 831 newValue = v.PruneInvalid(customTLSProfileNames) 832 } else { 833 err := v.Validate(customTLSProfileNames) 834 if err != nil { 835 return nil, errors.Trace(err) 836 } 837 } 838 case protocol.QUICVersions: 839 if skipOnError { 840 newValue = v.PruneInvalid() 841 } else { 842 err := v.Validate() 843 if err != nil { 844 return nil, errors.Trace(err) 845 } 846 } 847 case protocol.LabeledQUICVersions: 848 if skipOnError { 849 newValue = v.PruneInvalid() 850 } else { 851 err := v.Validate() 852 if err != nil { 853 return nil, errors.Trace(err) 854 } 855 } 856 case protocol.CustomTLSProfiles: 857 err := v.Validate() 858 if err != nil { 859 if skipOnError { 860 continue 861 } 862 return nil, errors.Trace(err) 863 } 864 case KeyValues: 865 err := v.Validate() 866 if err != nil { 867 if skipOnError { 868 continue 869 } 870 return nil, errors.Trace(err) 871 } 872 case *BPFProgramSpec: 873 if v != nil { 874 err := v.Validate() 875 if err != nil { 876 if skipOnError { 877 continue 878 } 879 return nil, errors.Trace(err) 880 } 881 } 882 case PacketManipulationSpecs: 883 err := v.Validate() 884 if err != nil { 885 if skipOnError { 886 continue 887 } 888 return nil, errors.Trace(err) 889 } 890 case ProtocolPacketManipulations: 891 892 var packetManipulationSpecs PacketManipulationSpecs 893 if name == ServerProtocolPacketManipulations { 894 packetManipulationSpecs = serverPacketManipulationSpecs 895 } 896 897 err := v.Validate(packetManipulationSpecs) 898 if err != nil { 899 if skipOnError { 900 continue 901 } 902 return nil, errors.Trace(err) 903 } 904 case RegexStrings: 905 err := v.Validate() 906 if err != nil { 907 if skipOnError { 908 continue 909 } 910 return nil, errors.Trace(err) 911 } 912 } 913 914 // Enforce any minimums. Assumes defaultParameters[name] 915 // exists. 916 if defaultParameters[name].minimum != nil { 917 valid := true 918 switch v := newValue.(type) { 919 case int: 920 m, ok := defaultParameters[name].minimum.(int) 921 if !ok || v < m { 922 valid = false 923 } 924 case float64: 925 m, ok := defaultParameters[name].minimum.(float64) 926 if !ok || v < m { 927 valid = false 928 } 929 case time.Duration: 930 m, ok := defaultParameters[name].minimum.(time.Duration) 931 if !ok || v < m { 932 valid = false 933 } 934 default: 935 if skipOnError { 936 continue 937 } 938 return nil, errors.Tracef("unexpected parameter with minimum: %s", name) 939 } 940 if !valid { 941 if skipOnError { 942 continue 943 } 944 return nil, errors.Tracef("parameter below minimum: %s", name) 945 } 946 } 947 948 parameters[name] = newValue 949 950 count++ 951 } 952 953 counts = append(counts, count) 954 } 955 956 snapshot := ¶metersSnapshot{ 957 getValueLogger: p.getValueLogger, 958 tag: tag, 959 parameters: parameters, 960 } 961 962 p.snapshot.Store(snapshot) 963 964 return counts, nil 965} 966 967// Get returns the current parameters. 968// 969// Values read from the current parameters are not deep copies and must be 970// treated read-only. 971// 972// The returned ParametersAccessor may be used to read multiple related values 973// atomically and consistently while the current set of values in Parameters 974// may change concurrently. 975// 976// Get does not perform any heap allocations and is intended for repeated, 977// direct, low-overhead invocations. 978func (p *Parameters) Get() ParametersAccessor { 979 return ParametersAccessor{ 980 snapshot: p.snapshot.Load().(*parametersSnapshot)} 981} 982 983// GetCustom returns the current parameters while also setting customizations 984// for this instance. 985// 986// The properties of Get also apply to GetCustom: must be read-only; atomic 987// and consisent view; no heap allocations. 988// 989// Customizations include: 990// 991// - customNetworkLatencyMultiplier, which overrides NetworkLatencyMultiplier 992// for this instance only. 993// 994func (p *Parameters) GetCustom( 995 customNetworkLatencyMultiplier float64) ParametersAccessor { 996 997 return ParametersAccessor{ 998 snapshot: p.snapshot.Load().(*parametersSnapshot), 999 customNetworkLatencyMultiplier: customNetworkLatencyMultiplier, 1000 } 1001} 1002 1003// parametersSnapshot is an atomic snapshot of the parameter values. 1004// Parameters.Get will return a snapshot which may be used to read multiple 1005// related values atomically and consistently while the current snapshot in 1006// Parameters may change concurrently. 1007type parametersSnapshot struct { 1008 getValueLogger func(error) 1009 tag string 1010 parameters map[string]interface{} 1011} 1012 1013// getValue sets target to the value of the named parameter. 1014// 1015// It is an error if the name is not found, target is not a pointer, or the 1016// type of target points to does not match the value. 1017// 1018// Any of these conditions would be a bug in the caller. getValue does not 1019// panic in these cases as clients are deployed as a library in various apps 1020// and the failure of Psiphon may not be a failure for the app process. 1021// 1022// Instead, errors are logged to the getValueLogger and getValue leaves the 1023// target unset, which will result in the caller getting and using a zero 1024// value of the requested type. 1025func (p *parametersSnapshot) getValue(name string, target interface{}) { 1026 1027 value, ok := p.parameters[name] 1028 if !ok { 1029 if p.getValueLogger != nil { 1030 p.getValueLogger(errors.Tracef( 1031 "value %s not found", name)) 1032 } 1033 return 1034 } 1035 1036 valueType := reflect.TypeOf(value) 1037 1038 if reflect.PtrTo(valueType) != reflect.TypeOf(target) { 1039 if p.getValueLogger != nil { 1040 p.getValueLogger(errors.Tracef( 1041 "value %s has unexpected type %s", name, valueType.Name())) 1042 } 1043 return 1044 } 1045 1046 // Note: there is no deep copy of parameter values; the returned value may 1047 // share memory with the original and should not be modified. 1048 1049 targetValue := reflect.ValueOf(target) 1050 1051 if targetValue.Kind() != reflect.Ptr { 1052 p.getValueLogger(errors.Tracef( 1053 "target for value %s is not pointer", name)) 1054 return 1055 } 1056 1057 targetValue.Elem().Set(reflect.ValueOf(value)) 1058} 1059 1060// ParametersAccessor provides consistent, atomic access to parameter values. 1061// Any customizations are applied transparently. 1062type ParametersAccessor struct { 1063 snapshot *parametersSnapshot 1064 customNetworkLatencyMultiplier float64 1065} 1066 1067// MakeNilParametersAccessor produces a stub ParametersAccessor which returns 1068// true for IsNil. This may be used where a ParametersAccessor value is 1069// required, but Parameters.Get may not succeed. In contexts where 1070// MakeNilParametersAccessor may be used, calls to ParametersAccessor must 1071// first check IsNil before calling accessor functions. 1072func MakeNilParametersAccessor() ParametersAccessor { 1073 return ParametersAccessor{} 1074} 1075 1076// IsNil indicates that this ParametersAccessor is a stub and its accessor 1077// functions may not be called. A ParametersAccessor produced by 1078// Parameters.Get will never return true for IsNil and IsNil guards are not 1079// required for ParametersAccessors known to be produced by Parameters.Get. 1080func (p ParametersAccessor) IsNil() bool { 1081 return p.snapshot == nil 1082} 1083 1084// Close clears internal references to large memory objects, allowing them to 1085// be garbage collected. Call Close when done using a ParametersAccessor, 1086// where memory footprint is a concern, and where the ParametersAccessor is 1087// not immediately going out of scope. After Close is called, all other 1088// ParametersAccessor functions will panic if called. 1089func (p ParametersAccessor) Close() { 1090 p.snapshot = nil 1091} 1092 1093// Tag returns the tag associated with these parameters. 1094func (p ParametersAccessor) Tag() string { 1095 return p.snapshot.tag 1096} 1097 1098// String returns a string parameter value. 1099func (p ParametersAccessor) String(name string) string { 1100 value := "" 1101 p.snapshot.getValue(name, &value) 1102 return value 1103} 1104 1105func (p ParametersAccessor) Strings(name string) []string { 1106 value := []string{} 1107 p.snapshot.getValue(name, &value) 1108 return value 1109} 1110 1111// Int returns an int parameter value. 1112func (p ParametersAccessor) Int(name string) int { 1113 value := int(0) 1114 p.snapshot.getValue(name, &value) 1115 return value 1116} 1117 1118// Bool returns a bool parameter value. 1119func (p ParametersAccessor) Bool(name string) bool { 1120 value := false 1121 p.snapshot.getValue(name, &value) 1122 return value 1123} 1124 1125// Float returns a float64 parameter value. 1126func (p ParametersAccessor) Float(name string) float64 { 1127 value := float64(0.0) 1128 p.snapshot.getValue(name, &value) 1129 return value 1130} 1131 1132// WeightedCoinFlip returns the result of prng.FlipWeightedCoin using the 1133// specified float parameter as the probability input. 1134func (p ParametersAccessor) WeightedCoinFlip(name string) bool { 1135 var value float64 1136 p.snapshot.getValue(name, &value) 1137 return prng.FlipWeightedCoin(value) 1138} 1139 1140// Duration returns a time.Duration parameter value. When the duration 1141// parameter has the useNetworkLatencyMultiplier flag, the 1142// NetworkLatencyMultiplier is applied to the returned value. 1143func (p ParametersAccessor) Duration(name string) time.Duration { 1144 value := time.Duration(0) 1145 p.snapshot.getValue(name, &value) 1146 1147 defaultParameter, ok := defaultParameters[name] 1148 if value > 0 && ok && defaultParameter.flags&useNetworkLatencyMultiplier != 0 { 1149 1150 multiplier := float64(0.0) 1151 1152 if p.customNetworkLatencyMultiplier != 0.0 { 1153 multiplier = p.customNetworkLatencyMultiplier 1154 } else { 1155 p.snapshot.getValue(NetworkLatencyMultiplier, &multiplier) 1156 } 1157 1158 if multiplier > 0.0 { 1159 value = time.Duration(float64(value) * multiplier) 1160 } 1161 1162 } 1163 1164 return value 1165} 1166 1167// TunnelProtocols returns a protocol.TunnelProtocols parameter value. 1168// If there is a corresponding Probability value, a weighted coin flip 1169// will be performed and, depending on the result, the value or the 1170// parameter default will be returned. 1171func (p ParametersAccessor) TunnelProtocols(name string) protocol.TunnelProtocols { 1172 1173 probabilityName := name + "Probability" 1174 _, ok := p.snapshot.parameters[probabilityName] 1175 if ok { 1176 probabilityValue := float64(1.0) 1177 p.snapshot.getValue(probabilityName, &probabilityValue) 1178 if !prng.FlipWeightedCoin(probabilityValue) { 1179 defaultParameter, ok := defaultParameters[name] 1180 if ok { 1181 defaultValue, ok := defaultParameter.value.(protocol.TunnelProtocols) 1182 if ok { 1183 value := make(protocol.TunnelProtocols, len(defaultValue)) 1184 copy(value, defaultValue) 1185 return value 1186 } 1187 } 1188 } 1189 } 1190 1191 value := protocol.TunnelProtocols{} 1192 p.snapshot.getValue(name, &value) 1193 return value 1194} 1195 1196// TLSProfiles returns a protocol.TLSProfiles parameter value. 1197// If there is a corresponding Probability value, a weighted coin flip 1198// will be performed and, depending on the result, the value or the 1199// parameter default will be returned. 1200func (p ParametersAccessor) TLSProfiles(name string) protocol.TLSProfiles { 1201 1202 probabilityName := name + "Probability" 1203 _, ok := p.snapshot.parameters[probabilityName] 1204 if ok { 1205 probabilityValue := float64(1.0) 1206 p.snapshot.getValue(probabilityName, &probabilityValue) 1207 if !prng.FlipWeightedCoin(probabilityValue) { 1208 defaultParameter, ok := defaultParameters[name] 1209 if ok { 1210 defaultValue, ok := defaultParameter.value.(protocol.TLSProfiles) 1211 if ok { 1212 value := make(protocol.TLSProfiles, len(defaultValue)) 1213 copy(value, defaultValue) 1214 return value 1215 } 1216 } 1217 } 1218 } 1219 1220 value := protocol.TLSProfiles{} 1221 p.snapshot.getValue(name, &value) 1222 return value 1223} 1224 1225// LabeledTLSProfiles returns a protocol.TLSProfiles parameter value 1226// corresponding to the specified labeled set and label value. The return 1227// value is nil when no set is found. 1228func (p ParametersAccessor) LabeledTLSProfiles(name, label string) protocol.TLSProfiles { 1229 var value protocol.LabeledTLSProfiles 1230 p.snapshot.getValue(name, &value) 1231 return value[label] 1232} 1233 1234// QUICVersions returns a protocol.QUICVersions parameter value. 1235// If there is a corresponding Probability value, a weighted coin flip 1236// will be performed and, depending on the result, the value or the 1237// parameter default will be returned. 1238func (p ParametersAccessor) QUICVersions(name string) protocol.QUICVersions { 1239 1240 probabilityName := name + "Probability" 1241 _, ok := p.snapshot.parameters[probabilityName] 1242 if ok { 1243 probabilityValue := float64(1.0) 1244 p.snapshot.getValue(probabilityName, &probabilityValue) 1245 if !prng.FlipWeightedCoin(probabilityValue) { 1246 defaultParameter, ok := defaultParameters[name] 1247 if ok { 1248 defaultValue, ok := defaultParameter.value.(protocol.QUICVersions) 1249 if ok { 1250 value := make(protocol.QUICVersions, len(defaultValue)) 1251 copy(value, defaultValue) 1252 return value 1253 } 1254 } 1255 } 1256 } 1257 1258 value := protocol.QUICVersions{} 1259 p.snapshot.getValue(name, &value) 1260 return value 1261} 1262 1263// LabeledQUICVersions returns a protocol.QUICVersions parameter value 1264// corresponding to the specified labeled set and label value. The return 1265// value is nil when no set is found. 1266func (p ParametersAccessor) LabeledQUICVersions(name, label string) protocol.QUICVersions { 1267 value := protocol.LabeledQUICVersions{} 1268 p.snapshot.getValue(name, &value) 1269 return value[label] 1270} 1271 1272// TransferURLs returns a TransferURLs parameter value. 1273func (p ParametersAccessor) TransferURLs(name string) TransferURLs { 1274 value := TransferURLs{} 1275 p.snapshot.getValue(name, &value) 1276 return value 1277} 1278 1279// RateLimits returns a common.RateLimits parameter value. 1280func (p ParametersAccessor) RateLimits(name string) common.RateLimits { 1281 value := common.RateLimits{} 1282 p.snapshot.getValue(name, &value) 1283 return value 1284} 1285 1286// HTTPHeaders returns an http.Header parameter value. 1287func (p ParametersAccessor) HTTPHeaders(name string) http.Header { 1288 value := make(http.Header) 1289 p.snapshot.getValue(name, &value) 1290 return value 1291} 1292 1293// CustomTLSProfileNames returns the CustomTLSProfile.Name fields for 1294// each profile in the CustomTLSProfiles parameter value. 1295func (p ParametersAccessor) CustomTLSProfileNames() []string { 1296 value := protocol.CustomTLSProfiles{} 1297 p.snapshot.getValue(CustomTLSProfiles, &value) 1298 names := make([]string, len(value)) 1299 for i := 0; i < len(value); i++ { 1300 names[i] = value[i].Name 1301 } 1302 return names 1303} 1304 1305// CustomTLSProfile returns the CustomTLSProfile fields with the specified 1306// Name field if it exists in the CustomTLSProfiles parameter value. 1307// Returns nil if not found. 1308func (p ParametersAccessor) CustomTLSProfile(name string) *protocol.CustomTLSProfile { 1309 value := protocol.CustomTLSProfiles{} 1310 p.snapshot.getValue(CustomTLSProfiles, &value) 1311 1312 // Note: linear lookup -- assumes a short list 1313 1314 for i := 0; i < len(value); i++ { 1315 if value[i].Name == name { 1316 return value[i] 1317 } 1318 } 1319 return nil 1320} 1321 1322// KeyValues returns a KeyValues parameter value. 1323func (p ParametersAccessor) KeyValues(name string) KeyValues { 1324 value := KeyValues{} 1325 p.snapshot.getValue(name, &value) 1326 return value 1327} 1328 1329// BPFProgram returns an assembled BPF program corresponding to a 1330// BPFProgramSpec parameter value. Returns nil in the case of any empty 1331// program. 1332func (p ParametersAccessor) BPFProgram(name string) (bool, string, []bpf.RawInstruction) { 1333 var value *BPFProgramSpec 1334 p.snapshot.getValue(name, &value) 1335 if value == nil { 1336 return false, "", nil 1337 } 1338 // Validation checks that Assemble is successful. 1339 rawInstructions, _ := value.Assemble() 1340 return true, value.Name, rawInstructions 1341} 1342 1343// PacketManipulationSpecs returns a PacketManipulationSpecs parameter value. 1344func (p ParametersAccessor) PacketManipulationSpecs(name string) PacketManipulationSpecs { 1345 value := PacketManipulationSpecs{} 1346 p.snapshot.getValue(name, &value) 1347 return value 1348} 1349 1350// ProtocolPacketManipulations returns a ProtocolPacketManipulations parameter value. 1351func (p ParametersAccessor) ProtocolPacketManipulations(name string) ProtocolPacketManipulations { 1352 value := make(ProtocolPacketManipulations) 1353 p.snapshot.getValue(name, &value) 1354 return value 1355} 1356 1357// RegexStrings returns a RegexStrings parameter value. 1358func (p ParametersAccessor) RegexStrings(name string) RegexStrings { 1359 value := RegexStrings{} 1360 p.snapshot.getValue(name, &value) 1361 return value 1362} 1363 1364// FrontingSpecs returns a FrontingSpecs parameter value. 1365func (p ParametersAccessor) FrontingSpecs(name string) FrontingSpecs { 1366 value := FrontingSpecs{} 1367 p.snapshot.getValue(name, &value) 1368 return value 1369} 1370