136 linhas
2,9 KiB
Go
136 linhas
2,9 KiB
Go
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"log"
|
|
"net/http"
|
|
"net/http/httputil"
|
|
"regexp"
|
|
"strings"
|
|
)
|
|
|
|
func passAndLearn(resp *http.Response) error {
|
|
|
|
ProxyFlow.response = resp
|
|
ProxyFlow.seniority++
|
|
req := ProxyFlow.request
|
|
|
|
switch {
|
|
case resp.StatusCode == 401:
|
|
log.Println("401: We don't want to store credentials")
|
|
case resp.StatusCode > 399:
|
|
buf := bytes.NewBufferString(BlockMessage)
|
|
resp.Body = ioutil.NopCloser(buf)
|
|
resp.Status = "403 Forbidden"
|
|
resp.StatusCode = 403
|
|
resp.Header["Content-Length"] = []string{fmt.Sprint(buf.Len())}
|
|
resp.Header.Set("Content-Encoding", "none")
|
|
log.Println("Filing inside bad class")
|
|
feedRequest(req, "BAD")
|
|
ControPlane.StatsTokens <- "LEARN-BAD"
|
|
default:
|
|
log.Println("Filing inside Good Class: ", resp.StatusCode)
|
|
feedRequest(req, "GOOD")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func blockAndlearn(resp *http.Response) error {
|
|
|
|
ProxyFlow.response = resp
|
|
ProxyFlow.seniority++
|
|
req := ProxyFlow.request
|
|
|
|
buf := bytes.NewBufferString(BlockMessage)
|
|
resp.Body = ioutil.NopCloser(buf)
|
|
resp.Status = "403 Forbidden"
|
|
resp.StatusCode = 403
|
|
resp.Header["Content-Length"] = []string{fmt.Sprint(buf.Len())}
|
|
resp.Header.Set("Content-Encoding", "none")
|
|
|
|
switch {
|
|
case resp.StatusCode == 401:
|
|
log.Println("401: We don't want to store credentials")
|
|
case resp.StatusCode > 399:
|
|
log.Println("Filing inside bad class")
|
|
feedRequest(req, "BAD")
|
|
default:
|
|
log.Println("Filing inside Good Class: ", resp.StatusCode)
|
|
ControPlane.StatsTokens <- "LEARN-GOOD"
|
|
feedRequest(req, "GOOD")
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
func sanitizeHeaders(s string) string {
|
|
|
|
re := regexp.MustCompile(`[a-zA-Z]{4,32}|([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})|([0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12})`)
|
|
matched := re.FindAllString(s, -1)
|
|
|
|
uMatched := Unique(matched)
|
|
|
|
tmpSt := strings.ToLower(strings.Join(uMatched, " "))
|
|
|
|
log.Println("Matched: " + tmpSt)
|
|
|
|
return tmpSt
|
|
|
|
}
|
|
|
|
func feedRequest(req *http.Request, class string) {
|
|
|
|
feed := formatRequest(req)
|
|
|
|
if class == "BAD" {
|
|
|
|
log.Println("Feeding BAD token: ", feed)
|
|
|
|
ControPlane.BadTokens <- sanitizeHeaders(feed)
|
|
|
|
}
|
|
|
|
if class == "GOOD" {
|
|
|
|
log.Println("Feeding GOOD Token:", feed)
|
|
|
|
ControPlane.GoodTokens <- sanitizeHeaders(feed)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
func formatRequest(req *http.Request) string {
|
|
|
|
ingestBody := req.ContentLength < 2048 && req.ContentLength > 1
|
|
|
|
log.Println("Ingesting the body: ", ingestBody)
|
|
|
|
requestDump, err := httputil.DumpRequest(req, ingestBody)
|
|
if err != nil {
|
|
fmt.Println(err)
|
|
}
|
|
|
|
return fmt.Sprintf("%s\n", requestDump)
|
|
|
|
}
|
|
|
|
//Unique returns unique elements in the string
|
|
func Unique(slice []string) []string {
|
|
// create a map with all the values as key
|
|
uniqMap := make(map[string]struct{})
|
|
for _, v := range slice {
|
|
uniqMap[v] = struct{}{}
|
|
}
|
|
|
|
// turn the map keys into a slice
|
|
uniqSlice := make([]string, 0, len(uniqMap))
|
|
for v := range uniqMap {
|
|
uniqSlice = append(uniqSlice, v)
|
|
}
|
|
return uniqSlice
|
|
}
|