# Invalid HTTPS domain with no cert does a 301 redirect to the 1st configured server

**URL:** <https://community.nginx.org/t/invalid-https-domain-with-no-cert-does-a-301-redirect-to-the-1st-configured-server/10141>\
**Category:** NGINX\
**Tags:** ssl, web-server, config\
**Created:** [July 16, 2026, 1:45pm UTC](https://community.nginx.org/t/invalid-https-domain-with-no-cert-does-a-301-redirect-to-the-1st-configured-server/10141 "2026-07-16T13:45:43Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![crean](https://avatars.discourse-cdn.com/v4/letter/c/b4bc9f/32.png) [@crean](https://community.nginx.org/u/crean)\
**Post date:** [July 16, 2026, 1:45pm UTC](https://community.nginx.org/t/invalid-https-domain-with-no-cert-does-a-301-redirect-to-the-1st-configured-server/10141/1 "2026-07-16T13:45:43Z")

</div>

**My issue:**

Sending a request to an HTTPS domain that is not configured in nginx but points to my server, you get the usual certificate error, but if you ignore that, nginx will send a 301 redirect to one of the configured servers (probably the 1st, but I haven’t investigated the order).

**How I encountered the problem:**

Some domain points to my IP for no reason.

**Solutions I’ve tried:**

Catch all for HTTP traffic works fine, but I can’t do a default\_server for 443 without a cert. I could technically fetch the cert for the specific domain domain that is pointing over, but is that really the solution if the domain is something I don’t own or care about?

**Version of NGINX or NGINX adjacent software (e.g. NGINX Gateway Fabric):**

I tried on 1.18 and 1.24 so maybe there’s a change/fix in a later version?

**Deployment environment:**

Ubuntu 22-LTS, 24-LTS, cloud VM

**Minimal NGINX config to reproduce your issue:**

```auto
# catch-all
server {
listen 80 default_server;
server_name _;
return 444;
}

# Site something.tld with an http => https redirect
server {
listen 80;
server_name something.tld;
return 301 https://something.tld$request_uri;
}
server {
listen 443 ssl http2;
server_name something.tld;
# and all the ssl_ settings
}

```

Let’s assume the server IP is 1.2.3.4 and you have an `/etc/hosts` with this:

```auto
1.2.3.4 foobar.tld

```

Then you run curl test:

```auto
❱ curl -I http://foobar.tld
curl: (52) Empty reply from server

❱ curl -I https://foobar.tld
curl: (60) SSL: no alternative certificate subject name matches target hostname 'foobar.tld'

❱ curl -kI https://foobar.tld
HTTP/2 301
server: nginx
date: Thu, 16 Jul 2026 06:28:51 GMT
content-type: text/html
content-length: 162
location: https://something.tld

```

This last one is the one I have an issue with. How can I make it do nothing?

**NGINX access/error log:**

```auto
x.x.x.x - - [16/Jul/2026:09:19:31 +0200] "HEAD / HTTP/1.1" 444 0 "-" "curl/8.21.0" "-"
x.x.x.x - - [16/Jul/2026:09:18:32 +0200] "HEAD / HTTP/2.0" 301 0 "-" "curl/8.21.0" "-"

```

---

<div class="post-metadata">

**Author:** ![FrancisD](https://avatars.discourse-cdn.com/v4/letter/f/ea5d25/32.png) [@FrancisD](https://community.nginx.org/u/FrancisD)\
**Post date:** [July 16, 2026, 10:18pm UTC](https://community.nginx.org/t/invalid-https-domain-with-no-cert-does-a-301-redirect-to-the-1st-configured-server/10141/2 "2026-07-16T22:18:17Z")

</div>

Hi there,

the basic “fix” for https is essentially the same as for http – create a server{} with the matching “listen” ip:port and mark it default\_server. If you want to give the client some indication of what is wrong, then you would need a ssl\_certificate and ssl\_certificate\_key; and because you do not expect any “real” requests to get to this service, you can safely use something like a self-signed certificate for a hostname like “go-away”. But if you want the client to “just” see that things failed mostly-silently, then the example for ssl\_reject\_handshake ( [Module ngx\_http\_ssl\_module](https://nginx.org/r/ssl_reject_handshake) ) will probably do what you want.

Note that this would “break” any https clients that do not use SNI; but I suspect that it is reasonable to call them broken anyway.

The reason that this works is that every server{} has at least one effective “listen” directive which names an ip:port. (There are default values, if they are not all explicitly listed.) When a http request comes in to an ip:port, nginx chooses which server{} to use based on the “listen” directives, and (in the common case) the “Host:” header – if “Host” does not match any relevant server\_name, then the default\_server (explicit, or implicit) for that ip:port is used.  
When a https request comes in to an ip:port, the same applies except that the Host: header is not available early enough, and so nginx chooses based on the Server Name Indication field of the client side of the TLS negotiation.

The fuller details for selecting the server{} for http are described at [How nginx processes a request](https://nginx.org/en/docs/http/request_processing.html) while the SNI-handling is described towards the end of [Configuring HTTPS servers](https://nginx.org/en/docs/http/configuring_https_servers.html)

The example for ssl\_reject\_handshake is:

```auto
server {
    listen 443 ssl default_server;
    ssl_reject_handshake on;
}

server {
    listen 443 ssl;
    server_name example.com;
    ssl_certificate example.com.crt;
    ssl_certificate_key example.com.key;
}

```

where any https connection attempt to a name other than [example.com](http://example.com) will get an error response similar to what curl shows as

```
curl: (35) OpenSSL/3.0.20: error:0A000458:SSL routines::tlsv1 unrecognized name

```

Cheers,

---

<div class="post-metadata">

**Author:** ![crean](https://avatars.discourse-cdn.com/v4/letter/c/b4bc9f/32.png) [@crean](https://community.nginx.org/u/crean)\
**Post date:** [July 17, 2026, 5:41am UTC](https://community.nginx.org/t/invalid-https-domain-with-no-cert-does-a-301-redirect-to-the-1st-configured-server/10141/3 "2026-07-17T05:41:11Z")

</div>

Hi, Francis

thanks for the exhaustive reply! Dunno why I didn’t think about using a self signed cert but the `ssl_reject_handshake` is definitely the correct way to go for my case.

---

<div class="post-metadata">

**Author:** ![system](https://drob5swvtjqxg.cloudfront.net/user_avatar/community.nginx.org/system/32/19_2.png) [@system](https://community.nginx.org/u/system)\
**Post date:** [July 24, 2026, 5:41am UTC](https://community.nginx.org/t/invalid-https-domain-with-no-cert-does-a-301-redirect-to-the-1st-configured-server/10141/4 "2026-07-24T05:41:33Z")

</div>

Closed on July 24, 2026, 5:41am UTC

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