-
Notifications
You must be signed in to change notification settings - Fork 191
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(caddy): add a WebSockets handler that connects to Shadowsocks handler #216
base: master
Are you sure you want to change the base?
Conversation
23e1d37
to
2f96565
Compare
2f96565
to
21b32cb
Compare
46407e4
to
c4a74d7
Compare
c4f554e
to
1a18692
Compare
caddy/ws2outline_handler.go
Outdated
compiledHandler layer4.NextHandler | ||
|
||
logger *slog.Logger | ||
zlogger *zap.Logger |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do you need both loggers?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because caddy's WrapConnection()
expects a zap logger, not an slog logger: https://github.com/mholt/caddy-l4/blob/87e3e5e2c7f986b34c0df373a5799670d7b8ca03/layer4/connection.go#L33. We use it below in the ServeHTTP()
function, so we have to reference both.
caddy/ws2outline_handler.go
Outdated
compiledHandler layer4.NextHandler | ||
|
||
logger *slog.Logger | ||
zlogger *zap.Logger |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because caddy's WrapConnection()
expects a zap logger, not an slog logger: https://github.com/mholt/caddy-l4/blob/87e3e5e2c7f986b34c0df373a5799670d7b8ca03/layer4/connection.go#L33. We use it below in the ServeHTTP()
function, so we have to reference both.
@@ -346,8 +346,9 @@ func (s *OutlineServer) runConfig(config Config) (func() error, error) { | |||
slog.Error("failed to upgrade", "err", err) | |||
} | |||
defer conn.Close() | |||
if clientIP := net.ParseIP(r.RemoteAddr); clientIP != nil { | |||
conn = &replaceAddrConn{StreamConn: conn, raddr: &net.TCPAddr{IP: clientIP}} | |||
clientAddrPort, err := onet.ParseAddrPortOrIP(r.RemoteAddr) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not a fan of not knowing our types. This makes our code fragile.
At a minimum, we need to document when to expect an IP and when to expect an addr:port.
But the http documentation says this is a host:port. Why do you need to parse as IP?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The documentation also states the RemoteAddr
has no defined format. The http server sets it to host:port, but the forwarded proxy headers are usually just an IP. The gorilla library sets the header IP value in RemoteAddr: https://github.com/gorilla/handlers/blob/9c61bd81e701cf500437e1b516b675cdd3b73ca7/proxy_headers.go#L46C13-L46C18. If we want to use that we should support both. I can add a comment though.
} | ||
} | ||
} | ||
cx := layer4.WrapConnection(conn, []byte{}, h.zlogger) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do you need this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The layer4 handler we pass this to expects a *layer4.Connection. https://github.com/mholt/caddy-l4/blob/87e3e5e2c7f986b34c0df373a5799670d7b8ca03/layer4/connection.go#L33
This PR enables Shadowsocks-over-WebSockets functionality in the Caddy server, allowing clients to connect to Shadowsocks servers via WebSockets. This is achieved by introducing three new modules:
Named Connection Handlers: These reusable handlers can be shared by different applications and are configured within the Outline app.
WebSocket-to-Outline Handler: An HTTP app handler which bridges WebSocket requests to a designated named connection handler, enabling Shadowsocks connections over WebSockets.
Layer4 Outline Handler: A layer 4 handler which bridges TCP/UDP connections to a designated named connection handler.
Example Configuration:
This example demonstrates how to configure a Shadowsocks handler with access keys and utilize it for both WebSocket and TCP connections: