Rod Hynes 1 год назад
Родитель
Сommit
7a2f799e1f
31 измененных файлов с 422 добавлено и 414 удалено
  1. 1 0
      psiphon/common/crypto/Yawning/chacha20/chacha20_amd64.go
  2. 1 0
      psiphon/common/crypto/Yawning/chacha20/chacha20_ref.go
  3. 1 0
      psiphon/common/crypto/Yawning/chacha20/chacha20_ref_go19.go
  4. 2 3
      psiphon/common/crypto/internal/poly1305/sum_generic.go
  5. 1 0
      psiphon/common/crypto/internal/poly1305/sum_s390x.go
  6. 1 0
      psiphon/common/crypto/internal/subtle/aliasing_appengine.go
  7. 0 2
      psiphon/common/errors/errors.go
  8. 1 0
      psiphon/common/networkConfig_other.go
  9. 12 12
      psiphon/common/packetman/packetman.go
  10. 1 0
      psiphon/common/packetman/packetman_unsupported.go
  11. 4 3
      psiphon/common/quic/gquic-go/internal/utils/float16.go
  12. 1 1
      psiphon/common/quic/gquic-go/internal/wire/blocked_frame_legacy.go
  13. 1 1
      psiphon/common/quic/gquic-go/internal/wire/max_data_frame.go
  14. 1 1
      psiphon/common/quic/gquic-go/internal/wire/rst_stream_frame.go
  15. 1 0
      psiphon/common/quic/gquic-go/qerr/error_codes.go
  16. 2 0
      psiphon/common/regen/rng.go
  17. 10 10
      psiphon/common/sss/sss.go
  18. 0 2
      psiphon/common/stacktrace/stacktrace.go
  19. 0 1
      psiphon/common/wildcard/wildcard.go
  20. 6 6
      psiphon/config_test.go
  21. 349 349
      psiphon/inproxy_test.go
  22. 1 0
      psiphon/pprof.go
  23. 1 0
      psiphon/pprof_disabled.go
  24. 1 0
      psiphon/server/bpf.go
  25. 1 0
      psiphon/server/bpf_unsupported.go
  26. 4 5
      psiphon/server/dns.go
  27. 1 0
      psiphon/server/signal.go
  28. 14 15
      psiphon/upstreamproxy/go-ntlm/ntlm/helpers.go
  29. 1 1
      psiphon/upstreamproxy/go-ntlm/ntlm/keys.go
  30. 1 1
      psiphon/upstreamproxy/go-ntlm/ntlm/message_negotiate.go
  31. 1 1
      psiphon/upstreamproxy/go-ntlm/ntlm/ntlmv1.go

+ 1 - 0
psiphon/common/crypto/Yawning/chacha20/chacha20_amd64.go

@@ -5,6 +5,7 @@
 // Commons "CC0" public domain dedication. See LICENSE or
 // <http://creativecommons.org/publicdomain/zero/1.0/> for full details.
 
+//go:build amd64 && !gccgo && !appengine
 // +build amd64,!gccgo,!appengine
 
 package chacha20

+ 1 - 0
psiphon/common/crypto/Yawning/chacha20/chacha20_ref.go

@@ -5,6 +5,7 @@
 // Commons "CC0" public domain dedication. See LICENSE or
 // <http://creativecommons.org/publicdomain/zero/1.0/> for full details.
 
+//go:build !go1.9
 // +build !go1.9
 
 package chacha20

+ 1 - 0
psiphon/common/crypto/Yawning/chacha20/chacha20_ref_go19.go

@@ -5,6 +5,7 @@
 // Commons "CC0" public domain dedication. See LICENSE or
 // <http://creativecommons.org/publicdomain/zero/1.0/> for full details.
 
+//go:build go1.9
 // +build go1.9
 
 package chacha20

+ 2 - 3
psiphon/common/crypto/internal/poly1305/sum_generic.go

@@ -136,7 +136,7 @@ func shiftRightBy2(a uint128) uint128 {
 // updateGeneric absorbs msg into the state.h accumulator. For each chunk m of
 // 128 bits of message, it computes
 //
-//     h₊ = (h + m) * r  mod  2¹³⁰ - 5
+//	h₊ = (h + m) * r  mod  2¹³⁰ - 5
 //
 // If the msg length is not a multiple of TagSize, it assumes the last
 // incomplete chunk is the final one.
@@ -278,8 +278,7 @@ const (
 
 // finalize completes the modular reduction of h and computes
 //
-//     out = h + s  mod  2¹²⁸
-//
+//	out = h + s  mod  2¹²⁸
 func finalize(out *[TagSize]byte, h *[3]uint64, s *[2]uint64) {
 	h0, h1, h2 := h[0], h[1], h[2]
 

+ 1 - 0
psiphon/common/crypto/internal/poly1305/sum_s390x.go

@@ -14,6 +14,7 @@ import (
 // updateVX is an assembly implementation of Poly1305 that uses vector
 // instructions. It must only be called if the vector facility (vx) is
 // available.
+//
 //go:noescape
 func updateVX(state *macState, msg []byte)
 

+ 1 - 0
psiphon/common/crypto/internal/subtle/aliasing_appengine.go

@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build appengine
 // +build appengine
 
 // Package subtle implements functions that are often useful in cryptographic

+ 0 - 2
psiphon/common/errors/errors.go

@@ -18,10 +18,8 @@
  */
 
 /*
-
 Package errors provides error wrapping helpers that add inline, single frame
 stack trace information to error messages.
-
 */
 package errors
 

+ 1 - 0
psiphon/common/networkConfig_other.go

@@ -1,3 +1,4 @@
+//go:build !linux
 // +build !linux
 
 /*

+ 12 - 12
psiphon/common/packetman/packetman.go

@@ -23,17 +23,17 @@ variety of strategies to evade network censorship.
 
 This implementation is entirely based on and is a subset of Geneva:
 
-  Come as You Are: Helping Unmodified Clients Bypass Censorship with
-  Server-side Evasion
-  Kevin Bock, George Hughey, Louis-Henri Merino, Tania Arya, Daniel Liscinsky,
-  Regina Pogosian, Dave Levin
-  ACM SIGCOMM 2020
+	Come as You Are: Helping Unmodified Clients Bypass Censorship with
+	Server-side Evasion
+	Kevin Bock, George Hughey, Louis-Henri Merino, Tania Arya, Daniel Liscinsky,
+	Regina Pogosian, Dave Levin
+	ACM SIGCOMM 2020
 
-  Geneva: Evolving Censorship Evasion Strategies
-  Kevin Bock, George Hughey, Xiao Qiang, Dave Levin
-  ACM CCS 2019 (Conference on Computer and Communications Security)
+	Geneva: Evolving Censorship Evasion Strategies
+	Kevin Bock, George Hughey, Xiao Qiang, Dave Levin
+	ACM CCS 2019 (Conference on Computer and Communications Security)
 
-  https://github.com/Kkevsterrr/geneva
+	https://github.com/Kkevsterrr/geneva
 
 This package implements the equivilent of the Geneva "engine", which can
 execute packet manipulation strategies. It does not implement the genetic
@@ -57,7 +57,6 @@ Security: external parties can induce the server to emit a SYN-ACK, invoking
 the packet manipulation logic. External parties cannot set the transformation
 specs, and, as the input is the server-side generated SYN-ACK packet, cannot
 influence the packet manipulation with any external input parameters.
-
 */
 package packetman
 
@@ -144,11 +143,12 @@ type Config struct {
 // "TCP-payload random|<hex>"
 //
 // For example, this Geneva strategy:
-//   [TCP:flags:SA]-duplicate(tamper{TCP:flags:replace:R},tamper{TCP:flags:replace:S})-| \/
+//
+//	[TCP:flags:SA]-duplicate(tamper{TCP:flags:replace:R},tamper{TCP:flags:replace:S})-| \/
 //
 // is represented as follows (in JSON encoding):
-//   [["TCP-flags R"], ["TCP-flags S"]]
 //
+//	[["TCP-flags R"], ["TCP-flags S"]]
 //
 // Field and option values must be the expected length (see implementation).
 //

+ 1 - 0
psiphon/common/packetman/packetman_unsupported.go

@@ -1,3 +1,4 @@
+//go:build !linux
 // +build !linux
 
 /*

+ 4 - 3
psiphon/common/quic/gquic-go/internal/utils/float16.go

@@ -12,9 +12,10 @@ import (
 // bit) and denormals, but without signs, transfinites or fractions. Wire format
 // 16 bits (little-endian byte order) are split into exponent (high 5) and
 // mantissa (low 11) and decoded as:
-//   uint64_t value;
-//   if (exponent == 0) value = mantissa;
-//   else value = (mantissa | 1 << 11) << (exponent - 1)
+//
+//	uint64_t value;
+//	if (exponent == 0) value = mantissa;
+//	else value = (mantissa | 1 << 11) << (exponent - 1)
 const uFloat16ExponentBits = 5
 const uFloat16MaxExponent = (1 << uFloat16ExponentBits) - 2                                        // 30
 const uFloat16MantissaBits = 16 - uFloat16ExponentBits                                             // 11

+ 1 - 1
psiphon/common/quic/gquic-go/internal/wire/blocked_frame_legacy.go

@@ -29,7 +29,7 @@ func parseBlockedFrameLegacy(r *bytes.Reader, _ protocol.VersionNumber) (Frame,
 	return &StreamBlockedFrame{StreamID: protocol.StreamID(streamID)}, nil
 }
 
-//Write writes a BLOCKED frame
+// Write writes a BLOCKED frame
 func (f *blockedFrameLegacy) Write(b *bytes.Buffer, _ protocol.VersionNumber) error {
 	b.WriteByte(0x05)
 	utils.BigEndian.WriteUint32(b, uint32(f.StreamID))

+ 1 - 1
psiphon/common/quic/gquic-go/internal/wire/max_data_frame.go

@@ -28,7 +28,7 @@ func parseMaxDataFrame(r *bytes.Reader, version protocol.VersionNumber) (*MaxDat
 	return frame, nil
 }
 
-//Write writes a MAX_STREAM_DATA frame
+// Write writes a MAX_STREAM_DATA frame
 func (f *MaxDataFrame) Write(b *bytes.Buffer, version protocol.VersionNumber) error {
 	if !version.UsesIETFFrameFormat() {
 		// write a gQUIC WINDOW_UPDATE frame (with stream ID 0, which means connection-level there)

+ 1 - 1
psiphon/common/quic/gquic-go/internal/wire/rst_stream_frame.go

@@ -65,7 +65,7 @@ func parseRstStreamFrame(r *bytes.Reader, version protocol.VersionNumber) (*RstS
 	}, nil
 }
 
-//Write writes a RST_STREAM frame
+// Write writes a RST_STREAM frame
 func (f *RstStreamFrame) Write(b *bytes.Buffer, version protocol.VersionNumber) error {
 	b.WriteByte(0x01)
 	if version.UsesIETFFrameFormat() {

+ 1 - 0
psiphon/common/quic/gquic-go/qerr/error_codes.go

@@ -2,6 +2,7 @@ package qerr
 
 // The error codes defined by QUIC
 // Remember to run `go generate ./...` whenever the error codes change.
+//
 //go:generate stringer -type=ErrorCode
 const (
 	InternalError ErrorCode = 1

+ 2 - 0
psiphon/common/regen/rng.go

@@ -23,9 +23,11 @@ This source seeds very quickly, and only uses a single variable, so concurrent
 modification by multiple goroutines is possible.
 
 To create a seeded source:
+
 	randSource := xorShift64Source(mySeed)
 
 To create a source with the default seed:
+
 	var randSource xorShift64Source
 */
 type xorShift64Source uint64

+ 10 - 10
psiphon/common/sss/sss.go

@@ -8,19 +8,19 @@
 // random polynomial equations of degree K-1 which have an X-intercept equal to
 // the secret. Given K=3, the following equations might be generated:
 //
-//     f1(x) =  78x^2 +  19x + 42
-//     f2(x) = 128x^2 + 171x + 42
-//     f3(x) = 121x^2 +   3x + 42
-//     f4(x) =  91x^2 +  95x + 42
-//     etc.
+//	f1(x) =  78x^2 +  19x + 42
+//	f2(x) = 128x^2 + 171x + 42
+//	f3(x) = 121x^2 +   3x + 42
+//	f4(x) =  91x^2 +  95x + 42
+//	etc.
 //
 // These polynomials are then evaluated for values of X > 0:
 //
-//     f1(1) =  139
-//     f2(2) =  896
-//     f3(3) = 1140
-//     f4(4) = 1783
-//     etc.
+//	f1(1) =  139
+//	f2(2) =  896
+//	f3(3) = 1140
+//	f4(4) = 1783
+//	etc.
 //
 // These (x, y) pairs are the shares given to the parties. In order to combine
 // shares to recover the secret, these (x, y) pairs are used as the input points

+ 0 - 2
psiphon/common/stacktrace/stacktrace.go

@@ -18,9 +18,7 @@
  */
 
 /*
-
 Package stacktrace provides helpers for handling stack trace information.
-
 */
 package stacktrace
 

+ 0 - 1
psiphon/common/wildcard/wildcard.go

@@ -57,7 +57,6 @@
 // BenchmarkPrefixGlob-4                 1000000      1502 ns/op
 // BenchmarkSuffixGlob-4                 1000000      1501 ns/op
 // BenchmarkMultipleGlob-4                300000      5203 ns/op
-//
 package wildcard
 
 import (

+ 6 - 6
psiphon/config_test.go

@@ -549,12 +549,12 @@ type FileTree struct {
 //
 // For example:
 //
-//   a
-//   ├── b
-//   │   ├── 1
-//   │   └── 2
-//   └── c
-//       └── 3
+//	a
+//	├── b
+//	│   ├── 1
+//	│   └── 2
+//	└── c
+//	    └── 3
 //
 // Will result in: ["a", "a/b", "a/b/1", "a/b/2", "a/c", "a/c/3"].
 func traverseFileTree(f func(node FileTree, nodePath string), basePath string, tree FileTree) {

+ 349 - 349
psiphon/inproxy_test.go

@@ -20,426 +20,426 @@
 package psiphon
 
 import (
-    "encoding/json"
-    "io/ioutil"
-    "os"
-    "regexp"
-    "testing"
-
-    "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/errors"
-    "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/inproxy"
-    "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/parameters"
-    "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/prng"
-    "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/resolver"
+	"encoding/json"
+	"io/ioutil"
+	"os"
+	"regexp"
+	"testing"
+
+	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/errors"
+	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/inproxy"
+	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/parameters"
+	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/prng"
+	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/resolver"
 )
 
 func TestInproxyComponents(t *testing.T) {
 
-    // This is a unit test of the in-proxy components internals, such as
-    // replay; actual in-proxy broker round trips are exercised in the
-    // psiphon/server end-to-end tests.
+	// This is a unit test of the in-proxy components internals, such as
+	// replay; actual in-proxy broker round trips are exercised in the
+	// psiphon/server end-to-end tests.
 
-    err := runInproxyBrokerDialParametersTest()
-    if err != nil {
-        t.Fatalf(errors.Trace(err).Error())
-    }
+	err := runInproxyBrokerDialParametersTest()
+	if err != nil {
+		t.Fatalf(errors.Trace(err).Error())
+	}
 
-    err = runInproxySTUNDialParametersTest()
-    if err != nil {
-        t.Fatalf(errors.Trace(err).Error())
-    }
+	err = runInproxySTUNDialParametersTest()
+	if err != nil {
+		t.Fatalf(errors.Trace(err).Error())
+	}
 
-    err = runInproxyNATStateTest()
-    if err != nil {
-        t.Fatalf(errors.Trace(err).Error())
-    }
+	err = runInproxyNATStateTest()
+	if err != nil {
+		t.Fatalf(errors.Trace(err).Error())
+	}
 
-    // TODO: test inproxyUDPConn multiplexed IPv6Synthesizer
+	// TODO: test inproxyUDPConn multiplexed IPv6Synthesizer
 }
 
 func runInproxyBrokerDialParametersTest() error {
 
-    testDataDirName, err := ioutil.TempDir("", "psiphon-inproxy-broker-test")
-    if err != nil {
-        return errors.Trace(err)
-    }
-    defer os.RemoveAll(testDataDirName)
-
-    isProxy := false
-    propagationChannelID := prng.HexString(8)
-    sponsorID := prng.HexString(8)
-    networkID := "NETWORK1"
-    addressRegex := `[a-z0-9]{5,10}\.example\.org`
-    commonCompartmentID, _ := inproxy.MakeID()
-    personalCompartmentID, _ := inproxy.MakeID()
-    commonCompartmentIDs := []string{commonCompartmentID.String()}
-    personalCompartmentIDs := []string{personalCompartmentID.String()}
-    privateKey, _ := inproxy.GenerateSessionPrivateKey()
-    publicKey, _ := privateKey.GetPublicKey()
-    obfuscationSecret, _ := inproxy.GenerateRootObfuscationSecret()
-    brokerSpecs := []*parameters.InproxyBrokerSpec{
-        &parameters.InproxyBrokerSpec{
-            BrokerPublicKey:             publicKey.String(),
-            BrokerRootObfuscationSecret: obfuscationSecret.String(),
-            BrokerFrontingSpecs: []*parameters.FrontingSpec{
-                &parameters.FrontingSpec{
-                    FrontingProviderID: prng.HexString(8),
-                    Addresses:          []string{addressRegex},
-                    VerifyServerName:   "example.org",
-                    Host:               "example.org",
-                },
-            },
-        },
-    }
-    retainFailed := float64(0.0)
-
-    config := &Config{
-        DataRootDirectory:    testDataDirName,
-        PropagationChannelId: propagationChannelID,
-        SponsorId:            sponsorID,
-        NetworkID:            networkID,
-    }
-    err = config.Commit(false)
-    if err != nil {
-        return errors.Trace(err)
-    }
-
-    err = OpenDataStore(config)
-    if err != nil {
-        return errors.Trace(err)
-    }
-    defer CloseDataStore()
-
-    manager := NewInproxyBrokerClientManager(config, isProxy)
-
-    // Test: no broker specs
-
-    _, _, err = manager.GetBrokerClient(networkID)
-    if err == nil {
-        return errors.TraceNew("unexpected success")
-    }
-
-    // Test: select broker and common compartment IDs
-
-    config = &Config{
-        DataRootDirectory:           testDataDirName,
-        PropagationChannelId:        propagationChannelID,
-        SponsorId:                   sponsorID,
-        NetworkID:                   networkID,
-        InproxyBrokerSpecs:          brokerSpecs,
-        InproxyCommonCompartmentIDs: commonCompartmentIDs,
-        InproxyReplayBrokerRetainFailedProbability: &retainFailed,
-    }
-    err = config.Commit(false)
-    if err != nil {
-        return errors.Trace(err)
-    }
-    config.SetResolver(resolver.NewResolver(&resolver.NetworkConfig{}, networkID))
-
-    manager = NewInproxyBrokerClientManager(config, isProxy)
-
-    brokerClient, brokerDialParams, err := manager.GetBrokerClient(networkID)
-    if err != nil {
-        return errors.Trace(err)
-    }
-
-    if !regexp.MustCompile(addressRegex).Copy().Match(
-        []byte(brokerDialParams.FrontingDialAddress)) {
-        return errors.TraceNew("unexpected FrontingDialAddress")
-    }
-
-    if len(brokerClient.GetBrokerDialCoordinator().CommonCompartmentIDs()) != 1 ||
-        brokerClient.GetBrokerDialCoordinator().CommonCompartmentIDs()[0].String() !=
-            commonCompartmentID.String() {
-        return errors.TraceNew("unexpected compartment IDs")
-    }
-
-    _ = brokerDialParams.GetMetrics()
-
-    // Test: replay on success
-
-    previousFrontingDialAddress := brokerDialParams.FrontingDialAddress
-    previousTLSProfile := brokerDialParams.TLSProfile
-
-    roundTripper, err := brokerClient.GetBrokerDialCoordinator().BrokerClientRoundTripper()
-    if err != nil {
-        return errors.Trace(err)
-    }
-
-    brokerClient.GetBrokerDialCoordinator().BrokerClientRoundTripperSucceeded(roundTripper)
-
-    manager = NewInproxyBrokerClientManager(config, isProxy)
-
-    brokerClient, brokerDialParams, err = manager.GetBrokerClient(networkID)
-    if err != nil {
-        return errors.Trace(err)
-    }
-
-    if !brokerDialParams.isReplay {
-        return errors.TraceNew("unexpected non-replay")
-    }
-
-    if brokerDialParams.FrontingDialAddress != previousFrontingDialAddress {
-        return errors.TraceNew("unexpected replayed FrontingDialAddress")
-    }
-
-    if brokerDialParams.TLSProfile != previousTLSProfile {
-        return errors.TraceNew("unexpected replayed TLSProfile")
-    }
+	testDataDirName, err := ioutil.TempDir("", "psiphon-inproxy-broker-test")
+	if err != nil {
+		return errors.Trace(err)
+	}
+	defer os.RemoveAll(testDataDirName)
+
+	isProxy := false
+	propagationChannelID := prng.HexString(8)
+	sponsorID := prng.HexString(8)
+	networkID := "NETWORK1"
+	addressRegex := `[a-z0-9]{5,10}\.example\.org`
+	commonCompartmentID, _ := inproxy.MakeID()
+	personalCompartmentID, _ := inproxy.MakeID()
+	commonCompartmentIDs := []string{commonCompartmentID.String()}
+	personalCompartmentIDs := []string{personalCompartmentID.String()}
+	privateKey, _ := inproxy.GenerateSessionPrivateKey()
+	publicKey, _ := privateKey.GetPublicKey()
+	obfuscationSecret, _ := inproxy.GenerateRootObfuscationSecret()
+	brokerSpecs := []*parameters.InproxyBrokerSpec{
+		&parameters.InproxyBrokerSpec{
+			BrokerPublicKey:             publicKey.String(),
+			BrokerRootObfuscationSecret: obfuscationSecret.String(),
+			BrokerFrontingSpecs: []*parameters.FrontingSpec{
+				&parameters.FrontingSpec{
+					FrontingProviderID: prng.HexString(8),
+					Addresses:          []string{addressRegex},
+					VerifyServerName:   "example.org",
+					Host:               "example.org",
+				},
+			},
+		},
+	}
+	retainFailed := float64(0.0)
+
+	config := &Config{
+		DataRootDirectory:    testDataDirName,
+		PropagationChannelId: propagationChannelID,
+		SponsorId:            sponsorID,
+		NetworkID:            networkID,
+	}
+	err = config.Commit(false)
+	if err != nil {
+		return errors.Trace(err)
+	}
+
+	err = OpenDataStore(config)
+	if err != nil {
+		return errors.Trace(err)
+	}
+	defer CloseDataStore()
+
+	manager := NewInproxyBrokerClientManager(config, isProxy)
+
+	// Test: no broker specs
+
+	_, _, err = manager.GetBrokerClient(networkID)
+	if err == nil {
+		return errors.TraceNew("unexpected success")
+	}
+
+	// Test: select broker and common compartment IDs
+
+	config = &Config{
+		DataRootDirectory:           testDataDirName,
+		PropagationChannelId:        propagationChannelID,
+		SponsorId:                   sponsorID,
+		NetworkID:                   networkID,
+		InproxyBrokerSpecs:          brokerSpecs,
+		InproxyCommonCompartmentIDs: commonCompartmentIDs,
+		InproxyReplayBrokerRetainFailedProbability: &retainFailed,
+	}
+	err = config.Commit(false)
+	if err != nil {
+		return errors.Trace(err)
+	}
+	config.SetResolver(resolver.NewResolver(&resolver.NetworkConfig{}, networkID))
+
+	manager = NewInproxyBrokerClientManager(config, isProxy)
+
+	brokerClient, brokerDialParams, err := manager.GetBrokerClient(networkID)
+	if err != nil {
+		return errors.Trace(err)
+	}
+
+	if !regexp.MustCompile(addressRegex).Copy().Match(
+		[]byte(brokerDialParams.FrontingDialAddress)) {
+		return errors.TraceNew("unexpected FrontingDialAddress")
+	}
+
+	if len(brokerClient.GetBrokerDialCoordinator().CommonCompartmentIDs()) != 1 ||
+		brokerClient.GetBrokerDialCoordinator().CommonCompartmentIDs()[0].String() !=
+			commonCompartmentID.String() {
+		return errors.TraceNew("unexpected compartment IDs")
+	}
+
+	_ = brokerDialParams.GetMetrics()
+
+	// Test: replay on success
+
+	previousFrontingDialAddress := brokerDialParams.FrontingDialAddress
+	previousTLSProfile := brokerDialParams.TLSProfile
+
+	roundTripper, err := brokerClient.GetBrokerDialCoordinator().BrokerClientRoundTripper()
+	if err != nil {
+		return errors.Trace(err)
+	}
+
+	brokerClient.GetBrokerDialCoordinator().BrokerClientRoundTripperSucceeded(roundTripper)
+
+	manager = NewInproxyBrokerClientManager(config, isProxy)
+
+	brokerClient, brokerDialParams, err = manager.GetBrokerClient(networkID)
+	if err != nil {
+		return errors.Trace(err)
+	}
+
+	if !brokerDialParams.isReplay {
+		return errors.TraceNew("unexpected non-replay")
+	}
+
+	if brokerDialParams.FrontingDialAddress != previousFrontingDialAddress {
+		return errors.TraceNew("unexpected replayed FrontingDialAddress")
+	}
+
+	if brokerDialParams.TLSProfile != previousTLSProfile {
+		return errors.TraceNew("unexpected replayed TLSProfile")
+	}
 
-    _ = brokerDialParams.GetMetrics()
+	_ = brokerDialParams.GetMetrics()
 
-    // Test: manager's broker client and dial parameters reinitialized after
-    // network ID change
+	// Test: manager's broker client and dial parameters reinitialized after
+	// network ID change
 
-    previousBrokerClient := brokerClient
-    previousNetworkID := networkID
-    networkID = "NETWORK2"
-    config.networkIDGetter = newStaticNetworkGetter(networkID)
-    config.SetResolver(resolver.NewResolver(&resolver.NetworkConfig{}, networkID))
+	previousBrokerClient := brokerClient
+	previousNetworkID := networkID
+	networkID = "NETWORK2"
+	config.networkIDGetter = newStaticNetworkGetter(networkID)
+	config.SetResolver(resolver.NewResolver(&resolver.NetworkConfig{}, networkID))
 
-    brokerClient, brokerDialParams, err = manager.GetBrokerClient(networkID)
-    if err != nil {
-        return errors.Trace(err)
-    }
+	brokerClient, brokerDialParams, err = manager.GetBrokerClient(networkID)
+	if err != nil {
+		return errors.Trace(err)
+	}
 
-    if brokerClient == previousBrokerClient {
-        return errors.TraceNew("unexpected brokerClient")
-    }
+	if brokerClient == previousBrokerClient {
+		return errors.TraceNew("unexpected brokerClient")
+	}
 
-    if brokerDialParams.isReplay {
-        return errors.TraceNew("unexpected replay")
-    }
+	if brokerDialParams.isReplay {
+		return errors.TraceNew("unexpected replay")
+	}
 
-    if brokerDialParams.FrontingDialAddress == previousFrontingDialAddress {
-        return errors.TraceNew("unexpected non-replayed FrontingDialAddress")
-    }
+	if brokerDialParams.FrontingDialAddress == previousFrontingDialAddress {
+		return errors.TraceNew("unexpected non-replayed FrontingDialAddress")
+	}
 
-    _ = brokerDialParams.GetMetrics()
+	_ = brokerDialParams.GetMetrics()
 
-    // Test: another replay after switch back to previous network ID
+	// Test: another replay after switch back to previous network ID
 
-    networkID = previousNetworkID
-    config.networkIDGetter = newStaticNetworkGetter(networkID)
+	networkID = previousNetworkID
+	config.networkIDGetter = newStaticNetworkGetter(networkID)
 
-    brokerClient, brokerDialParams, err = manager.GetBrokerClient(networkID)
-    if err != nil {
-        return errors.Trace(err)
-    }
+	brokerClient, brokerDialParams, err = manager.GetBrokerClient(networkID)
+	if err != nil {
+		return errors.Trace(err)
+	}
 
-    if !brokerDialParams.isReplay {
-        return errors.TraceNew("unexpected non-replay")
-    }
+	if !brokerDialParams.isReplay {
+		return errors.TraceNew("unexpected non-replay")
+	}
 
-    if brokerDialParams.FrontingDialAddress != previousFrontingDialAddress {
-        return errors.TraceNew("unexpected replayed FrontingDialAddress")
-    }
+	if brokerDialParams.FrontingDialAddress != previousFrontingDialAddress {
+		return errors.TraceNew("unexpected replayed FrontingDialAddress")
+	}
 
-    if brokerDialParams.TLSProfile != previousTLSProfile {
-        return errors.TraceNew("unexpected replayed TLSProfile")
-    }
+	if brokerDialParams.TLSProfile != previousTLSProfile {
+		return errors.TraceNew("unexpected replayed TLSProfile")
+	}
 
-    _ = brokerDialParams.GetMetrics()
+	_ = brokerDialParams.GetMetrics()
 
-    // Test: clear replay
+	// Test: clear replay
 
-    roundTripper, err = brokerClient.GetBrokerDialCoordinator().BrokerClientRoundTripper()
-    if err != nil {
-        return errors.Trace(err)
-    }
+	roundTripper, err = brokerClient.GetBrokerDialCoordinator().BrokerClientRoundTripper()
+	if err != nil {
+		return errors.Trace(err)
+	}
 
-    brokerClient.GetBrokerDialCoordinator().BrokerClientRoundTripperFailed(roundTripper)
+	brokerClient.GetBrokerDialCoordinator().BrokerClientRoundTripperFailed(roundTripper)
 
-    manager = NewInproxyBrokerClientManager(config, isProxy)
+	manager = NewInproxyBrokerClientManager(config, isProxy)
 
-    brokerClient, brokerDialParams, err = manager.GetBrokerClient(networkID)
-    if err != nil {
-        return errors.Trace(err)
-    }
+	brokerClient, brokerDialParams, err = manager.GetBrokerClient(networkID)
+	if err != nil {
+		return errors.Trace(err)
+	}
 
-    if brokerDialParams.isReplay {
-        return errors.TraceNew("unexpected replay")
-    }
+	if brokerDialParams.isReplay {
+		return errors.TraceNew("unexpected replay")
+	}
 
-    if brokerDialParams.FrontingDialAddress == previousFrontingDialAddress {
-        return errors.TraceNew("unexpected non-replayed FrontingDialAddress")
-    }
+	if brokerDialParams.FrontingDialAddress == previousFrontingDialAddress {
+		return errors.TraceNew("unexpected non-replayed FrontingDialAddress")
+	}
 
-    _ = brokerDialParams.GetMetrics()
+	_ = brokerDialParams.GetMetrics()
 
-    // Test: no common compartment IDs sent when personal ID is set
+	// Test: no common compartment IDs sent when personal ID is set
 
-    config.InproxyClientPersonalCompartmentIDs = personalCompartmentIDs
-    config.InproxyProxyPersonalCompartmentIDs = personalCompartmentIDs
+	config.InproxyClientPersonalCompartmentIDs = personalCompartmentIDs
+	config.InproxyProxyPersonalCompartmentIDs = personalCompartmentIDs
 
-    manager = NewInproxyBrokerClientManager(config, isProxy)
+	manager = NewInproxyBrokerClientManager(config, isProxy)
 
-    brokerClient, brokerDialParams, err = manager.GetBrokerClient(networkID)
-    if err != nil {
-        return errors.Trace(err)
-    }
+	brokerClient, brokerDialParams, err = manager.GetBrokerClient(networkID)
+	if err != nil {
+		return errors.Trace(err)
+	}
 
-    if len(brokerClient.GetBrokerDialCoordinator().CommonCompartmentIDs()) != 0 ||
-        len(brokerClient.GetBrokerDialCoordinator().PersonalCompartmentIDs()) != 1 ||
-        brokerClient.GetBrokerDialCoordinator().PersonalCompartmentIDs()[0].String() !=
-            personalCompartmentID.String() {
-        return errors.TraceNew("unexpected compartment IDs")
-    }
+	if len(brokerClient.GetBrokerDialCoordinator().CommonCompartmentIDs()) != 0 ||
+		len(brokerClient.GetBrokerDialCoordinator().PersonalCompartmentIDs()) != 1 ||
+		brokerClient.GetBrokerDialCoordinator().PersonalCompartmentIDs()[0].String() !=
+			personalCompartmentID.String() {
+		return errors.TraceNew("unexpected compartment IDs")
+	}
 
-    // Test: use persisted common compartment IDs
+	// Test: use persisted common compartment IDs
 
-    config = &Config{
-        PropagationChannelId: propagationChannelID,
-        SponsorId:            sponsorID,
-        NetworkID:            networkID,
-    }
-    config.InproxyBrokerSpecs = brokerSpecs
-    config.InproxyCommonCompartmentIDs = nil
-    err = config.Commit(false)
-    if err != nil {
-        return errors.Trace(err)
-    }
-    config.SetResolver(resolver.NewResolver(&resolver.NetworkConfig{}, networkID))
+	config = &Config{
+		PropagationChannelId: propagationChannelID,
+		SponsorId:            sponsorID,
+		NetworkID:            networkID,
+	}
+	config.InproxyBrokerSpecs = brokerSpecs
+	config.InproxyCommonCompartmentIDs = nil
+	err = config.Commit(false)
+	if err != nil {
+		return errors.Trace(err)
+	}
+	config.SetResolver(resolver.NewResolver(&resolver.NetworkConfig{}, networkID))
 
-    manager = NewInproxyBrokerClientManager(config, isProxy)
+	manager = NewInproxyBrokerClientManager(config, isProxy)
 
-    brokerClient, brokerDialParams, err = manager.GetBrokerClient(networkID)
-    if err != nil {
-        return errors.Trace(err)
-    }
+	brokerClient, brokerDialParams, err = manager.GetBrokerClient(networkID)
+	if err != nil {
+		return errors.Trace(err)
+	}
 
-    if len(brokerClient.GetBrokerDialCoordinator().CommonCompartmentIDs()) != 1 ||
-        brokerClient.GetBrokerDialCoordinator().CommonCompartmentIDs()[0].String() !=
-            commonCompartmentID.String() {
-        return errors.TraceNew("unexpected compartment IDs")
-    }
+	if len(brokerClient.GetBrokerDialCoordinator().CommonCompartmentIDs()) != 1 ||
+		brokerClient.GetBrokerDialCoordinator().CommonCompartmentIDs()[0].String() !=
+			commonCompartmentID.String() {
+		return errors.TraceNew("unexpected compartment IDs")
+	}
 
-    _ = brokerDialParams.GetMetrics()
+	_ = brokerDialParams.GetMetrics()
 
-    return nil
+	return nil
 }
 
 func runInproxySTUNDialParametersTest() error {
 
-    testDataDirName, err := ioutil.TempDir("", "psiphon-inproxy-stun-test")
-    if err != nil {
-        return errors.Trace(err)
-    }
-    defer os.RemoveAll(testDataDirName)
-
-    propagationChannelID := prng.HexString(8)
-    sponsorID := prng.HexString(8)
-    networkID := "NETWORK1"
-    stunServerAddresses := []string{"example.org"}
-
-    config := &Config{
-        DataRootDirectory:                 testDataDirName,
-        PropagationChannelId:              propagationChannelID,
-        SponsorId:                         sponsorID,
-        NetworkID:                         networkID,
-        InproxySTUNServerAddresses:        stunServerAddresses,
-        InproxySTUNServerAddressesRFC5780: stunServerAddresses,
-    }
-    err = config.Commit(false)
-    if err != nil {
-        return errors.Trace(err)
-    }
-    config.SetResolver(resolver.NewResolver(&resolver.NetworkConfig{}, networkID))
-
-    p := config.GetParameters().Get()
-    defer p.Close()
-
-    dialParams, err := MakeInproxySTUNDialParameters(config, p, false)
-    if err != nil {
-        return errors.Trace(err)
-    }
-
-    _ = dialParams.GetMetrics()
-
-    dialParamsJSON, err := json.Marshal(dialParams)
-    if err != nil {
-        return errors.Trace(err)
-    }
-
-    var replayDialParams *InproxySTUNDialParameters
-    err = json.Unmarshal(dialParamsJSON, &replayDialParams)
-    if err != nil {
-        return errors.Trace(err)
-    }
-
-    replayDialParams.Prepare()
-
-    _ = replayDialParams.GetMetrics()
-
-    return nil
+	testDataDirName, err := ioutil.TempDir("", "psiphon-inproxy-stun-test")
+	if err != nil {
+		return errors.Trace(err)
+	}
+	defer os.RemoveAll(testDataDirName)
+
+	propagationChannelID := prng.HexString(8)
+	sponsorID := prng.HexString(8)
+	networkID := "NETWORK1"
+	stunServerAddresses := []string{"example.org"}
+
+	config := &Config{
+		DataRootDirectory:                 testDataDirName,
+		PropagationChannelId:              propagationChannelID,
+		SponsorId:                         sponsorID,
+		NetworkID:                         networkID,
+		InproxySTUNServerAddresses:        stunServerAddresses,
+		InproxySTUNServerAddressesRFC5780: stunServerAddresses,
+	}
+	err = config.Commit(false)
+	if err != nil {
+		return errors.Trace(err)
+	}
+	config.SetResolver(resolver.NewResolver(&resolver.NetworkConfig{}, networkID))
+
+	p := config.GetParameters().Get()
+	defer p.Close()
+
+	dialParams, err := MakeInproxySTUNDialParameters(config, p, false)
+	if err != nil {
+		return errors.Trace(err)
+	}
+
+	_ = dialParams.GetMetrics()
+
+	dialParamsJSON, err := json.Marshal(dialParams)
+	if err != nil {
+		return errors.Trace(err)
+	}
+
+	var replayDialParams *InproxySTUNDialParameters
+	err = json.Unmarshal(dialParamsJSON, &replayDialParams)
+	if err != nil {
+		return errors.Trace(err)
+	}
+
+	replayDialParams.Prepare()
+
+	_ = replayDialParams.GetMetrics()
+
+	return nil
 }
 
 func runInproxyNATStateTest() error {
 
-    propagationChannelID := prng.HexString(8)
-    sponsorID := prng.HexString(8)
-    networkID := "NETWORK1"
+	propagationChannelID := prng.HexString(8)
+	sponsorID := prng.HexString(8)
+	networkID := "NETWORK1"
 
-    config := &Config{
-        PropagationChannelId: propagationChannelID,
-        SponsorId:            sponsorID,
-        NetworkID:            networkID,
-    }
-    err := config.Commit(false)
-    if err != nil {
-        return errors.Trace(err)
-    }
+	config := &Config{
+		PropagationChannelId: propagationChannelID,
+		SponsorId:            sponsorID,
+		NetworkID:            networkID,
+	}
+	err := config.Commit(false)
+	if err != nil {
+		return errors.Trace(err)
+	}
 
-    manager := NewInproxyNATStateManager(config)
+	manager := NewInproxyNATStateManager(config)
 
-    // Test: set values stored and cached
+	// Test: set values stored and cached
 
-    manager.setNATType(networkID, inproxy.NATTypeSymmetric)
-    manager.setPortMappingTypes(networkID, inproxy.PortMappingTypes{inproxy.PortMappingTypeUPnP})
+	manager.setNATType(networkID, inproxy.NATTypeSymmetric)
+	manager.setPortMappingTypes(networkID, inproxy.PortMappingTypes{inproxy.PortMappingTypeUPnP})
 
-    if manager.getNATType(networkID) != inproxy.NATTypeSymmetric {
-        return errors.TraceNew("unexpected NAT type")
-    }
+	if manager.getNATType(networkID) != inproxy.NATTypeSymmetric {
+		return errors.TraceNew("unexpected NAT type")
+	}
 
-    portMappingTypes := manager.getPortMappingTypes(networkID)
-    if len(portMappingTypes) != 1 || portMappingTypes[0] != inproxy.PortMappingTypeUPnP {
-        return errors.TraceNew("unexpected port mapping types")
-    }
+	portMappingTypes := manager.getPortMappingTypes(networkID)
+	if len(portMappingTypes) != 1 || portMappingTypes[0] != inproxy.PortMappingTypeUPnP {
+		return errors.TraceNew("unexpected port mapping types")
+	}
 
-    // Test: set values ignored when network ID is changing
+	// Test: set values ignored when network ID is changing
 
-    otherNetworkID := "NETWORK2"
+	otherNetworkID := "NETWORK2"
 
-    manager.setNATType(otherNetworkID, inproxy.NATTypePortRestrictedCone)
-    manager.setPortMappingTypes(otherNetworkID, inproxy.PortMappingTypes{inproxy.PortMappingTypePMP})
+	manager.setNATType(otherNetworkID, inproxy.NATTypePortRestrictedCone)
+	manager.setPortMappingTypes(otherNetworkID, inproxy.PortMappingTypes{inproxy.PortMappingTypePMP})
 
-    if manager.getNATType(networkID) != inproxy.NATTypeSymmetric {
-        return errors.TraceNew("unexpected NAT type")
-    }
+	if manager.getNATType(networkID) != inproxy.NATTypeSymmetric {
+		return errors.TraceNew("unexpected NAT type")
+	}
 
-    portMappingTypes = manager.getPortMappingTypes(networkID)
-    if len(portMappingTypes) != 1 || portMappingTypes[0] != inproxy.PortMappingTypeUPnP {
-        return errors.TraceNew("unexpected port mapping types")
-    }
+	portMappingTypes = manager.getPortMappingTypes(networkID)
+	if len(portMappingTypes) != 1 || portMappingTypes[0] != inproxy.PortMappingTypeUPnP {
+		return errors.TraceNew("unexpected port mapping types")
+	}
 
-    // Test: reset
+	// Test: reset
 
-    networkID = "NETWORK2"
-    config.networkIDGetter = newStaticNetworkGetter(networkID)
+	networkID = "NETWORK2"
+	config.networkIDGetter = newStaticNetworkGetter(networkID)
 
-    manager.reset()
+	manager.reset()
 
-    if manager.networkID != networkID {
-        return errors.TraceNew("unexpected network ID")
-    }
+	if manager.networkID != networkID {
+		return errors.TraceNew("unexpected network ID")
+	}
 
-    if manager.getNATType(networkID) != inproxy.NATTypeUnknown {
-        return errors.TraceNew("unexpected NAT type")
-    }
+	if manager.getNATType(networkID) != inproxy.NATTypeUnknown {
+		return errors.TraceNew("unexpected NAT type")
+	}
 
-    if len(manager.getPortMappingTypes(networkID)) != 0 {
-        return errors.TraceNew("unexpected port mapping types")
-    }
+	if len(manager.getPortMappingTypes(networkID)) != 0 {
+		return errors.TraceNew("unexpected port mapping types")
+	}
 
-    return nil
+	return nil
 }

+ 1 - 0
psiphon/pprof.go

@@ -1,3 +1,4 @@
+//go:build PSIPHON_RUN_PPROF
 // +build PSIPHON_RUN_PPROF
 
 /*

+ 1 - 0
psiphon/pprof_disabled.go

@@ -1,3 +1,4 @@
+//go:build !PSIPHON_RUN_PPROF
 // +build !PSIPHON_RUN_PPROF
 
 /*

+ 1 - 0
psiphon/server/bpf.go

@@ -1,3 +1,4 @@
+//go:build linux
 // +build linux
 
 /*

+ 1 - 0
psiphon/server/bpf_unsupported.go

@@ -1,3 +1,4 @@
+//go:build !linux
 // +build !linux
 
 /*

+ 4 - 5
psiphon/server/dns.go

@@ -64,12 +64,11 @@ type DNSResolver struct {
 // more than 5 seconds before the last Get(), which is similar to
 // frequencies in other implementations:
 //
-// - https://golang.org/src/net/dnsclient_unix.go,
-//   resolverConfig.tryUpdate: 5 seconds
-//
-// - https://github.com/ambrop72/badvpn/blob/master/udpgw/udpgw.c,
-//   maybe_update_dns: 2 seconds
+//   - https://golang.org/src/net/dnsclient_unix.go,
+//     resolverConfig.tryUpdate: 5 seconds
 //
+//   - https://github.com/ambrop72/badvpn/blob/master/udpgw/udpgw.c,
+//     maybe_update_dns: 2 seconds
 func NewDNSResolver(defaultResolver string) (*DNSResolver, error) {
 
 	dns := &DNSResolver{

+ 1 - 0
psiphon/server/signal.go

@@ -1,3 +1,4 @@
+//go:build !windows
 // +build !windows
 
 /*

+ 14 - 15
psiphon/upstreamproxy/go-ntlm/ntlm/helpers.go

@@ -5,8 +5,8 @@ package ntlm
 import (
 	"bytes"
 	"crypto/rand"
-	"unicode/utf16"
 	"encoding/binary"
+	"unicode/utf16"
 )
 
 // Concatenate two byte slices into a new slice
@@ -67,23 +67,22 @@ func utf16FromString(s string) []byte {
 
 // Convert a UTF16 string to UTF8 string for Go usage
 func utf16ToString(bytes []byte) string {
-       var data []uint16
+	var data []uint16
 
-       // NOTE: This is definitely not the best way to do this, but when I tried using a buffer.Read I could not get it to work
-       for offset := 0; offset < len(bytes); offset = offset + 2 {
-               i := binary.LittleEndian.Uint16(bytes[offset : offset+2])
-               data = append(data, i)
-       }
+	// NOTE: This is definitely not the best way to do this, but when I tried using a buffer.Read I could not get it to work
+	for offset := 0; offset < len(bytes); offset = offset + 2 {
+		i := binary.LittleEndian.Uint16(bytes[offset : offset+2])
+		data = append(data, i)
+	}
 
-       return string(utf16.Decode(data))
+	return string(utf16.Decode(data))
 }
 
 func uint32ToBytes(v uint32) []byte {
-       bytes := make([]byte, 4)
-       bytes[0] = byte(v & 0xff)
-       bytes[1] = byte((v >> 8) & 0xff)
-       bytes[2] = byte((v >> 16) & 0xff)
-       bytes[3] = byte((v >> 24) & 0xff)
-       return bytes
+	bytes := make([]byte, 4)
+	bytes[0] = byte(v & 0xff)
+	bytes[1] = byte((v >> 8) & 0xff)
+	bytes[2] = byte((v >> 16) & 0xff)
+	bytes[3] = byte((v >> 24) & 0xff)
+	return bytes
 }
-

+ 1 - 1
psiphon/upstreamproxy/go-ntlm/ntlm/keys.go

@@ -41,7 +41,7 @@ func signKey(flags uint32, randomSessionKey []byte, mode string) (signKey []byte
 	return
 }
 
-// 	Define SEALKEY(NegotiateFlags, RandomSessionKey, Mode) as
+// Define SEALKEY(NegotiateFlags, RandomSessionKey, Mode) as
 func sealKey(flags uint32, randomSessionKey []byte, mode string) (sealKey []byte) {
 	if NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY.IsSet(flags) {
 		if NTLMSSP_NEGOTIATE_128.IsSet(flags) {

+ 1 - 1
psiphon/upstreamproxy/go-ntlm/ntlm/message_negotiate.go

@@ -7,7 +7,7 @@ import (
 	"encoding/binary"
 )
 
-//Supported negotiate flags
+// Supported negotiate flags
 const (
 	NEGOTIATE_FLAG_REQUEST_NTLMv1           = 0x00000200
 	NEGOTIATE_FLAG_REQUEST_NTLM2_SESSION    = 0x00080000

+ 1 - 1
psiphon/upstreamproxy/go-ntlm/ntlm/ntlmv1.go

@@ -376,7 +376,7 @@ func ntowfv1(passwd string) []byte {
 	return md4(utf16FromString(passwd))
 }
 
-//	ConcatenationOf( DES( UpperCase( Passwd)[0..6],"KGS!@#$%"), DES( UpperCase( Passwd)[7..13],"KGS!@#$%"))
+// ConcatenationOf( DES( UpperCase( Passwd)[0..6],"KGS!@#$%"), DES( UpperCase( Passwd)[7..13],"KGS!@#$%"))
 func lmowfv1(passwd string) ([]byte, error) {
 	asciiPassword := []byte(strings.ToUpper(passwd))
 	keyBytes := zeroPaddedBytes(asciiPassword, 0, 14)