Commit graph

1313 commits

Author SHA1 Message Date
Renovate Bot
d0c52757aa
chore(deps): update module golang.org/x/crypto to v0.27.0 2024-09-23 12:32:33 -04:00
Renovate Bot
60c89648aa
chore(deps): update module github.com/aws/aws-sdk-go-v2/credentials to v1.17.34 2024-09-23 12:20:36 -04:00
Renovate Bot
43b91c79c6
chore(deps): update module github.com/prometheus/client_golang to v1.20.4 2024-09-23 12:19:07 -04:00
Cecylia Bocovich
4497d68d6f
Move time.Sleep call in turbotunnel test
An update the the kcp-go library removes the guarantee that all data
written to a KCP connection will be flushed before the connection is
closed. Moving the sleep call has no impact on the integrity of the
tests, and gives the connection time to flush data before the connection
is closed.

See https://github.com/xtaci/kcp-go/issues/273
2024-09-23 10:08:18 -04:00
Renovate Bot
99521fb134 chore(deps): update module github.com/xtaci/kcp-go/v5 to v5.6.17 2024-09-23 12:49:18 +00:00
Renovate Bot
721c028d73
chore(deps): update module github.com/aws/aws-sdk-go-v2/service/sqs to v1.35.0 2024-09-23 13:21:05 +01:00
David Fifield
de61d7bb8d Document relayURL return in SignalingServer.pollOffer.
The second return value was added in
863a8296e8.
2024-09-21 18:28:17 +00:00
WofWca
0f0f118827 improvement(proxy): don't panic on invalid relayURL
Though prior to this change the panic could only happen
if the default relayURL set by the proxy is invalid,
since `datachannelHandler` is only called after a succesful
`checkIsRelayURLAcceptable()`, which ensures that it _is_ valid.
But in the case of invalid default relay URL, a warning is printed
already.
2024-09-21 18:20:31 +00:00
WofWca
71828580bb fix(broker): empty pattern if bridge-list is empty
i.e. if no bridge list file is provided, the relay pattern
would not get set.

AFAIK this is not a breaking change because the broker
can't be used as a library, unlike client and server.
2024-09-21 15:11:37 +00:00
David Fifield
f752d2ab0c Spell out EphemeralMinPort and EphemeralMaxPort in comment.
For searching purposes.
2024-09-21 14:30:59 +00:00
WofWca
daff4d8913 refactor(proxy): add comment about packet size 2024-09-19 19:14:04 +00:00
Shelikhoo
bcac2250ec
update mobile CI test's golang version to 1.23 2024-09-12 11:10:13 +01:00
meskio
9d2c513e6b
Merge remote-tracking branch 'gitlab/mr/394' 2024-09-09 18:22:27 +02:00
meskio
f046361e4a
Merge remote-tracking branch 'gitlab/mr/393' 2024-09-09 18:22:21 +02:00
Renovate Bot
1d951e3708 chore(deps): update module github.com/prometheus/client_golang to v1.20.3 2024-09-09 15:28:00 +00:00
Renovate Bot
0323ccba49
chore(deps): update module github.com/xtaci/smux to v1.5.29 2024-09-09 15:53:08 +01:00
WofWca
55c4c90a3a
fix(probetest): NAT check timing out sometimes
if ICE gathering on the probetest server is taking long
to complete.

Related: https://gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake/-/issues/40230
2024-09-09 15:26:59 +01:00
WofWca
2d13e2a5d1
fix(probetest): maybe resource leak
...on failed requests: WebRTC connection wouldn't get
closed in such cases.
2024-09-09 15:26:58 +01:00
WofWca
51edbbfd26
fix(proxy): maybe memory leak on failed NAT check
Maybe related: https://gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake/-/issues/40243
2024-09-09 15:26:58 +01:00
WofWca
f44aa279fe
refactor(proxy): improve NAT check logging
4ed5da7f2f introduced `OnError` but it did not print
failed periodic NAT type check errors - the error was simply
ignored.
2024-09-09 15:26:55 +01:00
WofWca
7f9fea5797
fix(proxy): send answer even if ICE gathering is not complete
Otherwise the connection is guaranteed to fail, even though
we actually might have gathered enough to make a successful
connection.

Closes https://gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake/-/issues/40230

This is the standalone proxy counterpart of https://gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake-webext/-/merge_requests/55
2024-09-09 11:58:28 +01:00
WofWca
78f4b9dbc5 test(client): add test for BrokerChannel 2024-09-08 14:50:08 +04:00
WofWca
2bbd4d0643
refactor(proxy): better RelayURL description
It's the case that it's simply "default" after
https://gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake/-/merge_requests/87
Now the broker specifies the relay URL (see `ProxyPollResponse`).
2024-09-05 13:04:42 +01:00
WofWca
ec9476e5ab
Better error msg on bad fingerprint 2024-09-04 10:47:08 -04:00
meskio
f701641382
Merge remote-tracking branch 'gitlab/mr/383' 2024-09-04 13:16:17 +02:00
Renovate Bot
f058a3daf5 chore(deps): update module github.com/aws/aws-sdk-go-v2 to v1.30.5 2024-09-03 18:54:49 +00:00
WofWca
94c6089cdd
hardening(proxy): don't proxy private IP addresses
...by default.

This is useful when `RelayDomainNamePattern` is lax (e.g. just "$")
(which is not the case by default, so this is simply
a hardening measure).
2024-09-02 14:59:26 +01:00
WofWca
399bda5257
refactor(proxy): tidy up isRelayURLAcceptable
Add clearer error messages
2024-09-02 14:59:26 +01:00
WofWca
0f2bdffba0
hardening(proxy): only accept ws & wss relays 2024-09-02 14:59:26 +01:00
WofWca
14f4c82ff7
test(proxy): add tests for relayURL check 2024-09-02 14:59:23 +01:00
meskio
978a55b7c4
Merge remote-tracking branch 'gitlab/mr/374' 2024-09-02 13:03:08 +02:00
Renovate Bot
9f832f8bb2 chore(deps): update module github.com/prometheus/client_golang to v1.20.2 2024-08-27 14:00:16 +00:00
Renovate Bot
97e21e3a29
chore(deps): update module github.com/pion/stun to v3 2024-08-27 09:43:08 -04:00
Renovate Bot
0a942f8ecb
chore(deps): update module github.com/aws/aws-sdk-go-v2/credentials to v1.17.30 2024-08-27 09:20:43 -04:00
Renovate Bot
37c1e2c244
chore(deps): update module golang.org/x/sys to v0.24.0 2024-08-27 09:19:09 -04:00
WofWca
f4db64612c
feat: expose pollInterval in CLI
Closes https://gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake/-/issues/40373
2024-08-22 09:31:37 -04:00
Renovate Bot
8f429666a8
chore(deps): update module github.com/aws/aws-sdk-go-v2/config to v1.27.28 2024-08-22 12:56:14 +01:00
meskio
2ebfcf6e20
Merge remote-tracking branch 'gitlab/mr/367' 2024-08-22 13:36:46 +02:00
meskio
0804d8651f
Merge remote-tracking branch 'gitlab/mr/362' 2024-08-22 13:35:53 +02:00
Renovate Bot
5fb1290fd0 chore(deps): update module github.com/prometheus/client_golang to v1.20.1 2024-08-22 11:10:40 +00:00
Renovate Bot
44a962316c
chore(deps): update module github.com/miekg/dns to v1.1.62 2024-08-22 11:18:02 +01:00
Renovate Bot
450c309653
chore(deps): update module golang.org/x/net to v0.28.0 2024-08-22 11:00:07 +01:00
meskio
240dd3af3c
Merge remote-tracking branch 'gitlab/mr/365' 2024-08-22 11:46:35 +02:00
Renovate Bot
f6320e42f0 chore(deps): update docker.io/library/golang docker tag to v1.23 2024-08-22 05:12:30 +00:00
Renovate Bot
937860b1bb
chore(deps): update module golang.org/x/crypto to v0.26.0 2024-08-22 05:59:24 +01:00
David Fifield
bb2126b7c6
Use %w, not %v, in fmt.Errorf, so errors can be unwrapped.
https://go.dev/blog/go1.13-errors#wrapping-errors-with-w
2024-08-21 17:00:18 -04:00
WofWca
062411143c
docs: fix example server library usage
`Listen` now accepts `numKCPInstances`
2024-08-21 16:23:12 -04:00
WofWca
677146c9d5 add test_bridgeList.txt file
As an example for the `bridge-list-path` parameter
2024-08-21 20:50:59 +04:00
obble
a6d4570c23
Fix log message in CopyLoop 2024-08-21 16:06:41 +01:00
obble
1d6a2580c6 Improving Snowflake Proxy Performance by Adjusting Copy Buffer Size
TL;DR: The current implementation uses a 32K buffer size for a total of 64K of
buffers/connection, but each read/write is less than 2K according to my measurements.

# Background

The Snwoflake proxy uses as particularly hot function `copyLoop`
(proxy/lib/snowflake.go) to proxy data from a Tor relay to a connected client.
This is currently done using the `io.Copy` function to write all incoming data
both ways.

Looking at the `io.Copy` implementation, it internally uses `io.CopyBuffer`,
which in turn defaults to a buffer of size 32K for copying data (I checked and
the current implementation uses 32K every time).

Since `snowflake-proxy` is intended to be run in a very distributed manner, on
as many machines as possible, minimizing the CPU and memory footprint of each
proxied connection would be ideal, as well as maximising throughput for
clients.

# Hypothesis

There might exist a buffer size `X` that is more suitable for usage in `copyLoop` than 32K.

# Testing

## Using tcpdump

Assuming you use `-ephemeral-ports-range 50000:51000` for `snowflake-proxy`,
you can capture the UDP packets being proxied using

```sh
sudo tcpdump  -i <interface> udp portrange 50000-51000
```

which will provide a `length` value for each packet captured. One good start
value for `X` could then be slighly larger than the largest captured packet,
assuming one packet is copied at a time.

Experimentally I found this value to be 1265 bytes, which would make `X = 2K` a
possible starting point.

## Printing actual read

The following snippe was added in `proxy/lib/snowflake.go`:

```go
// Taken straight from standardlib io.copyBuffer
func copyBuffer(dst io.Writer, src io.Reader, buf []byte) (written int64, err error) {
	// If the reader has a WriteTo method, use it to do the copy.
	// Avoids an allocation and a copy.
	if wt, ok := src.(io.WriterTo); ok {
		return wt.WriteTo(dst)
	}
	// Similarly, if the writer has a ReadFrom method, use it to do the copy.
	if rt, ok := dst.(io.ReaderFrom); ok {
		return rt.ReadFrom(src)
	}
	if buf == nil {
		size := 32 * 1024
		if l, ok := src.(*io.LimitedReader); ok && int64(size) > l.N {
			if l.N < 1 {
				size = 1
			} else {
				size = int(l.N)
			}
		}
		buf = make([]byte, size)
	}
	for {
		nr, er := src.Read(buf)
		if nr > 0 {
			log.Printf("Read %d", nr) // THIS IS THE ONLY DIFFERENCE FROM io.CopyBuffer
			nw, ew := dst.Write(buf[0:nr])
			if nw < 0 || nr < nw {
				nw = 0
				if ew == nil {
					ew = errors.New("invalid write result")
				}
			}
			written += int64(nw)
			if ew != nil {
				err = ew
				break
			}
			if nr != nw {
				err = io.ErrShortWrite
				break
			}
		}
		if er != nil {
			if er != io.EOF {
				err = er
			}
			break
		}
	}
	return written, err
}
```

and `copyLoop` was amended to use this instead of `io.Copy`.

The `Read: BYTES` was saved to a file using this command

```sh
./proxy -verbose -ephemeral-ports-range 50000:50010 2>&1 >/dev/null  | awk '/Read: / { print $4 }' | tee read_sizes.txt
```

I got the result:

min: 8
max: 1402
median: 1402
average: 910.305

Suggested buffer size: 2K
Current buffer size: 32768 (32K, experimentally verified)

## Using a Snowflake Proxy in Tor browser and use Wireshark

I also used Wireshark, and concluded that all packets sent was < 2K.

# Conclusion

As per the commit I suggest changing the buffer size to 2K. Some things I have not been able to answer:

1. Does this make a big impact on performance?
1. Are there any unforseen consequences? What happens if a packet is > 2K (I
	 think the Go standard libary just splits the packet, but someone please confirm).
2024-08-21 15:02:15 +00:00