Skip to content

Add WeirdSplitter #45

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

Closed
wants to merge 4 commits into from
Closed

Conversation

Lanius-collaris
Copy link
Contributor

@Lanius-collaris Lanius-collaris commented Apr 9, 2024

sequenceDiagram
 Client --x Router : 1st segment, TTL = 1
 Client ->> Server: 2nd segment, TTL = 64
 Client ->> Server: 1st segment, TTL = 64
Loading

WeirdSplitter can access some websites that cannot handle handshake messages that are fragmented to multiple TCP segments. (e.g. www.itu.int)

Comment on lines +40 to +46
rawErr := rawConn.Control(func(fd uintptr) {
if isIPv6 {
err = syscall.SetsockoptInt(int(fd), syscall.IPPROTO_IPV6, syscall.IPV6_UNICAST_HOPS, 1)
} else {
err = syscall.SetsockoptInt(int(fd), syscall.IPPROTO_IP, syscall.IP_TTL, 1)
}
})
Copy link
Contributor

@ignoramous ignoramous Apr 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add a succinct code comment on what this approach does to bypass censorship or link to existing projects using this technique?

Is it similar to what's discussed here? #46

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GoodbyeDPI commit e28cb526
ValdikSS wrote:

Some websites (or more precisely, TLS terminators/balancers) can't
handle segmented TLS ClientHello packet properly, requiring the whole
ClientHello in a single segment, otherwise the connection gets dropped.

However they still operate with a proper TCP stack.
Cheat on them: send the latter segment first (with TCP SEQ "in the future"),
the former segment second (with "current" SEQ), allowing OS TCP
stack to combine it in a single TCP read().

But we don't have privileges, so we should implement this with setting TTL. The TCP stack transmits the segment with TTL=1 first, then we restore TTL option before the TCP stack retransmits, this idea is mentioned in #46 too.

Comment on lines +25 to +27
if len(b) < 2 {
return conn.Write(b)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you think we should add a code comment on why len(b) < 2 won't work?

(to my untrained eye, it isn't obvious)

type WeirdSplitter struct {
*net.TCPConn
Used bool
Size int
Copy link
Contributor

@ignoramous ignoramous Apr 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A code comment on how clients should set this field? To half of MSS/MTU? Or, some arbitrary value greater than 0 will do (and why)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know. splitHello() choose where the upstream segment to be split randomly.
https://github.com/celzero/firestack/blob/n2/intra/dialers/retrier.go#L343-L359
And should I rename this field position?

@Lanius-collaris
Copy link
Contributor Author

Suggest a name please.

@ignoramous
Copy link
Contributor

ignoramous commented May 6, 2024

Suggest a name please.

Following current dialers (DialWithSplit, DialWithSplitRetry), how about:

  • DialWithSplitAndDesync, DialWithSplitAndDesyncRetry
  • DialWithDesync, DialWithDesyncRetry

@Lanius-collaris
Copy link
Contributor Author

Suggest a name please.

Following current dialers (DialWithSplit, DialWithSplitRetry), how about:

* `DialWithSplitAndDesync`, `DialWithSplitAndDesyncRetry`

* `DialWithDesync`, `DialWithDesyncRetry`

Are they for #48? #45 doesn't implement TCB Desynchronization.

Lanius-collaris added a commit to Lanius-collaris/firestack that referenced this pull request May 13, 2024
@ignoramous
Copy link
Contributor

ignoramous commented Jul 18, 2024

Are they for #48? #45 doesn't implement TCB Desynchronization

Well, I am confused as to what weirdsplitter does vs what desync is doing. Can these two be a single PR?

@Lanius-collaris
Copy link
Contributor Author

@ignoramous
weirdsplitter is similar to direct_split from DPI perspective (can bypass stateless DPI but cannot bypass stateful DPI), the only advantage of weirdsplitter is that it works with websites which can't handle segmented TLS ClientHello. #48 also has this advantage, because they are implemented in similar ways.
In addition, #48 overwrites the buffer before retransmitting, so TCP stack will retransmit different payload.

Why does weirdsplitter not cause desynchronization?
If original 1st segment and 2nd segment are reassembled, the censor will inject RST.
But our prepared payload + 2nd segment doesn't trigger RST, so the censor increases the sequence number in TCB and waits for more packets.

Why is the sequence number of the server inconsistent with the sequence number of censor ?
Only the censor sees the first packet.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants