miniproxy/main.go

103 lines
2.2 KiB
Go
Raw Normal View History

2021-09-15 13:25:23 +00:00
package main
import (
"net/http"
"net/url"
"log"
"os"
"strconv"
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"io"
"github.com/gorilla/mux"
"github.com/BurntSushi/toml"
)
type tomlConfig struct {
Port int `toml:"port"`
Secret string `toml:"secret"`
}
func proxyRequest(w http.ResponseWriter, r *http.Request, secret []byte) {
vars := mux.Vars(r)
requestUrl, err := url.QueryUnescape(vars["url"])
if err != nil {
log.Printf("Failed to url decode url: %s", err)
return
}
macRaw, err := url.QueryUnescape(vars["hmac"])
if err != nil {
log.Printf("Failed to url decode HMAC: %s", err)
return
}
mac := hmac.New(sha256.New, secret)
mac.Write([]byte(requestUrl))
expectedMac := mac.Sum(nil)
receivedMac, err := base64.StdEncoding.DecodeString(macRaw)
if err != nil {
log.Printf("Failed to decode HMAC: %s", err)
return
}
if !hmac.Equal(expectedMac, receivedMac) {
log.Printf("invalid-hmac:%s", r.RemoteAddr)
log.Printf("URL: '%s'", requestUrl)
http.Error(w, "Invalid HMAC", http.StatusUnauthorized)
return
}
client := &http.Client{}
resp, err := client.Get(requestUrl)
defer resp.Body.Close()
if err != nil {
log.Fatalf("Failed to perform GET: %s", err)
}
w.WriteHeader(resp.StatusCode)
io.Copy(w, resp.Body)
}
func makeProxyRequestHandler(secret []byte) http.HandlerFunc {
fn := func(w http.ResponseWriter, r *http.Request) {
proxyRequest(w, r, secret)
}
return http.HandlerFunc(fn)
}
func exists(path string) bool {
// Returns true if path exists. false otherwise
_, err := os.Stat(path)
return !os.IsNotExist(err)
}
func main() {
config := tomlConfig {
Port: 8080,
}
switch {
case exists("./config.toml"):
_, err := toml.DecodeFile("./config.toml", &config)
if err != nil {
log.Fatalf("Failed to read ./config.toml: %s", err)
}
case exists("/etc/miniproxy/config.toml"):
_, err := toml.DecodeFile("/etc/miniproxy/config.toml", &config)
if err != nil {
log.Fatalf("Failed to read /etc/miniproxy/config.toml: %s", err)
}
}
log.Printf("Running on :%d\n", config.Port)
r := mux.NewRouter()
r.UseEncodedPath()
r.HandleFunc("/proxy/{hmac}/{url:.+}", makeProxyRequestHandler([]byte(config.Secret)))
log.Fatal(http.ListenAndServe(":" + strconv.Itoa(config.Port), r))
}