mirror of
https://github.com/XTLS/Xray-core.git
synced 2024-11-21 16:11:31 +00:00
Sniff: Routing “attrs” support non http inbound (#3808)
* Sniff: Support attrs route in non http inbound * Add capability to sniff method and path * Fix test * Skip HTTP inbound PlainHTTP mode * Fix test again
This commit is contained in:
parent
c259e4e4a6
commit
88ae774cce
|
@ -35,7 +35,7 @@ type Sniffer struct {
|
|||
func NewSniffer(ctx context.Context) *Sniffer {
|
||||
ret := &Sniffer{
|
||||
sniffer: []protocolSnifferWithMetadata{
|
||||
{func(c context.Context, b []byte) (SniffResult, error) { return http.SniffHTTP(b) }, false, net.Network_TCP},
|
||||
{func(c context.Context, b []byte) (SniffResult, error) { return http.SniffHTTP(b, c) }, false, net.Network_TCP},
|
||||
{func(c context.Context, b []byte) (SniffResult, error) { return tls.SniffTLS(b) }, false, net.Network_TCP},
|
||||
{func(c context.Context, b []byte) (SniffResult, error) { return bittorrent.SniffBittorrent(b) }, false, net.Network_TCP},
|
||||
{func(c context.Context, b []byte) (SniffResult, error) { return quic.SniffQUIC(b) }, false, net.Network_UDP},
|
||||
|
|
|
@ -2,11 +2,13 @@ package http
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"strings"
|
||||
|
||||
"github.com/xtls/xray-core/common"
|
||||
"github.com/xtls/xray-core/common/net"
|
||||
"github.com/xtls/xray-core/common/session"
|
||||
)
|
||||
|
||||
type version byte
|
||||
|
@ -56,7 +58,14 @@ func beginWithHTTPMethod(b []byte) error {
|
|||
return errNotHTTPMethod
|
||||
}
|
||||
|
||||
func SniffHTTP(b []byte) (*SniffHeader, error) {
|
||||
func SniffHTTP(b []byte, c context.Context) (*SniffHeader, error) {
|
||||
content := session.ContentFromContext(c)
|
||||
ShouldSniffAttr := true
|
||||
// If content.Attributes have information, that means it comes from HTTP inbound PlainHTTP mode.
|
||||
// It will set attributes, so skip it.
|
||||
if content == nil || len(content.Attributes) != 0 {
|
||||
ShouldSniffAttr = false
|
||||
}
|
||||
if err := beginWithHTTPMethod(b); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -76,8 +85,12 @@ func SniffHTTP(b []byte) (*SniffHeader, error) {
|
|||
continue
|
||||
}
|
||||
key := strings.ToLower(string(parts[0]))
|
||||
value := string(bytes.TrimSpace(parts[1]))
|
||||
if ShouldSniffAttr {
|
||||
content.SetAttribute(key, value) // Put header in attribute
|
||||
}
|
||||
if key == "host" {
|
||||
rawHost := strings.ToLower(string(bytes.TrimSpace(parts[1])))
|
||||
rawHost := strings.ToLower(value)
|
||||
dest, err := ParseHost(rawHost, net.Port(80))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -85,6 +98,16 @@ func SniffHTTP(b []byte) (*SniffHeader, error) {
|
|||
sh.host = dest.Address.String()
|
||||
}
|
||||
}
|
||||
// Parse request line
|
||||
// Request line is like this
|
||||
// "GET /homo/114514 HTTP/1.1"
|
||||
if len(headers) > 0 && ShouldSniffAttr {
|
||||
RequestLineParts := bytes.Split(headers[0], []byte{' '})
|
||||
if len(RequestLineParts) == 3 {
|
||||
content.SetAttribute(":method", string(RequestLineParts[0]))
|
||||
content.SetAttribute(":path", string(RequestLineParts[1]))
|
||||
}
|
||||
}
|
||||
|
||||
if len(sh.host) > 0 {
|
||||
return sh, nil
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package http_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
. "github.com/xtls/xray-core/common/protocol/http"
|
||||
|
@ -88,7 +89,7 @@ first_name=John&last_name=Doe&action=Submit`,
|
|||
}
|
||||
|
||||
for _, test := range cases {
|
||||
header, err := SniffHTTP([]byte(test.input))
|
||||
header, err := SniffHTTP([]byte(test.input), context.TODO())
|
||||
if test.err {
|
||||
if err == nil {
|
||||
t.Errorf("Expect error but nil, in test: %v", test)
|
||||
|
|
Loading…
Reference in a new issue