totally transparent proxying with nginx on openbsd

Srebrenko Šehić ssehic at armorlogic.com
Mon Jan 7 11:06:15 UTC 2013


Hi,

I tried this with 1.2.6 and it works just fine. Have you given this
any scrutiny in real life production systems?

Thx,
ssehic


Best regards,

Srebrenko Sehic
Armorlogic

Phone: +45 70 27 77 32
Mobile: +45 26 10 02 76

http://www.armorlogic.com


On Thu, Oct 28, 2010 at 4:14 PM, David Gwynne <loki at animata.net> wrote:

> openbsd has a setsockopt option called SO_BINDANY that allows a
> process to bind to any ip address, even if it is not local to the
> system. the patch below uses it to allow nginx to connect to a
> backend server using the ip of the client making the request.
>
> my main goal here is to allow the backend server to know the ip of
> the client actually making the request without having to look at
> extra hhtp headers
>
> i thought id throw this out there to get some help since this is
> my first attempt at tweaking nginx. there are a few issues with
> this implementation:
>
> 1. it is completely specific to openbsd.
> 2. it needs root privileges to use the SO_BINDANY sockopt.
> 3. im not sure if connections to backends are cached. if so then
> it is probable that a different client will reuse a previous clients
> proxy connection, so it will appear that the same client made both
> requests to the backend.
>
> to use this you just configure nginx to run as root and add
> "proxy_transparent on" to the sections you want this feature enabled
> on. you will need to add appropriate "pass out proto tcp divert-reply"
> rules to pf for the SO_BINDANY sockopt to work too.
>
> if anyone has some tips on how to handle problems 2 and 3 i would
> be grateful.
>
> cheers,
> dlg
>
>
> --- src/event/ngx_event_connect.c.orig  Thu Nov 26 04:03:59 2009
> +++ src/event/ngx_event_connect.c       Thu Oct 28 23:22:37 2010
> @@ -11,7 +11,7 @@
>
>
>  ngx_int_t
> -ngx_event_connect_peer(ngx_peer_connection_t *pc)
> +ngx_event_connect_peer(ngx_peer_connection_t *pc, ngx_connection_t *cc)
>  {
>      int                rc;
>      ngx_int_t          event;
> @@ -20,6 +20,7 @@ ngx_event_connect_peer(ngx_peer_connection_t *pc)
>      ngx_socket_t       s;
>      ngx_event_t       *rev, *wev;
>      ngx_connection_t  *c;
> +    int                bindany;
>
>      rc = pc->get(pc, pc->data);
>      if (rc != NGX_OK) {
> @@ -46,6 +47,40 @@ ngx_event_connect_peer(ngx_peer_connection_t *pc)
>          }
>
>          return NGX_ERROR;
> +    }
> +
> +    if (cc != NULL) {
> +        bindany = 1;
> +        if (setsockopt(s, SOL_SOCKET, SO_BINDANY,
> +                      &bindany, sizeof(bindany)) == -1)
> +        {
> +            ngx_log_error(NGX_LOG_ALERT, pc->log, ngx_socket_errno,
> +                          "setsockopt(SO_BINDANY) failed");
> +
> +            ngx_free_connection(c);
> +
> +            if (ngx_close_socket(s) == -1) {
> +                ngx_log_error(NGX_LOG_ALERT, pc->log, ngx_socket_errno,
> +                              ngx_close_socket_n " failed");
> +            }
> +
> +            return NGX_ERROR;
> +        }
> +
> +       if (bind(s, cc->sockaddr, cc->socklen) == -1)
> +       {
> +            ngx_log_error(NGX_LOG_ALERT, pc->log, ngx_socket_errno,
> +                          "bind() failed");
> +
> +            ngx_free_connection(c);
> +
> +            if (ngx_close_socket(s) == -1) {
> +                ngx_log_error(NGX_LOG_ALERT, pc->log, ngx_socket_errno,
> +                              ngx_close_socket_n " failed");
> +            }
> +
> +            return NGX_ERROR;
> +       }
>      }
>
>      if (pc->rcvbuf) {
> --- src/event/ngx_event_connect.h.orig  Tue Nov  3 01:24:02 2009
> +++ src/event/ngx_event_connect.h       Thu Oct 28 23:22:37 2010
> @@ -68,7 +68,8 @@ struct ngx_peer_connection_s {
>  };
>
>
> -ngx_int_t ngx_event_connect_peer(ngx_peer_connection_t *pc);
> +ngx_int_t ngx_event_connect_peer(ngx_peer_connection_t *pc,
> +    ngx_connection_t *cc);
>  ngx_int_t ngx_event_get_peer(ngx_peer_connection_t *pc, void *data);
>
>
> --- src/http/modules/ngx_http_proxy_module.c.orig       Mon May 24
> 21:01:05 2010
> +++ src/http/modules/ngx_http_proxy_module.c    Thu Oct 28 23:42:10 2010
> @@ -71,6 +71,7 @@ typedef struct {
>      ngx_http_proxy_vars_t          vars;
>
>      ngx_flag_t                     redirect;
> +    ngx_flag_t                     transparent;
>
>      ngx_uint_t                     headers_hash_max_size;
>      ngx_uint_t                     headers_hash_bucket_size;
> @@ -196,6 +197,13 @@ static ngx_command_t  ngx_http_proxy_commands[] = {
>        0,
>        NULL },
>
> +    { ngx_string("proxy_transparent"),
> +
>  NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
> +      ngx_conf_set_flag_slot,
> +      NGX_HTTP_LOC_CONF_OFFSET,
> +      offsetof(ngx_http_proxy_loc_conf_t, transparent),
> +      NULL },
> +
>      { ngx_string("proxy_store"),
>
>  NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
>        ngx_http_proxy_store,
> @@ -626,6 +634,7 @@ ngx_http_proxy_handler(ngx_http_request_t *r)
>      u->abort_request = ngx_http_proxy_abort_request;
>      u->finalize_request = ngx_http_proxy_finalize_request;
>      r->state = 0;
> +    r->transparent = (plcf->transparent == 1);
>
>      if (plcf->redirects) {
>          u->rewrite_redirect = ngx_http_proxy_rewrite_redirect;
> @@ -1940,6 +1949,7 @@ ngx_http_proxy_create_loc_conf(ngx_conf_t *cf)
>      conf->upstream.cyclic_temp_file = 0;
>
>      conf->redirect = NGX_CONF_UNSET;
> +    conf->transparent = NGX_CONF_UNSET;
>      conf->upstream.change_buffering = 1;
>
>      conf->headers_hash_max_size = NGX_CONF_UNSET_UINT;
> @@ -2214,6 +2224,8 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void
> *pa
>              }
>          }
>      }
> +
> +    ngx_conf_merge_value(conf->transparent, prev->transparent, 0);
>
>      /* STUB */
>      if (prev->proxy_lengths) {
> --- src/http/ngx_http_request.h.orig    Mon May 24 22:35:10 2010
> +++ src/http/ngx_http_request.h Thu Oct 28 23:22:37 2010
> @@ -511,6 +511,8 @@ struct ngx_http_request_s {
>      unsigned                          stat_writing:1;
>  #endif
>
> +    unsigned                          transparent:1;
> +
>      /* used to parse HTTP headers */
>
>      ngx_uint_t                        state;
> --- src/http/ngx_http_upstream.c.orig   Mon May 24 22:35:10 2010
> +++ src/http/ngx_http_upstream.c        Thu Oct 28 23:22:37 2010
> @@ -1066,7 +1066,8 @@ ngx_http_upstream_connect(ngx_http_request_t *r,
> ngx_h
>      u->state->response_sec = tp->sec;
>      u->state->response_msec = tp->msec;
>
> -    rc = ngx_event_connect_peer(&u->peer);
> +    rc = ngx_event_connect_peer(&u->peer, r->transparent ?
> +                                r->connection : NULL);
>
>      ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
>                     "http upstream connect: %i", rc);
> --- src/mail/ngx_mail_auth_http_module.c.orig   Fri May 14 19:56:37 2010
> +++ src/mail/ngx_mail_auth_http_module.c        Thu Oct 28 23:22:37 2010
> @@ -191,7 +191,7 @@ ngx_mail_auth_http_init(ngx_mail_session_t *s)
>      ctx->peer.log = s->connection->log;
>      ctx->peer.log_error = NGX_ERROR_ERR;
>
> -    rc = ngx_event_connect_peer(&ctx->peer);
> +    rc = ngx_event_connect_peer(&ctx->peer, NULL);
>
>      if (rc == NGX_ERROR || rc == NGX_BUSY || rc == NGX_DECLINED) {
>          if (ctx->peer.connection) {
> --- src/mail/ngx_mail_proxy_module.c.orig       Thu Oct 28 23:32:15 2010
> +++ src/mail/ngx_mail_proxy_module.c    Thu Oct 28 23:30:53 2010
> @@ -147,7 +147,7 @@ ngx_mail_proxy_init(ngx_mail_session_t *s, ngx_addr_t
>      p->upstream.log = s->connection->log;
>      p->upstream.log_error = NGX_ERROR_ERR;
>
> -    rc = ngx_event_connect_peer(&p->upstream);
> +    rc = ngx_event_connect_peer(&p->upstream, NULL);
>
>      if (rc == NGX_ERROR || rc == NGX_BUSY || rc == NGX_DECLINED) {
>          ngx_mail_proxy_internal_server_error(s);
>
> _______________________________________________
> nginx-devel mailing list
> nginx-devel at nginx.org
> http://nginx.org/mailman/listinfo/nginx-devel
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.nginx.org/pipermail/nginx-devel/attachments/20130107/0759a863/attachment-0001.html>


More information about the nginx-devel mailing list