Entre 08/02/2023 e 09/02/2023, a SEFAZ-SP fez algumas alterações de segurança nos webservices de NF-e do ambiente de Homologação. Infelizmente estas mudanças não foram publicadas pela SEFAZ-SP, e desde então nossos ambientes GRC NF-e não têm conseguido se conectar aos serviços para que possamos executar testes, impactando diversos projetos relacionados à NF-e aqui na empresa. Felizmente, o problema está restrito ao ambiente de Homologação, não tendo sido feita nenhuma modificação pela SEFAZ-SP no ambiente de Produção até este momento.
O objetivo deste blog é mostrar a análise do problema, identificação da causa raiz e solução implementada.
O Problema
Dependendo do nosso ambiente interno de GRC NF-e (DEV, Pre-QA ou QA), entre 08/02/2023 e 09/02/2023, a consulta de status de serviço na SEFAZ-SP de Homologação começou a retornar erro:
Inicialmente achei que era uma intermitência temporária, e como o SVC está configurado em todos os ambientes, as Notas Fiscais continuaram sendo processadas em ambiente de Homologação, com exceção do serviço de Inutilização que não existe no SVC.
Na semana seguinte, em conversa com outras empresas, recebi a confirmação que o problema que estávamos enfrentando também estava ocorrendo em outras empresas, porém confirmei também que outras empresas não estava sofrendo nenhuma indisponibilidade de serviço. Coincidentemente – e isto acabou desviando o foco da análise – as empresas que estavam enfrentando problemas possuem seus servidores GRC NF-e fora do país. Por causa disto, minha primeira suspeita é que a SEFAZ-SP passou a bloquear também em ambiente de Homologação as conexões provenientes de fora do país.
Para confirmar isto, solicitei ao time de Basis para fazer um traceroute a partir de um dos servidores afetados até o endereço homologacao.nfe.fazenda.sp.gov.br:
Para complicar as coisas, aparentemente o traceroute falhava ao tentar sair da rede interna. Então o que inicialmente parecia ser um problema externo de repente se tornou um problema de infraestrutura interna.
Acionei o time de redes e de firewall para analisar o motivo pelo qual o tráfego não saía da rede interna. Depois de vários dias de troubleshooting e análises, o veredito veio através da utilização da ferramenta TCP Gateway, disponível na Nota SAP 856597. Basicamente o teste que fiz em casa foi instalar o TCP Gateway em duas máquinas: a primeira o meu laptop de trabalho, conectado à rede da empresa via VPN e acessível pelo GRC NF-e, e a segunda uma máquina pessoal sem nenhuma restrição de firewall e acessando a SEFAZ-SP sem nenhum bloqueio. Apontei o Canal de Comunicação da consulta de status de serviço no GRC NF-e para o TCP Gateway da primeira máquina, e o TCP Gateway da primeira máquina para o TCP Gateway da segunda máquina que, por fim, estava apontando para o WebService da SEFAZ. Ao disparar a comunicação pelo GRC NF-e, pude ver que o tráfego estava normal, passando por ambos os TCP Gateways, e mesmo assim não havia uma comunicação efetiva com a SEFAZ-SP.
Uma vez descartado um possível bloqueio de firewall e também um possível bloqueio de IPs de fora do Brasil pela SEFAZ-SP em Homologação, e considerando que havia empresas em que a counicação estava ocorrendo sem problemas, ficou evidente que era agum problema específico do GRC NF-e, porém causado por algo que havia mudado na SEFAZ-SP, uma vez que não houve nenhuma modificação implementada nos ambientes GRC NF-e recentemente.
A Causa Raiz
Ativei o trace do Canal de Comunicação através da ferramenta XPI Inspector (vide Nota SAP 1514898). Ao rodar a interface de Consulta de Status de Serviço com o XPI Inspector ativado, o seguinte trecho do log chamou a minha atenção:
Begin IAIK Debug:
ssl_debug(7821): Starting handshake (iSaSiLk 5.104)...
ssl_debug(7821): Sending v3 client_hello message to homologacao.nfe.fazenda.sp.gov.br:443, requesting version 3.3...
ssl_debug(7821): Sending extensions: renegotiation_info (65281), signature_algorithms (13)
ssl_debug(7821): IOException while handshaking: Connection reset
ssl_debug(7821): Sending alert: Alert Fatal: handshake failure
ssl_debug(7821): Exception sending message: java.net.SocketException: errno: 32 (Broken pipe), error: Write failed (local port 29780 to address 10.38.175.201 (***********.jnj.com), remote host unknown)
ssl_debug(7821): Shutting down SSL layer...
ssl_debug(7821): Closing transport...
End IAIK Debug.
A análise de certificados, tanto interno quando da SEFAZ-SP, não retornou nenhum erro, porém ainda assim ocorria erro de handshake TLS. Um trecho importante do log é a frase “remote host unknown”, mostrando que durante o handshake não foi possível identificar o servidor de destino. Baseado nestas informações, algumas pesquisas na internet me apontaram para uma possível causa do problema, que posteriormente se confirmaram como sendo efetivamente a causa raiz: Cipher Suites.
Em resumo, todas vez que um serviço se conecta a um servidor utilizando um protocolo seguro, tal como o HTTPS utilizado pelos webservices das diversas SEFAZ, há uma troca de mensagens inicialmente entre o cliente – no caso, o GRC NF-e – e o servidor – no caso, a SEFAZ-SP. Essas mensagens iniciam com um handshake, através do qual cada parte envolvida na comunicação se “apresenta”. A grosso modo e para fins didáticos, eis o que deveria ocorrer:
Handshake (aperto de mãos) iniciado. Cliente: Olá, servidor. Sou o cliente e falo os seguintes idiomas de segurança: X, Y, Z. Servidor: Olá, cliente. Sou o servidor, e dos idiomas que você fala, o mais adequado para a nossa comunicação é o idioma Y. Vou abrir uma sessão neste idioma para conversarmos com privacidade. Servidor: Envio para você a chave pública de meu certificado digital, bem como toda a cadeia de certificação. Cliente verifica se o certificado é confiável. Cliente: Confio no seu certificado pois o mesmo foi emitido por uma Autoridade Certificadora de minha confiança. Cliente: Envio para você a chave pública de meu certificado digital, bem como toda a cadeia de certificação. Servidor verifica se o certificado é confiável. Servidor: Confio no seu certificado pois o mesmo foi emitido por uma Autoridade Certificadora de minha confiança. Handhsake finalizado. Servidor abre uma sessão no idioma Y, e cliente e servidor trocam mensagens nesta sessão até a mesma ser finalizada.
Basicamente, o que cito acima como “idioma de segurança” são os Cipher Suites, que são um conjunto de altoritmos criptográficos que auxiliam na segurança de uma conexão de rede. E, no log da comunicação do nosso GRC NF-e com a SEFAZ-SP, o servidor não conseguiu nem mesmo enviar a primeira mensagem pois o servidor não conseguiu selecionar entre os Cipher Suites listados pelo cliente algum suportado.
Com a provável causa raiz detectada, começou o trabalho para mapear a solução.
A Solução
O primeiro passo para mapear a solução era identificar quais os Cipher Suites suportados pela SEFAZ-SP em Homologação. Para tal, utilizei o excelente serviço do site SSLLabs.com. O trace mais recente para a SEFAZ-SP em Homologação está disponível neste link: SEFAZ-SP Homologação. Do resultado, o trecho mais importante é o abaixo:
Aqui estão listadas as Cipher Suites que a SEFAZ-SP Homologação suporta. Para fins de comparação, na imagem abaixo estão listadas as Cipher Suites suportadas pelo ambiente de Produção da SEFAZ-SP:
Notem que a lista de Produção é maior, inclusive suportando a Cipher Suite TLS_RSA_WITH_AES_128_CBC_SHA que, de acordo com a RFC 5246 deveria ser mandatória. Por curiosidade, pesquisei mais algumas SEFAZ e todas implementam a Cipher Suite TLS_RSA_WITH_AES_128_CBC_SHA, tanto em Homologação quanto em Produção.
Uma vez tendo a lista de Cipher Suites suportadas pela SEFAZ-SP Homologação, era apenas questão de identificar as mudanças necessárias no GRC NF-e para adicionar novas Cipher Suites. Infelizmente esta não é uma resposta direta, e precisei pesquisar diversas Notas SAP para poder mapear as informações necessárias. Aos interessados, seguem as principais Notas SAP estudadas:
- 2604240 – TLS handshake failure due to missing SNI extension
- 2616983 – How to customize cipher suites in SSLContext.properties file
- 2708581 – ECC Support for Outbound Connections in SAP NW AS Java
- 2538934 – Handshake is failing in AS Java when connecting to a server which only supports TLS_ECDHE ciphers
- 2569156 – How to create, modify and validate SSLContext.properties file
- 2284059 – Update of SSL library within NW Java server
- 2881916 – Unable to encrypt SSL message: java.security.InvalidKeyException: Illegal key size
Baseado nas informações presentes em algumas das Notas acima, os Cipher Suites suportados por padrão no PI ou PO são:
- TLS_RSA_WITH_AES_256_GCM_SHA384
- TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384
- TLS_RSA_WITH_AES_256_CBC_SHA256
- TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256
- TLS_RSA_WITH_AES_128_GCM_SHA256
- TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256
- TLS_RSA_WITH_AES_128_CBC_SHA256
- TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256
- TLS_RSA_WITH_AES_256_CBC_SHA
- TLS_RSA_WITH_CAMELLIA_256_CBC_SHA
- TLS_RSA_WITH_AES_128_CBC_SHA
- TLS_RSA_WITH_CAMELLIA_128_CBC_SHA
- SSL_RSA_WITH_3DES_EDE_CBC_SHA
- SSL_RSA_WITH_RC4_128_SHA
Nenhuma das Cipher Suites acima são aceitas pela SEFAZ-SP em Homologação. Seguindo as orientações das Notas SAP 2604240 e 2616983, preparei um novo arquivo SSLContext.properties com o seguinte conteúdo:
#########################################
# SSLContext properties
# supported since ISASILK 4.4
# Location of configuration file is iaik/security/ssl/SSLContext.properties within CLASSPATH
# It can be redefined with system property iaik.security.ssl.configFile
# e.g.java -Diaik.security.ssl.configFile=file:c:/java/SSLContext.properties
#
#########################################
# allowLegacyRenegotiation is set to true otherwise we cann't communicate with unpatched peers
allowLegacyRenegotiation=true
# unsecure renegotiation is disabled for SSL server but remains allowed for client SSL
server.disableRenegotiation=true
#deactivated to avoid regressions after ISASIK5.102
chainVerifier.checkExtensions=false
#avoid issues with IIS server
extension=signature_algorithms
extension=server_name.noncritical
#default cipher suits
cipherSuite=TLS_RSA_WITH_AES_256_GCM_SHA384
cipherSuite=TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384
cipherSuite=TLS_RSA_WITH_AES_256_CBC_SHA256
cipherSuite=TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256
cipherSuite=TLS_RSA_WITH_AES_128_GCM_SHA256
cipherSuite=TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256
cipherSuite=TLS_RSA_WITH_AES_128_CBC_SHA256
cipherSuite=TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256
cipherSuite=TLS_RSA_WITH_AES_256_CBC_SHA
cipherSuite=TLS_RSA_WITH_CAMELLIA_256_CBC_SHA
cipherSuite=TLS_RSA_WITH_AES_128_CBC_SHA
cipherSuite=TLS_RSA_WITH_CAMELLIA_128_CBC_SHA
cipherSuite=SSL_RSA_WITH_3DES_EDE_CBC_SHA
cipherSuite=SSL_RSA_WITH_RC4_128_SHA
#custom cipher suites
cipherSuite=TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
cipherSuite=TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
cipherSuite=TLS_DHE_RSA_WITH_AES_256_CBC_SHA
cipherSuite=TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
cipherSuite=TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
cipherSuite=TLS_DHE_RSA_WITH_AES_128_CBC_SHA
Infelizmente nosso NetWeaver ainda está na versão 7.4, e as Cipher Suites que utilizam curva elípticas são suportadas apenas para SAP NetWeaver 7.5 a partir do Support Package 8 (vide Nota SAP 2708581), então não pude adicionar as Cipher Suites mais modernas abaixo:
- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
- TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
- TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256
- TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256
Seguindo os passos da Nota SAP 2569156, Basis salvou o arquivo novo SSLContext.properties no diretório /usr/sap/<system name>/SYS/global/security/lib/tools/, incluíram o parâmetro de memória virtual -Diaik.security.ssl.configFile apontando para o arquivo novo, e reiniciaram o servidor. Após o reinício, a comunicação com a SEFAZ-SP foi estabelecida corretamente, resolvendo em definitivo o problema:
Conclusão
Infelizmente do início do problema até a solução foram várias semanas tentando descobrir a causa do problema. Caso a SEFAZ-SP houvesse publicado em seu portal uma nota informando a mudança de Cipher Suites, a solução teria sido muito mais rápida.
Espero que esse post auxilie outras empresas que estão passando pelo mesmo problema.