-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathproxy.go
More file actions
114 lines (101 loc) · 2.56 KB
/
proxy.go
File metadata and controls
114 lines (101 loc) · 2.56 KB
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
package main
import (
"context"
"crypto/tls"
_ "embed"
"encoding/gob"
"encoding/hex"
"fmt"
"net"
"net/http"
"net/http/httputil"
"net/url"
"strings"
"github.com/samber/lo"
"github.com/sprisa/x/errutil"
l "github.com/sprisa/x/log"
)
type Certificate struct {
Cert []byte
Key []byte
}
func StartProxyService(
ctx context.Context,
addrIp net.IP,
listenPort int,
hostPort int,
availableSubdomains []string,
) error {
// res, err := http.Get("http://localhost:8080/certs")
res, err := http.Get("https://svc.host/certs")
if err != nil {
return errutil.WrapErr(err, "error fetching certs")
}
decoder := gob.NewDecoder(res.Body)
certificate := &Certificate{}
err = decoder.Decode(certificate)
if err != nil {
return errutil.WrapErr(err, "error decoding certificate")
}
cert := make([]byte, hex.DecodedLen(len(certificate.Cert)))
_, err = hex.Decode(cert, certificate.Cert)
if err != nil {
return errutil.WrapErr(err, "error decoding certificate.Cert")
}
certKey := make([]byte, hex.DecodedLen(len(certificate.Key)))
_, err = hex.Decode(certKey, certificate.Key)
if err != nil {
return errutil.WrapErr(err, "error decoding certificate.Key")
}
tlsCert, err := tls.X509KeyPair(cert, certKey)
if err != nil {
return errutil.WrapErr(err, "error creating tls cert")
}
log := l.Log.With().Int("targetPort", hostPort).Logger()
handler := http.NewServeMux()
target := fmt.Sprintf("http://127.0.0.1:%d", hostPort)
url, err := url.Parse(target)
if err != nil {
log.Err(err).Msg("error building url")
return err
}
proxy := httputil.NewSingleHostReverseProxy(url)
// Proxy request handler
handler.HandleFunc("/", func(res http.ResponseWriter, req *http.Request) {
res.Header().Add("Strict-Transport-Security", "max-age=63072000; includeSubDomains; preload")
proxy.ServeHTTP(res, req)
})
server := &http.Server{
Addr: fmt.Sprintf("%s:%d", addrIp, listenPort),
Handler: handler,
TLSConfig: &tls.Config{
Certificates: []tls.Certificate{tlsCert},
},
}
var closeError error
// Shutdown handler
go func() {
<-ctx.Done()
l.Log.Info().Msg("Shutting down proxy server.")
closeError = server.Close()
}()
l.Log.Info().Msgf(
"localhost proxy up\n%s",
strings.Join(
lo.Map(availableSubdomains, func(subdomain string, _ int) string {
return fmt.Sprintf(" - https://%s.svc.host:%d", subdomain, listenPort)
}),
"\n",
),
)
err = server.ListenAndServeTLS("", "")
if err != nil {
switch err {
case http.ErrServerClosed:
l.Log.Info().Msg("Proxy server closed successfully.")
default:
return err
}
}
return closeError
}