Skip to content
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

TLS Hello Fragmenting: New Single TLS Hello Fragmenting Method #3660

Closed
wants to merge 4 commits into from
Closed

TLS Hello Fragmenting: New Single TLS Hello Fragmenting Method #3660

wants to merge 4 commits into from

Conversation

radioactiveAHM
Copy link
Contributor

  • Splits the TLS Hello message into two fragments and sends them within a single TCP segment.
  • Proven effective in Iran with MTN and MCI operators.
  • Capable of generating additional fragments if needed.

I’ve been using this method for about three months without any issues in my DnsSafeguard project.

Comment on lines +410 to +415
// 😐 Concat requires go v1.22
x := append(p1, p2...)
x = append(x, p3...)
x = append(x, p4...)

return f.writer.Write(x)
Copy link
Collaborator

@mmmray mmmray Aug 8, 2024

Choose a reason for hiding this comment

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

This feels wrong. has it been tested? You are splitting up the bytestring and then concatenate it again. And then write out the entire packet anyway. Normally they should be sent using individual Write calls, with Sleep inbetween. Take a look at the other fragment settings' code, where a for-loop is used.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, I tested and checked using Wireshark, and it works fine. I know it’s unusual, but as long as it works, it is useful. The tlshello fragmenting method generates fragments of a specified length, writes each fragment with one TCP segment, and then sleeps for the specified interval. However, this new method splits the TLS ClientHello into two halves, generates two fragments into one buffer, and sends both fragments using one TCP segment.

Copy link
Collaborator

Choose a reason for hiding this comment

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

oh i misunderstood. I just realized you have some hardcoded bytes in there as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, I have observed that almost all TLS Client Hello messages start with [22, 3, 1], so I hardcoded this value. I don’t anticipate this causing any bugs, but I can make it dynamic if needed.

Copy link
Member

Choose a reason for hiding this comment

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

话说这里为啥备注需要 Go 1.22?append 不是自古以来就有的吗

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 need go 1.22 for Concat method. with Concat you can do this

slices.Concat(p1, p2, p3, p4)

@mmmray
Copy link
Collaborator

mmmray commented Aug 8, 2024

Thanks for your contribution. I am not sure if the project wants to accept more fragment settings, but if it has been tested (or rather, another implementation of it), I guess why not. The added code is certainly small and easy to maintain. Until other core devs add their opinion, I suspect that this port from DnsSafeguard code doesn't actually work and has to be fixed (see code review)

@ImMohammad20000
Copy link

ImMohammad20000 commented Aug 9, 2024

i tested this and it work better than tlshello fragmenting method in MCI and TCI

@RPRX
Copy link
Member

RPRX commented Aug 9, 2024

Maybe we should call it "record layer fragment"

@Fangliding
Copy link
Member

Fangliding commented Aug 9, 2024

Maybe we should call it "record layer fragment"

RFC 8446 5.1 这个分片是在这个层分的

@RPRX
Copy link
Member

RPRX commented Aug 9, 2024

Maybe we should call it "record layer fragment"

RFC 8446 5.1 这个分片是在这个层分的

tlshello 分片不也是吗

@Fangliding
Copy link
Member

Maybe we should call it "record layer fragment"

RFC 8446 5.1 这个分片是在这个层分的

tlshello 分片不也是吗

哦 好像是的 我傻了 我只看过singbox被拒掉的那个pr 那个只有delay

@RPRX
Copy link
Member

RPRX commented Aug 9, 2024

我不确定现在 tlshello 分片的 interval 为 0 时有没有默认值,可能是有,所以我觉得可以设为 -1 代表把分片后的包 combine 后再发,虽然 X25519Kyber768Draft00 出来之后都是至少得两个 TCP 报文,还有 length 可以支持一下分数,比如 1/2 代表均分

@5e2t
Copy link

5e2t commented Aug 9, 2024

20240809185216
20240809184832

第一张图的SNI在出口GFW黑名单里,不在河南SNI黑名单里
第二张图的SNI在河南SNI黑名单里,不在出口GFW黑名单里。
这个分片功能是可以避免被出口GFW发RST,并不能避免被河南的墙发RST。而且我是用的固定宽带网络测试的。这个RST是固定宽带网络上的审查设备发的。

@5e2t
Copy link

5e2t commented Aug 9, 2024

package main

import (
	"fmt"
	"net"
	"time"
)

func main() {
	s1 := append([]byte{00, 00, 00, 0x1b, 00, 0x19, 00, 00, 0x16}, []byte("www.eulogysthermas.com")...)
	s2 := append([]byte{0x16, 0x03, 0x01, 0x02, 0x39, 0x01, 0x00, 0x02, 0x35, 0x03, 0x03, 0x6a, 0x53, 0x2a, 0x46, 0x47, 0x90, 0x9e, 0x72, 0xec, 0xf1, 0x81, 0xb3, 0xee, 0xd9, 0x5a, 0xee, 0x19, 0xe5, 0x8c, 0x6d, 0x7b, 0x5e, 0xda, 0x62, 0x17, 0xdf, 0x55, 0xe4, 0x25, 0x17, 0xeb, 0x31, 0x20, 0x45, 0x40, 0xb7, 0xcc, 0x0f, 0x7a, 0xf9, 0x92, 0x03, 0x0d, 0x4e, 0xb8, 0x81, 0x55, 0x4b, 0x16, 0x5f, 0x89, 0xe4, 0xbd, 0x8c, 0xe6, 0xcf, 0xc3, 0x04, 0x79, 0xac, 0x01, 0xac, 0xbe, 0x9d, 0xcd, 0, 2, 0x13, 0x01, 01, 00, 01, 0xcc}, s1...)
	server, err := net.Dial("tcp", "104.21.34.5:443")
	if err != nil {
		fmt.Println("err=", err)
		return
	}
	defer server.Close()
	server.Write(s2)
	time.Sleep(time.Second * 5)
}

20240809205214

20240809205900

这是一个extension字段只有一个Servername字段的ClientHello,也能触发河南SNI墙的RST。

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.

6 participants