-
Notifications
You must be signed in to change notification settings - Fork 1
/
sillyProxy.go
134 lines (116 loc) · 3.08 KB
/
sillyProxy.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
124
125
126
127
128
129
130
131
132
133
134
package main
import (
"crypto/tls"
"fmt"
"log"
"net/http"
"os"
"os/signal"
"reflect"
"syscall"
"time"
"unsafe"
)
//MinTLSVer is the minimum version of TLS that Silly enforces for client
// connections. Defaults to TLSv1.0
var minVersionTLS uint16 = 0x0301
/*
const (
VersionSSL30 = 0x0300
VersionTLS10 = 0x0301
VersionTLS11 = 0x0302
VersionTLS12 = 0x0303
)
*/
//SillyProxy sets up certMap, proxyMap from keystore, routesInfo and fires up
func SillyProxy(keyStoreFile *string, keyStorePass *string,
minTLSVer *uint, bindAddr *string, routeMapFilePath *string) (*http.Server, error) {
//build routeMap
routeMap := &RouteMap{}
buildRouteMapError := buildRouteMap(routeMapFilePath, routeMap)
if buildRouteMapError != nil {
return nil, fmt.Errorf("RouteMap build failed with error: %#v", buildRouteMapError)
}
//build proxyHandlerMap
pHMap := make(proxyHanlderMap)
assignRoutes(&pHMap, routeMap)
// verify minTLSVer value supplied
switch *minTLSVer {
case 2:
minVersionTLS = 0x0302
case 3:
minVersionTLS = 0x0303
default:
//log.Println("Minimum Version of TLS is set to 1")
minVersionTLS = 0x0301
}
keyStorePassBytes = []byte(*keyStorePass)
zeroString(keyStorePass)
//load the keystore into the
certMap = make(map[string]tls.Certificate)
loadError := loadCertMap(keyStoreFile, keyStorePassBytes, &certMap)
if loadError != nil {
return nil, fmt.Errorf("Certificate load failed: %#v", loadError)
}
//use a goroutine to reload the certMap every 30 mins from the keyStore
quitReloadChannel := make(chan struct{})
go reloadCertMap(keyStoreFile, keyStorePassBytes, &certMap,
quitReloadChannel, uint(60*30))
//Graceful shutdown in case of interrupts
sigChannel := make(chan os.Signal, 1)
go func(sigChannel <-chan os.Signal) {
for {
select {
case <-sigChannel:
stopReloadKeyStore(quitReloadChannel)
zeroBytes(keyStorePassBytes)
for _, v := range certMap {
clearOut(&v)
}
clearOut(ECDSAdefault)
clearOut(RSAdefault)
log.Printf("\nReceived %#v, purged keystore secret and certificate map. Goodbye!\n", sigChannel)
os.Exit(1)
}
}
}(sigChannel)
signal.Notify(sigChannel, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT,
syscall.SIGIOT, syscall.SIGABRT, syscall.SIGQUIT, syscall.SIGTSTP,
os.Interrupt)
//Declare server properties
server := &http.Server{
ReadTimeout: 50 * time.Second,
WriteTimeout: 600 * time.Second,
IdleTimeout: 60 * time.Second,
Addr: *bindAddr,
TLSConfig: &tls.Config{
MinVersion: minVersionTLS,
GetCertificate: returnCert,
},
Handler: pHMap,
}
return server, nil
}
func stopReloadKeyStore(quit chan<- struct{}) {
quit <- struct{}{}
}
func zeroBytes(s []byte) {
for i := 0; i < len(s); i++ {
s[i] = 0
}
}
func clearOut(v interface{}) {
p := reflect.ValueOf(v).Elem()
p.Set(reflect.Zero(p.Type()))
}
func zeroString(s *string) {
len := len(*s)
sHeader := (*reflect.StringHeader)(unsafe.Pointer(s))
var a []byte
for i := 0; i < len; i++ {
a = append(a, 48)
}
dupe := string(a)
dupeHeader := (*reflect.StringHeader)(unsafe.Pointer(&dupe))
sHeader.Data = dupeHeader.Data
}