SpoofDPI/packet/http.go

159 lines
2.6 KiB
Go
Raw Normal View History

2022-01-08 06:35:32 +00:00
package packet
2022-01-07 17:41:02 +00:00
import (
2022-05-09 01:57:34 +00:00
"bufio"
"io"
2022-05-09 01:57:34 +00:00
"net"
"net/http"
2022-01-07 17:41:02 +00:00
"strings"
)
2022-01-10 19:27:12 +00:00
var validMethod = map[string]struct{}{
"DELETE": {},
"GET": {},
"HEAD": {},
"POST": {},
"PUT": {},
"CONNECT": {},
"OPTIONS": {},
"TRACE": {},
"COPY": {},
"LOCK": {},
"MKCOL": {},
"MOVE": {},
"PROPFIND": {},
"PROPPATCH": {},
"SEARCH": {},
"UNLOCK": {},
"BIND": {},
"REBIND": {},
"UNBIND": {},
"ACL": {},
"REPORT": {},
"MKACTIVITY": {},
"CHECKOUT": {},
"MERGE": {},
"M-SEARCH": {},
"NOTIFY": {},
"SUBSCRIBE": {},
"UNSUBSCRIBE": {},
"PATCH": {},
"PURGE": {},
"MKCALENDAR": {},
"LINK": {},
"UNLINK": {},
}
type HttpRequest struct {
2022-01-11 17:15:45 +00:00
raw []byte
method string
domain string
2022-11-29 07:54:28 +00:00
port string
2022-01-15 16:44:00 +00:00
path string
2022-01-11 17:15:45 +00:00
version string
2022-01-07 17:41:02 +00:00
}
func ReadHttpRequest(rdr io.Reader) (*HttpRequest, error) {
2024-08-14 17:39:23 +00:00
p, err := parse(rdr)
if err != nil {
return nil, err
}
2024-08-14 17:39:23 +00:00
return p, nil
2022-01-07 18:01:54 +00:00
}
func (p *HttpRequest) Raw() []byte {
2022-01-11 17:15:45 +00:00
return p.raw
}
func (p *HttpRequest) Method() string {
2022-01-11 17:15:45 +00:00
return p.method
}
2022-01-15 16:44:00 +00:00
func (p *HttpRequest) Domain() string {
2022-01-11 17:15:45 +00:00
return p.domain
}
2022-01-15 16:44:00 +00:00
func (p *HttpRequest) Port() string {
2022-03-05 02:51:17 +00:00
return p.port
}
func (p *HttpRequest) Version() string {
2022-01-11 17:15:45 +00:00
return p.version
}
func (p *HttpRequest) IsValidMethod() bool {
2022-01-11 17:15:45 +00:00
if _, exists := validMethod[p.Method()]; exists {
2022-01-07 17:41:02 +00:00
return true
}
return false
}
func (p *HttpRequest) IsConnectMethod() bool {
2022-01-11 17:15:45 +00:00
return p.Method() == "CONNECT"
2022-01-07 17:41:02 +00:00
}
func (p *HttpRequest) Tidy() {
2022-01-14 21:40:57 +00:00
s := string(p.raw)
2022-03-04 23:49:28 +00:00
lines := strings.Split(s, "\r\n")
2022-01-15 16:44:00 +00:00
lines[0] = p.method + " " + p.path + " " + p.version
2022-01-14 21:40:57 +00:00
for i := 0; i < len(lines); i++ {
if strings.HasPrefix(lines[i], "Proxy-Connection") {
lines[i] = ""
}
}
result := ""
2022-03-04 23:49:28 +00:00
2022-01-14 21:40:57 +00:00
for i := 0; i < len(lines); i++ {
if lines[i] == "" {
continue
}
2022-03-04 23:49:28 +00:00
result += lines[i] + "\r\n"
2022-01-14 21:40:57 +00:00
}
2022-11-29 07:54:28 +00:00
result += "\r\n"
2022-03-04 23:49:28 +00:00
2022-01-14 21:40:57 +00:00
p.raw = []byte(result)
}
func parse(rdr io.Reader) (*HttpRequest, error) {
2024-08-14 17:39:23 +00:00
sb := strings.Builder{}
tee := io.TeeReader(rdr, &sb)
request, err := http.ReadRequest(bufio.NewReader(tee))
2022-11-29 07:54:28 +00:00
if err != nil {
2024-08-14 17:39:23 +00:00
return nil, err
2022-11-29 07:54:28 +00:00
}
p := &HttpRequest{}
2024-08-14 17:39:23 +00:00
p.raw = []byte(sb.String())
2022-11-29 07:54:28 +00:00
p.domain, p.port, err = net.SplitHostPort(request.Host)
if err != nil {
p.domain = request.Host
p.port = ""
}
p.method = request.Method
p.version = request.Proto
p.path = request.URL.Path
if request.URL.RawQuery != "" {
p.path += "?" + request.URL.RawQuery
}
if request.URL.RawFragment != "" {
p.path += "#" + request.URL.RawFragment
}
if p.path == "" {
p.path = "/"
}
request.Body.Close()
2024-08-14 17:39:23 +00:00
return p, nil
2022-01-07 17:41:02 +00:00
}