|
|
@@ -27,6 +27,7 @@ import (
|
|
|
"regexp"
|
|
|
"testing"
|
|
|
|
|
|
+ "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common"
|
|
|
mapset "github.com/deckarep/golang-set"
|
|
|
"github.com/stretchr/testify/suite"
|
|
|
)
|
|
|
@@ -88,11 +89,11 @@ func makeStatsDialer(serverID string, regexps *Regexps) func(network, addr strin
|
|
|
}
|
|
|
|
|
|
func (suite *StatsTestSuite) Test_StatsConn() {
|
|
|
- resp, err := suite.httpClient.Get("http://example.com/index.html")
|
|
|
+ resp, err := suite.httpClient.Get("http://psiphon.ca/index.html")
|
|
|
suite.Nil(err, "basic HTTP requests should succeed")
|
|
|
resp.Body.Close()
|
|
|
|
|
|
- resp, err = suite.httpClient.Get("https://example.org/index.html")
|
|
|
+ resp, err = suite.httpClient.Get("https://psiphon.ca/index.html")
|
|
|
suite.Nil(err, "basic HTTPS requests should succeed")
|
|
|
resp.Body.Close()
|
|
|
}
|
|
|
@@ -104,7 +105,7 @@ func (suite *StatsTestSuite) Test_TakeOutStatsForServer() {
|
|
|
payload := TakeOutStatsForServer(suite.serverID)
|
|
|
suite.Equal(payload, zeroPayload, "should get zero stats before any traffic")
|
|
|
|
|
|
- resp, err := suite.httpClient.Get("http://example.com/index.html")
|
|
|
+ resp, err := suite.httpClient.Get("https://psiphon.ca/index.html")
|
|
|
suite.Nil(err, "need successful http to proceed with tests")
|
|
|
resp.Body.Close()
|
|
|
|
|
|
@@ -123,16 +124,35 @@ func (suite *StatsTestSuite) Test_PutBackStatsForServer() {
|
|
|
regexp, _ := regexp.Compile(`^[a-z0-9\.]*\.(nomatch\.com)$`)
|
|
|
replace := "$1"
|
|
|
regexps := &Regexps{regexpReplace{regexp: regexp, replace: replace}}
|
|
|
+ statsDialer := makeStatsDialer(suite.serverID, regexps)
|
|
|
+
|
|
|
+ // Track all conns underlying the HTTP client, to facilitate closing them
|
|
|
+ // all and ensuring no further traffic after that point. See below.
|
|
|
+ trackConns := common.NewConns[net.Conn]()
|
|
|
+ trackConnDialer := func(network, addr string) (net.Conn, error) {
|
|
|
+ conn, err := statsDialer(network, addr)
|
|
|
+ if err == nil {
|
|
|
+ trackConns.Add(conn)
|
|
|
+ }
|
|
|
+ return conn, err
|
|
|
+ }
|
|
|
+
|
|
|
suite.httpClient = &http.Client{
|
|
|
Transport: &http.Transport{
|
|
|
- Dial: makeStatsDialer(suite.serverID, regexps),
|
|
|
+ Dial: trackConnDialer,
|
|
|
},
|
|
|
}
|
|
|
|
|
|
- resp, err := suite.httpClient.Get("http://example.com/index.html")
|
|
|
+ resp, err := suite.httpClient.Get("https://psiphon.ca/index.html")
|
|
|
suite.Nil(err, "need successful http to proceed with tests")
|
|
|
resp.Body.Close()
|
|
|
|
|
|
+ // Close all conns to ensure transfer stats recording is stopped.
|
|
|
+ // Otherwise, any additional traffic that occurs between the take-out and
|
|
|
+ // put-back may invalidate the assertion that the 2nd take-out is
|
|
|
+ // identical.
|
|
|
+ trackConns.CloseAll()
|
|
|
+
|
|
|
payloadToPutBack := TakeOutStatsForServer(suite.serverID)
|
|
|
suite.NotNil(payloadToPutBack, "should receive valid payload for valid server ID")
|
|
|
|
|
|
@@ -160,7 +180,7 @@ func (suite *StatsTestSuite) Test_NoRegexes() {
|
|
|
// Ensure there are no stats before making the no-regex request
|
|
|
_ = TakeOutStatsForServer(suite.serverID)
|
|
|
|
|
|
- resp, err := suite.httpClient.Get("http://example.com/index.html")
|
|
|
+ resp, err := suite.httpClient.Get("http://psiphon.ca/index.html")
|
|
|
suite.Nil(err, "need successful http to proceed with tests")
|
|
|
resp.Body.Close()
|
|
|
|
|
|
@@ -211,9 +231,9 @@ func (suite *StatsTestSuite) Test_MakeRegexps() {
|
|
|
func (suite *StatsTestSuite) Test_Regex() {
|
|
|
// We'll make a new client with actual regexps.
|
|
|
hostnameRegexes := []map[string]string{make(map[string]string), make(map[string]string)}
|
|
|
- hostnameRegexes[0]["regex"] = `^[a-z0-9\.]*\.(example\.com)$`
|
|
|
+ hostnameRegexes[0]["regex"] = `^[w0-9\.]*\.(psiphon\.ca)$`
|
|
|
hostnameRegexes[0]["replace"] = "$1"
|
|
|
- hostnameRegexes[1]["regex"] = `^.*example\.org$`
|
|
|
+ hostnameRegexes[1]["regex"] = `^psiphon\.ca$`
|
|
|
hostnameRegexes[1]["replace"] = "replacement"
|
|
|
regexps, _ := MakeRegexps(hostnameRegexes)
|
|
|
|
|
|
@@ -225,20 +245,20 @@ func (suite *StatsTestSuite) Test_Regex() {
|
|
|
|
|
|
// Using both HTTP and HTTPS will help us to exercise both methods of hostname parsing
|
|
|
for _, scheme := range []string{"http", "https"} {
|
|
|
- // No subdomain, so won't match regex
|
|
|
- url := fmt.Sprintf("%s://example.com/index.html", scheme)
|
|
|
+ // Won't match regex
|
|
|
+ url := fmt.Sprintf("%s://blog.psiphon.ca/index.html", scheme)
|
|
|
resp, err := suite.httpClient.Get(url)
|
|
|
suite.Nil(err)
|
|
|
resp.Body.Close()
|
|
|
|
|
|
// Will match the first regex
|
|
|
- url = fmt.Sprintf("%s://www.example.com/index.html", scheme)
|
|
|
+ url = fmt.Sprintf("%s://www.psiphon.ca/index.html", scheme)
|
|
|
resp, err = suite.httpClient.Get(url)
|
|
|
suite.Nil(err)
|
|
|
resp.Body.Close()
|
|
|
|
|
|
// Will match the second regex
|
|
|
- url = fmt.Sprintf("%s://example.org/index.html", scheme)
|
|
|
+ url = fmt.Sprintf("%s://psiphon.ca/index.html", scheme)
|
|
|
resp, err = suite.httpClient.Get(url)
|
|
|
suite.Nil(err)
|
|
|
resp.Body.Close()
|
|
|
@@ -248,7 +268,7 @@ func (suite *StatsTestSuite) Test_Regex() {
|
|
|
|
|
|
expectedHostnames := mapset.NewSet()
|
|
|
expectedHostnames.Add("(OTHER)")
|
|
|
- expectedHostnames.Add("example.com")
|
|
|
+ expectedHostnames.Add("psiphon.ca")
|
|
|
expectedHostnames.Add("replacement")
|
|
|
|
|
|
hostnames := make([]interface{}, 0)
|
|
|
@@ -258,7 +278,7 @@ func (suite *StatsTestSuite) Test_Regex() {
|
|
|
|
|
|
actualHostnames := mapset.NewSetFromSlice(hostnames)
|
|
|
|
|
|
- suite.Equal(expectedHostnames, actualHostnames, "post-regex hostnames should be processed as expecteds; %s", scheme)
|
|
|
+ suite.Equal(expectedHostnames, actualHostnames, "post-regex hostnames should be processed as expected: %s", scheme)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -272,12 +292,12 @@ func (suite *StatsTestSuite) Test_getTLSHostname() {
|
|
|
// would be to use the clientHelloMsg struct and marshal function from:
|
|
|
// https://github.com/golang/go/blob/master/src/crypto/tls/handshake_messages.go
|
|
|
|
|
|
- // TODO: Talk to a local TCP server instead of spamming example.com
|
|
|
+ // TODO: Talk to a local TCP server instead of depending on a remote site.
|
|
|
|
|
|
dialer := makeStatsDialer(suite.serverID, nil)
|
|
|
|
|
|
// Data too short
|
|
|
- conn, err := dialer("tcp", "example.com:80")
|
|
|
+ conn, err := dialer("tcp", "psiphon.ca:80")
|
|
|
suite.Nil(err)
|
|
|
b := []byte(`my bytes`)
|
|
|
n, err := conn.Write(b)
|
|
|
@@ -287,7 +307,7 @@ func (suite *StatsTestSuite) Test_getTLSHostname() {
|
|
|
suite.Nil(err)
|
|
|
|
|
|
// Data long enough, but wrong first byte
|
|
|
- conn, err = dialer("tcp", "example.com:80")
|
|
|
+ conn, err = dialer("tcp", "psiphon.ca:80")
|
|
|
suite.Nil(err)
|
|
|
b = []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
|
|
|
n, err = conn.Write(b)
|
|
|
@@ -297,7 +317,7 @@ func (suite *StatsTestSuite) Test_getTLSHostname() {
|
|
|
suite.Nil(err)
|
|
|
|
|
|
// Data long enough, correct first byte
|
|
|
- conn, err = dialer("tcp", "example.com:80")
|
|
|
+ conn, err = dialer("tcp", "psiphon.ca:80")
|
|
|
suite.Nil(err)
|
|
|
b = []byte{22, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
|
|
|
n, err = conn.Write(b)
|
|
|
@@ -307,7 +327,7 @@ func (suite *StatsTestSuite) Test_getTLSHostname() {
|
|
|
suite.Nil(err)
|
|
|
|
|
|
// Correct until after SSL version
|
|
|
- conn, err = dialer("tcp", "example.com:80")
|
|
|
+ conn, err = dialer("tcp", "psiphon.ca:80")
|
|
|
suite.Nil(err)
|
|
|
b = []byte{22, 3, 1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
|
|
|
n, err = conn.Write(b)
|
|
|
@@ -319,7 +339,7 @@ func (suite *StatsTestSuite) Test_getTLSHostname() {
|
|
|
plaintextLen := byte(70)
|
|
|
|
|
|
// Correct until after plaintext length
|
|
|
- conn, err = dialer("tcp", "example.com:80")
|
|
|
+ conn, err = dialer("tcp", "psiphon.ca:80")
|
|
|
suite.Nil(err)
|
|
|
b = []byte{22, 3, 1, 0, plaintextLen, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
|
|
|
n, err = conn.Write(b)
|
|
|
@@ -329,7 +349,7 @@ func (suite *StatsTestSuite) Test_getTLSHostname() {
|
|
|
suite.Nil(err)
|
|
|
|
|
|
// Correct until after handshake type
|
|
|
- conn, err = dialer("tcp", "example.com:80")
|
|
|
+ conn, err = dialer("tcp", "psiphon.ca:80")
|
|
|
suite.Nil(err)
|
|
|
b = []byte{22, 3, 1, 0, plaintextLen, 1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
|
|
|
n, err = conn.Write(b)
|
|
|
@@ -339,7 +359,7 @@ func (suite *StatsTestSuite) Test_getTLSHostname() {
|
|
|
suite.Nil(err)
|
|
|
|
|
|
// Correct until after handshake length
|
|
|
- conn, err = dialer("tcp", "example.com:80")
|
|
|
+ conn, err = dialer("tcp", "psiphon.ca:80")
|
|
|
suite.Nil(err)
|
|
|
b = []byte{22, 3, 1, 0, plaintextLen, 1, 0, 0, plaintextLen - 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
|
|
|
n, err = conn.Write(b)
|
|
|
@@ -349,7 +369,7 @@ func (suite *StatsTestSuite) Test_getTLSHostname() {
|
|
|
suite.Nil(err)
|
|
|
|
|
|
// Correct until after protocol version
|
|
|
- conn, err = dialer("tcp", "example.com:80")
|
|
|
+ conn, err = dialer("tcp", "psiphon.ca:80")
|
|
|
suite.Nil(err)
|
|
|
b = []byte{22, 3, 1, 0, plaintextLen, 1, 0, 0, plaintextLen - 4, 3, 3, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
|
|
|
n, err = conn.Write(b)
|