HTTP naar HTTPS omleiden met .htaccess (301-redirect)

Gepubliceerd op Bijgewerkt op 4 min leestijd

Komen bezoekers nog steeds op de onversleutelde pagina terecht? Met een paar regels in het .htaccess-bestand stuurt u elke HTTP-aanroep via een 301-redirect permanent door naar HTTPS.

Uw server serveert de website al via HTTPS, maar bezoekers komen nog steeds op de onversleutelde HTTP-versie terecht? Dan ontbreekt er een doorverwijzing. In deze handleiding richt u met een .htaccess-bestand een permanente redirect (statuscode 301) van HTTP naar HTTPS in.

Een 301-redirect is ook vanuit SEO-oogpunt de juiste keuze: zoekmachines dragen daarmee de rankings van het oude HTTP-adres over op het HTTPS-adres, in plaats van beide varianten als aparte pagina's te behandelen.

Vereisten

  • Op uw server draait Apache. Voor nginx geldt een andere configuratie, daarover verderop meer.
  • Er is al een geldig SSL-certificaat ingericht. Is dat nog niet zo, dan vindt u de bijbehorende handleiding in het artikel Gratis SSL-certificaat met Let's Encrypt instellen.
  • U hebt toegang tot de webmap van uw server, via SSH of via FTP.

Belangrijk: richt de doorverwijzing pas in wanneer HTTPS werkt. Anders stuurt u bezoekers door naar een adres dat een certificaatwaarschuwing toont.

mod_rewrite activeren en .htaccess toestaan

De doorverwijzing maakt gebruik van de Apache-module mod_rewrite. Activeer die en herstart Apache:

a2enmod rewrite
systemctl restart apache2

Apache leest het .htaccess-bestand alleen wanneer de VirtualHost dat toestaat. Controleer in de configuratie onder /etc/apache2/sites-available/ of voor uw map AllowOverride All is ingesteld:

<Directory /var/www/MijnDomein.nl>
    AllowOverride All
    Require all granted
</Directory>

Staat daar AllowOverride None, dan wordt uw .htaccess-bestand stilzwijgend genegeerd. Na een wijziging in het VirtualHost-bestand is een herstart van Apache nodig.

Het .htaccess-bestand aanmaken

Ga naar de map waarin uw website staat:

cd /var/www/<UW-WEBMAP>

Open het .htaccess-bestand in de editor. Bestaat het nog niet, dan maakt het commando het aan:

nano .htaccess

Voer de volgende regels in. Deze variant controleert rechtstreeks of de verbinding versleuteld is en hangt het volledige opgevraagde pad achter het doeladres:

RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

Sla het bestand op met "CTRL + X", daarna "Y" en "Enter".

Alternatief via de serverpoort

Op oudere configuraties, waarin de variabele HTTPS niet wordt gezet, werkt in plaats daarvan het uitlezen van de poort:

RewriteEngine On
RewriteCond %{SERVER_PORT} !^443$
RewriteRule (.*) https://%{HTTP_HOST}/$1 [R=301,L]

Variant achter een reverse proxy of load balancer

Staat er voor uw Apache een reverse proxy of een load balancer die de versleuteling zelf afhandelt, dan komt het verzoek onversleuteld bij Apache binnen. De bovenstaande regel zou dan eindeloos blijven doorverwijzen. Lees in dat geval de header uit die de proxy meestuurt:

RewriteEngine On
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

Doorverwijzing testen

Roep uw domein in de browser op via http://. U zou meteen op https:// moeten belanden. Op de commandoregel controleert u de statuscode direct:

curl -I http://MijnDomein.nl

In de uitvoer moet HTTP/1.1 301 Moved Permanently staan, plus een Location-regel met het HTTPS-adres. Verschijnt in plaats daarvan statuscode 302, controleer dan of R=301 werkelijk in de rewriteregel staat.

HSTS activeren (optioneel)

Met HTTP Strict Transport Security draagt u de browser op om uw domein voortaan helemaal niet meer via HTTP te benaderen. Daarmee vervalt de eerste onbeveiligde aanroep. Activeer eerst de benodigde module:

a2enmod headers
systemctl restart apache2

Vervolgens vult u het .htaccess-bestand aan met:

<IfModule mod_headers.c>
    Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
</IfModule>

Houd er rekening mee: HSTS legt u een jaar lang vast. Zolang de waarde in de browser is opgeslagen, is het domein niet meer via HTTP bereikbaar. Zet de header pas wanneer HTTPS betrouwbaar draait en ook alle subdomeinen een geldig certificaat hebben.

Veelvoorkomende fouten

  • Eindeloze lus ("too many redirects"): bijna altijd het gevolg van een proxy die ervoor is geschakeld. Gebruik de variant met X-Forwarded-Proto.
  • Er gebeurt niets: ofwel is mod_rewrite niet actief, ofwel staat de VirtualHost geen .htaccess-bestand toe (AllowOverride None).
  • Fout 500 na het opslaan: een typefout in het .htaccess-bestand. De precieze reden staat in het foutlogbestand van Apache onder /var/log/apache2/error.log.
  • Gemengde inhoud: de pagina laadt weliswaar via HTTPS, maar haalt afbeeldingen of scripts nog via HTTP binnen. Pas die adressen aan in uw broncode of in de database.
  • Bestand wordt niet gevonden: het .htaccess-bestand begint met een punt en is daardoor verborgen. Met ls -la ziet u het staan.

Doorverwijzing zonder .htaccess

Een .htaccess-bestand wordt bij elk afzonderlijk verzoek opnieuw ingelezen. Hebt u toegang tot de serverconfiguratie, dan is het sneller om de regels rechtstreeks in de VirtualHost vast te leggen. Voor de HTTP-VirtualHost volstaat dan:

<VirtualHost *:80>
    ServerName MijnDomein.nl
    Redirect permanent / https://MijnDomein.nl/
</VirtualHost>

Gebruikt u nginx in plaats van Apache, dan bestaan er geen .htaccess-bestanden. Daar zet u de doorverwijzing in het serverblok voor poort 80:

server {
    listen 80;
    server_name MijnDomein.nl www.MijnDomein.nl;
    return 301 https://$host$request_uri;
}

Veelgestelde vragen

Waarom een 301-redirect en geen 302?
301 staat voor een permanente doorverwijzing. Zoekmachines dragen daarmee de waardering van het bestaande HTTP-adres over op het HTTPS-adres. Een 302 geldt als tijdelijk en geeft die signalen niet door.
Mijn .htaccess-bestand wordt genegeerd. Hoe komt dat?
Ofwel is mod_rewrite niet geactiveerd, ofwel staat de VirtualHost geen overrides toe. Stel voor uw map AllowOverride All in en herstart Apache daarna.
Waarom kom ik in een eindeloze lus terecht?
Dat gebeurt vrijwel altijd wanneer een reverse proxy of load balancer voor Apache de versleuteling afhandelt. Lees in dat geval de header X-Forwarded-Proto uit in plaats van de variabele HTTPS.
Werkt dit ook met nginx?
Nee, nginx kent geen .htaccess-bestanden. Daar zet u de doorverwijzing rechtstreeks in het serverblok voor poort 80, met de regel return 301 https://$host$request_uri.
Moet ik daarnaast HSTS activeren?
HSTS verhoogt de veiligheid, maar legt u voor de ingestelde looptijd vast. Activeer het pas wanneer HTTPS op het domein en op alle subdomeinen betrouwbaar werkt.

.htaccess Omleiding 301-redirect HTTPS Apache mod_rewrite HSTS