Sfoglia il codice sorgente

Merge https://github.com/Psiphon-Labs/psiphon-tunnel-core

Miro Kuratczyk 10 anni fa
parent
commit
0e7e6dd828

+ 83 - 0
CLA-entity.md

@@ -0,0 +1,83 @@
+Psiphon Entity Contributor License Agreement
+==================================================
+
+Thank you for your interest in contributing to Psiphon ("We" or "Us").
+
+This contributor agreement ("Agreement") documents the rights granted by contributors to Us. To make this document effective, please submit a pull request with a file under the `/contributors` directory indicating your acceptance of this agreement, following the instructions at https://github.com/Psiphon-Labs/psiphon-tunnel-core/blob/master/CONTRIBUTING.md.
+
+This is a legally binding document, so please read it carefully before agreeing to it. The Agreement may cover more than one software project managed by Us.
+
+## 1. Definitions
+
+"You" means any Legal Entity on behalf of whom a Contribution has been received by Us. "Legal Entity" means an entity which is not a natural person. "Affiliates" means other Legal Entities that control, are controlled by, or under common control with that Legal Entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such Legal Entity, whether by contract or otherwise, (ii) ownership of fifty percent (50%) or more of the outstanding shares or securities which vote to elect the management or other persons who direct such Legal Entity or (iii) beneficial ownership of such entity.
+
+"Contribution" means any work of authorship that is Submitted by You to Us in which You own or assert ownership of the Copyright. If You do not own the Copyright in the entire work of authorship, please follow the instructions in https://github.com/Psiphon-Labs/psiphon-tunnel-core/blob/master/CONTRIBUTING.md.
+
+"Copyright" means all rights protecting works of authorship owned or controlled by You or Your Affiliates, including copyright, moral and neighboring rights, as appropriate, for the full term of their existence including any extensions by You.
+
+"Material" means the work of authorship which is made available by Us to third parties. When this Agreement covers more than one software project, the Material means the work of authorship to which the Contribution was Submitted. After You Submit the Contribution, it may be included in the Material.
+
+"Submit" means any form of electronic, verbal, or written communication sent to Us or our representatives, including but not limited to electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, Us for the purpose of discussing and improving the Material, but excluding communication that is conspicuously marked or otherwise designated in writing by You as "Not a Contribution."
+
+"Submission Date" means the date on which You Submit a Contribution to Us.
+
+"Effective Date" means the date You execute this Agreement or the date You first Submit a Contribution to Us, whichever is earlier.
+
+## 2. Grant of Rights
+
+2.1 Copyright License
+
+(a) You retain ownership of the Copyright in Your Contribution and have the same rights to use or license the Contribution which You would have had without entering into the Agreement.
+
+(b) To the maximum extent permitted by the relevant law, You grant to Us a perpetual, worldwide, non-exclusive, transferable, royalty-free, irrevocable license under the Copyright covering the Contribution, with the right to sublicense such rights through multiple tiers of sublicensees, to reproduce, modify, display, perform and distribute the Contribution as part of the Material; provided that this license is conditioned upon compliance with Section 2.3.
+
+2.2 Patent License
+
+For patent claims including, without limitation, method, process, and apparatus claims which You or Your Affiliates own, control or have the right to grant, now or in the future, You grant to Us a perpetual, worldwide, non-exclusive, transferable, royalty-free, irrevocable patent license, with the right to sublicense these rights to multiple tiers of sublicensees, to make, have made, use, sell, offer for sale, import and otherwise transfer the Contribution and the Contribution in combination with the Material (and portions of such combination). This license is granted only to the extent that the exercise of the licensed rights infringes such patent claims; and provided that this license is conditioned upon compliance with Section 2.3.
+
+2.3 Outbound License
+
+Based on the grant of rights in Sections 2.1 and 2.2, if We include Your Contribution in a Material, We may license the Contribution under any license, including copyleft, permissive, commercial, or proprietary licenses. As a condition on the exercise of this right, We agree to also license the Contribution under the terms of the license or licenses which We are using for the Material on the Submission Date.
+
+2.4 Moral Rights. If moral rights apply to the Contribution, to the maximum extent permitted by law, You waive and agree not to assert such moral rights against Us or our successors in interest, or any of our licensees, either direct or indirect.
+
+2.5 Our Rights. You acknowledge that We are not obligated to use Your Contribution as part of the Material and may decide to include any Contribution We consider appropriate.
+
+2.6 Reservation of Rights. Any rights not expressly licensed under this section are expressly reserved by You.
+
+## 3. Agreement
+
+You confirm that:
+
+(a) You have the legal authority to enter into this Agreement.
+
+(b) You or Your Affiliates own the Copyright and patent claims covering the Contribution which are required to grant the rights under Section 2.
+
+(c) The grant of rights under Section 2 does not violate any grant of rights which You or Your Affiliates have made to third parties.
+
+(d) You have followed the instructions in https://github.com/Psiphon-Labs/psiphon-tunnel-core/blob/master/CONTRIBUTING.md, if You do not own the Copyright in the entire work of authorship Submitted.
+
+## 4. Disclaimer
+
+EXCEPT FOR THE EXPRESS WARRANTIES IN SECTION 3, THE CONTRIBUTION IS PROVIDED "AS IS". MORE PARTICULARLY, ALL EXPRESS OR IMPLIED WARRANTIES INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE EXPRESSLY DISCLAIMED BY YOU TO US. TO THE EXTENT THAT ANY SUCH WARRANTIES CANNOT BE DISCLAIMED, SUCH WARRANTY IS LIMITED IN DURATION TO THE MINIMUM PERIOD PERMITTED BY LAW.
+
+## 5. Consequential Damage Waiver
+
+TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, IN NO EVENT WILL YOU BE LIABLE FOR ANY LOSS OF PROFITS, LOSS OF ANTICIPATED SAVINGS, LOSS OF DATA, INDIRECT, SPECIAL, INCIDENTAL, CONSEQUENTIAL AND EXEMPLARY DAMAGES ARISING OUT OF THIS AGREEMENT REGARDLESS OF THE LEGAL OR EQUITABLE THEORY (CONTRACT, TORT OR OTHERWISE) UPON WHICH THE CLAIM IS BASED.
+
+## 6. Miscellaneous
+
+6.1 This Agreement will be governed by and construed in accordance with the laws of Canada excluding its conflicts of law provisions. Under certain circumstances, the governing law in this section might be superseded by the United Nations Convention on Contracts for the International Sale of Goods ("UN Convention") and the parties intend to avoid the application of the UN Convention to this Agreement and, thus, exclude the application of the UN Convention in its entirety to this Agreement.
+
+6.2 This Agreement sets out the entire agreement between You and Us for Your Contributions to Us and overrides all other agreements or understandings.
+
+6.3 If You or We assign the rights or obligations received through this Agreement to a third party, as a condition of the assignment, that third party must agree in writing to abide by all the rights and obligations in the Agreement.
+
+6.4 The failure of either party to require performance by the other party of any provision of this Agreement in one situation shall not affect the right of a party to require such performance at any time in the future. A waiver of performance under a provision in one situation shall not be considered a waiver of the performance of the provision in the future or a waiver of the provision in its entirety.
+
+6.5 If any provision of this Agreement is found void and unenforceable, such provision will be replaced to the extent possible with a provision that comes closest to the meaning of the original provision and which is enforceable. The terms and conditions set forth in this Agreement shall apply notwithstanding any failure of essential purpose of this Agreement or any limited remedy to the maximum extent possible under law.
+
+This agreement is derived from the Project Harmony CLA generator:
+http://www.harmonyagreements.org/
+
+Harmony (HA-CLA-E-ANY) Version 1.0

+ 83 - 0
CLA-individual.md

@@ -0,0 +1,83 @@
+Psiphon Individual Contributor License Agreement
+======================================================
+
+Thank you for your interest in contributing to Psiphon ("We" or "Us").
+
+This contributor agreement ("Agreement") documents the rights granted by contributors to Us. To make this document effective, please submit a pull request with a file under the `/contributors` directory indicating your acceptance of this agreement, following the instructions at https://github.com/Psiphon-Labs/psiphon-tunnel-core/blob/master/CONTRIBUTING.md.
+
+This is a legally binding document, so please read it carefully before agreeing to it. The Agreement may cover more than one software project managed by Us.
+
+## 1. Definitions
+
+"You" means the individual who Submits a Contribution to Us.
+
+"Contribution" means any work of authorship that is Submitted by You to Us in which You own or assert ownership of the Copyright. If You do not own the Copyright in the entire work of authorship, please follow the instructions in https://github.com/Psiphon-Labs/psiphon-tunnel-core/blob/master/CONTRIBUTING.md.
+
+"Copyright" means all rights protecting works of authorship owned or controlled by You, including copyright, moral and neighboring rights, as appropriate, for the full term of their existence including any extensions by You.
+
+"Material" means the work of authorship which is made available by Us to third parties. When this Agreement covers more than one software project, the Material means the work of authorship to which the Contribution was Submitted. After You Submit the Contribution, it may be included in the Material.
+
+"Submit" means any form of electronic, verbal, or written communication sent to Us or our representatives, including but not limited to electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, Us for the purpose of discussing and improving the Material, but excluding communication that is conspicuously marked or otherwise designated in writing by You as "Not a Contribution."
+
+"Submission Date" means the date on which You Submit a Contribution to Us.
+
+"Effective Date" means the date You execute this Agreement or the date You first Submit a Contribution to Us, whichever is earlier.
+
+## 2. Grant of Rights
+
+2.1 Copyright License
+
+(a) You retain ownership of the Copyright in Your Contribution and have the same rights to use or license the Contribution which You would have had without entering into the Agreement.
+
+(b) To the maximum extent permitted by the relevant law, You grant to Us a perpetual, worldwide, non-exclusive, transferable, royalty-free, irrevocable license under the Copyright covering the Contribution, with the right to sublicense such rights through multiple tiers of sublicensees, to reproduce, modify, display, perform and distribute the Contribution as part of the Material; provided that this license is conditioned upon compliance with Section 2.3.
+
+2.2 Patent License
+
+For patent claims including, without limitation, method, process, and apparatus claims which You own, control or have the right to grant, now or in the future, You grant to Us a perpetual, worldwide, non-exclusive, transferable, royalty-free, irrevocable patent license, with the right to sublicense these rights to multiple tiers of sublicensees, to make, have made, use, sell, offer for sale, import and otherwise transfer the Contribution and the Contribution in combination with the Material (and portions of such combination). This license is granted only to the extent that the exercise of the licensed rights infringes such patent claims; and provided that this license is conditioned upon compliance with Section 2.3.
+
+2.3 Outbound License
+
+Based on the grant of rights in Sections 2.1 and 2.2, if We include Your Contribution in a Material, We may license the Contribution under any license, including copyleft, permissive, commercial, or proprietary licenses. As a condition on the exercise of this right, We agree to also license the Contribution under the terms of the license or licenses which We are using for the Material on the Submission Date.
+
+2.4 Moral Rights. If moral rights apply to the Contribution, to the maximum extent permitted by law, You waive and agree not to assert such moral rights against Us or our successors in interest, or any of our licensees, either direct or indirect.
+
+2.5 Our Rights. You acknowledge that We are not obligated to use Your Contribution as part of the Material and may decide to include any Contribution We consider appropriate.
+
+2.6 Reservation of Rights. Any rights not expressly licensed under this section are expressly reserved by You.
+
+3. Agreement
+
+You confirm that:
+
+(a) You have the legal authority to enter into this Agreement.
+
+(b) You own the Copyright and patent claims covering the Contribution which are required to grant the rights under Section 2.
+
+(c) The grant of rights under Section 2 does not violate any grant of rights which You have made to third parties, including Your employer. If You are an employee, You have had Your employer approve this Agreement or sign the Entity version of this document. If You are less than eighteen years old, please have Your parents or guardian sign the Agreement.
+
+(d) You have followed the instructions in https://github.com/Psiphon-Labs/psiphon-tunnel-core/blob/master/CONTRIBUTING.md, if You do not own the Copyright in the entire work of authorship Submitted.
+
+## 4. Disclaimer
+
+EXCEPT FOR THE EXPRESS WARRANTIES IN SECTION 3, THE CONTRIBUTION IS PROVIDED "AS IS". MORE PARTICULARLY, ALL EXPRESS OR IMPLIED WARRANTIES INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE EXPRESSLY DISCLAIMED BY YOU TO US. TO THE EXTENT THAT ANY SUCH WARRANTIES CANNOT BE DISCLAIMED, SUCH WARRANTY IS LIMITED IN DURATION TO THE MINIMUM PERIOD PERMITTED BY LAW.
+
+## 5. Consequential Damage Waiver
+
+TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, IN NO EVENT WILL YOU BE LIABLE FOR ANY LOSS OF PROFITS, LOSS OF ANTICIPATED SAVINGS, LOSS OF DATA, INDIRECT, SPECIAL, INCIDENTAL, CONSEQUENTIAL AND EXEMPLARY DAMAGES ARISING OUT OF THIS AGREEMENT REGARDLESS OF THE LEGAL OR EQUITABLE THEORY (CONTRACT, TORT OR OTHERWISE) UPON WHICH THE CLAIM IS BASED.
+
+## 6. Miscellaneous
+
+6.1 This Agreement will be governed by and construed in accordance with the laws of Canada excluding its conflicts of law provisions. Under certain circumstances, the governing law in this section might be superseded by the United Nations Convention on Contracts for the International Sale of Goods ("UN Convention") and the parties intend to avoid the application of the UN Convention to this Agreement and, thus, exclude the application of the UN Convention in its entirety to this Agreement.
+
+6.2 This Agreement sets out the entire agreement between You and Us for Your Contributions to Us and overrides all other agreements or understandings.
+
+6.3 If You or We assign the rights or obligations received through this Agreement to a third party, as a condition of the assignment, that third party must agree in writing to abide by all the rights and obligations in the Agreement.
+
+6.4 The failure of either party to require performance by the other party of any provision of this Agreement in one situation shall not affect the right of a party to require such performance at any time in the future. A waiver of performance under a provision in one situation shall not be considered a waiver of the performance of the provision in the future or a waiver of the provision in its entirety.
+
+6.5 If any provision of this Agreement is found void and unenforceable, such provision will be replaced to the extent possible with a provision that comes closest to the meaning of the original provision and which is enforceable. The terms and conditions set forth in this Agreement shall apply notwithstanding any failure of essential purpose of this Agreement or any limited remedy to the maximum extent possible under law.
+
+This agreement is derived from the Project Harmony CLA generator:
+http://www.harmonyagreements.org/
+
+Harmony (HA-CLA-I-ANY) Version 1.0

+ 9 - 0
CONTRIBUTING.md

@@ -0,0 +1,9 @@
+# Contributing.md
+
+## Code contributions
+
+### Contributor license agreement
+
+When submitting a pull request for the first time, you will need to agree to the contributor license agreement (for [individuals](https://github.com/Psiphon-Labs/psiphon-tunnel-core/blob/master/CLA-individual.md) or [entities](https://github.com/Psiphon-Labs/psiphon-tunnel-core/blob/master/CLA-entity.md)). To do this, in the pull request please create a file with a name like `/contributors/{github_username}.md`, and in the content of that file indicate your agreement. An example of what that file should contain can be seen in [adam-p's agreement file](https://github.com/Psiphon-Labs/psiphon-tunnel-core/blob/master/contributors/adam-p.md).
+
+(This method of CLA "signing" is borrowed from [Medium's open source project](https://github.com/medium/opensource).)

+ 1 - 3
README.md

@@ -79,6 +79,4 @@ Please see the LICENSE file.
 Contacts
 --------------------------------------------------------------------------------
 
-For more information on Psiphon Inc, please visit our web site at:
-
-[www.psiphon.ca](http://www.psiphon.ca)
+We maintain a developer mailing list at	<psiphon3-developers@googlegroups.com>. For more information about Psiphon Inc., please visit our web site at [www.psiphon.ca](http://www.psiphon.ca).

+ 9 - 0
SampleApps/Psibot/app/src/main/jniLibs/armeabi-v7a/libtun2socks.so

@@ -0,0 +1,9 @@
+2016-03-30
+
+I hereby agree to the terms of the "Psiphon Individual Contributor License Agreement", with MD5 checksum 83d54c85a43e0c0f416758779ea6740a.
+
+I furthermore declare that I am authorized and able to make this agreement and sign this declaration.
+
+Signed,
+
+Adam Pritchard https://github.com/adam-p

+ 94 - 8
psiphon/config.go

@@ -35,27 +35,27 @@ const (
 	DATA_STORE_FILENAME                            = "psiphon.boltdb"
 	CONNECTION_WORKER_POOL_SIZE                    = 10
 	TUNNEL_POOL_SIZE                               = 1
-	TUNNEL_CONNECT_TIMEOUT                         = 20 * time.Second
+	TUNNEL_CONNECT_TIMEOUT_SECONDS                 = 20
 	TUNNEL_OPERATE_SHUTDOWN_TIMEOUT                = 1 * time.Second
-	TUNNEL_PORT_FORWARD_DIAL_TIMEOUT               = 10 * time.Second
+	TUNNEL_PORT_FORWARD_DIAL_TIMEOUT_SECONDS       = 10
 	TUNNEL_SSH_KEEP_ALIVE_PAYLOAD_MAX_BYTES        = 256
 	TUNNEL_SSH_KEEP_ALIVE_PERIOD_MIN               = 60 * time.Second
 	TUNNEL_SSH_KEEP_ALIVE_PERIOD_MAX               = 120 * time.Second
-	TUNNEL_SSH_KEEP_ALIVE_PERIODIC_TIMEOUT         = 30 * time.Second
+	TUNNEL_SSH_KEEP_ALIVE_PERIODIC_TIMEOUT_SECONDS = 30
 	TUNNEL_SSH_KEEP_ALIVE_PERIODIC_INACTIVE_PERIOD = 10 * time.Second
-	TUNNEL_SSH_KEEP_ALIVE_PROBE_TIMEOUT            = 5 * time.Second
+	TUNNEL_SSH_KEEP_ALIVE_PROBE_TIMEOUT_SECONDS    = 5
 	TUNNEL_SSH_KEEP_ALIVE_PROBE_INACTIVE_PERIOD    = 10 * time.Second
 	ESTABLISH_TUNNEL_TIMEOUT_SECONDS               = 300
 	ESTABLISH_TUNNEL_WORK_TIME                     = 60 * time.Second
 	ESTABLISH_TUNNEL_PAUSE_PERIOD                  = 5 * time.Second
 	ESTABLISH_TUNNEL_SERVER_AFFINITY_GRACE_PERIOD  = 1 * time.Second
-	HTTP_PROXY_ORIGIN_SERVER_TIMEOUT               = 15 * time.Second
+	HTTP_PROXY_ORIGIN_SERVER_TIMEOUT_SECONDS       = 15
 	HTTP_PROXY_MAX_IDLE_CONNECTIONS_PER_HOST       = 50
-	FETCH_REMOTE_SERVER_LIST_TIMEOUT               = 30 * time.Second
+	FETCH_REMOTE_SERVER_LIST_TIMEOUT_SECONDS       = 30
 	FETCH_REMOTE_SERVER_LIST_RETRY_PERIOD          = 5 * time.Second
 	FETCH_REMOTE_SERVER_LIST_STALE_PERIOD          = 6 * time.Hour
 	PSIPHON_API_CLIENT_SESSION_ID_LENGTH           = 16
-	PSIPHON_API_SERVER_TIMEOUT                     = 20 * time.Second
+	PSIPHON_API_SERVER_TIMEOUT_SECONDS             = 20
 	PSIPHON_API_SHUTDOWN_SERVER_TIMEOUT            = 1 * time.Second
 	PSIPHON_API_STATUS_REQUEST_PERIOD_MIN          = 5 * time.Minute
 	PSIPHON_API_STATUS_REQUEST_PERIOD_MAX          = 10 * time.Minute
@@ -65,7 +65,7 @@ const (
 	PSIPHON_API_CONNECTED_REQUEST_PERIOD           = 24 * time.Hour
 	PSIPHON_API_CONNECTED_REQUEST_RETRY_PERIOD     = 5 * time.Second
 	PSIPHON_API_TUNNEL_STATS_MAX_COUNT             = 1000
-	FETCH_ROUTES_TIMEOUT                           = 1 * time.Minute
+	FETCH_ROUTES_TIMEOUT_SECONDS                   = 60
 	DOWNLOAD_UPGRADE_TIMEOUT                       = 15 * time.Minute
 	DOWNLOAD_UPGRADE_RETRY_PERIOD                  = 5 * time.Second
 	DOWNLOAD_UPGRADE_STALE_PERIOD                  = 6 * time.Hour
@@ -309,6 +309,52 @@ type Config struct {
 	// network information, they should not be insecurely distributed or displayed
 	// to users. Default is off.
 	EmitDiagnosticNotices bool
+
+	// TunnelConnectTimeoutSeconds specifies a single tunnel connection sequence timeout.
+	// Zero value means that connection process will not time out.
+	// If omitted default value is TUNNEL_CONNECT_TIMEOUT_SECONDS.
+	TunnelConnectTimeoutSeconds *int
+
+	// TunnelPortForwardTimeoutSeconds specifies a timeout per SSH port forward.
+	// Zero value means a port forward will not time out.
+	// If omitted default value is TUNNEL_PORT_FORWARD_DIAL_TIMEOUT_SECONDS.
+	TunnelPortForwardTimeoutSeconds *int
+
+	// TunnelSshKeepAliveProbeTimeoutSeconds specifies a timeout value for "probe"
+	// SSH keep-alive that is sent upon port forward failure.
+	// Zero value means keep-alive request will not time out.
+	// If omitted default value is TUNNEL_SSH_KEEP_ALIVE_PROBE_TIMEOUT_SECONDS.
+	TunnelSshKeepAliveProbeTimeoutSeconds *int
+
+	// TunnelSshKeepAlivePeriodicTimeoutSeconds specifies a timeout value for regular
+	// SSH keep-alives that are sent periodically.
+	// Zero value means keep-alive request will not time out.
+	// If omitted default value is TUNNEL_SSH_KEEP_ALIVE_PERIODIC_TIMEOUT_SECONDS.
+	TunnelSshKeepAlivePeriodicTimeoutSeconds *int
+
+	// FetchRemoteServerListTimeoutSeconds specifies a timeout value for remote server list
+	// HTTP request. Zero value means that request will not time out.
+	// If omitted default value is FETCH_REMOTE_SERVER_LIST_TIMEOUT_SECONDS.
+	FetchRemoteServerListTimeoutSeconds *int
+
+	// PsiphonApiServerTimeoutSeconds specifies a timeout for periodic API HTTP
+	// requests to Psiphon server such as stats, home pages, etc.
+	// Zero value means that request will not time out.
+	// If omitted default value is PSIPHON_API_SERVER_TIMEOUT_SECONDS.
+	// Note that this value is overridden for final stats requests during shutdown
+	// process in order to prevent hangs.
+	PsiphonApiServerTimeoutSeconds *int
+
+	// FetchRoutesTimeoutSeconds specifies a timeout value for split tunnel routes
+	// HTTP request. Zero value means that request will not time out.
+	// If omitted default value is FETCH_ROUTES_TIMEOUT_SECONDS.
+	FetchRoutesTimeoutSeconds *int
+
+	// HttpProxyOriginServerTimeoutSeconds specifies an HTTP response header timeout
+	// value in various HTTP relays found in httpProxy.
+	// Zero value means that request will not time out.
+	// If omitted default value  HTTP_PROXY_ORIGIN_SERVER_TIMEOUT_SECONDS.
+	HttpProxyOriginServerTimeoutSeconds *int
 }
 
 // LoadConfig parses and validates a JSON format Psiphon config JSON
@@ -394,5 +440,45 @@ func LoadConfig(configJson []byte) (*Config, error) {
 			"UpgradeDownloadUrl requires UpgradeDownloadClientVersionHeader and UpgradeDownloadFilename"))
 	}
 
+	if config.TunnelConnectTimeoutSeconds == nil {
+		defaultTunnelConnectTimeoutSeconds := TUNNEL_CONNECT_TIMEOUT_SECONDS
+		config.TunnelConnectTimeoutSeconds = &defaultTunnelConnectTimeoutSeconds
+	}
+
+	if config.TunnelPortForwardTimeoutSeconds == nil {
+		defaultTunnelPortForwardTimeoutSeconds := TUNNEL_PORT_FORWARD_DIAL_TIMEOUT_SECONDS
+		config.TunnelPortForwardTimeoutSeconds = &defaultTunnelPortForwardTimeoutSeconds
+	}
+
+	if config.TunnelSshKeepAliveProbeTimeoutSeconds == nil {
+		defaultTunnelSshKeepAliveProbeTimeoutSeconds := TUNNEL_SSH_KEEP_ALIVE_PROBE_TIMEOUT_SECONDS
+		config.TunnelSshKeepAliveProbeTimeoutSeconds = &defaultTunnelSshKeepAliveProbeTimeoutSeconds
+	}
+
+	if config.TunnelSshKeepAlivePeriodicTimeoutSeconds == nil {
+		defaultTunnelSshKeepAlivePeriodicTimeoutSeconds := TUNNEL_SSH_KEEP_ALIVE_PERIODIC_TIMEOUT_SECONDS
+		config.TunnelSshKeepAlivePeriodicTimeoutSeconds = &defaultTunnelSshKeepAlivePeriodicTimeoutSeconds
+	}
+
+	if config.FetchRemoteServerListTimeoutSeconds == nil {
+		defaultFetchRemoteServerListTimeoutSeconds := FETCH_REMOTE_SERVER_LIST_TIMEOUT_SECONDS
+		config.FetchRemoteServerListTimeoutSeconds = &defaultFetchRemoteServerListTimeoutSeconds
+	}
+
+	if config.PsiphonApiServerTimeoutSeconds == nil {
+		defaultPsiphonApiServerTimeoutSeconds := PSIPHON_API_SERVER_TIMEOUT_SECONDS
+		config.PsiphonApiServerTimeoutSeconds = &defaultPsiphonApiServerTimeoutSeconds
+	}
+
+	if config.FetchRoutesTimeoutSeconds == nil {
+		defaultFetchRoutesTimeoutSeconds := FETCH_ROUTES_TIMEOUT_SECONDS
+		config.FetchRoutesTimeoutSeconds = &defaultFetchRoutesTimeoutSeconds
+	}
+
+	if config.HttpProxyOriginServerTimeoutSeconds == nil {
+		defaultHttpProxyOriginServerTimeoutSeconds := HTTP_PROXY_ORIGIN_SERVER_TIMEOUT_SECONDS
+		config.HttpProxyOriginServerTimeoutSeconds = &defaultHttpProxyOriginServerTimeoutSeconds
+	}
+
 	return &config, nil
 }

+ 6 - 3
psiphon/config_test.go

@@ -28,6 +28,7 @@ import (
 	"net/url"
 	"strings"
 	"sync"
+	"time"
 )
 
 // HttpProxy is a HTTP server that relays HTTP requests through the Psiphon tunnel.
@@ -94,12 +95,13 @@ func NewHttpProxy(
 		return DialTCP(addr, untunneledDialConfig)
 	}
 
+	responseHeaderTimeout := time.Duration(*config.HttpProxyOriginServerTimeoutSeconds) * time.Second
 	// TODO: could HTTP proxy share a tunneled transport with URL proxy?
 	// For now, keeping them distinct just to be conservative.
 	httpProxyTunneledRelay := &http.Transport{
 		Dial:                  tunneledDialer,
 		MaxIdleConnsPerHost:   HTTP_PROXY_MAX_IDLE_CONNECTIONS_PER_HOST,
-		ResponseHeaderTimeout: HTTP_PROXY_ORIGIN_SERVER_TIMEOUT,
+		ResponseHeaderTimeout: responseHeaderTimeout,
 	}
 
 	// Note: URL proxy relays use http.Client for upstream requests, so
@@ -109,12 +111,13 @@ func NewHttpProxy(
 	urlProxyTunneledRelay := &http.Transport{
 		Dial:                  tunneledDialer,
 		MaxIdleConnsPerHost:   HTTP_PROXY_MAX_IDLE_CONNECTIONS_PER_HOST,
-		ResponseHeaderTimeout: HTTP_PROXY_ORIGIN_SERVER_TIMEOUT,
+		ResponseHeaderTimeout: responseHeaderTimeout,
 	}
 	urlProxyTunneledClient := &http.Client{
 		Transport: urlProxyTunneledRelay,
 		Jar:       nil, // TODO: cookie support for URL proxy?
 
+		// Leaving original value in the note below:
 		// Note: don't use this timeout -- it interrupts downloads of large response bodies
 		//Timeout:   HTTP_PROXY_ORIGIN_SERVER_TIMEOUT,
 	}
@@ -122,7 +125,7 @@ func NewHttpProxy(
 	urlProxyDirectRelay := &http.Transport{
 		Dial:                  directDialer,
 		MaxIdleConnsPerHost:   HTTP_PROXY_MAX_IDLE_CONNECTIONS_PER_HOST,
-		ResponseHeaderTimeout: HTTP_PROXY_ORIGIN_SERVER_TIMEOUT,
+		ResponseHeaderTimeout: responseHeaderTimeout,
 	}
 	urlProxyDirectClient := &http.Client{
 		Transport: urlProxyDirectRelay,

+ 2 - 1
psiphon/remoteServerList.go

@@ -24,6 +24,7 @@ import (
 	"fmt"
 	"io/ioutil"
 	"net/http"
+	"time"
 )
 
 // FetchRemoteServerList downloads a remote server list JSON record from
@@ -41,7 +42,7 @@ func FetchRemoteServerList(config *Config, dialConfig *DialConfig) (err error) {
 	}
 
 	httpClient, requestUrl, err := MakeUntunneledHttpsClient(
-		dialConfig, nil, config.RemoteServerListUrl, FETCH_REMOTE_SERVER_LIST_TIMEOUT)
+		dialConfig, nil, config.RemoteServerListUrl, time.Duration(*config.FetchRemoteServerListTimeoutSeconds)*time.Second)
 	if err != nil {
 		return ContextError(err)
 	}

+ 7 - 4
psiphon/serverApi.go

@@ -32,6 +32,7 @@ import (
 	"net/http"
 	"strconv"
 	"sync/atomic"
+	"time"
 
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/transferstats"
 )
@@ -424,9 +425,10 @@ func doUntunneledStatusRequest(
 		return ContextError(err)
 	}
 
+	timeout := time.Duration(*tunnel.config.PsiphonApiServerTimeoutSeconds) * time.Second
+
 	dialConfig := tunnel.untunneledDialConfig
 
-	timeout := PSIPHON_API_SERVER_TIMEOUT
 	if isShutdown {
 		timeout = PSIPHON_API_SHUTDOWN_SERVER_TIMEOUT
 
@@ -712,18 +714,19 @@ func makePsiphonHttpsClient(tunnel *Tunnel) (httpsClient *http.Client, err error
 		// TODO: check tunnel.isClosed, and apply TUNNEL_PORT_FORWARD_DIAL_TIMEOUT as in Tunnel.Dial?
 		return tunnel.sshClient.Dial("tcp", addr)
 	}
+	timeout := time.Duration(*tunnel.config.PsiphonApiServerTimeoutSeconds) * time.Second
 	dialer := NewCustomTLSDialer(
 		&CustomTLSConfig{
 			Dial:                    tunneledDialer,
-			Timeout:                 PSIPHON_API_SERVER_TIMEOUT,
+			Timeout:                 timeout,
 			VerifyLegacyCertificate: certificate,
 		})
 	transport := &http.Transport{
 		Dial: dialer,
-		ResponseHeaderTimeout: PSIPHON_API_SERVER_TIMEOUT,
+		ResponseHeaderTimeout: timeout,
 	}
 	return &http.Client{
 		Transport: transport,
-		Timeout:   PSIPHON_API_SERVER_TIMEOUT,
+		Timeout:   timeout,
 	}, nil
 }

+ 2 - 2
psiphon/serverEntry_test.go

@@ -235,11 +235,11 @@ func (classifier *SplitTunnelClassifier) getRoutes(tunnel *Tunnel) (routesData [
 	}
 	transport := &http.Transport{
 		Dial: tunneledDialer,
-		ResponseHeaderTimeout: FETCH_ROUTES_TIMEOUT,
+		ResponseHeaderTimeout: time.Duration(*tunnel.config.FetchRoutesTimeoutSeconds) * time.Second,
 	}
 	httpClient := &http.Client{
 		Transport: transport,
-		Timeout:   FETCH_ROUTES_TIMEOUT,
+		Timeout:   time.Duration(*tunnel.config.FetchRoutesTimeoutSeconds) * time.Second,
 	}
 
 	// At this time, the largest uncompressed routes data set is ~1MB. For now,

+ 18 - 12
psiphon/tunnel.go

@@ -218,9 +218,11 @@ func (tunnel *Tunnel) Dial(
 		err                error
 	}
 	resultChannel := make(chan *tunnelDialResult, 2)
-	time.AfterFunc(TUNNEL_PORT_FORWARD_DIAL_TIMEOUT, func() {
-		resultChannel <- &tunnelDialResult{nil, errors.New("tunnel dial timeout")}
-	})
+	if *tunnel.config.TunnelPortForwardTimeoutSeconds > 0 {
+		time.AfterFunc(time.Duration(*tunnel.config.TunnelPortForwardTimeoutSeconds)*time.Second, func() {
+			resultChannel <- &tunnelDialResult{nil, errors.New("tunnel dial timeout")}
+		})
+	}
 	go func() {
 		sshPortForwardConn, err := tunnel.sshClient.Dial("tcp", remoteAddr)
 		resultChannel <- &tunnelDialResult{sshPortForwardConn, err}
@@ -513,7 +515,7 @@ func dialSsh(
 	// Create the base transport: meek or direct connection
 	dialConfig := &DialConfig{
 		UpstreamProxyUrl:              config.UpstreamProxyUrl,
-		ConnectTimeout:                TUNNEL_CONNECT_TIMEOUT,
+		ConnectTimeout:                time.Duration(*config.TunnelConnectTimeoutSeconds) * time.Second,
 		PendingConns:                  pendingConns,
 		DeviceBinder:                  config.DeviceBinder,
 		DnsServerGetter:               config.DnsServerGetter,
@@ -597,9 +599,11 @@ func dialSsh(
 		err       error
 	}
 	resultChannel := make(chan *sshNewClientResult, 2)
-	time.AfterFunc(TUNNEL_CONNECT_TIMEOUT, func() {
-		resultChannel <- &sshNewClientResult{nil, errors.New("ssh dial timeout")}
-	})
+	if *config.TunnelConnectTimeoutSeconds > 0 {
+		time.AfterFunc(time.Duration(*config.TunnelConnectTimeoutSeconds)*time.Second, func() {
+			resultChannel <- &sshNewClientResult{nil, errors.New("ssh dial timeout")}
+		})
+	}
 
 	go func() {
 		// The folowing is adapted from ssh.Dial(), here using a custom conn
@@ -797,7 +801,7 @@ func (tunnel *Tunnel) operateTunnel(tunnelOwner TunnelOwner) {
 		case <-sshKeepAliveTimer.C:
 			if lastBytesReceivedTime.Add(TUNNEL_SSH_KEEP_ALIVE_PERIODIC_INACTIVE_PERIOD).Before(time.Now()) {
 				select {
-				case signalSshKeepAlive <- TUNNEL_SSH_KEEP_ALIVE_PERIODIC_TIMEOUT:
+				case signalSshKeepAlive <- time.Duration(*tunnel.config.TunnelSshKeepAlivePeriodicTimeoutSeconds) * time.Second:
 				default:
 				}
 			}
@@ -811,7 +815,7 @@ func (tunnel *Tunnel) operateTunnel(tunnelOwner TunnelOwner) {
 
 			if lastBytesReceivedTime.Add(TUNNEL_SSH_KEEP_ALIVE_PROBE_INACTIVE_PERIOD).Before(time.Now()) {
 				select {
-				case signalSshKeepAlive <- TUNNEL_SSH_KEEP_ALIVE_PROBE_TIMEOUT:
+				case signalSshKeepAlive <- time.Duration(*tunnel.config.TunnelSshKeepAliveProbeTimeoutSeconds) * time.Second:
 				default:
 				}
 			}
@@ -903,9 +907,11 @@ func sendSshKeepAlive(
 	sshClient *ssh.Client, conn net.Conn, timeout time.Duration) error {
 
 	errChannel := make(chan error, 2)
-	time.AfterFunc(timeout, func() {
-		errChannel <- TimeoutError{}
-	})
+	if timeout > 0 {
+		time.AfterFunc(timeout, func() {
+			errChannel <- TimeoutError{}
+		})
+	}
 
 	go func() {
 		// Random padding to frustrate fingerprinting