From fb9d1df1004215a31b89b5ad47911ca43475613e Mon Sep 17 00:00:00 2001 From: Mzack9999 Date: Fri, 16 Apr 2021 16:06:42 +0200 Subject: [PATCH 01/12] adding common tools to docker --- Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Dockerfile b/Dockerfile index 4603b20..0919a3c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,6 +3,7 @@ RUN apk add --no-cache git RUN GO111MODULE=auto go get -u -v github.com/projectdiscovery/simplehttpserver/cmd/simplehttpserver FROM alpine:latest +RUN apk add --no-cache bind-tools ca-certificates COPY --from=builder /go/bin/simplehttpserver /usr/local/bin/ ENTRYPOINT ["simplehttpserver"] From 49ceaa7165da0d8fe1bb991b1094d0d95b8f17aa Mon Sep 17 00:00:00 2001 From: Mzack9999 Date: Fri, 16 Apr 2021 16:07:06 +0200 Subject: [PATCH 02/12] removing sslcert + deps bump --- go.mod | 1 + go.sum | 2 + pkg/httpserver/httpserver.go | 8 +- pkg/sslcert/options.go | 21 ----- pkg/sslcert/sslcert.go | 153 ----------------------------------- pkg/sslcert/tlsconfig.go | 19 ----- pkg/tcpserver/tcpserver.go | 2 +- 7 files changed, 7 insertions(+), 199 deletions(-) delete mode 100644 pkg/sslcert/options.go delete mode 100644 pkg/sslcert/sslcert.go delete mode 100644 pkg/sslcert/tlsconfig.go diff --git a/go.mod b/go.mod index f8bb144..1d88f80 100644 --- a/go.mod +++ b/go.mod @@ -5,5 +5,6 @@ go 1.15 require ( github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2 github.com/projectdiscovery/gologger v1.1.4 + github.com/projectdiscovery/sslcert v0.0.0-20210416140253-8f56bec1bb5e gopkg.in/yaml.v2 v2.4.0 ) diff --git a/go.sum b/go.sum index 6757769..aafe4a2 100644 --- a/go.sum +++ b/go.sum @@ -25,6 +25,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/projectdiscovery/gologger v1.1.4 h1:qWxGUq7ukHWT849uGPkagPKF3yBPYAsTtMKunQ8O2VI= github.com/projectdiscovery/gologger v1.1.4/go.mod h1:Bhb6Bdx2PV1nMaFLoXNBmHIU85iROS9y1tBuv7T5pMY= +github.com/projectdiscovery/sslcert v0.0.0-20210416140253-8f56bec1bb5e h1:IZa08TUGbU7I0HUb9QQt/8wuu2fPZqfnMXwWhtMxei8= +github.com/projectdiscovery/sslcert v0.0.0-20210416140253-8f56bec1bb5e/go.mod h1:jSp8W5zIkNPxAqVdcoFlfv0K5cqogTe65fMinR0Fvuk= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= diff --git a/pkg/httpserver/httpserver.go b/pkg/httpserver/httpserver.go index c37355e..958a6e7 100644 --- a/pkg/httpserver/httpserver.go +++ b/pkg/httpserver/httpserver.go @@ -1,10 +1,9 @@ package httpserver import ( - "net" "net/http" - "github.com/projectdiscovery/simplehttpserver/pkg/sslcert" + "github.com/projectdiscovery/sslcert" ) type Options struct { @@ -22,9 +21,8 @@ type Options struct { } type HTTPServer struct { - options *Options - layers http.Handler - listener net.Listener + options *Options + layers http.Handler } func New(options *Options) (*HTTPServer, error) { diff --git a/pkg/sslcert/options.go b/pkg/sslcert/options.go deleted file mode 100644 index 54cbc0d..0000000 --- a/pkg/sslcert/options.go +++ /dev/null @@ -1,21 +0,0 @@ -package sslcert - -import "time" - -type Options struct { - Host string // Comma-separated hostnames and IPs to generate a certificate for") - Organization string - ValidFrom string // Creation date formatted as Jan 1 15:04:05 2011 - ValidFor time.Duration // 365*24*time.Hour Duration that certificate is valid for - IsCA bool // whether this cert should be its own Certificate Authority - RSABits int // 2048 Size of RSA key to generate. Ignored if --ecdsa-curve is set - EcdsaCurve string // ECDSA curve to use to generate a key. Valid values are P224, P256 (recommended), P384, P521 - Ed25519Key bool // Generate an Ed25519 key -} - -var DefaultOptions = Options{ - ValidFor: time.Duration(365 * 24 * time.Hour), - IsCA: false, - RSABits: 2048, - Organization: "Acme Co", -} diff --git a/pkg/sslcert/sslcert.go b/pkg/sslcert/sslcert.go deleted file mode 100644 index 862ee21..0000000 --- a/pkg/sslcert/sslcert.go +++ /dev/null @@ -1,153 +0,0 @@ -// Package sslcert contains a reworked version of https://golang.org/src/crypto/tls/generate_cert.go -package sslcert - -import ( - "bufio" - "bytes" - "crypto/ecdsa" - "crypto/ed25519" - "crypto/elliptic" - "crypto/rand" - "crypto/rsa" - "crypto/x509" - "crypto/x509/pkix" - "encoding/pem" - "errors" - "fmt" - "math/big" - "net" - "strings" - "time" -) - -func pubKey(priv interface{}) interface{} { - switch k := priv.(type) { - case *rsa.PrivateKey: - return &k.PublicKey - case *ecdsa.PrivateKey: - return &k.PublicKey - case ed25519.PrivateKey: - return k.Public().(ed25519.PublicKey) - default: - return nil - } -} - -func Generate(options Options) (privateKey, publicKey []byte, err error) { - if options.Host == "" { - return nil, nil, errors.New("Empty host value") - } - - var priv interface{} - switch options.EcdsaCurve { - case "": - if options.Ed25519Key { - _, priv, err = ed25519.GenerateKey(rand.Reader) - } else { - priv, err = rsa.GenerateKey(rand.Reader, options.RSABits) - } - case "P224": - priv, err = ecdsa.GenerateKey(elliptic.P224(), rand.Reader) - case "P256": - priv, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader) - case "P384": - priv, err = ecdsa.GenerateKey(elliptic.P384(), rand.Reader) - case "P521": - priv, err = ecdsa.GenerateKey(elliptic.P521(), rand.Reader) - default: - err = fmt.Errorf("Unrecognized elliptic curve: %q", options.EcdsaCurve) - return - } - if err != nil { - err = fmt.Errorf("Failed to generate private key: %v", err) - return - } - - // ECDSA, ED25519 and RSA subject keys should have the DigitalSignature - // KeyUsage bits set in the x509.Certificate template - keyUsage := x509.KeyUsageDigitalSignature - // Only RSA subject keys should have the KeyEncipherment KeyUsage bits set. In - // the context of TLS this KeyUsage is particular to RSA key exchange and - // authentication. - if _, isRSA := priv.(*rsa.PrivateKey); isRSA { - keyUsage |= x509.KeyUsageKeyEncipherment - } - - var notBefore time.Time - if len(options.ValidFrom) == 0 { - notBefore = time.Now() - } else { - notBefore, err = time.Parse("Jan 2 15:04:05 2006", options.ValidFrom) - if err != nil { - err = fmt.Errorf("Failed to parse creation date: %v", err) - return - } - } - - notAfter := notBefore.Add(options.ValidFor) - - serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) - serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) - if err != nil { - err = fmt.Errorf("Failed to generate serial number: %v", err) - return - } - - template := x509.Certificate{ - SerialNumber: serialNumber, - Subject: pkix.Name{ - Organization: []string{options.Organization}, - }, - NotBefore: notBefore, - NotAfter: notAfter, - - KeyUsage: keyUsage, - ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, - BasicConstraintsValid: true, - } - - hosts := strings.Split(options.Host, ",") - for _, h := range hosts { - if ip := net.ParseIP(h); ip != nil { - template.IPAddresses = append(template.IPAddresses, ip) - } else { - template.DNSNames = append(template.DNSNames, h) - } - } - - if options.IsCA { - template.IsCA = true - template.KeyUsage |= x509.KeyUsageCertSign - } - - derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, pubKey(priv), priv) - if err != nil { - err = fmt.Errorf("Failed to create certificate: %v", err) - return - } - - var pubKeyBuf bytes.Buffer - pubKeyBufb := bufio.NewWriter(&pubKeyBuf) - err = pem.Encode(pubKeyBufb, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) - if err != nil { - err = fmt.Errorf("Failed to write data to cert.pem: %v", err) - return - } - pubKeyBufb.Flush() - - privBytes, err := x509.MarshalPKCS8PrivateKey(priv) - if err != nil { - err = fmt.Errorf("Unable to marshal private key: %v", err) - return - } - var privKeyBuf bytes.Buffer - privKeyBufb := bufio.NewWriter(&privKeyBuf) - err = pem.Encode(privKeyBufb, &pem.Block{Type: "PRIVATE KEY", Bytes: privBytes}) - if err != nil { - err = fmt.Errorf("Failed to write data to key.pem: %v", err) - return - } - privKeyBufb.Flush() - - return pubKeyBuf.Bytes(), privKeyBuf.Bytes(), nil -} diff --git a/pkg/sslcert/tlsconfig.go b/pkg/sslcert/tlsconfig.go deleted file mode 100644 index e2bbe92..0000000 --- a/pkg/sslcert/tlsconfig.go +++ /dev/null @@ -1,19 +0,0 @@ -package sslcert - -import ( - "crypto/tls" -) - -func NewTLSConfig(options Options) (*tls.Config, error) { - pubKey, privKey, err := Generate(options) - if err != nil { - return nil, err - } - - cert, err := tls.X509KeyPair(pubKey, privKey) - if err != nil { - return nil, err - } - - return &tls.Config{Certificates: []tls.Certificate{cert}}, nil -} diff --git a/pkg/tcpserver/tcpserver.go b/pkg/tcpserver/tcpserver.go index 7d46b3a..f78f876 100644 --- a/pkg/tcpserver/tcpserver.go +++ b/pkg/tcpserver/tcpserver.go @@ -7,7 +7,7 @@ import ( "time" "github.com/projectdiscovery/gologger" - "github.com/projectdiscovery/simplehttpserver/pkg/sslcert" + "github.com/projectdiscovery/sslcert" "gopkg.in/yaml.v2" ) From d068ebe21e9a746612bc357a8cda8fa29d7720c6 Mon Sep 17 00:00:00 2001 From: Mzack9999 Date: Fri, 16 Apr 2021 16:40:25 +0200 Subject: [PATCH 03/12] using go 1.14 --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 1d88f80..f4c4a9d 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/projectdiscovery/simplehttpserver -go 1.15 +go 1.14 require ( github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2 From e55d3feac94109c6eded54b0a6a98edd7933921e Mon Sep 17 00:00:00 2001 From: Mzack9999 Date: Fri, 16 Apr 2021 16:41:26 +0200 Subject: [PATCH 04/12] updated readme --- README.md | 119 +++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 109 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index f88164f..00daf9c 100644 --- a/README.md +++ b/README.md @@ -11,14 +11,14 @@ [![Docker Images](https://img.shields.io/docker/pulls/projectdiscovery/simplehttpserver.svg)](https://hub.docker.com/r/projectdiscovery/simplehttpserver) [![Chat on Discord](https://img.shields.io/discord/695645237418131507.svg?logo=discord)](https://discord.gg/KECAGdH) -simplehttpserver is a go enhanced version of the well known python simplehttpserver. +simplehttpserver is a go enhanced version of the well known python simplehttpserver with in addition a fully customizable TCP server, both supporting TLS. # Resources - [Features](#features) - [Usage](#usage) - [Installation Instructions](#installation-instructions) -- [Running simplehttpserver](#running-simplehttpserver-in-the-current-folder ) +- [Running simplehttpserver](#running-simplehttpserver-in-the-current-folder) - [Thanks](#thanks) # Features @@ -28,9 +28,11 @@ simplehttpserver is a go enhanced version of the well known python simplehttpser
- - File server in arbitrary directory - - Full request/response dump - - Configurable ip address and listening port +- HTTPS support +- File server in arbitrary directory +- Full request/response dump +- Configurable ip address and listening port +- Configurable HTTP/TCP server with customizable response via YAML template # Installation Instructions @@ -70,11 +72,23 @@ simplehttpserver -h This will display help for the tool. Here are all the switches it supports. -| Flag | Description | Example | -| ------ | ---------------------------------------------------- | --------------------------------------- | -| listen | Configure listening ip:port (default 127.0.0.1:8000) | simplehttpserver -listen 127.0.0.1:8000 | -| path | Fileserver folder (default current directory) | simplehttpserver -path /var/docs | -| v | Verbose (dump request/response, default false) | simplehttpserver -v | +| Flag | Description | Example | +| ----------- | -------------------------------------------------------------------- | ------------------------------------------------- | +| listen | Configure listening ip:port (default 127.0.0.1:8000) | simplehttpserver -listen 127.0.0.1:8000 | +| path | Fileserver folder (default current directory) | simplehttpserver -path /var/docs | +| verbose | Verbose (dump request/response, default false) | simplehttpserver -v | +| tcp | TCP server (default 127.0.0.1:8000) | simplehttpserver -tcp 127.0.0.1:8000 | +| tls | Enable TLS for TCP server | simplehttpserver -tls | +| rules | File containing yaml rules | simplehttpserver -rules rule.yaml | | +| upload | Enable file upload in case of http server | simplehttpserver -upload | +| https | Enable HTTPS in case of http server | simplehttpserver -https | +| cert | HTTPS/TLS certificate (self generated if not specified) | simplehttpserver -cert cert.pem | +| key | HTTPS/TLS certificate private key (self generated if not specified) | simplehttpserver -key cert.key | +| domain | Domain name to use for the self-generated certificate | simplehttpserver -domain projectdiscovery.io | +| basic-auth | Basic auth (username:password) | simplehttpserver -basic-auth user:password | +| realm | Basic auth message | simplehttpserver -realm "insert the credentials" | +| version | Show version | simplehttpserver -version | +| silent | Show only results | simplehttpserver -silent | ### Running simplehttpserver in the current folder @@ -87,6 +101,91 @@ This will run the tool exposing the current directory on port 8000 2021/01/11 21:41:15 [::1]:50181 "GET /favicon.ico HTTP/1.1" 404 19 ``` +### Running simplehttpserver in the current folder with HTTPS + +This will run the tool exposing the current directory on port 8000 over HTTPS with user provided certificate: + +```sh +▶ simplehttpserver -https -cert cert.pen -key cert.key +2021/01/11 21:40:48 Serving . on http://0.0.0.0:8000/... +2021/01/11 21:41:15 [::1]:50181 "GET / HTTP/1.1" 200 383 +2021/01/11 21:41:15 [::1]:50181 "GET /favicon.ico HTTP/1.1" 404 19 +``` + +Instead, to run with self-signed certificate and specific domain name: +```sh +▶ simplehttpserver -https -domain localhost +2021/01/11 21:40:48 Serving . on http://0.0.0.0:8000/... +2021/01/11 21:41:15 [::1]:50181 "GET / HTTP/1.1" 200 383 +2021/01/11 21:41:15 [::1]:50181 "GET /favicon.ico HTTP/1.1" 404 19 +``` + +### Running simplehttpserver with basic auth and file upload + +This will run the tool and will request the user to enter username and password before authorizing file uploads + +```sh +▶ simplehttpserver -basic-auth root:root -upload +2021/01/11 21:40:48 Serving . on http://0.0.0.0:8000/... +``` + +To upload files use the following curl request with basic auth header: +```sh +▶ curl -v --user 'root:root' --upload-file file.txt http://localhost:8000/file.txt +``` + +### Running TCP server with custom responses + +This will run the tool as TLS TCP server and enable custom responses based on YAML templates: + +```sh +▶ simplehttpserver -rule rules.yaml -tcp -tls -domain localhost +``` + +The rules are written as follows: +```yaml +rules: + - match: regex + response: response data +``` + +For example to handle two different paths simulating an HTTP server or SMTP commands: +```yaml +rules: + # HTTP Requests + - match: GET /path1 + response: | + HTTP/1.0 200 OK + Server: httpd/2.0 + x-frame-options: SAMEORIGIN + x-xss-protection: 1; mode=block + Date: Fri, 16 Apr 2021 14:30:32 GMT + Content-Type: text/html + Connection: close + + + + - match: GET /path2 + response: | + HTTP/1.0 404 OK + Server: httpd/2.0 + + Not found + # SMTP Commands + - match: "EHLO example.com" + response: | + 250-localhost Nice to meet you, [127.0.0.1] + 250-PIPELINING + 250-8BITMIME + 250-SMTPUTF8 + 250-AUTH LOGIN PLAIN + 250 STARTTLS + - match: "MAIL FROM: " + response: 250 Accepted + - match: "RCPT TO: " + response: 250 Accepted +``` + # Thanks simplehttpserver is made with 🖤 by the [projectdiscovery](https://projectdiscovery.io) team. Community contributions have made the project what it is. See the **[Thanks.md](https://github.com/projectdiscovery/simplehttpserver/blob/master/THANKS.md)** file for more details. From ef3b178ae32b8499bc25fb38933e31d8ed168394 Mon Sep 17 00:00:00 2001 From: sandeep <8293321+ehsandeep@users.noreply.github.com> Date: Fri, 16 Apr 2021 22:08:06 +0530 Subject: [PATCH 05/12] Update build.yaml --- .github/workflows/build.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 11d1658..008bca6 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -32,8 +32,8 @@ jobs: - name: Test run: go test . - working-directory: cmd/simplehttpserver/ + working-directory: . - name: Build run: go build . - working-directory: cmd/simplehttpserver/ + working-directory: . From bce92ad125f31668a58d4bcdff509a061f04d1d0 Mon Sep 17 00:00:00 2001 From: sandeep <8293321+ehsandeep@users.noreply.github.com> Date: Fri, 16 Apr 2021 22:15:35 +0530 Subject: [PATCH 06/12] reverting working-directory --- .github/workflows/build.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 008bca6..4179b91 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -32,8 +32,8 @@ jobs: - name: Test run: go test . - working-directory: . + working-directory: cmd/simplehttpserver - name: Build run: go build . - working-directory: . + working-directory: cmd/simplehttpserver/ From 566a82a76a360d0dce6cac9c479041d86a302612 Mon Sep 17 00:00:00 2001 From: Mzack9999 Date: Fri, 16 Apr 2021 19:09:45 +0200 Subject: [PATCH 07/12] adding absolute path --- internal/runner/options.go | 9 +++++++++ internal/runner/runner.go | 4 ++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/internal/runner/options.go b/internal/runner/options.go index 3170cd3..9104c4a 100644 --- a/internal/runner/options.go +++ b/internal/runner/options.go @@ -3,6 +3,7 @@ package runner import ( "flag" "os" + "path/filepath" "strings" "github.com/projectdiscovery/gologger" @@ -91,3 +92,11 @@ func (options *Options) configureOutput() { gologger.DefaultLogger.SetMaxLevel(levels.LevelSilent) } } + +func (o Options) FolderAbsPath() string { + abspath, err := filepath.Abs(o.Folder) + if err != nil { + return o.Folder + } + return abspath +} diff --git a/internal/runner/runner.go b/internal/runner/runner.go index 6603d50..820dc51 100644 --- a/internal/runner/runner.go +++ b/internal/runner/runner.go @@ -72,11 +72,11 @@ func (r *Runner) Run() error { } if r.options.HTTPS { - gologger.Print().Msgf("Serving %s on https://%s/...", r.options.Folder, r.options.ListenAddress) + gologger.Print().Msgf("Serving %s on https://%s/", r.options.FolderAbsPath(), r.options.ListenAddress) return r.httpServer.ListenAndServeTLS() } - gologger.Print().Msgf("Serving %s on http://%s/...", r.options.Folder, r.options.ListenAddress) + gologger.Print().Msgf("Serving %s on http://%s/", r.options.FolderAbsPath(), r.options.ListenAddress) return r.httpServer.ListenAndServe() } From 1fe30e15f17c64dc45e59b840512b1c8c78b38d8 Mon Sep 17 00:00:00 2001 From: Mzack9999 Date: Fri, 16 Apr 2021 19:19:24 +0200 Subject: [PATCH 08/12] adding comments --- cmd/simplehttpserver/simplehttpserver.go | 6 +++--- internal/runner/options.go | 1 + internal/runner/runner.go | 3 +++ pkg/binder/binder.go | 2 ++ pkg/httpserver/httpserver.go | 6 ++++++ pkg/httpserver/loglayer.go | 3 +++ pkg/tcpserver/responseengine.go | 3 ++- pkg/tcpserver/rule.go | 5 ++++- pkg/tcpserver/tcpserver.go | 7 +++++++ 9 files changed, 31 insertions(+), 5 deletions(-) diff --git a/cmd/simplehttpserver/simplehttpserver.go b/cmd/simplehttpserver/simplehttpserver.go index 0dbbe6c..36ae61d 100644 --- a/cmd/simplehttpserver/simplehttpserver.go +++ b/cmd/simplehttpserver/simplehttpserver.go @@ -8,11 +8,11 @@ import ( func main() { // Parse the command line flags and read config files options := runner.ParseOptions() - runner, err := runner.New(options) + r, err := runner.New(options) if err != nil { gologger.Fatal().Msgf("Could not create runner: %s\n", err) } - runner.Run() - runner.Close() + r.Run() + defer r.Close() } diff --git a/internal/runner/options.go b/internal/runner/options.go index 9104c4a..6c8e1f9 100644 --- a/internal/runner/options.go +++ b/internal/runner/options.go @@ -93,6 +93,7 @@ func (options *Options) configureOutput() { } } +// FolderAbsPath of the fileserver folder func (o Options) FolderAbsPath() string { abspath, err := filepath.Abs(o.Folder) if err != nil { diff --git a/internal/runner/runner.go b/internal/runner/runner.go index 820dc51..653cbed 100644 --- a/internal/runner/runner.go +++ b/internal/runner/runner.go @@ -14,6 +14,7 @@ type Runner struct { httpServer *httpserver.HTTPServer } +// New instance of runner func New(options *Options) (*Runner, error) { r := Runner{options: options} // Check if the process can listen on the specified ip:port @@ -65,6 +66,7 @@ func New(options *Options) (*Runner, error) { return &r, nil } +// Run logic func (r *Runner) Run() error { if r.options.EnableTCP { gologger.Print().Msgf("Serving TCP rule based server on tcp://%s", r.options.ListenAddress) @@ -80,6 +82,7 @@ func (r *Runner) Run() error { return r.httpServer.ListenAndServe() } +// Close the listening services func (r *Runner) Close() error { if r.serverTCP != nil { r.serverTCP.Close() diff --git a/pkg/binder/binder.go b/pkg/binder/binder.go index 2a248a1..a530cf1 100644 --- a/pkg/binder/binder.go +++ b/pkg/binder/binder.go @@ -7,6 +7,7 @@ import ( "github.com/phayes/freeport" ) +// CanListenOn the specified address func CanListenOn(address string) bool { listener, err := net.Listen("tcp4", address) if err != nil { @@ -16,6 +17,7 @@ func CanListenOn(address string) bool { return true } +// GetRandomListenAddress from the specified one func GetRandomListenAddress(currentAddress string) (string, error) { addrOrig, _, err := net.SplitHostPort(currentAddress) if err != nil { diff --git a/pkg/httpserver/httpserver.go b/pkg/httpserver/httpserver.go index 958a6e7..1747017 100644 --- a/pkg/httpserver/httpserver.go +++ b/pkg/httpserver/httpserver.go @@ -6,6 +6,7 @@ import ( "github.com/projectdiscovery/sslcert" ) +// Options of the http server type Options struct { Folder string EnableUpload bool @@ -20,11 +21,13 @@ type Options struct { Verbose bool } +// HTTPServer instance type HTTPServer struct { options *Options layers http.Handler } +// New http server instance with options func New(options *Options) (*HTTPServer, error) { var h HTTPServer EnableUpload = options.EnableUpload @@ -37,10 +40,12 @@ func New(options *Options) (*HTTPServer, error) { return &HTTPServer{options: options, layers: layers}, nil } +// ListenAndServe requests over http func (t *HTTPServer) ListenAndServe() error { return http.ListenAndServe(t.options.ListenAddress, t.layers) } +// ListenAndServeTLS requests over https func (t *HTTPServer) ListenAndServeTLS() error { if t.options.Certificate == "" || t.options.CertificateKey == "" { tlsOptions := sslcert.DefaultOptions @@ -59,6 +64,7 @@ func (t *HTTPServer) ListenAndServeTLS() error { return http.ListenAndServeTLS(t.options.ListenAddress, t.options.Certificate, t.options.CertificateKey, t.layers) } +// Close the service func (t *HTTPServer) Close() error { return nil } diff --git a/pkg/httpserver/loglayer.go b/pkg/httpserver/loglayer.go index 2d84d9a..1e64b8f 100644 --- a/pkg/httpserver/loglayer.go +++ b/pkg/httpserver/loglayer.go @@ -54,15 +54,18 @@ func newLoggingResponseWriter(w http.ResponseWriter) *loggingResponseWriter { return &loggingResponseWriter{w, http.StatusOK, []byte{}} } +// Write the data func (lrw *loggingResponseWriter) Write(data []byte) (int, error) { lrw.Data = append(lrw.Data, data...) return lrw.ResponseWriter.Write(data) } +// Header of the response func (lrw *loggingResponseWriter) Header() http.Header { return lrw.ResponseWriter.Header() } +// WriteHeader status code func (lrw *loggingResponseWriter) WriteHeader(code int) { lrw.statusCode = code lrw.ResponseWriter.WriteHeader(code) diff --git a/pkg/tcpserver/responseengine.go b/pkg/tcpserver/responseengine.go index c3286f8..ec15da0 100644 --- a/pkg/tcpserver/responseengine.go +++ b/pkg/tcpserver/responseengine.go @@ -4,6 +4,7 @@ import ( "errors" ) +// BuildResponse according to rules func (t *TCPServer) BuildResponse(data []byte) ([]byte, error) { // Process all the rules for _, rule := range t.options.rules { @@ -11,5 +12,5 @@ func (t *TCPServer) BuildResponse(data []byte) ([]byte, error) { return []byte(rule.Response), nil } } - return nil, errors.New("No matched rule") + return nil, errors.New("no matched rule") } diff --git a/pkg/tcpserver/rule.go b/pkg/tcpserver/rule.go index ba31839..903331b 100644 --- a/pkg/tcpserver/rule.go +++ b/pkg/tcpserver/rule.go @@ -2,17 +2,20 @@ package tcpserver import "regexp" +// RulesConfiguration from yaml type RulesConfiguration struct { Rules []Rule `yaml:"rules"` } +// Rule to apply to various requests type Rule struct { Match string `yaml:"match,omitempty"` matchRegex *regexp.Regexp Response string `yaml:"response,omitempty"` } -func NewRule(match string, response string) (*Rule, error) { +// NewRule from model +func NewRule(match, response string) (*Rule, error) { regxp, err := regexp.Compile(match) if err != nil { return nil, err diff --git a/pkg/tcpserver/tcpserver.go b/pkg/tcpserver/tcpserver.go index f78f876..7bff39e 100644 --- a/pkg/tcpserver/tcpserver.go +++ b/pkg/tcpserver/tcpserver.go @@ -11,6 +11,7 @@ import ( "gopkg.in/yaml.v2" ) +// Options of the tcp server type Options struct { Listen string TLS bool @@ -21,20 +22,24 @@ type Options struct { Verbose bool } +// TCPServer instance type TCPServer struct { options Options listener net.Listener } +// New tcp server instance with specified options func New(options Options) (*TCPServer, error) { return &TCPServer{options: options}, nil } +// AddRule to the server func (t *TCPServer) AddRule(rule Rule) error { t.options.rules = append(t.options.rules, rule) return nil } +// ListenAndServe requests func (t *TCPServer) ListenAndServe() error { listener, err := net.Listen("tcp4", t.options.Listen) if err != nil { @@ -68,6 +73,7 @@ func (t *TCPServer) handleConnection(conn net.Conn) error { } } +// ListenAndServe requests over tls func (t *TCPServer) ListenAndServeTLS() error { var tlsConfig *tls.Config if t.options.Certificate != "" && t.options.Key != "" { @@ -108,6 +114,7 @@ func (t *TCPServer) Close() error { return t.listener.Close() } +// LoadTemplate from yaml func (t *TCPServer) LoadTemplate(templatePath string) error { var config RulesConfiguration yamlFile, err := ioutil.ReadFile(templatePath) From b0911c1316fb5c187fe71b1f5372af0372b65852 Mon Sep 17 00:00:00 2001 From: Mzack9999 Date: Fri, 16 Apr 2021 19:30:13 +0200 Subject: [PATCH 09/12] adding missing error checks --- cmd/simplehttpserver/simplehttpserver.go | 4 +++- internal/runner/options.go | 3 ++- internal/runner/runner.go | 8 ++++++-- pkg/binder/binder.go | 5 ++++- pkg/tcpserver/tcpserver.go | 11 ++++++++--- 5 files changed, 23 insertions(+), 8 deletions(-) diff --git a/cmd/simplehttpserver/simplehttpserver.go b/cmd/simplehttpserver/simplehttpserver.go index 36ae61d..9d37de8 100644 --- a/cmd/simplehttpserver/simplehttpserver.go +++ b/cmd/simplehttpserver/simplehttpserver.go @@ -13,6 +13,8 @@ func main() { gologger.Fatal().Msgf("Could not create runner: %s\n", err) } - r.Run() + if err := r.Run(); err != nil { + gologger.Info().Msgf("%s\n", err) + } defer r.Close() } diff --git a/internal/runner/options.go b/internal/runner/options.go index 6c8e1f9..0b5e587 100644 --- a/internal/runner/options.go +++ b/internal/runner/options.go @@ -10,6 +10,7 @@ import ( "github.com/projectdiscovery/gologger/levels" ) +// Options of the tool type Options struct { ListenAddress string Folder string @@ -94,7 +95,7 @@ func (options *Options) configureOutput() { } // FolderAbsPath of the fileserver folder -func (o Options) FolderAbsPath() string { +func (o *Options) FolderAbsPath() string { abspath, err := filepath.Abs(o.Folder) if err != nil { return o.Folder diff --git a/internal/runner/runner.go b/internal/runner/runner.go index 653cbed..4bda588 100644 --- a/internal/runner/runner.go +++ b/internal/runner/runner.go @@ -85,10 +85,14 @@ func (r *Runner) Run() error { // Close the listening services func (r *Runner) Close() error { if r.serverTCP != nil { - r.serverTCP.Close() + if err := r.serverTCP.Close(); err != nil { + return err + } } if r.httpServer != nil { - r.httpServer.Close() + if err := r.httpServer.Close(); err != nil { + return err + } } return nil } diff --git a/pkg/binder/binder.go b/pkg/binder/binder.go index a530cf1..88a051b 100644 --- a/pkg/binder/binder.go +++ b/pkg/binder/binder.go @@ -5,6 +5,7 @@ import ( "net" "github.com/phayes/freeport" + "github.com/projectdiscovery/gologger" ) // CanListenOn the specified address @@ -13,7 +14,9 @@ func CanListenOn(address string) bool { if err != nil { return false } - defer listener.Close() + if err := listener.Close(); err != nil { + gologger.Info().Msgf("%s\n", err) + } return true } diff --git a/pkg/tcpserver/tcpserver.go b/pkg/tcpserver/tcpserver.go index 7bff39e..dfcb18b 100644 --- a/pkg/tcpserver/tcpserver.go +++ b/pkg/tcpserver/tcpserver.go @@ -54,7 +54,9 @@ func (t *TCPServer) handleConnection(conn net.Conn) error { buf := make([]byte, 4096) for { - conn.SetReadDeadline(time.Now().Add(time.Duration(5 * time.Second))) + if err := conn.SetReadDeadline(time.Now().Add(time.Duration(5 * time.Second))); err != nil { + gologger.Info().Msgf("%s\n", err) + } _, err := conn.Read(buf) if err != nil { return err @@ -67,7 +69,9 @@ func (t *TCPServer) handleConnection(conn net.Conn) error { return err } - conn.Write(resp) + if _, err := conn.Write(resp); err != nil { + gologger.Info().Msgf("%s\n", err) + } gologger.Print().Msgf("%s\n", resp) } @@ -106,10 +110,11 @@ func (t *TCPServer) run() error { if err != nil { return err } - go t.handleConnection(c) + go t.handleConnection(c) //nolint } } +// Close the service func (t *TCPServer) Close() error { return t.listener.Close() } From 309e6bc1170114b3bb80ddb5e403cce4bd77dc0b Mon Sep 17 00:00:00 2001 From: Mzack9999 Date: Fri, 16 Apr 2021 19:33:04 +0200 Subject: [PATCH 10/12] adding missing go docs --- pkg/binder/doc.go | 2 ++ pkg/httpserver/doc.go | 2 ++ pkg/tcpserver/doc.go | 2 ++ 3 files changed, 6 insertions(+) create mode 100644 pkg/binder/doc.go create mode 100644 pkg/httpserver/doc.go create mode 100644 pkg/tcpserver/doc.go diff --git a/pkg/binder/doc.go b/pkg/binder/doc.go new file mode 100644 index 0000000..709dc10 --- /dev/null +++ b/pkg/binder/doc.go @@ -0,0 +1,2 @@ +// Package binder contains binding helpers +package binder diff --git a/pkg/httpserver/doc.go b/pkg/httpserver/doc.go new file mode 100644 index 0000000..5344c9f --- /dev/null +++ b/pkg/httpserver/doc.go @@ -0,0 +1,2 @@ +// Package httpserver contains the http server logic +package httpserver diff --git a/pkg/tcpserver/doc.go b/pkg/tcpserver/doc.go new file mode 100644 index 0000000..4ab6d69 --- /dev/null +++ b/pkg/tcpserver/doc.go @@ -0,0 +1,2 @@ +// Package tcpserver contains the tcp server logic +package tcpserver From 89bbfaac877c637c32f56dc98d2d3a6ece77c9b9 Mon Sep 17 00:00:00 2001 From: mzack Date: Fri, 16 Apr 2021 20:10:40 +0200 Subject: [PATCH 11/12] fixing misc lint errors --- .golangci.yml | 6 +----- cmd/simplehttpserver/simplehttpserver.go | 2 +- internal/runner/options.go | 6 +++--- internal/runner/runner.go | 2 +- pkg/binder/binder.go | 1 - pkg/tcpserver/tcpserver.go | 12 +++++++----- 6 files changed, 13 insertions(+), 16 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index d5e9089..31b66f3 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -41,8 +41,6 @@ linters-settings: - (github.com/golangci/golangci-lint/pkg/logutils.Log).Fatalf # lll: # line-length: 140 - maligned: - suggest-new: true misspell: locale: US nolintlint: @@ -73,14 +71,12 @@ linters: - gosimple - govet - ineffassign - - interfacer - - maligned - misspell - nakedret - noctx - nolintlint - rowserrcheck - - scopelint + - exportloopref - staticcheck - structcheck - stylecheck diff --git a/cmd/simplehttpserver/simplehttpserver.go b/cmd/simplehttpserver/simplehttpserver.go index 9d37de8..ed82b40 100644 --- a/cmd/simplehttpserver/simplehttpserver.go +++ b/cmd/simplehttpserver/simplehttpserver.go @@ -16,5 +16,5 @@ func main() { if err := r.Run(); err != nil { gologger.Info().Msgf("%s\n", err) } - defer r.Close() + defer r.Close() //nolint } diff --git a/internal/runner/options.go b/internal/runner/options.go index 0b5e587..bf69db3 100644 --- a/internal/runner/options.go +++ b/internal/runner/options.go @@ -95,10 +95,10 @@ func (options *Options) configureOutput() { } // FolderAbsPath of the fileserver folder -func (o *Options) FolderAbsPath() string { - abspath, err := filepath.Abs(o.Folder) +func (options *Options) FolderAbsPath() string { + abspath, err := filepath.Abs(options.Folder) if err != nil { - return o.Folder + return options.Folder } return abspath } diff --git a/internal/runner/runner.go b/internal/runner/runner.go index 4bda588..7d69e25 100644 --- a/internal/runner/runner.go +++ b/internal/runner/runner.go @@ -28,7 +28,7 @@ func New(options *Options) (*Runner, error) { } if r.options.EnableTCP { - serverTCP, err := tcpserver.New(tcpserver.Options{ + serverTCP, err := tcpserver.New(&tcpserver.Options{ Listen: r.options.ListenAddress, TLS: r.options.TCPWithTLS, Domain: "local.host", diff --git a/pkg/binder/binder.go b/pkg/binder/binder.go index 88a051b..549e9d9 100644 --- a/pkg/binder/binder.go +++ b/pkg/binder/binder.go @@ -33,5 +33,4 @@ func GetRandomListenAddress(currentAddress string) (string, error) { } return net.JoinHostPort(addrOrig, fmt.Sprintf("%d", newPort)), nil - } diff --git a/pkg/tcpserver/tcpserver.go b/pkg/tcpserver/tcpserver.go index dfcb18b..876fbb4 100644 --- a/pkg/tcpserver/tcpserver.go +++ b/pkg/tcpserver/tcpserver.go @@ -11,6 +11,8 @@ import ( "gopkg.in/yaml.v2" ) +const readTimeout = 5 + // Options of the tcp server type Options struct { Listen string @@ -24,12 +26,12 @@ type Options struct { // TCPServer instance type TCPServer struct { - options Options + options *Options listener net.Listener } // New tcp server instance with specified options -func New(options Options) (*TCPServer, error) { +func New(options *Options) (*TCPServer, error) { return &TCPServer{options: options}, nil } @@ -50,11 +52,11 @@ func (t *TCPServer) ListenAndServe() error { } func (t *TCPServer) handleConnection(conn net.Conn) error { - defer conn.Close() + defer conn.Close() //nolint buf := make([]byte, 4096) for { - if err := conn.SetReadDeadline(time.Now().Add(time.Duration(5 * time.Second))); err != nil { + if err := conn.SetReadDeadline(time.Now().Add(readTimeout * time.Second)); err != nil { gologger.Info().Msgf("%s\n", err) } _, err := conn.Read(buf) @@ -77,7 +79,7 @@ func (t *TCPServer) handleConnection(conn net.Conn) error { } } -// ListenAndServe requests over tls +// ListenAndServeTLS requests over tls func (t *TCPServer) ListenAndServeTLS() error { var tlsConfig *tls.Config if t.options.Certificate != "" && t.options.Key != "" { From 8a339ee35b4f329b9b4c2f2f830e4594769751ba Mon Sep 17 00:00:00 2001 From: mzack Date: Fri, 16 Apr 2021 20:12:26 +0200 Subject: [PATCH 12/12] bumping version --- internal/runner/banner.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/runner/banner.go b/internal/runner/banner.go index c8972db..2d31eb8 100644 --- a/internal/runner/banner.go +++ b/internal/runner/banner.go @@ -12,7 +12,7 @@ const banner = ` ` // Version is the current version -const Version = `0.0.1` +const Version = `0.0.2` // showBanner is used to show the banner to the user func showBanner() {