Desenvolvimento

5 ago, 2013

Simples SPDY e Negociação NPN com HAProxy

Publicidade

SPDY é um protocolo experimental desenvolvido pelo Google e projetado para reduzir a latência das páginas web. Especificamente, o objetivo é abordar as limitações do HTTP 1.1 e para remover os gargalos existentes: cabeçalho do bloqueio de linha, uso ineficiente de conexões TCP subjacentes e cabeçalho lotado, entre outros. No entanto, enquanto tudo isso soa muito bem por escrito, a implementatação de um novo protocolo na web, na prática, é repleta de dificuldades.

Especificamente, as muitas camadas de roteadores HTTP, caches e ferramentas personalizadas, que muitas vezes se comportam de maneiras imprevisíveis quando apresentadas com um protocolo alternativo, levando à queda de conexão aleatória e a usuários frustrados. Para resolver isso, o SPDY é entregue via SSL: do início ao fim, o túnel criptografado permite que o cliente e o servidor troquem de frames SPDY sem a intervenção de nós intermediários. É importante notar que o SPDY não requer SSL, mas, na prática, o SSL é uma escolha pragmática para se chegar a uma solução de trabalho.

Next Protocol Negotiation (NPN)

Mas como é que o cliente e o servidor sabem usar SPDY quando o túnel SSL é aberto? Este é o lugar onde o Next Protocol Negotiation (NPN) entra em cena. O NPN é uma extensão SSL que permite que o cliente e o servidor negociem o protocolo de aplicação, como parte do handshake do SSL.

xnpn-negotiation

O NPN elimina a viagem extra para negociar o protocolo de aplicação – compare isso com o handshake do WebSocket atual, que impõe uma outra ida e volta de latência em cima da negociação SSL. Se você está contando, isso é um RTT para o handshake do TCP, dois para a negociação SSL, e um para a atualização do WebSocket – quatro RTTs antes de quaisquer dados de aplicativos podem ser trocados!

Suporte para NPN foi adicionado no OpenSSL (1.0.0d +), NSS, e TLSLite. Chrome, Firefox, Opera suportam o SPDY (e, portanto, também NPN), bem como muitos dos servidores populares: Apache, nginx, Jetty, e Node.js, entre outros. Dito isso, a necessidade de suporte para NPN tem sido, no entanto, uma barreira para a adoção mais ampla. Isto é, até o HAProxy decidiu tornar a vida de todos muito mais fácil! Vamos dar uma olhada em um exemplo.

Construindo HAProxy com suporte para NPN

O suporte para SSL chegou aos builds de desenvolvimento do HAProxy no início de setembro e foi melhorando rapidamente desde então. Uma adição notável é, você adivinhou, o suporte para negociação NPN! Para fazê-la funcionar, baixe o último pacote de desenvolvimento, ou faça um check-out de git e construa o binário contra uma versão mais recente do OpenSSL:

gt; wget http://www.openssl.org/source/openssl-1.0.1c.tar.gz
gt; tar -zxvf openssl* && cd openssl*
gt; ./configure --prefix=/tmp/openssl --openssldir=/tmp/openssl darwin64-x86_64-cc
gt; make && make install

gt; git clone http://git.1wt.eu/git/haproxy.git/ && cd haproxy
gt; make =generic =1 =-I/tmp/openssl/include =-L/tmp/openssl/lib -lssl
gt; ./haproxy -vv
  # Built with OpenSSL version : OpenSSL 1.0.1c 10 May 2012
  # OpenSSL library supports TLS extensions : yes

As instruções acima devem construir a última versão do HAProxy em OSX. Se você já tem OpenSSL 1.0.0d +, então você pode pular o primeiro passo, assim como o ADDINC extra e directivas ADDLIB. Com isso, estamos quase prontos para lidar com SPDY ao lado de nosso HTTP regular e tráfego HTTPS!

Configurando HAProxy para HTTP, HTTPS e SPDY

O que queremos fazer é configurar nosso HAProxy como um proxy de terminação SSL. Ou seja, o HAProxy servirá o nosso certificado SSL para o cliente, e todo o tráfego encaminhado para nossos servidores internos fluirá sem criptografia. Isso também significa que o HAProxy terá de lidar com o handshake do NPN. Na verdade, de modo ideal, ele deve tratar e rotear todos os tipos de tráfego: HTTP, HTTPS, e SPDY.

xhaproxy-npn

defaults
  log 127.0.0.1 local0

# accept connections on port 80, forward requests to "http_cluster"
frontend http
  mode http
  bind :80
  default_backend http_cluster

# accept connections on port 443 (SSL)
# - forward SPDY connections to spdy_cluster
# - forward regular HTTPS connections to http_cluster
# - ha.pem should be a concatenated file: certificate first then the key
frontend secure
  mode tcp

  # advertise spdy/2 support via NPN
  bind :443 ssl crt ./certs/ha.pem npn spdy/2
  use_backend spdy_cluster if { ssl_npn -i spdy/2 }

  default_backend http_cluster

# SPDY server running on port 10000
backend spdy_cluster
  server srv01 127.0.0.1:10000

# HTTP server running on port 8000
backend http_cluster
  mode http
  server srv01 127.0.0.1:8000

Simples assim. HAProxy aceita a conexão SSL, realiza o handshake do SSL e anuncia suporte para spdy/2 se o cliente suporta NPN. Se o cliente seleciona spdy/, então o pedido é encaminhado para o servidor SPDY. Caso contrário, a solicitação HTTPS é encaminhada para o cluster HTTP. A parte importante é que, em ambos os casos, o tráfego encaminhado já não é criptografado – o servidor SPDY não precisa executar o handshake do SSL ou se preocupar com NPN; em vez disso, simplesmente tem que analisar e devolver os frames SPDY  de volta para o proxy.

NPN não é apenas para SPDY

Para ver o SPDY em ação, você pode baixar e executar a demonstração do servidor SPDY escrito em Ruby atrás do HAProxy. Com suporte nativo para NPN no HAProxy, adicionar suporte SPDY nunca foi tão fácil – você está literalmente a apenas algumas regras de distância para rotear as solicitações SPDY recebidas com o resto do seu tráfego. Não há necessidade de reduzir sua conexão SPDY para HTTP, furar sua infraestrutura para expor servidores NPN capazes, ou implementar infraestrutura paralela.

O melhor de tudo, enquanto que o exemplo acima é específico para o SPDY, é que o mecanismo do NPN funciona para qualquer protocolo novo, ou já existente. Como exemplo, podemos eliminar a viagem extra em na negociação do WebSocket com NPN, ou podemos implementar outros, protocolos novos e experimentais, sem impor quaisquer penalidades de latência adicionais.

***

Artigo traduzido pela Redação iMasters, com autorização do autor. Publicado originalmente em http://www.igvita.com/2012/10/31/simple-spdy-and-npn-negotiation-with-haproxy/