Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions server/config_check_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2404,7 +2404,7 @@ func TestConfigCheck(t *testing.T) {
leafnodes {
remotes = [
{
url: "ws://127.0.0.1:7422"
url: "nats://127.0.0.1:7422"
proxy {
url: "ftp://proxy.example.com:8080"
}
Expand All @@ -2422,7 +2422,7 @@ func TestConfigCheck(t *testing.T) {
leafnodes {
remotes = [
{
url: "ws://127.0.0.1:7422"
url: "nats://127.0.0.1:7422"
proxy {
url: "http://"
}
Expand All @@ -2440,7 +2440,7 @@ func TestConfigCheck(t *testing.T) {
leafnodes {
remotes = [
{
url: "ws://127.0.0.1:7422"
url: "nats://127.0.0.1:7422"
proxy {
url: "http://proxy.example.com:8080"
username: "testuser"
Expand All @@ -2459,7 +2459,7 @@ func TestConfigCheck(t *testing.T) {
leafnodes {
remotes = [
{
url: "ws://127.0.0.1:7422"
url: "nats://127.0.0.1:7422"
proxy {
url: "http://proxy.example.com:8080"
password: "testpass"
Expand Down
34 changes: 12 additions & 22 deletions server/leafnode.go
Original file line number Diff line number Diff line change
Expand Up @@ -399,26 +399,12 @@ func validateLeafNodeProxyOptions(remote *RemoteLeafOpts) ([]string, error) {
}

if len(remote.URLs) > 0 {
hasWebSocketURL := false
hasNonWebSocketURL := false

for _, remoteURL := range remote.URLs {
if remoteURL.Scheme == wsSchemePrefix || remoteURL.Scheme == wsSchemePrefixTLS {
hasWebSocketURL = true
if (remoteURL.Scheme == wsSchemePrefixTLS) &&
remote.TLSConfig == nil && !remote.TLS {
return warnings, fmt.Errorf("proxy is configured but remote URL %s requires TLS and no TLS configuration is provided. When using proxy with TLS endpoints, ensure TLS is properly configured for the leafnode remote", remoteURL.String())
}
} else {
hasNonWebSocketURL = true
if (remoteURL.Scheme == wsSchemePrefixTLS) &&
remote.TLSConfig == nil && !remote.TLS {
return warnings, fmt.Errorf("proxy is configured but remote URL %s requires TLS and no TLS configuration is provided. When using proxy with TLS endpoints, ensure TLS is properly configured for the leafnode remote", remoteURL.String())
}
}

if !hasWebSocketURL {
warnings = append(warnings, "proxy configuration will be ignored: proxy settings only apply to WebSocket connections (ws:// or wss://), but all configured URLs use TCP connections (nats://)")
} else if hasNonWebSocketURL {
warnings = append(warnings, "proxy configuration will only be used for WebSocket URLs: proxy settings do not apply to TCP connections (nats://)")
}
}

return warnings, nil
Expand Down Expand Up @@ -752,15 +738,19 @@ func (s *Server) connectToRemoteLeafNode(remote *leafNodeCfg, firstConnect bool)
} else {
s.Debugf("Trying to connect as leafnode to remote server on %q%s", rURL.Host, ipStr)

// Check if proxy is configured first, then check if URL supports it
if proxyURL != _EMPTY_ && isWSURL(rURL) {
// Use proxy for WebSocket connections - use original hostname, resolved IP for connection
// Check if proxy is configured
if proxyURL != _EMPTY_ {
// Use proxy for connection - use original hostname, resolved IP for connection
targetHost := rURL.Host
// If URL doesn't include port, add the default port for the scheme
if rURL.Port() == _EMPTY_ {
defaultPort := "80"
if rURL.Scheme == wsSchemePrefixTLS {
defaultPort := "4222" // Default NATS port
if rURL.Scheme == "tls" || rURL.Scheme == "nats+tls" {
defaultPort = "4222" // NATS TLS still uses 4222 by default
} else if rURL.Scheme == wsSchemePrefixTLS {
defaultPort = "443"
} else if rURL.Scheme == wsSchemePrefix {
defaultPort = "80"
}
targetHost = net.JoinHostPort(rURL.Hostname(), defaultPort)
}
Expand Down
54 changes: 48 additions & 6 deletions server/leafnode_proxy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ func TestLeafNodeHttpProxyConfigWarnings(t *testing.T) {
warningMatch string
}{
{
name: "proxy with only TCP URLs",
name: "proxy with only TCP URLs - now supported",
config: `
leafnodes {
remotes = [
Expand All @@ -272,11 +272,10 @@ func TestLeafNodeHttpProxyConfigWarnings(t *testing.T) {
]
}
`,
expectWarning: true,
warningMatch: "proxy configuration will be ignored",
expectWarning: false, // No longer generates warnings
},
{
name: "proxy with mixed TCP and WebSocket URLs",
name: "proxy with mixed TCP and WebSocket URLs - now supported",
config: `
leafnodes {
remotes = [
Expand All @@ -289,8 +288,7 @@ func TestLeafNodeHttpProxyConfigWarnings(t *testing.T) {
]
}
`,
expectWarning: true,
warningMatch: "proxy configuration will only be used for WebSocket URLs",
expectWarning: false, // No longer generates warnings
},
{
name: "proxy with only WebSocket URLs",
Expand Down Expand Up @@ -388,6 +386,50 @@ func TestLeafNodeHttpProxyConnection(t *testing.T) {
checkLeafNodeConnected(t, hub)
}

func TestLeafNodeHttpProxyConnectionTCP(t *testing.T) {
// Create a hub server with regular TCP leafnode support
hubConfig := createConfFile(t, []byte(`
listen: "127.0.0.1:-1"
leafnodes {
listen: "127.0.0.1:-1"
}
`))

hub, hubOpts := RunServerWithConfig(hubConfig)
defer hub.Shutdown()

// Create HTTP proxy
proxy := createTestHTTPProxy(_EMPTY_, _EMPTY_)
proxy.start()
defer proxy.stop()

// Create spoke server with proxy configuration for TCP connection via config file
configContent := fmt.Sprintf(`
listen: "127.0.0.1:-1"
leafnodes {
reconnect_interval: "50ms"
remotes = [
{
url: "nats://127.0.0.1:%d"
proxy {
url: "%s"
timeout: 5s
}
}
]
}
`, hubOpts.LeafNode.Port, proxy.url())

configFile := createConfFile(t, []byte(configContent))

spoke, _ := RunServerWithConfig(configFile)
defer spoke.Shutdown()

// Verify leafnode connections are established
checkLeafNodeConnected(t, spoke)
checkLeafNodeConnected(t, hub)
}

func TestLeafNodeHttpProxyWithAuthentication(t *testing.T) {
// Create a hub server with WebSocket support using config file
hubConfig := createConfFile(t, []byte(`
Expand Down
2 changes: 1 addition & 1 deletion server/opts.go
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ type RemoteLeafOpts struct {
NoMasking bool `json:"-"`
}

// HTTP Proxy configuration for WebSocket connections
// HTTP Proxy configuration for leafnode connections
Proxy struct {
// URL of the HTTP proxy server (e.g., "http://proxy.example.com:8080")
URL string `json:"-"`
Expand Down