/
config.go
executable file
·2846 lines (2338 loc) · 108 KB
/
config.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*
* Copyright (c) 2015, Psiphon Inc.
* All rights reserved.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package psiphon
import (
"crypto/md5"
"encoding/base64"
"encoding/binary"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"os"
"path/filepath"
"reflect"
"regexp"
"strconv"
"strings"
"sync"
"unicode"
"github.com/astaguna/popon-core/psiphon/common"
"github.com/astaguna/popon-core/psiphon/common/errors"
"github.com/astaguna/popon-core/psiphon/common/parameters"
"github.com/astaguna/popon-core/psiphon/common/protocol"
"github.com/astaguna/popon-core/psiphon/common/resolver"
"github.com/astaguna/popon-core/psiphon/common/transforms"
"golang.org/x/crypto/nacl/secretbox"
)
const (
TUNNEL_POOL_SIZE = 1
MAX_TUNNEL_POOL_SIZE = 32
// Psiphon data directory name, relative to config.DataRootDirectory.
// See config.GetPsiphonDataDirectory().
PsiphonDataDirectoryName = "ca.psiphon.PsiphonTunnel.tunnel-core"
// Filename constants, all relative to config.GetPsiphonDataDirectory().
HomepageFilename = "homepage"
NoticesFilename = "notices"
OldNoticesFilename = "notices.1"
UpgradeDownloadFilename = "upgrade"
)
// Config is the Psiphon configuration specified by the application. This
// configuration controls the behavior of the core tunnel functionality.
//
// To distinguish omitted timeout params from explicit 0 value timeout params,
// corresponding fields are int pointers. nil means no value was supplied and
// to use the default; a non-nil pointer to 0 means no timeout.
type Config struct {
// DataRootDirectory is the directory in which to store persistent files,
// which contain information such as server entries. By default, current
// working directory.
//
// Psiphon will assume full control of files under this directory. They may
// be deleted, moved or overwritten.
DataRootDirectory string
// UseNoticeFiles configures notice files for writing. If set, homepages
// will be written to a file created at config.GetHomePageFilename()
// and notices will be written to a file created at
// config.GetNoticesFilename().
//
// The homepage file may be read after the Tunnels notice with count of 1.
//
// The value of UseNoticeFiles sets the size and frequency at which the
// notices file, config.GetNoticesFilename(), will be rotated. See the
// comment for UseNoticeFiles for more details. One rotated older file,
// config.GetOldNoticesFilename(), is retained.
//
// The notice files may be may be read at any time; and should be opened
// read-only for reading. Diagnostic notices are omitted from the notice
// files.
//
// See comment for setNoticeFiles in notice.go for further details.
UseNoticeFiles *UseNoticeFiles
// PropagationChannelId is a string identifier which indicates how the
// Psiphon client was distributed. This parameter is required. This value
// is supplied by and depends on the Psiphon Network, and is typically
// embedded in the client binary.
PropagationChannelId string
// SponsorId is a string identifier which indicates who is sponsoring this
// Psiphon client. One purpose of this value is to determine the home
// pages for display. This parameter is required. This value is supplied
// by and depends on the Psiphon Network, and is typically embedded in the
// client binary.
SponsorId string
// ClientVersion is the client version number that the client reports to
// the server. The version number refers to the host client application,
// not the core tunnel library. One purpose of this value is to enable
// automatic updates. This value is supplied by and depends on the Psiphon
// Network, and is typically embedded in the client binary.
//
// Note that sending a ClientPlatform string which includes "windows"
// (case insensitive) and a ClientVersion of <= 44 will cause an error in
// processing the response to DoConnectedRequest calls.
ClientVersion string
// ClientPlatform is the client platform ("Windows", "Android", etc.) that
// the client reports to the server.
ClientPlatform string
// ClientFeatures is a list of feature names denoting enabled application
// features. Clients report enabled features to the server for stats
// purposes.
ClientFeatures []string
// EgressRegion is a ISO 3166-1 alpha-2 country code which indicates which
// country to egress from. For the default, "", the best performing server
// in any country is selected.
EgressRegion string
// SplitTunnelOwnRegion enables split tunnel mode for the client's own
// country. When enabled, TCP port forward destinations that resolve to
// the same GeoIP country as the client are connected to directly,
// untunneled.
SplitTunnelOwnRegion bool
// SplitTunnelRegions enables selected split tunnel mode in which the
// client specifies a list of ISO 3166-1 alpha-2 country codes for which
// traffic should be untunneled. TCP port forwards destined to any
// country specified in SplitTunnelRegions will be untunneled, regardless
// of whether SplitTunnelOwnRegion is on or off.
SplitTunnelRegions []string
// ListenInterface specifies which interface to listen on. If no
// interface is provided then listen on 127.0.0.1. If 'any' is provided
// then use 0.0.0.0. If there are multiple IP addresses on an interface
// use the first IPv4 address.
ListenInterface string
// DisableLocalSocksProxy disables running the local SOCKS proxy.
DisableLocalSocksProxy bool
// LocalSocksProxyPort specifies a port number for the local SOCKS proxy
// running at 127.0.0.1. For the default value, 0, the system selects a
// free port (a notice reporting the selected port is emitted).
LocalSocksProxyPort int
// LocalHttpProxyPort specifies a port number for the local HTTP proxy
// running at 127.0.0.1. For the default value, 0, the system selects a
// free port (a notice reporting the selected port is emitted).
LocalHttpProxyPort int
// DisableLocalHTTPProxy disables running the local HTTP proxy.
DisableLocalHTTPProxy bool
// NetworkLatencyMultiplier is a multiplier that is to be applied to
// default network event timeouts. Set this to tune performance for
// slow networks.
// When set, must be >= 1.0.
NetworkLatencyMultiplier float64
// LimitTunnelProtocols indicates which protocols to use. Valid values
// include: "SSH", "OSSH", "TLS-OSSH", "UNFRONTED-MEEK-OSSH",
// "UNFRONTED-MEEK-HTTPS-OSSH", "UNFRONTED-MEEK-SESSION-TICKET-OSSH",
// "FRONTED-MEEK-OSSH", "FRONTED-MEEK-HTTP-OSSH", "QUIC-OSSH",
// "FRONTED-MEEK-QUIC-OSSH", "TAPDANCE-OSSH", and "CONJURE-OSSH".
// For the default, an empty list, all protocols are used.
LimitTunnelProtocols []string
// InitialLimitTunnelProtocols is an optional initial phase of limited
// protocols for the first InitialLimitTunnelProtocolsCandidateCount
// candidates; after these candidates, LimitTunnelProtocols applies.
//
// For the default, an empty list, InitialLimitTunnelProtocols is off.
InitialLimitTunnelProtocols []string
// InitialLimitTunnelProtocolsCandidateCount is the number of candidates
// to which InitialLimitTunnelProtocols is applied instead of
// LimitTunnelProtocols.
//
// For the default, 0, InitialLimitTunnelProtocols is off.
InitialLimitTunnelProtocolsCandidateCount int
// LimitTLSProfiles indicates which TLS profiles to select from. Valid
// values are listed in protocols.SupportedTLSProfiles.
// For the default, an empty list, all profiles are candidates for
// selection.
LimitTLSProfiles []string
// LimitQUICVersions indicates which QUIC versions to select from. Valid
// values are listed in protocols.SupportedQUICVersions.
// For the default, an empty list, all versions are candidates for
// selection.
LimitQUICVersions []string
// EstablishTunnelTimeoutSeconds specifies a time limit after which to
// halt the core tunnel controller if no tunnel has been established. The
// default is parameters.EstablishTunnelTimeout.
EstablishTunnelTimeoutSeconds *int
// EstablishTunnelPausePeriodSeconds specifies the delay between attempts
// to establish tunnels. Briefly pausing allows for network conditions to
// improve and for asynchronous operations such as fetch remote server
// list to complete. If omitted, a default value is used. This value is
// typical overridden for testing.
EstablishTunnelPausePeriodSeconds *int
// EstablishTunnelPausePeriodSeconds specifies the grace period, or head
// start, provided to the affinity server candidate when establishing. The
// affinity server is the server used for the last established tunnel.
EstablishTunnelServerAffinityGracePeriodMilliseconds *int
// ConnectionWorkerPoolSize specifies how many connection attempts to
// attempt in parallel. If omitted of when 0, a default is used; this is
// recommended.
ConnectionWorkerPoolSize int
// TunnelPoolSize specifies how many tunnels to run in parallel. Port
// forwards are multiplexed over multiple tunnels. If omitted or when 0,
// the default is TUNNEL_POOL_SIZE, which is recommended. Any value over
// MAX_TUNNEL_POOL_SIZE is treated as MAX_TUNNEL_POOL_SIZE.
TunnelPoolSize int
// StaggerConnectionWorkersMilliseconds adds a specified delay before
// making each server candidate available to connection workers. This
// option is enabled when StaggerConnectionWorkersMilliseconds > 0.
StaggerConnectionWorkersMilliseconds int
// LimitIntensiveConnectionWorkers limits the number of concurrent
// connection workers attempting connections with resource intensive
// protocols. This option is enabled when LimitIntensiveConnectionWorkers
// > 0.
LimitIntensiveConnectionWorkers int
// LimitMeekBufferSizes selects smaller buffers for meek protocols.
LimitMeekBufferSizes bool
// LimitCPUThreads minimizes the number of CPU threads -- and associated
// overhead -- the are used.
LimitCPUThreads bool
// LimitRelayBufferSizes selects smaller buffers for port forward relaying.
LimitRelayBufferSizes bool
// IgnoreHandshakeStatsRegexps skips compiling and using stats regexes.
IgnoreHandshakeStatsRegexps bool
// UpstreamProxyURL is a URL specifying an upstream proxy to use for all
// outbound connections. The URL should include proxy type and
// authentication information, as required. See example URLs here:
// https://github.com/astaguna/popon-core/tree/master/psiphon/upstreamproxy
UpstreamProxyURL string
// CustomHeaders is a set of additional arbitrary HTTP headers that are
// added to all plaintext HTTP requests and requests made through an HTTP
// upstream proxy when specified by UpstreamProxyURL.
CustomHeaders http.Header
// NetworkConnectivityChecker is an interface that enables tunnel-core to
// call into the host application to check for network connectivity. See:
// NetworkConnectivityChecker doc.
NetworkConnectivityChecker NetworkConnectivityChecker
// DeviceBinder is an interface that enables tunnel-core to call into the
// host application to bind sockets to specific devices. See: DeviceBinder
// doc.
//
// When DeviceBinder is set, the "VPN" feature name is automatically added
// when reporting ClientFeatures.
DeviceBinder DeviceBinder
// AllowDefaultDNSResolverWithBindToDevice indicates that it's safe to use
// the default resolver when DeviceBinder is configured, as the host OS
// will automatically exclude DNS requests from the VPN.
AllowDefaultDNSResolverWithBindToDevice bool
// IPv6Synthesizer is an interface that allows tunnel-core to call into
// the host application to synthesize IPv6 addresses. See: IPv6Synthesizer
// doc.
IPv6Synthesizer IPv6Synthesizer
// HasIPv6RouteGetter is an interface that allows tunnel-core to call into
// the host application to determine if the host has an IPv6 route. See:
// HasIPv6RouteGetter doc.
HasIPv6RouteGetter HasIPv6RouteGetter
// DNSServerGetter is an interface that enables tunnel-core to call into
// the host application to discover the native network DNS server
// settings. See: DNSServerGetter doc.
DNSServerGetter DNSServerGetter
// NetworkIDGetter in an interface that enables tunnel-core to call into
// the host application to get an identifier for the host's current active
// network. See: NetworkIDGetter doc.
NetworkIDGetter NetworkIDGetter
// NetworkID, when not blank, is used as the identifier for the host's
// current active network.
// NetworkID is ignored when NetworkIDGetter is set.
NetworkID string
// DisableTactics disables tactics operations including requests, payload
// handling, and application of parameters.
DisableTactics bool
// DisableReplay causes any persisted dial parameters to be ignored when
// they would otherwise be used for replay.
DisableReplay bool
// TargetServerEntry is an encoded server entry. When specified, this
// server entry is used exclusively and all other known servers are
// ignored; also, when set, ConnectionWorkerPoolSize is ignored and
// the pool size is 1.
TargetServerEntry string
// DisableApi disables Psiphon server API calls including handshake,
// connected, status, etc. This is used for special case temporary tunnels
// (Windows VPN mode).
DisableApi bool
// TargetApiProtocol specifies whether to force use of "ssh" or "web" API
// protocol. When blank, the default, the optimal API protocol is used.
// Note that this capability check is not applied before the
// "CandidateServers" count is emitted.
//
// This parameter is intended for testing and debugging only. Not all
// parameters are supported in the legacy "web" API protocol, including
// speed test samples.
TargetApiProtocol string
// RemoteServerListURLs is list of URLs which specify locations to fetch
// out-of-band server entries. This facility is used when a tunnel cannot
// be established to known servers. This value is supplied by and depends
// on the Psiphon Network, and is typically embedded in the client binary.
// All URLs must point to the same entity with the same ETag. At least one
// TransferURL must have OnlyAfterAttempts = 0.
RemoteServerListURLs parameters.TransferURLs
// RemoteServerListSignaturePublicKey specifies a public key that's used
// to authenticate the remote server list payload. This value is supplied
// by and depends on the Psiphon Network, and is typically embedded in the
// client binary.
RemoteServerListSignaturePublicKey string
// DisableRemoteServerListFetcher disables fetching remote server lists.
// This is used for special case temporary tunnels.
DisableRemoteServerListFetcher bool
// FetchRemoteServerListRetryPeriodMilliseconds specifies the delay before
// resuming a remote server list download after a failure. If omitted, a
// default value is used. This value is typical overridden for testing.
FetchRemoteServerListRetryPeriodMilliseconds *int
// ObfuscatedServerListRootURLs is a list of URLs which specify root
// locations from which to fetch obfuscated server list files. This value
// is supplied by and depends on the Psiphon Network, and is typically
// embedded in the client binary. All URLs must point to the same entity
// with the same ETag. At least one DownloadURL must have
// OnlyAfterAttempts = 0.
ObfuscatedServerListRootURLs parameters.TransferURLs
// UpgradeDownloadURLs is list of URLs which specify locations from which
// to download a host client upgrade file, when one is available. The core
// tunnel controller provides a resumable download facility which
// downloads this resource and emits a notice when complete. This value is
// supplied by and depends on the Psiphon Network, and is typically
// embedded in the client binary. All URLs must point to the same entity
// with the same ETag. At least one DownloadURL must have
// OnlyAfterAttempts = 0.
UpgradeDownloadURLs parameters.TransferURLs
// UpgradeDownloadClientVersionHeader specifies the HTTP header name for
// the entity at UpgradeDownloadURLs which specifies the client version
// (an integer value). A HEAD request may be made to check the version
// number available at UpgradeDownloadURLs.
// UpgradeDownloadClientVersionHeader is required when UpgradeDownloadURLs
// is specified.
UpgradeDownloadClientVersionHeader string
// FetchUpgradeRetryPeriodMilliseconds specifies the delay before resuming
// a client upgrade download after a failure. If omitted, a default value
// is used. This value is typical overridden for testing.
FetchUpgradeRetryPeriodMilliseconds *int
// FeedbackUploadURLs is a list of SecureTransferURLs which specify
// locations where feedback data can be uploaded, pairing with each
// location a public key with which to encrypt the feedback data. This
// value is supplied by and depends on the Psiphon Network, and is
// typically embedded in the client binary. At least one TransferURL must
// have OnlyAfterAttempts = 0.
FeedbackUploadURLs parameters.TransferURLs
// FeedbackEncryptionPublicKey is a default base64-encoded, RSA public key
// value used to encrypt feedback data. Used when uploading feedback with a
// TransferURL which has no public key value configured, i.e.
// B64EncodedPublicKey = "".
FeedbackEncryptionPublicKey string
// TrustedCACertificatesFilename specifies a file containing trusted CA
// certs. When set, this toggles use of the trusted CA certs, specified in
// TrustedCACertificatesFilename, for tunneled TLS connections that expect
// server certificates signed with public certificate authorities
// (currently, only upgrade downloads). This option is used with stock Go
// TLS in cases where Go may fail to obtain a list of root CAs from the
// operating system.
TrustedCACertificatesFilename string
// DisableSystemRootCAs, when true, disables loading system root CAs when
// verifying TLS certificates for all remote server list downloads, upgrade
// downloads, and feedback uploads. Each of these transfers has additional
// security at the payload level. Verifying TLS certificates is preferred,
// as an additional security and circumvention layer; set
// DisableSystemRootCAs only in cases where system root CAs cannot be
// loaded; for example, if unsupported (iOS < 12) or insufficient memory
// (VPN extension on iOS < 15).
DisableSystemRootCAs bool
// DisablePeriodicSshKeepAlive indicates whether to send an SSH keepalive
// every 1-2 minutes, when the tunnel is idle. If the SSH keepalive times
// out, the tunnel is considered to have failed.
DisablePeriodicSshKeepAlive bool
// DeviceRegion is the optional, reported region the host device is
// running in. This input value should be a ISO 3166-1 alpha-2 country
// code. The device region is reported to the server in the connected
// request and recorded for Psiphon stats.
//
// When provided, this value may be used, pre-connection, to select
// performance or circumvention optimization strategies for the given
// region.
DeviceRegion string
// EmitDiagnosticNotices indicates whether to output notices containing
// detailed information about the Psiphon session. As these notices may
// contain sensitive information, they should not be insecurely distributed
// or displayed to users. Default is off.
EmitDiagnosticNotices bool
// EmitDiagnosticNetworkParameters indicates whether to include network
// parameters in diagnostic notices. As these parameters are sensitive
// circumvention network information, they should not be insecurely
// distributed or displayed to users. Default is off.
EmitDiagnosticNetworkParameters bool
// EmitBytesTransferred indicates whether to emit periodic notices showing
// bytes sent and received.
EmitBytesTransferred bool
// EmitSLOKs indicates whether to emit notices for each seeded SLOK. As
// this could reveal user browsing activity, it's intended for debugging
// and testing only.
EmitSLOKs bool
// EmitRefractionNetworkingLogs indicates whether to emit gotapdance log
// messages to stdout. Note that gotapdance log messages do not conform to
// the Notice format standard. Default is off.
EmitRefractionNetworkingLogs bool
// EmitServerAlerts indicates whether to emit notices for server alerts.
EmitServerAlerts bool
// EmitClientAddress indicates whether to emit the client's public network
// address, IP and port, as seen by the server.
EmitClientAddress bool
// RateLimits specify throttling configuration for the tunnel.
RateLimits common.RateLimits
// PacketTunnelTunDeviceFileDescriptor specifies a tun device file
// descriptor to use for running a packet tunnel. When this value is > 0,
// a packet tunnel is established through the server and packets are
// relayed via the tun device file descriptor. The file descriptor is
// duped in NewController. When PacketTunnelTunDeviceFileDescriptor is
// set, TunnelPoolSize must be 1.
PacketTunnelTunFileDescriptor int
// PacketTunnelTransparentDNSIPv4Address is the IPv4 address of the DNS
// server configured by a VPN using a packet tunnel. All DNS packets
// destined to this DNS server are transparently redirected to the
// Psiphon server DNS.
PacketTunnelTransparentDNSIPv4Address string
// PacketTunnelTransparentDNSIPv6Address is the IPv6 address of the DNS
// server configured by a VPN using a packet tunnel. All DNS packets
// destined to this DNS server are transparently redirected to the
// Psiphon server DNS.
PacketTunnelTransparentDNSIPv6Address string
// SessionID specifies a client session ID to use in the Psiphon API. The
// session ID should be a randomly generated value that is used only for a
// single session, which is defined as the period between a user starting
// a Psiphon client and stopping the client.
//
// A session ID must be 32 hex digits (lower case). When blank, a random
// session ID is automatically generated. Supply a session ID when a
// single client session will cross multiple Controller instances.
SessionID string
// Authorizations is a list of encoded, signed access control
// authorizations that the client has obtained and will present to the
// server.
Authorizations []string
// ServerEntrySignaturePublicKey is a base64-encoded, ed25519 public
// key value used to verify individual server entry signatures. This value
// is supplied by and depends on the Psiphon Network, and is typically
// embedded in the client binary.
ServerEntrySignaturePublicKey string
// ExchangeObfuscationKey is a base64-encoded, NaCl secretbox key used to
// obfuscate server info exchanges between clients.
// Required for the exchange functionality.
ExchangeObfuscationKey string
// MigrateHomepageNoticesFilename migrates a homepage file from the path
// previously configured with setNoticeFiles to the new path for homepage
// files under the data root directory. The file specified by this config
// value will be moved to config.GetHomePageFilename().
//
// Note: see comment for config.Commit() for a description of how file
// migrations are performed.
//
// If not set, no migration operation will be performed.
MigrateHomepageNoticesFilename string
// MigrateRotatingNoticesFilename migrates notice files from the path
// previously configured with setNoticeFiles to the new path for notice
// files under the data root directory.
//
// MigrateRotatingNoticesFilename will be moved to
// config.GetNoticesFilename().
//
// MigrateRotatingNoticesFilename.1 will be moved to
// config.GetOldNoticesFilename().
//
// Note: see comment for config.Commit() for a description of how file
// migrations are performed.
//
// If not set, no migration operation will be performed.
MigrateRotatingNoticesFilename string
// MigrateDataStoreDirectory indicates the location of the datastore
// directory, as previously configured with the deprecated
// DataStoreDirectory config field. Datastore files found in the specified
// directory will be moved under the data root directory.
//
// Note: see comment for config.Commit() for a description of how file
// migrations are performed.
MigrateDataStoreDirectory string
// MigrateRemoteServerListDownloadFilename indicates the location of
// remote server list download files. The remote server list files found at
// the specified path will be moved under the data root directory.
//
// Note: see comment for config.Commit() for a description of how file
// migrations are performed.
MigrateRemoteServerListDownloadFilename string
// MigrateObfuscatedServerListDownloadDirectory indicates the location of
// the obfuscated server list downloads directory, as previously configured
// with ObfuscatedServerListDownloadDirectory. Obfuscated server list
// download files found in the specified directory will be moved under the
// data root directory.
//
// Warning: if the directory is empty after obfuscated server
// list files are moved, then it will be deleted.
//
// Note: see comment for config.Commit() for a description of how file
// migrations are performed.
MigrateObfuscatedServerListDownloadDirectory string
// MigrateUpgradeDownloadFilename indicates the location of downloaded
// application upgrade files. Downloaded upgrade files found at the
// specified path will be moved under the data root directory.
//
// Note: see comment for config.Commit() for a description of how file
// migrations are performed.
MigrateUpgradeDownloadFilename string
//
// The following parameters are deprecated.
//
// DataStoreDirectory is the directory in which to store the persistent
// database, which contains information such as server entries. By
// default, current working directory.
//
// Deprecated:
// Use MigrateDataStoreDirectory. When MigrateDataStoreDirectory
// is set, this parameter is ignored.
//
// DataStoreDirectory has been subsumed by the new data root directory,
// which is configured with DataRootDirectory. If set, datastore files
// found in the specified directory will be moved under the data root
// directory.
DataStoreDirectory string
// RemoteServerListDownloadFilename specifies a target filename for
// storing the remote server list download. Data is stored in co-located
// files (RemoteServerListDownloadFilename.part*) to allow for resumable
// downloading.
//
// Deprecated:
// Use MigrateRemoteServerListDownloadFilename. When
// MigrateRemoteServerListDownloadFilename is set, this parameter is
// ignored.
//
// If set, remote server list download files found at the specified path
// will be moved under the data root directory.
RemoteServerListDownloadFilename string
// ObfuscatedServerListDownloadDirectory specifies a target directory for
// storing the obfuscated remote server list downloads. Data is stored in
// co-located files (<OSL filename>.part*) to allow for resumable
// downloading.
//
// Deprecated:
// Use MigrateObfuscatedServerListDownloadDirectory. When
// MigrateObfuscatedServerListDownloadDirectory is set, this parameter is
// ignored.
//
// If set, obfuscated server list download files found at the specified path
// will be moved under the data root directory.
ObfuscatedServerListDownloadDirectory string
// UpgradeDownloadFilename is the local target filename for an upgrade
// download. This parameter is required when UpgradeDownloadURLs (or
// UpgradeDownloadUrl) is specified. Data is stored in co-located files
// (UpgradeDownloadFilename.part*) to allow for resumable downloading.
//
// Deprecated:
// Use MigrateUpgradeDownloadFilename. When MigrateUpgradeDownloadFilename
// is set, this parameter is ignored.
//
// If set, upgrade download files found at the specified path will be moved
// under the data root directory.
UpgradeDownloadFilename string
// TunnelProtocol indicates which protocol to use. For the default, "",
// all protocols are used.
//
// Deprecated: Use LimitTunnelProtocols. When LimitTunnelProtocols is not
// nil, this parameter is ignored.
TunnelProtocol string
// Deprecated: Use CustomHeaders. When CustomHeaders is not nil, this
// parameter is ignored.
UpstreamProxyCustomHeaders http.Header
// RemoteServerListUrl is a URL which specifies a location to fetch out-
// of-band server entries. This facility is used when a tunnel cannot be
// established to known servers. This value is supplied by and depends on
// the Psiphon Network, and is typically embedded in the client binary.
//
// Deprecated: Use RemoteServerListURLs. When RemoteServerListURLs is not
// nil, this parameter is ignored.
RemoteServerListUrl string
// ObfuscatedServerListRootURL is a URL which specifies the root location
// from which to fetch obfuscated server list files. This value is
// supplied by and depends on the Psiphon Network, and is typically
// embedded in the client binary.
//
// Deprecated: Use ObfuscatedServerListRootURLs. When
// ObfuscatedServerListRootURLs is not nil, this parameter is ignored.
ObfuscatedServerListRootURL string
// UpgradeDownloadUrl specifies a URL from which to download a host client
// upgrade file, when one is available. The core tunnel controller
// provides a resumable download facility which downloads this resource
// and emits a notice when complete. This value is supplied by and depends
// on the Psiphon Network, and is typically embedded in the client binary.
//
// Deprecated: Use UpgradeDownloadURLs. When UpgradeDownloadURLs is not
// nil, this parameter is ignored.
UpgradeDownloadUrl string
//
// The following parameters are for testing purposes.
//
// TransformHostNameProbability is for testing purposes.
TransformHostNameProbability *float64
// FragmentorProbability and associated Fragmentor fields are for testing
// purposes.
FragmentorProbability *float64
FragmentorLimitProtocols []string
FragmentorMinTotalBytes *int
FragmentorMaxTotalBytes *int
FragmentorMinWriteBytes *int
FragmentorMaxWriteBytes *int
FragmentorMinDelayMicroseconds *int
FragmentorMaxDelayMicroseconds *int
// MeekTrafficShapingProbability and associated fields are for testing
// purposes.
MeekTrafficShapingProbability *float64
MeekTrafficShapingLimitProtocols []string
MeekMinTLSPadding *int
MeekMaxTLSPadding *int
MeekMinLimitRequestPayloadLength *int
MeekMaxLimitRequestPayloadLength *int
MeekRedialTLSProbability *float64
MeekAlternateCookieNameProbability *float64
MeekAlternateContentTypeProbability *float64
// ObfuscatedSSHAlgorithms and associated ObfuscatedSSH fields are for
// testing purposes. If specified, ObfuscatedSSHAlgorithms must have 4 SSH
// KEX elements in order: the kex algorithm, cipher, MAC, and server host
// key algorithm.
ObfuscatedSSHAlgorithms []string
ObfuscatedSSHMinPadding *int
ObfuscatedSSHMaxPadding *int
// LivenessTestMinUpstreamBytes and other LivenessTest fields are for
// testing purposes.
LivenessTestMinUpstreamBytes *int
LivenessTestMaxUpstreamBytes *int
LivenessTestMinDownstreamBytes *int
LivenessTestMaxDownstreamBytes *int
// ReplayCandidateCount and other Replay fields are for testing purposes.
ReplayCandidateCount *int
ReplayDialParametersTTLSeconds *int
ReplayTargetUpstreamBytes *int
ReplayTargetDownstreamBytes *int
ReplayTargetTunnelDurationSeconds *int
ReplayLaterRoundMoveToFrontProbability *float64
ReplayRetainFailedProbability *float64
ReplayIgnoreChangedConfigState *bool
// NetworkLatencyMultiplierMin and other NetworkLatencyMultiplier fields are
// for testing purposes.
NetworkLatencyMultiplierMin float64
NetworkLatencyMultiplierMax float64
NetworkLatencyMultiplierLambda float64
// UseOnlyCustomTLSProfiles and other TLS configuration fields are for
// testing purposes.
UseOnlyCustomTLSProfiles *bool
CustomTLSProfiles protocol.CustomTLSProfiles
SelectRandomizedTLSProfileProbability *float64
NoDefaultTLSSessionIDProbability *float64
DisableFrontingProviderTLSProfiles protocol.LabeledTLSProfiles
// ClientBurstUpstreamTargetBytes and other burst metric fields are for
// testing purposes.
ClientBurstUpstreamTargetBytes *int
ClientBurstUpstreamDeadlineMilliseconds *int
ClientBurstDownstreamTargetBytes *int
ClientBurstDownstreamDeadlineMilliseconds *int
// ApplicationParameters is for testing purposes.
ApplicationParameters parameters.KeyValues
// CustomHostNameRegexes and other custom host name fields are for testing
// purposes.
CustomHostNameRegexes []string
CustomHostNameProbability *float64
CustomHostNameLimitProtocols []string
// ConjureCachedRegistrationTTLSeconds and other Conjure fields are for
// testing purposes.
ConjureCachedRegistrationTTLSeconds *int
ConjureAPIRegistrarBidirectionalURL string
ConjureAPIRegistrarFrontingSpecs parameters.FrontingSpecs
ConjureAPIRegistrarMinDelayMilliseconds *int
ConjureAPIRegistrarMaxDelayMilliseconds *int
ConjureDecoyRegistrarProbability *float64
ConjureDecoyRegistrarWidth *int
ConjureDecoyRegistrarMinDelayMilliseconds *int
ConjureDecoyRegistrarMaxDelayMilliseconds *int
// HoldOffTunnelMinDurationMilliseconds and other HoldOffTunnel fields are
// for testing purposes.
HoldOffTunnelMinDurationMilliseconds *int
HoldOffTunnelMaxDurationMilliseconds *int
HoldOffTunnelProtocols []string
HoldOffTunnelFrontingProviderIDs []string
HoldOffTunnelProbability *float64
// RestrictFrontingProviderIDs and other RestrictFrontingProviderIDs fields
// are for testing purposes.
RestrictFrontingProviderIDs []string
RestrictFrontingProviderIDsClientProbability *float64
// UpstreamProxyAllowAllServerEntrySources is for testing purposes.
UpstreamProxyAllowAllServerEntrySources *bool
// LimitTunnelDialPortNumbers is for testing purposes.
LimitTunnelDialPortNumbers parameters.TunnelProtocolPortLists
// QUICDisablePathMTUDiscoveryProbability is for testing purposes.
QUICDisablePathMTUDiscoveryProbability *float64
// DNSResolverAttemptsPerServer and other DNSResolver fields are for
// testing purposes.
DNSResolverAttemptsPerServer *int
DNSResolverAttemptsPerPreferredServer *int
DNSResolverRequestTimeoutMilliseconds *int
DNSResolverAwaitTimeoutMilliseconds *int
DNSResolverPreresolvedIPAddressCIDRs parameters.LabeledCIDRs
DNSResolverPreresolvedIPAddressProbability *float64
DNSResolverAlternateServers []string
DNSResolverPreferredAlternateServers []string
DNSResolverPreferAlternateServerProbability *float64
DNSResolverProtocolTransformSpecs transforms.Specs
DNSResolverProtocolTransformScopedSpecNames transforms.ScopedSpecNames
DNSResolverProtocolTransformProbability *float64
DNSResolverIncludeEDNS0Probability *float64
DNSResolverCacheExtensionInitialTTLMilliseconds *int
DNSResolverCacheExtensionVerifiedTTLMilliseconds *int
DirectHTTPProtocolTransformSpecs transforms.Specs
DirectHTTPProtocolTransformScopedSpecNames transforms.ScopedSpecNames
DirectHTTPProtocolTransformProbability *float64
FrontedHTTPProtocolTransformSpecs transforms.Specs
FrontedHTTPProtocolTransformScopedSpecNames transforms.ScopedSpecNames
FrontedHTTPProtocolTransformProbability *float64
OSSHObfuscatorSeedTransformSpecs transforms.Specs
OSSHObfuscatorSeedTransformScopedSpecNames transforms.ScopedSpecNames
OSSHObfuscatorSeedTransformProbability *float64
ObfuscatedQUICNonceTransformSpecs transforms.Specs
ObfuscatedQUICNonceTransformScopedSpecNames transforms.ScopedSpecNames
ObfuscatedQUICNonceTransformProbability *float64
// OSSHPrefix parameters are for testing purposes only.
OSSHPrefixSpecs transforms.Specs
OSSHPrefixScopedSpecNames transforms.ScopedSpecNames
OSSHPrefixProbability *float64
OSSHPrefixSplitMinDelayMilliseconds *int
OSSHPrefixSplitMaxDelayMilliseconds *int
OSSHPrefixEnableFragmentor *bool
// TLSTunnelTrafficShapingProbability and associated fields are for testing.
TLSTunnelTrafficShapingProbability *float64
TLSTunnelMinTLSPadding *int
TLSTunnelMaxTLSPadding *int
// AdditionalParameters is used for testing.
AdditionalParameters string
// params is the active parameters.Parameters with defaults, config values,
// and, optionally, tactics applied.
//
// New tactics must be applied by calling Config.SetParameters; calling
// params.Set directly will fail to add config values.
params *parameters.Parameters
dialParametersHash []byte
dynamicConfigMutex sync.Mutex
sponsorID string
authorizations []string
deviceBinder DeviceBinder
networkIDGetter NetworkIDGetter
clientFeatures []string
resolverMutex sync.Mutex
resolver *resolver.Resolver
committed bool
loadTimestamp string
}
// Config field which specifies if notice files should be used and at which
// frequency and size they should be rotated.
//
// If either RotatingFileSize or RotatingSyncFrequency are <= 0, default values
// are used.
//
// See comment for setNoticeFiles in notice.go for further details.
type UseNoticeFiles struct {
RotatingFileSize int
RotatingSyncFrequency int
}
// LoadConfig parses a JSON format Psiphon config JSON string and returns a
// Config struct populated with config values.
//
// The Config struct may then be programmatically populated with additional
// values, including callbacks such as DeviceBinder.
//
// Before using the Config, Commit must be called, which will perform further
// validation and initialize internal data structures.
func LoadConfig(configJson []byte) (*Config, error) {
var config Config
err := json.Unmarshal(configJson, &config)
if err != nil {
return nil, errors.Trace(err)
}
config.loadTimestamp = common.TruncateTimestampToHour(
common.GetCurrentTimestamp())
return &config, nil
}
// IsCommitted checks if Commit was called.
func (config *Config) IsCommitted() bool {
return config.committed
}
// Commit validates Config fields finalizes initialization.
//
// Config fields should not be set after calling Config, as any changes may
// not be reflected in internal data structures.
//
// If migrateFromLegacyFields is set to true, then an attempt to migrate from
// legacy fields is made.
//
// Migration from legacy fields:
// Config fields of the naming Migrate* (e.g. MigrateDataStoreDirectory) specify
// a file migration operation which should be performed. These fields correspond
// to deprecated fields, which previously could be used to specify where Psiphon
// stored different sets of persistent files (e.g. MigrateDataStoreDirectory
// corresponds to the deprecated field DataStoreDirectory).
//
// Psiphon now stores all persistent data under the configurable
// DataRootDirectory (see Config.DataRootDirectory). The deprecated fields, and
// corresponding Migrate* fields, are now used to specify the file or directory
// path where, or under which, persistent files and directories created by
// previous versions of Psiphon exist, so they can be moved under the
// DataRootDirectory.
//
// For each migration operation:
// - In the case of directories that could have defaulted to the current working
// directory, persistent files and directories created by Psiphon are
// precisely targeted to avoid moving files which were not created by Psiphon.
// - If no file is found at the specified path, or an error is encountered while
// migrating the file, then an error is logged and execution continues
// normally.
//
// A sentinel file which signals that file migration has been completed, and
// should not be attempted again, is created under DataRootDirectory after one
// full pass through Commit(), regardless of whether file migration succeeds or
// fails. It is better to not endlessly retry file migrations on each Commit()
// because file system errors are expected to be rare and persistent files will
// be re-populated over time.
func (config *Config) Commit(migrateFromLegacyFields bool) error {
// Apply any additional parameters first
additionalParametersInfoMsgs, err := config.applyAdditionalParameters()
if err != nil {
return errors.TraceMsg(err, "failed to apply additional parameters")
}
// Do SetEmitDiagnosticNotices first, to ensure config file errors are
// emitted.
if config.EmitDiagnosticNotices {
SetEmitDiagnosticNotices(
true, config.EmitDiagnosticNetworkParameters)
}
// Migrate and set notice files before any operations that may emit an
// error. This is to ensure config file errors are written to file when
// notice files are configured with config.UseNoticeFiles.
//
// Note:
// Errors encountered while configuring the data directory cannot be written
// to notice files. This is because notices files are created within the
// data directory.
if config.DataRootDirectory == "" {
wd, err := os.Getwd()
if err != nil {
return errors.Trace(common.RedactFilePathsError(err))
}
config.DataRootDirectory = wd
}
// Create root directory
dataDirectoryPath := config.GetPsiphonDataDirectory()
if !common.FileExists(dataDirectoryPath) {
err := os.Mkdir(dataDirectoryPath, os.ModePerm)
if err != nil {
return errors.Tracef(
"failed to create datastore directory with error: %s",