-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
WIP: disorder #1
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the contribution. This is exciting!
transport/disorder/stream_dialer.go
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same comments as in the other PRs: let's keep all the new stuff in the x
module until they have comprehensive tests and are validated. That also simplifies development.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
transport/disorder/writer.go
Outdated
data = data[written:] | ||
} | ||
w.resetTTL.Do(func() { | ||
err = syscall.SetsockoptInt(w.fd, syscall.IPPROTO_IP, syscall.IP_TTL, defaultTTL) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ideally this should work on Windows as well, and both IPv4 and IPv6, so providers can easily specify strategies that work everywhere. It would be great if you can validate that.
By the way, I don't know if it helps, but there's
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome, didn't know about this package
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ideally this should work on Windows as well
I think for windows, mac and ios we would need a completely different implementation. I personally don't have any ways to test on those platforms, so I am thinking about disabling this code anywhere but on linux
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here is an example of a prototype I was working some time ago: https://github.com/Jigsaw-Code/outline-sdk/edit/fortuna-disorder/transport/split/writer.go
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this will only work on Linux btw (but will at least compile on other platforms, which is maybe a bit better)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do you think it will only work on Linux? I don't see any documentation saying that. They usually say when it doesn't work on other platforms.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmm, I might have mis-read the code when I checked it, looks like the implementations are there
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in any case, some testing is required on each platform, even if API is there there's no guarantee it works the same way
transport/disorder/stream_dialer.go
Outdated
return nil, fmt.Errorf("setting tcp NO_DELAY failed: %w", err) | ||
} | ||
|
||
file, err := tcpConn.File() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use syscall.RawConn.Control instead
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
changed to use x/net
transport/disorder/stream_dialer.go
Outdated
// this strategy only works when we set TCP as a strategy | ||
tcpConn, ok := innerConn.(*net.TCPConn) | ||
if !ok { | ||
return nil, fmt.Errorf("split strategy only works with direct TCP connections") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return nil, fmt.Errorf("split strategy only works with direct TCP connections") | |
return nil, fmt.Errorf("disorder strategy only works with direct TCP connections") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
transport/disorder/stream_dialer.go
Outdated
return nil, fmt.Errorf("split strategy only works with direct TCP connections") | ||
} | ||
|
||
err = tcpConn.SetNoDelay(true) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't this the default? Also, I'd rather not silently change settings. The base dialer provider should be responsible for that.
Perhaps we check if it's set and error if not. Though I don't see an easy way to check.
Add to the comments that the TCPConn must have NoDelay set.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't this the default?
Honestly no idea. In Linux it's default now (but only for recent kernels, most android likely will need years to adopt the change), but in golang no idea.
I've added this in an attempt to debug something, but the issue was somewhere else, so this is no longer needed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's enabled by default in Go, so no need to set it: https://pkg.go.dev/net#TCPConn.SetNoDelay
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
awesome
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
161f18f
to
db99e8a
Compare
x/disorder/stream_dialer.go
Outdated
conn := ipv6.NewConn(conn) | ||
oldTTL, _ = conn.HopLimit() | ||
err = conn.SetHopLimit(ttl) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should fail if we can't set the TTL
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
error check for both SetTTL
and SetHopLimit
is on lines 88-90
x/disorder/stream_dialer.go
Outdated
} | ||
|
||
if oldTTL == 0 { | ||
oldTTL = defaultTTL |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the rationale of returning a default if it's zero? Why not return zero if it's zero?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was not sure what happens by default (what getsockopt returns if ttl was not changed), also need to check what happens when we set ttl to 0
x/disorder/stream_dialer.go
Outdated
return nil, err | ||
} | ||
|
||
oldTTL, err := setTtl(innerConn, 1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please move this to the Writer, so the Writer can be used independent of the Dialer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the idea was to fail early if something (like setting socket options) is not supported or lacks permissions
x/disorder/stream_dialer.go
Outdated
|
||
// setTtl changes the socket TTL and returns the old value | ||
// socket must be `*net.TCPConn` | ||
func setTtl(conn net.Conn, ttl int) (oldTTL int, err error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's rename this to setHopLimit, which is a preferred term. TTL is actually confusing, since it is not related to time, hop limit is clearer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
renamed
x/configurl/disorder.go
Outdated
prefixBytesStr := config.URL.Opaque | ||
prefixBytes, err := strconv.Atoi(prefixBytesStr) | ||
if err != nil { | ||
return nil, fmt.Errorf("prefixBytes is not a number: %v. Split config should be in split:<number> format", prefixBytesStr) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return nil, fmt.Errorf("prefixBytes is not a number: %v. Split config should be in split:<number> format", prefixBytesStr) | |
return nil, fmt.Errorf("Disorder config should take a number, got %v: %w, prefixBytesStr, err) |
I'd move away from specifying the format scheme, since that can be changed in registration.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
transport/disorder/writer.go
Outdated
data = data[written:] | ||
} | ||
w.resetTTL.Do(func() { | ||
err = syscall.SetsockoptInt(w.fd, syscall.IPPROTO_IP, syscall.IP_TTL, defaultTTL) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do you think it will only work on Linux? I don't see any documentation saying that. They usually say when it doesn't work on other platforms.
x/disorder/writer.go
Outdated
w.resetTTL.Do(func() { | ||
_, err = setTtl(w.conn, w.oldTTL) | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
before resetting ttl back to the "normal" value we might need to make sure send buffers are empty (= the first packet already departed). if golang is too fast this might change ttl back to normal too fast
other methods using setsocksopt also suffer from the same
d35a4da
to
a910d10
Compare
x/disorder/writer.go
Outdated
// var _ io.ReaderFrom = (*splitWriterReaderFrom)(nil) | ||
|
||
// TODO | ||
func NewWriter(conn net.Conn, prefixBytes int64, oldTTL int) io.Writer { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oldTTL is not needed. You can read it from the connection.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you send this code to the official repository?
Thanks!
x/disorder/stream_dialer.go
Outdated
|
||
// setHopLimit changes the socket TTL for IPv4 (or HopLimit for IPv6) and returns the old value | ||
// socket must be `*net.TCPConn` | ||
func setHopLimit(conn net.Conn, ttl int) (oldTTL int, err error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you use Jigsaw-Code#316 instead?
x/disorder/writer.go
Outdated
// var _ io.ReaderFrom = (*splitWriterReaderFrom)(nil) | ||
|
||
// TODO | ||
func NewWriter(conn net.Conn, prefixBytes int64, oldTTL int) io.Writer { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please pass an io.Writer
and the new sockopt.TCPOptions
instead of net.Conn
.
x/disorder/writer.go
Outdated
data = data[written:] | ||
} | ||
w.resetTTL.Do(func() { | ||
_, err = setHopLimit(w.conn, w.oldTTL) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please use the new https://pkg.go.dev/github.com/Jigsaw-Code/outline-sdk/x/sockopt instead
4cb2ac5
to
e5480ac
Compare
e5480ac
to
36def4b
Compare
2d98f62
to
b6aef3d
Compare
Superseded by Jigsaw-Code#323 @PeterZhizhin please check the last commits were pushed where you expected them to be pushed |
No description provided.