golang 写一个万能waf 和cdn

 

main.go

package main

import (
   "log"
   "net/http"
)
var cmd Cmd
var srv http.Server

func StartServer(bind string, remote string)  {
   log.Printf("Listening on %s, forwarding to %s", bind, remote)
   h := &handle{reverseProxy: remote}
   srv.Addr = bind
   srv.Handler = h
   //go func() {
      if err := srv.ListenAndServe(); err != nil {
         log.Fatalln("ListenAndServe: ", err)
      }
   //}()
}

func StopServer()  {
   if err := srv.Shutdown(nil) ; err != nil {
      log.Println(err)
   }
}

cmd.go

package main

import "flag"

type Cmd struct {
   bind string
   remote string
   ip string
}

func parseCmd() Cmd {
   var cmd Cmd
   flag.StringVar(&cmd.bind, "l", "0.0.0.0:8080", "listen on ip:port")
   flag.StringVar(&cmd.remote, "r", "https://www.xunblog.com", "reverse proxy addr")
   flag.StringVar(&cmd.ip, "ip", "", "reverse proxy addr server ip")
   flag.Parse()
   return cmd
}

 

handle.go

package main

import (
   "context"
   "fmt"
   "io/ioutil"
   "log"
   "math/rand"
   "net"
   "net/http"
   "net/http/httputil"
   "net/url"
   "os"
   "strings"
   "time"
)

type handle struct {
   reverseProxy string
}

func GetRandomString(len int) string{
   str := "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
   bytes := []byte(str)
   result := []byte{}
   r := rand.New(rand.NewSource(time.Now().UnixNano()))
   for i := 0; i < len; i++ {
      result = append(result, bytes[r.Intn(62)])
   }
   return string(result)
}
func (this *handle) ServeHTTP(w http.ResponseWriter, r *http.Request) {
   normallogFile, err1 := os.OpenFile("normal.log", os.O_CREATE|os.O_RDWR|os.O_APPEND, 0666)
   highlogFile, err2 := os.OpenFile("high.log", os.O_CREATE|os.O_RDWR|os.O_APPEND, 0666)
   if err1 != nil {
      log.Fatalln("fail to create normal.log file!")
   }
   if err2 != nil {
      log.Fatalln("fail to create high.log file!")
   }
   post, _ := ioutil.ReadAll(r.Body)
   r.Body = ioutil.NopCloser(strings.NewReader(string(post)))
   log.SetOutput(normallogFile)
   //log.Println(r.RemoteAddr + " " + r.Method + " " + r.URL.String() + " " + r.Proto + " " + r.UserAgent() + " " + string(post))
   if string(post) != ""{
      log.Println(r.RemoteAddr + " " + r.Method + " " + r.URL.String() + " " + r.Proto + " " + r.UserAgent() + "  " + string(post))
   }else {
      log.Println(r.RemoteAddr + " " + r.Method + " " + r.URL.String() + " " + r.Proto + " " + r.UserAgent())
   }
   query ,_ := url.PathUnescape(r.URL.String())
   postdata ,_ := url.PathUnescape(string(post))
   if strings.Contains(strings.ToLower(query),"flag")||strings.Contains(strings.ToLower(postdata),"flag"){
      fmt.Fprintln(w,GetRandomString(20))
      log.SetOutput(highlogFile)
      if string(post) != ""{
         log.Println(r.RemoteAddr + " " + r.Method + " " + r.URL.String() + " " + r.Proto + " " + r.UserAgent() + "  " + string(post))
      }else {
         log.Println(r.RemoteAddr + " " + r.Method + " " + r.URL.String() + " " + r.Proto + " " + r.UserAgent())
      }

   }else {
      remote, err := url.Parse(this.reverseProxy)
      if err != nil {
         log.Fatalln(err)
      }
      dialer := &net.Dialer{
         Timeout:   30 * time.Second,
         KeepAlive: 30 * time.Second,
         DualStack: true,
      }
      http.DefaultTransport.(*http.Transport).DialContext = func(ctx context.Context, network, addr string) (net.Conn, error) {
         //remote := strings.Split(addr, ":")
         //if cmd.ip == "" {
         // resolver := dns_resolver.New([]string{"114.114.114.114", "114.114.115.115", "119.29.29.29", "223.5.5.5", "8.8.8.8", "208.67.222.222", "208.67.220.220"})
         // resolver.RetryTimes = 5
         // ip, err := resolver.LookupHost(remote[0])
         // if err != nil {
         //    log.Println(err)
         // }
         // fmt.Println(cmd.ip)
         // cmd.ip = ip[0].String()
         //
         //}
         //addr = cmd.ip + ":" + remote[1]
         return dialer.DialContext(ctx, network, addr)
      }
      proxy := httputil.NewSingleHostReverseProxy(remote)
      r.Host = remote.Host
      proxy.ServeHTTP(w, r)
   }
}

 

当时比赛写的端口转发,监听发送包和返回包里有flag 字符串的话 则返回随机的flag,可以改成拦截恶意字符串,起到waf的作用,由于使用了端口转发,所以也可以起到cdn的作用。转发效率也相当可以

点赞

发表评论

电子邮件地址不会被公开。 必填项已用*标注