config.go 46 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196
  1. /*
  2. * Copyright (c) 2016, 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. package server
  20. import (
  21. "crypto/rand"
  22. "crypto/rsa"
  23. "crypto/x509"
  24. "encoding/base64"
  25. "encoding/hex"
  26. "encoding/json"
  27. "encoding/pem"
  28. "fmt"
  29. "net"
  30. "os"
  31. "strconv"
  32. "strings"
  33. "sync/atomic"
  34. "time"
  35. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common"
  36. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/accesscontrol"
  37. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/crypto/ssh"
  38. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/errors"
  39. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/osl"
  40. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/prng"
  41. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/protocol"
  42. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/tactics"
  43. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/values"
  44. "golang.org/x/crypto/nacl/box"
  45. )
  46. const (
  47. SERVER_CONFIG_FILENAME = "psiphond.config"
  48. SERVER_TRAFFIC_RULES_CONFIG_FILENAME = "psiphond-traffic-rules.config"
  49. SERVER_OSL_CONFIG_FILENAME = "psiphond-osl.config"
  50. SERVER_TACTICS_CONFIG_FILENAME = "psiphond-tactics.config"
  51. SERVER_ENTRY_FILENAME = "server-entry.dat"
  52. DEFAULT_SERVER_IP_ADDRESS = "127.0.0.1"
  53. WEB_SERVER_SECRET_BYTE_LENGTH = 32
  54. DISCOVERY_VALUE_KEY_BYTE_LENGTH = 32
  55. SSH_USERNAME_SUFFIX_BYTE_LENGTH = 8
  56. SSH_PASSWORD_BYTE_LENGTH = 32
  57. SSH_RSA_HOST_KEY_BITS = 2048
  58. SSH_OBFUSCATED_KEY_BYTE_LENGTH = 32
  59. PEAK_UPSTREAM_FAILURE_RATE_MINIMUM_SAMPLE_SIZE = 10
  60. PERIODIC_GARBAGE_COLLECTION = 120 * time.Second
  61. STOP_ESTABLISH_TUNNELS_ESTABLISHED_CLIENT_THRESHOLD = 20
  62. DEFAULT_LOG_FILE_REOPEN_RETRIES = 25
  63. )
  64. // Config specifies the configuration and behavior of a Psiphon
  65. // server.
  66. type Config struct {
  67. // LogLevel specifies the log level. Valid values are:
  68. // panic, fatal, error, warn, info, debug
  69. LogLevel string
  70. // LogFilename specifies the path of the file to log
  71. // to. When blank, logs are written to stderr.
  72. LogFilename string
  73. // LogFileReopenRetries specifies how many retries, each with a 1ms delay,
  74. // will be attempted after reopening a rotated log file fails. Retries
  75. // mitigate any race conditions between writes/reopens and file operations
  76. // performed by external log managers, such as logrotate.
  77. //
  78. // When omitted, DEFAULT_LOG_FILE_REOPEN_RETRIES is used.
  79. LogFileReopenRetries *int
  80. // LogFileCreateMode specifies that the Psiphon server should create a new
  81. // log file when one is not found, such as after rotation with logrotate
  82. // configured with nocreate. The value is the os.FileMode value to use when
  83. // creating the file.
  84. //
  85. // When omitted, the Psiphon server does not create log files.
  86. LogFileCreateMode *int
  87. // SkipPanickingLogWriter disables panicking when
  88. // unable to write any logs.
  89. SkipPanickingLogWriter bool
  90. // DiscoveryValueHMACKey is the network-wide secret value
  91. // used to determine a unique discovery strategy.
  92. DiscoveryValueHMACKey string
  93. // GeoIPDatabaseFilenames are paths of GeoIP2/GeoLite2
  94. // MaxMind database files. When empty, no GeoIP lookups are
  95. // performed. Each file is queried, in order, for the
  96. // logged fields: country code, city, and ISP. Multiple
  97. // file support accommodates the MaxMind distribution where
  98. // ISP data in a separate file.
  99. GeoIPDatabaseFilenames []string
  100. // PsinetDatabaseFilename is the path of the file containing
  101. // psinet.Database data.
  102. PsinetDatabaseFilename string
  103. // HostID identifies the server host; this value is included with all logs.
  104. HostID string
  105. // HostProvider identifies the server host provider; this value is
  106. // included with all logs and logged only when not blank.
  107. HostProvider string
  108. // ServerIPAddress is the public IP address of the server.
  109. ServerIPAddress string
  110. // WebServerPort is the listening port of the web server.
  111. // When <= 0, no web server component is run.
  112. WebServerPort int
  113. // WebServerSecret is the unique secret value that the client
  114. // must supply to make requests to the web server.
  115. WebServerSecret string
  116. // WebServerCertificate is the certificate the client uses to
  117. // authenticate the web server.
  118. WebServerCertificate string
  119. // WebServerPrivateKey is the private key the web server uses to
  120. // authenticate itself to clients.
  121. WebServerPrivateKey string
  122. // WebServerPortForwardAddress specifies the expected network
  123. // address ("<host>:<port>") specified in a client's port forward
  124. // HostToConnect and PortToConnect when the client is making a
  125. // tunneled connection to the web server. This address is always
  126. // exempted from validation against SSH_DISALLOWED_PORT_FORWARD_HOSTS
  127. // and AllowTCPPorts.
  128. WebServerPortForwardAddress string
  129. // WebServerPortForwardRedirectAddress specifies an alternate
  130. // destination address to be substituted and dialed instead of
  131. // the original destination when the port forward destination is
  132. // WebServerPortForwardAddress.
  133. WebServerPortForwardRedirectAddress string
  134. // TunnelProtocolPorts specifies which tunnel protocols to run
  135. // and which ports to listen on for each protocol. Valid tunnel
  136. // protocols include:
  137. // "SSH", "OSSH", "TLS-OSSH", "UNFRONTED-MEEK-OSSH", "UNFRONTED-MEEK-HTTPS-OSSH",
  138. // "UNFRONTED-MEEK-SESSION-TICKET-OSSH", "FRONTED-MEEK-OSSH",
  139. // "FRONTED-MEEK-QUIC-OSSH", "FRONTED-MEEK-HTTP-OSSH", "QUIC-OSSH",
  140. // "TAPDANCE-OSSH", abd "CONJURE-OSSH".
  141. TunnelProtocolPorts map[string]int
  142. // TunnelProtocolPassthroughAddresses specifies passthrough addresses to be
  143. // used for tunnel protocols configured in TunnelProtocolPorts. Passthrough
  144. // is a probing defense which relays all network traffic between a client and
  145. // the passthrough target when the client fails anti-probing tests.
  146. //
  147. // TunnelProtocolPassthroughAddresses is supported for:
  148. // "TLS-OSSH", "UNFRONTED-MEEK-HTTPS-OSSH",
  149. // "UNFRONTED-MEEK-SESSION-TICKET-OSSH", "UNFRONTED-MEEK-OSSH".
  150. TunnelProtocolPassthroughAddresses map[string]string
  151. // LegacyPassthrough indicates whether to expect legacy passthrough messages
  152. // from clients attempting to connect. This should be set for existing/legacy
  153. // passthrough servers only.
  154. LegacyPassthrough bool
  155. // EnableGQUIC indicates whether to enable legacy gQUIC QUIC-OSSH
  156. // versions, for backwards compatibility with all versions used by older
  157. // clients. Enabling gQUIC degrades the anti-probing stance of QUIC-OSSH,
  158. // as the legacy gQUIC stack will respond to probing packets.
  159. EnableGQUIC bool
  160. // SSHPrivateKey is the SSH host key. The same key is used for
  161. // all protocols, run by this server instance, which use SSH.
  162. SSHPrivateKey string
  163. // SSHServerVersion is the server version presented in the
  164. // identification string. The same value is used for all
  165. // protocols, run by this server instance, which use SSH.
  166. SSHServerVersion string
  167. // SSHUserName is the SSH user name to be presented by the
  168. // the tunnel-core client. The same value is used for all
  169. // protocols, run by this server instance, which use SSH.
  170. SSHUserName string
  171. // SSHPassword is the SSH password to be presented by the
  172. // the tunnel-core client. The same value is used for all
  173. // protocols, run by this server instance, which use SSH.
  174. SSHPassword string
  175. // SSHBeginHandshakeTimeoutMilliseconds specifies the timeout
  176. // for clients queueing to begin an SSH handshake. The default
  177. // is SSH_BEGIN_HANDSHAKE_TIMEOUT.
  178. SSHBeginHandshakeTimeoutMilliseconds *int
  179. // SSHHandshakeTimeoutMilliseconds specifies the timeout
  180. // before which a client must complete its handshake. The default
  181. // is SSH_HANDSHAKE_TIMEOUT.
  182. SSHHandshakeTimeoutMilliseconds *int
  183. // ObfuscatedSSHKey is the secret key for use in the Obfuscated
  184. // SSH protocol. The same secret key is used for all protocols,
  185. // run by this server instance, which use Obfuscated SSH.
  186. ObfuscatedSSHKey string
  187. // MeekCookieEncryptionPrivateKey is the NaCl private key used
  188. // to decrypt meek cookie payload sent from clients. The same
  189. // key is used for all meek protocols run by this server instance.
  190. MeekCookieEncryptionPrivateKey string
  191. // MeekObfuscatedKey is the secret key used for obfuscating
  192. // meek cookies sent from clients. The same key is used for all
  193. // meek protocols run by this server instance.
  194. //
  195. // NOTE: this key is also used by the TLS-OSSH protocol, which allows
  196. // clients with legacy unfronted meek-https server entries, that have the
  197. // passthrough capability, to connect with TLS-OSSH to the servers
  198. // corresponding to those server entries, which now support TLS-OSSH by
  199. // demultiplexing meek-https and TLS-OSSH over the meek-https port.
  200. MeekObfuscatedKey string
  201. // MeekProhibitedHeaders is a list of HTTP headers to check for
  202. // in client requests. If one of these headers is found, the
  203. // request fails. This is used to defend against abuse.
  204. MeekProhibitedHeaders []string
  205. // MeekRequiredHeaders is a list of HTTP header names and values that must
  206. // appear in requests. This is used to defend against abuse.
  207. MeekRequiredHeaders map[string]string
  208. // MeekProxyForwardedForHeaders is a list of HTTP headers which
  209. // may be added by downstream HTTP proxies or CDNs in front
  210. // of clients. These headers supply the original client IP
  211. // address, which is geolocated for stats purposes. Headers
  212. // include, for example, X-Forwarded-For. The header's value
  213. // is assumed to be a comma delimted list of IP addresses where
  214. // the client IP is the first IP address in the list. Meek protocols
  215. // look for these headers and use the client IP address from
  216. // the header if any one is present and the value is a valid
  217. // IP address; otherwise the direct connection remote address is
  218. // used as the client IP.
  219. MeekProxyForwardedForHeaders []string
  220. // MeekTurnAroundTimeoutMilliseconds specifies the amount of time meek will
  221. // wait for downstream bytes before responding to a request. The default is
  222. // MEEK_DEFAULT_TURN_AROUND_TIMEOUT.
  223. MeekTurnAroundTimeoutMilliseconds *int
  224. // MeekExtendedTurnAroundTimeoutMilliseconds specifies the extended amount of
  225. // time meek will wait for downstream bytes, as long as bytes arrive every
  226. // MeekTurnAroundTimeoutMilliseconds, before responding to a request. The
  227. // default is MEEK_DEFAULT_EXTENDED_TURN_AROUND_TIMEOUT.
  228. MeekExtendedTurnAroundTimeoutMilliseconds *int
  229. // MeekSkipExtendedTurnAroundThresholdBytes specifies when to skip the
  230. // extended turn around. When the number of bytes received in the client
  231. // request meets the threshold, optimize for upstream flows with quicker
  232. // round trip turn arounds.
  233. MeekSkipExtendedTurnAroundThresholdBytes *int
  234. // MeekMaxSessionStalenessMilliseconds specifies the TTL for meek sessions.
  235. // The default is MEEK_DEFAULT_MAX_SESSION_STALENESS.
  236. MeekMaxSessionStalenessMilliseconds *int
  237. // MeekHTTPClientIOTimeoutMilliseconds specifies meek HTTP server I/O
  238. // timeouts. The default is MEEK_DEFAULT_HTTP_CLIENT_IO_TIMEOUT.
  239. MeekHTTPClientIOTimeoutMilliseconds *int
  240. // MeekFrontedHTTPClientIOTimeoutMilliseconds specifies meek HTTP server
  241. // I/O timeouts for fronted protocols. The default is
  242. // MEEK_DEFAULT_FRONTED_HTTP_CLIENT_IO_TIMEOUT.
  243. MeekFrontedHTTPClientIOTimeoutMilliseconds *int
  244. // MeekCachedResponseBufferSize is the size of a private,
  245. // fixed-size buffer allocated for every meek client. The buffer
  246. // is used to cache response payload, allowing the client to retry
  247. // fetching when a network connection is interrupted. This retry
  248. // makes the OSSH tunnel within meek resilient to interruptions
  249. // at the HTTP TCP layer.
  250. // Larger buffers increase resiliency to interruption, but consume
  251. // more memory as buffers as never freed. The maximum size of a
  252. // response payload is a function of client activity, network
  253. // throughput and throttling.
  254. // A default of 64K is used when MeekCachedResponseBufferSize is 0.
  255. MeekCachedResponseBufferSize int
  256. // MeekCachedResponsePoolBufferSize is the size of a fixed-size,
  257. // shared buffer used to temporarily extend a private buffer when
  258. // MeekCachedResponseBufferSize is insufficient. Shared buffers
  259. // allow some clients to successfully retry longer response payloads
  260. // without allocating large buffers for all clients.
  261. // A default of 64K is used when MeekCachedResponsePoolBufferSize
  262. // is 0.
  263. MeekCachedResponsePoolBufferSize int
  264. // MeekCachedResponsePoolBufferCount is the number of shared
  265. // buffers. Shared buffers are allocated on first use and remain
  266. // allocated, so shared buffer count * size is roughly the memory
  267. // overhead of this facility.
  268. // A default of 2048 is used when MeekCachedResponsePoolBufferCount
  269. // is 0.
  270. MeekCachedResponsePoolBufferCount int
  271. // UDPInterceptUdpgwServerAddress specifies the network address of
  272. // a udpgw server which clients may be port forwarding to. When
  273. // specified, these TCP port forwards are intercepted and handled
  274. // directly by this server, which parses the SSH channel using the
  275. // udpgw protocol. Handling includes udpgw transparent DNS: tunneled
  276. // UDP DNS packets are rerouted to the host's DNS server.
  277. //
  278. // The intercept is applied before the port forward destination is
  279. // validated against SSH_DISALLOWED_PORT_FORWARD_HOSTS and
  280. // AllowTCPPorts. So the intercept address may be any otherwise
  281. // prohibited destination.
  282. UDPInterceptUdpgwServerAddress string
  283. // DNSResolverIPAddress specifies the IP address of a DNS server
  284. // to be used when "/etc/resolv.conf" doesn't exist or fails to
  285. // parse. When blank, "/etc/resolv.conf" must contain a usable
  286. // "nameserver" entry.
  287. DNSResolverIPAddress string
  288. // LoadMonitorPeriodSeconds indicates how frequently to log server
  289. // load information (number of connected clients per tunnel protocol,
  290. // number of running goroutines, amount of memory allocated, etc.)
  291. // The default, 0, disables load logging.
  292. LoadMonitorPeriodSeconds int
  293. // PeakUpstreamFailureRateMinimumSampleSize specifies the minimum number
  294. // of samples (e.g., upstream port forward attempts) that are required
  295. // before taking a failure rate snapshot which may be recorded as
  296. // peak_dns_failure_rate/peak_tcp_port_forward_failure_rate. The default
  297. // is PEAK_UPSTREAM_FAILURE_RATE_SAMPLE_SIZE.
  298. PeakUpstreamFailureRateMinimumSampleSize *int
  299. // ProcessProfileOutputDirectory is the path of a directory to which
  300. // process profiles will be written when signaled with SIGUSR2. The
  301. // files are overwritten on each invocation. When set to the default
  302. // value, blank, no profiles are written on SIGUSR2. Profiles include
  303. // the default profiles here: https://golang.org/pkg/runtime/pprof/#Profile.
  304. ProcessProfileOutputDirectory string
  305. // ProcessBlockProfileDurationSeconds specifies the sample duration for
  306. // "block" profiling. For the default, 0, no "block" profile is taken.
  307. ProcessBlockProfileDurationSeconds int
  308. // ProcessCPUProfileDurationSeconds specifies the sample duration for
  309. // CPU profiling. For the default, 0, no CPU profile is taken.
  310. ProcessCPUProfileDurationSeconds int
  311. // TrafficRulesFilename is the path of a file containing a JSON-encoded
  312. // TrafficRulesSet, the traffic rules to apply to Psiphon client tunnels.
  313. TrafficRulesFilename string
  314. // OSLConfigFilename is the path of a file containing a JSON-encoded
  315. // OSL Config, the OSL schemes to apply to Psiphon client tunnels.
  316. OSLConfigFilename string
  317. // RunPacketTunnel specifies whether to run a packet tunnel.
  318. RunPacketTunnel bool
  319. // PacketTunnelEgressInterface specifies tun.ServerConfig.EgressInterface.
  320. PacketTunnelEgressInterface string
  321. // PacketTunnelEnableDNSFlowTracking sets
  322. // tun.ServerConfig.EnableDNSFlowTracking.
  323. PacketTunnelEnableDNSFlowTracking bool
  324. // PacketTunnelDownstreamPacketQueueSize specifies
  325. // tun.ServerConfig.DownStreamPacketQueueSize.
  326. PacketTunnelDownstreamPacketQueueSize int
  327. // PacketTunnelSessionIdleExpirySeconds specifies
  328. // tun.ServerConfig.SessionIdleExpirySeconds.
  329. PacketTunnelSessionIdleExpirySeconds int
  330. // PacketTunnelSudoNetworkConfigCommands sets
  331. // tun.ServerConfig.SudoNetworkConfigCommands.
  332. PacketTunnelSudoNetworkConfigCommands bool
  333. // RunPacketManipulator specifies whether to run a packet manipulator.
  334. RunPacketManipulator bool
  335. // MaxConcurrentSSHHandshakes specifies a limit on the number of concurrent
  336. // SSH handshake negotiations. This is set to mitigate spikes in memory
  337. // allocations and CPU usage associated with SSH handshakes when many clients
  338. // attempt to connect concurrently. When a maximum limit is specified and
  339. // reached, additional clients that establish TCP or meek connections will
  340. // be disconnected after a short wait for the number of concurrent handshakes
  341. // to drop below the limit.
  342. // The default, 0 is no limit.
  343. MaxConcurrentSSHHandshakes int
  344. // PeriodicGarbageCollectionSeconds turns on periodic calls to
  345. // debug.FreeOSMemory, every specified number of seconds, to force garbage
  346. // collection and memory scavenging. Specify 0 to disable. The default is
  347. // PERIODIC_GARBAGE_COLLECTION.
  348. PeriodicGarbageCollectionSeconds *int
  349. // StopEstablishTunnelsEstablishedClientThreshold sets the established client
  350. // threshold for dumping profiles when SIGTSTP is signaled. When there are
  351. // less than or equal to the threshold number of established clients,
  352. // profiles are dumped to aid investigating unusual load limited states that
  353. // occur when few clients are connected and load should be relatively low. A
  354. // profile dump is attempted at most once per process lifetime, the first
  355. // time the threshold is met. Disabled when < 0.
  356. StopEstablishTunnelsEstablishedClientThreshold *int
  357. // AccessControlVerificationKeyRing is the access control authorization
  358. // verification key ring used to verify signed authorizations presented
  359. // by clients. Verified, active (unexpired) access control types will be
  360. // available for matching in the TrafficRulesFilter for the client via
  361. // AuthorizedAccessTypes. All other authorizations are ignored.
  362. AccessControlVerificationKeyRing accesscontrol.VerificationKeyRing
  363. // TacticsConfigFilename is the path of a file containing a JSON-encoded
  364. // tactics server configuration.
  365. TacticsConfigFilename string
  366. // BlocklistFilename is the path of a file containing a CSV-encoded
  367. // blocklist configuration. See NewBlocklist for more file format
  368. // documentation.
  369. BlocklistFilename string
  370. // BlocklistActive indicates whether to actively prevent blocklist hits in
  371. // addition to logging events.
  372. BlocklistActive bool
  373. // AllowBogons disables port forward bogon checks. This should be used only
  374. // for testing.
  375. AllowBogons bool
  376. // EnableSteeringIPs enables meek server steering IP support.
  377. EnableSteeringIPs bool
  378. // OwnEncodedServerEntries is a list of the server's own encoded server
  379. // entries, idenfified by server entry tag. These values are used in the
  380. // handshake API to update clients that don't yet have a signed copy of these
  381. // server entries.
  382. //
  383. // For purposes of compartmentalization, each server receives only its own
  384. // server entries here; and, besides the discovery server entries, in
  385. // psinet.Database, necessary for the discovery feature, no other server
  386. // entries are stored on a Psiphon server.
  387. OwnEncodedServerEntries map[string]string
  388. sshBeginHandshakeTimeout time.Duration
  389. sshHandshakeTimeout time.Duration
  390. peakUpstreamFailureRateMinimumSampleSize int
  391. periodicGarbageCollection time.Duration
  392. stopEstablishTunnelsEstablishedClientThreshold int
  393. dumpProfilesOnStopEstablishTunnelsDone int32
  394. providerID string
  395. frontingProviderID string
  396. region string
  397. runningProtocols []string
  398. }
  399. // GetLogFileReopenConfig gets the reopen retries, and create/mode inputs for
  400. // rotate.NewRotatableFileWriter, which is used when writing to log files.
  401. //
  402. // By default, we expect the log files to be managed by logrotate, with
  403. // logrotate configured to re-create the next log file after rotation. As
  404. // described in the documentation for rotate.NewRotatableFileWriter, and as
  405. // observed in production, we occasionally need retries when attempting to
  406. // reopen the log file post-rotation; and we avoid conflicts, and spurious
  407. // re-rotations, by disabling file create in rotate.NewRotatableFileWriter. In
  408. // large scale production, incidents requiring retry are very rare, so the
  409. // retry delay is not expected to have a significant impact on performance.
  410. //
  411. // The defaults may be overriden in the Config.
  412. func (config *Config) GetLogFileReopenConfig() (int, bool, os.FileMode) {
  413. retries := DEFAULT_LOG_FILE_REOPEN_RETRIES
  414. if config.LogFileReopenRetries != nil {
  415. retries = *config.LogFileReopenRetries
  416. }
  417. create := false
  418. mode := os.FileMode(0)
  419. if config.LogFileCreateMode != nil {
  420. create = true
  421. mode = os.FileMode(*config.LogFileCreateMode)
  422. }
  423. return retries, create, mode
  424. }
  425. // RunWebServer indicates whether to run a web server component.
  426. func (config *Config) RunWebServer() bool {
  427. return config.WebServerPort > 0
  428. }
  429. // RunLoadMonitor indicates whether to monitor and log server load.
  430. func (config *Config) RunLoadMonitor() bool {
  431. return config.LoadMonitorPeriodSeconds > 0
  432. }
  433. // RunPeriodicGarbageCollection indicates whether to run periodic garbage collection.
  434. func (config *Config) RunPeriodicGarbageCollection() bool {
  435. return config.periodicGarbageCollection > 0
  436. }
  437. // DumpProfilesOnStopEstablishTunnels indicates whether dump profiles due to
  438. // an unexpectedly low number of established clients during high load.
  439. func (config *Config) DumpProfilesOnStopEstablishTunnels(establishedClientsCount int) bool {
  440. if config.stopEstablishTunnelsEstablishedClientThreshold < 0 {
  441. return false
  442. }
  443. if atomic.LoadInt32(&config.dumpProfilesOnStopEstablishTunnelsDone) != 0 {
  444. return false
  445. }
  446. dump := (establishedClientsCount <= config.stopEstablishTunnelsEstablishedClientThreshold)
  447. atomic.StoreInt32(&config.dumpProfilesOnStopEstablishTunnelsDone, 1)
  448. return dump
  449. }
  450. // GetOwnEncodedServerEntry returns one of the server's own server entries, as
  451. // identified by the server entry tag.
  452. func (config *Config) GetOwnEncodedServerEntry(serverEntryTag string) (string, bool) {
  453. serverEntry, ok := config.OwnEncodedServerEntries[serverEntryTag]
  454. return serverEntry, ok
  455. }
  456. // GetProviderID returns the provider ID associated with the server.
  457. func (config *Config) GetProviderID() string {
  458. return config.providerID
  459. }
  460. // GetFrontingProviderID returns the fronting provider ID associated with the
  461. // server's fronted protocol(s).
  462. func (config *Config) GetFrontingProviderID() string {
  463. return config.frontingProviderID
  464. }
  465. // GetRegion returns the region associated with the server.
  466. func (config *Config) GetRegion() string {
  467. return config.region
  468. }
  469. // GetRunningProtocols returns the list of protcols this server is running.
  470. // The caller must not mutate the return value.
  471. func (config *Config) GetRunningProtocols() []string {
  472. return config.runningProtocols
  473. }
  474. // LoadConfig loads and validates a JSON encoded server config.
  475. func LoadConfig(configJSON []byte) (*Config, error) {
  476. var config Config
  477. err := json.Unmarshal(configJSON, &config)
  478. if err != nil {
  479. return nil, errors.Trace(err)
  480. }
  481. if config.ServerIPAddress == "" {
  482. return nil, errors.TraceNew("ServerIPAddress is required")
  483. }
  484. if config.WebServerPort > 0 && (config.WebServerSecret == "" || config.WebServerCertificate == "" ||
  485. config.WebServerPrivateKey == "") {
  486. return nil, errors.TraceNew(
  487. "Web server requires WebServerSecret, WebServerCertificate, WebServerPrivateKey")
  488. }
  489. if config.WebServerPortForwardAddress != "" {
  490. if err := validateNetworkAddress(config.WebServerPortForwardAddress, false); err != nil {
  491. return nil, errors.TraceNew("WebServerPortForwardAddress is invalid")
  492. }
  493. }
  494. if config.WebServerPortForwardRedirectAddress != "" {
  495. if config.WebServerPortForwardAddress == "" {
  496. return nil, errors.TraceNew(
  497. "WebServerPortForwardRedirectAddress requires WebServerPortForwardAddress")
  498. }
  499. if err := validateNetworkAddress(config.WebServerPortForwardRedirectAddress, false); err != nil {
  500. return nil, errors.TraceNew("WebServerPortForwardRedirectAddress is invalid")
  501. }
  502. }
  503. for tunnelProtocol, _ := range config.TunnelProtocolPorts {
  504. if !common.Contains(protocol.SupportedTunnelProtocols, tunnelProtocol) {
  505. return nil, errors.Tracef("Unsupported tunnel protocol: %s", tunnelProtocol)
  506. }
  507. if protocol.TunnelProtocolUsesSSH(tunnelProtocol) ||
  508. protocol.TunnelProtocolUsesObfuscatedSSH(tunnelProtocol) {
  509. if config.SSHPrivateKey == "" || config.SSHServerVersion == "" ||
  510. config.SSHUserName == "" || config.SSHPassword == "" {
  511. return nil, errors.Tracef(
  512. "Tunnel protocol %s requires SSHPrivateKey, SSHServerVersion, SSHUserName, SSHPassword",
  513. tunnelProtocol)
  514. }
  515. }
  516. if protocol.TunnelProtocolUsesObfuscatedSSH(tunnelProtocol) {
  517. if config.ObfuscatedSSHKey == "" {
  518. return nil, errors.Tracef(
  519. "Tunnel protocol %s requires ObfuscatedSSHKey",
  520. tunnelProtocol)
  521. }
  522. }
  523. if protocol.TunnelProtocolUsesTLSOSSH(tunnelProtocol) {
  524. // Meek obfuscated key used for legacy reasons. See comment for
  525. // MeekObfuscatedKey.
  526. if config.MeekObfuscatedKey == "" {
  527. return nil, errors.Tracef(
  528. "Tunnel protocol %s requires MeekObfuscatedKey",
  529. tunnelProtocol)
  530. }
  531. }
  532. if protocol.TunnelProtocolUsesMeekHTTP(tunnelProtocol) ||
  533. protocol.TunnelProtocolUsesMeekHTTPS(tunnelProtocol) {
  534. if config.MeekCookieEncryptionPrivateKey == "" || config.MeekObfuscatedKey == "" {
  535. return nil, errors.Tracef(
  536. "Tunnel protocol %s requires MeekCookieEncryptionPrivateKey, MeekObfuscatedKey",
  537. tunnelProtocol)
  538. }
  539. }
  540. // For FRONTED QUIC and HTTP, HTTPS is always used on the
  541. // edge-to-server hop, so it must be enabled or else this
  542. // configuration will not work. There is no FRONTED QUIC listener at
  543. // all; see TunnelServer.Run.
  544. if protocol.TunnelProtocolUsesFrontedMeek(tunnelProtocol) {
  545. _, ok := config.TunnelProtocolPorts[protocol.TUNNEL_PROTOCOL_FRONTED_MEEK]
  546. if !ok {
  547. return nil, errors.Tracef(
  548. "Tunnel protocol %s requires %s to be enabled",
  549. tunnelProtocol,
  550. protocol.TUNNEL_PROTOCOL_FRONTED_MEEK)
  551. }
  552. }
  553. }
  554. for tunnelProtocol, address := range config.TunnelProtocolPassthroughAddresses {
  555. if !protocol.TunnelProtocolSupportsPassthrough(tunnelProtocol) {
  556. return nil, errors.Tracef("Passthrough unsupported tunnel protocol: %s", tunnelProtocol)
  557. }
  558. if _, _, err := net.SplitHostPort(address); err != nil {
  559. if err != nil {
  560. return nil, errors.Tracef(
  561. "Tunnel protocol %s passthrough address %s invalid: %s",
  562. tunnelProtocol, address, err)
  563. }
  564. }
  565. }
  566. config.sshBeginHandshakeTimeout = SSH_BEGIN_HANDSHAKE_TIMEOUT
  567. if config.SSHBeginHandshakeTimeoutMilliseconds != nil {
  568. config.sshBeginHandshakeTimeout = time.Duration(*config.SSHBeginHandshakeTimeoutMilliseconds) * time.Millisecond
  569. }
  570. config.sshHandshakeTimeout = SSH_HANDSHAKE_TIMEOUT
  571. if config.SSHHandshakeTimeoutMilliseconds != nil {
  572. config.sshHandshakeTimeout = time.Duration(*config.SSHHandshakeTimeoutMilliseconds) * time.Millisecond
  573. }
  574. if config.ObfuscatedSSHKey != "" {
  575. seed, err := protocol.DeriveSSHServerVersionPRNGSeed(config.ObfuscatedSSHKey)
  576. if err != nil {
  577. return nil, errors.Tracef(
  578. "DeriveSSHServerVersionPRNGSeed failed: %s", err)
  579. }
  580. serverVersion := values.GetSSHServerVersion(seed)
  581. if serverVersion != "" {
  582. config.SSHServerVersion = serverVersion
  583. }
  584. }
  585. if config.UDPInterceptUdpgwServerAddress != "" {
  586. if err := validateNetworkAddress(config.UDPInterceptUdpgwServerAddress, true); err != nil {
  587. return nil, errors.Tracef("UDPInterceptUdpgwServerAddress is invalid: %s", err)
  588. }
  589. }
  590. if config.DNSResolverIPAddress != "" {
  591. if net.ParseIP(config.DNSResolverIPAddress) == nil {
  592. return nil, errors.Tracef("DNSResolverIPAddress is invalid")
  593. }
  594. }
  595. config.peakUpstreamFailureRateMinimumSampleSize = PEAK_UPSTREAM_FAILURE_RATE_MINIMUM_SAMPLE_SIZE
  596. if config.PeakUpstreamFailureRateMinimumSampleSize != nil {
  597. config.peakUpstreamFailureRateMinimumSampleSize = *config.PeakUpstreamFailureRateMinimumSampleSize
  598. }
  599. config.periodicGarbageCollection = PERIODIC_GARBAGE_COLLECTION
  600. if config.PeriodicGarbageCollectionSeconds != nil {
  601. config.periodicGarbageCollection = time.Duration(*config.PeriodicGarbageCollectionSeconds) * time.Second
  602. }
  603. config.stopEstablishTunnelsEstablishedClientThreshold = STOP_ESTABLISH_TUNNELS_ESTABLISHED_CLIENT_THRESHOLD
  604. if config.StopEstablishTunnelsEstablishedClientThreshold != nil {
  605. config.stopEstablishTunnelsEstablishedClientThreshold = *config.StopEstablishTunnelsEstablishedClientThreshold
  606. }
  607. err = accesscontrol.ValidateVerificationKeyRing(&config.AccessControlVerificationKeyRing)
  608. if err != nil {
  609. return nil, errors.Tracef(
  610. "AccessControlVerificationKeyRing is invalid: %s", err)
  611. }
  612. // Limitation: the following is a shortcut which extracts the server's
  613. // fronting provider ID from the server's OwnEncodedServerEntries. This logic
  614. // assumes a server has only one fronting provider. In principle, it's
  615. // possible for server with multiple server entries to run multiple fronted
  616. // protocols, each with a different fronting provider ID.
  617. //
  618. // TODO: add an explicit parameter mapping tunnel protocol ports to fronting
  619. // provider IDs.
  620. for _, encodedServerEntry := range config.OwnEncodedServerEntries {
  621. serverEntry, err := protocol.DecodeServerEntry(encodedServerEntry, "", "")
  622. if err != nil {
  623. return nil, errors.Tracef(
  624. "protocol.DecodeServerEntry failed: %s", err)
  625. }
  626. if config.providerID == "" {
  627. config.providerID = serverEntry.ProviderID
  628. } else if config.providerID != serverEntry.ProviderID {
  629. return nil, errors.Tracef("unsupported multiple ProviderID values")
  630. }
  631. if config.frontingProviderID == "" {
  632. config.frontingProviderID = serverEntry.FrontingProviderID
  633. } else if config.frontingProviderID != serverEntry.FrontingProviderID {
  634. return nil, errors.Tracef("unsupported multiple FrontingProviderID values")
  635. }
  636. if config.region == "" {
  637. config.region = serverEntry.Region
  638. } else if config.region != serverEntry.Region {
  639. return nil, errors.Tracef("unsupported multiple Region values")
  640. }
  641. }
  642. config.runningProtocols = []string{}
  643. for tunnelProtocol := range config.TunnelProtocolPorts {
  644. config.runningProtocols = append(config.runningProtocols, tunnelProtocol)
  645. }
  646. return &config, nil
  647. }
  648. func validateNetworkAddress(address string, requireIPaddress bool) error {
  649. host, portStr, err := net.SplitHostPort(address)
  650. if err != nil {
  651. return err
  652. }
  653. if requireIPaddress && net.ParseIP(host) == nil {
  654. return errors.TraceNew("host must be an IP address")
  655. }
  656. port, err := strconv.Atoi(portStr)
  657. if err != nil {
  658. return err
  659. }
  660. if port < 0 || port > 65535 {
  661. return errors.TraceNew("invalid port")
  662. }
  663. return nil
  664. }
  665. // GenerateConfigParams specifies customizations to be applied to
  666. // a generated server config.
  667. type GenerateConfigParams struct {
  668. LogFilename string
  669. SkipPanickingLogWriter bool
  670. LogLevel string
  671. ServerIPAddress string
  672. WebServerPort int
  673. EnableSSHAPIRequests bool
  674. TunnelProtocolPorts map[string]int
  675. TunnelProtocolPassthroughAddresses map[string]string
  676. TrafficRulesConfigFilename string
  677. OSLConfigFilename string
  678. TacticsConfigFilename string
  679. TacticsRequestPublicKey string
  680. TacticsRequestObfuscatedKey string
  681. Passthrough bool
  682. LegacyPassthrough bool
  683. LimitQUICVersions protocol.QUICVersions
  684. EnableGQUIC bool
  685. FrontingProviderID string
  686. }
  687. // GenerateConfig creates a new Psiphon server config. It returns JSON encoded
  688. // configs and a client-compatible "server entry" for the server. It generates
  689. // all necessary secrets and key material, which are emitted in the config
  690. // file and server entry as necessary.
  691. //
  692. // GenerateConfig uses sample values for many fields. The intention is for
  693. // generated configs to be used for testing or as examples for production
  694. // setup, not to generate production-ready configurations.
  695. //
  696. // When tactics key material is provided in GenerateConfigParams, tactics
  697. // capabilities are added for all meek protocols in TunnelProtocolPorts.
  698. func GenerateConfig(params *GenerateConfigParams) ([]byte, []byte, []byte, []byte, []byte, error) {
  699. // Input validation
  700. if net.ParseIP(params.ServerIPAddress) == nil {
  701. return nil, nil, nil, nil, nil, errors.TraceNew("invalid IP address")
  702. }
  703. if len(params.TunnelProtocolPorts) == 0 {
  704. return nil, nil, nil, nil, nil, errors.TraceNew("no tunnel protocols")
  705. }
  706. usedPort := make(map[int]bool)
  707. if params.WebServerPort != 0 {
  708. usedPort[params.WebServerPort] = true
  709. }
  710. usingMeek := false
  711. usingTLSOSSH := false
  712. for tunnelProtocol, port := range params.TunnelProtocolPorts {
  713. if !common.Contains(protocol.SupportedTunnelProtocols, tunnelProtocol) {
  714. return nil, nil, nil, nil, nil, errors.TraceNew("invalid tunnel protocol")
  715. }
  716. if usedPort[port] {
  717. return nil, nil, nil, nil, nil, errors.TraceNew("duplicate listening port")
  718. }
  719. usedPort[port] = true
  720. if protocol.TunnelProtocolUsesTLSOSSH(tunnelProtocol) {
  721. usingTLSOSSH = true
  722. }
  723. if protocol.TunnelProtocolUsesMeekHTTP(tunnelProtocol) ||
  724. protocol.TunnelProtocolUsesMeekHTTPS(tunnelProtocol) {
  725. usingMeek = true
  726. }
  727. }
  728. // One test mode populates the tactics config file; this will generate
  729. // keys. Another test mode passes in existing keys to be used in the
  730. // server entry. Both the filename and existing keys cannot be passed in.
  731. if (params.TacticsConfigFilename != "") &&
  732. (params.TacticsRequestPublicKey != "" || params.TacticsRequestObfuscatedKey != "") {
  733. return nil, nil, nil, nil, nil, errors.TraceNew("invalid tactics parameters")
  734. }
  735. // Web server config
  736. var webServerSecret, webServerCertificate,
  737. webServerPrivateKey, webServerPortForwardAddress string
  738. if params.WebServerPort != 0 {
  739. webServerSecretBytes, err := common.MakeSecureRandomBytes(WEB_SERVER_SECRET_BYTE_LENGTH)
  740. if err != nil {
  741. return nil, nil, nil, nil, nil, errors.Trace(err)
  742. }
  743. webServerSecret = hex.EncodeToString(webServerSecretBytes)
  744. webServerCertificate, webServerPrivateKey, err = common.GenerateWebServerCertificate("")
  745. if err != nil {
  746. return nil, nil, nil, nil, nil, errors.Trace(err)
  747. }
  748. webServerPortForwardAddress = net.JoinHostPort(
  749. params.ServerIPAddress, strconv.Itoa(params.WebServerPort))
  750. }
  751. // SSH config
  752. rsaKey, err := rsa.GenerateKey(rand.Reader, SSH_RSA_HOST_KEY_BITS)
  753. if err != nil {
  754. return nil, nil, nil, nil, nil, errors.Trace(err)
  755. }
  756. sshPrivateKey := pem.EncodeToMemory(
  757. &pem.Block{
  758. Type: "RSA PRIVATE KEY",
  759. Bytes: x509.MarshalPKCS1PrivateKey(rsaKey),
  760. },
  761. )
  762. signer, err := ssh.NewSignerFromKey(rsaKey)
  763. if err != nil {
  764. return nil, nil, nil, nil, nil, errors.Trace(err)
  765. }
  766. sshPublicKey := signer.PublicKey()
  767. sshUserNameSuffixBytes, err := common.MakeSecureRandomBytes(SSH_USERNAME_SUFFIX_BYTE_LENGTH)
  768. if err != nil {
  769. return nil, nil, nil, nil, nil, errors.Trace(err)
  770. }
  771. sshUserNameSuffix := hex.EncodeToString(sshUserNameSuffixBytes)
  772. sshUserName := "psiphon_" + sshUserNameSuffix
  773. sshPasswordBytes, err := common.MakeSecureRandomBytes(SSH_PASSWORD_BYTE_LENGTH)
  774. if err != nil {
  775. return nil, nil, nil, nil, nil, errors.Trace(err)
  776. }
  777. sshPassword := hex.EncodeToString(sshPasswordBytes)
  778. sshServerVersion := "SSH-2.0-Psiphon"
  779. // Obfuscated SSH config
  780. obfuscatedSSHKeyBytes, err := common.MakeSecureRandomBytes(SSH_OBFUSCATED_KEY_BYTE_LENGTH)
  781. if err != nil {
  782. return nil, nil, nil, nil, nil, errors.Trace(err)
  783. }
  784. obfuscatedSSHKey := hex.EncodeToString(obfuscatedSSHKeyBytes)
  785. // Meek config
  786. var meekCookieEncryptionPublicKey, meekCookieEncryptionPrivateKey, meekObfuscatedKey string
  787. if usingMeek {
  788. rawMeekCookieEncryptionPublicKey, rawMeekCookieEncryptionPrivateKey, err :=
  789. box.GenerateKey(rand.Reader)
  790. if err != nil {
  791. return nil, nil, nil, nil, nil, errors.Trace(err)
  792. }
  793. meekCookieEncryptionPublicKey = base64.StdEncoding.EncodeToString(rawMeekCookieEncryptionPublicKey[:])
  794. meekCookieEncryptionPrivateKey = base64.StdEncoding.EncodeToString(rawMeekCookieEncryptionPrivateKey[:])
  795. }
  796. if usingMeek || usingTLSOSSH {
  797. meekObfuscatedKeyBytes, err := common.MakeSecureRandomBytes(SSH_OBFUSCATED_KEY_BYTE_LENGTH)
  798. if err != nil {
  799. return nil, nil, nil, nil, nil, errors.Trace(err)
  800. }
  801. meekObfuscatedKey = hex.EncodeToString(meekObfuscatedKeyBytes)
  802. }
  803. // Other config
  804. discoveryValueHMACKeyBytes, err := common.MakeSecureRandomBytes(DISCOVERY_VALUE_KEY_BYTE_LENGTH)
  805. if err != nil {
  806. return nil, nil, nil, nil, nil, errors.Trace(err)
  807. }
  808. discoveryValueHMACKey := base64.StdEncoding.EncodeToString(discoveryValueHMACKeyBytes)
  809. // Assemble configs and server entry
  810. // Note: this config is intended for either testing or as an illustrative
  811. // example or template and is not intended for production deployment.
  812. logLevel := params.LogLevel
  813. if logLevel == "" {
  814. logLevel = "info"
  815. }
  816. // For testing, set the Psiphon server to create its log files; we do not
  817. // expect tests to necessarily run under log managers, such as logrotate.
  818. createMode := 0666
  819. config := &Config{
  820. LogLevel: logLevel,
  821. LogFilename: params.LogFilename,
  822. LogFileCreateMode: &createMode,
  823. SkipPanickingLogWriter: params.SkipPanickingLogWriter,
  824. GeoIPDatabaseFilenames: nil,
  825. HostID: "example-host-id",
  826. ServerIPAddress: params.ServerIPAddress,
  827. DiscoveryValueHMACKey: discoveryValueHMACKey,
  828. WebServerPort: params.WebServerPort,
  829. WebServerSecret: webServerSecret,
  830. WebServerCertificate: webServerCertificate,
  831. WebServerPrivateKey: webServerPrivateKey,
  832. WebServerPortForwardAddress: webServerPortForwardAddress,
  833. SSHPrivateKey: string(sshPrivateKey),
  834. SSHServerVersion: sshServerVersion,
  835. SSHUserName: sshUserName,
  836. SSHPassword: sshPassword,
  837. ObfuscatedSSHKey: obfuscatedSSHKey,
  838. TunnelProtocolPorts: params.TunnelProtocolPorts,
  839. TunnelProtocolPassthroughAddresses: params.TunnelProtocolPassthroughAddresses,
  840. DNSResolverIPAddress: "8.8.8.8",
  841. UDPInterceptUdpgwServerAddress: "127.0.0.1:7300",
  842. MeekCookieEncryptionPrivateKey: meekCookieEncryptionPrivateKey,
  843. MeekObfuscatedKey: meekObfuscatedKey,
  844. MeekProhibitedHeaders: nil,
  845. MeekProxyForwardedForHeaders: []string{"X-Forwarded-For"},
  846. LoadMonitorPeriodSeconds: 300,
  847. TrafficRulesFilename: params.TrafficRulesConfigFilename,
  848. OSLConfigFilename: params.OSLConfigFilename,
  849. TacticsConfigFilename: params.TacticsConfigFilename,
  850. LegacyPassthrough: params.LegacyPassthrough,
  851. EnableGQUIC: params.EnableGQUIC,
  852. }
  853. encodedConfig, err := json.MarshalIndent(config, "\n", " ")
  854. if err != nil {
  855. return nil, nil, nil, nil, nil, errors.Trace(err)
  856. }
  857. intPtr := func(i int) *int {
  858. return &i
  859. }
  860. trafficRulesSet := &TrafficRulesSet{
  861. DefaultRules: TrafficRules{
  862. RateLimits: RateLimits{
  863. ReadUnthrottledBytes: new(int64),
  864. ReadBytesPerSecond: new(int64),
  865. WriteUnthrottledBytes: new(int64),
  866. WriteBytesPerSecond: new(int64),
  867. },
  868. IdleTCPPortForwardTimeoutMilliseconds: intPtr(DEFAULT_IDLE_TCP_PORT_FORWARD_TIMEOUT_MILLISECONDS),
  869. IdleUDPPortForwardTimeoutMilliseconds: intPtr(DEFAULT_IDLE_UDP_PORT_FORWARD_TIMEOUT_MILLISECONDS),
  870. MaxTCPPortForwardCount: intPtr(DEFAULT_MAX_TCP_PORT_FORWARD_COUNT),
  871. MaxUDPPortForwardCount: intPtr(DEFAULT_MAX_UDP_PORT_FORWARD_COUNT),
  872. AllowTCPPorts: nil,
  873. AllowUDPPorts: nil,
  874. },
  875. }
  876. encodedTrafficRulesSet, err := json.MarshalIndent(trafficRulesSet, "\n", " ")
  877. if err != nil {
  878. return nil, nil, nil, nil, nil, errors.Trace(err)
  879. }
  880. encodedOSLConfig, err := json.MarshalIndent(&osl.Config{}, "\n", " ")
  881. if err != nil {
  882. return nil, nil, nil, nil, nil, errors.Trace(err)
  883. }
  884. tacticsRequestPublicKey := params.TacticsRequestPublicKey
  885. tacticsRequestObfuscatedKey := params.TacticsRequestObfuscatedKey
  886. var tacticsRequestPrivateKey string
  887. var encodedTacticsConfig []byte
  888. if params.TacticsConfigFilename != "" {
  889. tacticsRequestPublicKey, tacticsRequestPrivateKey, tacticsRequestObfuscatedKey, err =
  890. tactics.GenerateKeys()
  891. if err != nil {
  892. return nil, nil, nil, nil, nil, errors.Trace(err)
  893. }
  894. decodedTacticsRequestPublicKey, err := base64.StdEncoding.DecodeString(tacticsRequestPublicKey)
  895. if err != nil {
  896. return nil, nil, nil, nil, nil, errors.Trace(err)
  897. }
  898. decodedTacticsRequestPrivateKey, err := base64.StdEncoding.DecodeString(tacticsRequestPrivateKey)
  899. if err != nil {
  900. return nil, nil, nil, nil, nil, errors.Trace(err)
  901. }
  902. decodedTacticsRequestObfuscatedKey, err := base64.StdEncoding.DecodeString(tacticsRequestObfuscatedKey)
  903. if err != nil {
  904. return nil, nil, nil, nil, nil, errors.Trace(err)
  905. }
  906. tacticsConfig := &tactics.Server{
  907. RequestPublicKey: decodedTacticsRequestPublicKey,
  908. RequestPrivateKey: decodedTacticsRequestPrivateKey,
  909. RequestObfuscatedKey: decodedTacticsRequestObfuscatedKey,
  910. DefaultTactics: tactics.Tactics{
  911. TTL: "1m",
  912. Probability: 1.0,
  913. },
  914. }
  915. encodedTacticsConfig, err = json.MarshalIndent(tacticsConfig, "\n", " ")
  916. if err != nil {
  917. return nil, nil, nil, nil, nil, errors.Trace(err)
  918. }
  919. }
  920. capabilities := []string{}
  921. if params.EnableSSHAPIRequests {
  922. capabilities = append(capabilities, protocol.CAPABILITY_SSH_API_REQUESTS)
  923. }
  924. if params.WebServerPort != 0 {
  925. capabilities = append(capabilities, protocol.CAPABILITY_UNTUNNELED_WEB_API_REQUESTS)
  926. }
  927. var frontingProviderID string
  928. for tunnelProtocol := range params.TunnelProtocolPorts {
  929. capability := protocol.GetCapability(tunnelProtocol)
  930. // Note: do not add passthrough annotation if HTTP unfronted meek
  931. // because it would result in an invalid capability.
  932. if params.Passthrough && protocol.TunnelProtocolSupportsPassthrough(tunnelProtocol) && tunnelProtocol != protocol.TUNNEL_PROTOCOL_UNFRONTED_MEEK {
  933. if !params.LegacyPassthrough {
  934. capability += "-PASSTHROUGH-v2"
  935. } else {
  936. capability += "-PASSTHROUGH"
  937. }
  938. }
  939. if tunnelProtocol == protocol.TUNNEL_PROTOCOL_QUIC_OBFUSCATED_SSH && !params.EnableGQUIC {
  940. capability += "v1"
  941. }
  942. capabilities = append(capabilities, capability)
  943. if params.TacticsRequestPublicKey != "" && params.TacticsRequestObfuscatedKey != "" &&
  944. protocol.TunnelProtocolUsesMeek(tunnelProtocol) {
  945. capabilities = append(capabilities, protocol.GetTacticsCapability(tunnelProtocol))
  946. }
  947. if protocol.TunnelProtocolUsesFrontedMeek(tunnelProtocol) {
  948. frontingProviderID = params.FrontingProviderID
  949. }
  950. }
  951. sshPort := params.TunnelProtocolPorts[protocol.TUNNEL_PROTOCOL_SSH]
  952. obfuscatedSSHPort := params.TunnelProtocolPorts[protocol.TUNNEL_PROTOCOL_OBFUSCATED_SSH]
  953. obfuscatedSSHQUICPort := params.TunnelProtocolPorts[protocol.TUNNEL_PROTOCOL_QUIC_OBFUSCATED_SSH]
  954. tlsOSSHPort := params.TunnelProtocolPorts[protocol.TUNNEL_PROTOCOL_TLS_OBFUSCATED_SSH]
  955. // Meek port limitations
  956. // - fronted meek protocols are hard-wired in the client to be port 443 or 80.
  957. // - only one other meek port may be specified.
  958. meekPort := params.TunnelProtocolPorts[protocol.TUNNEL_PROTOCOL_UNFRONTED_MEEK]
  959. if meekPort == 0 {
  960. meekPort = params.TunnelProtocolPorts[protocol.TUNNEL_PROTOCOL_UNFRONTED_MEEK_HTTPS]
  961. }
  962. if meekPort == 0 {
  963. meekPort = params.TunnelProtocolPorts[protocol.TUNNEL_PROTOCOL_UNFRONTED_MEEK_SESSION_TICKET]
  964. }
  965. // Note: fronting params are a stub; this server entry will exercise
  966. // client and server fronting code paths, but not actually traverse
  967. // a fronting hop.
  968. serverEntryWebServerPort := ""
  969. strippedWebServerCertificate := ""
  970. if params.WebServerPort != 0 {
  971. serverEntryWebServerPort = fmt.Sprintf("%d", params.WebServerPort)
  972. // Server entry format omits the BEGIN/END lines and newlines
  973. lines := strings.Split(webServerCertificate, "\n")
  974. strippedWebServerCertificate = strings.Join(lines[1:len(lines)-2], "")
  975. }
  976. serverEntry := &protocol.ServerEntry{
  977. IpAddress: params.ServerIPAddress,
  978. WebServerPort: serverEntryWebServerPort,
  979. WebServerSecret: webServerSecret,
  980. WebServerCertificate: strippedWebServerCertificate,
  981. TlsOSSHPort: tlsOSSHPort,
  982. SshPort: sshPort,
  983. SshUsername: sshUserName,
  984. SshPassword: sshPassword,
  985. SshHostKey: base64.RawStdEncoding.EncodeToString(sshPublicKey.Marshal()),
  986. SshObfuscatedPort: obfuscatedSSHPort,
  987. SshObfuscatedQUICPort: obfuscatedSSHQUICPort,
  988. LimitQUICVersions: params.LimitQUICVersions,
  989. SshObfuscatedKey: obfuscatedSSHKey,
  990. Capabilities: capabilities,
  991. Region: "US",
  992. ProviderID: prng.HexString(8),
  993. FrontingProviderID: frontingProviderID,
  994. MeekServerPort: meekPort,
  995. MeekCookieEncryptionPublicKey: meekCookieEncryptionPublicKey,
  996. MeekObfuscatedKey: meekObfuscatedKey,
  997. MeekFrontingHosts: []string{params.ServerIPAddress},
  998. MeekFrontingAddresses: []string{params.ServerIPAddress},
  999. MeekFrontingDisableSNI: false,
  1000. TacticsRequestPublicKey: tacticsRequestPublicKey,
  1001. TacticsRequestObfuscatedKey: tacticsRequestObfuscatedKey,
  1002. ConfigurationVersion: 1,
  1003. }
  1004. encodedServerEntry, err := protocol.EncodeServerEntry(serverEntry)
  1005. if err != nil {
  1006. return nil, nil, nil, nil, nil, errors.Trace(err)
  1007. }
  1008. return encodedConfig, encodedTrafficRulesSet, encodedOSLConfig, encodedTacticsConfig, []byte(encodedServerEntry), nil
  1009. }