mirror of
https://github.com/gogrlx/nats-server.git
synced 2026-04-02 03:38:42 -07:00
Fix for #1256, mixed IP and DNS for cluster and TLS with leafnodes
Signed-off-by: Derek Collison <derek@nats.io>
This commit is contained in:
2
go.mod
2
go.mod
@@ -9,3 +9,5 @@ require (
|
||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4
|
||||
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e
|
||||
)
|
||||
|
||||
go 1.13
|
||||
|
||||
@@ -652,7 +652,7 @@ func (s *Server) createLeafNode(conn net.Conn, remote *leafNodeCfg) *client {
|
||||
url := c.leaf.remote.getCurrentURL()
|
||||
host, _, _ := net.SplitHostPort(url.Host)
|
||||
// We need to check if this host is an IP. If so, we probably
|
||||
// had this advertised to us an should use the configured host
|
||||
// had this advertised to us and should use the configured host
|
||||
// name for the TLS server name.
|
||||
if net.ParseIP(host) != nil {
|
||||
if c.leaf.remote.tlsName != "" {
|
||||
@@ -679,9 +679,18 @@ func (s *Server) createLeafNode(conn net.Conn, remote *leafNodeCfg) *client {
|
||||
|
||||
// Force handshake
|
||||
c.mu.Unlock()
|
||||
if err := conn.Handshake(); err != nil {
|
||||
if err = conn.Handshake(); err != nil {
|
||||
c.Errorf("TLS handshake error: %v", err)
|
||||
c.closeConnection(TLSHandshakeError)
|
||||
// If we overrode and used the saved tlsName but that failed
|
||||
// we will clear that here. This is for the case that another server
|
||||
// does not have the same tlsName, maybe only IPs.
|
||||
// https://github.com/nats-io/nats-server/issues/1256
|
||||
c.mu.Lock()
|
||||
if host == c.leaf.remote.tlsName {
|
||||
c.leaf.remote.tlsName = ""
|
||||
}
|
||||
c.mu.Unlock()
|
||||
return nil
|
||||
}
|
||||
// Reset the read deadline
|
||||
|
||||
21
test/configs/certs/server-iponly.pem
Normal file
21
test/configs/certs/server-iponly.pem
Normal file
@@ -0,0 +1,21 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDgTCCAmmgAwIBAgIJAJT2U0V//QjOMA0GCSqGSIb3DQEBBQUAMHAxCzAJBgNV
|
||||
BAYTAlVTMQswCQYDVQQIDAJDQTEQMA4GA1UECgwHU3luYWRpYTEQMA4GA1UECwwH
|
||||
bmF0cy5pbzESMBAGA1UEAwwJbG9jYWxob3N0MRwwGgYJKoZIhvcNAQkBFg1kZXJl
|
||||
a0BuYXRzLmlvMB4XDTIwMDEyMjE1MDQ1M1oXDTMwMDExOTE1MDQ1M1owXDELMAkG
|
||||
A1UEBhMCVVMxCzAJBgNVBAgMAkNBMRAwDgYDVQQKDAdTeW5hZGlhMRAwDgYDVQQL
|
||||
DAdOQVRTLmlvMRwwGgYJKoZIhvcNAQkBFg1kZXJla0BuYXRzLmlvMIIBIjANBgkq
|
||||
hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvZjcFEmSQxpzNnVtwTNzs+f2iuID9yST
|
||||
6zbaj2TGVhm3ktLx39NPfnjO29xu1FxYpKd5a0n/MDfZcZIh15FyjRohdQ+AI/Av
|
||||
DmoaYpvrHnTf32GKBagxt9SX7sZgG2+xhZusPc2hnqi1VoTOn4xkpVdBdYHGAMjY
|
||||
Pe+FnHgESVqUKa8nCr5WYGugUgZT9c/OR5zPUIodkjoh0STtgeiFl4xBRpbaAte3
|
||||
9auSTKsK4hmfuCEHXPfRfm5JcKnERcOyEKvKUOPJ6m+1GWQSMg6TWfiO/KK8M/Ml
|
||||
5FmYbQ6XdrbanlDPTaFrYs5HhB33gora0JDnph9DJWFXwxV+4LhcFwIDAQABozIw
|
||||
MDAPBgNVHREECDAGhwR/AAABMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcD
|
||||
ATANBgkqhkiG9w0BAQUFAAOCAQEAlfWreTwqvMk3EXSW6ii781l7ypIRzaExxqYu
|
||||
aBWtE7Q5UlISNFAsRu9TPqMHCtot52B/E3cPANcMRAQmzSlGhrqCVSpd6L7QTk+2
|
||||
b7UZHlFnxRHh8Pja25Z/R5vozV/3I1lDtRKGImSWa8GUHqNOkqz2sIWCUm2xWGL6
|
||||
Xiyr3LFzrelB6dMAlCiuHC5LVvjaEq/x3SKZ87XxAfbfBWLbbfDA95ZmWuskOSGv
|
||||
8ntY0Y6fdXwAIzAldeFctNhmLy2cn2THQj3Qy1BiHO9NI+sxpt8ocRQRcR/eJvKs
|
||||
Jd0TryU7HLFN/fk9V57q3GQ6gxD4ky+gUOKRylFitr2xlPfuRw==
|
||||
-----END CERTIFICATE-----
|
||||
28
test/configs/certs/server-key-iponly.pem
Normal file
28
test/configs/certs/server-key-iponly.pem
Normal file
@@ -0,0 +1,28 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC9mNwUSZJDGnM2
|
||||
dW3BM3Oz5/aK4gP3JJPrNtqPZMZWGbeS0vHf009+eM7b3G7UXFikp3lrSf8wN9lx
|
||||
kiHXkXKNGiF1D4Aj8C8Oahpim+sedN/fYYoFqDG31JfuxmAbb7GFm6w9zaGeqLVW
|
||||
hM6fjGSlV0F1gcYAyNg974WceARJWpQprycKvlZga6BSBlP1z85HnM9Qih2SOiHR
|
||||
JO2B6IWXjEFGltoC17f1q5JMqwriGZ+4IQdc99F+bklwqcRFw7IQq8pQ48nqb7UZ
|
||||
ZBIyDpNZ+I78orwz8yXkWZhtDpd2ttqeUM9NoWtizkeEHfeCitrQkOemH0MlYVfD
|
||||
FX7guFwXAgMBAAECggEAE6qdeYVAJLHDrax0nAvIPqsbCcD0BFjI9ycTeLhNUnUM
|
||||
c7Bp4nu6zTWez3OIE4MYtsugbp6YV9oTNhKgbAnsRfKl8cyP0CqD1wzue7gMpXYe
|
||||
Gr+1X2zY62aj8+Kj6XSmh2NkdGy2DQ0W8kiIXkhj0DrC0XuKnF45AAOualKQr0MG
|
||||
JRFXi/AEEDkyWwfmqteD60HBzdweBqzYvsIyA8cQAgI4LguRKHKmLexqNDL0h0K+
|
||||
nPbQl5pg7es3kOaQ7DMICqd+E11btSXBJop95MLVhPXkzAyktIdfc1M7LsBNb7Dw
|
||||
ja5G+wmmGG0KxCbqMVKCACxs63lWakIxFlrsxi+Q4QKBgQDwrM4f/j289+PBKlED
|
||||
UCXHsGBgE1vNZMAinfAazWAImTAwWoY0FDrMBBPJGx+Azke5teI82o+Sq4jTL44Y
|
||||
qvmqblHb9XEQLnRxSdl5WP794o1K9pP7nEvIpL+RngRIC1qt9BEGd5Pmn8FcF4BT
|
||||
Zo9sdP8Hh6EJLGb33iYxUrTNTwKBgQDJq3GclCnVukbaGbCU2w54EDTJoghIY+W4
|
||||
kXeGL1VbSXD/NnyuhH/mua+UwBM7XSFJXKV2vfIhI1Qe9VW+7p4vyiLFp3atSb86
|
||||
AirajUPrCJNX1X/sm7fIss9U1ko/JruXSh1DxzEZvBQa52SwYH5bM6LbE6NJRuhS
|
||||
xMY2ipyiuQKBgQCm0gCl6GH+w4wYbi5tL3agbT7AGWr+eSE8XWD6EvTHwPbH7Vcs
|
||||
bgE7PHBCawxxCYppzQqdx5jQvxk92K6Tpp8bZRBUeFIAN1L624dkNy236PqqxTNZ
|
||||
qcJVtuwaEP9CuKwH+y553xSjPISYQqnuJR6wvH+xRm92nlJY6KBse7lavQKBgCEV
|
||||
NeMIz0AXec4HjtcshFgf2HkHUrKFaMb5XhEuLKN4DchgKN38MHsqFOqjA8SmR3Kg
|
||||
dyheipzzDbayammS/XI7h67DBQ3yXiNm/Z6ys+SXmIw9IuoutVyAMNDrAm0PrpBo
|
||||
ARsAT0a4etfbA8KHYdMWSm4D77JypmQFkbqazI1JAoGBAKZTn6KQaBcZ5JrSya17
|
||||
sClZPlSsYhIW8EbxqDgNwDippcNrLuJCsWiwMNW+glQoDIcGAo557PwAXrridH89
|
||||
5mjFCVggHeso3T6/nsBB86Q8B1hq5E8AszhEKH6IeKd5tFNZkK83eWjAlbIUrEBH
|
||||
xXZFMGnYPPS7korkEzzuGJ+7
|
||||
-----END PRIVATE KEY-----
|
||||
@@ -15,8 +15,10 @@ package test
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"math/rand"
|
||||
"net"
|
||||
"net/url"
|
||||
@@ -3016,3 +3018,81 @@ func TestLeafNodeDaisyChain(t *testing.T) {
|
||||
t.Fatalf("Expected a response")
|
||||
}
|
||||
}
|
||||
|
||||
// This will test failover to a server with a cert with only an IP after successfully connecting
|
||||
// to a server with a cert with both.
|
||||
func TestClusterTLSMixedIPAndDNS(t *testing.T) {
|
||||
confA := createConfFile(t, []byte(`
|
||||
listen: 127.0.0.1:-1
|
||||
leafnodes {
|
||||
listen: "127.0.0.1:-1"
|
||||
tls {
|
||||
cert_file: "./configs/certs/server-iponly.pem"
|
||||
key_file: "./configs/certs/server-key-iponly.pem"
|
||||
ca_file: "./configs/certs/ca.pem"
|
||||
timeout: 2
|
||||
}
|
||||
}
|
||||
cluster {
|
||||
listen: "127.0.0.1:-1"
|
||||
}
|
||||
`))
|
||||
srvA, optsA := RunServerWithConfig(confA)
|
||||
defer srvA.Shutdown()
|
||||
|
||||
bConfigTemplate := `
|
||||
listen: 127.0.0.1:-1
|
||||
leafnodes {
|
||||
listen: "localhost:-1"
|
||||
tls {
|
||||
cert_file: "./configs/certs/server-cert.pem"
|
||||
key_file: "./configs/certs/server-key.pem"
|
||||
ca_file: "./configs/certs/ca.pem"
|
||||
timeout: 2
|
||||
}
|
||||
}
|
||||
cluster {
|
||||
listen: "127.0.0.1:-1"
|
||||
routes [
|
||||
"nats://%s:%d"
|
||||
]
|
||||
}
|
||||
`
|
||||
confB := createConfFile(t, []byte(fmt.Sprintf(bConfigTemplate,
|
||||
optsA.Cluster.Host, optsA.Cluster.Port)))
|
||||
srvB, optsB := RunServerWithConfig(confB)
|
||||
defer srvB.Shutdown()
|
||||
|
||||
checkClusterFormed(t, srvA, srvB)
|
||||
|
||||
// Solicit a leafnode server here. Don't use the helper since we need verification etc.
|
||||
o := DefaultTestOptions
|
||||
o.Port = -1
|
||||
rurl, _ := url.Parse(fmt.Sprintf("nats-leaf://%s:%d", optsB.LeafNode.Host, optsB.LeafNode.Port))
|
||||
o.LeafNode.ReconnectInterval = 10 * time.Millisecond
|
||||
remote := &server.RemoteLeafOpts{URLs: []*url.URL{rurl}}
|
||||
remote.TLSConfig = &tls.Config{MinVersion: tls.VersionTLS12}
|
||||
pool := x509.NewCertPool()
|
||||
rootPEM, err := ioutil.ReadFile("./configs/certs/ca.pem")
|
||||
if err != nil || rootPEM == nil {
|
||||
t.Fatalf("Error loading or parsing rootCA file: %v", err)
|
||||
}
|
||||
ok := pool.AppendCertsFromPEM(rootPEM)
|
||||
if !ok {
|
||||
t.Fatalf("Failed to parse root certificate from %q", "./configs/certs/ca.pem")
|
||||
}
|
||||
remote.TLSConfig.RootCAs = pool
|
||||
host, _, _ := net.SplitHostPort(optsB.LeafNode.Host)
|
||||
remote.TLSConfig.ServerName = host
|
||||
o.LeafNode.Remotes = []*server.RemoteLeafOpts{remote}
|
||||
sl, _ := RunServer(&o), &o
|
||||
defer sl.Shutdown()
|
||||
|
||||
checkLeafNodeConnected(t, srvB)
|
||||
|
||||
// Now kill off srvB and force client to connect to srvA.
|
||||
srvB.Shutdown()
|
||||
|
||||
// Make sure this works.
|
||||
checkLeafNodeConnected(t, srvA)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user