title: TLS handshake failed with error remote error: tls: bad certificate server=Orderer using Raft and Intermediate certs
body: <p>I see there are a lot of questions about this error, I have seen this solution <a href="https://stackoverflow.com/questions/59842863/hyperledger-fabrictls-handshake-failed-with-error-remote-error-tls-bad-certif">Raft bad format</a> but I doubled checked and the folders are right and the certs are in there, I also looked at <a href="https://stackoverflow.com/questions/55803125/tls-handshake-failed-with-error-remote-error-tls-bad-certificate-server-ordere">Sans problem</a> but for what I understand I don't need Sans when using Raft (I may be wrong). I think my problem its because I'm not handling the intermediate certificates correctly and I'm getting the error both creating a channel and in the Raft consensus.</p>
  <p>So here is what I've done so far:</p>
  <p>I created my genesis block using a configtx.yaml and this msp folder structure:</p>
  <p>configtx.yaml</p>
  <pre><code>    Organizations:
      - &amp;ordererOrg
          Name: orderer
          ID: orderer
          MSPDir: /crypto/msp
          Policies:
              Readers:
                  Type: Signature
                  Rule: &quot;OR('orderer.member')&quot;
              Writers:
                  Type: Signature
                  Rule: &quot;OR('orderer.member')&quot;
              Admins:
                  Type: Signature
                  Rule: &quot;OR('orderer.admin')&quot; 
      Capabilities:
          Channel: &amp;ChannelCapabilities
              V1_4_3: true
          Orderer: &amp;OrdererCapabilities
              V1_4_2: true
          Application: &amp;ApplicationCapabilities
              V1_4_2: true
      Application: &amp;ApplicationDefaults
          Organizations:
          Policies:
              Readers:
                  Type: ImplicitMeta
                  Rule: &quot;ANY Readers&quot;
              Writers:
                  Type: ImplicitMeta
                  Rule: &quot;ANY Writers&quot;
              Admins:
                  Type: ImplicitMeta
                  Rule: &quot;MAJORITY Admins&quot;
          Capabilities:
              &lt;&lt;: *ApplicationCapabilities
      Orderer: &amp;OrdererDefaults
          OrdererType: solo
          BatchTimeout: 2s
          BatchSize:
              MaxMessageCount: 10
              AbsoluteMaxBytes: 99 MB
              PreferredMaxBytes: 512 KB
          Kafka:
              Brokers:
                  - 127.0.0.1:9092
          Organizations:
          Policies:
              Readers:
                  Type: ImplicitMeta
                  Rule: &quot;ANY Readers&quot;
              Writers:
                  Type: ImplicitMeta
                  Rule: &quot;ANY Writers&quot;
              Admins:
                  Type: ImplicitMeta
                  Rule: &quot;MAJORITY Admins&quot;
              BlockValidation:
                  Type: ImplicitMeta
                  Rule: &quot;ANY Writers&quot;
      Channel: &amp;ChannelDefaults
          Policies:
              Readers:
                  Type: ImplicitMeta
                  Rule: &quot;ANY Readers&quot;
              Writers:
                  Type: ImplicitMeta
                  Rule: &quot;ANY Writers&quot;
              Admins:
                  Type: ImplicitMeta
                  Rule: &quot;MAJORITY Admins&quot;
          Capabilities:
              &lt;&lt;: *ChannelCapabilities
      Profiles:
      SampleEtcdRaftProfile:
          &lt;&lt;: *ChannelDefaults
          Capabilities:
              &lt;&lt;: *ChannelCapabilities
          Orderer:
              &lt;&lt;: *OrdererDefaults
              OrdererType: etcdraft
              Addresses:
                  - orderer1.xxxx.eastus.aksapp.io:443
                  - orderer2.xxxx.eastus.aksapp.io:443
              Organizations:
              - *ordererOrg
              EtcdRaft:
                  Consenters:
                      - Host: orderer1
                      Port: 7050
                      ClientTLSCert: /crypto/orderers/orderer1/tls/server.crt
                      ServerTLSCert: /crypto/orderers/orderer1/tls/server.crt
                      - Host: orderer2
                      Port: 7050
                      ClientTLSCert: /crypto/orderers/orderer2/tls/server.crt
                      ServerTLSCert: /crypto/orderers/orderer2/tls/server.crt
              Capabilities:
                  &lt;&lt;: *OrdererCapabilities
          Application:
              &lt;&lt;: *ApplicationDefaults
              Organizations:
                  - &lt;&lt;: *ordererOrg
          Consortiums:
          SampleConsortium:
              Organizations:
                  - *ordererOrg
  </code></pre>
  <p>MSP folder structure:</p>
  <pre><code>+ /crypto
    configtx.yaml
    + msp
      + cacerts &gt; ca.crt
      + tlscacerts &gt; ca.crt
      + intermediatecerts &gt; intermediate.crt
      + tlsintermediatecerts &gt; intermediate.crt
      + admincerts &gt; admin.crt
    + orderers
      + orderer1/tls &gt; server.crt
      + orderer2/tls &gt; server.crt
  </code></pre>
  <p>I created my genesis block using this:</p>
  <pre><code>configtxgen -profile SampleEtcdRaftProfile -outputBlock genesis.block -channelID mychannel
  </code></pre>
  <p>Now here I have a doubt inside my orderer the msp structure is like this:</p>
  <pre><code>+ /var/hyperledger/orderer
    genesis.block
    + msp
      + cacerts &gt; ca.crt
      + intermediatecerts &gt; intermediate.crt
      + admincerts &gt; admin.crt
      + signcerts &gt; cert.pem
      + keystore &gt; key.pem
    + tls
      server.crt
      server.key
      ca.crt
      intermediate.crt
  </code></pre>
  <p>And these are my env variables:</p>
  <pre><code>ORDERER_GENERAL_TLS_ENABLED=true
  ORDERER_GENERAL_TLS_PRIVATEKEY=/var/hyperledger/orderer/tls/server.key
  ORDERER_GENERAL_TLS_CERTIFICATE=/var/hyperledger/orderer/tls/server.crt
  ORDERER_GENERAL_TLS_CLIENTROOTCAS=/var/hyperledger/orderer/tls/ca.crt
  ORDERER_GENERAL_TLS_CLIENTAUTHREQUIRED=false
  ORDERER_GENERAL_CLUSTER_CLIENTPRIVATEKEY=/var/hyperledger/orderer/tls/server.key
  ORDERER_GENERAL_CLUSTER_CLIENTCERTIFICATE=/var/hyperledger/orderer/tls/server.crt
  ORDERER_GENERAL_CLUSTER_ROOTCAS=/var/hyperledger/orderer/tls/ca.crt
  </code></pre>
  <p>I'm not sure why the structure is different and the tls files are somewhere else but I am copying the configuration from the <a href="https://github.com/Azure/Hyperledger-Fabric-on-Azure-Kubernetes-Service" rel="nofollow noreferrer">azure hyperledger template</a> That I have already used successfuly.</p>
  <p>Now my orderers are running but orderer1 keeps starting a new election and orderer 2 becomes precandidate and finally fails with a TLS handshake error.</p>
  <p>These are the error logs in orderer2:</p>
  <pre><code>2021-03-23 22:15:21.969 UTC [orderer.consensus.etcdraft] Step -&gt; INFO f96 2 is starting a new election at term 1 channel=canalenergia node=2
  2021-03-23 22:15:21.969 UTC [orderer.consensus.etcdraft] becomePreCandidate -&gt; INFO f97 2 became pre-candidate at term 1 channel=canalenergia node=2
  2021-03-23 22:15:21.969 UTC [orderer.consensus.etcdraft] poll -&gt; INFO f98 2 received MsgPreVoteResp from 2 at term 1 channel=canalenergia node=2
  2021-03-23 22:15:21.969 UTC [orderer.consensus.etcdraft] campaign -&gt; INFO f99 2 [logterm: 1, index: 2] sent MsgPreVote request to 1 at term 1 channel=canalenergia node=2
  2021-03-23 22:15:26.673 UTC [core.comm] ServerHandshake -&gt; ERRO f9a TLS handshake failed with error remote error: tls: bad certificate server=Orderer remoteaddress=x.x.x.x:45472 
  </code></pre>
  <p>I tried deleting intermediate.crt and mixing ca.crt and intermediate.crt into one file in ca.crt in the tls folder of the orderer like this:</p>
  <pre><code>-----BEGIN CERTIFICATE-----
  ROOTCERTxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
  xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
  -----END CERTIFICATE-----
  -----BEGIN CERTIFICATE-----
  INTERMEDIATExxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
  xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
  -----END CERTIFICATE-----
  </code></pre>
  <p>But it didn't work either.</p>
  <p>I tried openssl verify -CAfile chain.crt orderer1-tls.crt and returns OK.</p>
  <p>This is what happens when I try to create a new channel:</p>
  <pre><code>peer channel create -o orderer1.xxxx.eastus.aksapp.io -c testchannel -f ./channel.tx --tls --cafile /var/hyperledger/peer/msp/tlscacerts/ca.crt --clientauth --certfile /var/hyperledger/peer/tls/cert.pem --keyfile /var/hyperledger/peer/tls/key.pem
  2021-03-24 00:04:40.331 UTC [comm.tls] ClientHandshake -&gt; ERRO 001 Client TLS handshake failed after 939.077µs with error: EOF remoteaddress=x.x.x.x:443
  </code></pre>
  <p>I tested my urls with telnet and they are ok.</p>
  <p>I created my certificates using openSSL but I don't see anything wrong in them, the only difference is that they aren't signed by a fabric-ca but by an intermediate CA from a big company.</p>
  <p>I have double checked all the values but I guess orderer wouldn't even be running if they weren't right and followed this <a href="https://github.com/Azure/Hyperledger-Fabric-on-Azure-Kubernetes-Service/blob/72d5de82996bff8c9a8f09df8bc23cf84d1c1ec0/fabricTools/scripts/buildNetwork.sh#L100" rel="nofollow noreferrer">script</a> from azure for the creation of the genesis block only adding the intermediate info.</p>
  <p>Any advice would be great.</p>
  <p>Thanks</p>
  <p><strong>UPDATE:</strong></p>
  <p>I activated the debug logs with this variable:</p>
  <pre><code>FABRIC_LOGGING_SPEC=&quot;grpc=debug:info&quot;
  </code></pre>
  <p>And found the problem is this:</p>
  <p>transport: authentication handshake failed: x509: certificate is not valid for any names, but wanted to match orderer1</p>
  <p>My certificate has this subject:</p>
  <p>CN=orderer1-tls@blockchain.company.com,O=Company,L=CITY,ST=STATE,C=US</p>
  <p>Now, I don't understand why its telling me it doesn't have a name, I though the CN orderer1-tls@blockchain.company.com was the name, and, also, where did I tell the orderer that the name to search is &quot;orderer1&quot;?</p>
  <p><strong>UPDATE 2:</strong></p>
  <p>I changed my TLS certificates to CN=orderer.company.com and then the error was this:</p>
  <pre><code>x509: certificate is valid for orderer1.company.com, not orderer1
  </code></pre>
  <p>So as 李可以 says, the orderer is expecting the hostname in the certificate CN and my hostname is orderer1 so I changed it to that.</p>
  <p>Now I'm getting a new error:</p>
  <pre><code>UTC [comm.grpc.server] 1 -&gt; INFO 118 streaming call completed grpc.service=orderer.Cluster grpc.method=Step grpc.peer_address=x.x.x.x:39424 error=&quot;no TLS certificate sent&quot; grpc.code=Unknown grpc.call_duration=161.713µs
  </code></pre>
  <p>I guess This is a new error so I'm going to open a new question. thanks!</p>