[PATCH] Added nonlocal to the listen directive

Trygve Vea tv at redpill-linpro.com
Fri Mar 28 09:45:53 UTC 2014


# HG changeset patch
# User Trygve Vea <tv at redpill-linpro.com>
# Date 1395999940 -3600
#      Fri Mar 28 10:45:40 2014 +0100
# Node ID 16eacd8609c8362e9dd729c743ed7a869c2993fe
# Parent  2411d4b5be2ca690a5a00a1d8ad96ff69a00317f
Added nonlocal to the listen directive

The nonlocal option is used to set the needed socket options to be able to bind
to an address not necessarily owned by the host.

This patch currently implements this for Linux >= 2.4 IPv4/IPv6.

The problem we solve by doing this, is in an environment where the following
conditions are met:

* HTTPS with multiple certificates, and a client base that are unable to use
  SNI - thus having the need to tie specific certificates to specific ip/ports.
* Setting the ip_nonlocal_bind-sysctl is not an option (for example for Linux
  IPv6)
* Used in a failover-setup, where the service IP-addresses are moved around by
  a daemon like linux-ha or keepalived.

diff -r 2411d4b5be2c -r 16eacd8609c8 src/core/ngx_connection.c
--- a/src/core/ngx_connection.c	Wed Mar 26 18:01:11 2014 +0400
+++ b/src/core/ngx_connection.c	Fri Mar 28 10:45:40 2014 +0100
@@ -305,6 +305,14 @@
 ngx_open_listening_sockets(ngx_cycle_t *cycle)
 {
     int               reuseaddr;
+#ifdef NGX_LINUX
+#ifdef IP_FREEBIND
+    int               so_freebind;
+#endif
+#ifdef IP_TRANSPARENT
+    int               so_transparent;
+#endif
+#endif
     ngx_uint_t        i, tries, failed;
     ngx_err_t         err;
     ngx_log_t        *log;
@@ -370,6 +378,35 @@
                 return NGX_ERROR;
             }
 
+            if (ls[i].nonlocal) {
+#if (defined NGX_LINUX && defined IP_FREEBIND)
+                so_freebind = 1;
+
+                if (setsockopt(s, SOL_IP, IP_FREEBIND,
+                               (const void *) &so_freebind, sizeof(int))
+                    == -1)
+                {
+                    ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
+                                  "setsockopt(IP_FREEBIND, %d) %V failed",
+                                  so_freebind, &ls[i].addr_text);
+                }
+#if (NGX_HAVE_INET6 && defined IP_TRANSPARENT)
+                so_transparent = 1;
+
+                if (setsockopt(s, SOL_IP, IP_TRANSPARENT,
+                               (const void *) &so_transparent, sizeof(int))
+                    == -1)
+                {
+                    ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
+                                  "setsockopt(IP_TRANSPARENT, %d) %V failed",
+                                  so_transparent, &ls[i].addr_text);
+                }
+#endif
+                ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
+                              "nonlocal requires Linux >= 2.4, ignored");
+#endif
+            }
+
 #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
 
             if (ls[i].sockaddr->sa_family == AF_INET6) {
diff -r 2411d4b5be2c -r 16eacd8609c8 src/core/ngx_connection.h
--- a/src/core/ngx_connection.h	Wed Mar 26 18:01:11 2014 +0400
+++ b/src/core/ngx_connection.h	Fri Mar 28 10:45:40 2014 +0100
@@ -66,6 +66,7 @@
 #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
     unsigned            ipv6only:1;
 #endif
+    unsigned            nonlocal:1;
     unsigned            keepalive:2;
 
 #if (NGX_HAVE_DEFERRED_ACCEPT)
diff -r 2411d4b5be2c -r 16eacd8609c8 src/http/ngx_http.c
--- a/src/http/ngx_http.c	Wed Mar 26 18:01:11 2014 +0400
+++ b/src/http/ngx_http.c	Fri Mar 28 10:45:40 2014 +0100
@@ -1808,6 +1808,7 @@
 #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
     ls->ipv6only = addr->opt.ipv6only;
 #endif
+    ls->nonlocal = addr->opt.nonlocal;
 
 #if (NGX_HAVE_SETFIB)
     ls->setfib = addr->opt.setfib;
diff -r 2411d4b5be2c -r 16eacd8609c8 src/http/ngx_http_core_module.c
--- a/src/http/ngx_http_core_module.c	Wed Mar 26 18:01:11 2014 +0400
+++ b/src/http/ngx_http_core_module.c	Fri Mar 28 10:45:40 2014 +0100
@@ -4283,6 +4283,11 @@
             continue;
         }
 
+        if (ngx_strcmp(value[n].data, "nonlocal") == 0) {
+            lsopt.nonlocal = 1;
+            continue;
+        }
+
         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                            "invalid parameter \"%V\"", &value[n]);
         return NGX_CONF_ERROR;
diff -r 2411d4b5be2c -r 16eacd8609c8 src/http/ngx_http_core_module.h
--- a/src/http/ngx_http_core_module.h	Wed Mar 26 18:01:11 2014 +0400
+++ b/src/http/ngx_http_core_module.h	Fri Mar 28 10:45:40 2014 +0100
@@ -81,6 +81,7 @@
 #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
     unsigned                   ipv6only:1;
 #endif
+    unsigned                   nonlocal:1;
     unsigned                   so_keepalive:2;
     unsigned                   proxy_protocol:1;
 
diff -r 2411d4b5be2c -r 16eacd8609c8 src/mail/ngx_mail.c
--- a/src/mail/ngx_mail.c	Wed Mar 26 18:01:11 2014 +0400
+++ b/src/mail/ngx_mail.c	Fri Mar 28 10:45:40 2014 +0100
@@ -327,6 +327,7 @@
 #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
     addr->ipv6only = listen->ipv6only;
 #endif
+    addr->nonlocal = listen->nonlocal;
 
     return NGX_OK;
 }
diff -r 2411d4b5be2c -r 16eacd8609c8 src/mail/ngx_mail.h
--- a/src/mail/ngx_mail.h	Wed Mar 26 18:01:11 2014 +0400
+++ b/src/mail/ngx_mail.h	Fri Mar 28 10:45:40 2014 +0100
@@ -41,6 +41,7 @@
 #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
     unsigned                ipv6only:1;
 #endif
+    unsigned                nonlocal:1;
     unsigned                so_keepalive:2;
 #if (NGX_HAVE_KEEPALIVE_TUNABLE)
     int                     tcp_keepidle;
diff -r 2411d4b5be2c -r 16eacd8609c8 src/mail/ngx_mail_core_module.c
--- a/src/mail/ngx_mail_core_module.c	Wed Mar 26 18:01:11 2014 +0400
+++ b/src/mail/ngx_mail_core_module.c	Fri Mar 28 10:45:40 2014 +0100
@@ -456,6 +456,11 @@
 #endif
         }
 
+        if (ngx_strcmp(value[i].data, "nonlocal") == 0) {
+            ls->nonlocal = 1;
+            continue;
+        }
+
         if (ngx_strcmp(value[i].data, "ssl") == 0) {
 #if (NGX_MAIL_SSL)
             ls->ssl = 1;



More information about the nginx-devel mailing list