Debugging TLS handshake failure - hyperledger-fabric

I'm trying to access my peer through the fabric-network nodejs sdk.
However, I encounter an error during the gateway.connect in the sdk and the logs I find in the peer container is not helpful.
All I have, even with the grpc=debug logging mode is :
peer0.catie-test | 2020-09-21 13:27:07.731 UTC [core.comm] ServerHandshake -> ERRO 087 TLS handshake failed with error remote error: tls: handshake failure server=PeerServer remoteaddress=172.17.0.1:49918
peer0.catie-test | 2020-09-21 13:27:07.731 UTC [grpc] handleRawConn -> DEBU 088 grpc: Server.Serve failed to complete security handshake from "172.17.0.1:49918": remote error: tls: handshake failure
Any way to have more helpful logs ? I would like to know, for example, which key are used for the TLS handshake check.
Edit with more infos: Configuration files and TLS verification
My peer is configured with TLS with the env variables :
CORE_PEER_TLS_ENABLED=true
CORE_PEER_TLS_KEY_FILE=/etc/hyperledger/crypto/peer/tls-msp/keystore/key.pem
CORE_PEER_TLS_CERT_FILE=/etc/hyperledger/crypto/peer/tls-msp/signcerts/cert.pem
CORE_PEER_TLS_ROOTCERT_FILE=/etc/hyperledger/crypto/peer/tls-msp/tlscacerts/tlsca.catie-test-cert.pem
I have the correct tlscacert of my peer on the client side, because the output from the peer and from client side are the same:
cat /etc/hyperledger/crypto/peer/tls-msp/tlscacerts/tlsca.catie-test-cert.pem # From the peer, output ZTd/o8LLw== at the end
cat /tmp/fabric-start-catie-test/building/artifacts/peer0.catie-test-crypto/tls-msp/tlscacerts/tlsca.catie-test-cert.pem # From the client, output ZTd/o8LLw== at the end
Path to the peer tlscacert is filled in the client side connection-profile.json :
"peers": {
"peer0.catie-test": {
"tlsCACerts": {
"path": "/tmp/fabric-start-catie-test/building/artifacts/peer0.catie-test-crypto/tls-msp/tlscacerts/tlsca.catie-test-cert.pem"
},
"grpcOptions":{
"ssl-target-name-override": "172.17.0.7",
"grpc.keepalive_time_ms": 10000
},
"url": "grpcs://172.17.0.4:7051",
"eventUrl": "grpcs://172.17.0.4:7053"
}
}
And I also checked that the tlsCAcert is the one that generated my peer cert :
openssl verify -CAfile $CORE_PEER_TLS_ROOTCERT_FILE $CORE_PEER_TLS_CERT_FILE # Output : /etc/hyperledger/crypto/peer/tls-msp/signcerts/cert.pem: OK
Edit 2 : Grpc option, peer name instead of IP and client logs
Also tried adding the grpcOptions to the peer section of the connection-profile.json (see the updated paragraph above) but it didn't change anything.
Also tried to add peer name to my /etc/hosts to reach my peer via its name instead of its IP. It makes a warning disappear but don't solve my problem and I prefer to work with IPs in my scripts.
Here are the logs of the nodejs sdk client in case it helps to diagnose the problem, but it only says that the Endorser must be connected and I think it is, because it reaches my peer as I have this TLS error in my peer's logs.
(node:59350) [DEP0123] DeprecationWarning: Setting the TLS ServerName to an IP address is not permitted by RFC 6066. This will be ignored in a future version.
2020-09-23T06:42:20.704Z - error: [ServiceEndpoint]: Error: Failed to connect before the deadline on Endorser- name: peer0.catie-test, url:grpcs://172.17.0.7:7051, connected:false, connectAttempted:true
2020-09-23T06:42:20.705Z - error: [ServiceEndpoint]: waitForReady - Failed to connect to remote gRPC server peer0.catie-test url:grpcs://172.17.0.7:7051 timeout:3000
2020-09-23T06:42:20.708Z - error: [NetworkConfig]: buildPeer - Unable to connect to the endorser peer0.catie-test due to Error: Failed to connect before the deadline on Endorser- name: peer0.catie-test, url:grpcs://172.17.0.7:7051, connected:false, connectAttempted:true
at checkState (/home/rqueraud/CATIE/Myrmica/myrmica-start/node_modules/#grpc/grpc-js/build/src/client.js:69:26)
at Timeout._onTimeout (/home/rqueraud/CATIE/Myrmica/myrmica-start/node_modules/#grpc/grpc-js/build/src/channel.js:292:17)
at listOnTimeout (internal/timers.js:549:17)
at processTimers (internal/timers.js:492:7) {
connectFailed: true
}
(node:59350) UnhandledPromiseRejectionWarning: Error: Endorser must be connected
at Channel.addEndorser (/home/rqueraud/CATIE/Myrmica/myrmica-start/node_modules/fabric-common/lib/Channel.js:259:10)
at buildChannel (/home/rqueraud/CATIE/Myrmica/myrmica-start/node_modules/fabric-network/lib/impl/ccp/networkconfig.js:50:21)
at Object.loadFromConfig (/home/rqueraud/CATIE/Myrmica/myrmica-start/node_modules/fabric-network/lib/impl/ccp/networkconfig.js:34:19)
at processTicksAndRejections (internal/process/task_queues.js:97:5)
at async Gateway.connect (/home/rqueraud/CATIE/Myrmica/myrmica-start/node_modules/fabric-network/lib/gateway.js:279:13)
at async queryChaincode (/home/rqueraud/CATIE/Myrmica/myrmica-start/test/chaincode-sdk/index.js:41:5)
at async /home/rqueraud/CATIE/Myrmica/myrmica-start/test/chaincode-sdk/index.js:57:5
Edit 3 : Docker IPs ? Trying with EC2 instances.
As #Urko mentionned, my nodes are in fact docker container running docker-in-docker (dind) images. Inside these containers are some other containers running the hyperledger peers, cli, ... images.
I access them from the host which is also where I run the fabric sdk nodejs client. I cannot access them via their container name, I think it is only possible in a docker-compose configuration, isn't it ? I already tried (see Edit 2 above) to add their name to my /etc/hosts to reach them via a name instead of an IP but it didn't change anything.
However, as my network startup is scripted, I deployed it using docker-machine in AWS instead of the dind docker containers this time, so these are real instances reachable on the internet. But I still encounter the same errors, here is the log from the peer where you can see this is coming from a public IP :
2020-09-24 08:32:57.653 UTC [core.comm] ServerHandshake -> ERRO 0d7 TLS handshake failed with error remote error: tls: handshake failure server=PeerServer remoteaddress=31.36.26.4:35462

It seems that the connection with your Peer have been defined to be secured by the TLS protocol. So, you may configure you Peer configuration to know wich certificates are you using at the TLS.
As when you connect to any server using this protocol, the communication among the parties is encripted using the certificate of the server (in this case, the Peer will be the server). So, you need to configure your client to trust on the server by the Root CA that haven been used to issue the Peers TLS certificates.
The client is where you use the SDK, so, you should configure it to trust on the Peer TLS certificate. When you configure the connection to the Blockchain nodes (peers and orderers), you would define their direction, as well as their TLS certificate. This one is an example that you can find at the following link. There, you have to define the value of the tlsCACerts param:
orderers:
orderer.example.com:
url: grpcs://localhost:7050
grpcOptions:
ssl-target-name-override: orderer.example.com
grpc-max-send-message-length: 4194304
tlsCACerts:
path: test/fixtures/channel/crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/tlscacerts/example.com-cert.pem
peers:
peer0.org1.example.com:
url: grpcs://localhost:7051
grpcOptions:
ssl-target-name-override: peer0.org1.example.com
grpc.keepalive_time_ms: 600000
tlsCACerts:
path: test/fixtures/channel/crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tlscacerts/org1.example.com-cert.pem
----- Edited ----
Also, you have to check the value of the ssl-target-name-override param. It should be the same to you nodes name, as you can see in the example file
----- Edited ----
Why are you using those IPs?! I understand that those IPs are internal from the Docker network, so you should not use them. Could you try using your containers names instead of the docker networks IPs?
----- Edited ----
Could you verify your ca-server configuration file and check that the tls is set to true?

You try a gRPC call in peer Server where peer server is secured with it's TLS system. So if you fail to provide the valid TLS certificate, server tls handshake will be failed and you will not get success to establish the connection.
Please check that your network config file is properly develop, also check that you are using the same TLS certificate that is used to run the peer server and your TLS certificate path is correct.

Related

not able to invoke/query chaincode usin fabric Node SDK

I have created a sample HLF network with 3 organizations. I have taken an orderer and a peer from each organization ( total 3 orderers, 3 peers, 3 fabric-CA, 3 CouchDB instances).
I have successfully created the certificates, system channel, channel configuration, application channel and also successfully deployed the chaincode on each peer.
I am able to invoke/query any chaincode using peer binary in docker cli but not able to invoke/query the same chaincode through fabric Node SDK.
I have created the connection profile as per the template provided in the test network and also able to register any user for a specific organization. But whenever I am trying to query any chaincode function I am getting the below error:
[ServiceEndpoint]: Error: Failed to connect before the deadline on
Committer- name: orderer.example.com:7050, url:grpcs://localhost:7050,
connected:false, connectAttempted:true [ServiceEndpoint]: waitForReady
Failed to connect to remote gRPC server orderer.example.com:7050 url:grpcs://localhost:7050 timeout:3000
When I check the orderer logs I found this error:
ServerHandshake -> ERRO 087 Server TLS handshake failed in 2.085859ms
with error EOF server=Orderer remoteaddress=172.23.0.1:45678
**Why I am getting this error?
I am trying to just query so why it's connecting to the orderer?
If there is any TLS issue then why I am able to query it through peer binary?**
This link might help Hyperledger Fabric CA releasing wrong certificates (wrong issuer) to Node SDK when TLS enabled
If you are not running as a test network on your local machine, then you will need to specify the connection option of discovery.asLocalhost as false

Hyperledger Fabric, javascript fabcar chaincode error. Transport: error while dialing: dial tcp 127.0.0.1:7051: connect: connection refused

I am having the same problem with Hyperledger fabric 2.1.1, but I am able to run test network with default options, but when I try to run Fabcar javascript chaincode I get an error:
Error: error getting endorser client for channel: endorser client failed to connect to localhost:7051: failed to create new connection: connection error: desc = "transport: error while dialing: dial tcp 127.0.0.1:7051: connect: connection refused"
I have tried everything mentioned in thread Error deploying Fabric test-network fabcar chaincode, removed docker images, ran prune, removed organizations data and fired ./network.sh up createChannel -ca -c mychannel -s couchdb -i 2.1.1, but the error is still there. Also, my RAM is 16Gb, so the problem is not there. Any other suggestion, please ?
This situation is happened because you called a gRPC to 127.0.0.1:7051 server but your call failed to hit the server. This situation may happen for many reasons, but for most of the cases the situation is happened due to server down(server exit or down due to misconfiguration) or for wrong certificate or your call failed to hit the server due to misconfiguration.
Please check the following docker container and ensure that is running properly.

TLS handshake failed with error remote error: tls: bad certificate server=Orderer

I am trying to set up a hyperledger fabric on a VM manually. I have generated all the artifacts and configured the orderer.yaml and core.yaml. I have orderer running on port 127.0.0.1:7050. When I try to create channel using the peer cli channel create command I am getting a context deadline exceeded message on peer terminal.
./bin/peer channel create -o 127.0.0.1:7050 -c $CHANNEL_NAME -f ./channel-artifacts/channel.tx --tls --cafile /home/fabric-release/mynetwork/crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
Error: failed to create deliver client: orderer client failed to connect to 127.0.0.1:7050: failed to create new connection: context deadline exceeded
On the orderer terminal I am getting the following error:
2019-04-23 09:22:03.707 EDT [core.comm] ServerHandshake -> ERRO 01b TLS handshake failed with error remote error: tls: bad certificate server=Orderer remoteaddress=127.0.0.1:38618
2019-04-23 09:22:04.699 EDT [core.comm] ServerHandshake -> ERRO 01c TLS handshake failed with error remote error: tls: bad certificate server=Orderer remoteaddress=127.0.0.1:38620
2019-04-23 09:22:06.187 EDT [core.comm] ServerHandshake -> ERRO 01d TLS handshake failed with error remote error: tls: bad certificate server=Orderer remoteaddress=127.0.0.1:38622
I have gone through the configurations a few time, I am not sure if I am missing something. Following is my orderer.yaml
General:
LedgerType: file
ListenAddress: 127.0.0.1
ListenPort: 7050
TLS:
Enabled: true
PrivateKey: /home/fabric-release/mynetwork/crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/tls/server.key
Certificate: /home/fabric-release/mynetwork/crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/tls/server.crt
RootCAs:
- /home/fabric-release/mynetwork/crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/tls/ca.crt
ClientAuthRequired: true
Keepalive:
ServerMinInterval: 60s
ServerInterval: 7200s
ServerTimeout: 20s
GenesisMethod: file
GenesisProfile: OneOrgOrdererGenesis
GenesisFile: channel-artifacts/genesis.block
LocalMSPDIR: /home/fabric-release/mynetwork/crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/msp
LocalMSPID: OrdererMSP
Authentication:
TimeWindow: 15m
FileLedger:
Location: /var/hyperledger/production/orderer
Prefix: hyperledger-fabric-ordererledger
The issue is that the TLS server certificate used by the orderer does not have a SAN matching "127.0.0.1". You can add "localhost" and/or "127.0.0.1" to you TLS certificates by using a custom crypto-config.yaml when generating your artifacts with cryptogen:
# ---------------------------------------------------------------------------
# "OrdererOrgs" - Definition of organizations managing orderer nodes
# ---------------------------------------------------------------------------
OrdererOrgs:
# ---------------------------------------------------------------------------
# Orderer
# ---------------------------------------------------------------------------
- Name: Orderer
Domain: example.com
EnableNodeOUs: false
# ---------------------------------------------------------------------------
# "Specs" - See PeerOrgs below for complete description
# ---------------------------------------------------------------------------
Specs:
- Hostname: orderer
SANS:
- "localhost"
- "127.0.0.1"
# ---------------------------------------------------------------------------
# "PeerOrgs" - Definition of organizations managing peer nodes
# ---------------------------------------------------------------------------
PeerOrgs:
# ---------------------------------------------------------------------------
# Org1
# ---------------------------------------------------------------------------
- Name: org1
Domain: org1.example.com
EnableNodeOUs: true
Template:
Count: 2
SANS:
- "localhost"
- "127.0.0.1"
Users:
Count: 1
- Name: org2
Domain: org2.example.com
EnableNodeOUs: false
Template:
Count: 2
SANS:
- "localhost"
- "127.0.0.1"
Users:
Count: 1
I also faced the same problem and in my case, the issue was that I made some changes to the local directory files and apparently those changes were not successfully reflected while mounting those files back into the docker containers. What fixed the problem for me was
docker volume rm $(docker volume ls)
I restarted the network again and didn't see any more certificate errors. Worth a try.
when the problem of TLS handshake failed occurs between the orderer and orderer, it is most likely that there is an error in the configuration parameters when generating the TLS file.
if you are registered with TLS via fabric-ca, then you need to check whether the CSR properties in the TLS files of the two orderer are the same. You can use the following command "openssl x509 -in certificate.crt -text -noout".
The following you need to check whether the --cer.names, -m and other parameters of the orderer enroll are duplicate or incorrect.
In cases where the contents of the TLS file are consistent and the HostName specified, it is rare for the handshake to fail

Failed to connect to Hyperledger peer when TLS is enabled

When I try to connect to Hyperledgerpeer with TLS enabled I get the following error. If I disable TLS it works well.
{ Error: Failed to connect before the deadline URL:grpcs://localhost:7051
at checkState (/Users/pro/fabric-client/node_modules/grpc/src/client.js:720:16) connectFailed: true }
Did anyone come across this? I have set up TLS Cert and key on docker env variables.

Hyperledger Fabric: Do we need to pass TLS cert/key files while joining channel?

I have a multi-org network fabric network up and running from different hosts.
The docker containers for the peers have TLS enabled. The build configuration of the peer:
- CORE_PEER_TLS_ENABLED=true
- CORE_PEER_TLS_CERT_FILE=/etc/hyperledger/fabric/tls/server.crt
- CORE_PEER_TLS_KEY_FILE=/etc/hyperledger/fabric/tls/server.key
- CORE_PEER_TLS_ROOTCERT_FILE=/etc/hyperledger/fabric/tls/ca.crt
While creating and joining the channel I followed byfn docs and did not supply the TLS cert/file of the peer while joining the channel. All the peers were able to join the channel.
However, when I tried to fetch the newest block using peer channel fetch newest -o orderer.example.com:7050 -c examplechannel, I got the error:
Serve failed to complete security handshake from "ip:43402": tls: first record does not look like a TLS handshake
Further, I referred this doc on TLS and this doc
on passing TLS certs of the peer with the above fetch command:
peer channel fetch newest -o orderer.example.com:7050 -c examplechannel --tls --certfile $CORE_PEER_TLS_CERT_FILE --keyfile $CORE_PEER_TLS_KEY_FILE --cafile $CORE_PEER_TLS_ROOTCERT_FILE
This gave a new error:
grpc: Server.Serve failed to complete security handshake from "ip:43496": remote error: tls: bad certificate
Debugging TLS issues doc states that this happens when the server does not trust the client certificate. So in my case, I infer that the orderer is not trusting the certificate that the peer is passing.
So
Does it mean that I was supposed to pass TLS_CERT, TLS_KEY and TLS_ROOT cert while proposing a channel join from this peer?
If #1 is true, can I pass these certificates without bringing down the network and rejoining the channel with certs?
While creating the channel, it uses orderer's ca-cert. Also, when submitting anchor peer transaction, it uses orderer's ca cert? So am I supposed to use Orderer's ca cert for peer fetch command as well?
If #3 is true, then in a production environment, do we need to build up the peer containers such that it contains orderer's ca-cert?
There are multiple concepts baked into your questions. It's important to understand that there is a difference between using the peer to run a peer node--peer node start-- and using the peer as a CLI (e.g. peer channel fetch).
When the peer is running as a server, there's no need to pass in crypto material for the channels as the peer actually extracts the required TLS certificate information from the config block passed in the peer channel join ... command.
When the peer is running in CLI mode, you do need to provide the the TLS certificate information to connect to the various endpoints. When communicating with peers, this information is extracted from the peer config (either in core.yaml or from the corresponding CORE_ environment variables). When communicating with the orderer, there are specific command line flags for setting the TLS material.

Resources