Nginx HTTP not redirecting to HTTPS 400 Bad Request "The plain HTTP request was sent to HTTPS port"

Omair Nabiel picture Omair Nabiel · Mar 6, 2019 · Viewed 9.3k times · Source

I'm running nginx in docker. HTTPS works fine but when I explicitly make HTTP request I get the following error

400 Bad Request The plain HTTP request was sent to HTTPS port

nginx.conf is as follows

worker_processes auto ;          
events {}

http {

include /etc/nginx/mime.types;

access_log /var/log/nginx/main.access.log;                                           

server {    
listen 80;                                                                                                       
location / {
    return 301 https://localhost:3000$request_uri; 
}

}

server {   
listen 443 ssl;                                                      
server_name  localhost:3000;                  
 root    /var/www/html; 

ssl_certificate         /etc/nginx/ssl/cert.pem; 
ssl_certificate_key     /etc/nginx/ssl/key.pem;

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DH+3DES:!ADH:!AECDH:!MD5;

location / {
try_files  $uri /index.html;        
}

}

}

I run this container using

docker run -p 3000:443 -it -d --name nginxtest nginx-test

and get the following error

docker file is as follows

FROM nginx:latest
COPY ./build /var/www/html
COPY ./nginx.conf /etc/nginx/nginx.conf
COPY ./ssl /etc/nginx/ssl
EXPOSE 443
CMD [ "nginx","-g","daemon off;" ]

Weird thing is that sometimes it works perfectly fine, and all of a sudden it stops working and won't even work if I recreate the containers.

Even tried doing the following. Still no luck

 server {    
    listen 80;                                                                                                       
     server_name localhost:3000
        return 301 https://localhost:3000$request_uri; 
    }

Another odd thing when I run the following docker command

docker run -p 3000:443 -p 3001:80 -it -d --name nginxtest nginx-test

and go to localhost:3001 it redirects me to https just fine but other things do break. Sorry for the long question

Answer

Yarimadam picture Yarimadam · Mar 6, 2019

Put the following directive to the server block where you listen for port 443.

error_page 497 https://$host:$server_port$request_uri;

This directive implies that when "The plain HTTP request was sent to HTTPS port" happens, redirect it to https version of current hostname, port and URI.

Kinda hacky but works.