Aprenda neste tutorial como configurar certificados SSL válidos usando a tecnologia Let’s Encrypt, que permite emitir certificações para sites que exigem encriptação SSL usando o protocolo https para navegação, como por exemplo lojas virtuais ou páginas de login.
Let’s Encrypt é um projeto de esforço mundial que visa tornar a internet mais segura e que tem o apoio de grandes empresas do setor de tecnologia. A emissão e a renovação dos certificados são gratuitas e “lifetime”, ou seja, você nunca irá precisar pagar por ele o resto da vida do domínio.
Seguindo os meus tutoriais você deve ter notado que ao navegar pelas páginas do painel de controle, phpMyAdmin e Webmail usando https o acesso exibe uma aviso dizendo que o certificado não é válido. Isso ocorre porque ao instalar o ISPConfig e os serviços emitimos um certificado genérico a partir do próprio servidor, sem a devida validação por órgãos competentes.
Com a instalação do Let’s Encrypt e a devida configuração do bloco de diretivas no NginX podemos adicionar ao servidor e aos sites certificados válidos, e que inclusive são homologados para uso em lojas virtuais que conectam-se a Cielo por exemplo.
*Eu já utilizo o Let’s Encrypt por aproximadamente um ano instalando em servidores de sites parceiros e clientes para lojas Magento, Opencart e Prestashop, além de sites WordPress que dependem de login com https. Até hoje não tivemos problema algum com ele.
* Esta documentação pode servir como base para implementação do Let’s Encrypt em servidores com Apache e outras distros Linux diferentes de Debian 8, porém é altamente recomendável seguir nosso tutorial de Servidor Linux VPS: Debian 8 Jessie com ISPConfig 3 e NginX + Servidor de Emails, clique aqui e aprenda como instalar.
O nosso tutorial de Debian 8 (ver link acima) já tem os comandos para instalar e ativar o certbot (app usado para instalar e gerenciar os certificados da Let’s Encrypt no servidor). Mas caso você não tenha ele instalado siga os procedimentos abaixo:
*Execute os comandos para instalação e configuração dos certificados logado no servidor com o superusuário root.
Adicione o repositório backports do Debian, atualize a lista de pacotes e instale o aplicativo.
Edite o arquivo /etc/apt/sources.list e verifique se ao final há uma linha parecida com esta, se não houver adicione:
deb http://ftp.debian.org/debian jessie-backports main
Em seguida atualize o repositório e instale o Let’s Encrypt:
> apt-get update > apt-get -y install -t jessie-backports certbot
*Mas somente execute este primeiro passo caso não tenha o certbot instalado ainda.
Para prevenir este tipo de ataque ao SSL pode-se configurar um parâmetro nas diretivas do site gerando uma chave de criptografia adicional ao certificado. Execute os comandos abaixo. *Estes comandos só serão necessários uma única vez para o servidor e a encriptação da chave poderá demorar até 3 minutos em alguns casos.
> cd /etc/ssl/private > openssl dhparam -out dhparams.pem 2048 > chmod 600 dhparams.pem
Se você seguiu atentamente o meu tutorial provavelmente criou o nome do servidor (hostname) com uma URL válida (FQDN). Por exemplo, ao fazer o deploy do VPS digitou no hostname uma URL válida como esta: server1.SEUDOMINIO.COM e adicionou o subdominio “server1” nos registros da tabela DNS do SEUDOMINIO.COM. Caso não tenha feito isso sempre há tempo para recomeçar da maneira correta.
Considerando que o seu FQDN (URL de acesso ao servidor) seja server1.SEUDOMINIO.COM, crie um novo arquivo no diretório /etc/nginx/sites-available com o nome de vps.vhost e cole as diretivas abaixo dentro dele, substituindo server1.SEUDOMINIO.COM pelo FQDN do servidor:
server { listen 80; #COMENTAR as linhas SSL para validar o certificado LetsEncrypt e liberar elas apos a emissao # listen 443 ssl; # ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # ssl_certificate /etc/letsencrypt/live/server1.SEUDOMINIO.COM/cert.pem; # ssl_certificate_key /etc/letsencrypt/live/server1.SEUDOMINIO.COM/privkey.pem; # ssl_trusted_certificate /etc/letsencrypt/live/server1.SEUDOMINIO.COM/fullchain.pem; # ssl_stapling on; # ssl_stapling_verify on; # ssl_dhparam /etc/ssl/private/dhparams.pem; # ssl_session_cache shared:ssl_session_cache:10m; # ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA'; server_name server1.SEUDOMINIO.COM; root /usr/local/ispconfig/interface/web/; client_max_body_size 100M; location / { index index.php index.html; } # serve static files directly location ~* ^.+.(jpg|jpeg|gif|css|png|js|ico|html|xml|txt)$ { access_log off; } location ~ \.php$ { try_files $uri =404; include /etc/nginx/fastcgi_params; fastcgi_pass unix:/var/lib/php5-fpm/ispconfig.sock; #Caso tenha instalado o Debian 9 com multiplas versoes de PHP substitua a linha acima por esta (descomente): #fastcgi_pass unix:/var/lib/php7.0-fpm/ispconfig.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; #fastcgi_param PATH_INFO $fastcgi_script_name; fastcgi_buffer_size 128k; fastcgi_buffers 256 4k; fastcgi_busy_buffers_size 256k; fastcgi_temp_file_write_size 256k; } location ~ /\. { deny all; } location ^~ /.well-known/acme-challenge/ { default_type text/plain; } location /phpmyadmin { root /usr/share/; index index.php index.html index.htm; location ~ ^/phpmyadmin/(.+\.php)$ { try_files $uri =404; root /usr/share/; fastcgi_param QUERY_STRING $query_string; fastcgi_param REQUEST_METHOD $request_method; fastcgi_param CONTENT_TYPE $content_type; fastcgi_param CONTENT_LENGTH $content_length; fastcgi_param SCRIPT_FILENAME $request_filename; fastcgi_param SCRIPT_NAME $fastcgi_script_name; fastcgi_param REQUEST_URI $request_uri; fastcgi_param DOCUMENT_URI $document_uri; fastcgi_param DOCUMENT_ROOT $document_root; fastcgi_param SERVER_PROTOCOL $server_protocol; fastcgi_param GATEWAY_INTERFACE CGI/1.1; fastcgi_param SERVER_SOFTWARE nginx/$nginx_version; fastcgi_param REMOTE_ADDR $remote_addr; fastcgi_param REMOTE_PORT $remote_port; fastcgi_param SERVER_ADDR $server_addr; fastcgi_param SERVER_PORT $server_port; fastcgi_param SERVER_NAME $server_name; fastcgi_param HTTPS $https; # PHP only, required if PHP was built with --enable-force-cgi-redirect fastcgi_param REDIRECT_STATUS 200; # To access phpMyAdmin, the default user (like www-data on Debian/Ubuntu) must be used #fastcgi_pass 127.0.0.1:9000; fastcgi_pass unix:/var/run/php5-fpm.sock; #Caso tenha instalado o Debian 9 com multiplas versoes de PHP substitua a linha acima por esta (descomente): #fastcgi_pass unix:/var/run/php/php7.0-fpm.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_buffer_size 128k; fastcgi_buffers 256 4k; fastcgi_busy_buffers_size 256k; fastcgi_temp_file_write_size 256k; fastcgi_read_timeout 1200; } location ~* ^/phpmyadmin/(.+\.(jpg|jpeg|gif|css|png|js|ico|html|xml|txt))$ { root /usr/share/; } } location /phpMyAdmin { rewrite ^/* /phpmyadmin last; } location /roundcube { root /var/lib/; index index.php index.html index.htm; location ~ ^/roundcube/(.+\.php)$ { try_files $uri =404; root /var/lib/; include /etc/nginx/fastcgi_params; fastcgi_pass unix:/var/run/php5-fpm.sock; #Caso tenha instalado o Debian 9 com multiplas versoes de PHP substitua a linha acima por esta (descomente): #fastcgi_pass unix:/var/run/php/php7.0-fpm.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_buffer_size 128k; fastcgi_buffers 256 4k; fastcgi_busy_buffers_size 256k; fastcgi_temp_file_write_size 256k; } location ~* ^/roundcube/(.+\.(jpg|jpeg|gif|css|png|js|ico|html|xml|txt))$ { root /var/lib/; } location ~* /.svn/ { deny all; } location ~* /README|INSTALL|LICENSE|SQL|bin|CHANGELOG$ { deny all; } } location /webmail { rewrite ^/* /roundcube last; } }
***Observação: Caso tenha seguido o tutorial de Debian 9 com múltiplas versões de PHP veja as anotações no script acima, elas foram feitas em 3 lugares, para os blocos ISPConfig, phpMyAdmin e Roundcube. É necessário apontar o arquivo de sock correto ou receberá uma mensagem de 502 Bad Gateway ao tentar acessar o painel. Naquelas linhas de sock é definido qual a versão PHP usada para o painel, pode-se ainda usar a 7.1 ou qualquer outra.
Salve o arquivo, que deverá ser /etc/nginx/sites-available/vps.vhost, e execute os comandos abaixo:
> ln -s /etc/nginx/sites-available/vps.vhost /etc/nginx/sites-enabled/vps.vhost > /etc/init.d/nginx restart
Após fazermos isso note que já podemos acessar o painel do ISPConfig pela URL http://server1.SEUDOMINIO.COM, o phpMyAdmin pela URL http://server1.SEUDOMINIO.COM/phpmyadmin e o Roundcube pela URL http://server1.SEUDOMINIO.COM/webmail. Mas ainda falta emitir o certificado para que seja possível acessar as mesmas URLs com https.
Agora que já temos uma URL válida para acessar o servidor podemos solicitar a emissão do certificado SSL para ela. *O emissor de certificados da Let’s Encrypt (ACME) irá verificar se a URL existe e se tem um caminho reverso para a origem, por isso a necessidade de configurar uma URL válida.
*A ACME não permite a emissão de certificados “wildcards” (subdomínios múltiplos), então para cada subdomínio será necessário um novo pedido de emissão. A única exceção é o “www”.
Comando para emitir o certificado para o FQDN de um servidor com ISPConfig e NginX, note o caminho de instalação dos scripts web da página. Substitua o FQDN pelo do seu servidor e [email protected] por um email válido, pois caso haja problemas com o certificado você será notificado:
> certbot certonly --agree-tos --renew-by-default --webroot --email [email protected] -w /usr/local/ispconfig/interface/web -d SERVER1.SEUDOMINIO.COM
Para saber se o certificado foi emitido corretamente uma mensagem de “Congratulations” será exibida indicando o caminho que o certificado foi instalado e que deverá ser /etc/letsencrypt/live/. *Para verificar pode-se também listar o diretório e ver se há um subdiretório com o domínio do site.
Após isso só precisamos descomentar as linhas do certificado no arquivo de diretivas (retirando as “#” hashtags das linhas 5 a 14 do vps.vhost), salvar o arquivo e reiniciar o NginX:
> /etc/init.d/nginx restart
Agora o ISPConfig, phpMyAdmin e Webmail já podem ser acessados com https sem dar erro de certificado.
Muito bem. Agora que já temos o certbot instalado e o método de uso pronto, já podemos emitir certificados para todos os sites no mesmo servidor. O ISPConfig facilita a configuração das diretivas NginX para os sites, irei mostrar abaixo como fazer isso usando ele, mas caso não tenha ISPConfig então verifique na configuração do seu painel como fazer.
Acesse o painel do ISPConfig e selecione o site que deseja emitir o certificado. Clique na aba “Options” do site e adicione as diretivas abaixo ao final das demais diretivas NginX que lá estão:
location ^~ /.well-known/acme-challenge/ { default_type text/plain; }
Clique em salvar e aguarde alguns minutos. Em seguida execute o comando abaixo logado no servidor como superusuário root e substituindo os textos em vermelho pelo email e domínio corretos:
*Note que agora o caminho web para o site é diferente do anterior para o FQDN, nesta emissão você deverá digitar onde cada site está instalado. Para sites adicionados ao ISPConfig basta trocar DOMINIO001.COM pelo seu domínio de site.
*E note que adicionamos um novo parâmetro ao comando para que a emissão seja feita também para o “www”.
> certbot certonly --agree-tos --renew-by-default --webroot --email [email protected] -w /var/www/DOMINIO001.COM/web -d DOMINIO001.COM -d www.DOMINIO001.COM
E para finalizar você deverá colar as diretivas NginX para cada site, na caixa de diretivas NginX da aba “Options” do site. Mas desta vez cole-as no início, antes de todas as outras diretivas lá.
*Lembre-se de substituir o DOMINIO.
listen 443 ssl; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_certificate /etc/letsencrypt/live/DOMINIO001.COM/cert.pem; ssl_certificate_key /etc/letsencrypt/live/DOMINIO001.COM/privkey.pem; ssl_trusted_certificate /etc/letsencrypt/live/DOMINIO001.COM/fullchain.pem; ssl_stapling on; ssl_stapling_verify on; ssl_dhparam /etc/ssl/private/dhparams.pem; ssl_session_cache shared:ssl_session_cache:10m; ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';
Um último passo irá assegurar que o servidor nunca fique sem o certificado de segurança. Na documentação do Let’s Encrypt esta informação não é clara por isso é bom prevenir. E há vários relatos nos fóruns deles dizendo que é necessário reiniciar o NginX após a reemissão do certificado.
O certificado da Let’s Encrypt é lifetime porém a reemissão e revalidação do mesmo é obrigatória a cada 4 meses em média.
Edite o CRON:
> crontab -e
E cole as seguintes linhas ao final:
15 23 * * * /usr/bin/certbot renew -q 0 5 * * * /etc/init.d/php5-fpm restart > /dev/null 0 5 * * * /etc/init.d/nginx restart > /dev/null
Salve as tarefas (para sair do editor salvando tecle CTRL+X e y).
* OBSERVAÇÃO em 19/05/2017:
Ao emitir o certificado talvez ocorra o erro abaixo:
Starting new HTTPS connection (1): acme-v01.api.letsencrypt.org An unexpected error occurred: ClientError: <Response [504]>
O motivo do erro 504 na maioria das vezes é: ou problema de conexão com a Lets Encrypt, ou problema nos servidores deles. Verifique o status do serviço de emissão dos certificados neste link: https://letsencrypt.status.io/
NOTAS:
Domínios com a tabela DNS configurada na CloudFlare e que estejam com a nuvem ativada (laranja) é importante verificar na aba “Crypto” se o certificado está ligado. Na maioria dos casos essa opção deverá estar selecionada como “Flexible” mas para lojas virtuais é recomendável deixar como “Full Strict“.
Mesmo com as diretivas acima configuradas note que o https das páginas não está “forçado”, ou seja, ainda é possível acessar o site com http. Para sites WordPress existe um plugin que resolve isso chamado Really Simple SSL. Se quiser encontrá-lo mais facilmente entre no painel admin do WordPress e clique em Adicionar Novo Plugin e na aba Favoritos digite “fatorbinario“, isso irá exibir todos os plugins que marquei como favoritos no WordPress.org. Instale o plugin e ative-o. Por último será exibida uma mensagem no topo da tela com um botão azul de “Go ahead, activate SSL!“, clique nele e pronto.
Para saber como forçar o SSL em todas as páginas usando outros CMS ou até mesmo para sites em PHP deixe um comentário.