Skip to content

Commit adbe171

Browse files
committed
2 parents 5bf8c81 + 2549281 commit adbe171

File tree

15 files changed

+259
-96
lines changed

15 files changed

+259
-96
lines changed

x/configurl/tls.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ func parseOptions(configURL url.URL) ([]tls.ClientOption, error) {
5656
if len(values) != 1 {
5757
return nil, fmt.Errorf("certName option must has one value, found %v", len(values))
5858
}
59-
options = append(options, tls.WithCertificateName(values[0]))
59+
options = append(options, tls.WithCertVerifier(&tls.StandardCertVerifier{CertificateName: values[0]}))
6060
default:
6161
return nil, fmt.Errorf("unsupported option %v", key)
6262

x/configurl/tls_test.go

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,25 +26,27 @@ func TestTLS_SNI(t *testing.T) {
2626
require.NoError(t, err)
2727
options, err := parseOptions(config.URL)
2828
require.NoError(t, err)
29-
cfg := tls.ClientConfig{ServerName: "host", CertificateName: "host"}
29+
certVerifier := &tls.StandardCertVerifier{CertificateName: "host"}
30+
cfg := tls.ClientConfig{ServerName: "host", CertVerifier: certVerifier}
3031
for _, option := range options {
3132
option("host", &cfg)
3233
}
3334
require.Equal(t, "www.google.com", cfg.ServerName)
34-
require.Equal(t, "host", cfg.CertificateName)
35+
require.Equal(t, certVerifier, cfg.CertVerifier)
3536
}
3637

3738
func TestTLS_NoSNI(t *testing.T) {
3839
config, err := ParseConfig("tls:sni=")
3940
require.NoError(t, err)
4041
options, err := parseOptions(config.URL)
4142
require.NoError(t, err)
42-
cfg := tls.ClientConfig{ServerName: "host", CertificateName: "host"}
43+
certVerifier := &tls.StandardCertVerifier{CertificateName: "host"}
44+
cfg := tls.ClientConfig{ServerName: "host", CertVerifier: certVerifier}
4345
for _, option := range options {
4446
option("host", &cfg)
4547
}
4648
require.Equal(t, "", cfg.ServerName)
47-
require.Equal(t, "host", cfg.CertificateName)
49+
require.Equal(t, certVerifier, cfg.CertVerifier)
4850
}
4951

5052
func TestTLS_MultipleSNI(t *testing.T) {
@@ -59,25 +61,25 @@ func TestTLS_CertName(t *testing.T) {
5961
require.NoError(t, err)
6062
options, err := parseOptions(config.URL)
6163
require.NoError(t, err)
62-
cfg := tls.ClientConfig{ServerName: "host", CertificateName: "host"}
64+
cfg := tls.ClientConfig{ServerName: "host", CertVerifier: &tls.StandardCertVerifier{CertificateName: "host"}}
6365
for _, option := range options {
6466
option("host", &cfg)
6567
}
6668
require.Equal(t, "host", cfg.ServerName)
67-
require.Equal(t, "www.google.com", cfg.CertificateName)
69+
require.Equal(t, "www.google.com", cfg.CertVerifier.(*tls.StandardCertVerifier).CertificateName)
6870
}
6971

7072
func TestTLS_Combined(t *testing.T) {
7173
config, err := ParseConfig("tls:SNI=sni.example.com&CertName=certname.example.com")
7274
require.NoError(t, err)
7375
options, err := parseOptions(config.URL)
7476
require.NoError(t, err)
75-
cfg := tls.ClientConfig{ServerName: "host", CertificateName: "host"}
77+
cfg := tls.ClientConfig{ServerName: "host", CertVerifier: &tls.StandardCertVerifier{CertificateName: "host"}}
7678
for _, option := range options {
7779
option("host", &cfg)
7880
}
7981
require.Equal(t, "sni.example.com", cfg.ServerName)
80-
require.Equal(t, "certname.example.com", cfg.CertificateName)
82+
require.Equal(t, "certname.example.com", cfg.CertVerifier.(*tls.StandardCertVerifier).CertificateName)
8183
}
8284

8385
func TestTLS_UnsupportedOption(t *testing.T) {

x/examples/smart-proxy/config_broken.yaml

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,15 @@ tls:
2525
fallback:
2626
# Nonexistent Outline Server
2727
- ss://Y2hhY2hhMjAtaWV0Zi1wb2x5MTMwNTprSzdEdHQ0MkJLOE9hRjBKYjdpWGFK@1.2.3.4:9999/?outline=1
28-
# Nonexistant Psiphon Config JSON. Not yet supported
28+
# Nonexistant Psiphon Config JSON
2929
- psiphon: {
30-
"PropagationChannelId":"FFFFFFFFFFFFFFFF",
31-
"SponsorId":"FFFFFFFFFFFFFFFF",
30+
"PropagationChannelId":"ID1",
31+
"SponsorId":"ID2",
32+
"DisableLocalSocksProxy" : true,
33+
"DisableLocalHTTPProxy" : true,
34+
"EstablishTunnelTimeoutSeconds": 1,
35+
# URL points to google.com
36+
"RemoteServerListURLs" : [{"URL": "aHR0cHM6Ly9nb29nbGUuY29t", "OnlyAfterAttempts": 0, "SkipVerify": false}],
3237
}
3338
# Nonexistant local socks5 proxy
3439
- socks5://192.168.1.10:1080

x/examples/smart-proxy/main.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,10 @@ func main() {
119119

120120
fmt.Println("Finding strategy")
121121
startTime := time.Now()
122-
dialer, err := finder.NewDialer(context.Background(), domainsFlag, finderConfig)
122+
findCtx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
123+
defer cancel()
124+
125+
dialer, err := finder.NewDialer(findCtx, domainsFlag, finderConfig)
123126
if err != nil {
124127
log.Fatalf("Failed to find dialer: %v", err)
125128
}

x/go.mod

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@ module github.com/Jigsaw-Code/outline-sdk/x
33
go 1.23.0
44

55
require (
6-
github.com/Jigsaw-Code/outline-sdk v0.0.19
6+
github.com/Jigsaw-Code/outline-sdk v0.0.20
77
// Use github.com/Psiphon-Labs/psiphon-tunnel-core@staging-client as per
88
// https://github.com/Psiphon-Labs/psiphon-tunnel-core/?tab=readme-ov-file#using-psiphon-with-go-modules
99
github.com/Psiphon-Labs/psiphon-tunnel-core v1.0.11-0.20250319154633-ceb78316d06e
10-
github.com/goccy/go-yaml v1.16.0
10+
github.com/goccy/go-yaml v1.17.1
1111
github.com/gorilla/websocket v1.5.3
12-
github.com/lmittmann/tint v1.0.5
12+
github.com/lmittmann/tint v1.0.7
1313
github.com/quic-go/quic-go v0.48.1
1414
github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8
1515
github.com/stretchr/testify v1.9.0

x/go.sum

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96 h1:cTp8I5+VIo
88
github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8=
99
github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
1010
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
11-
github.com/Jigsaw-Code/outline-sdk v0.0.19 h1:/OpMz+3B/9ypjq/UyEvwZSflzJ4jXFginUOZeN0UssM=
12-
github.com/Jigsaw-Code/outline-sdk v0.0.19/go.mod h1:CFDKyGZA4zatKE4vMLe8TyQpZCyINOeRFbMAmYHxodw=
11+
github.com/Jigsaw-Code/outline-sdk v0.0.20 h1:4ep7MK9lFmcyPIRIbn4xrP1VKdJNsqR6+iJEOHDKnNg=
12+
github.com/Jigsaw-Code/outline-sdk v0.0.20/go.mod h1:CFDKyGZA4zatKE4vMLe8TyQpZCyINOeRFbMAmYHxodw=
1313
github.com/Jigsaw-Code/outline-ss-server v1.8.0 h1:6h7CZsyl1vQLz3nvxmL9FbhDug4QxJ1YTxm534eye1E=
1414
github.com/Jigsaw-Code/outline-ss-server v1.8.0/go.mod h1:slnHH3OZsQmZx/DRKhxvvaGE/8+n3Lkd6363h1ev71E=
1515
github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE=
@@ -100,8 +100,8 @@ github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEe
100100
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
101101
github.com/gobwas/glob v0.2.4-0.20180402141543-f00a7392b439 h1:T6zlOdzrYuHf6HUKujm9bzkzbZ5Iv/xf6rs8BHZDpoI=
102102
github.com/gobwas/glob v0.2.4-0.20180402141543-f00a7392b439/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
103-
github.com/goccy/go-yaml v1.16.0 h1:d7m1G7A0t+logajVtklHfDYJs2Et9g3gHwdBNNFou0w=
104-
github.com/goccy/go-yaml v1.16.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=
103+
github.com/goccy/go-yaml v1.17.1 h1:LI34wktB2xEE3ONG/2Ar54+/HJVBriAGJ55PHls4YuY=
104+
github.com/goccy/go-yaml v1.17.1/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=
105105
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
106106
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
107107
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
@@ -141,8 +141,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
141141
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
142142
github.com/libp2p/go-reuseport v0.4.0 h1:nR5KU7hD0WxXCJbmw7r2rhRYruNRl2koHw8fQscQm2s=
143143
github.com/libp2p/go-reuseport v0.4.0/go.mod h1:ZtI03j/wO5hZVDFo2jKywN6bYKWLOy8Se6DrI2E1cLU=
144-
github.com/lmittmann/tint v1.0.5 h1:NQclAutOfYsqs2F1Lenue6OoWCajs5wJcP3DfWVpePw=
145-
github.com/lmittmann/tint v1.0.5/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE=
144+
github.com/lmittmann/tint v1.0.7 h1:D/0OqWZ0YOGZ6AyC+5Y2kD8PBEzBk6rFHVSfOqCkF9Y=
145+
github.com/lmittmann/tint v1.0.7/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE=
146146
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
147147
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
148148
github.com/marusama/semaphore v0.0.0-20171214154724-565ffd8e868a h1:6SRny9FLB1eWasPyDUqBQnMi9NhXU01XIlB0ao89YoI=

x/mobileproxy/README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,14 @@ From the `x/` directory:
3434
go build -o "$(pwd)/out/" golang.org/x/mobile/cmd/gomobile golang.org/x/mobile/cmd/gobind
3535
```
3636

37+
> [!WARNING]
38+
> The Psiphon library is not included in the build by default because the Psiphon codebase uses GPL. To support Psiphon configuration in the Mobile Proxy please build using the [`psiphon` build tag](https://pkg.go.dev/github.com/Jigsaw-Code/outline-sdk/x/psiphon).
39+
> When integrating Psiphon into your application please work with the Psiphon team at [email protected]
40+
41+
```bash
42+
go build -tags psiphon -o "$(pwd)/out/" golang.org/x/mobile/cmd/gomobile golang.org/x/mobile/cmd/gobind
43+
```
44+
3745
Then build the iOS and Android libraries with [`gomobile bind`](https://pkg.go.dev/golang.org/x/mobile/cmd/gomobile#hdr-Build_a_library_for_Android_and_iOS)
3846

3947
```bash

x/psiphon/doc.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,7 @@ For testing, you can [generate a Psiphon config yourself].
2626
Psiphon code is licensed as GPLv3, which you will have to take into account if you incorporate Psiphon logic into your app.
2727
If you don't want your app to be GPL, consider acquiring an appropriate license when acquiring their services.
2828
29-
Note that a few of Psiphon's dependencies may impose additional restrictions. For example, github.com/hashicorp/golang-lru is MPL-2.0
30-
and github.com/juju/ratelimit is LGPL-3.0. You can use [go-licenses] to analyze the licenses of your Go code dependencies.
29+
Note that a few of Psiphon's dependencies may impose additional restrictions. You can use [go-licenses] to analyze the licenses of your Go code dependencies.
3130
3231
To prevent accidental inclusion of unvetted licenses, you must use the "psiphon" build tag in order to use this package. Typically you do that with
3332
"-tags psiphon".

x/psiphon/psiphon.go

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ func getClientPlatform() string {
101101
// Allows for overriding in tests.
102102
var startTunnel func(ctx context.Context, config *DialerConfig) (psiphonTunnel, error) = psiphonStartTunnel
103103

104-
func psiphonStartTunnel(ctx context.Context, config *DialerConfig) (psiphonTunnel, error) {
104+
func psiphonStartTunnel(tunnelCtx context.Context, config *DialerConfig) (psiphonTunnel, error) {
105105
if config == nil {
106106
return nil, errors.New("config must not be nil")
107107
}
@@ -117,11 +117,11 @@ func psiphonStartTunnel(ctx context.Context, config *DialerConfig) (psiphonTunne
117117
DisableLocalHTTPProxy: &trueValue,
118118
}
119119

120-
return clientlib.StartTunnel(ctx, config.ProviderConfig, "", params, nil, nil)
120+
return clientlib.StartTunnel(tunnelCtx, config.ProviderConfig, "", params, nil, nil)
121121
}
122122

123123
// Start configures and runs the Dialer. It must be called before you can use the Dialer. It returns when the tunnel is ready.
124-
func (d *Dialer) Start(ctx context.Context, config *DialerConfig) error {
124+
func (d *Dialer) Start(startCtx context.Context, config *DialerConfig) error {
125125
resultCh := make(chan error)
126126
go func() {
127127
d.mu.Lock()
@@ -132,13 +132,23 @@ func (d *Dialer) Start(ctx context.Context, config *DialerConfig) error {
132132
return
133133
}
134134

135-
ctx, cancel := context.WithCancel(ctx)
136-
defer cancel()
135+
// startCtx is intended for the lifetime of the startup.
136+
// dialerCtx is intended for the lifetime of the tunnel.
137+
dialerCtx, dialerCancel := context.WithCancel(context.Background())
138+
defer dialerCancel()
139+
140+
// This ties startCtx and dialerCtx together
141+
// so dialerCtx will be cancelled if startCtx is cancelled.
142+
// We run detatchContexts after startTunnel to disconnect them.
143+
detatchContexts := context.AfterFunc(startCtx, func() {
144+
dialerCancel()
145+
})
146+
137147
tunnelDone := make(chan struct{})
138148
defer close(tunnelDone)
139149
d.stop = func() {
140150
// Tell start to stop.
141-
cancel()
151+
dialerCancel()
142152
// Wait for tunnel to be done.
143153
<-tunnelDone
144154
}
@@ -148,13 +158,13 @@ func (d *Dialer) Start(ctx context.Context, config *DialerConfig) error {
148158
}()
149159

150160
d.mu.Unlock()
151-
152-
tunnel, err := startTunnel(ctx, config)
161+
tunnel, err := startTunnel(dialerCtx, config)
153162

154163
d.mu.Lock()
164+
detatchContexts()
155165

156-
if ctx.Err() != nil {
157-
err = context.Cause(ctx)
166+
if dialerCtx.Err() != nil {
167+
err = context.Cause(dialerCtx)
158168
}
159169
if err != nil {
160170
resultCh <- err
@@ -169,7 +179,7 @@ func (d *Dialer) Start(ctx context.Context, config *DialerConfig) error {
169179

170180
d.mu.Unlock()
171181
// wait for Stop
172-
<-ctx.Done()
182+
<-dialerCtx.Done()
173183
d.mu.Lock()
174184
}()
175185
return <-resultCh

x/psiphon/psiphon_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ func TestDialer_Start_Timeout(t *testing.T) {
139139
errCh <- GetSingletonDialer().Start(ctx, cfg)
140140
}()
141141
err := <-errCh
142-
require.ErrorIs(t, err, context.DeadlineExceeded)
142+
require.ErrorIs(t, err, context.Canceled)
143143
}
144144

145145
type errorTunnel struct {

0 commit comments

Comments
 (0)