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

[app/dispatcher] Correctly implement QUIC sniffer #2335

Merged
merged 3 commits into from
Feb 19, 2023

Conversation

Vigilans
Copy link
Contributor

Current QUIC sniffer can work with curl's --http3 option, but is basically unusable when using chromium browser to browse HTTP3 websites.

Current QUIC sniffer is problematic for following three reasons:

  1. Packet Number. Although some spec mentioned initial packet will use packet number 0, but actually chromium will always start with packet number 1.
    So following check blocks all QUIC sniffing for chromium HTTP3 payload:

    if packetNumber != 0 {
    return nil, errNotQuicInitial
    }

  2. Frames. The payload of QUIC packets consists of a sequence of complete frames. Current QUIC sniffer assumes that there's only 1 frame in initial packet:

    buffer = buf.FromBytes(decrypted)
    frameType, err := buffer.ReadByte()
    if err != nil {
    return nil, io.ErrUnexpectedEOF
    }
    if frameType != 0x6 {
    // not crypto frame
    return &SniffHeader{domain: ""}, nil
    }

    Above check blocks sniffing if the first frame is not crypto frame. In chromium's QUIC payload, this is often not the case. The first frame can be PADDING frame or PING frame.

    Therefore, we need to parse multiple frames in QUIC packet to find a crypto frame with ClientHello payload.

  3. CRYPTO Frames. Even if the first frame in initial packet is crypto frame, it may not contain full data for a ClientHello payload. In QUIC spec, all crypto frames make up a stream of bytes, where each crypto frame is just a slice of the stream with offset and length information in.

    Therefore, we need to parse all frames in initial QUIC packet, to compose a complete CRYPTO data stream buffer, so as to fetch the complete ClientHello payload.

This PR fixes all above three issues, to provide a basically usable QUIC sniffer for browsing HTTP3 websites in chromium browser.

@Vigilans Vigilans changed the title Correctly implement quic sniffer's frame parsing [app/dispatcher] Correctly implement QUIC sniffer Feb 17, 2023
cubarco and others added 3 commits February 19, 2023 12:24
The Keep-Alive configs may be overridden with golang default settings when `tcpKeepAliveInterval` is set without `tcpKeepAliveIdle`.
Adopt: XTLS/Xray-core#1328
When SystemPolicy.OverrideAccessLogDest is enabled, destination host
in access log will be replaced with sniffed host. (v2fly#866)
@heygo1345678
Copy link

隔壁v2ray的quic sniffing实现是近期才修复的 #2335 ,实施于 v5.4.0(pre-release)。也许是因为xray-core存在同样的bug?你可以先去试试隔壁修复后的quic sniffing好不好使。
v2ray v5.4.0版本的 quic sniffing我测试了,没有问题,这个修复有效,sing-box目前还没有测试

2023/03/19 08:50:54 [Info] app/dns: DOH//1.1.1.1 got answer: quic.nginx.org. TypeA -> [35.214.218.230] 417.026704ms
2023/03/19 08:50:54 [Debug] app/dns: domain quic.nginx.org matches following rules: [nginx.org(DNS idx:0)]
2023/03/19 08:50:54 [Debug] app/dns: domain quic.nginx.org will use DNS in order: [DOH//1.1.1.1] [TypeA]
2023/03/19 08:50:54 [Debug] app/dns: domain quic.nginx.org will use DNS in order: [DOH//1.1.1.1] [TypeAAAA]
2023/03/19 08:50:54 [Info] app/dns: DOH//1.1.1.1 querying: quic.nginx.org.
2023/03/19 08:50:54 [Info] app/dns: DOH//1.1.1.1 got answer: quic.nginx.org. TypeAAAA -> [] 416.473492ms
2023/03/19 08:50:56 [Info] [3127533985] app/dispatcher: sniffed domain: quic.nginx.org for tcp:35.214.218.230:443
2023/03/19 08:50:56 [Info] [3127533985] app/dispatcher: taking detour [proxy] for [tcp:quic.nginx.org:443]
2023/03/19 08:50:57 [Info] [3127533985] proxy/vmess/outbound: tunneling request to tcp:quic.nginx.org:443 via cf:443
2023/03/19 08:51:01 [Info] [3818921917] app/dispatcher: sniffed domain: quic.nginx.org for udp:35.214.218.230:443
2023/03/19 08:51:01 [Info] [3818921917] app/dispatcher: taking detour [proxy] for [udp:quic.nginx.org:443]
2023/03/19 08:51:01 [Info] [3818921917] proxy/vmess/outbound: tunneling request to udp:quic.nginx.org:443 via cf:443

2023/03/19 08:50:56 192.168.1.4:12622 accepted tcp:35.214.218.230:443 [proxy]
2023/03/19 08:50:56 192.168.1.4:12622 accepted tcp:35.214.218.230:443 [proxy]
2023/03/19 08:51:01 [Debug] transport/internet/udp: UDP original destination: udp:35.214.218.230:443
2023/03/19 08:51:01 192.168.1.4:54406 accepted udp:35.214.218.230:443 [proxy]

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