diff --git a/packet/http.go b/packet/http.go index 5ca57f3..8cf38d7 100644 --- a/packet/http.go +++ b/packet/http.go @@ -53,11 +53,7 @@ type HttpPacket struct { version string } -func ParseUrl(raw []byte) { - -} - -func NewHttpPacketFromReader(rdr io.Reader) (*HttpPacket, error) { +func ReadHttpPacket(rdr io.Reader) (*HttpPacket, error) { sb := strings.Builder{} tee := io.TeeReader(rdr, &sb) p := &HttpPacket{} diff --git a/packet/https.go b/packet/https.go index fc857b2..49abeb8 100644 --- a/packet/https.go +++ b/packet/https.go @@ -1,15 +1,66 @@ package packet -type HttpsPacket struct { - raw []byte +import ( + "encoding/binary" + "io" +) + +type TLSMessageType byte + +const ( + TLSHeaderLen = 5 + TLSInvalid TLSMessageType = 0x0 + TLSChangeCipherSpec TLSMessageType = 0x14 + TLSAlert TLSMessageType = 0x15 + TLSHandshake TLSMessageType = 0x16 + TLSApplicationData TLSMessageType = 0x17 + TLSHeartbeat TLSMessageType = 0x18 +) + +type TLSMessage struct { + Header TLSHeader + Raw []byte //Header + Payload + RawHeader []byte + RawPayload []byte } -func NewHttpsPacket(raw []byte) HttpsPacket { - return HttpsPacket{ - raw: raw, +type TLSHeader struct { + Type TLSMessageType + ProtoVersion uint16 // major | minor + PayloadLen uint16 +} + +func ReadTLSMessage(r io.Reader) (*TLSMessage, error) { + var rawHeader [TLSHeaderLen]byte + _, err := io.ReadFull(r, rawHeader[:]) + if err != nil { + return nil, err } + + header := TLSHeader{ + Type: TLSMessageType(rawHeader[0]), + ProtoVersion: binary.BigEndian.Uint16(rawHeader[1:3]), + PayloadLen: binary.BigEndian.Uint16(rawHeader[3:5]), + } + + raw := make([]byte, header.PayloadLen+TLSHeaderLen) + copy(raw[0:TLSHeaderLen], rawHeader[:]) + _, err = io.ReadFull(r, raw[TLSHeaderLen:]) + if err != nil { + return nil, err + } + + hello := &TLSMessage{ + Header: header, + Raw: raw, + RawHeader: raw[:TLSHeaderLen], + RawPayload: raw[TLSHeaderLen:], + } + return hello, nil } -func (p *HttpsPacket) Raw() []byte { - return p.raw +func (m *TLSMessage) IsClientHello() bool { + // According to RFC 8446 section 4. + // first byte (Raw[5]) of handshake message should be 0x1 - means client_hello + return m.Header.Type == TLSHandshake && m.Raw[5] == 0x01 } diff --git a/proxy/client_hello.go b/proxy/client_hello.go deleted file mode 100644 index 09d1f57..0000000 --- a/proxy/client_hello.go +++ /dev/null @@ -1,66 +0,0 @@ -package proxy - -import ( - "encoding/binary" - "io" -) - -const headerLen = 5 - -type TLSMessageType byte - -const ( - TLSInvalid TLSMessageType = 0x0 - TLSChangeCipherSpec TLSMessageType = 0x14 - TLSAlert TLSMessageType = 0x15 - TLSHandshake TLSMessageType = 0x16 - TLSApplicationData TLSMessageType = 0x17 - TLSHeartbeat TLSMessageType = 0x18 -) - -type TlsMessage struct { - Header TlsHeader - Raw []byte //Header + Payload - RawHeader []byte - RawPayload []byte -} - -type TlsHeader struct { - Type TLSMessageType - ProtoVersion uint16 // major | minor - PayloadLen uint16 -} - -func ReadTlsMessage(r io.Reader) (*TlsMessage, error) { - var rawHeader [5]byte - _, err := io.ReadFull(r, rawHeader[:]) - if err != nil { - return nil, err - } - - header := TlsHeader{ - Type: TLSMessageType(rawHeader[0]), - ProtoVersion: binary.BigEndian.Uint16(rawHeader[1:3]), - PayloadLen: binary.BigEndian.Uint16(rawHeader[3:5]), - } - raw := make([]byte, header.PayloadLen+headerLen) - copy(raw[0:headerLen], rawHeader[:]) - _, err = io.ReadFull(r, raw[headerLen:]) - if err != nil { - return nil, err - } - hello := &TlsMessage{ - Header: header, - Raw: raw, - RawHeader: raw[:headerLen], - RawPayload: raw[headerLen:], - } - return hello, nil -} - -func IsClientHello(message *TlsMessage) bool { - // According to RFC 8446 section 4. - // first byte (Raw[5]) of handshake message should be 0x1 - means client_hello - return message.Header.Type == TLSHandshake && - message.Raw[5] == 0x1 -} diff --git a/proxy/https.go b/proxy/https.go index 94eb1c4..c4f256e 100644 --- a/proxy/https.go +++ b/proxy/https.go @@ -45,8 +45,8 @@ func (pxy *Proxy) handleHttps(lConn *net.TCPConn, exploit bool, initPkt *packet. log.Debug("[HTTPS] Sent 200 Connection Estabalished to ", lConn.RemoteAddr()) // Read client hello - m, err := ReadTlsMessage(lConn) - if err != nil || !IsClientHello(m) { + m, err := packet.ReadTLSMessage(lConn) + if err != nil || !m.IsClientHello() { log.Debug("[HTTPS] Error reading client hello from the client", err) return } @@ -55,24 +55,18 @@ func (pxy *Proxy) handleHttps(lConn *net.TCPConn, exploit bool, initPkt *packet. log.Debug("[HTTPS] Client sent hello ", len(clientHello), "bytes") // Generate a go routine that reads from the server - - chPkt := packet.NewHttpsPacket(clientHello) - - // lConn.SetLinger(3) - // rConn.SetLinger(3) - go Serve(rConn, lConn, "[HTTPS]", rConn.RemoteAddr().String(), initPkt.Domain(), pxy.timeout, pxy.bufferSize) if exploit { log.Debug("[HTTPS] Writing chunked client hello to ", initPkt.Domain()) - chunks := splitInChunks(chPkt.Raw(), pxy.windowSize) - if _, err := WriteChunks(rConn, chunks); err != nil { + chunks := splitInChunks(clientHello, pxy.windowSize) + if _, err := writeChunks(rConn, chunks); err != nil { log.Debug("[HTTPS] Error writing chunked client hello to ", initPkt.Domain(), err) return } } else { log.Debug("[HTTPS] Writing plain client hello to ", initPkt.Domain()) - if _, err := rConn.Write(chPkt.Raw()); err != nil { + if _, err := rConn.Write(clientHello); err != nil { log.Debug("[HTTPS] Error writing plain client hello to ", initPkt.Domain(), err) return } @@ -116,3 +110,18 @@ func splitInChunks(bytes []byte, size int) [][]byte { return [][]byte{raw[:1], raw[1:]} } + +func writeChunks(conn *net.TCPConn, c [][]byte) (n int, err error) { + total := 0 + for i := 0; i < len(c); i++ { + b, err := conn.Write(c[i]) + if err != nil { + return 0, nil + } + + total += b + } + + return total, nil +} + diff --git a/proxy/proxy.go b/proxy/proxy.go index f1a7701..4fd2bb1 100644 --- a/proxy/proxy.go +++ b/proxy/proxy.go @@ -13,7 +13,7 @@ import ( "github.com/xvzc/SpoofDPI/util" ) -const BUFFER_SIZE = 1024 +const BufferSize = 1024 type Proxy struct { addr string @@ -33,7 +33,7 @@ func New(config *util.Config) *Proxy { windowSize: *config.WindowSize, allowedPattern: config.AllowedPattern, resolver: dns.NewResolver(config), - bufferSize: BUFFER_SIZE, + bufferSize: BufferSize, } } @@ -61,19 +61,15 @@ func (pxy *Proxy) Start() { } go func() { - pkt, err := packet.NewHttpPacketFromReader(conn) - if err != nil { - return - } - - log.Debug("[PROXY] Request from ", conn.RemoteAddr(), "\n\n", string(pkt.Raw())) - + pkt, err := packet.ReadHttpPacket(conn) if err != nil { log.Debug("[PROXY] Error while parsing request: ", string(pkt.Raw())) conn.Close() return } + log.Debug("[PROXY] Request from ", conn.RemoteAddr(), "\n\n", string(pkt.Raw())) + if !pkt.IsValidMethod() { log.Debug("[PROXY] Unsupported method: ", pkt.Method()) conn.Close() diff --git a/proxy/io.go b/proxy/server.go similarity index 83% rename from proxy/io.go rename to proxy/server.go index bb58c7e..8b4aca8 100644 --- a/proxy/io.go +++ b/proxy/server.go @@ -9,19 +9,7 @@ import ( log "github.com/sirupsen/logrus" ) -func WriteChunks(conn *net.TCPConn, c [][]byte) (n int, err error) { - total := 0 - for i := 0; i < len(c); i++ { - b, err := conn.Write(c[i]) - if err != nil { - return 0, nil - } - - total += b - } - - return total, nil -} +const TLSHeaderLen = 5 func ReadBytes(conn *net.TCPConn, dest []byte) ([]byte, error) { n, err := readBytesInternal(conn, dest)