This commit is contained in:
maintell
2021-12-16 16:31:40 +08:00
parent 995bcc77c6
commit c27d0f03ba
7 changed files with 435 additions and 2 deletions
+2
View File
@@ -0,0 +1,2 @@
.idea
bin
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2020 maintell
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+40 -2
View File
@@ -1,4 +1,42 @@
# webBenchmark
a simple tool of website benchmark.
http benchmark tool to ran out your server bandwidth.
- random User-Agent on every Request
- customizable Referer Url,
- concurrent routines as you wish, depends on you server performance.
- add http post mode
- specify target ip, or resolved by system dns.
- randomly X-Forwarded-For and X-Real-IP (default on).
# Todo
- automatically tune concurrent routines to gain maximum performance.
- randomly target ip.
- support NOT standard port in address with specify target ip.
# Usage:
webBenchmark -c [COUNT] -s [URL] -r [REFERER]
-c int
concurrent routines for download (default 16)
-r string
referer url
-s string
target url (default "https://baidu.com")
-i string
customize ip
-f string
randomized X-Forwarded-For and X-Real-IP address
-p string
post content
# LINUX:
wget https://github.com/maintell/webBenchmark/releases/download/0.3/webBenchmark_linux_x64
chmod +x webBenchmark_linux_x64
./webBenchmark_linux_x64 -c 32 -s https://target.url
## advanced example
# send request to 1.1.1.1 for https://target.url with 32 concurrent threads
# and refer is https://refer.url
./webBenchmark_linux_x64 -c 32 -s https://target.url -r https://refer.url -i 1.1.1.1
# Usage: webBenchmark -c [COUNT] -s [URL] -r [Refer]
+14
View File
@@ -0,0 +1,14 @@
@echo off
SET CGO_ENABLED=0
SET GOOS=linux
SET GOARCH=amd64
go build -o webBenchmark_linux_x64
SET GOOS=linux
SET GOARCH=arm
go build -o webBenchmark_linux_arm
SET GOOS=windows
SET GOARCH=amd64
go build -o webBenchmark_x64.exe
SET GOOS=windows
SET GOARCH=arm
go build -o webBenchmark_x64_arm.exe
+17
View File
@@ -0,0 +1,17 @@
module github.com/maintell/webBenchmark
go 1.16
require (
github.com/EDDYCJY/fake-useragent v0.2.0
github.com/PuerkitoBio/goquery v1.6.1 // indirect
github.com/StackExchange/wmi v0.0.0-20210224194228-fe8f1750fd46 // indirect
github.com/apoorvam/goterminal v0.0.0-20180523175556-614d345c47e5
github.com/go-ole/go-ole v1.2.5 // indirect
github.com/mattn/go-isatty v0.0.12 // indirect
github.com/miekg/dns v1.1.43
github.com/shirou/gopsutil v3.21.4+incompatible
github.com/stretchr/testify v1.7.0 // indirect
github.com/tklauser/go-sysconf v0.3.6 // indirect
golang.org/x/sys v0.0.0-20210514084401-e8d321eab015 // indirect
)
+51
View File
@@ -0,0 +1,51 @@
github.com/EDDYCJY/fake-useragent v0.2.0 h1:Jcnkk2bgXmDpX0z+ELlUErTkoLb/mxFBNd2YdcpvJBs=
github.com/EDDYCJY/fake-useragent v0.2.0/go.mod h1:5wn3zzlDxhKW6NYknushqinPcAqZcAPHy8lLczCdJdc=
github.com/PuerkitoBio/goquery v1.6.1 h1:FgjbQZKl5HTmcn4sKBgvx8vv63nhyhIpv7lJpFGCWpk=
github.com/PuerkitoBio/goquery v1.6.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc=
github.com/StackExchange/wmi v0.0.0-20210224194228-fe8f1750fd46 h1:5sXbqlSomvdjlRbWyNqkPsJ3Fg+tQZCbgeX1VGljbQY=
github.com/StackExchange/wmi v0.0.0-20210224194228-fe8f1750fd46/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
github.com/andybalholm/cascadia v1.1.0 h1:BuuO6sSfQNFRu1LppgbD25Hr2vLYW25JvxHs5zzsLTo=
github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
github.com/apoorvam/goterminal v0.0.0-20180523175556-614d345c47e5 h1:VYqcjykqpcq262cDxBAkAelSdg6HETkxgwzQRTS40Aw=
github.com/apoorvam/goterminal v0.0.0-20180523175556-614d345c47e5/go.mod h1:E7x8aDc3AQzDKjEoIZCt+XYheHk2OkP+p2UgeNjecH8=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-ole/go-ole v1.2.5 h1:t4MGB5xEDZvXI+0rMjjsfBsD7yAgp/s9ZDkL1JndXwY=
github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/miekg/dns v1.1.43 h1:JKfpVSCB84vrAmHzyrsxB5NAr5kLoMXZArPSw7Qlgyg=
github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/shirou/gopsutil v3.21.4+incompatible h1:fuHcTm5mX+wzo542cmYcV9RTGQLbnHLI5SyQ5ryTVck=
github.com/shirou/gopsutil v3.21.4+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/tklauser/go-sysconf v0.3.6 h1:oc1sJWvKkmvIxhDHeKWvZS4f6AW+YcoguSfRF2/Hmo4=
github.com/tklauser/go-sysconf v0.3.6/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI=
github.com/tklauser/numcpus v0.2.2 h1:oyhllyrScuYI6g+h/zUvNXNp1wy7x8qQy3t/piefldA=
github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 h1:qWPm9rbaAMKs8Bq/9LRpbMqxWRVUAQwMI9fVrssnTfw=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210514084401-e8d321eab015 h1:hZR0X1kPW+nwyJ9xRxqZk1vx5RUObAPBdKVvXPDUH/E=
golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+290
View File
@@ -0,0 +1,290 @@
package main
import (
"container/list"
"context"
"flag"
"fmt"
"github.com/EDDYCJY/fake-useragent"
"io"
"io/ioutil"
"math"
"math/rand"
"net/http"
"os"
"strings"
"sync"
"time"
"github.com/miekg/dns"
"net"
URL "net/url"
"github.com/apoorvam/goterminal"
"github.com/shirou/gopsutil/cpu"
"github.com/shirou/gopsutil/load"
"github.com/shirou/gopsutil/mem"
netstat "github.com/shirou/gopsutil/net"
)
const (
letterIdxBits = 6
letterIdxMask = 1<<letterIdxBits - 1
letterIdxMax = 63 / letterIdxBits
)
type speedPair struct {
index uint64
speed float64
}
const letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
var SpeedQueue = list.New()
var SpeedIndex uint64 = 0
type ipArray []string
func (i *ipArray) String() string {
return strings.Join(*i, ",")
}
func (i *ipArray) Set(value string) error {
*i = append(*i, strings.TrimSpace(value))
return nil
}
func RandStringBytesMaskImpr(n int) string {
b := make([]byte, n)
for i, cache, remain := n-1, rand.Int63(), letterIdxMax; i >= 0; {
if remain == 0 {
cache, remain = rand.Int63(), letterIdxMax
}
if idx := int(cache & letterIdxMask); idx < len(letterBytes) {
b[i] = letterBytes[idx]
i--
}
cache >>= letterIdxBits
remain--
}
return string(b)
}
func generateRandomIPAddress() string {
rand.Seed(time.Now().Unix())
ip := fmt.Sprintf("%d.%d.%d.%d", rand.Intn(255), rand.Intn(255), rand.Intn(255), rand.Intn(255))
return ip
}
func LeastSquares(x []float64, y []float64) (a float64, b float64) {
xi := float64(0)
x2 := float64(0)
yi := float64(0)
xy := float64(0)
if len(x) != len(y) {
a = 0
b = 0
return
} else {
length := float64(len(x))
for i := 0; i < len(x); i++ {
xi += x[i]
x2 += x[i] * x[i]
yi += y[i]
xy += x[i] * y[i]
}
a = (yi*xi - xy*length) / (xi*xi - x2*length)
b = (yi*x2 - xy*xi) / (x2*length - xi*xi)
}
return
}
func showStat() {
initialNetCounter, _ := netstat.IOCounters(true)
iplist := ""
if customIP !=nil && len(customIP)>0{
iplist = customIP.String()
}else{
u, _ := URL.Parse(*url)
iplist = strings.Join(nslookup(u.Hostname(),"8.8.8.8"),",")
}
for true {
percent, _ := cpu.Percent(time.Second, false)
memStat, _ := mem.VirtualMemory()
netCounter, _ := netstat.IOCounters(true)
loadStat, _ := load.Avg()
fmt.Fprintf(TerminalWriter, "target URL:%s\n", *url)
fmt.Fprintf(TerminalWriter, "target IP:%s\n", iplist)
fmt.Fprintf(TerminalWriter, "cpu percent:%.3f%% \n", percent)
fmt.Fprintf(TerminalWriter, "mem percent:%.3f%% \n", memStat.UsedPercent)
fmt.Fprintf(TerminalWriter, "load info:%.3f %.3f %.3f\n", loadStat.Load1, loadStat.Load5, loadStat.Load15)
for i := 0; i < len(netCounter); i++ {
if netCounter[i].BytesRecv == 0 && netCounter[i].BytesSent == 0 {
continue
}
RecvBytes := float64(netCounter[i].BytesRecv - initialNetCounter[i].BytesRecv)
SendBytes := float64(netCounter[i].BytesSent - initialNetCounter[i].BytesSent)
//if RecvBytes > 1000 {
// SpeedIndex++
// pair := speedPair{
// index: SpeedIndex,
// speed: RecvBytes,
// }
// SpeedQueue.PushBack(pair)
// if SpeedQueue.Len() > 60 {
// SpeedQueue.Remove(SpeedQueue.Front())
// }
// var x []float64
// var y []float64
// x = make([]float64, 60)
// y = make([]float64, 60)
// var point = 0
// for item := SpeedQueue.Front(); item != nil; item = item.Next() {
// spdPair := item.Value.(speedPair)
// x[point] = float64(spdPair.index)
// y[point] = spdPair.speed
// point++
// }
// _, b := LeastSquares(x, y)
// log.Printf("Speed Vertical:%.3f\n", b)
//}
fmt.Fprintf(TerminalWriter, "Nic:%v,Recv %s/s,Send %s/s\n", netCounter[i].Name,
readableBytes(RecvBytes),
readableBytes(SendBytes))
}
initialNetCounter = netCounter
TerminalWriter.Clear()
TerminalWriter.Print()
time.Sleep(1 * time.Millisecond)
}
}
func readableBytes(bytes float64) (expression string) {
if bytes == 0 {
return "0B"
}
var i = math.Floor(math.Log(bytes) / math.Log(1024))
var sizes = []string{"B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"}
return fmt.Sprintf("%.3f%s", bytes/math.Pow(1024, i), sizes[int(i)])
}
func nslookup(targetAddress, server string) (res []string) {
if server == "" {
server = "8.8.8.8"
}
c := dns.Client{}
m := dns.Msg{}
m.SetQuestion(targetAddress+".", dns.TypeA)
ns := server + ":53"
r, t, err := c.Exchange(&m, ns)
if err != nil {
fmt.Printf("nameserver %s error: %v\n", ns, err)
return res
}
fmt.Printf("nameserver %s took %v", ns, t)
if len(r.Answer) == 0 {
return res
}
for _, ans := range r.Answer {
Arecord := ans.(*dns.A)
res = append(res, fmt.Sprintf("%s", Arecord))
}
return
}
func goFun(Url string, postContent string, Referer string, XforwardFor bool, customIP ipArray, wg *sync.WaitGroup) {
defer func() {
if r := recover(); r != nil {
go goFun(Url, postContent, Referer, XforwardFor, customIP, wg)
}
}()
for true {
if customIP != nil && len(customIP) > 0 {
dialer := &net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
}
http.DefaultTransport.(*http.Transport).DialContext = func(ctx context.Context, network, addr string) (net.Conn, error) {
rand.Seed(time.Now().Unix())
ip := customIP[rand.Intn(len(customIP))]
if strings.HasPrefix(addr,"https"){
addr = ip + ":443"
} else if strings.HasPrefix(addr,"http") {
addr = ip + ":80"
} else {
addr = ip + ":80"
}
return dialer.DialContext(ctx, network, addr)
}
}
var request *http.Request
var err1 error = nil
client := &http.Client{}
if len(postContent) > 0 {
request, err1 = http.NewRequest("POST", Url, strings.NewReader(postContent))
} else {
request, err1 = http.NewRequest("GET", Url, nil)
}
if err1 != nil {
continue
}
if len(Referer) == 0 {
Referer = Url
}
request.Header.Add("Cookie", RandStringBytesMaskImpr(12))
request.Header.Add("User-Agent", browser.Random())
request.Header.Add("Referer", Referer)
if XforwardFor {
randomip := generateRandomIPAddress()
request.Header.Add("X-Forwarded-For", randomip)
request.Header.Add("X-Real-IP", randomip)
}
resp, err2 := client.Do(request)
if err2 != nil {
continue
}
_, err3 := io.Copy(ioutil.Discard, resp.Body)
if err3 != nil {
continue
}
}
wg.Done()
}
var count = flag.Int("c", 16, "concurrent thread for download,default 8")
var url = flag.String("s", "https://baidu.com", "target url")
var postContent = flag.String("p", "", "post content")
var referer = flag.String("r", "", "referer url")
var xforwardfor = flag.Bool("f", true, "randomized X-Forwarded-For and X-Real-IP address")
var TerminalWriter = goterminal.New(os.Stdout)
var customIP ipArray
func main() {
flag.Var(&customIP, "i", "custom ip address for that domain, multiple addresses automatically will be assigned randomly")
flag.Parse()
routines := *count
if customIP != nil && len(customIP) > 0 && routines < len(customIP){
routines = len(customIP)
}
go showStat()
var waitgroup sync.WaitGroup
if routines <= 0 {
routines = 16
}
for i := 0; i < routines; i++ {
waitgroup.Add(1)
go goFun(*url, *postContent, *referer, *xforwardfor, customIP, &waitgroup)
}
waitgroup.Wait()
TerminalWriter.Reset()
}