SpoofDPI/packet/http.go
2022-05-08 20:38:00 +09:00

180 lines
2.8 KiB
Go

package packet
import (
"errors"
"strings"
)
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 HttpPacket struct {
raw []byte
method string
domain string
port string
path string
version string
}
func ParseUrl(raw []byte) {
}
func NewHttpPacket(raw []byte) (*HttpPacket, error){
pkt := &HttpPacket{raw: raw}
pkt.parse()
return pkt, nil
}
func (p *HttpPacket) Raw() []byte {
return p.raw
}
func (p *HttpPacket) Method() string {
return p.method
}
func (p *HttpPacket) Domain() string {
return p.domain
}
func (p *HttpPacket) Port() string {
return p.port
}
func (p *HttpPacket) Version() string {
return p.version
}
func (p *HttpPacket) IsValidMethod() bool {
if _, exists := validMethod[p.Method()]; exists {
return true
}
return false
}
func (p *HttpPacket) IsConnectMethod() bool {
return p.Method() == "CONNECT"
}
func (p *HttpPacket) Tidy() {
s := string(p.raw)
lines := strings.Split(s, "\r\n")
lines[0] = p.method + " " + p.path + " " + p.version
for i := 0; i < len(lines); i++ {
if strings.HasPrefix(lines[i], "Proxy-Connection") {
lines[i] = ""
}
}
result := ""
for i := 0; i < len(lines); i++ {
if lines[i] == "" {
continue
}
result += lines[i] + "\r\n"
}
result += "\r\n"
p.raw = []byte(result)
}
func (p *HttpPacket )parse() error {
var firstLine string
for i := 0; i < len(p.raw); i++ {
if (p.raw)[i] == '\r' {
firstLine = string(p.raw[:i])
break
}
}
tokens := strings.Split(firstLine, " ")
if (len(tokens) < 3) {
return errors.New("Error parsing http request")
}
p.method = tokens[0]
url := tokens[1]
p.version = tokens[2]
if strings.HasPrefix(url, "http://") {
url = strings.Replace(url, "http://", "", 1)
}
if strings.HasPrefix(url, "https://") {
url = strings.Replace(url, "https://", "", 1)
}
domain := ""
port := ""
for i := 0; i < len(url); i++ {
if url[i] == ':' {
domain = url[:i]
port = url[i:]
break
}
if url[i] == '/' {
domain = url[:i]
break
}
}
p.domain = domain
p.port = port
path := "/"
for i := 0; i < len(url); i++ {
if url[i] == '/' {
path = url[i:]
break
}
}
p.path = path
return nil
}