@@ -31,10 +31,11 @@ import (
3131
3232 "github.com/Jigsaw-Code/outline-sdk/transport"
3333 "github.com/Jigsaw-Code/outline-sdk/transport/shadowsocks"
34+ "github.com/Jigsaw-Code/outline-sdk/x/websocket"
35+ "github.com/gorilla/handlers"
3436 "github.com/lmittmann/tint"
3537 "github.com/prometheus/client_golang/prometheus"
3638 "github.com/prometheus/client_golang/prometheus/promhttp"
37- "golang.org/x/net/websocket"
3839 "golang.org/x/term"
3940
4041 "github.com/Jigsaw-Code/outline-ss-server/ipinfo"
@@ -306,18 +307,22 @@ func (s *OutlineServer) runConfig(config Config) (func() error, error) {
306307 if err != nil {
307308 return err
308309 }
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+ )
309319 for _ , cfg := range serviceConfig .Listeners {
310320 if cfg .TCP != nil {
311321 ln , err := lnSet .ListenStream (cfg .TCP .Address )
312322 if err != nil {
313323 return err
314324 }
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 ())
321326 go service .StreamServe (ln .AcceptStream , func (ctx context.Context , conn transport.StreamConn ) {
322327 streamHandler .HandleStream (ctx , conn , s .serviceMetrics .AddOpenTCPConnection (conn ))
323328 })
@@ -326,12 +331,7 @@ func (s *OutlineServer) runConfig(config Config) (func() error, error) {
326331 if err != nil {
327332 return err
328333 }
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 ())
335335 go service .PacketServe (pc , func (ctx context.Context , conn net.Conn ) {
336336 associationHandler .HandleAssociation (ctx , conn , s .serviceMetrics .AddOpenUDPAssociation (conn ))
337337 }, s .serverMetrics )
@@ -340,48 +340,37 @@ func (s *OutlineServer) runConfig(config Config) (func() error, error) {
340340 return fmt .Errorf ("websocket-stream listener references unknown web server `%s`" , cfg .WebsocketStream .WebServer )
341341 }
342342 mux := webServers [cfg .WebsocketStream .WebServer ]
343- // TODO: Support a "half-closed" state for WebSockets.
344343 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 )
357347 }
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 ))
359353 })
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 )
362356 } else if cfg .WebsocketPacket != nil {
363357 if _ , exists := webServers [cfg .WebsocketPacket .WebServer ]; ! exists {
364358 return fmt .Errorf ("websocket-packet listener references unknown web server `%s`" , cfg .WebsocketPacket .WebServer )
365359 }
366360 mux := webServers [cfg .WebsocketPacket .WebServer ]
367361 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 }}
380369 }
381- websocket . Handler ( handler ). ServeHTTP ( w , r )
370+ associationHandler . HandleAssociation ( r . Context (), conn , s . serviceMetrics . AddOpenUDPAssociation ( conn ) )
382371 })
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 )
385374 } else {
386375 return fmt .Errorf ("unknown listener configuration: %v" , cfg )
387376 }
@@ -452,31 +441,16 @@ func RunOutlineServer(filename string, natTimeout time.Duration, serverMetrics *
452441}
453442
454443// 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.
456445type replaceAddrConn struct {
457- * websocket. Conn
446+ transport. StreamConn
458447 raddr net.Addr
459448}
460449
461450func (c replaceAddrConn ) RemoteAddr () net.Addr {
462451 return c .raddr
463452}
464453
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-
480454func main () {
481455 slog .SetDefault (slog .New (logHandler ))
482456
0 commit comments