O que é TLS/HTTPS no Apache (e o papel do mod_ssl)
HTTPS é HTTP “por dentro” de uma conexão criptografada via TLS. Na prática, o navegador (ou o curl) negocia uma sessão segura com o servidor antes de trafegar requisições HTTP. Isso protege contra interceptação e adulteração do tráfego e permite autenticar o servidor por meio de um certificado.
No Apache, o suporte a TLS normalmente é fornecido pelo módulo mod_ssl. Ele habilita o Apache a escutar em 443/tcp e a servir Virtual Hosts com diretivas como SSLEngine, SSLCertificateFile e SSLCertificateKeyFile.
Passo a passo: habilitar HTTPS em um Virtual Host
1) Habilitar o módulo SSL e o listener em 443
Em distribuições baseadas em Debian/Ubuntu, o fluxo mais comum é habilitar o módulo e o site SSL padrão (se aplicável) e garantir que o Apache esteja escutando em 443:
sudo a2enmod sslVerifique se existe um arquivo de portas com a linha de escuta em 443 (o nome pode variar conforme a distro). O essencial é haver:
Listen 443Recarregue o Apache para aplicar:
- Ouça o áudio com a tela desligada
- Ganhe Certificado após a conclusão
- + de 5000 cursos para você explorar!
Baixar o aplicativo
sudo apachectl configtest && sudo systemctl reload apache2Em RHEL/CentOS/Rocky/Alma, o módulo costuma vir como pacote separado (mod_ssl) e a configuração padrão já inclui o listener. O ponto-chave é: o Apache precisa ter o módulo SSL carregado e estar escutando em 443.
2) Criar um certificado autoassinado (laboratório)
Para laboratório/testes internos, um certificado autoassinado é suficiente. Ele não será “confiável” para navegadores por padrão, mas permite validar a configuração TLS.
Crie um diretório para armazenar chave/cert (ajuste conforme seu padrão):
sudo install -d -m 0755 /etc/apache2/sslGere chave privada e certificado autoassinado (válido por 365 dias). Substitua o CN pelo nome que você usará para acessar (ex.: site1.local ou um FQDN real):
sudo openssl req -x509 -nodes -newkey rsa:2048 -days 365 \
-keyout /etc/apache2/ssl/site1.key \
-out /etc/apache2/ssl/site1.crt \
-subj "/C=BR/ST=SP/L=SaoPaulo/O=Lab/OU=Apache/CN=site1.local"Ajuste permissões: a chave privada deve ser legível apenas por root (o Apache lê a chave ao iniciar/recarregar como root e depois faz drop de privilégios):
sudo chmod 600 /etc/apache2/ssl/site1.key
sudo chmod 644 /etc/apache2/ssl/site1.crtSe você quiser evitar alerta de “nome não corresponde”, inclua Subject Alternative Name (SAN). Um jeito simples é usar um arquivo de configuração do OpenSSL. Exemplo (crie /tmp/site1-openssl.cnf):
[req]
distinguished_name=req_distinguished_name
x509_extensions=v3_req
prompt=no
[req_distinguished_name]
C=BR
ST=SP
L=SaoPaulo
O=Lab
OU=Apache
CN=site1.local
[v3_req]
subjectAltName=@alt_names
[alt_names]
DNS.1=site1.local
DNS.2=www.site1.localGere novamente usando esse arquivo:
sudo openssl req -x509 -nodes -newkey rsa:2048 -days 365 \
-keyout /etc/apache2/ssl/site1.key \
-out /etc/apache2/ssl/site1.crt \
-config /tmp/site1-openssl.cnf3) Criar/ajustar o Virtual Host em 443 com mod_ssl
Agora crie um vhost SSL (arquivo e caminho variam por distro). O essencial é que exista um bloco <VirtualHost *:443> com TLS habilitado e apontando para o certificado e a chave.
<VirtualHost *:443>
ServerName site1.local
# (Opcional) ServerAlias www.site1.local
DocumentRoot /var/www/site1/public
SSLEngine on
SSLCertificateFile /etc/apache2/ssl/site1.crt
SSLCertificateKeyFile /etc/apache2/ssl/site1.key
# Boas práticas básicas (ajuste conforme sua política/compatibilidade)
SSLProtocol -all +TLSv1.2 +TLSv1.3
# Ciphers: em TLS 1.3 a seleção é diferente e geralmente não depende desta lista.
# Para TLS 1.2, use um conjunto moderno e evite suites fracas.
SSLCipherSuite HIGH:!aNULL:!MD5:!3DES:!RC4
SSLHonorCipherOrder on
# (Opcional) Ajuda a depurar qual vhost respondeu
Header always set X-Served-By "site1-https"
ErrorLog ${APACHE_LOG_DIR}/site1-ssl-error.log
CustomLog ${APACHE_LOG_DIR}/site1-ssl-access.log combined
</VirtualHost>Observações importantes:
SSLEngine onativa TLS naquele vhost.SSLCertificateFileaponta para o certificado (público).SSLCertificateKeyFileaponta para a chave privada correspondente.SSLProtocolaqui desabilita protocolos legados e habilita apenas TLS 1.2 e 1.3 (boa linha de base). Se você precisa suportar clientes muito antigos, isso pode exigir ajustes — mas evite TLS 1.0/1.1 quando possível.
Se você usar diretivas de Header (como no exemplo), garanta que o módulo de headers esteja habilitado:
sudo a2enmod headersAtive o site (Debian/Ubuntu) e recarregue:
sudo a2ensite site1-ssl
sudo apachectl configtest && sudo systemctl reload apache2Checagens de segurança iniciais
1) Redirecionar HTTP → HTTPS
Uma prática inicial importante é garantir que quem acessar em HTTP seja redirecionado para HTTPS. Faça isso no vhost de porta 80 do mesmo site (não no de 443).
<VirtualHost *:80>
ServerName site1.local
# (Opcional) ServerAlias www.site1.local
# Redireciona tudo para HTTPS
Redirect permanent / https://site1.local/
ErrorLog ${APACHE_LOG_DIR}/site1-error.log
CustomLog ${APACHE_LOG_DIR}/site1-access.log combined
</VirtualHost>Alternativa mais flexível (preserva host e URI) usando mod_rewrite:
RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]Se usar rewrite, habilite o módulo:
sudo a2enmod rewrite2) Evitar protocolos legados (quando aplicável)
Em nível básico, a linha abaixo já cobre a maior parte dos cenários modernos:
SSLProtocol -all +TLSv1.2 +TLSv1.3Se você estiver em um ambiente com OpenSSL/Apache mais antigos que não suportam TLS 1.3, mantenha pelo menos TLS 1.2:
SSLProtocol -all +TLSv1.2Evite reabilitar TLS 1.0/1.1 a menos que exista uma exigência real e temporária, pois reduz a segurança e pode causar alertas em scanners e navegadores.
Como validar a configuração (navegador e curl)
1) Validar no navegador
Acesse https://site1.local. Com certificado autoassinado, o navegador exibirá um aviso de segurança. Para laboratório, você pode prosseguir e então checar:
- Se o cadeado aparece (após aceitar a exceção).
- Se o certificado exibido corresponde ao CN/SAN esperado.
- Se o redirecionamento de
http://site1.localpara HTTPS ocorre.
2) Validar com curl (incluindo certificado autoassinado)
Verifique o redirecionamento HTTP → HTTPS:
curl -I http://site1.localVocê deve ver um 301/302 com Location: https://....
Verifique a resposta em HTTPS. Como é autoassinado, use -k (inseguro, apenas para laboratório) para ignorar validação:
curl -k -I https://site1.localSe você adicionou o header de depuração, confirme qual vhost respondeu:
curl -k -I https://site1.local | grep -i x-served-byPara inspecionar o handshake e o certificado apresentado:
openssl s_client -connect site1.local:443 -servername site1.local -showcertsProcure por:
Protocol : TLSv1.2ouTLSv1.3Cipher :com uma suite moderna- O certificado exibido e o
subject/issuer
Como confirmar qual Virtual Host está atendendo na porta 443
1) Conferir o mapeamento de vhosts carregados
Use o comando do Apache que lista os vhosts e suas portas. Ele ajuda a identificar qual arquivo define o vhost em *:443 e qual é o “default” para aquela porta:
sudo apachectl -SNa saída, observe as entradas relacionadas a *:443. O Apache escolhe o vhost por SNI (nome do host no TLS) quando há múltiplos vhosts em 443. Se o cliente não enviar SNI (raro hoje), o primeiro vhost definido para 443 tende a virar o default.
2) Testar SNI explicitamente (quando há múltiplos sites em 443)
Se você tem mais de um vhost SSL, valide qual certificado/vhost é servido para cada nome usando -servername:
openssl s_client -connect 127.0.0.1:443 -servername site1.local | openssl x509 -noout -subject -issuerRepita para outro hostname e compare o subject. Isso confirma se o SNI está direcionando para o vhost correto.
3) Confirmar via header de identificação (técnica de laboratório)
Durante configuração, é comum inserir temporariamente um header diferente em cada vhost SSL para confirmar roteamento:
Header always set X-VHost "site1-443"Então:
curl -k -I https://site1.local | grep -i x-vhostRemova esse header quando terminar a validação para não expor detalhes desnecessários.
Checklist rápido de troubleshooting (quando não abre HTTPS)
| Sintoma | Verificação objetiva | Ação típica |
|---|---|---|
| Conexão recusada em 443 | ss -lntp | grep :443 | Garantir Listen 443, módulo SSL habilitado e serviço ativo |
| Erro ao recarregar Apache | apachectl configtest e journalctl -u apache2/httpd | Corrigir caminho/permissões de .key/.crt e sintaxe do vhost |
| Certificado “não corresponde ao nome” | Ver SAN/CN no certificado | Gerar certificado com SAN correto para o hostname usado |
| Vhost errado em 443 | apachectl -S e teste com openssl s_client -servername | Ajustar ordem/definições e garantir ServerName correto em cada vhost |