@@ -7,10 +7,21 @@ import (
7
7
"log/slog"
8
8
"net"
9
9
"net/http"
10
+ "os"
10
11
"time"
11
12
13
+ "crypto/rand"
14
+ "crypto/rsa"
15
+ "crypto/tls"
16
+ "crypto/x509"
17
+ "crypto/x509/pkix"
18
+ "encoding/pem"
19
+ "errors"
20
+ "math/big"
21
+
12
22
"golang.org/x/crypto/acme"
13
23
"golang.org/x/crypto/acme/autocert"
24
+ "golang.org/x/net/idna"
14
25
)
15
26
16
27
type Server struct {
@@ -38,7 +49,13 @@ func (s *Server) Start() {
38
49
s .httpServer .Handler = manager .HTTPHandler (http .HandlerFunc (httpRedirectHandler ))
39
50
40
51
s .httpsServer = s .defaultHttpServer (httpsAddress )
41
- s .httpsServer .TLSConfig = manager .TLSConfig ()
52
+
53
+ if s .config .TLSLocal {
54
+ s .httpsServer .TLSConfig = s .localTLSConfig ()
55
+ } else {
56
+ s .httpsServer .TLSConfig = manager .TLSConfig ()
57
+ }
58
+
42
59
s .httpsServer .Handler = s .handler
43
60
44
61
go s .httpServer .ListenAndServe ()
@@ -84,6 +101,161 @@ func (s *Server) certManager() *autocert.Manager {
84
101
}
85
102
}
86
103
104
+ func (s * Server ) localTLSConfig () * tls.Config {
105
+ return & tls.Config {
106
+ GetCertificate : s .getLocalCertificate ,
107
+ NextProtos : []string {
108
+ "h2" , "http/1.1" , // enable HTTP/2
109
+ },
110
+ }
111
+ }
112
+
113
+ func (s * Server ) getLocalCertificate (hello * tls.ClientHelloInfo ) (* tls.Certificate , error ) {
114
+ name := hello .ServerName
115
+ if name == "" {
116
+ return nil , errors .New ("thruster_local_tls: missing server name" )
117
+ }
118
+
119
+ name , err := idna .Lookup .ToASCII (name )
120
+ if err != nil {
121
+ return nil , errors .New ("thruster/local_tls: server name contains invalid character" )
122
+ }
123
+
124
+ keyUsage := x509 .KeyUsageDigitalSignature
125
+ keyUsage |= x509 .KeyUsageKeyEncipherment
126
+
127
+ serialNumber , err := rand .Int (rand .Reader , new (big.Int ).Lsh (big .NewInt (1 ), 128 ))
128
+ if err != nil {
129
+ return nil , err
130
+ }
131
+
132
+ template := x509.Certificate {
133
+ SerialNumber : serialNumber ,
134
+ Subject : pkix.Name {
135
+ Organization : []string {"Thruster Local" },
136
+ },
137
+ NotBefore : time .Now (),
138
+ NotAfter : time .Now ().Add (365 * 10 * 24 * time .Hour ),
139
+ KeyUsage : keyUsage ,
140
+ ExtKeyUsage : []x509.ExtKeyUsage {x509 .ExtKeyUsageServerAuth },
141
+ BasicConstraintsValid : true ,
142
+ }
143
+
144
+ if ip := net .ParseIP (name ); ip != nil {
145
+ template .IPAddresses = append (template .IPAddresses , ip )
146
+ } else {
147
+ template .DNSNames = append (template .DNSNames , name )
148
+ }
149
+
150
+ authority , err := s .getLocalAuthority ()
151
+ if err != nil {
152
+ return nil , err
153
+ }
154
+
155
+ priv , err := rsa .GenerateKey (rand .Reader , 2048 )
156
+ if err != nil {
157
+ return nil , err
158
+ }
159
+
160
+ authcert , err := x509 .ParseCertificate (authority .Certificate [0 ])
161
+ if err != nil {
162
+ return nil , err
163
+ }
164
+
165
+ derBytes , err := x509 .CreateCertificate (rand .Reader , & template , authcert , & priv .PublicKey , authority .PrivateKey )
166
+ if err != nil {
167
+ return nil , err
168
+ }
169
+
170
+ cert := & tls.Certificate {
171
+ Certificate : [][]byte {authority .Certificate [0 ], derBytes },
172
+ PrivateKey : authority .PrivateKey ,
173
+ }
174
+
175
+ return cert , nil
176
+ }
177
+
178
+ func (s * Server ) getLocalAuthority () (* tls.Certificate , error ) {
179
+
180
+ cert , err := tls .LoadX509KeyPair (fmt .Sprintf ("%s/authority.crt" , s .config .StoragePath ), fmt .Sprintf ("%s/authority.pem" , s .config .StoragePath ))
181
+ if err == nil {
182
+ return & cert , nil
183
+ }
184
+
185
+ err = os .Mkdir (s .config .StoragePath , 0750 )
186
+
187
+ keyUsage := x509 .KeyUsageDigitalSignature
188
+ keyUsage |= x509 .KeyUsageKeyEncipherment
189
+ keyUsage |= x509 .KeyUsageCertSign
190
+
191
+ serialNumber , err := rand .Int (rand .Reader , new (big.Int ).Lsh (big .NewInt (1 ), 128 ))
192
+ if err != nil {
193
+ return nil , err
194
+ }
195
+
196
+ template := x509.Certificate {
197
+ SerialNumber : serialNumber ,
198
+ Subject : pkix.Name {
199
+ Organization : []string {"Thruster Local CA" },
200
+ },
201
+ NotBefore : time .Now (),
202
+ NotAfter : time .Now ().Add (365 * 10 * 24 * time .Hour ),
203
+ KeyUsage : keyUsage ,
204
+ ExtKeyUsage : []x509.ExtKeyUsage {x509 .ExtKeyUsageServerAuth },
205
+ BasicConstraintsValid : true ,
206
+ IsCA : true ,
207
+ }
208
+
209
+ priv , err := rsa .GenerateKey (rand .Reader , 2048 )
210
+ if err != nil {
211
+ return nil , err
212
+ }
213
+
214
+ derBytes , err := x509 .CreateCertificate (rand .Reader , & template , & template , & priv .PublicKey , priv )
215
+ if err != nil {
216
+ return nil , err
217
+ }
218
+
219
+ certOut , err := os .Create (fmt .Sprintf ("%s/authority.crt" , s .config .StoragePath ))
220
+ if err != nil {
221
+ return nil , err
222
+ }
223
+
224
+ if err := pem .Encode (certOut , & pem.Block {Type : "CERTIFICATE" , Bytes : derBytes }); err != nil {
225
+ return nil , err
226
+ }
227
+
228
+ if err := certOut .Close (); err != nil {
229
+ return nil , err
230
+ }
231
+
232
+ keyOut , err := os .Create (fmt .Sprintf ("%s/authority.pem" , s .config .StoragePath ))
233
+ if err != nil {
234
+ return nil , err
235
+ }
236
+
237
+ privBytes , err := x509 .MarshalPKCS8PrivateKey (priv )
238
+
239
+ if err != nil {
240
+ return nil , err
241
+ }
242
+
243
+ if err := pem .Encode (keyOut , & pem.Block {Type : "PRIVATE KEY" , Bytes : privBytes }); err != nil {
244
+ return nil , err
245
+ }
246
+
247
+ if err := keyOut .Close (); err != nil {
248
+ return nil , err
249
+ }
250
+
251
+ cer := tls.Certificate {
252
+ Certificate : [][]byte {derBytes },
253
+ PrivateKey : priv ,
254
+ }
255
+
256
+ return & cer , nil
257
+ }
258
+
87
259
func (s * Server ) externalAccountBinding () * acme.ExternalAccountBinding {
88
260
if s .config .EAB_KID == "" || s .config .EAB_HMACKey == "" {
89
261
return nil
0 commit comments