@@ -30,10 +30,11 @@ import (
30
30
)
31
31
32
32
var (
33
- serverSecret = ""
34
- serverAddr = ""
35
-
36
33
uiPath = ""
34
+
35
+ httpServer * http.Server
36
+ tlsServer * http.Server
37
+ unixServer * http.Server
37
38
)
38
39
39
40
type Traffic struct {
@@ -46,11 +47,28 @@ type Memory struct {
46
47
OSLimit uint64 `json:"oslimit"` // maybe we need it in the future
47
48
}
48
49
50
+ type Config struct {
51
+ Addr string
52
+ TLSAddr string
53
+ UnixAddr string
54
+ Secret string
55
+ Certificate string
56
+ PrivateKey string
57
+ DohServer string
58
+ IsDebug bool
59
+ }
60
+
61
+ func ReCreateServer (cfg * Config ) {
62
+ go start (cfg )
63
+ go startTLS (cfg )
64
+ go startUnix (cfg )
65
+ }
66
+
49
67
func SetUIPath (path string ) {
50
68
uiPath = C .Path .Resolve (path )
51
69
}
52
70
53
- func router (isDebug bool , withAuth bool , dohServer string ) * chi.Mux {
71
+ func router (isDebug bool , secret string , dohServer string ) * chi.Mux {
54
72
r := chi .NewRouter ()
55
73
corsM := cors .New (cors.Options {
56
74
AllowedOrigins : []string {"*" },
@@ -72,8 +90,8 @@ func router(isDebug bool, withAuth bool, dohServer string) *chi.Mux {
72
90
}())
73
91
}
74
92
r .Group (func (r chi.Router ) {
75
- if withAuth {
76
- r .Use (authentication )
93
+ if secret != "" {
94
+ r .Use (authentication ( secret ) )
77
95
}
78
96
r .Get ("/" , hello )
79
97
r .Get ("/logs" , getLogs )
@@ -111,88 +129,111 @@ func router(isDebug bool, withAuth bool, dohServer string) *chi.Mux {
111
129
return r
112
130
}
113
131
114
- func Start (addr string , tlsAddr string , secret string ,
115
- certificate , privateKey string , dohServer string , isDebug bool ) {
116
- if serverAddr != "" {
117
- return
132
+ func start (cfg * Config ) {
133
+ // first stop existing server
134
+ if httpServer != nil {
135
+ _ = httpServer .Close ()
136
+ httpServer = nil
118
137
}
119
138
120
- serverAddr = addr
121
- serverSecret = secret
122
-
123
- if len (tlsAddr ) > 0 {
124
- go func () {
125
- c , err := CN .ParseCert (certificate , privateKey , C .Path )
126
- if err != nil {
127
- log .Errorln ("External controller tls listen error: %s" , err )
128
- return
129
- }
139
+ // handle addr
140
+ if len (cfg .Addr ) > 0 {
141
+ l , err := inbound .Listen ("tcp" , cfg .Addr )
142
+ if err != nil {
143
+ log .Errorln ("External controller listen error: %s" , err )
144
+ return
145
+ }
146
+ log .Infoln ("RESTful API listening at: %s" , l .Addr ().String ())
130
147
131
- l , err := inbound .Listen ("tcp" , tlsAddr )
132
- if err != nil {
133
- log .Errorln ("External controller tls listen error: %s" , err )
134
- return
135
- }
148
+ server := & http.Server {
149
+ Handler : router (cfg .IsDebug , cfg .Secret , cfg .DohServer ),
150
+ }
151
+ if err = server .Serve (l ); err != nil {
152
+ log .Errorln ("External controller serve error: %s" , err )
153
+ }
154
+ httpServer = server
155
+ }
156
+ }
136
157
137
- serverAddr = l .Addr ().String ()
138
- log .Infoln ("RESTful API tls listening at: %s" , serverAddr )
139
- tlsServe := & http.Server {
140
- Handler : router (isDebug , true , dohServer ),
141
- TLSConfig : & tls.Config {
142
- Certificates : []tls.Certificate {c },
143
- },
144
- }
145
- if err = tlsServe .ServeTLS (l , "" , "" ); err != nil {
146
- log .Errorln ("External controller tls serve error: %s" , err )
147
- }
148
- }()
158
+ func startTLS (cfg * Config ) {
159
+ // first stop existing server
160
+ if tlsServer != nil {
161
+ _ = tlsServer .Close ()
162
+ tlsServer = nil
149
163
}
150
164
151
- l , err := inbound .Listen ("tcp" , addr )
152
- if err != nil {
153
- log .Errorln ("External controller listen error: %s" , err )
154
- return
165
+ // handle tlsAddr
166
+ if len (cfg .TLSAddr ) > 0 {
167
+ c , err := CN .ParseCert (cfg .Certificate , cfg .PrivateKey , C .Path )
168
+ if err != nil {
169
+ log .Errorln ("External controller tls listen error: %s" , err )
170
+ return
171
+ }
172
+
173
+ l , err := inbound .Listen ("tcp" , cfg .TLSAddr )
174
+ if err != nil {
175
+ log .Errorln ("External controller tls listen error: %s" , err )
176
+ return
177
+ }
178
+
179
+ log .Infoln ("RESTful API tls listening at: %s" , l .Addr ().String ())
180
+ server := & http.Server {
181
+ Handler : router (cfg .IsDebug , cfg .Secret , cfg .DohServer ),
182
+ TLSConfig : & tls.Config {
183
+ Certificates : []tls.Certificate {c },
184
+ },
185
+ }
186
+ if err = server .ServeTLS (l , "" , "" ); err != nil {
187
+ log .Errorln ("External controller tls serve error: %s" , err )
188
+ }
189
+ tlsServer = server
155
190
}
156
- serverAddr = l .Addr ().String ()
157
- log .Infoln ("RESTful API listening at: %s" , serverAddr )
191
+ }
158
192
159
- if err = http .Serve (l , router (isDebug , true , dohServer )); err != nil {
160
- log .Errorln ("External controller serve error: %s" , err )
193
+ func startUnix (cfg * Config ) {
194
+ // first stop existing server
195
+ if unixServer != nil {
196
+ _ = unixServer .Close ()
197
+ unixServer = nil
161
198
}
162
199
163
- }
200
+ // handle addr
201
+ if len (cfg .UnixAddr ) > 0 {
202
+ addr := C .Path .Resolve (cfg .UnixAddr )
203
+
204
+ dir := filepath .Dir (addr )
205
+ if _ , err := os .Stat (dir ); os .IsNotExist (err ) {
206
+ if err := os .MkdirAll (dir , 0o755 ); err != nil {
207
+ log .Errorln ("External controller unix listen error: %s" , err )
208
+ return
209
+ }
210
+ }
164
211
165
- func StartUnix (addr string , dohServer string , isDebug bool ) {
166
- addr = C .Path .Resolve (addr )
212
+ // https://devblogs.microsoft.com/commandline/af_unix-comes-to-windows/
213
+ //
214
+ // Note: As mentioned above in the ‘security’ section, when a socket binds a socket to a valid pathname address,
215
+ // a socket file is created within the filesystem. On Linux, the application is expected to unlink
216
+ // (see the notes section in the man page for AF_UNIX) before any other socket can be bound to the same address.
217
+ // The same applies to Windows unix sockets, except that, DeleteFile (or any other file delete API)
218
+ // should be used to delete the socket file prior to calling bind with the same path.
219
+ _ = syscall .Unlink (addr )
167
220
168
- dir := filepath .Dir (addr )
169
- if _ , err := os .Stat (dir ); os .IsNotExist (err ) {
170
- if err := os .MkdirAll (dir , 0o755 ); err != nil {
221
+ l , err := inbound .Listen ("unix" , addr )
222
+ if err != nil {
171
223
log .Errorln ("External controller unix listen error: %s" , err )
172
224
return
173
225
}
174
- }
226
+ log . Infoln ( "RESTful API unix listening at: %s" , l . Addr (). String ())
175
227
176
- // https://devblogs.microsoft.com/commandline/af_unix-comes-to-windows/
177
- //
178
- // Note: As mentioned above in the ‘security’ section, when a socket binds a socket to a valid pathname address,
179
- // a socket file is created within the filesystem. On Linux, the application is expected to unlink
180
- // (see the notes section in the man page for AF_UNIX) before any other socket can be bound to the same address.
181
- // The same applies to Windows unix sockets, except that, DeleteFile (or any other file delete API)
182
- // should be used to delete the socket file prior to calling bind with the same path.
183
- _ = syscall .Unlink (addr )
184
-
185
- l , err := inbound .Listen ("unix" , addr )
186
- if err != nil {
187
- log .Errorln ("External controller unix listen error: %s" , err )
188
- return
228
+ server := & http.Server {
229
+ Handler : router (cfg .IsDebug , "" , cfg .DohServer ),
230
+ }
231
+ if err = server .Serve (l ); err != nil {
232
+ log .Errorln ("External controller unix serve error: %s" , err )
233
+ }
234
+ unixServer = server
189
235
}
190
- serverAddr = l .Addr ().String ()
191
- log .Infoln ("RESTful API unix listening at: %s" , serverAddr )
192
236
193
- if err = http .Serve (l , router (isDebug , false , dohServer )); err != nil {
194
- log .Errorln ("External controller unix serve error: %s" , err )
195
- }
196
237
}
197
238
198
239
func setPrivateNetworkAccess (next http.Handler ) http.Handler {
@@ -210,38 +251,35 @@ func safeEuqal(a, b string) bool {
210
251
return subtle .ConstantTimeCompare (aBuf , bBuf ) == 1
211
252
}
212
253
213
- func authentication (next http.Handler ) http.Handler {
214
- fn := func (w http.ResponseWriter , r * http.Request ) {
215
- if serverSecret == "" {
216
- next .ServeHTTP (w , r )
217
- return
218
- }
254
+ func authentication (secret string ) func (http.Handler ) http.Handler {
255
+ return func (next http.Handler ) http.Handler {
256
+ fn := func (w http.ResponseWriter , r * http.Request ) {
257
+ // Browser websocket not support custom header
258
+ if r .Header .Get ("Upgrade" ) == "websocket" && r .URL .Query ().Get ("token" ) != "" {
259
+ token := r .URL .Query ().Get ("token" )
260
+ if ! safeEuqal (token , secret ) {
261
+ render .Status (r , http .StatusUnauthorized )
262
+ render .JSON (w , r , ErrUnauthorized )
263
+ return
264
+ }
265
+ next .ServeHTTP (w , r )
266
+ return
267
+ }
219
268
220
- // Browser websocket not support custom header
221
- if r .Header .Get ("Upgrade" ) == "websocket" && r .URL .Query ().Get ("token" ) != "" {
222
- token := r .URL .Query ().Get ("token" )
223
- if ! safeEuqal (token , serverSecret ) {
269
+ header := r .Header .Get ("Authorization" )
270
+ bearer , token , found := strings .Cut (header , " " )
271
+
272
+ hasInvalidHeader := bearer != "Bearer"
273
+ hasInvalidSecret := ! found || ! safeEuqal (token , secret )
274
+ if hasInvalidHeader || hasInvalidSecret {
224
275
render .Status (r , http .StatusUnauthorized )
225
276
render .JSON (w , r , ErrUnauthorized )
226
277
return
227
278
}
228
279
next .ServeHTTP (w , r )
229
- return
230
280
}
231
-
232
- header := r .Header .Get ("Authorization" )
233
- bearer , token , found := strings .Cut (header , " " )
234
-
235
- hasInvalidHeader := bearer != "Bearer"
236
- hasInvalidSecret := ! found || ! safeEuqal (token , serverSecret )
237
- if hasInvalidHeader || hasInvalidSecret {
238
- render .Status (r , http .StatusUnauthorized )
239
- render .JSON (w , r , ErrUnauthorized )
240
- return
241
- }
242
- next .ServeHTTP (w , r )
281
+ return http .HandlerFunc (fn )
243
282
}
244
- return http .HandlerFunc (fn )
245
283
}
246
284
247
285
func hello (w http.ResponseWriter , r * http.Request ) {
0 commit comments