1
0
mirror of https://github.com/v2fly/v2ray-core.git synced 2026-06-22 02:39:55 -04:00

move sniffer to their own directory

This commit is contained in:
Darien Raymond
2018-07-16 12:56:50 +02:00
parent eafe580be4
commit 8912e4eb90
5 changed files with 477 additions and 0 deletions

View File

@@ -0,0 +1,90 @@
package http
import (
"bytes"
"errors"
"strings"
"v2ray.com/core"
)
type version byte
const (
HTTP1 version = iota
HTTP2
)
type SniffHeader struct {
version version
host string
}
func (h *SniffHeader) Protocol() string {
switch h.version {
case HTTP1:
return "http1"
case HTTP2:
return "http2"
default:
return "unknown"
}
}
func (h *SniffHeader) Domain() string {
return h.host
}
var (
methods = [...]string{"get", "post", "head", "put", "delete", "options", "connect"}
errNotHTTPMethod = errors.New("not an HTTP method")
)
func beginWithHTTPMethod(b []byte) error {
for _, m := range methods {
if len(b) >= len(m) && strings.ToLower(string(b[:len(m)])) == m {
return nil
}
if len(b) < len(m) {
return core.ErrNoClue
}
}
return errNotHTTPMethod
}
func SniffHTTP(b []byte) (*SniffHeader, error) {
if err := beginWithHTTPMethod(b); err != nil {
return nil, err
}
sh := &SniffHeader{
version: HTTP1,
}
headers := bytes.Split(b, []byte{'\n'})
for i := 1; i < len(headers); i++ {
header := headers[i]
if len(header) == 0 {
return nil, core.ErrNoClue
}
parts := bytes.SplitN(header, []byte{':'}, 2)
if len(parts) != 2 {
continue
}
key := strings.ToLower(string(parts[0]))
value := strings.ToLower(string(bytes.Trim(parts[1], " ")))
if key == "host" {
domain := strings.Split(value, ":")
sh.host = strings.TrimSpace(domain[0])
}
}
if len(sh.host) > 0 {
return sh, nil
}
return nil, core.ErrNoClue
}

View File

@@ -0,0 +1,106 @@
package http_test
import (
"testing"
"v2ray.com/core/common/compare"
. "v2ray.com/core/common/protocol/http"
)
func TestHTTPHeaders(t *testing.T) {
cases := []struct {
input string
domain string
err bool
}{
{
input: `GET /tutorials/other/top-20-mysql-best-practices/ HTTP/1.1
Host: net.tutsplus.com
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 (.NET CLR 3.5.30729)
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Cookie: PHPSESSID=r2t5uvjq435r4q7ib3vtdjq120
Pragma: no-cache
Cache-Control: no-cache`,
domain: "net.tutsplus.com",
},
{
input: `POST /foo.php HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 (.NET CLR 3.5.30729)
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Referer: http://localhost/test.php
Content-Type: application/x-www-form-urlencoded
Content-Length: 43
first_name=John&last_name=Doe&action=Submit`,
domain: "localhost",
},
{
input: `X /foo.php HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 (.NET CLR 3.5.30729)
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Referer: http://localhost/test.php
Content-Type: application/x-www-form-urlencoded
Content-Length: 43
first_name=John&last_name=Doe&action=Submit`,
domain: "",
err: true,
},
{
input: `GET /foo.php HTTP/1.1
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 (.NET CLR 3.5.30729)
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Referer: http://localhost/test.php
Content-Type: application/x-www-form-urlencoded
Content-Length: 43
Host: localhost
first_name=John&last_name=Doe&action=Submit`,
domain: "",
err: true,
},
{
input: `GET /tutorials/other/top-20-mysql-best-practices/ HTTP/1.1`,
domain: "",
err: true,
},
}
for _, test := range cases {
header, err := SniffHTTP([]byte(test.input))
if test.err {
if err == nil {
t.Errorf("Expect error but nil, in test: %v", test)
}
} else {
if err != nil {
t.Errorf("Expect no error but actually %s in test %v", err.Error(), test)
}
if err := compare.StringEqualWithDetail(header.Domain(), test.domain); err != nil {
t.Error(err)
}
}
}
}