Certain websites are showing the wrong SSL certificate for both my EndevourOS systems

I am using a Debian server to run multiple web services. The problem is that some of the webpages show the wrong SSL certificate and redirect me to a webpage that isn’t the correct one. This only happens on my EndevourOS systems. My phone and my windows computer can access the webpages with the correct certificate.
Both of the following websites when I access them these systems, they don’t take me to the landing pages.
https://atuin.tuxtower.net/
https://immich.tuxtower.net/

But this service which I have also set up with similiar nginx configs works just fine:
https://picoshare.tuxtower.net

this is the curl results when for each website:

❯ curl https://atuin.tuxtower.net        
curl: (60) SSL: no alternative certificate subject name matches target host name 'atuin.tuxtower.net'
More details here: https://curl.se/docs/sslcerts.html

curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.
❯ curl https://immich.tuxtower.net
curl: (60) SSL: no alternative certificate subject name matches target host name 'immich.tuxtower.net'
More details here: https://curl.se/docs/sslcerts.html

curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.
❯ curl https://picoshare.tuxtower.net 

  <!DOCTYPE html>
  <html lang="en">
    <head>
      <meta charset="utf-8" />
      <meta http-equiv="X-UA-Compatible" content="IE=edge" />
      <meta name="viewport" content="width=device-width,initial-scale=1.0" />
      <title>PicoShare</title>
      <link
        rel="stylesheet"
        type="text/css"
        href="/third-party/bulma@0.9.3/bulma.min.css"
      />
      <link href="/third-party/fontawesome6/css/all.min.css" rel="stylesheet" />
      <link rel="stylesheet" type="text/css" href="/css/style.css" />
      

      <script type="module" src="/js/navbar.js"></script>
      

      <link
        rel="apple-touch-icon"
        sizes="180x180"
        href="/apple-touch-icon.png"
      />
      <link
        rel="icon"
        type="image/png"
        sizes="32x32"
        href="/favicon-32x32.png"
      />
      <link
        rel="icon"
        type="image/png"
        sizes="16x16"
        href="/favicon-16x16.png"
      />
      <link rel="manifest" href="/site.webmanifest" />
      <link rel="mask-icon" href="/safari-pinned-tab.svg" color="#5bbad5" />
      <meta name="msapplication-TileColor" content="#da532c" />
      <meta name="theme-color" content="#ffffff" />
    </head>

    <body>
      

      <template id="snackbar-notifications-template">
  <style nonce="YJkt&#43;VbDT/HaAq1Y3VmjIQ==">
    #notifications {
      position: fixed;
      bottom: 0px;
      left: 50%;
      transform: translate(-50%, 0);
    }

    .notification {
      background-color: #3488ce;
      font-weight: 600;
      margin-bottom: 0.5rem;
      color: #fff;
      text-align: center;
      border-radius: 2px;
      padding: 1rem;
      animation: fadein 0.5s, fadeout 0.5s 2.5s;
    }

    @keyframes fadein {
      from {
        bottom: 0;
        opacity: 0;
      }
      to {
        bottom: 30px;
        opacity: 1;
      }
    }

    @keyframes fadeout {
      from {
        bottom: 30px;
        opacity: 1;
      }
      to {
        bottom: 0;
        opacity: 0;
      }
    }
  </style>
  <div id="notifications"></div>
</template>

<script type="module" nonce="YJkt&#43;VbDT/HaAq1Y3VmjIQ==">
  (function () {
    const template = document.querySelector("#snackbar-notifications-template");

    customElements.define(
      "snackbar-notifications",
      class extends HTMLElement {
        connectedCallback() {
          this.attachShadow({ mode: "open" }).appendChild(
            template.content.cloneNode(true)
          );
        }

        addInfoMessage(message) {
          const notificationEl = document.createElement("div");

          this.shadowRoot
            .getElementById("notifications")
            .append(notificationEl);
          notificationEl.innerText = message;
          notificationEl.classList.add("notification");

          setTimeout(() => {
            notificationEl.remove();
          }, 3000);
        }
      }
    );
  })();
</script>


      
  <nav class="navbar" role="navigation">
    <div class="container">
      <div class="navbar-brand">
        <a class="navbar-item" href="/">PicoShare</a>
        <a
          role="button"
          class="navbar-burger"
          aria-label="menu"
          aria-expanded="false"
          data-target="navbar-links"
        >
          <span aria-hidden="true"></span>
          <span aria-hidden="true"></span>
          <span aria-hidden="true"></span>
        </a>
      </div>
      <div id="navbar-links" class="navbar-menu">
        
        <div class="navbar-end">
          
            <div class="navbar-item">
              <a class="button is-primary" role="menuitem" href="/login">
                Log In
              </a>
            </div>
          
        </div>
      </div>
    </div>
  </nav>



      <div class="content container">
        
  <h1 class="title">What is PicoShare?</h1>

  <p>PicoShare is a service for sharing images, videos, and other files.</p>

  <p>
    On PicoShare, only <i>you</i> can upload files. You can share links to those
    files with anyone, and they never have to sign up for an account.
  </p>

  <p>PicoShare puts you fully in control, which means:</p>

  <ul>
    <li>
      You can share direct download links without forcing your guests to see ads
      or prompts to sign up for an account.
    </li>
    <li>There are no restrictions on file type, size, or content.</li>
    <li>PicoShare never resizes or re-encodes your media files.</li>
    <li>
      PicoShare preserves the original filename and metadata for your files.
    </li>
  </ul>

  <p>
    PicoShare is easy to self-host. See our
    <a href="https://github.com/mtlynch/picoshare">source repo</a> for details.
  </p>

  <p>
    PicoShare is written by <a href="https://mtlynch.io">Michael Lynch</a> and
    licensed under the open-source
    <a href="https://www.gnu.org/licenses/agpl-3.0.en.html">AGPLv3 license</a>.
  </p>

      </div>

      <snackbar-notifications></snackbar-notifications>
    </body>
  </html>

I want to believe that I’ve set everything up correctly on the server because every other device I use and have tested can access these webpages so I think there is something wrong with the way endevouros is configured. How would I fix this issue?

I am able to at least confirm no issue here with either of those domains, under Endeavour OS. Tested with browser and curl.

There’s a couple of things that come to mind here.

On your Endeavour OS systems:

  • Are you using VPN and/or secure DNS service?
  • Is the date and time correct on your web server, and Endeavour OS systems?

Also, try curl with verbose argument, and note what it says under subjectAltName, which is where it seems to be throwing the error.

$ curl -v https://atuin.tuxtower.net

* Server certificate:
*  subject: CN=atuin.tuxtower.net
*  start date: May  9 01:39:00 2024 GMT
*  expire date: Aug  7 01:38:59 2024 GMT
*  subjectAltName: host "atuin.tuxtower.net" matched cert's "atuin.tuxtower.net"

This is what it looks like when it doesn’t fail.

this is what my verbose curl looks like

❯ curl -v https://atuin.tuxtower.net
* Host atuin.tuxtower.net:443 was resolved.
* IPv6: fde4:1d15:8139:0:3697:f6ff:fe8d:372f
* IPv4: 203.59.234.109
*   Trying [fde4:1d15:8139:0:3697:f6ff:fe8d:372f]:443...
* Connected to atuin.tuxtower.net (fde4:1d15:8139:0:3697:f6ff:fe8d:372f) port 443
* ALPN: curl offers h2,http/1.1
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
*  CAfile: /etc/ssl/certs/ca-certificates.crt
*  CApath: none
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384 / x25519 / RSASSA-PSS
* ALPN: server accepted h2
* Server certificate:
*  subject: CN=jellyfin.tuxtower.net
*  start date: Mar 31 17:59:58 2024 GMT
*  expire date: Jun 29 17:59:57 2024 GMT
*  subjectAltName does not match host name atuin.tuxtower.net
* SSL: no alternative certificate subject name matches target host name 'atuin.tuxtower.net'
* Closing connection
* TLSv1.3 (OUT), TLS alert, close notify (256):
curl: (60) SSL: no alternative certificate subject name matches target host name 'atuin.tuxtower.net'
More details here: https://curl.se/docs/sslcerts.html

curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.

I’m not using a vpn or DNS service, I think im just using the defaults.

The date and time i believe is set up correctly on my endevouros system. Here is my timedatectl:

~                                                                    adamw@adamDesktopLinux
❯ timedatectl status      
               Local time: Thu 2024-05-09 12:21:25 AWST
           Universal time: Thu 2024-05-09 04:21:25 UTC
                 RTC time: Thu 2024-05-09 04:21:25
                Time zone: Australia/Perth (AWST, +0800)
System clock synchronized: yes
              NTP service: active
          RTC in local TZ: no

here is the tuxtower server

adamw@TuxTower ~
❯ timedatectl status   
               Local time: Thu 2024-05-09 12:22:27 AWST
           Universal time: Thu 2024-05-09 04:22:27 UTC
                 RTC time: Thu 2024-05-09 04:22:27
                Time zone: Australia/Perth (AWST, +0800)
System clock synchronized: yes
              NTP service: active
          RTC in local TZ: no

I’ve also checked the websites outside of my home network and they seem to work. So the issue only happens if the devices are on my local network. I’ve tried restarting my router to refresh the DNS but it didn’t seem to fix it.

You’re getting a different CN (Common Name) there, from a certificate generated Mar 31, as opposed to the expected May 9.

* subject: CN=jellyfin.tuxtower.net

I’m going to hazard a guess, that jellyfin.tuxtower.net is your Nginx server’s default host? You might try setting up a generic catch-all (and fail) as the defined default, to avoid these issues.

I use something like this, which essentially drops all traffic with 444 (no response), to any destination not specifically defined as a host (a catch all). Mind, that this is a BSD config, so paths and use of “/dev/null” may need to be modified.

server {
        listen                  80 reuseport default_server;
        listen                  443 ssl http2 reuseport default_server;
        ssl_certificate         /usr/local/etc/nginx/default.crt;
        ssl_certificate_key     /usr/local/etc/nginx/default.key;
        server_name             _;
        return                  444;

        # logging
        access_log off;
        error_log /dev/null;
}

Actually jellyfin is another subdomain on my nginx. The default servers host is tuxtower.net. If this helps my nginx defautl nginx config is here:

server {
	listen 80;
	listen [::]:80;

root /var/www/html;
	index index.php index.html  index.htm index.nginx-debian.html;

server_name _;

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

}

and here is atuin’s config

server {
	server_name atuin.tuxtower.net ;

	location / {
		proxy_pass http://10.1.1.85:8888;
		proxy_set_header Host $host;
		proxy_set_header X-Real-IP $remote_addr;
		proxy_set_header X-Forwarded-for $proxy_add_x_forwarded_for;
	}


    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/atuin.tuxtower.net/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/atuin.tuxtower.net/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 = atuin.tuxtower.net) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


	server_name atuin.tuxtower.net ;
    listen 80;
    return 404; # managed by Certbot


}

So should i include what you sent in my default config or in each of my subdomain configs?

A couple of things noted there perhaps.

  • Your default server is not handling port 443, so it will not be default for that, which opens up the possibility of jellyfin.tuxtower.net assuming that role.
  • Your default server may not actually be default, as it is not explicitly defined as such with the default_server directive, again, opening up possibilities of another host picking that up (for port 80 at least).

The default config I shared is a once only. It is essentially a host definition. So don’t include it per host.
Per host would likely fail too, as once some defaults are defined, they should not, and need not be repeated in Nginx.

ive done this to make it the default but it didnt seem to change anything

server {
	listen 80 default_server;
	listen [::]:80 default_server;
	listen 443 ssl http2 default_server;
	listen [::]:443 ssl http2 default_server;

	root /var/www/html;
	index index.php index.html  index.htm index.nginx-debian.html;

	server_name _;

	ssl_certificate /etc/nginx/ssl/default.crt;
	ssl_certificate_key /etc/nginx/ssl/default.key;

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

}

i used openssl to generate the ssl certificates. I normally use certbot for my setting up https certificates for all my domains. Is this correct?

Because I seem to only have the issues if my endevouros devices are connected to my home network. Could the issue be related to something else rather than how my nginx server is set up?

For the default catch-all host, generating your own certificates (self-signed certificates) is fine, if the purpose is to essentially drop that traffic. It doesn’t matter that the end-user browser might throw a warning, they’ve tried to connect to your server in an unexpected way (eg: bot traffic, probes, etc).

Your default catch-all is offering content, and perhaps that’s for the purpose of current debugging. But you might consider quickly dropping that traffic in future (return 444;), as it’d likely just be internet noise and wasting your server resources.

Yeah it certainly remains possible it’s unrelated to your Nginx setup, but I will offer that the changes you’ve made so far, have been good to have in any case.

After a restarting your Nginx service, your router and your Endeavour systems, perhaps try the curl command again and see if it’s still referencing the jellyfin.tuxtower.net common name?

$ curl -v https://atuin.tuxtower.net

Ah thinking on this, I just spotted a possible discrepancy.

Note your config for atuin.tuxtower.net. You’ve not defined a listening pair for IPv6:443.

In addition to what you have, you would also need to add:

listen [::]:443 ssl;

Your curl command is connecting using IPv6:

* Connected to atuin.tuxtower.net (fde4:1d15:8139:0:3697:f6ff:fe8d:372f) port 443

My network has IPv6 disabled, which is why I’m successfully connecting to IPv4. Your atuin.tuxtower.net host is not handling IPv6, so connections to that are shuffled to the default_host.

Your working devices, must be using IPv4.

4 Likes

Amazing this is what fixed it. I guess when I’m on the local network it is using ipv6 instead of ipv4 so it was a problem with how nginx was set up. I will apply this change to all my subdomains so they work now. Thank you!!!

Here is the new nginx config of what I changed. I added a listening pair for 443 and 80:

server {
	server_name atuin.tuxtower.net ;

	location / {
		proxy_pass http://10.1.1.85:8888;
		proxy_set_header Host $host;
		proxy_set_header X-Real-IP $remote_addr;
		proxy_set_header X-Forwarded-for $proxy_add_x_forwarded_for;
	}


    listen 443 ssl; # managed by Certbot
    listen [::]:443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/atuin.tuxtower.net/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/atuin.tuxtower.net/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 = atuin.tuxtower.net) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


	server_name atuin.tuxtower.net ;
    listen 80;
    listen [::]:80;
    return 404; # managed by Certbot


}
2 Likes

Great news :sunglasses:

I recommend using the DigitalOcean Nginx config generator, to provide you with a base config. That’ll help avoid some of these little oversights.

2 Likes

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.