The plain http request was sent to https port как исправить

I’m running a Sinatra app behind passenger/nginx. I’m trying to get it to respond to both http and https calls. The problem is, when both are defined in the server block https calls are responded to normally but http yields a 400 “The plain HTTP request was sent to HTTPS port” error. This is for a static page so I’m guessing Sinatra has nothing to do with this. Any ideas on how to fix this?

Here’s the server block:

server {
        listen 80;
        listen 443  ssl;
        server_name localhost;
        root /home/myhome/app/public;
        passenger_enabled on;

        ssl on;
        ssl_certificate      /opt/nginx/ssl_keys/ssl.crt;
        ssl_certificate_key  /opt/nginx/ssl_keys/ssl.key;
        ssl_protocols        SSLv3 TLSv1;
        ssl_ciphers          HIGH:!aNULL:!MD5;

        location /static {
            root  /home/myhome/app/public;
            index  index.html index.htm index.php;
        }

        error_page 404 /404.html;

        # redirect server error pages to the static page /50x.html
        error_page 500 /500.html;

        access_log /home/myhome/app/logs/access.log;
        error_log /home/myhome/app/logs/error.log;
}

asked Jan 7, 2012 at 10:21

Johnny's user avatar

2

I ran into a similar problem. It works on one server and does not on another server with same Nginx configuration. Found the the solution which is answered by Igor here http://forum.nginx.org/read.php?2,1612,1627#msg-1627

Yes. Or you may combine SSL/non-SSL servers in one server:

server {
  listen 80;
  listen 443 default ssl;

  # ssl on   - remember to comment this out

}

Niyaz's user avatar

Niyaz

53.7k55 gold badges150 silver badges182 bronze badges

answered Jan 10, 2012 at 22:53

bobojam's user avatar

bobojambobojam

2,4251 gold badge15 silver badges7 bronze badges

8

The above answers are incorrect in that most over-ride the ‘is this connection HTTPS’ test to allow serving the pages over http irrespective of connection security.

The secure answer using an error-page on an NGINX specific http 4xx error code to redirect the client to retry the same request to https. (as outlined here https://serverfault.com/questions/338700/redirect-http-mydomain-com12345-to-https-mydomain-com12345-in-nginx )

The OP should use:

server {
  listen        12345;
  server_name   php.myadmin.com;

  root         /var/www/php;

  ssl           on;

  # If they come here using HTTP, bounce them to the correct scheme
  error_page 497 https://$server_name:$server_port$request_uri;

  [....]
}

kaiser's user avatar

kaiser

21.6k16 gold badges87 silver badges109 bronze badges

answered Sep 26, 2012 at 21:04

Michael J. Evans's user avatar

3

The error says it all actually. Your configuration tells Nginx to listen on port 80 (HTTP) and use SSL. When you point your browser to http://localhost, it tries to connect via HTTP. Since Nginx expects SSL, it complains with the error.

The workaround is very simple. You need two server sections:

server {
  listen 80;

  // other directives...
}

server {
  listen 443;

  ssl on;
  // SSL directives...

  // other directives...
}

answered Jan 7, 2012 at 16:36

Alexander Azarov's user avatar

Alexander AzarovAlexander Azarov

12.9k2 gold badges49 silver badges54 bronze badges

1

According to wikipedia article on status codes. Nginx has a custom error code when http traffic is sent to https port(error code 497)

And according to nginx docs on error_page, you can define a URI that will be shown for a specific error.
Thus we can create a uri that clients will be sent to when error code 497 is raised.

nginx.conf

#lets assume your IP address is 89.89.89.89 and also 
#that you want nginx to listen on port 7000 and your app is running on port 3000

server {
    listen 7000 ssl;
 
    ssl_certificate /path/to/ssl_certificate.cer;
    ssl_certificate_key /path/to/ssl_certificate_key.key;
    ssl_client_certificate /path/to/ssl_client_certificate.cer;

    error_page 497 301 =307 https://89.89.89.89:7000$request_uri;

    location / {
        proxy_pass http://89.89.89.89:3000/;

        proxy_pass_header Server;
        proxy_set_header Host $http_host;
        proxy_redirect off;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-Protocol $scheme;
    }
}

However if a client makes a request via any other method except a GET, that request will be turned into a GET. Thus to preserve the request method that the client came in via; we use error processing redirects as shown in nginx docs on error_page

And thats why we use the 301 =307 redirect.

Using the nginx.conf file shown here, we are able to have http and https listen in on the same port

Community's user avatar

answered Feb 4, 2015 at 13:56

Komu's user avatar

KomuKomu

14k2 gold badges28 silver badges22 bronze badges

2

I had the exact same issue, I have kind of the same configuration as your exemple and I got it working by removing the line :

ssl on;

To quote the doc:

If HTTP and HTTPS servers are equal, a single server that handles both HTTP and HTTPS requests may be configured by deleting the directive “ssl on” and adding the ssl parameter for *:443 port

answered Nov 22, 2012 at 16:33

Remiz's user avatar

RemizRemiz

3903 silver badges10 bronze badges

1

Here is an example to config HTTP and HTTPS in same config block with ipv6 support. The config is tested in Ubuntu Server and NGINX/1.4.6 but this should work with all servers.

server {
    # support http and ipv6
    listen 80 default_server;
    listen [::]:80 default_server ipv6only=on;

    # support https and ipv6
    listen 443 default_server ssl;
    listen [::]:443 ipv6only=on default_server ssl;

    # path to web directory
    root /path/to/example.com;
    index index.html index.htm;

    # domain or subdomain
    server_name example.com www.example.com;

    # ssl certificate
    ssl_certificate /path/to/certs/example_com-bundle.crt;
    ssl_certificate_key /path/to/certs/example_com.key;

    ssl_session_timeout 5m;

    ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers "HIGH:!aNULL:!MD5 or HIGH:!aNULL:!MD5:!3DES";
    ssl_prefer_server_ciphers on;
}

Don’t include ssl on which may cause 400 error. The config above should work for

http://example.com

http://www.example.com

https://example.com

https://www.example.com

Hope this helps!

answered Jan 1, 2016 at 4:32

Madan Sapkota's user avatar

Madan SapkotaMadan Sapkota

24.8k11 gold badges112 silver badges117 bronze badges

if use phpmyadmin add: fastcgi_param HTTPS on;

answered Mar 31, 2012 at 0:11

Rodrigo Gregorio's user avatar

Actually you can do this with:

ssl off; 

This solved my problem in using nginxvhosts; now I am able to use both SSL and plain HTTP.
Works even with combined ports.

Brad Koch's user avatar

Brad Koch

19k19 gold badges107 silver badges137 bronze badges

answered Feb 20, 2012 at 17:02

rapan iosif's user avatar

1

its error 497 and not error 400 . you can handle Error 497 like this and redirect http to https with a 301 (moved permanently) or 302 (moved temporary) like this:

error_page 497 = @foobar;

location @foobar {
return 301 https://$host:$server_port$request_uri;
}

this will redirect you to the exact url you requested but replace your request ‘http’ with ‘https’ with no error or confirm (its 301 redirect and counts as seo safe)

answered Aug 15, 2021 at 14:08

Alireza Far's user avatar

In my case my response redirected from jenkins to 443

Just added a proxy redirect in nginx configuration to make it work

proxy_redirect http://test.example.com:443/ https://test.example.com/;

answered Sep 22, 2021 at 16:59

Ishan's user avatar

IshanIshan

6501 gold badge8 silver badges19 bronze badges

In my case just those lines help me:

   if ($scheme = 'http') {
        return 301 https://$server_name$request_uri;
    }

answered Jan 16 at 8:14

Ivan's user avatar

IvanIvan

311 silver badge5 bronze badges

1

Блог «Дивасофт»

9 июня 2017, Михаил

После включение редиректа на https, в некоторых случаях появляется ошибка 400 Bad Request The plain HTTP request was sent to HTTPS port

Всё происходит из за mod_dir, он берет на себя редирект с папки без слеша на папку с слешом, но он не воспринимает “HTTPS on” как побудитель использования схемы https:// 

Что бы всё это заработало, нужно:

  • В конфигах nginx’a ничего не трогаем
    proxy_set_header       Host       $host:443;
  • В конфиге апача который отвечает за ваш домен
    Если у вас конфигурация многосайтовая – /etc/httpd/bx/conf/bx_ext_site.local.conf
    односайтовая – /etc/httpd/bx/conf/default.conf
    К названию сервера ServerName  site.local  дописываем:
    ServerName  https://site.local 

смысл следующий: http://httpd.apache.org/docs/2.2/mod/core.html#servername

Sometimes, the server runs behind a device that processes SSL, such as a reverse proxy, load balancer or SSL offload appliance. When this is the case, specify the https:// scheme and the port number to which the clients connect in the ServerName directive to make sure that the server generates the correct self-referential URLs.

Так же можно применить вот это решение Чиним ошибку 400 Bad Request с помощью mod_rpaf у BitrixEnv

In this article, we will show how to solve the “400 Bad Request: The plain HTTP request was sent to HTTPS port” in Nginx HTTP server. This error normally arises when you try to configure Nginx to handle both HTTP and HTTPS requests.

For the purpose of this guide, we are considering a scenario in which nginx is serving multiple websites implemented through server blocks (or virtual hosts in Apache) only one website uses SSL and the rest do not.

Read Also: The Ultimate Guide to Secure, Harden and Improve Performance of Nginx

We will also consider the sample SSL configuration below (we have changed the actual domain name for security reasons), which tells nginx to listen to both port 80 and 443. And all requests on HTTP should to be redirected to HTTPS by default.

Nginx Sample Configuration

server{
        listen 80;
        server_name example.com www.example.com;
        return 301 https://www.example.com$request_uri;
}
server {
        listen 443 ssl http2;
        server_name example.com www.example.com;

        root   /var/www/html/example.com/;
        index index.php index.html index.htm;

        #charset koi8-r;
        access_log /var/log/nginx/example.com/example.com_access_log;
        error_log   /var/log/nginx/example.com/example.com_error_log   error;

        # SSL/TLS configs
        ssl on;
        ssl_certificate /etc/ssl/certs/example_com_cert_chain.crt;
        ssl_certificate_key /etc/ssl/private/example_com.key;

        include /etc/nginx/ssl.d/ssl.conf;

        location / {
                try_files $uri $uri/ /index.php?$query_string;
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
                root   /var/www/html/example.com/;
        }

        # proxy the PHP scripts to Apache listening on 127.0.0.1:80
        #
        #location ~ .php$ {
        #    proxy_pass   http://127.0.0.1;
        #}

        # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
        #
        location ~ .php$ {

                root   /var/www/html/example.com/;
                fastcgi_pass   127.0.0.1:9001;
                #fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
                fastcgi_index  index.php;
                fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
                include         fastcgi_params;
                include /etc/nginx/fastcgi_params;

        }
        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        #location ~ /.ht {
        #    deny  all;
        #}
}

Using the above configuration, once a client tries to access your site via port 80 i.e http://example.com, the error in question will be displayed as in the following screen shot.

Nginx 404 Bad Request Error

Nginx 404 Bad Request Error

You encounter this error because every time a clien tries to access your site via HTTP, the request is redirected to HTTPS. It’s because the nginx expects SSL to be used in the transaction yet the original reques t(received via port 80) was plain HTTP, it complains with the error.

On the other hand, if a client uses https://example.com, they will not encounter the above error. In addition, if you have other websites configured not to use SSL, nginx will try to use HTTPS by default for them resulting to the above error.

To fix this error, comment out the line below in your configuration or set it to off.

#ssl on 
OR
ssl off

Save and close the file. Then restart the nginx service.

# systemctl restart nginx
OR
$ sudo systemctl restart nginx

This way, you can enable nginx to handle both HTTP and HTTPS requests for multiple server blocks.

Finally, below is a list of articles about setting up SSL HTTPS on common Linux distributions and FreeBSD.

  1. Setting Up HTTPS with Let’s Encrypt SSL Certificate For Nginx on RHEL/CentOS
  2. Secure Nginx with Free Let’s Encrypt SSL Certificate on Ubuntu and Debian
  3. How to Secure Nginx with SSL and Let’s Encrypt in FreeBSD

That’s all for now. If you know of any other way to solve this error, please let us know via the feedback form below.

If you read this far, tweet to the author to show them you care. Tweet a thanks

Photo of author

Aaron Kili is a Linux and F.O.S.S enthusiast, an upcoming Linux SysAdmin, web developer, and currently a content creator for TecMint who loves working with computers and strongly believes in sharing knowledge.


Each tutorial at TecMint is created by a team of experienced Linux system administrators so that it meets our high-quality standards.

When working with web servers, it’s common to encounter issues related to SSL/TLS encryption and HTTP/HTTPS ports. One such problem is when a plain HTTP request is sent to an HTTPS port, causing connection errors. This documentation will guide you through the process of resolving this issue, providing a step-by-step solution to help you get your web server running smoothly again.

Table of Contents

  1. Understanding the Issue
  2. Step-by-Step Solution
  3. FAQ
  4. Related Links

Understanding the Issue

Before diving into the solution, let’s first understand the issue at hand. When a client sends an HTTP request to a server, the server expects the request to be sent to a specific port, usually port 80 for HTTP and port 443 for HTTPS. If a plain HTTP request is sent to an HTTPS port, the server will be unable to process the request, resulting in connection errors.

This issue can occur in various scenarios, such as:

  • Incorrect server configuration, causing the server to listen on the wrong port
  • Client-side issues, where the client sends an HTTP request to an HTTPS URL
  • Network issues, such as misconfigured firewalls or proxy servers

In this guide, we will focus on resolving the issue from the server-side, which is the most common cause of the problem.

Step-by-Step Solution

To resolve the issue of plain HTTP requests being sent to an HTTPS port, follow these steps:

Step 1: Identify the Problem

First, verify that the issue is indeed due to a plain HTTP request being sent to an HTTPS port. You can use tools like SSL Labs to test your server’s SSL/TLS configuration and identify any potential issues.

Step 2: Check Server Configuration

Once you’ve confirmed the issue, check your server configuration to ensure that it is set up correctly. Specifically, verify that your server is listening on the correct ports and that the SSL/TLS configuration is accurate. This process will vary depending on your web server software. Below are links to the official documentation for some popular web servers:

  • Apache
  • Nginx
  • IIS

Step 3: Update Server Configuration

If your server configuration is incorrect, update the settings to ensure that the server is listening on the correct ports and that the SSL/TLS configuration is accurate. After making the necessary changes, restart your server.

Step 4: Test Your Server

Once your server has been restarted, test the updated configuration to ensure that the issue has been resolved. You can use tools like SSL Labs or Curl to verify that the server is now correctly handling HTTP and HTTPS requests.

FAQ

How do I know if my server is using the correct SSL/TLS configuration?

You can use tools like SSL Labs to test your server’s SSL/TLS configuration and identify any potential issues.

What is the difference between HTTP and HTTPS?

HTTP is the protocol used for transmitting data over the internet, while HTTPS is a secure version of HTTP that uses SSL/TLS encryption to protect data transmitted between the client and server.

Can I force users to use HTTPS instead of HTTP?

Yes, you can set up a server-side redirect to automatically redirect users from HTTP to HTTPS. This can be done using your web server’s configuration settings. See the following guides for more information:

  • Redirect HTTP to HTTPS in Apache
  • Redirect HTTP to HTTPS in Nginx
  • Redirect HTTP to HTTPS in IIS

What are some common causes for plain HTTP requests being sent to an HTTPS port?

Some common causes include incorrect server configuration, client-side issues, and network issues such as misconfigured firewalls or proxy servers.

How do I fix client-side issues with plain HTTP requests being sent to an HTTPS port?

If the issue is on the client-side, you may need to update your website’s code or configuration to ensure that all requests are being made over HTTPS. This can include updating links, resources, and API calls to use HTTPS instead of HTTP.

  • Mozilla: How to Fix Mixed Content
  • Let’s Encrypt: Getting Started
  • SSL Labs: SSL Server Test

Note: This guide assumes that you have already set up SSL/TLS encryption for your server. If you have not yet done so, you may want to consider using a free SSL/TLS certificate provider like Let’s Encrypt to secure your server.



Я запускаю приложение Sinatra позади passenger / nginx. Я пытаюсь заставить его отвечать на вызовы http и https. Проблема в том, что когда оба определены в серверном блоке, вызовы https отвечают нормально, но http дает ошибку 400 “простой HTTP-запрос был отправлен на порт HTTPS”. Это для статической страницы, поэтому я предполагаю, что Синатра не имеет к этому никакого отношения. Есть идеи, как это исправить?

вот блок сервера:

server {
listen 80;
listen 443 ssl;
server_name localhost;
root /home/myhome/app/public;
passenger_enabled on;

ssl on;
ssl_certificate /opt/nginx/ssl_keys/ssl.crt;
ssl_certificate_key /opt/nginx/ssl_keys/ssl.key;
ssl_protocols SSLv3 TLSv1;
ssl_ciphers HIGH:!aNULL:!MD5;

location /static {
root /home/myhome/app/public;
index index.html index.htm index.php;
}

error_page 404 /404.html;

# redirect server error pages to the static page /50x.html
error_page 500 /500.html;

access_log /home/myhome/app/logs/access.log;
error_log /home/myhome/app/logs/error.log;
}


2548  


8  

8 ответов:

я столкнулся с подобной проблемой. Он работает на одном сервере и не работает на другом сервере с той же конфигурацией Nginx. Нашел решение, на которое отвечает Игорь вот http://forum.nginx.org/read.php?2,1612, 1627#msg-1627

да. Или вы можете объединить серверы SSL / non-SSL на одном сервере:

server {
  listen 80;
  listen 443 default ssl;

  # ssl on   - remember to comment this out

}

приведенные выше ответы неверны в том, что большинство из них используют тест “is this connection HTTPS”, чтобы разрешить обслуживание страниц по http независимо от безопасности соединения.

безопасный ответ с использованием страницы ошибки на nginx специфический код ошибки http 4xx для перенаправления клиента, чтобы повторить тот же запрос на https. (как указано здесь https://serverfault.com/questions/338700/redirect-http-mydomain-com12345-to-https-mydomain-com12345-in-nginx)

ФП следует использовать:

server {
  listen        12345;
  server_name   php.myadmin.com;

  root         /var/www/php;

  ssl           on;

  # If they come here using HTTP, bounce them to the correct scheme
  error_page 497 https://$host:$server_port$request_uri;

  [....]
}

ошибка говорит все это на самом деле. Ваша конфигурация говорит Nginx прослушивать порт 80 (HTTP) и использовать SSL. Когда вы указываете свой браузер на http://localhost, он пытается подключиться через HTTP. Поскольку Nginx ожидает SSL, он жалуется на ошибку.

решение очень простое. Вам нужно два server разделы:

server {
  listen 80;

  // other directives...
}

server {
  listen 443;

  ssl on;
  // SSL directives...

  // other directives...
}

У меня была точно такая же проблема, у меня есть такая же конфигурация, как и ваш exemple, и я получил ее, удалив строку:

ssl on;

чтобы процитировать документ:

если серверы HTTP и HTTPS равны, один сервер, который обрабатывает запросы HTTP и HTTPS, может быть настроен путем удаления директивы “ssl on” и добавления параметра ssl для *:443 port

по данным статья в Википедии о кодах статуса. Nginx имеет пользовательский код ошибки при отправке http-трафика на порт https (код ошибки 497)

и по nginx docs on error_page, вы можете определить URI, который будет отображаться для конкретной ошибки.
Таким образом, мы можем создать uri, который будет отправлен клиентам при возникновении кода ошибки 497.

nginx.conf

#lets assume your IP address is 89.89.89.89 and also 
#that you want nginx to listen on port 7000 and your app is running on port 3000

server {
    listen 7000 ssl;

    ssl_certificate /path/to/ssl_certificate.cer;
    ssl_certificate_key /path/to/ssl_certificate_key.key;
    ssl_client_certificate /path/to/ssl_client_certificate.cer;

    error_page 497 301 =307 https://89.89.89.89:7000$request_uri;

    location / {
        proxy_pass http://89.89.89.89:3000/;

        proxy_pass_header Server;
        proxy_set_header Host $http_host;
        proxy_redirect off;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-Protocol $scheme;
    }
}

однако если клиент делает запрос через любой другой способ Если вам этот запрос будет сделать. Таким образом, чтобы сохранить метод запроса, который клиент пришел через; Мы используем перенаправление обработки ошибок, как показано в nginx docs on error_page

и вот почему мы используем 301 =307 редирект.

С помощью nginx.файл conf показано здесь, мы можем иметь http и https слушать на одном и том же порту

вот пример для конфигурации HTTP и HTTPS в том же блоке конфигурации с протокол IPv6 поддержка. Конфиг тестируется в Ubuntu Server и NGINX / 1.4.6 но это должно работать со всеми серверами.

server {
    # support http and ipv6
    listen 80 default_server;
    listen [::]:80 default_server ipv6only=on;

    # support https and ipv6
    listen 443 default_server ssl;
    listen [::]:443 ipv6only=on default_server ssl;

    # path to web directory
    root /path/to/example.com;
    index index.html index.htm;

    # domain or subdomain
    server_name example.com www.example.com;

    # ssl certificate
    ssl_certificate /path/to/certs/example_com-bundle.crt;
    ssl_certificate_key /path/to/certs/example_com.key;

    ssl_session_timeout 5m;

    ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers "HIGH:!aNULL:!MD5 or HIGH:!aNULL:!MD5:!3DES";
    ssl_prefer_server_ciphers on;
}

не входить ssl on что может привести к 400 ошибка. Конфигурация выше должна работать для

http://example.com

http://www.example.com

https://example.com

https://www.example.com

надеюсь, что это помогает!

Если использовать phpmyadmin добавить: fastcgi_param HTTPS on;

на самом деле вы можете сделать это с:

ssl off; 

это решило мою проблему в использовании nginxvhosts; теперь я могу использовать как SSL, так и простой HTTP.
Работает даже с комбинированными портами.

Добавить комментарий