0

I have ElasticSearch and NGINX set up on my server. Accessing it via SSL is failing.

I can access ElasticSearch fine via:
http://ipaddress:9200
http://mydomain.co.uk:9200

The domain was then set up with an SSL letsencrypt cert.
https://mydomain.co.uk - loads fine
https://mydomain.co.uk:9200 - does not load

This site can’t provide a secure connection
mydomain.co.uk sent an invalid response.
ERR_SSL_PROTOCOL_ERROR

Based on this response, I think NGINX is not letting any traffic through to that port.

  • No server firewall enabled.
  • Digital ocean firewall enabled but port and my IP address is whitelisted.
  • As it mentions, seems more of an SSL misconfiguration issue (or lack of).

Here is my nginx conf for mydomain.co.uk

server {

  root /var/www/mydomain.co.uk/html;
  index index.html index.htm index.nginx-debian.html;

  server_name mydomain.co.uk www.mydomain.co.uk;

  location / {
    try_files $uri $uri/ =404;
  }

  listen [::]:443 ssl ipv6only=on; # managed by Certbot
  listen 443 ssl; # managed by Certbot
  ssl_certificate /etc/letsencrypt/live/mydomain.co.uk/fullchain.pem; # managed by Certbot
  ssl_certificate_key /etc/letsencrypt/live/mydomain.co.uk/privkey.pem; # managed by Certbot
  include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
  ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}

server {
  if ($host = www.mydomain.co.uk) {
    return 301 https://$host$request_uri;
  } # managed by Certbot

  if ($host = mydomain.co.uk) {
    return 301 https://$host$request_uri;
  } # managed by Certbot

  listen 80;
  listen [::]:80;

  server_name mydomain.co.uk www.mydomain.co.uk;
  return 404; # managed by Certbot
}

My attempts to resolve:

#1

listen 443 ssl;
listen 9200 ssl;

#2

listen 443 9200 ssl;

#3 I duplicated the 443 server block and changed to 9200.

server {

  root /var/www/mydomain.co.uk/html;
  index index.html index.htm index.nginx-debian.html;

  server_name mydomain.co.uk www.mydomain.co.uk;

  location / {
    try_files $uri $uri/ =404;
  }

  listen [::]:9200 ssl ipv6only=on; # managed by Certbot
  listen 9200 ssl; # managed by Certbot
  ssl_certificate /etc/letsencrypt/live/mydomain.co.uk/fullchain.pem; # managed by Certbot
  ssl_certificate_key /etc/letsencrypt/live/mydomain.co.uk/privkey.pem; # managed by Certbot
  include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
  ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}

After every attempt I refreshed nginx and it failed:

Job for nginx.service failed because the control process exited with error code.
See "systemctl status nginx.service" and "journalctl -xe" for details.

It's the default port for ElasticSearch so I presume that handles it to some extent. When I first added ES I had to go in this file and uncomment http.port: 9200

/etc/elasticsearch/elasticsearch.yml

#
# Set the bind address to a specific IP (IPv4 or IPv6):
#
network.host: 206.189.29.75
#
# Set a custom port for HTTP:
#
http.port: 9200 
wharfdale
  • 151
  • 8
  • I've done the same a few years back, but then your 3rd method was the solution. Can you try it wihtou listening on IPv6 (without `listen [::]:9200 ssl ipv6only=on`) only with `listen 9200;` (no need the ssl) – Bert Sep 25 '20 at 08:44
  • @Bert - Tried attempt #3 again with the ipv6 line removed and port 9200, no luck. `nginx -t` comes back as ok but when restarting nginx I get the same `nginx.service` failed message. – wharfdale Sep 25 '20 at 08:54
  • Can you show us the log of NginX? A `systemctl status nginx` woud be nice too. – Bert Sep 25 '20 at 08:55
  • 1
    I'd guess that ES is still listening on port 9200 and nginx can't bind to it? configure ES such that is listens on localhost:19200 for example and then proxy from nginx to that address. – Phillip -Zyan K Lee- Stockmann Sep 25 '20 at 08:56
  • Oh sh*t, Phillip is right. If EL is listening on 9200, then you'll never be able to do what you want to do this way. What you need is a new location and proxy_pass it to 9200. – Bert Sep 25 '20 at 08:58
  • 1
    just because I'm nice: how do you ensure noone messes with your elasticsearch? it seems to me like you are opening it up to the world - which is a really BAAAAAD idea if it's not going to be secured by some authentication mechanism. – Phillip -Zyan K Lee- Stockmann Sep 25 '20 at 09:00
  • 1
    I'm going down the "get it working first" approach. This is purely development for now then I'll secure. But also I am using DigitalOcean firewall to prevent any access to the IP/Port if not whitelisted. – wharfdale Sep 25 '20 at 09:01
  • @Bert - Would I need to create a new `server {` block still too or a `location {` block inside the top `server {` block which has 443 inside. – wharfdale Sep 25 '20 at 09:03

1 Answers1

1

An example NginX config would be like this:

server  {
    listen  80;
 
    server_name mydomain.co.uk;
 
    return 301  https://mydomain.co.uk$request_uri;
}

server {
        listen  443 ssl;

        server_name     mydomain.co.uk;
        root            /var/www/mydomain.co.uk/html;

        error_log       /var/log/nginx/mydomain.co.uk/error.log;
        access_log      /var/log/nginx/mydomain.co.uk/access.log;

        ssl_certificate         /etc/letsencrypt/live/mydomain.co.uk/fullchain.pem;
        ssl_certificate_key     /etc/letsencrypt/live/mydomain.co.uk/privkey.pem;
        ssl_protocols TLSv1.3;
        ssl_prefer_server_ciphers on;
        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:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-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;
        add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";
        ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

        client_max_body_size 20M;

        index           index.html index.htm index.nginx-debian.html;

        location / {
                try_files $uri $uri/ =404;
        }

        location /el {
                proxy_pass http://ipaddress:9200;
        }
}

I think this could work. Could you test it?

Bert
  • 984
  • 1
  • 11
  • 29
  • I made one change which is to use `/` instead of `/el,` else ElasticSearch thinks I am searching for the word `el`. So, now mydomain.co.uk displays the default ES page on https which is amazing! One final thing but this is a little more specific to my set up to be fair. You can go to `https://mydomain.co.uk` fine, but requests from my site are sending to: `https://mydomain.co.uk:9200` (because I use the ElasticPress plugin which forwards requests to the defined ES server) which then return: `POST https://mydomain.co.uk:9200/ net::ERR_SSL_PROTOCOL_ERROR` – wharfdale Sep 25 '20 at 09:25
  • Keep the proxy_pass to HTTP and not HTTPS. Your ES have no clue about the SSL, thus it reports an error when the communication is sent to it via SSL. – Bert Sep 25 '20 at 10:14