Difference between revisions of "Gorelay"

From UVOO Tech Wiki
Jump to navigation Jump to search
 
Line 95: Line 95:
 
                         return err
 
                         return err
 
                 }
 
                 }
                if *username != "" && *password != "" {
+
 
                        newReq.SetBasicAuth(*username, *password)
 
                }
 
  
 
                 for k, v := range req.Header {
 
                 for k, v := range req.Header {
 
                         newReq.Header[k] = v
 
                         newReq.Header[k] = v
 +
                }
 +
                if *username != "" && *password != "" {
 +
                        newReq.SetBasicAuth(*username, *password)
 
                 }
 
                 }
  

Latest revision as of 02:56, 3 May 2024

Simple HTTP Relay written in go

run.sh

#!/bin/bash
set -eu

go build gorelay.go
pkill gorelay || true
sleep 2
./gorelay -fqdn="192.168.x.y" -port=8443 -username="admin" -password="admin" -skip_tls_verify=true -uri_reg_old "/api/v1/foo/" -uri_reg_new "/api/v1/bar/"

curl

cat <<EOF > example.json
{
"foo": "bar"
}

curl -sku $AUTH -X POST -d @example.json https://proxyhost.example.com/foo

gorelay.go

package main

import (
        "crypto/tls"
        "flag"
        "fmt"
        "io"
        "log"
        "net/http"
        "regexp"
        "time"

        "github.com/labstack/echo/v4"
)

func syslogLogger(next echo.HandlerFunc) echo.HandlerFunc {
        return func(c echo.Context) error {
                start := time.Now()
                err := next(c)
                stop := time.Now()
                req := c.Request()
                res := c.Response()

                log.Printf("%s - [%s] \"%s %s %s\" %d %d %v",
                        c.RealIP(),
                        stop.Format(time.RFC3339),
                        req.Method, req.RequestURI, req.Proto,
                        res.Status, res.Size, stop.Sub(start),
                )

                return err
        }
}

func main() {
        schema := flag.String("schema", "https", "URI schema (http or https)")
        port := flag.Int("port", 443, "Port number of the remote HTTPS endpoint")
        fqdn := flag.String("fqdn", "", "Fully Qualified Domain Name (required)")
        username := flag.String("username", "", "Username for basic authentication")
        password := flag.String("password", "", "Password for basic authentication")
        skipTLS := flag.Bool("skip_tls_verify", false, "Skip TLS certificate verification")
        uriRegOld := flag.String("uri_reg_old", "", "Regex to replace in URI")
        uriRegNew := flag.String("uri_reg_new", "", "String to replace old URI")
        flag.Parse()

        if *fqdn == "" {
                panic("FQDN argument is required")
        }

        uriBase := fmt.Sprintf("%s://%s:%d", *schema, *fqdn, *port)

        e := echo.New()

        e.Use(syslogLogger)

        e.Any("/*", func(c echo.Context) error {
                req := c.Request()

                client := &http.Client{}
                if *skipTLS {
                        client.Transport = &http.Transport{
                                TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
                        }
                }
                regex := regexp.MustCompile(*uriRegOld)
                replaceStr := *uriRegNew
                requestURI := regex.ReplaceAllString(req.RequestURI, replaceStr)

                newReq, err := http.NewRequest(req.Method, uriBase+requestURI, req.Body)
                if err != nil {
                        return err
                }


                for k, v := range req.Header {
                        newReq.Header[k] = v
                }
                if *username != "" && *password != "" {
                        newReq.SetBasicAuth(*username, *password)
                }

                resp, err := client.Do(newReq)
                if err != nil {
                        return err
                }
                defer resp.Body.Close()

                for k, v := range resp.Header {
                        c.Response().Header().Set(k, v[0])
                }

                io.Copy(c.Response().Writer, resp.Body)

                return nil
        })

        e.Logger.Fatal(e.Start(":8080"))
}