[PATCH 2 of 2] SSL: support for iPAddress subjectAltName in certificates

Maxim Dounin mdounin at mdounin.ru
Mon Aug 18 16:39:26 UTC 2025


Hello!

On Thu, Aug 14, 2025 at 06:52:02PM +0300, Maxim Dounin wrote:

> # HG changeset patch
> # User Maxim Dounin <mdounin at mdounin.ru>
> # Date 1755133582 -10800
> #      Thu Aug 14 04:06:22 2025 +0300
> # Node ID 870dfc16d381d90644b08159dd84d1ee391cf630
> # Parent  51d23ff6f109765f4c382d449d7ea0cea13ea220
> SSL: support for iPAddress subjectAltName in certificates.
> 
> Known public services with iPAddress subject altnames include 1.1.1.1
> and 8.8.8.8.  IP address certificates from Let's Encrypt are expected
> to be available soon:
> 
> https://letsencrypt.org/2025/07/01/issuing-our-first-ip-address-certificate
> 
> diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c
> --- a/src/event/ngx_event_openssl.c
> +++ b/src/event/ngx_event_openssl.c
> @@ -4901,19 +4901,63 @@ ngx_ssl_cleanup_ctx(void *data)
>  ngx_int_t
>  ngx_ssl_check_host(ngx_connection_t *c, ngx_str_t *name)
>  {
> -    X509   *cert;
> +    X509       *cert;
> +    u_char     *addr, addr6[16];
> +    size_t      alen;
> +    in_addr_t   addr4;
>  
>      cert = SSL_get_peer_certificate(c->ssl->connection);
>      if (cert == NULL) {
>          return NGX_ERROR;
>      }
>  
> +    if (name->len == 0) {
> +        goto failed;
> +    }
> +
> +    addr4 = ngx_inet_addr(name->data, name->len);
> +
> +    if (addr4 != INADDR_NONE) {
> +        addr = (u_char *) &addr4;
> +        alen = 4;
> +
> +#if (NGX_HAVE_INET6)
> +    } else if (name->data[0] == '[') {
> +
> +        if (name->data[name->len - 1] != ']') {
> +            goto failed;
> +        }
> +
> +        if (ngx_inet6_addr(name->data + 1, name->len - 2, &addr6[0])
> +            != NGX_OK)
> +        {
> +            goto failed;
> +        }
> +
> +        addr = &addr6[0];
> +        alen = 16;
> +
> +#endif
> +    } else {
> +        addr = NULL;
> +        alen = 0;
> +    }
> +
> +
>  #ifdef X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT
>  
>      /* X509_check_host() is only available in OpenSSL 1.0.2+ */
>  
> -    if (name->len == 0) {
> -        goto failed;
> +    if (addr) {
> +        if (X509_check_ip(cert, addr, alen, 0) != 1) {
> +            ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
> +                           "X509_check_ip(): no match");
> +            goto failed;
> +        }
> +
> +        ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
> +                       "X509_check_ip(): match");
> +        goto found;
>      }
>  
>      if (X509_check_host(cert, (char *) name->data, name->len, 0, NULL) != 1) {
> @@ -4924,12 +4968,13 @@ ngx_ssl_check_host(ngx_connection_t *c, 
>  
>      ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
>                     "X509_check_host(): match");
> -
>      goto found;
>  
>  #else
>      {
>      int                      n, i;
> +    size_t                   dlen;
> +    u_char                  *data;
>      X509_NAME               *sname;
>      ASN1_STRING             *str;
>      X509_NAME_ENTRY         *entry;
> @@ -4949,22 +4994,63 @@ ngx_ssl_check_host(ngx_connection_t *c, 
>          for (i = 0; i < n; i++) {
>              altname = sk_GENERAL_NAME_value(altnames, i);
>  
> -            if (altname->type != GEN_DNS) {
> -                continue;
> -            }
> -
> -            str = altname->d.dNSName;
> -
> -            ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
> -                           "SSL subjectAltName: \"%*s\"",
> -                           (size_t) ASN1_STRING_length(str),
> -                           ASN1_STRING_data(str));
> -
> -            if (ngx_ssl_check_name(name, str) == NGX_OK) {
> -                ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
> -                               "SSL subjectAltName: match");
> -                GENERAL_NAMES_free(altnames);
> -                goto found;
> +            if (altname->type == GEN_IPADD) {
> +
> +                str = altname->d.iPAddress;
> +                data = ASN1_STRING_data(str);
> +                dlen = ASN1_STRING_length(str);
> +
> +#if (NGX_DEBUG)
> +                {
> +                size_t  al;
> +                u_char  at[NGX_INET6_ADDRSTRLEN];
> +
> +                if (dlen == 4) {
> +                    al = ngx_inet_ntop(AF_INET, data, at,
> +                                       NGX_INET6_ADDRSTRLEN);
> +
> +#if (NGX_HAVE_INET6)
> +                } else if (dlen == 16) {
> +                    al = ngx_inet_ntop(AF_INET6, data, at,
> +                                       NGX_INET6_ADDRSTRLEN);
> +
> +#endif
> +                } else {
> +                    al = ngx_cpymem(at, "<invalid>", sizeof("<invalid>") - 1)
> +                         - at;
> +                }
> +
> +                ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
> +                               "SSL subjectAltName: %*s",
> +                               al, at);
> +                }
> +#endif
> +
> +                if (addr
> +                    && alen == dlen
> +                    && ngx_memcmp(addr, data, dlen) == 0)
> +                {
> +                    ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
> +                                   "SSL subjectAltName: match");
> +                    GENERAL_NAMES_free(altnames);
> +                    goto found;
> +                }
> +
> +            } else if (altname->type == GEN_DNS) {
> +
> +                str = altname->d.dNSName;
> +
> +                ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
> +                               "SSL subjectAltName: \"%*s\"",
> +                               (size_t) ASN1_STRING_length(str),
> +                               ASN1_STRING_data(str));
> +
> +                if (ngx_ssl_check_name(name, str) == NGX_OK) {
> +                    ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
> +                                   "SSL subjectAltName: match");
> +                    GENERAL_NAMES_free(altnames);
> +                    goto found;
> +                }
>              }
>          }
>  
> 

Amended with the following patch, to provide more natural order of 
altname->type handling:

diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c
--- a/src/event/ngx_event_openssl.c
+++ b/src/event/ngx_event_openssl.c
@@ -4994,7 +4994,23 @@ ngx_ssl_check_host(ngx_connection_t *c, 
         for (i = 0; i < n; i++) {
             altname = sk_GENERAL_NAME_value(altnames, i);
 
-            if (altname->type == GEN_IPADD) {
+            if (altname->type == GEN_DNS) {
+
+                str = altname->d.dNSName;
+
+                ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
+                               "SSL subjectAltName: \"%*s\"",
+                               (size_t) ASN1_STRING_length(str),
+                               ASN1_STRING_data(str));
+
+                if (ngx_ssl_check_name(name, str) == NGX_OK) {
+                    ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
+                                   "SSL subjectAltName: match");
+                    GENERAL_NAMES_free(altnames);
+                    goto found;
+                }
+
+            } else if (altname->type == GEN_IPADD) {
 
                 str = altname->d.iPAddress;
                 data = ASN1_STRING_data(str);
@@ -5035,22 +5051,6 @@ ngx_ssl_check_host(ngx_connection_t *c, 
                     GENERAL_NAMES_free(altnames);
                     goto found;
                 }
-
-            } else if (altname->type == GEN_DNS) {
-
-                str = altname->d.dNSName;
-
-                ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
-                               "SSL subjectAltName: \"%*s\"",
-                               (size_t) ASN1_STRING_length(str),
-                               ASN1_STRING_data(str));
-
-                if (ngx_ssl_check_name(name, str) == NGX_OK) {
-                    ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
-                                   "SSL subjectAltName: match");
-                    GENERAL_NAMES_free(altnames);
-                    goto found;
-                }
             }
         }
 


-- 
Maxim Dounin
http://mdounin.ru/


More information about the nginx-devel mailing list