-
Notifications
You must be signed in to change notification settings - Fork 11
/
main.go
123 lines (113 loc) · 3.48 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
package main
import (
"crypto/tls"
"flag"
"fmt"
"github.com/gorilla/mux"
"github.com/pkg/browser"
"golang.org/x/crypto/acme/autocert"
"log"
"net/http"
"net/http/httputil"
"net/url"
"regexp"
"strings"
)
var builtInSSL = false
var selfSSL = false
var listenAddr = "localhost:13331"
var login = ""
var password = ""
func init() {
flag.BoolVar(&builtInSSL, "ssl", false,
"built-in ssl support. this requires a public IP, and port 80 being available in order to fetch the certs",
)
flag.BoolVar(&selfSSL, "self-sign", false,
"self-signed ssl support. would display a warning on browsers",
)
flag.StringVar(&listenAddr, "listen", "localhost:13331", "which IP and port to listen?")
flag.StringVar(&login, "login", "", "server-side login")
flag.StringVar(&password, "password", "", "server-side password")
}
func main() {
flag.Parse()
stripDomain := regexp.MustCompile(`Domain=[^;]+; `)
handler := func(w http.ResponseWriter, r *http.Request) {
log.Printf("%s API - %s\n", r.RemoteAddr, r.URL.String())
varUrl := mux.Vars(r)["url"]
pathCleaned := !strings.Contains(varUrl, "://")
if pathCleaned {
varUrl = strings.ReplaceAll(varUrl, ":/", "://")
}
remote, _ := url.Parse(varUrl)
r.URL.Scheme = remote.Scheme
r.URL.Path = remote.Path
r.Host = remote.Host
remote.Path = ""
r.Header.Del("Referer")
r.Header.Del("Origin")
proxy := httputil.NewSingleHostReverseProxy(remote)
proxy.ModifyResponse = func(resp *http.Response) error {
if setCookie := resp.Header.Get("Set-Cookie"); setCookie != "" {
remotePath := remote.String()
if pathCleaned {
remotePath = strings.ReplaceAll(remotePath, "://", ":/")
}
setCookie = strings.ReplaceAll(setCookie, "Path=/", "Path=/proxy/"+remotePath+"/")
setCookie = strings.ReplaceAll(setCookie, ";SameSite=None;Secure", "")
setCookie = stripDomain.ReplaceAllString(setCookie, "")
resp.Header.Set("Set-Cookie", setCookie)
}
return nil
}
proxy.ServeHTTP(w, r)
}
staticRemote, _ := url.Parse("https://f1vp.netlify.app")
staticProxy := httputil.NewSingleHostReverseProxy(staticRemote)
serverSideLogin := 0
if login != "" && password != "" {
serverSideLogin = 1
}
staticProxy.ModifyResponse = func(resp *http.Response) (err error) {
resp.Header.Add("Set-Cookie", fmt.Sprintf("server_side_login=%d; Max-Age=86400; Path=/", serverSideLogin))
return nil
}
staticHandler := func(w http.ResponseWriter, r *http.Request) {
log.Printf("%s FE* - %s\n", r.RemoteAddr, r.URL.String())
r.Host = staticRemote.Host
staticProxy.ServeHTTP(w, r)
}
r := mux.NewRouter()
r.HandleFunc("/proxy/{url:https?://?.*}", handler)
r.PathPrefix("/authenticate").HandlerFunc(handleLogin)
r.PathPrefix("/").HandlerFunc(staticHandler)
r.SkipClean(true)
if builtInSSL {
certManager := autocert.Manager{
Prompt: autocert.AcceptTOS,
Cache: autocert.DirCache("certs"),
}
server := &http.Server{
Addr: listenAddr,
TLSConfig: &tls.Config{
GetCertificate: certManager.GetCertificate,
},
Handler: r,
}
go http.ListenAndServe(":http", certManager.HTTPHandler(nil))
log.Fatal(server.ListenAndServeTLS("", ""))
} else if selfSSL {
server := &http.Server{
Addr: listenAddr,
TLSConfig: &tls.Config{
GetCertificate: GetSelfSignedCertificate,
},
Handler: r,
}
log.Fatal(server.ListenAndServeTLS("", ""))
} else {
_ = browser.OpenURL(fmt.Sprintf("http://%s/", listenAddr))
log.Println("Reverse Proxy Server running at " + listenAddr + "\n")
log.Fatal(http.ListenAndServe(listenAddr, r))
}
}