@@ -31,10 +31,11 @@ import (
31
31
32
32
"github.com/Jigsaw-Code/outline-sdk/transport"
33
33
"github.com/Jigsaw-Code/outline-sdk/transport/shadowsocks"
34
+ "github.com/Jigsaw-Code/outline-sdk/x/websocket"
35
+ "github.com/gorilla/handlers"
34
36
"github.com/lmittmann/tint"
35
37
"github.com/prometheus/client_golang/prometheus"
36
38
"github.com/prometheus/client_golang/prometheus/promhttp"
37
- "golang.org/x/net/websocket"
38
39
"golang.org/x/term"
39
40
40
41
"github.com/Jigsaw-Code/outline-ss-server/ipinfo"
@@ -306,18 +307,22 @@ func (s *OutlineServer) runConfig(config Config) (func() error, error) {
306
307
if err != nil {
307
308
return err
308
309
}
310
+ logger := slog .Default ().With (
311
+ slog .Int ("access_keys" , len (serviceConfig .Keys )),
312
+ slog .Any ("fwmark" , func () any {
313
+ if serviceConfig .Dialer .Fwmark == 0 {
314
+ return "disabled"
315
+ }
316
+ return serviceConfig .Dialer .Fwmark
317
+ }()),
318
+ )
309
319
for _ , cfg := range serviceConfig .Listeners {
310
320
if cfg .TCP != nil {
311
321
ln , err := lnSet .ListenStream (cfg .TCP .Address )
312
322
if err != nil {
313
323
return err
314
324
}
315
- slog .Info ("TCP service started." , "address" , ln .Addr ().String (), "fwmark" , func () any {
316
- if serviceConfig .Dialer .Fwmark == 0 {
317
- return "disabled"
318
- }
319
- return serviceConfig .Dialer .Fwmark
320
- }())
325
+ logger .Info ("TCP service started." , "address" , ln .Addr ().String ())
321
326
go service .StreamServe (ln .AcceptStream , func (ctx context.Context , conn transport.StreamConn ) {
322
327
streamHandler .HandleStream (ctx , conn , s .serviceMetrics .AddOpenTCPConnection (conn ))
323
328
})
@@ -326,12 +331,7 @@ func (s *OutlineServer) runConfig(config Config) (func() error, error) {
326
331
if err != nil {
327
332
return err
328
333
}
329
- slog .Info ("UDP service started." , "address" , pc .LocalAddr ().String (), "fwmark" , func () any {
330
- if serviceConfig .Dialer .Fwmark == 0 {
331
- return "disabled"
332
- }
333
- return serviceConfig .Dialer .Fwmark
334
- }())
334
+ logger .Info ("UDP service started." , "address" , pc .LocalAddr ().String ())
335
335
go service .PacketServe (pc , func (ctx context.Context , conn net.Conn ) {
336
336
associationHandler .HandleAssociation (ctx , conn , s .serviceMetrics .AddOpenUDPAssociation (conn ))
337
337
}, s .serverMetrics )
@@ -340,48 +340,37 @@ func (s *OutlineServer) runConfig(config Config) (func() error, error) {
340
340
return fmt .Errorf ("websocket-stream listener references unknown web server `%s`" , cfg .WebsocketStream .WebServer )
341
341
}
342
342
mux := webServers [cfg .WebsocketStream .WebServer ]
343
- // TODO: Support a "half-closed" state for WebSockets.
344
343
handler := http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
345
- handler := func (wsConn * websocket.Conn ) {
346
- defer wsConn .Close ()
347
- ctx , contextCancel := context .WithCancel (context .Background ())
348
- defer contextCancel ()
349
- clientIP , err := onet .GetClientIPFromRequest (r )
350
- if err != nil {
351
- slog .Error ("failed to determine client address" , "err" , err )
352
- w .WriteHeader (http .StatusBadGateway )
353
- return
354
- }
355
- conn := & streamConn {& replaceAddrConn {Conn : wsConn , raddr : & net.TCPAddr {IP : clientIP }}}
356
- streamHandler .HandleStream (ctx , conn , s .serviceMetrics .AddOpenTCPConnection (conn ))
344
+ conn , err := websocket .Upgrade (w , r , nil )
345
+ if err != nil {
346
+ slog .Error ("failed to upgrade" , "err" , err )
357
347
}
358
- websocket .Handler (handler ).ServeHTTP (w , r )
348
+ defer conn .Close ()
349
+ if clientIP := net .ParseIP (r .RemoteAddr ); clientIP != nil {
350
+ conn = & replaceAddrConn {StreamConn : conn , raddr : & net.TCPAddr {IP : clientIP }}
351
+ }
352
+ streamHandler .HandleStream (r .Context (), conn , s .serviceMetrics .AddOpenTCPConnection (conn ))
359
353
})
360
- mux .Handle (cfg .WebsocketStream .Path , http .StripPrefix (cfg .WebsocketStream .Path , handler ))
361
- slog .Info ("WebSocket stream service started." , "ID" , cfg .WebsocketStream .WebServer , "path" , cfg .WebsocketStream .Path )
354
+ mux .Handle (cfg .WebsocketStream .Path , http .StripPrefix (cfg .WebsocketStream .Path , handlers . ProxyHeaders ( handler ) ))
355
+ logger .Info ("WebSocket stream service started." , "ID" , cfg .WebsocketStream .WebServer , "path" , cfg .WebsocketStream .Path )
362
356
} else if cfg .WebsocketPacket != nil {
363
357
if _ , exists := webServers [cfg .WebsocketPacket .WebServer ]; ! exists {
364
358
return fmt .Errorf ("websocket-packet listener references unknown web server `%s`" , cfg .WebsocketPacket .WebServer )
365
359
}
366
360
mux := webServers [cfg .WebsocketPacket .WebServer ]
367
361
handler := http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
368
- handler := func (wsConn * websocket.Conn ) {
369
- defer wsConn .Close ()
370
- ctx , contextCancel := context .WithCancel (context .Background ())
371
- defer contextCancel ()
372
- clientIP , err := onet .GetClientIPFromRequest (r )
373
- if err != nil {
374
- slog .Error ("failed to determine client address" , "err" , err )
375
- w .WriteHeader (http .StatusBadGateway )
376
- return
377
- }
378
- conn := & replaceAddrConn {Conn : wsConn , raddr : & net.UDPAddr {IP : clientIP }}
379
- associationHandler .HandleAssociation (ctx , conn , s .serviceMetrics .AddOpenUDPAssociation (conn ))
362
+ conn , err := websocket .Upgrade (w , r , nil )
363
+ if err != nil {
364
+ slog .Error ("failed to upgrade" , "err" , err )
365
+ }
366
+ defer conn .Close ()
367
+ if clientIP := net .ParseIP (r .RemoteAddr ); clientIP != nil {
368
+ conn = & replaceAddrConn {StreamConn : conn , raddr : & net.UDPAddr {IP : clientIP }}
380
369
}
381
- websocket . Handler ( handler ). ServeHTTP ( w , r )
370
+ associationHandler . HandleAssociation ( r . Context (), conn , s . serviceMetrics . AddOpenUDPAssociation ( conn ) )
382
371
})
383
- mux .Handle (cfg .WebsocketPacket .Path , http .StripPrefix (cfg .WebsocketPacket .Path , handler ))
384
- slog .Info ("WebSocket packet service started." , "ID" , cfg .WebsocketPacket .WebServer , "path" , cfg .WebsocketPacket .Path )
372
+ mux .Handle (cfg .WebsocketPacket .Path , http .StripPrefix (cfg .WebsocketPacket .Path , handlers . ProxyHeaders ( handler ) ))
373
+ logger .Info ("WebSocket packet service started." , "ID" , cfg .WebsocketPacket .WebServer , "path" , cfg .WebsocketPacket .Path )
385
374
} else {
386
375
return fmt .Errorf ("unknown listener configuration: %v" , cfg )
387
376
}
@@ -452,31 +441,16 @@ func RunOutlineServer(filename string, natTimeout time.Duration, serverMetrics *
452
441
}
453
442
454
443
// TODO: Create a dedicated `ClientConn` struct with `ClientAddr` and `Conn`.
455
- // replaceAddrConn overrides [websocket.Conn ]'s remote address handling.
444
+ // replaceAddrConn overrides a [transport.StreamConn ]'s remote address handling.
456
445
type replaceAddrConn struct {
457
- * websocket. Conn
446
+ transport. StreamConn
458
447
raddr net.Addr
459
448
}
460
449
461
450
func (c replaceAddrConn ) RemoteAddr () net.Addr {
462
451
return c .raddr
463
452
}
464
453
465
- type streamConn struct {
466
- net.Conn
467
- }
468
-
469
- var _ transport.StreamConn = (* streamConn )(nil )
470
-
471
- // TODO: Support a "half-closed" state.
472
- func (c * streamConn ) CloseRead () error {
473
- return c .Close ()
474
- }
475
-
476
- func (c * streamConn ) CloseWrite () error {
477
- return c .Close ()
478
- }
479
-
480
454
func main () {
481
455
slog .SetDefault (slog .New (logHandler ))
482
456
0 commit comments