Avançar para a área de conteúdo

ir para o conteúdo principal

developerWorks Brasil  >  WebSphere | Lotus  >

SSL sem problemas: usando TLS/SSL com micro broker v3 no IBM Lotus Expeditor

developerWorks
Opções de documento

Opções de documento que necessitam de JavaScript não são exibidas

Discutir


Classificar esta página

Ajude-nos a melhorar este conteúdo


Nível: Intermediário

Steve Russell, Software test, Pervasive and Advanced Messaging Technologies, IBM

14/Abr/2009
Atualizado 29/Jun/2009

Um dos novos recursos de segurança do micro broker v3, incluso no IBM® Lotus® Expeditor 6.2, é a capacidade de criptografar dados de rede transmitidos do e para o broker utilizando os protocolos TLS/SSL (Segurança de Camada de Transporte/Camada de Conexões Seguras) padrão da indústria. Este artigo descreve diversas maneiras de proteger a comunicação de seu micro broker utilizando esse novo recurso.

Nota do editor: Conhece bem este tópico? Deseja compartilhar seus conhecimentos? Participe do programa de wiki de softwares IBM Lotus.

Lotus Expeditor wikiWebSphere Portal wiki

Apresentação



Voltar para parte superior


Utilização do TLS/SSL com micro broker

Este artigo não tem como objetivo ser um tutorial a respeito de TLS/SSL e todos os seus recursos. Seria necessário um livro enorme para fornecer uma descrição completa das maneiras nas quais eles podem e devem ser utilizados de forma a garantir a segurança da comunicação e minimizar a possibilidade de interceptação e comprometimento de seus dados, sendo que várias dessas descrições já foram escritas. O prazer de desenvolver o nível necessário de conhecimento é, portanto, deixado como um exercício para o leitor.

Em vez disso, este artigo descreve diversas maneiras de proteger a comunicação de seu micro broker utilizando um novo recurso de segurança. Após uma breve apresentação dos tipos de conexão SSL, ele fornece exemplos de códigos específicos que podem lhe ajudar a realizar operações de modo fácil e seguro.

Transport Layer Security e seu protocolo antecessor, o Secure Sockets Layer, costumam ser chamados de SSL. Mesmo que tal utilização do termo SSL não seja estritamente correta, ela é a convenção aceita por este artigo daqui em diante. À medida que você for ficando mais familiarizado com o micro broker security API, será possível ver que um programador é capaz de determinar o protocolo utilizado para cada link específico.



Voltar para parte superior


Tipos de conexão SSL

Conexões SSL típicas se dividem em três categorias:

  • Comunicação criptografada, sem autenticação
  • Comunicação criptografada, autenticação de servidor
  • Comunicação criptografada, autenticação mútua

O primeiro tipo de conexão não costuma ser utilizado, já que a autenticação é um dos recursos importantes de SSL, fornecendo um mecanismo para que uma entidade prove que é quem ela afirma ser. O segundo tipo de conexão, autenticação de servidor, é obtido por meio da apresentação, pelo servidor ao cliente, de um certificado que declare a identidade da organização proprietária. Um certificado válido inclui uma cadeia de confiança desde a organização proprietária até uma autoridade de certificação (CA), que deve ser um terceiro bem conhecido e confiável. Incluso no certificado está a chave pública do servidor, que é utilizada para iniciar o fluxo de dados criptografados.

Você pode já conhecer os certificados devido à sua utilização da Internet. De vez em quando, ao visitar uma nova página, uma janela é exibida lhe perguntando se você confia no certificado fornecido pelo site. Os navegadores costumam ser configurados para reconhecer um número de CAs de renome, mas caso o site não possua um certificado reconhecido e válido (o certificado pode ter vencido, ser de um CA desconhecido, ser autocertificado, etc.), uma mensagem será apresentada aos usuários. Caso isso ocorra, cabe ao usuário olhar o certificado e decidir se deve confiar no mesmo e no servidor que o está fornecendo.

A autenticação de servidor é a conexão SSL mais comumente utilizada. Essa autenticação fornece ao cliente uma maneira de garantir que ele está se comunicando com o servidor correto, em vez de um falso tentando interceptar comunicações. Em alguns casos, o servidor também pode precisar da garantia de que o cliente é quem alega ser, o que significa que uma conexão de autenticação mútua é requerida; tal categoria é a terceira listada anteriormente. A escolha de qual tipo de conexão SSL deve ser utilizado é uma questão de design de sistema para o implementador. Maneiras simples de configurar esses dois tipos de conexão, autenticação de servidor e autenticação mútua, serão descritas no restante deste artigo.



Voltar para parte superior


Autenticação de servidor

Como já discutido, um servidor que suporta conexões SSL deve possuir um certificado para ser apresentado ao usuário ou ao cliente. Um certificado contém a chave pública do proprietário, que é utilizada para iniciar a comunicação criptografada entre o cliente e o servidor. Assim que uma conexão é estabelecida, novas chaves aleatórias são usadas para a troca de dados no restante da sessão.

Chaves e certificados são mantidos em arquivos conhecidos como keystores e truststores. O servidor mantém sua chave privada e o certificado contendo sua chave pública (que é enviada ao cliente) em uma keystore. Quando o cliente recebe o certificado, o certificado é colocado na truststore do cliente caso o cliente escolha confiar no certificado.

Java™ fornece o utilitário keytool para gerenciar chaves, certificados, keystores e truststores. Para informações sobre as opções utilizadas nos comandos seguintes, consulte a documentação do keytool. Recomendamos que substitua seus próprios valores por nomes de arquivos e outros parâmetros à medida que tais substituições sejam necessárias.

Importante: É possível configurar o Lotus Expeditor para utilizar diferentes Java Virtual Machines (JVMs). A instalação padrão configura o Lotus Expeditor para usar o DesktopEE JVM. Keystores, truststores e o utilitário keytool para o ambiente do DesktopEE não são compatíveis com o ambiente da Java 2 Platform, Standard Edition (J2SE), com a recíproca sendo verdadeira. Utilize o utilitário keytool que corresponda à JVM utilizada no seu ambiente para manipular a sua keystore. Keystores e truststores não podem, portanto, ser transferidas de um ambiente a outro. Caso a compatibilidade com ambos os ambientes seja requerida, as truststores e a chave necessárias devem ser criadas separadamente para cada um deles.

Observe que os comandos do keytool devem ser digitados como uma única linha. As opções de keytool utilizadas aqui foram testadas e funcionam nos ambientes DesktopEE e J2SE. Essa seleção pode não ser aplicável a todas as opções disponíveis.

Recomendamos a revisão da documentação do keytool para compreender as opções utilizadas. As senhas e outros dados fornecidos por usuários utilizados devem, é claro, ser de sua própria escolha.

Criação de portas habilitadas a SSL

Siga as etapas a seguir para criar um link cliente-micro broker seguro utilizando autenticação de servidor, com o mínimo de configuração SSL.

Criar a keystore do micro broker

Presumindo que não exista nenhum certificado para o seu micro broker, crie o par de chaves privada/pública e o certificado do micro broker e os coloque em uma keystore. Uma única utilização do comando do keytool realiza tal tarefa:

keytool -genkey -alias examplecert -keystore mbrokerdtee.jks
-keypass default -storepass default -dname "CN=Micro broker, OU=PVC,
O=IBM, C=UK" -keyalg RSA

Ao concluir, o arquivo mbrokerdtee.jks será criado, contendo o par de chaves do broker e um certificado autoassinado correspondente.

Criar um ouvinte seguro

Um novo micro broker padrão é criado com um único TCPListener não criptografado na porta 1883. Há duas maneiras de criar um ouvinte seguro:

  • É possível adicionar um TCPListener a um broker em execução.
  • O broker pode ser criado com um TCPListener seguro padrão (e sem TCPListeners não criptografados).

Cobrimos ambas as opções.

Primeiro, adicionamos um novo TCPListener seguro a um micro broker existente, como exibido na listagem 1. Nesse exemplo, presume-se que o código esteja em execução na mesma JVM que o broker, obtendo assim uma referência de objeto LocalBroker. Na prática, o Ibroker poderia ser uma referência a um objeto RemoteBroker. De qualquer maneira, é necessário que o broker a que se faz referência esteja em execução antes que um ouvinte possa ser adicionado a ele.


Listagem 1. Adicionar um ouvinte seguro a um micro broker
private final String BROKER_NAME = "MBroker";
private final int SECURE_PORT = 8883;
private final String KEYSTORE_DTEE = "/mbrokerdtee.jks";
private final char[] KSPASSWD_DTEE ={'d','e','f','a','u','l','t'};

void _addSecurePort() throws Exception
{
    BrokerFactory factory = BrokerFactory.INSTANCE;
    LocalBroker lbroker = factory.getByName(BROKER_NAME);
    Communications bc = lbroker.getCommunications();
    // Especificar o número da porta nesta chamada de método. 8883 é a porta IANA
    // padrão para conexões MQTT segura.
    MQTTTCPListenerDefinition mqttld = 
                 bc.createMQTTTCPListenerDefinition(SECURE_PORT);
    mqttld.setSecure(true);
    ServerSSLDefinition ssld = mqttld.createSSLDefinition();
    ssld.setKeyStore(KEYSTORE_DTEE);
    ssld.setKeyStorePassword(KSPASSWD_DTEE);
    mqttld.setSSLDefinition(ssld);
    bc.addTCPListener(mqttld);
}

Essa técnica cria um novo ouvinte criptografado na porta especificada e deixa a porta não criptografada do broker (o padrão é 1883) disponível, o que pode ser adequado caso você deseje fornece acesso seguro a partir, por exemplo, da Internet, e o acesso à porta não segura esteja disponível apenas a partir de locais controlados. Caso esteja interessado nesse tipo de configuração, consulte a seção, "Ligar um ouvinte a um endereço IP específico".

Criar um broker seguro padrão deixa de ser difícil após você ter uma referência a um objeto BrokerFactory ("factory" no exemplo). Em código de produção, tal referência é obtida através do OSGi Service Registry. Uma referência direta é obtida no exemplo exibido na listagem 2 para proporcionar melhor entendimento. Recomendamos a criação de um broker seguro padrão caso não deseje que as conexões com o seu micro broker sejam criptografadas.


Listagem 2. Criar um micro broker seguro padrão
void createSecureBroker() throws Exception 
{
    BrokerFactory factory = BrokerFactory.INSTANCE;
    BrokerDefinition def = factory.createBrokerDefinition(BROKER_NAME);
    // setPort() é opcional – 8883 é usado se este método não for chamado
//  def.setPort(Integer.parseInt(SECURE_PORT));
    def.setDefaultListenerSecure(true);
    ServerSSLDefinition ssld = def.createSSLDefinition();
    ssld.setKeyStore(KEYSTORE_DTEE);
    ssld.setKeyStorePassword(KSPASSWD_DTEE);
    def.setSSLDefinition(ssld);
    factory.create(def);
}

Quando o ouvinte seguro do broker foi iniciado corretamente, duas mensagens são publicadas no log do broker:

>Info [3810] FMBD1128 MBroker Keystore '/mbrokerdtee.jks' will be used for SSL
>Info [3810] FMBD1125 MBroker Listening on port 8883 using SSL

Caso haja algum problema (tal como não ser capaz de abrir uma keystore), um erro será publicado no log.

>Error [3810] FMBD3020 MBroker SSL-Initialization failed. Keystore file not found.

Criar uma conexão segura a partir de um cliente

Neste ponto, já temos um broker em execução recebendo solicitações de conexões SSL na porta 8883. Agora, é necessário que um cliente solicite uma conexão em tal porta.

Crie uma conexão segura a partir de um cliente

No exemplo exibido na listagem 3, um cliente MQTTv5 foi criado e conectado ao broker utilizando a porta segura em 8883. Ao fornecer à URL de um broker o prefixo ssl://, e não tcp://, você indica que o cliente deve solicitar uma conexão segura. O restante da URL (no exemplo) mostra que você está se conectando a um broker em execução no mesmo sistema que o cliente e seleciona a porta segura padrão, 8883.

Configurações SSL para o lado de cliente da conexão, especialmente a truststore na qual é possível armazenar os certificados, são fornecidas pelo Lotus Expeditor (ver a seção posterior, "Configurações de SSL").

Há pequenas diferenças na maneira em que as propriedades de SSL são passadas aos diferentes tipos de clientes micro broker (MQTTv5, JMS e MQTTv3). Para obter mais informações, consulte a seção, "Clientes JMS e MQTTv3".


Listagem 3. Conectar a um cliente seguro
private MqttClient myClient;
private static final String BROKER_URL = "ssl://localhost:8883";
private static final String CLIENT_ID = "AnonUser";

public void createClient() throws Exception
{
    // Definir as opções de conexão para o cliente MQTTv5
    // Nos conectaremos anonimamente, então não temos nome de usuário/senha
    MqttConnectOptions connOpts = new MqttConnectOptions();
    connOpts.setPurge(true);
    // Criar o objeto do cliente
    myClient = new MqttClient(BROKER_URL, CLIENT_ID);
    // Criamos o cliente. Para uso normal também definimos e configuramos
    // um manipulador de callback, mas estamos conectando, então, não se preocupe.
    myClient.connect(connOpts);
}

Quando a última declaração é executada, o cliente recebe uma janela indagando se é possível confiar no certificado do broker. No Microsoft® Windows®, tal janela é semelhante àquela exibida na figura 1.


Figura 1. Janela de Alerta de Segurança
Security Alert window

Como o certificado é autoassinado (ou seja, não é assinado por um CA), não é possível estabelecer sua confiabilidade. Portanto, o usuário recebe acesso ao certificado e é indagado se deve ou não confiar no mesmo. A opção padrão é confiar no certificado apenas para a sessão atual. Caso, em vez disso, você selecione a opção Não confiar neste certificado, ele será rejeitado e a conexão SSL não será estabelecida. Selecionar uma dessas opções significa que, quando o Lotus Expeditor for desligado e reiniciado, a janela será apresentada na próxima vez em que o cliente tentar se conectar ao micro broker.

A opção final, Confiar nesse certificado, afirma ao Lotus Expeditor que você acredita que o certificado é legítimo. Então, o certificado será armazenado no truststore da plataforma Lotus Expeditor do cliente, e o cliente permitirá futuras conexões ao micro broker sem a necessidade de fazer mais perguntas.

Verifique se a conexão se estabeleceu

Nesse ponto, caso tudo tenha ocorrido como deveria, o cliente será conectado e a mensagem a seguir será publicada no log do micro broker:

>Info [3810] FMBT1741 MBroker Client 'AnonUser'
connected on port 8883 from /127.0.0.1:0

Criar uma ligação em ponte segura

Algumas topologias de sistema requerem que um micro broker se conecte a outros micro brokers ou brokers de mensagens utilizando o aparato de ponte do micro broker. É possível proteger ligações em ponte com micro brokers ou o IBM WebSphere ® MQ utilizando SSL. A listagem 4 mostra o código utilizado para configurar uma ligação em ponte SSL.

Criar uma ligação em ponte

Neste exemplo, o broker remoto é o MBroker, criado como exibido acima, com uma porta segura padrão em 8883. Um segundo micro broker, o LocalBroker, é executado no mesmo sistema, e ouve uma porta diferente. O código cria uma ligação em ponte MQTTv5 do LocalBroker com a porta segura do MBroker. É possível utilizar a mesma técnica para ligações em ponte MQTTv3 e MQJMS. Veja o código na listagem 4.

A diferença significativa entre criar uma ligação em ponte e uma conexão cliente é que o nome de host do broker remoto (ou endereço IP) é transmitido à ligação em ponte, em vez de sua URL. Tal diferença significa que o prefixo ssl:// não estará disponível para indicar a necessidade de uma conexão segura. Em vez disso, a chamada do método setSecure(true) no objeto MQTTConnectionDefinition realiza tal tarefa.


Listagem 4. Criar uma ligação em ponte segura
private final String BROKER_NAME = "LocalBroker";
private final int REMOTE_SECURE_PORT = 8883;

public void _createSecurePipe(CommandInterpreter ci) throws Exception
{
    BrokerFactory factory = BrokerFactory.INSTANCE;
    LocalBroker lbroker = factory.getByName(BROKER_NAME);
    bridge = lbroker.getBridge();
    PipeDefinition pipeDef = bridge.createPipeDefinition("securePipe");
    MQTTConnectionDefinition secBridge = 
                bridge.createMQTTConnectionDefinition("secConn");
    // Exclua as barras de comentário desta chamada de método para uma conexão MQTTv3
//  secBridge.setProtocolVersion(3);
    secBridge.setHost("localhost");
    secBridge.setPort(REMOTE_SECURE_PORT);
    secBridge.setSecure(true);
    pipeDef.setConnection(secBridge);
    // A barra deve ter pelo menos um fluxo...
    FlowDefinition outflow = bridge.createFlowDefinition("secureflow");
    outflow.setSources(new DestinationDefinition[]{
                bridge.createTopicDefinition("SSLBridge/#")});
    outflow.setQos(2);
    pipeDef.addOutboundFlow(outflow);
    Pipe pipe = bridge.addPipe(pipeDef);
    pipe.start();
}

Certifique-se de que a ligação em ponte tenha se estabelecido

Quando a ligação em ponte se iniciar (na última linha de código da listagem 4), o LocalBroker recebe a janela para decisão sobre a confiança em um Certificado, assim como ocorre com um cliente normal. Após aceitar o certificado, o log do LocalBroker exibe a mensagem detalhada na listagem 5.


Listagem 5. A mensagem de log do LocalBroker
>Info [1240] FMBB2006 bridge Pipe securePipe initializing.
>Info [1240] FMBB2004 bridge Pipe securePipe starting. 
>Info [1240] FMBB2000 bridge Pipe securePipe started. 
>Info [1240] FMBB2628 bridge Pipe securePipe has established its outbound connection.

No broker remoto (MBroker), o log mostra que a conexão se estabeleceu:

>Info [3810] FMBT1741 MBroker Client 'securePipe'
connected on port 8883 from /127.0.0.1:0


Voltar para parte superior


Autenticação mútua

Criar uma conexão de autenticação mútua entre o broker e o cliente (ou ponte) é um processo um pouco mais complexo. Novamente, o broker apresenta seu certificado para validação a um cliente solicitando uma conexão, com o cliente podendo aceitar ou rejeitar, como nos métodos anteriores. Em uma conexão de autenticação mútua, o cliente (ou ponte) também apresenta seu próprio certificado ao broker.

A grande diferença nessa transação é que o broker não tem a opção de aceitar ou recusar o certificado do cliente. Em vez disso, é necessário que o certificado já seja conhecido pelo broker (ou seja, armazenado em sua truststore) antes da solicitação do estabelecimento de uma conexão de autenticação mútua. A truststore padrão do Lotus Expeditor é a keystore Java runtime cacerts presente em:

$Expeditor_INSTALL_DIR\rcp\eclipse\plugins\$runtime_jre\jre\lib\security\cacerts

É nessa keystore que os exemplos a seguir armazenam o certificado do cliente.

Configurar o micro broker para autenticação mútua

Para configurar autenticação mútua para conexões com um micro broker, é necessário definir a porta segura de modo que ela requeira um certificado de cliente válido antes que uma conexão seja permitida.

Configurar autenticação mútua para uma porta adicional

Como é possível ver na listagem 6, apenas um linha adicional de código (em negrito) é necessária ao adicionar uma porta segura a um broker em execução.


Listagem 6. Adicionar um ouvinte seguro de autenticação mútua a um micro broker
private final String BROKER_NAME = "MBroker";
private final int SECURE_PORT = 8883;
private final String KEYSTORE_DTEE = "/mbrokerdtee.jks";
private final char[] KSPASSWD_DTEE ={'d','e','f','a','u','l','t'};

void _addSecurePort() throws Exception
{
    BrokerFactory factory = BrokerFactory.INSTANCE;
    LocalBroker lbroker = factory.getByName(BROKER_NAME);
    Communications bc = lbroker.getCommunications();
    // Esoecificar o número da porta nesta chamada de método. 8883 é a porta padrão IANA
    // para conexões MQTT seguras.
    MQTTTCPListenerDefinition mqttld = 
                 bc.createMQTTTCPListenerDefinition(SECURE_PORT);
    mqttld.setSecure(true);
    ServerSSLDefinition ssld = mqttld.createSSLDefinition();
    ssld.setKeyStore(KEYSTORE_DTEE);
    ssld.setKeyStorePassword(KSPASSWD_DTEE);
    ssld.setClientCertificateRequired(true);
    mqttld.setSSLDefinition(ssld);
    bc.addTCPListener(mqttld);
}

Configurar autenticação mútua para um broker seguro padrão

A mesma linha de código se aplica ao criar um micro broker seguro padrão que requeira autenticação mútua, como exibido na listagem 7.


Listagem 7. Criar um micro broker seguro padrão de autenticação mútua
void createSecureBroker() throws Exception 
{
    BrokerFactory factory = BrokerFactory.INSTANCE;
    BrokerDefinition def = factory.createBrokerDefinition(BROKER_NAME);
    // setPort() é opcional – 8883 é usado se este método não for chamado
//  def.setPort(Integer.parseInt(SECURE_PORT));
    def.setDefaultListenerSecure(true);
    ServerSSLDefinition ssld = def.createSSLDefinition();
    ssld.setKeyStore(KEYSTORE_DTEE);
    ssld.setKeyStorePassword(KSPASSWD_DTEE);
    ssld.setClientCertificateRequired(true);
    def.setSSLDefinition(ssld);
    factory.create(def);
}

As mensagens de log do broker quando ele é iniciado são idênticas àquelas vistas ao usar autenticação de servidor.

Observe que caso você tente conectar ao broker a partir de um cliente que não possua um certificado (ou que possua um certificado que não é conhecido do micro broker), uma MQTTException com uma SSLHandshakeException aninhada é utilizada pelo código do cliente.

Caso haja a tentativa de uma ligação em ponte sem certificado, as mensagens a seguir, exibidas na listagem 8, são publicadas no log do LocalBroker (ou seja, o broker tentando se conectar à porta segura):


Listagem 8. Mensagens publicadas no LocalBroker
> 2009/01/05 14:39:11.843 SEVERE FMBB2117 bridge MQTT connection for the pipe 
securePipe threw an MqttException. 
> 2009/01/05 14:39:11.859 WARNING FMBB2098 bridge Connector Class loading 
threw the exception  (0) - javax.net.ssl.SSLHandshakeException: The operation timed 
out for the Pipe securePipe 
 

Essas mensagens são publicadas em intervalos regulares à medida que o LocalBroker realiza novas tentativas de estabelecer a conexão.

O micro broker com a porta segura nunca vê a tentativa de conexão, já que sua pilha de rede SSL subjacente não transmite a solicitação recebida ao broker. O resultado disso é que nenhuma mensagem é publicada no log do broker seguro.

Criar uma keystore para o cliente (ponte)

Como já foi visto, é necessário que o cliente possua um certificado e o apresente ao micro broker remoto para que a conexão seja permitida.

Criar a keystore do cliente (ou ponte)

Assim como para o broker, utilizando o utilitário keytool, crie uma keystore que contenha as credenciais do cliente:

keytool -genkey -alias clientcert -keystore clientdtee.jks -keypass default -storepass
default -dname "CN=MB Client, OU=PVC, O=IBM, C=UK" -keyalg RSA

Tal utilitário cria um arquivo que contém o par de chaves do cliente e um certificado autoassinado correspondente.

Obter uma cópia do certificado do cliente

Como a plataforma do Lotus Expeditor não garante uma maneira do micro broker aceitar um certificado quando a conexão é solicitada, é necessário colocar uma cópia do certificado do cliente (ou ponte) na truststore do Lotus Expeditor antes que a solicitação seja feita. Primeiro, é necessário obter uma cópia do certificado a partir da keystore do cliente que acaba de ser criada. O utilitário keytool possui tal recurso:

keytool -export -alias clientcert -keystore clientdtee.jks -file clientdtee.cer

Esse recurso cria um arquivo (clientdtee.cer) que contém o certificado do cliente.

Importar o certificado do cliente (ponte)

Como já mencionado, o Lotus Expeditor utiliza o arquivo cacerts como sua truststore padrão. Portanto, é necessário importar o certificado da ponte ou cliente para o cacerts.

Importar o certificado do cliente (ponte) para a truststore do Lotus Expeditor

Execute o utilitário keytool novamente para importar o certificado:

keytool -import -alias clientcert -file clientdtee.cer -keystore cacerts

Este comando importa o certificado, mas somente após sua confirmação de que o certificado é confiável. Tal confirmação é uma medida preventiva para que você tenha a oportunidade de recusar o certificado caso tenha alguma razão para suspeitar que ele não seja genuíno. Observe que a senha padrão da keystore do cacerts do Lotus Expeditor é changeit, como mostrado na listagem 9.


Listagem 9. Confirmar a confiança no certificado
Enter store password: changeit
Owner : CN=MB Client,OU=PVC,O=IBM,C=UK
Issuer : CN=MB Client,OU=PVC,O=IBM,C=UK
Serial number : 4962101e
Valid from Mon Jan 05 13:50:22 GMT 2009 to Sun Apr 05 14:50:22 BST 2009
Certificate fingerprints :
  [MD5]   : a4:ab:83:af:14:2b:40:ae:a8:f4:67:92:d7:48:28:f8
  [SHA-1] : a4:13:05:4a:b2:12:96:ee:35:ee:fd:a8:ef:83:dc:bc:0e:27:44:32

Do you trust this certificate? [no]:  yes

É possível verificar que o certificado esteja no cacerts por meio da opção lista do utilitário keytool:

keytool -list -alias clientcert -keystore cacerts

Partindo do princípio de que o certificado tenha sido importado com sucesso, é possível ver o resultado exibido na listagem 10 (com a assinatura MD5 do certificado do seu cliente):


Listagem 10. A assinatura MD5 do certificado do cliente
Enter store password: changeit
clientcert, Mon Jan 05 15:31:51 GMT 2009, trusted certificate entry,
Certificate fingerprint:
  [MD5]   : a4:ab:83:af:14:2b:40:ae:a8:f4:67:92:d7:48:28:f8

Utilizar a opção de lista de keytool na keystore do cliente permite que você verifique que o certificado na truststore do micro broker corresponde à chave do cliente (ponte):

keytool -list -keystore clientdtee.jks

Como é possível ver na listagem 11, o hash MD5 da chave corresponde ao do certificado.


Listagem 11. O hash MD5 da chave
Enter store password: default
Keystore type: jks
Keystore provider: OTI

Keystore contains 1 entry:

clientcert, Mon Jan 05 13:50:22 GMT 2009, key entry,
Certificate fingerprint:
  [MD5]   : a4:ab:83:af:14:2b:40:ae:a8:f4:67:92:d7:48:28:f8

Criar uma conexão de cliente de autenticação mútua

Agora que todas as peças estão em seu devido lugar, o processo de criação de uma conexão de autenticação mútua de um cliente com um broker é bastante direto.

Criar uma conexão de autenticação mútua de um cliente

É necessário que o cliente saiba onde procurar seu certificado autoassinado para que possa apresentá-lo ao broker remoto. O cliente realiza tal etapa fornecendo um objeto Properties que contém o nome da keystore e sua senha, como exibido (em negrito) na listagem 12.


Listagem 12. Criar uma conexão de cliente de autenticação mútua
private MqttClient myClient;
private static final String BROKER_URL = "ssl://localhost:8883";
private static final String CLIENT_ID = "AnonUser";
private static final String CLIENT_KS = “clientdtee.jks";
private static final String CLIENT_KSPW = “default”:

public void createClient() throws Exception
{
    // Definir as opções de conexão para o cliente MQTTv5
    // Nos conectaremos anonimamente, então não definimos nome de usuário/senha
    MqttConnectOptions connOpts = new MqttConnectOptions();
    connOpts.setPurge(true);
    // Agora defina as propriedades SSL para o cliente
    Properties sslprops = new Properties();
    sslprops.setProperty("com.ibm.ssl.keyStore", CLIENT_KS);
    sslprops.setProperty("com.ibm.ssl.keyStorePassword", CLIENT_KSPW);
    connOpts.setSSLProperties(sslprops);
    // Finalmente crie o objeto do cliente
    myClient = new MqttClient(BROKER_URL, CLIENT_ID);
    // Criamos o cliente. Para a utilização normal, também definimos e configuramos um 
    // manipulador de chamada callback, mas estaremos conectando, então, não se preocupe.
    myClient.connect(connOpts);
}

As mensagens de log publicadas pelo broker são idênticas àquelas exibidas para a autenticação de servidor.

Criar uma ligação em ponte de autenticação mútua

A criação de uma ligação em ponte também é um processo bastante direto. Neste exemplo, a keystore e o certificado utilizados para a conexão do cliente são usados para a ponte para fins de simplicidade. Talvez você deseje criar um par de chaves/certificado e keystore separados para a ponte.

Criar uma ligação em ponte de autenticação mútua

A ponte também necessita saber onde encontrar seu certificado autoassinado. Diferentemente do cliente, a ponte obtém tal informação utilizando as chamadas de método exibidas na listagem 13.


Listagem 13. Criar uma ligação em ponte de autenticação mútua
private final String BROKER_NAME = "LocalBroker";
private final int REMOTE_SECURE_PORT = 8883;
private static final String BRIDGE_KS = “clientdtee.jks";
private static final String BRIDGE_KSPW = “default”:

public void _createSecurePipe(CommandInterpreter ci) throws Exception
{
    BrokerFactory factory = BrokerFactory.INSTANCE;
    LocalBroker lbroker = factory.getByName(BROKER_NAME);
    bridge = lbroker.getBridge();
    PipeDefinition pipeDef = bridge.createPipeDefinition("securePipe");
    MQTTConnectionDefinition secBridge = 
                bridge.createMQTTConnectionDefinition("secConn");
    // Remova as barras de comentário desta chamada de método para uma conexão MQTTv3
//  secBridge.setProtocolVersion(3);
    secBridge.setHost("localhost");
    secBridge.setPort(REMOTE_SECURE_PORT);
    secBridge.setSecure(true);
    SSLDefinition ssld = secBridge.createSSLDefinition();
    ssld.setKeyStore(BRIDGE_KS);
    ssld.setKeyStorePassword(BRIDGE_KSPW.toCharArray());
    secBridge.setSSLDefinition(ssld);
    pipeDef.setConnection(secBridge);
    // A barra precisa possuir pelo menos um fluxo...
    FlowDefinition outflow = bridge.createFlowDefinition("secureflow");
    outflow.setSources(new DestinationDefinition[]{
                bridge.createTopicDefinition("SSLBridge/#")});
    outflow.setQos(2);
    pipeDef.addOutboundFlow(outflow);
    Pipe pipe = bridge.addPipe(pipeDef);
    pipe.start();
}

As mensagens de log publicadas pelos brokers locais e remotos são idênticas àquelas exibidas para a autenticação de servidor.



Voltar para parte superior


Configurações SSL

Há vários locais a partir dos quais uma conexão SSL pode obter suas configurações. E é possível que isso cause confusões algumas vezes.

Como já foi visto, o cliente e a ponte são semelhantes, já que são configurados para criar uma conexão SSL. A principal diferença é que as configurações SSL são transmitidas ao cliente através de um objeto de propriedades, enquanto a ponte utiliza métodos setter para atingir o mesmo objetivo. As configurações de SSL para ouvintes micro broker usam os mesmos métodos setter que a ponte.

Os exemplos utilizam um número mínimo de configurações para estabelecer conectividade SSL. Há inúmeras configurações adicionais que permitem configurações mais complexas, mas elas estão fora do escopo deste artigo.

Há uma correlação de um para um entre as duas abordagens exibidas na tabela 1.


Tabela 1. Compara o método setter de ponte e property de cliente
Property de clienteMétodo setter de bridgeComentário
com.ibm.ssl.enabledCipherSuitessetEnabledCipherSuites(String[] ciphers)Especifica os pacotes de códigos que o broker utiliza para conectar clientes
com.ibm.ssl.keyStoresetKeyStore(String keyStore)Define o caminho para a keystore SSL/TLS
com.ibm.ssl.keyStorePasswordsetKeyStorePassword(char[] keyStorePassword)Define a senha requerida para carregar a keystore
com.ibm.ssl.keyStoreProvidersetKeyStoreProvider(String keyStoreProvider)Define o provedor da keystore
com.ibm.ssl.keyStoreTypesetKeyStoreType(String keyStoreType)Define o tipo utilizado para a keystore
com.ibm.ssl.keyManagersetKeyManager(String keyMgrAlgo)Define o gerente da keystore
com.ibm.ssl.protocolsetProtocol(String protocol)Define a versão do protocolo SSL/TLS que deve ser utilizado
com.ibm.ssl.contextProvidersetSecurityProvider(String securityProvider)Define o provedor de segurança utilizado para implementar o protocolo TLS
com.ibm.ssl.trustManagersetTrustManager(String trustMgrAlgo)Define o algoritmo utilizado para instanciar um objeto TrustManagerFactory, em vez de utilizar o algoritmo padrão disponível na plataforma
com.ibm.ssl.trustStoresetTrustStore(String trustStore)Define o nome do caminho da truststore SSL/TLS utilizada pelo broker
com.ibm.ssl.trustStorePasswordsetTrustStorePassword(char[] trustStorePassword)Define a senha da truststore utilizada
com.ibm.ssl.trustStoreProvidersetTrustStoreProvider(String trustStoreProvider)Define o provedor da truststore
com.ibm.ssl.trustStoreTypesetTrustStoreType(String trustStoreType)Define o tipo de truststore utilizado

Clientes JMS e MQTTv3

Os exemplos mostram um cliente MQTTv5 utilizando uma conexão SSL. Os clientes micro broker JMS e MQTTv3 também recebem suas propriedades SSL através de um objeto Properties, como exibido na tabela 2.


Tabela 2. Clientes e suas propriedades SSL
ClientePropriedades SSL
MQTTv5O objeto SSL Properties (sslprops nos exemplos) é definido no objeto connection options (connOpts nos exemplos) transmitido como um parâmetro ao método client.connect()
JMS O objeto SSL Properties é definido como um objeto property na JmsConnectionFactory. ((JmsConnectionFactory) cf).setObjectProperty(MQTTConstants.MQTT_SSL_PROPERTIES,sslClientProps);
MQTTv3O objeto SSL Properties é definido no objeto MqttProperties transmitido como um parâmetro aos métodos MqttClientFactory.createMqttClient()


Voltar para parte superior


Mais configurações avançadas

Há um grande número de opções disponíveis ao configurar o SSL para o micro broker. Esta seção dá uma breve descrição geral de algumas das maneiras que podem ser utilizadas para preencher requisitos específicos.

Ligação em ponte ao WebSphere MQ

O micro broker possui um conector específico para criar pontes que liguem a uma instância do WebSphere MQ. A configuração do SSL para esse tipo de conexão é um pouco diferente daquela utilizada para uma ponte MQTT. Além das propriedades padrão necessárias para uma ligação em ponte, é necessário definir algumas propriedades específicas do WebSphere MQ. Mais especificamente, setQueueManager() e setChannel() são necessários para definir a conexão. A definição SSL também requer que os pacotes de códigos habilitados sejam definidos. Tal configuração deve corresponder àquelas disponíveis na instância do WebSphere MQ. Ver listagem 14.


Listagem 14. Criar uma ligação em ponte ao WebSphere MQ
private final String BROKER_NAME = "MBroker";
private String mqhost = "swtest.hursley.ibm.com";
private int mqport = 1414;
private String qmgr = "swtest";

public void _createSecureMqPipe() throws Exception
{
    BrokerFactory factory = BrokerFactory.INSTANCE;
    LocalBroker lbroker = factory.getByName(BROKER_NAME);
    bridge = lbroker.getBridge();
    PipeDefinition pipeDef = bridge.createPipeDefinition("secureMqPipe");
    MQJMSConnectionDefinition remote = 
        bridge.createMQJMSConnectionDefinition("remote");
    remote.setHost(mqhost);
    remote.setPort(mqport); 
    remote.setQueueManager(qmgr);
    remote.setChannel("SECURE.CHANNEL");
    remote.setSecure(true);
    SSLDefinition ssld = remote.createSSLDefinition();
    ssld.setEnabledCipherSuites(new String[]{
        "SSL_RSA_WITH_RC4_128_SHA"}); 
    remote.setSSLDefinition(ssld);
    pipeDef.setConnection(remote);

    // A barra deve possuir pelo menos um fluxo...
    FlowDefinition outflow = bridge.createFlowDefinition("secureflow");
    outflow.setSources(new DestinationDefinition[]{
                bridge.createTopicDefinition("SSLBridge/#")});
    outflow.setQos(2);
    pipeDef.addOutboundFlow(outflow);
    Pipe pipe = bridge.addPipe(pipeDef);
    pipe.start();
}

Observe que a configuração padrão do WebSphere MQ determina que a autenticação mútua seja requerida. Neste exemplo, como a configuração do WebSphere MQ remoto foi alterada para que apenas a autenticação de servidor (ou seja, a instância do WebSphere remoto) seja requerida, uma keystore para a ponte (cliente) não foi especificada. Para autenticação mútua, é necessário que um certificado de ponte (cliente) válido que corresponda à chave na keystore da ponte esteja disponível ao WebSphere MQ.

Vincular um ouvinte a um endereço IP específico

Caso o seu sistema possua vários endereços IPs alocados a ele, possivelmente em redes diferentes, é possível especificar qual desses endereços um ouvinte deve monitorar em busca de solicitações de conexão. Solicitações recebidas em outros endereços IP serão ignoradas. Para realizar tal vinculação, adicione uma única linha de código (em negrito no exemplo exibido na listagem 15) à sua definição de ouvinte.


Listagem 15. Adicionar um ouvinte a uma interface de rede específica
private final String BROKER_NAME = "MBroker";
private final int SECURE_PORT = 8883;
private final String KEYSTORE_DTEE = "/mbrokerdtee.jks";
private final char[] KSPASSWD_DTEE ={'d','e','f','a','u','l','t'};

void _addSecurePort() throws Exception
{
    BrokerFactory factory = BrokerFactory.INSTANCE;
    LocalBroker lbroker = factory.getByName(BROKER_NAME);
    Communications bc = lbroker.getCommunications();
    // Especificar o número da porta nesta chamada de método. 8883 é a porta padrão IANA
    // para conexões MQTT seguras.
    MQTTTCPListenerDefinition mqttld = 
                 bc.createMQTTTCPListenerDefinition(SECURE_PORT);
    mqttld.setSecure(true);
    ServerSSLDefinition ssld = mqttld.createSSLDefinition();
    ssld.setKeyStore(KEYSTORE_DTEE);
    ssld.setKeyStorePassword(KSPASSWD_DTEE);
    mqttld.setNetworkInterface("127.0.0.1");
    mqttld.setSSLDefinition(ssld);
    bc.addTCPListener(mqttld);
}

No exemplo, o novo ouvinte seguro da porta 8883 responde apenas a solicitações recebidas de clientes hospedados no mesmo sistema que o micro broker. Uma configuração mais prática seria um ouvinte não seguro vinculado a uma porta presente em uma rede interna, com o ouvinte seguro em uma rede fora do firewall de seu departamento ou empresa, garantindo assim comunicação segura para as conexões iniciadas em organizações externas.



Voltar para parte superior


Solução de problemas de SSL de micro broker

Esta seção traz sugestões sobre como resolver problemas que podem surgir ao configurar conexões de SSL para o seu micro broker. Ela não contém todas as soluções existentes, mas cobre alguns erros típicos que podem surgir.

Problemas de keytool

O utilitário keytool não abre minha keystore. Recebo uma mensagem que diz "keytool error (provavelmente não traduzida): java.io.IOException: Invalid keystore format"

Tal problema está ocorrendo, provavelmente, porque você está tentando usar o utilitário keytool do J2SE para abrir uma keystore de DesktopEE.

O utilitário keytool não abre minha keystore. Após digitar a senha da keystore, recebo a mensagem "keytool error: Unable to open keystore. Check the file path and password" (Erro de keytool. Não foi possível abrir a keystore. Verifique o caminho do arquivo e a senha.)

Tal problema está ocorrendo, provavelmente, porque você está tentando usar o utilitário keytool do DesktopEE para abrir uma keystore de J2SE.

Problemas de falha na conexão SSL

A conexão SSL pode não obter sucesso devido a inúmeras razões. Em alguns casos, a mensagem de exceção é direta e aponta diretamente para o problema, como em "Incorrect password" (Senha incorreta).

Mas em outros casos, ela pode ser vaga, como nos exemplos a seguir.

Surge a mensagem de exceção "SSL Handshake failure" (Falha na comunicação SSL).

Tal mensagem pode surgir por diferentes motivos. Verifique se o micro broker e o cliente (ou ponte) possuem acesso às suas respectivas keystores e truststores.

Surge a mensagem de exceção "SSL-Initialization failed. I/O problem while loading the keystore" (Falha ao inicializar SSL. Problema de E/S ao carregar a keystore).

Tal mensagem é exibida por diferentes motivos. Ela é gerada pelo código SSL subjacente, o que significa que, infelizmente, o micro broker não pode fornecer quaisquer informações adicionais. Uma causa comum é que talvez o broker esteja sendo executado em um ambiente JVM, mas esteja tentando utilizar uma keystore criada com a keytool de outro ambiente JVM.

Surge a mensagem de exceção "java.io.IOException: Invalid keystore format"

Tal exceção pode indicar que a keystore está corrompida. Ela pode ocorrer caso você tente usar uma keystore DesktopEE no ambiente J2SE.

O micro broker está tentando acessar uma truststore ou keystore que não foi aquela definida por você.

O micro broker pode obter configurações SSL de diversos locais:

  • Chamadas específicas de método para o ouvinte ou cliente
  • Configurações de broker
  • Configurações da plataforma do Lotus Expeditor
  • Configurações da Java Virtual Machine

Caso você defina uma propriedade SSL de sistema (javax.net.ssl) na linha de comando Java, ela cancelará as configurações da plataforma do Lotus Expeditor.

Você está tentando conectar um cliente (ou ponte) a uma porta segura em um broker, mas a conexão não está obtendo sucesso e o sistema não lhe apresenta a janela solicitando que aceite ou recuse o certificado do broker.

A figura 1 traz um exemplo de janela de Alerta de Segurança, juntamente com uma descrição das diversas opções disponíveis.

Caso você já tenha se conectado ao broker e selecionado que o certificado do broker é confiável, o cliente estabelecerá a conexão sem exibir a janela exibida na figura 1. Caso contrário, é possível que você esteja executando o Lotus Expeditor com uma JVM não pertencente àquelas vendidas com o produto.

Um trust manager controla o modo no qual se deve lidar com certificados desconhecidos recebidos. O trust manager do Lotus Expeditor JVM exibe a janela de Alerta de Segurança, enquanto outras JVMs podem não fazer o mesmo.

Você criou sua keystore com o utilitário keytool do DesktopEE e confirmou que seu broker está sendo executado em uma JVM de DesktopEE. No entanto, os problemas persistem.

Você utilizou o parâmetro –keyalg RSA quando criou seu keypar com o utilitário keytool pela primeira vez? O algoritmo de chave padrão utilizado pelo keytool é DSA, que não é compatível com a JVM de DesktopEE.



Voltar para parte superior


Conclusão

Este artigo trouxe uma introdução simples à implementação de conexões seguras habilitadas a SSL de e com um micro broker. As informações fornecidas são suficientes para permitir que os usuários protejam seus dados à medida que eles viajam pela rede com um mínimo de conhecimento acerca das operações de SSL. Para aqueles que tiverem a necessidade e/ou o interesse, há muito mais a se conhecer a respeito de SSL.



Recursos



Sobre o autor

Steve Russell trabalha no laboratório da IBM no Reino Unido, em Hursley Park. Sua especialidade é o teste de softwares para tecnologias avançadas e abrangentes de envio e recebimento de mensagens. É possível entrar em contato com Steve no e-mail steve_russell@uk.ibm.com.




Avalie esta página


Reserve um instante para completar este formulário para nos ajudar a servi-lo melhor.



 


 


Não
são úteis
Extremamente
úteis
 






Voltar para parte superior