XHTTP client: Move x_padding into Referer header (#4298)

""Breaking"": Update the server side first, then client
This commit is contained in:
rPDmYQ 2025-01-18 20:05:19 +08:00 committed by GitHub
parent 30cb22afb1
commit 14a6636a41
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 182 additions and 59 deletions

View file

@ -4,6 +4,7 @@ import (
"crypto/rand"
"math/big"
"net/http"
"net/url"
"strings"
"github.com/xtls/xray-core/common"
@ -11,6 +12,8 @@ import (
"github.com/xtls/xray-core/transport/internet"
)
const paddingQuery = "x_padding"
func (c *Config) GetNormalizedPath() string {
pathAndQuery := strings.SplitN(c.Path, "?", 2)
path := pathAndQuery[0]
@ -39,11 +42,6 @@ func (c *Config) GetNormalizedQuery() string {
}
query += "x_version=" + core.Version()
paddingLen := c.GetNormalizedXPaddingBytes().rand()
if paddingLen > 0 {
query += "&x_padding=" + strings.Repeat("0", int(paddingLen))
}
return query
}
@ -53,6 +51,28 @@ func (c *Config) GetRequestHeader() http.Header {
header.Add(k, v)
}
paddingLen := c.GetNormalizedXPaddingBytes().rand()
if paddingLen > 0 {
query, err := url.ParseQuery(c.GetNormalizedQuery())
if err != nil {
query = url.Values{}
}
// https://www.rfc-editor.org/rfc/rfc7541.html#appendix-B
// h2's HPACK Header Compression feature employs a huffman encoding using a static table.
// 'X' is assigned an 8 bit code, so HPACK compression won't change actual padding length on the wire.
// https://www.rfc-editor.org/rfc/rfc9204.html#section-4.1.2-2
// h3's similar QPACK feature uses the same huffman table.
query.Set(paddingQuery, strings.Repeat("X", int(paddingLen)))
referrer := url.URL{
Scheme: "https", // maybe http actually, but this part is not being checked
Host: c.Host,
Path: c.GetNormalizedPath(),
RawQuery: query.Encode(),
}
header.Set("Referer", referrer.String())
}
return header
}
@ -63,7 +83,7 @@ func (c *Config) WriteResponseHeader(writer http.ResponseWriter) {
writer.Header().Set("X-Version", core.Version())
paddingLen := c.GetNormalizedXPaddingBytes().rand()
if paddingLen > 0 {
writer.Header().Set("X-Padding", strings.Repeat("0", int(paddingLen)))
writer.Header().Set("X-Padding", strings.Repeat("X", int(paddingLen)))
}
}