├── .clang-format ├── .gitignore ├── LICENSE ├── README.md ├── config ├── docker ├── alpine │ ├── dynamic │ │ ├── Dockerfile │ │ └── nginx.conf │ └── static │ │ ├── Dockerfile │ │ └── nginx.conf ├── openresty │ └── alpine │ │ ├── dynamic │ │ ├── Dockerfile │ │ ├── nginx.conf │ │ ├── nginx.vh.default.conf │ │ └── test │ │ │ ├── default.conf │ │ │ └── nginx.conf │ │ └── static │ │ ├── Dockerfile │ │ ├── nginx.conf │ │ ├── nginx.vh.default.conf │ │ └── test │ │ └── default.conf └── readme.md ├── ngx_http_upstream_ntlm_module.c ├── package-lock.json ├── t ├── 001-sanity.t ├── 002-timeout.t └── backend │ ├── index.js │ ├── package-lock.json │ └── package.json └── utils ├── build_linux_configure.sh ├── build_linux_download.sh ├── build_linux_make.sh ├── build_macos_configure.sh ├── build_macos_download.sh ├── build_macos_make.sh ├── build_win_configure.sh ├── build_win_download.sh └── build_win_make.sh /.clang-format: -------------------------------------------------------------------------------- 1 | Language: Cpp 2 | BasedOnStyle: LLVM 3 | IndentWidth: 4 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .clangd 2 | compile_commands.json 3 | t/servroot 4 | t/*/node_modules 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 gabihodoroaga 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # nginx-ntlm-module 2 | 3 | The NTLM module allows proxying requests with [NTLM Authentication](https://en.wikipedia.org/wiki/Integrated_Windows_Authentication). The upstream connection is bound to the client connection once the client sends a request with the "Authorization" header field value starting with "Negotiate" or "NTLM". Further client requests will be proxied through the same upstream connection, keeping the authentication context. 4 | 5 | ## How to use 6 | 7 | > Syntax: ntlm [connections]; 8 | > Default: ntlm 100; 9 | > Context: upstream 10 | 11 | 12 | ```nginx 13 | upstream http_backend { 14 | server 127.0.0.1:8080; 15 | 16 | ntlm; 17 | } 18 | 19 | server { 20 | ... 21 | 22 | location /http/ { 23 | proxy_pass http://http_backend; 24 | # next 2 settings are required for the keepalive to work properly 25 | proxy_http_version 1.1; 26 | proxy_set_header Connection ""; 27 | } 28 | } 29 | ``` 30 | 31 | The connections parameter sets the maximum number of connections to the upstream servers that are preserved in the cache. 32 | 33 | > Syntax: ntlm_timeout timeout; 34 | > Default: ntlm_timeout 60s; 35 | > Context: upstream 36 | 37 | Sets the timeout during which an idle connection to an upstream server will stay open. 38 | 39 | ## Build 40 | 41 | Follow the instructions from [Building nginx from Sources](http://nginx.org/en/docs/configure.html) and add the following line to the configure command 42 | 43 | ```bash 44 | ./configure \ 45 | --add-module=../nginx-ntlm-module 46 | ``` 47 | 48 | To build this as dynamic module run this command 49 | 50 | ```bash 51 | ./configure \ 52 | --add-dynamic-module=../nginx-ntlm-module 53 | ``` 54 | 55 | ## Tests 56 | 57 | In order to run the tests you need nodejs and perl installed on your system 58 | 59 | ```bash 60 | # install the backend packages 61 | npm install -C t/backend 62 | 63 | # instal the test framework 64 | cpan Test::Nginx 65 | 66 | # set the path to your nginx location 67 | export PATH=/opt/local/nginx/sbin:$PATH 68 | 69 | prove -r t 70 | ``` 71 | 72 | 73 | ## Acknowledgments 74 | 75 | - This module is using most of the code from the original nginx keepalive module. 76 | - DO NOT USE THIS IN PRODUCTION. [**Nginx Plus**](https://www.nginx.com/products/nginx/) has support for NTLM. 77 | 78 | ## Authors 79 | 80 | * Gabriel Hodoroaga ([hodo.dev](https://hodo.dev)) 81 | 82 | ## TODO 83 | 84 | - [x] Add tests 85 | - [x] Add support for multiple workers 86 | - [x] Drop the upstream connection when the client connection drops. 87 | - [ ] Add travis ci 88 | -------------------------------------------------------------------------------- /config: -------------------------------------------------------------------------------- 1 | ngx_addon_name=ngx_http_upstream_ntlm_module 2 | 3 | if test -n "$ngx_module_link"; then 4 | ngx_module_type=HTTP 5 | ngx_module_name=ngx_http_upstream_ntlm_module 6 | ngx_module_srcs="$ngx_addon_dir/ngx_http_upstream_ntlm_module.c" 7 | . auto/module 8 | else 9 | HTTP_MODULES="$HTTP_MODULES ngx_http_upstream_ntlm_module" 10 | NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_upstream_ntlm_module.c" 11 | fi 12 | -------------------------------------------------------------------------------- /docker/alpine/dynamic/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine:3.13 AS builder 2 | 3 | ARG NGINX_VERSION=1.19.3 4 | 5 | # install buidl tools 6 | RUN set -x \ 7 | && addgroup -g 101 -S nginx \ 8 | && adduser -S -D -H -u 101 -h /var/cache/nginx -s /sbin/nologin -G nginx -g nginx nginx \ 9 | && apk add --no-cache --virtual .build-deps \ 10 | gcc \ 11 | libc-dev \ 12 | make \ 13 | openssl-dev \ 14 | pcre-dev \ 15 | zlib-dev \ 16 | linux-headers \ 17 | libxslt-dev \ 18 | gd-dev \ 19 | geoip-dev \ 20 | perl-dev \ 21 | libedit-dev \ 22 | curl \ 23 | git 24 | 25 | WORKDIR /build 26 | 27 | # download nginx 28 | RUN curl -OL http://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz \ 29 | && tar -xvzf nginx-${NGINX_VERSION}.tar.gz && rm nginx-${NGINX_VERSION}.tar.gz \ 30 | && git clone https://github.com/gabihodoroaga/nginx-ntlm-module.git 31 | 32 | RUN cd nginx-${NGINX_VERSION}/ \ 33 | && ./configure \ 34 | --prefix=/etc/nginx \ 35 | --sbin-path=/usr/sbin/nginx \ 36 | --modules-path=/usr/lib/nginx/modules \ 37 | --conf-path=/etc/nginx/nginx.conf \ 38 | --error-log-path=/var/log/nginx/error.log \ 39 | --http-log-path=/var/log/nginx/access.log \ 40 | --pid-path=/var/run/nginx.pid \ 41 | --lock-path=/var/run/nginx.lock \ 42 | --http-client-body-temp-path=/var/cache/nginx/client_temp \ 43 | --http-proxy-temp-path=/var/cache/nginx/proxy_temp \ 44 | --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp \ 45 | --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp \ 46 | --http-scgi-temp-path=/var/cache/nginx/scgi_temp \ 47 | --with-perl_modules_path=/usr/lib/perl5/vendor_perl \ 48 | --user=nginx \ 49 | --group=nginx \ 50 | --with-compat \ 51 | --with-file-aio \ 52 | --with-threads \ 53 | --with-http_addition_module \ 54 | --with-http_auth_request_module \ 55 | --with-http_dav_module \ 56 | --with-http_flv_module \ 57 | --with-http_gunzip_module \ 58 | --with-http_gzip_static_module \ 59 | --with-http_mp4_module \ 60 | --with-http_random_index_module \ 61 | --with-http_realip_module \ 62 | --with-http_secure_link_module \ 63 | --with-http_slice_module \ 64 | --with-http_ssl_module \ 65 | --with-http_stub_status_module \ 66 | --with-http_sub_module \ 67 | --with-http_v2_module \ 68 | --with-mail \ 69 | --with-mail_ssl_module \ 70 | --with-stream \ 71 | --with-stream_realip_module \ 72 | --with-stream_ssl_module \ 73 | --with-stream_ssl_preread_module \ 74 | --with-cc-opt='-Os -fomit-frame-pointer' \ 75 | --with-ld-opt=-Wl,--as-needed \ 76 | # add the ntlm module 77 | --add-dynamic-module=../nginx-ntlm-module \ 78 | && make modules 79 | 80 | FROM nginx:1.19.3-alpine 81 | 82 | COPY --from=builder /build/nginx-${NGINX_VERSION}/objs/ngx_http_upstream_ntlm_module.so /etc/nginx/modules/ngx_http_upstream_ntlm_module.so 83 | 84 | -------------------------------------------------------------------------------- /docker/alpine/dynamic/nginx.conf: -------------------------------------------------------------------------------- 1 | 2 | load_module modules/ngx_http_upstream_ntlm_module.so; 3 | 4 | user nginx; 5 | worker_processes 1; 6 | error_log /var/log/nginx/error.log debug; 7 | pid /run/nginx.pid; 8 | events { 9 | worker_connections 1024; 10 | } 11 | 12 | 13 | http { 14 | log_format main '$remote_addr - $remote_user [$time_local] "$request" ' 15 | '$status $body_bytes_sent "$http_referer" ' 16 | '"$http_user_agent" "$http_x_forwarded_for"'; 17 | 18 | access_log /var/log/nginx/access.log main; 19 | sendfile on; 20 | keepalive_timeout 65; 21 | 22 | upstream backend { 23 | server localhost:8081; 24 | ntlm; 25 | } 26 | 27 | server { 28 | listen 80; 29 | server_name _; 30 | 31 | root /usr/share/nginx/html; 32 | index index.html; 33 | 34 | location /ntlm { 35 | proxy_pass http://backend; 36 | proxy_http_version 1.1; 37 | proxy_set_header Connection ""; 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /docker/alpine/static/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine:3.13 2 | 3 | ENV NGINX_VERSION 1.19.3 4 | 5 | 6 | # install buidl tools 7 | RUN set -x \ 8 | && addgroup -g 101 -S nginx \ 9 | && adduser -S -D -H -u 101 -h /var/cache/nginx -s /sbin/nologin -G nginx -g nginx nginx \ 10 | && apk add --no-cache --virtual .build-deps \ 11 | gcc \ 12 | libc-dev \ 13 | make \ 14 | openssl-dev \ 15 | pcre-dev \ 16 | zlib-dev \ 17 | linux-headers \ 18 | libxslt-dev \ 19 | gd-dev \ 20 | geoip-dev \ 21 | perl-dev \ 22 | libedit-dev \ 23 | curl \ 24 | git 25 | 26 | WORKDIR /build 27 | 28 | # download nginx 29 | RUN curl -OL http://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz \ 30 | && tar -xvzf nginx-${NGINX_VERSION}.tar.gz && rm nginx-${NGINX_VERSION}.tar.gz \ 31 | && git clone https://github.com/gabihodoroaga/nginx-ntlm-module.git 32 | 33 | RUN cd nginx-${NGINX_VERSION}/ \ 34 | && ./configure \ 35 | --prefix=/etc/nginx \ 36 | --sbin-path=/usr/sbin/nginx \ 37 | --modules-path=/usr/lib/nginx/modules \ 38 | --conf-path=/etc/nginx/nginx.conf \ 39 | --error-log-path=/var/log/nginx/error.log \ 40 | --http-log-path=/var/log/nginx/access.log \ 41 | --pid-path=/var/run/nginx.pid \ 42 | --lock-path=/var/run/nginx.lock \ 43 | --http-client-body-temp-path=/var/cache/nginx/client_temp \ 44 | --http-proxy-temp-path=/var/cache/nginx/proxy_temp \ 45 | --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp \ 46 | --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp \ 47 | --http-scgi-temp-path=/var/cache/nginx/scgi_temp \ 48 | --with-perl_modules_path=/usr/lib/perl5/vendor_perl \ 49 | --user=nginx \ 50 | --group=nginx \ 51 | --with-compat \ 52 | --with-file-aio \ 53 | --with-threads \ 54 | --with-http_addition_module \ 55 | --with-http_auth_request_module \ 56 | --with-http_dav_module \ 57 | --with-http_flv_module \ 58 | --with-http_gunzip_module \ 59 | --with-http_gzip_static_module \ 60 | --with-http_mp4_module \ 61 | --with-http_random_index_module \ 62 | --with-http_realip_module \ 63 | --with-http_secure_link_module \ 64 | --with-http_slice_module \ 65 | --with-http_ssl_module \ 66 | --with-http_stub_status_module \ 67 | --with-http_sub_module \ 68 | --with-http_v2_module \ 69 | --with-mail \ 70 | --with-mail_ssl_module \ 71 | --with-stream \ 72 | --with-stream_realip_module \ 73 | --with-stream_ssl_module \ 74 | --with-stream_ssl_preread_module \ 75 | --with-cc-opt='-Os -fomit-frame-pointer' \ 76 | --with-ld-opt=-Wl,--as-needed \ 77 | # add the ntlm module 78 | --add-module=../nginx-ntlm-module \ 79 | && make \ 80 | && make install \ 81 | && mkdir -p /var/cache/nginx 82 | 83 | WORKDIR / 84 | 85 | # clean up 86 | RUN apk del .build-deps \ 87 | && rm -rf /build \ 88 | && apk add pcre 89 | 90 | WORKDIR /etc/nginx/html 91 | 92 | EXPOSE 80 93 | 94 | STOPSIGNAL SIGQUIT 95 | 96 | CMD ["nginx", "-g", "daemon off;"] 97 | -------------------------------------------------------------------------------- /docker/alpine/static/nginx.conf: -------------------------------------------------------------------------------- 1 | user nginx; 2 | worker_processes 1; 3 | error_log /var/log/nginx/error.log debug; 4 | pid /run/nginx.pid; 5 | events { 6 | worker_connections 1024; 7 | } 8 | http { 9 | log_format main '$remote_addr - $remote_user [$time_local] "$request" ' 10 | '$status $body_bytes_sent "$http_referer" ' 11 | '"$http_user_agent" "$http_x_forwarded_for"'; 12 | 13 | access_log /var/log/nginx/access.log main; 14 | sendfile on; 15 | keepalive_timeout 65; 16 | 17 | upstream backend { 18 | server localhost:8081; 19 | ntlm; 20 | } 21 | 22 | server { 23 | listen 80; 24 | server_name _; 25 | 26 | root /etc/nginx/html; 27 | index index.html; 28 | 29 | location /ntlm { 30 | proxy_pass http://backend; 31 | proxy_http_version 1.1; 32 | proxy_set_header Connection ""; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /docker/openresty/alpine/dynamic/Dockerfile: -------------------------------------------------------------------------------- 1 | # The entire file was copied from here 2 | # https://github.com/openresty/docker-openresty/blob/master/alpine/Dockerfile 3 | # and added the ntlm module 4 | 5 | ARG RESTY_IMAGE_BASE="alpine" 6 | ARG RESTY_IMAGE_TAG="3.13" 7 | 8 | FROM ${RESTY_IMAGE_BASE}:${RESTY_IMAGE_TAG} as builder 9 | 10 | LABEL maintainer="Evan Wies " 11 | 12 | # Docker Build Arguments 13 | ARG RESTY_IMAGE_BASE="alpine" 14 | ARG RESTY_IMAGE_TAG="3.13" 15 | ARG RESTY_VERSION="1.19.3.1" 16 | ARG RESTY_OPENSSL_VERSION="1.1.1k" 17 | ARG RESTY_OPENSSL_PATCH_VERSION="1.1.1f" 18 | ARG RESTY_OPENSSL_URL_BASE="https://www.openssl.org/source" 19 | ARG RESTY_PCRE_VERSION="8.44" 20 | ARG RESTY_J="1" 21 | ARG RESTY_CONFIG_OPTIONS="\ 22 | --with-compat \ 23 | --with-file-aio \ 24 | --with-http_addition_module \ 25 | --with-http_auth_request_module \ 26 | --with-http_dav_module \ 27 | --with-http_flv_module \ 28 | --with-http_geoip_module=dynamic \ 29 | --with-http_gunzip_module \ 30 | --with-http_gzip_static_module \ 31 | --with-http_image_filter_module=dynamic \ 32 | --with-http_mp4_module \ 33 | --with-http_random_index_module \ 34 | --with-http_realip_module \ 35 | --with-http_secure_link_module \ 36 | --with-http_slice_module \ 37 | --with-http_ssl_module \ 38 | --with-http_stub_status_module \ 39 | --with-http_sub_module \ 40 | --with-http_v2_module \ 41 | --with-http_xslt_module=dynamic \ 42 | --with-ipv6 \ 43 | --with-mail \ 44 | --with-mail_ssl_module \ 45 | --with-md5-asm \ 46 | --with-pcre-jit \ 47 | --with-sha1-asm \ 48 | --with-stream \ 49 | --with-stream_ssl_module \ 50 | --with-threads \ 51 | --add-dynamic-module=../nginx-ntlm-module \ 52 | " 53 | ARG RESTY_CONFIG_OPTIONS_MORE="" 54 | ARG RESTY_LUAJIT_OPTIONS="--with-luajit-xcflags='-DLUAJIT_NUMMODE=2 -DLUAJIT_ENABLE_LUA52COMPAT'" 55 | 56 | ARG RESTY_ADD_PACKAGE_BUILDDEPS="" 57 | ARG RESTY_ADD_PACKAGE_RUNDEPS="" 58 | ARG RESTY_EVAL_PRE_CONFIGURE="" 59 | ARG RESTY_EVAL_POST_MAKE="" 60 | 61 | # These are not intended to be user-specified 62 | ARG _RESTY_CONFIG_DEPS="--with-pcre \ 63 | --with-cc-opt='-DNGX_LUA_ABORT_AT_PANIC -I/usr/local/openresty/pcre/include -I/usr/local/openresty/openssl/include' \ 64 | --with-ld-opt='-L/usr/local/openresty/pcre/lib -L/usr/local/openresty/openssl/lib -Wl,-rpath,/usr/local/openresty/pcre/lib:/usr/local/openresty/openssl/lib' \ 65 | " 66 | 67 | LABEL resty_image_base="${RESTY_IMAGE_BASE}" 68 | LABEL resty_image_tag="${RESTY_IMAGE_TAG}" 69 | LABEL resty_version="${RESTY_VERSION}" 70 | LABEL resty_openssl_version="${RESTY_OPENSSL_VERSION}" 71 | LABEL resty_openssl_patch_version="${RESTY_OPENSSL_PATCH_VERSION}" 72 | LABEL resty_openssl_url_base="${RESTY_OPENSSL_URL_BASE}" 73 | LABEL resty_pcre_version="${RESTY_PCRE_VERSION}" 74 | LABEL resty_config_options="${RESTY_CONFIG_OPTIONS}" 75 | LABEL resty_config_options_more="${RESTY_CONFIG_OPTIONS_MORE}" 76 | LABEL resty_config_deps="${_RESTY_CONFIG_DEPS}" 77 | LABEL resty_add_package_builddeps="${RESTY_ADD_PACKAGE_BUILDDEPS}" 78 | LABEL resty_add_package_rundeps="${RESTY_ADD_PACKAGE_RUNDEPS}" 79 | LABEL resty_eval_pre_configure="${RESTY_EVAL_PRE_CONFIGURE}" 80 | LABEL resty_eval_post_make="${RESTY_EVAL_POST_MAKE}" 81 | 82 | 83 | RUN apk add --no-cache --virtual .build-deps \ 84 | build-base \ 85 | coreutils \ 86 | curl \ 87 | git \ 88 | gd-dev \ 89 | geoip-dev \ 90 | libxslt-dev \ 91 | linux-headers \ 92 | make \ 93 | perl-dev \ 94 | readline-dev \ 95 | zlib-dev \ 96 | ${RESTY_ADD_PACKAGE_BUILDDEPS} \ 97 | && apk add --no-cache \ 98 | gd \ 99 | geoip \ 100 | libgcc \ 101 | libxslt \ 102 | zlib \ 103 | ${RESTY_ADD_PACKAGE_RUNDEPS} \ 104 | && cd /tmp \ 105 | && if [ -n "${RESTY_EVAL_PRE_CONFIGURE}" ]; then eval $(echo ${RESTY_EVAL_PRE_CONFIGURE}); fi \ 106 | && cd /tmp \ 107 | && curl -fSL "${RESTY_OPENSSL_URL_BASE}/openssl-${RESTY_OPENSSL_VERSION}.tar.gz" -o openssl-${RESTY_OPENSSL_VERSION}.tar.gz \ 108 | && tar xzf openssl-${RESTY_OPENSSL_VERSION}.tar.gz \ 109 | && cd openssl-${RESTY_OPENSSL_VERSION} \ 110 | && if [ $(echo ${RESTY_OPENSSL_VERSION} | cut -c 1-5) = "1.1.1" ] ; then \ 111 | echo 'patching OpenSSL 1.1.1 for OpenResty' \ 112 | && curl -s https://raw.githubusercontent.com/openresty/openresty/master/patches/openssl-${RESTY_OPENSSL_PATCH_VERSION}-sess_set_get_cb_yield.patch | patch -p1 ; \ 113 | fi \ 114 | && if [ $(echo ${RESTY_OPENSSL_VERSION} | cut -c 1-5) = "1.1.0" ] ; then \ 115 | echo 'patching OpenSSL 1.1.0 for OpenResty' \ 116 | && curl -s https://raw.githubusercontent.com/openresty/openresty/ed328977028c3ec3033bc25873ee360056e247cd/patches/openssl-1.1.0j-parallel_build_fix.patch | patch -p1 \ 117 | && curl -s https://raw.githubusercontent.com/openresty/openresty/master/patches/openssl-${RESTY_OPENSSL_PATCH_VERSION}-sess_set_get_cb_yield.patch | patch -p1 ; \ 118 | fi \ 119 | && ./config \ 120 | no-threads shared zlib -g \ 121 | enable-ssl3 enable-ssl3-method \ 122 | --prefix=/usr/local/openresty/openssl \ 123 | --libdir=lib \ 124 | -Wl,-rpath,/usr/local/openresty/openssl/lib \ 125 | && make -j${RESTY_J} \ 126 | && make -j${RESTY_J} install_sw \ 127 | && cd /tmp \ 128 | && curl -fSL https://ftp.pcre.org/pub/pcre/pcre-${RESTY_PCRE_VERSION}.tar.gz -o pcre-${RESTY_PCRE_VERSION}.tar.gz \ 129 | && tar xzf pcre-${RESTY_PCRE_VERSION}.tar.gz \ 130 | && cd /tmp/pcre-${RESTY_PCRE_VERSION} \ 131 | && ./configure \ 132 | --prefix=/usr/local/openresty/pcre \ 133 | --disable-cpp \ 134 | --enable-jit \ 135 | --enable-utf \ 136 | --enable-unicode-properties \ 137 | && make -j${RESTY_J} \ 138 | && make -j${RESTY_J} install \ 139 | && cd /tmp \ 140 | && curl -fSL https://openresty.org/download/openresty-${RESTY_VERSION}.tar.gz -o openresty-${RESTY_VERSION}.tar.gz \ 141 | && tar xzf openresty-${RESTY_VERSION}.tar.gz \ 142 | # clone the ntlm repository 143 | && git clone https://github.com/gabihodoroaga/nginx-ntlm-module.git \ 144 | # end 145 | && cd /tmp/openresty-${RESTY_VERSION} \ 146 | && eval ./configure -j${RESTY_J} ${_RESTY_CONFIG_DEPS} ${RESTY_CONFIG_OPTIONS} ${RESTY_CONFIG_OPTIONS_MORE} ${RESTY_LUAJIT_OPTIONS} \ 147 | && make -j${RESTY_J} 148 | 149 | 150 | FROM openresty/openresty:1.19.3.1-alpine 151 | 152 | COPY --from=builder /tmp/openresty-1.19.3.1/build/nginx-1.19.3/objs/ngx_http_upstream_ntlm_module.so /usr/local/openresty/nginx/modules/ngx_http_upstream_ntlm_module.so 153 | 154 | COPY nginx.conf /usr/local/openresty/nginx/conf/nginx.conf 155 | COPY nginx.vh.default.conf /etc/nginx/conf.d/default.conf 156 | -------------------------------------------------------------------------------- /docker/openresty/alpine/dynamic/nginx.conf: -------------------------------------------------------------------------------- 1 | # nginx.conf -- docker-openresty 2 | # 3 | # This file is installed to: 4 | # `/usr/local/openresty/nginx/conf/nginx.conf` 5 | # and is the file loaded by nginx at startup, 6 | # unless the user specifies otherwise. 7 | # 8 | # It tracks the upstream OpenResty's `nginx.conf`, but removes the `server` 9 | # section and adds this directive: 10 | # `include /etc/nginx/conf.d/*.conf;` 11 | # 12 | # The `docker-openresty` file `nginx.vh.default.conf` is copied to 13 | # `/etc/nginx/conf.d/default.conf`. It contains the `server section 14 | # of the upstream `nginx.conf`. 15 | # 16 | # See https://github.com/openresty/docker-openresty/blob/master/README.md#nginx-config-files 17 | # 18 | 19 | #user nobody; 20 | #worker_processes 1; 21 | 22 | # Enables the use of JIT for regular expressions to speed-up their processing. 23 | pcre_jit on; 24 | 25 | 26 | 27 | #error_log logs/error.log; 28 | #error_log logs/error.log notice; 29 | #error_log logs/error.log info; 30 | 31 | #pid logs/nginx.pid; 32 | 33 | 34 | events { 35 | worker_connections 1024; 36 | } 37 | 38 | 39 | http { 40 | include mime.types; 41 | default_type application/octet-stream; 42 | 43 | # Enables or disables the use of underscores in client request header fields. 44 | # When the use of underscores is disabled, request header fields whose names contain underscores are marked as invalid and become subject to the ignore_invalid_headers directive. 45 | # underscores_in_headers off; 46 | 47 | #log_format main '$remote_addr - $remote_user [$time_local] "$request" ' 48 | # '$status $body_bytes_sent "$http_referer" ' 49 | # '"$http_user_agent" "$http_x_forwarded_for"'; 50 | 51 | #access_log logs/access.log main; 52 | 53 | # Log in JSON Format 54 | # log_format nginxlog_json escape=json '{ "timestamp": "$time_iso8601", ' 55 | # '"remote_addr": "$remote_addr", ' 56 | # '"body_bytes_sent": $body_bytes_sent, ' 57 | # '"request_time": $request_time, ' 58 | # '"response_status": $status, ' 59 | # '"request": "$request", ' 60 | # '"request_method": "$request_method", ' 61 | # '"host": "$host",' 62 | # '"upstream_addr": "$upstream_addr",' 63 | # '"http_x_forwarded_for": "$http_x_forwarded_for",' 64 | # '"http_referrer": "$http_referer", ' 65 | # '"http_user_agent": "$http_user_agent", ' 66 | # '"http_version": "$server_protocol", ' 67 | # '"nginx_access": true }'; 68 | # access_log /dev/stdout nginxlog_json; 69 | 70 | # See Move default writable paths to a dedicated directory (#119) 71 | # https://github.com/openresty/docker-openresty/issues/119 72 | client_body_temp_path /var/run/openresty/nginx-client-body; 73 | proxy_temp_path /var/run/openresty/nginx-proxy; 74 | fastcgi_temp_path /var/run/openresty/nginx-fastcgi; 75 | uwsgi_temp_path /var/run/openresty/nginx-uwsgi; 76 | scgi_temp_path /var/run/openresty/nginx-scgi; 77 | 78 | sendfile on; 79 | #tcp_nopush on; 80 | 81 | #keepalive_timeout 0; 82 | keepalive_timeout 65; 83 | 84 | #gzip on; 85 | 86 | include /etc/nginx/conf.d/*.conf; 87 | 88 | # Don't reveal OpenResty version to clients. 89 | # server_tokens off; 90 | } 91 | -------------------------------------------------------------------------------- /docker/openresty/alpine/dynamic/nginx.vh.default.conf: -------------------------------------------------------------------------------- 1 | # nginx.vh.default.conf -- docker-openresty 2 | # 3 | # This file is installed to: 4 | # `/etc/nginx/conf.d/default.conf` 5 | # 6 | # It tracks the `server` section of the upstream OpenResty's `nginx.conf`. 7 | # 8 | # This config (and any other configs in `etc/nginx/conf.d/`) is loaded by 9 | # default by the `include` directive in `/usr/local/openresty/nginx/conf/nginx.conf`. 10 | # 11 | # See https://github.com/openresty/docker-openresty/blob/master/README.md#nginx-config-files 12 | # 13 | 14 | 15 | server { 16 | listen 80; 17 | server_name localhost; 18 | 19 | #charset koi8-r; 20 | #access_log /var/log/nginx/host.access.log main; 21 | 22 | location / { 23 | root /usr/local/openresty/nginx/html; 24 | index index.html index.htm; 25 | } 26 | 27 | #error_page 404 /404.html; 28 | 29 | # redirect server error pages to the static page /50x.html 30 | # 31 | error_page 500 502 503 504 /50x.html; 32 | location = /50x.html { 33 | root /usr/local/openresty/nginx/html; 34 | } 35 | 36 | # proxy the PHP scripts to Apache listening on 127.0.0.1:80 37 | # 38 | #location ~ \.php$ { 39 | # proxy_pass http://127.0.0.1; 40 | #} 41 | 42 | # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 43 | # 44 | #location ~ \.php$ { 45 | # root /usr/local/openresty/nginx/html; 46 | # fastcgi_pass 127.0.0.1:9000; 47 | # fastcgi_index index.php; 48 | # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; 49 | # include fastcgi_params; 50 | #} 51 | 52 | # deny access to .htaccess files, if Apache's document root 53 | # concurs with nginx's one 54 | # 55 | #location ~ /\.ht { 56 | # deny all; 57 | #} 58 | } 59 | -------------------------------------------------------------------------------- /docker/openresty/alpine/dynamic/test/default.conf: -------------------------------------------------------------------------------- 1 | 2 | upstream backend { 3 | server localhost:8081; 4 | ntlm; 5 | } 6 | 7 | server { 8 | listen 80; 9 | server_name localhost; 10 | 11 | location / { 12 | root /usr/local/openresty/nginx/html; 13 | index index.html index.htm; 14 | } 15 | 16 | location /ntlm { 17 | proxy_pass http://backend; 18 | proxy_http_version 1.1; 19 | proxy_set_header Connection ""; 20 | } 21 | 22 | error_page 500 502 503 504 /50x.html; 23 | location = /50x.html { 24 | root /usr/local/openresty/nginx/html; 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /docker/openresty/alpine/dynamic/test/nginx.conf: -------------------------------------------------------------------------------- 1 | # nginx.conf -- docker-openresty 2 | # 3 | # This file is installed to: 4 | # `/usr/local/openresty/nginx/conf/nginx.conf` 5 | # and is the file loaded by nginx at startup, 6 | # unless the user specifies otherwise. 7 | # 8 | # It tracks the upstream OpenResty's `nginx.conf`, but removes the `server` 9 | # section and adds this directive: 10 | # `include /etc/nginx/conf.d/*.conf;` 11 | # 12 | # The `docker-openresty` file `nginx.vh.default.conf` is copied to 13 | # `/etc/nginx/conf.d/default.conf`. It contains the `server section 14 | # of the upstream `nginx.conf`. 15 | # 16 | # See https://github.com/openresty/docker-openresty/blob/master/README.md#nginx-config-files 17 | # 18 | 19 | #user nobody; 20 | #worker_processes 1; 21 | 22 | # Enables the use of JIT for regular expressions to speed-up their processing. 23 | pcre_jit on; 24 | 25 | load_module modules/ngx_http_upstream_ntlm_module.so; 26 | 27 | #error_log logs/error.log; 28 | #error_log logs/error.log notice; 29 | #error_log logs/error.log info; 30 | 31 | #pid logs/nginx.pid; 32 | 33 | 34 | events { 35 | worker_connections 1024; 36 | } 37 | 38 | 39 | http { 40 | include mime.types; 41 | default_type application/octet-stream; 42 | 43 | # Enables or disables the use of underscores in client request header fields. 44 | # When the use of underscores is disabled, request header fields whose names contain underscores are marked as invalid and become subject to the ignore_invalid_headers directive. 45 | # underscores_in_headers off; 46 | 47 | #log_format main '$remote_addr - $remote_user [$time_local] "$request" ' 48 | # '$status $body_bytes_sent "$http_referer" ' 49 | # '"$http_user_agent" "$http_x_forwarded_for"'; 50 | 51 | #access_log logs/access.log main; 52 | 53 | # Log in JSON Format 54 | # log_format nginxlog_json escape=json '{ "timestamp": "$time_iso8601", ' 55 | # '"remote_addr": "$remote_addr", ' 56 | # '"body_bytes_sent": $body_bytes_sent, ' 57 | # '"request_time": $request_time, ' 58 | # '"response_status": $status, ' 59 | # '"request": "$request", ' 60 | # '"request_method": "$request_method", ' 61 | # '"host": "$host",' 62 | # '"upstream_addr": "$upstream_addr",' 63 | # '"http_x_forwarded_for": "$http_x_forwarded_for",' 64 | # '"http_referrer": "$http_referer", ' 65 | # '"http_user_agent": "$http_user_agent", ' 66 | # '"http_version": "$server_protocol", ' 67 | # '"nginx_access": true }'; 68 | # access_log /dev/stdout nginxlog_json; 69 | 70 | # See Move default writable paths to a dedicated directory (#119) 71 | # https://github.com/openresty/docker-openresty/issues/119 72 | client_body_temp_path /var/run/openresty/nginx-client-body; 73 | proxy_temp_path /var/run/openresty/nginx-proxy; 74 | fastcgi_temp_path /var/run/openresty/nginx-fastcgi; 75 | uwsgi_temp_path /var/run/openresty/nginx-uwsgi; 76 | scgi_temp_path /var/run/openresty/nginx-scgi; 77 | 78 | sendfile on; 79 | #tcp_nopush on; 80 | 81 | #keepalive_timeout 0; 82 | keepalive_timeout 65; 83 | 84 | #gzip on; 85 | 86 | include /etc/nginx/conf.d/*.conf; 87 | 88 | # Don't reveal OpenResty version to clients. 89 | # server_tokens off; 90 | } 91 | -------------------------------------------------------------------------------- /docker/openresty/alpine/static/Dockerfile: -------------------------------------------------------------------------------- 1 | # The entire file was copied from here 2 | # https://github.com/openresty/docker-openresty/blob/master/alpine/Dockerfile 3 | # and added the ntlm module 4 | 5 | ARG RESTY_IMAGE_BASE="alpine" 6 | ARG RESTY_IMAGE_TAG="3.13" 7 | 8 | FROM ${RESTY_IMAGE_BASE}:${RESTY_IMAGE_TAG} 9 | 10 | LABEL maintainer="Evan Wies " 11 | 12 | # Docker Build Arguments 13 | ARG RESTY_IMAGE_BASE="alpine" 14 | ARG RESTY_IMAGE_TAG="3.13" 15 | ARG RESTY_VERSION="1.19.3.1" 16 | ARG RESTY_OPENSSL_VERSION="1.1.1k" 17 | ARG RESTY_OPENSSL_PATCH_VERSION="1.1.1f" 18 | ARG RESTY_OPENSSL_URL_BASE="https://www.openssl.org/source" 19 | ARG RESTY_PCRE_VERSION="8.44" 20 | ARG RESTY_J="1" 21 | ARG RESTY_CONFIG_OPTIONS="\ 22 | --with-compat \ 23 | --with-file-aio \ 24 | --with-http_addition_module \ 25 | --with-http_auth_request_module \ 26 | --with-http_dav_module \ 27 | --with-http_flv_module \ 28 | --with-http_geoip_module=dynamic \ 29 | --with-http_gunzip_module \ 30 | --with-http_gzip_static_module \ 31 | --with-http_image_filter_module=dynamic \ 32 | --with-http_mp4_module \ 33 | --with-http_random_index_module \ 34 | --with-http_realip_module \ 35 | --with-http_secure_link_module \ 36 | --with-http_slice_module \ 37 | --with-http_ssl_module \ 38 | --with-http_stub_status_module \ 39 | --with-http_sub_module \ 40 | --with-http_v2_module \ 41 | --with-http_xslt_module=dynamic \ 42 | --with-ipv6 \ 43 | --with-mail \ 44 | --with-mail_ssl_module \ 45 | --with-md5-asm \ 46 | --with-pcre-jit \ 47 | --with-sha1-asm \ 48 | --with-stream \ 49 | --with-stream_ssl_module \ 50 | --with-threads \ 51 | --add-module=../nginx-ntlm-module \ 52 | " 53 | ARG RESTY_CONFIG_OPTIONS_MORE="" 54 | ARG RESTY_LUAJIT_OPTIONS="--with-luajit-xcflags='-DLUAJIT_NUMMODE=2 -DLUAJIT_ENABLE_LUA52COMPAT'" 55 | 56 | ARG RESTY_ADD_PACKAGE_BUILDDEPS="" 57 | ARG RESTY_ADD_PACKAGE_RUNDEPS="" 58 | ARG RESTY_EVAL_PRE_CONFIGURE="" 59 | ARG RESTY_EVAL_POST_MAKE="" 60 | 61 | # These are not intended to be user-specified 62 | ARG _RESTY_CONFIG_DEPS="--with-pcre \ 63 | --with-cc-opt='-DNGX_LUA_ABORT_AT_PANIC -I/usr/local/openresty/pcre/include -I/usr/local/openresty/openssl/include' \ 64 | --with-ld-opt='-L/usr/local/openresty/pcre/lib -L/usr/local/openresty/openssl/lib -Wl,-rpath,/usr/local/openresty/pcre/lib:/usr/local/openresty/openssl/lib' \ 65 | " 66 | 67 | LABEL resty_image_base="${RESTY_IMAGE_BASE}" 68 | LABEL resty_image_tag="${RESTY_IMAGE_TAG}" 69 | LABEL resty_version="${RESTY_VERSION}" 70 | LABEL resty_openssl_version="${RESTY_OPENSSL_VERSION}" 71 | LABEL resty_openssl_patch_version="${RESTY_OPENSSL_PATCH_VERSION}" 72 | LABEL resty_openssl_url_base="${RESTY_OPENSSL_URL_BASE}" 73 | LABEL resty_pcre_version="${RESTY_PCRE_VERSION}" 74 | LABEL resty_config_options="${RESTY_CONFIG_OPTIONS}" 75 | LABEL resty_config_options_more="${RESTY_CONFIG_OPTIONS_MORE}" 76 | LABEL resty_config_deps="${_RESTY_CONFIG_DEPS}" 77 | LABEL resty_add_package_builddeps="${RESTY_ADD_PACKAGE_BUILDDEPS}" 78 | LABEL resty_add_package_rundeps="${RESTY_ADD_PACKAGE_RUNDEPS}" 79 | LABEL resty_eval_pre_configure="${RESTY_EVAL_PRE_CONFIGURE}" 80 | LABEL resty_eval_post_make="${RESTY_EVAL_POST_MAKE}" 81 | 82 | 83 | RUN apk add --no-cache --virtual .build-deps \ 84 | build-base \ 85 | coreutils \ 86 | curl \ 87 | git \ 88 | gd-dev \ 89 | geoip-dev \ 90 | libxslt-dev \ 91 | linux-headers \ 92 | make \ 93 | perl-dev \ 94 | readline-dev \ 95 | zlib-dev \ 96 | ${RESTY_ADD_PACKAGE_BUILDDEPS} \ 97 | && apk add --no-cache \ 98 | gd \ 99 | geoip \ 100 | libgcc \ 101 | libxslt \ 102 | zlib \ 103 | ${RESTY_ADD_PACKAGE_RUNDEPS} \ 104 | && cd /tmp \ 105 | && if [ -n "${RESTY_EVAL_PRE_CONFIGURE}" ]; then eval $(echo ${RESTY_EVAL_PRE_CONFIGURE}); fi \ 106 | && cd /tmp \ 107 | && curl -fSL "${RESTY_OPENSSL_URL_BASE}/openssl-${RESTY_OPENSSL_VERSION}.tar.gz" -o openssl-${RESTY_OPENSSL_VERSION}.tar.gz \ 108 | && tar xzf openssl-${RESTY_OPENSSL_VERSION}.tar.gz \ 109 | && cd openssl-${RESTY_OPENSSL_VERSION} \ 110 | && if [ $(echo ${RESTY_OPENSSL_VERSION} | cut -c 1-5) = "1.1.1" ] ; then \ 111 | echo 'patching OpenSSL 1.1.1 for OpenResty' \ 112 | && curl -s https://raw.githubusercontent.com/openresty/openresty/master/patches/openssl-${RESTY_OPENSSL_PATCH_VERSION}-sess_set_get_cb_yield.patch | patch -p1 ; \ 113 | fi \ 114 | && if [ $(echo ${RESTY_OPENSSL_VERSION} | cut -c 1-5) = "1.1.0" ] ; then \ 115 | echo 'patching OpenSSL 1.1.0 for OpenResty' \ 116 | && curl -s https://raw.githubusercontent.com/openresty/openresty/ed328977028c3ec3033bc25873ee360056e247cd/patches/openssl-1.1.0j-parallel_build_fix.patch | patch -p1 \ 117 | && curl -s https://raw.githubusercontent.com/openresty/openresty/master/patches/openssl-${RESTY_OPENSSL_PATCH_VERSION}-sess_set_get_cb_yield.patch | patch -p1 ; \ 118 | fi \ 119 | && ./config \ 120 | no-threads shared zlib -g \ 121 | enable-ssl3 enable-ssl3-method \ 122 | --prefix=/usr/local/openresty/openssl \ 123 | --libdir=lib \ 124 | -Wl,-rpath,/usr/local/openresty/openssl/lib \ 125 | && make -j${RESTY_J} \ 126 | && make -j${RESTY_J} install_sw \ 127 | && cd /tmp \ 128 | && curl -fSL https://ftp.pcre.org/pub/pcre/pcre-${RESTY_PCRE_VERSION}.tar.gz -o pcre-${RESTY_PCRE_VERSION}.tar.gz \ 129 | && tar xzf pcre-${RESTY_PCRE_VERSION}.tar.gz \ 130 | && cd /tmp/pcre-${RESTY_PCRE_VERSION} \ 131 | && ./configure \ 132 | --prefix=/usr/local/openresty/pcre \ 133 | --disable-cpp \ 134 | --enable-jit \ 135 | --enable-utf \ 136 | --enable-unicode-properties \ 137 | && make -j${RESTY_J} \ 138 | && make -j${RESTY_J} install \ 139 | && cd /tmp \ 140 | && curl -fSL https://openresty.org/download/openresty-${RESTY_VERSION}.tar.gz -o openresty-${RESTY_VERSION}.tar.gz \ 141 | && tar xzf openresty-${RESTY_VERSION}.tar.gz \ 142 | # clone the ntlm repository 143 | && git clone https://github.com/gabihodoroaga/nginx-ntlm-module.git \ 144 | # end 145 | && cd /tmp/openresty-${RESTY_VERSION} \ 146 | && eval ./configure -j${RESTY_J} ${_RESTY_CONFIG_DEPS} ${RESTY_CONFIG_OPTIONS} ${RESTY_CONFIG_OPTIONS_MORE} ${RESTY_LUAJIT_OPTIONS} \ 147 | && make -j${RESTY_J} \ 148 | && make -j${RESTY_J} install \ 149 | && cd /tmp \ 150 | && if [ -n "${RESTY_EVAL_POST_MAKE}" ]; then eval $(echo ${RESTY_EVAL_POST_MAKE}); fi \ 151 | && rm -rf \ 152 | openssl-${RESTY_OPENSSL_VERSION}.tar.gz openssl-${RESTY_OPENSSL_VERSION} \ 153 | pcre-${RESTY_PCRE_VERSION}.tar.gz pcre-${RESTY_PCRE_VERSION} \ 154 | openresty-${RESTY_VERSION}.tar.gz openresty-${RESTY_VERSION} \ 155 | && apk del .build-deps \ 156 | && mkdir -p /var/run/openresty \ 157 | && ln -sf /dev/stdout /usr/local/openresty/nginx/logs/access.log \ 158 | && ln -sf /dev/stderr /usr/local/openresty/nginx/logs/error.log 159 | 160 | # Add additional binaries into PATH for convenience 161 | ENV PATH=$PATH:/usr/local/openresty/luajit/bin:/usr/local/openresty/nginx/sbin:/usr/local/openresty/bin 162 | 163 | # Copy nginx configuration files 164 | COPY nginx.conf /usr/local/openresty/nginx/conf/nginx.conf 165 | COPY nginx.vh.default.conf /etc/nginx/conf.d/default.conf 166 | 167 | CMD ["/usr/local/openresty/bin/openresty", "-g", "daemon off;"] 168 | 169 | # Use SIGQUIT instead of default SIGTERM to cleanly drain requests 170 | # See https://github.com/openresty/docker-openresty/blob/master/README.md#tips--pitfalls 171 | STOPSIGNAL SIGQUIT 172 | -------------------------------------------------------------------------------- /docker/openresty/alpine/static/nginx.conf: -------------------------------------------------------------------------------- 1 | # nginx.conf -- docker-openresty 2 | # 3 | # This file is installed to: 4 | # `/usr/local/openresty/nginx/conf/nginx.conf` 5 | # and is the file loaded by nginx at startup, 6 | # unless the user specifies otherwise. 7 | # 8 | # It tracks the upstream OpenResty's `nginx.conf`, but removes the `server` 9 | # section and adds this directive: 10 | # `include /etc/nginx/conf.d/*.conf;` 11 | # 12 | # The `docker-openresty` file `nginx.vh.default.conf` is copied to 13 | # `/etc/nginx/conf.d/default.conf`. It contains the `server section 14 | # of the upstream `nginx.conf`. 15 | # 16 | # See https://github.com/openresty/docker-openresty/blob/master/README.md#nginx-config-files 17 | # 18 | 19 | #user nobody; 20 | #worker_processes 1; 21 | 22 | # Enables the use of JIT for regular expressions to speed-up their processing. 23 | pcre_jit on; 24 | 25 | 26 | 27 | #error_log logs/error.log; 28 | #error_log logs/error.log notice; 29 | #error_log logs/error.log info; 30 | 31 | #pid logs/nginx.pid; 32 | 33 | 34 | events { 35 | worker_connections 1024; 36 | } 37 | 38 | 39 | http { 40 | include mime.types; 41 | default_type application/octet-stream; 42 | 43 | # Enables or disables the use of underscores in client request header fields. 44 | # When the use of underscores is disabled, request header fields whose names contain underscores are marked as invalid and become subject to the ignore_invalid_headers directive. 45 | # underscores_in_headers off; 46 | 47 | #log_format main '$remote_addr - $remote_user [$time_local] "$request" ' 48 | # '$status $body_bytes_sent "$http_referer" ' 49 | # '"$http_user_agent" "$http_x_forwarded_for"'; 50 | 51 | #access_log logs/access.log main; 52 | 53 | # Log in JSON Format 54 | # log_format nginxlog_json escape=json '{ "timestamp": "$time_iso8601", ' 55 | # '"remote_addr": "$remote_addr", ' 56 | # '"body_bytes_sent": $body_bytes_sent, ' 57 | # '"request_time": $request_time, ' 58 | # '"response_status": $status, ' 59 | # '"request": "$request", ' 60 | # '"request_method": "$request_method", ' 61 | # '"host": "$host",' 62 | # '"upstream_addr": "$upstream_addr",' 63 | # '"http_x_forwarded_for": "$http_x_forwarded_for",' 64 | # '"http_referrer": "$http_referer", ' 65 | # '"http_user_agent": "$http_user_agent", ' 66 | # '"http_version": "$server_protocol", ' 67 | # '"nginx_access": true }'; 68 | # access_log /dev/stdout nginxlog_json; 69 | 70 | # See Move default writable paths to a dedicated directory (#119) 71 | # https://github.com/openresty/docker-openresty/issues/119 72 | client_body_temp_path /var/run/openresty/nginx-client-body; 73 | proxy_temp_path /var/run/openresty/nginx-proxy; 74 | fastcgi_temp_path /var/run/openresty/nginx-fastcgi; 75 | uwsgi_temp_path /var/run/openresty/nginx-uwsgi; 76 | scgi_temp_path /var/run/openresty/nginx-scgi; 77 | 78 | sendfile on; 79 | #tcp_nopush on; 80 | 81 | #keepalive_timeout 0; 82 | keepalive_timeout 65; 83 | 84 | #gzip on; 85 | 86 | include /etc/nginx/conf.d/*.conf; 87 | 88 | # Don't reveal OpenResty version to clients. 89 | # server_tokens off; 90 | } 91 | -------------------------------------------------------------------------------- /docker/openresty/alpine/static/nginx.vh.default.conf: -------------------------------------------------------------------------------- 1 | # nginx.vh.default.conf -- docker-openresty 2 | # 3 | # This file is installed to: 4 | # `/etc/nginx/conf.d/default.conf` 5 | # 6 | # It tracks the `server` section of the upstream OpenResty's `nginx.conf`. 7 | # 8 | # This config (and any other configs in `etc/nginx/conf.d/`) is loaded by 9 | # default by the `include` directive in `/usr/local/openresty/nginx/conf/nginx.conf`. 10 | # 11 | # See https://github.com/openresty/docker-openresty/blob/master/README.md#nginx-config-files 12 | # 13 | 14 | 15 | server { 16 | listen 80; 17 | server_name localhost; 18 | 19 | #charset koi8-r; 20 | #access_log /var/log/nginx/host.access.log main; 21 | 22 | location / { 23 | root /usr/local/openresty/nginx/html; 24 | index index.html index.htm; 25 | } 26 | 27 | #error_page 404 /404.html; 28 | 29 | # redirect server error pages to the static page /50x.html 30 | # 31 | error_page 500 502 503 504 /50x.html; 32 | location = /50x.html { 33 | root /usr/local/openresty/nginx/html; 34 | } 35 | 36 | # proxy the PHP scripts to Apache listening on 127.0.0.1:80 37 | # 38 | #location ~ \.php$ { 39 | # proxy_pass http://127.0.0.1; 40 | #} 41 | 42 | # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 43 | # 44 | #location ~ \.php$ { 45 | # root /usr/local/openresty/nginx/html; 46 | # fastcgi_pass 127.0.0.1:9000; 47 | # fastcgi_index index.php; 48 | # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; 49 | # include fastcgi_params; 50 | #} 51 | 52 | # deny access to .htaccess files, if Apache's document root 53 | # concurs with nginx's one 54 | # 55 | #location ~ /\.ht { 56 | # deny all; 57 | #} 58 | } 59 | -------------------------------------------------------------------------------- /docker/openresty/alpine/static/test/default.conf: -------------------------------------------------------------------------------- 1 | 2 | upstream backend { 3 | server localhost:8081; 4 | ntlm; 5 | } 6 | 7 | server { 8 | listen 80; 9 | server_name localhost; 10 | 11 | location / { 12 | root /usr/local/openresty/nginx/html; 13 | index index.html index.htm; 14 | } 15 | 16 | location /ntlm { 17 | proxy_pass http://backend; 18 | proxy_http_version 1.1; 19 | proxy_set_header Connection ""; 20 | } 21 | 22 | error_page 500 502 503 504 /50x.html; 23 | location = /50x.html { 24 | root /usr/local/openresty/nginx/html; 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /docker/readme.md: -------------------------------------------------------------------------------- 1 | # Build using docker 2 | 3 | This document describes the steps to follow in order to build this modules using docker 4 | 5 | ## alpine - static 6 | 7 | ```bash 8 | cd alpine/static 9 | # build 10 | docker build -t nginx-ntlm . 11 | 12 | # test 13 | docker run --rm -it -p 8080:80 \ 14 | -v $(PWD)/nginx.conf:/etc/nginx/nginx.conf \ 15 | nginx-ntlm 16 | 17 | # if nginx starts without error you are good to go 18 | ``` 19 | 20 | ## alpine - dynamic 21 | 22 | ```bash 23 | cd alpine/dynamic 24 | 25 | # build 26 | docker build -t nginx-ntlm-dynamic . 27 | 28 | # test 29 | docker run --rm -it -p 8080:80 \ 30 | -v $(PWD)/nginx.conf:/etc/nginx/nginx.conf \ 31 | nginx-ntlm-dynamic 32 | 33 | # if nginx starts without error you are good to go 34 | ``` 35 | 36 | ## openresty alpine - using official build image 37 | 38 | ```bash 39 | docker build -t openresty-ntlm \ 40 | -f alpine/Dockerfile \ 41 | --build-arg RESTY_CONFIG_OPTIONS_MORE="--add-module=../nginx-ntlm-module" \ 42 | --build-arg RESTY_EVAL_PRE_CONFIGURE="curl -L https://github.com/gabihodoroaga/nginx-ntlm-module/archive/refs/tags/v1.19.3-beta.1.tar.gz -o nginx-ntlm-module.tar.gz && tar -xvzf nginx-ntlm-module.tar.gz && mv nginx-ntlm-module-1.19.3-beta.1 nginx-ntlm-module" \ 43 | https://github.com/openresty/docker-openresty.git 44 | ``` 45 | 46 | ## openresty alpine - static 47 | 48 | ```bash 49 | cd openresty/alpine/static 50 | 51 | # build 52 | docker build -t openresty-ntlm . 53 | 54 | # test 55 | docker run --rm -it -p 8080:80 \ 56 | -v $(PWD)/test/default.conf:/etc/nginx/conf.d/default.conf \ 57 | openresty-ntlm 58 | 59 | # if nginx starts without error you are good to go 60 | ``` 61 | 62 | ## openresty alpine - dynamic 63 | 64 | ```bash 65 | cd openresty/alpine/dynamic 66 | 67 | # build 68 | docker build -t openresty-ntlm-dynamic . 69 | 70 | # test 71 | docker run --rm -it -p 8080:80 \ 72 | -v $(PWD)/test/default.conf:/etc/nginx/conf.d/default.conf \ 73 | -v $(PWD)/test/nginx.conf:/usr/local/openresty/nginx/conf/nginx.conf \ 74 | openresty-ntlm-dynamic 75 | 76 | # if nginx starts without error you are good to go 77 | ``` 78 | -------------------------------------------------------------------------------- /ngx_http_upstream_ntlm_module.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | static ngx_int_t 6 | ngx_http_upstream_init_ntlm_peer(ngx_http_request_t *r, 7 | ngx_http_upstream_srv_conf_t *us); 8 | static ngx_int_t ngx_http_upstream_get_ntlm_peer(ngx_peer_connection_t *pc, 9 | void *data); 10 | static void ngx_http_upstream_free_ntlm_peer(ngx_peer_connection_t *pc, 11 | void *data, ngx_uint_t state); 12 | 13 | static void ngx_http_upstream_ntlm_dummy_handler(ngx_event_t *ev); 14 | static void ngx_http_upstream_ntlm_close_handler(ngx_event_t *ev); 15 | static void ngx_http_upstream_ntlm_close(ngx_connection_t *c); 16 | 17 | #if (NGX_HTTP_SSL) 18 | static ngx_int_t ngx_http_upstream_ntlm_set_session(ngx_peer_connection_t *pc, 19 | void *data); 20 | static void ngx_http_upstream_ntlm_save_session(ngx_peer_connection_t *pc, 21 | void *data); 22 | #endif 23 | 24 | static void *ngx_http_upstream_ntlm_create_conf(ngx_conf_t *cf); 25 | static char *ngx_http_upstream_ntlm(ngx_conf_t *cf, ngx_command_t *cmd, 26 | void *conf); 27 | 28 | static void ngx_http_upstream_client_conn_cleanup(void *data); 29 | 30 | typedef struct { 31 | ngx_uint_t max_cached; 32 | ngx_msec_t timeout; 33 | ngx_queue_t free; 34 | ngx_queue_t cache; 35 | ngx_http_upstream_init_pt original_init_upstream; 36 | ngx_http_upstream_init_peer_pt original_init_peer; 37 | } ngx_http_upstream_ntlm_srv_conf_t; 38 | 39 | typedef struct { 40 | ngx_http_upstream_ntlm_srv_conf_t *conf; 41 | ngx_queue_t queue; 42 | ngx_connection_t *peer_connection; 43 | ngx_connection_t *client_connection; 44 | } ngx_http_upstream_ntlm_cache_t; 45 | 46 | typedef struct { 47 | ngx_http_upstream_ntlm_srv_conf_t *conf; 48 | ngx_http_upstream_t *upstream; 49 | void *data; 50 | ngx_connection_t *client_connection; 51 | unsigned cached : 1; 52 | unsigned ntlm_init : 1; 53 | ngx_event_get_peer_pt original_get_peer; 54 | ngx_event_free_peer_pt original_free_peer; 55 | #if (NGX_HTTP_SSL) 56 | ngx_event_set_peer_session_pt original_set_session; 57 | ngx_event_save_peer_session_pt original_save_session; 58 | #endif 59 | 60 | } ngx_http_upstream_ntlm_peer_data_t; 61 | 62 | static ngx_command_t ngx_http_upstream_ntlm_commands[] = { 63 | 64 | {ngx_string("ntlm"), NGX_HTTP_UPS_CONF | NGX_CONF_NOARGS | NGX_CONF_TAKE1, 65 | ngx_http_upstream_ntlm, NGX_HTTP_SRV_CONF_OFFSET, 0, NULL}, 66 | 67 | {ngx_string("ntlm_timeout"), NGX_HTTP_UPS_CONF | NGX_CONF_TAKE1, 68 | ngx_conf_set_msec_slot, NGX_HTTP_SRV_CONF_OFFSET, 69 | offsetof(ngx_http_upstream_ntlm_srv_conf_t, timeout), NULL}, 70 | 71 | ngx_null_command /* command termination */ 72 | }; 73 | 74 | /* The module context */ 75 | static ngx_http_module_t ngx_http_upstream_ntlm_ctx = { 76 | NULL, /* preconfiguration */ 77 | NULL, /* postconfiguration */ 78 | 79 | NULL, /* create main configuration */ 80 | NULL, /* init main configuration */ 81 | 82 | ngx_http_upstream_ntlm_create_conf, /* create server configuration */ 83 | NULL, /* merge server configuration */ 84 | 85 | NULL, /* create location configuration */ 86 | NULL /* merge location configuration */ 87 | }; 88 | 89 | /* The module definition */ 90 | ngx_module_t ngx_http_upstream_ntlm_module = { 91 | NGX_MODULE_V1, 92 | &ngx_http_upstream_ntlm_ctx, /* module context */ 93 | ngx_http_upstream_ntlm_commands, /* module directives */ 94 | NGX_HTTP_MODULE, /* module type */ 95 | NULL, /* init master */ 96 | NULL, /* init module */ 97 | NULL, /* init process */ 98 | NULL, /* init thread */ 99 | NULL, /* exit thread */ 100 | NULL, /* exit process */ 101 | NULL, /* exit master */ 102 | NGX_MODULE_V1_PADDING}; 103 | 104 | static ngx_int_t ngx_http_upstream_init_ntlm(ngx_conf_t *cf, 105 | ngx_http_upstream_srv_conf_t *us) { 106 | ngx_uint_t i; 107 | ngx_http_upstream_ntlm_cache_t *cached; 108 | ngx_http_upstream_ntlm_srv_conf_t *hncf; 109 | 110 | ngx_log_debug0(NGX_LOG_DEBUG_HTTP, cf->log, 0, "ntlm init"); 111 | 112 | hncf = ngx_http_conf_upstream_srv_conf(us, ngx_http_upstream_ntlm_module); 113 | 114 | ngx_conf_init_uint_value(hncf->max_cached, 100); 115 | ngx_conf_init_msec_value(hncf->timeout, 60000); 116 | 117 | if (hncf->original_init_upstream(cf, us) != NGX_OK) { 118 | return NGX_ERROR; 119 | } 120 | 121 | hncf->original_init_peer = us->peer.init; 122 | us->peer.init = ngx_http_upstream_init_ntlm_peer; 123 | 124 | cached = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_ntlm_cache_t) * 125 | hncf->max_cached); 126 | if (cached == NULL) { 127 | return NGX_ERROR; 128 | } 129 | 130 | ngx_queue_init(&hncf->cache); 131 | ngx_queue_init(&hncf->free); 132 | 133 | for (i = 0; i < hncf->max_cached; i++) { 134 | ngx_queue_insert_head(&hncf->free, &cached[i].queue); 135 | cached[i].conf = hncf; 136 | } 137 | 138 | return NGX_OK; 139 | } 140 | 141 | static ngx_int_t 142 | ngx_http_upstream_init_ntlm_peer(ngx_http_request_t *r, 143 | ngx_http_upstream_srv_conf_t *us) { 144 | ngx_http_upstream_ntlm_peer_data_t *hnpd; 145 | ngx_http_upstream_ntlm_srv_conf_t *hncf; 146 | ngx_str_t auth_header_value; 147 | 148 | // get the upstream configuration 149 | hncf = ngx_http_conf_upstream_srv_conf(us, ngx_http_upstream_ntlm_module); 150 | 151 | // alocate memory for peer data 152 | hnpd = ngx_palloc(r->pool, sizeof(ngx_http_upstream_ntlm_peer_data_t)); 153 | if (hnpd == NULL) { 154 | return NGX_ERROR; 155 | } 156 | 157 | if (hncf->original_init_peer(r, us) != NGX_OK) { 158 | return NGX_ERROR; 159 | } 160 | 161 | hnpd->ntlm_init = 0; 162 | hnpd->cached = 0; 163 | 164 | if (r->headers_in.authorization != NULL) { 165 | auth_header_value = r->headers_in.authorization->value; 166 | 167 | if ((auth_header_value.len >= sizeof("NTLM") - 1 && 168 | ngx_strncasecmp(auth_header_value.data, (u_char *)"NTLM", 169 | sizeof("NTLM") - 1) == 0) || 170 | (auth_header_value.len >= sizeof("Negotiate") - 1 && 171 | ngx_strncasecmp(auth_header_value.data, (u_char *)"Negotiate", 172 | sizeof("Negotiate") - 1) == 0)) { 173 | ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 174 | "ntlm auth header found"); 175 | hnpd->ntlm_init = 1; 176 | } 177 | } 178 | 179 | hnpd->conf = hncf; 180 | hnpd->upstream = r->upstream; 181 | hnpd->data = r->upstream->peer.data; 182 | hnpd->client_connection = r->connection; 183 | 184 | hnpd->original_get_peer = r->upstream->peer.get; 185 | hnpd->original_free_peer = r->upstream->peer.free; 186 | 187 | r->upstream->peer.data = hnpd; 188 | r->upstream->peer.get = ngx_http_upstream_get_ntlm_peer; 189 | r->upstream->peer.free = ngx_http_upstream_free_ntlm_peer; 190 | 191 | #if (NGX_HTTP_SSL) 192 | hnpd->original_set_session = r->upstream->peer.set_session; 193 | hnpd->original_save_session = r->upstream->peer.save_session; 194 | 195 | r->upstream->peer.set_session = ngx_http_upstream_ntlm_set_session; 196 | r->upstream->peer.save_session = ngx_http_upstream_ntlm_save_session; 197 | #endif 198 | 199 | return NGX_OK; 200 | } 201 | 202 | static ngx_int_t ngx_http_upstream_get_ntlm_peer(ngx_peer_connection_t *pc, 203 | void *data) { 204 | ngx_http_upstream_ntlm_peer_data_t *hndp = data; 205 | ngx_http_upstream_ntlm_cache_t *item; 206 | 207 | ngx_int_t rc; 208 | ngx_queue_t *q, *cache; 209 | ngx_connection_t *c; 210 | 211 | /* ask balancer */ 212 | 213 | rc = hndp->original_get_peer(pc, hndp->data); 214 | 215 | if (rc != NGX_OK) { 216 | return rc; 217 | } 218 | 219 | /* search cache for suitable connection */ 220 | 221 | cache = &hndp->conf->cache; 222 | 223 | for (q = ngx_queue_head(cache); q != ngx_queue_sentinel(cache); 224 | q = ngx_queue_next(q)) { 225 | item = ngx_queue_data(q, ngx_http_upstream_ntlm_cache_t, queue); 226 | 227 | if (item->client_connection == hndp->client_connection) { 228 | c = item->peer_connection; 229 | ngx_queue_remove(q); 230 | ngx_queue_insert_head(&hndp->conf->free, q); 231 | hndp->cached = 1; 232 | goto found; 233 | } 234 | } 235 | 236 | return NGX_OK; 237 | 238 | found: 239 | 240 | ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0, 241 | "ntlm peer using connection %p", c); 242 | 243 | c->idle = 0; 244 | c->sent = 0; 245 | c->data = NULL; 246 | c->log = pc->log; 247 | c->read->log = pc->log; 248 | c->write->log = pc->log; 249 | c->pool->log = pc->log; 250 | 251 | if (c->read->timer_set) { 252 | ngx_del_timer(c->read); 253 | } 254 | 255 | pc->connection = c; 256 | pc->cached = 1; 257 | 258 | return NGX_DONE; 259 | } 260 | 261 | static void ngx_http_upstream_free_ntlm_peer(ngx_peer_connection_t *pc, 262 | void *data, ngx_uint_t state) { 263 | ngx_http_upstream_ntlm_peer_data_t *hndp = data; 264 | ngx_http_upstream_ntlm_cache_t *item; 265 | 266 | ngx_queue_t *q; 267 | ngx_connection_t *c; 268 | ngx_http_upstream_t *u; 269 | ngx_pool_cleanup_t *cln; 270 | ngx_http_upstream_ntlm_cache_t *cleanup_item = NULL; 271 | 272 | /* cache valid connections */ 273 | 274 | u = hndp->upstream; 275 | c = pc->connection; 276 | 277 | if (state & NGX_PEER_FAILED || c == NULL || c->read->eof || 278 | c->read->error || c->read->timedout || c->write->error || 279 | c->write->timedout) { 280 | goto invalid; 281 | } 282 | 283 | if (!u->keepalive) { 284 | goto invalid; 285 | } 286 | 287 | if (!u->request_body_sent) { 288 | goto invalid; 289 | } 290 | 291 | if (ngx_terminate || ngx_exiting) { 292 | goto invalid; 293 | } 294 | 295 | if (ngx_handle_read_event(c->read, 0) != NGX_OK) { 296 | goto invalid; 297 | } 298 | 299 | if (hndp->ntlm_init == 0 && hndp->cached == 0) { 300 | goto invalid; 301 | } 302 | 303 | if (ngx_queue_empty(&hndp->conf->free)) { 304 | q = ngx_queue_last(&hndp->conf->cache); 305 | ngx_queue_remove(q); 306 | 307 | item = ngx_queue_data(q, ngx_http_upstream_ntlm_cache_t, queue); 308 | ngx_http_upstream_ntlm_close(item->peer_connection); 309 | item->peer_connection = NULL; 310 | } else { 311 | q = ngx_queue_head(&hndp->conf->free); 312 | ngx_queue_remove(q); 313 | item = ngx_queue_data(q, ngx_http_upstream_ntlm_cache_t, queue); 314 | } 315 | 316 | ngx_queue_insert_head(&hndp->conf->cache, q); 317 | 318 | item->peer_connection = c; 319 | item->client_connection = hndp->client_connection; 320 | 321 | ngx_log_debug2( 322 | NGX_LOG_DEBUG_HTTP, pc->log, 0, 323 | "ntlm free peer saving item client_connection %p, pear connection %p", 324 | item->client_connection, c); 325 | 326 | // create the client connection drop down handler 327 | for (cln = item->client_connection->pool->cleanup; cln; cln = cln->next) { 328 | if (cln->handler == ngx_http_upstream_client_conn_cleanup) { 329 | cleanup_item = cln->data; 330 | break; 331 | } 332 | } 333 | if (cleanup_item == NULL) { 334 | cln = ngx_pool_cleanup_add(item->client_connection->pool, 0); 335 | if (cln == NULL) { 336 | ngx_log_debug0(NGX_LOG_DEBUG_HTTP, pc->log, 0, 337 | "ntlm free peer ngx_pool_cleanup_add returned null"); 338 | } else { 339 | cln->handler = ngx_http_upstream_client_conn_cleanup; 340 | cln->data = item; 341 | } 342 | } 343 | 344 | pc->connection = NULL; 345 | c->read->delayed = 0; 346 | 347 | ngx_add_timer(c->read, hndp->conf->timeout); 348 | 349 | if (c->write->timer_set) { 350 | ngx_del_timer(c->write); 351 | } 352 | 353 | c->write->handler = ngx_http_upstream_ntlm_dummy_handler; 354 | c->read->handler = ngx_http_upstream_ntlm_close_handler; 355 | 356 | c->data = item; 357 | c->idle = 1; 358 | c->log = ngx_cycle->log; 359 | c->read->log = ngx_cycle->log; 360 | c->write->log = ngx_cycle->log; 361 | c->pool->log = ngx_cycle->log; 362 | 363 | if (c->read->ready) { 364 | ngx_http_upstream_ntlm_close_handler(c->read); 365 | } 366 | 367 | invalid: 368 | hndp->original_free_peer(pc, hndp->data, state); 369 | } 370 | 371 | static void ngx_http_upstream_client_conn_cleanup(void *data) { 372 | ngx_http_upstream_ntlm_cache_t *item = data; 373 | 374 | ngx_log_debug2( 375 | NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0, 376 | "ntlm client connection closed %p, droping peer connection %p", 377 | item->client_connection, item->peer_connection); 378 | 379 | // Check if the item was removed previously from the queue (backend drop) 380 | if (item->peer_connection != NULL) { 381 | 382 | item->peer_connection->read->timedout = 1; 383 | ngx_post_event(item->peer_connection->read,&ngx_posted_events); 384 | 385 | ngx_queue_remove(&item->queue); 386 | ngx_queue_insert_head(&item->conf->free, &item->queue); 387 | } 388 | } 389 | 390 | static void ngx_http_upstream_ntlm_dummy_handler(ngx_event_t *ev) { 391 | ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ev->log, 0, "ntlm dummy handler"); 392 | } 393 | 394 | static void ngx_http_upstream_ntlm_close_handler(ngx_event_t *ev) { 395 | ngx_http_upstream_ntlm_srv_conf_t *conf; 396 | ngx_http_upstream_ntlm_cache_t *item; 397 | 398 | int n; 399 | char buf[1]; 400 | ngx_connection_t *c; 401 | 402 | c = ev->data; 403 | 404 | if (c->close || c->read->timedout) { 405 | goto close; 406 | } 407 | 408 | n = recv(c->fd, buf, 1, MSG_PEEK); 409 | 410 | if (n == -1 && ngx_socket_errno == NGX_EAGAIN) { 411 | ev->ready = 0; 412 | 413 | if (ngx_handle_read_event(c->read, 0) != NGX_OK) { 414 | goto close; 415 | } 416 | 417 | return; 418 | } 419 | 420 | close: 421 | 422 | ngx_log_debug2(NGX_LOG_DEBUG_HTTP, ev->log, 0, 423 | "ntlm close peer connection %p, timeout %ui", c, 424 | c->read->timedout); 425 | 426 | item = c->data; 427 | conf = item->conf; 428 | 429 | // set the item peer connection to null to make sure we don't close it again 430 | // when the client connection cleanup is triggered 431 | item->peer_connection = NULL; 432 | ngx_http_upstream_ntlm_close(c); 433 | 434 | ngx_queue_remove(&item->queue); 435 | ngx_queue_insert_head(&conf->free, &item->queue); 436 | } 437 | 438 | static void ngx_http_upstream_ntlm_close(ngx_connection_t *c) { 439 | 440 | #if (NGX_HTTP_SSL) 441 | 442 | if (c->ssl) { 443 | c->ssl->no_wait_shutdown = 1; 444 | c->ssl->no_send_shutdown = 1; 445 | 446 | if (ngx_ssl_shutdown(c) == NGX_AGAIN) { 447 | c->ssl->handler = ngx_http_upstream_ntlm_close; 448 | return; 449 | } 450 | } 451 | 452 | #endif 453 | 454 | if (c->pool) { 455 | ngx_destroy_pool(c->pool); 456 | c->pool = NULL; 457 | } 458 | ngx_close_connection(c); 459 | } 460 | 461 | #if (NGX_HTTP_SSL) 462 | 463 | static ngx_int_t ngx_http_upstream_ntlm_set_session(ngx_peer_connection_t *pc, 464 | void *data) { 465 | ngx_http_upstream_ntlm_peer_data_t *hndp = data; 466 | 467 | return hndp->original_set_session(pc, hndp->data); 468 | } 469 | 470 | static void ngx_http_upstream_ntlm_save_session(ngx_peer_connection_t *pc, 471 | void *data) { 472 | ngx_http_upstream_ntlm_peer_data_t *hndp = data; 473 | 474 | hndp->original_save_session(pc, hndp->data); 475 | return; 476 | } 477 | 478 | #endif 479 | 480 | static void *ngx_http_upstream_ntlm_create_conf(ngx_conf_t *cf) { 481 | ngx_http_upstream_ntlm_srv_conf_t *conf; 482 | conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_ntlm_srv_conf_t)); 483 | if (conf == NULL) { 484 | return NULL; 485 | } 486 | 487 | conf->max_cached = NGX_CONF_UNSET_UINT; 488 | conf->timeout = NGX_CONF_UNSET_MSEC; 489 | 490 | return conf; 491 | } 492 | 493 | static char *ngx_http_upstream_ntlm(ngx_conf_t *cf, ngx_command_t *cmd, 494 | void *conf) { 495 | ngx_http_upstream_srv_conf_t *uscf; 496 | ngx_http_upstream_ntlm_srv_conf_t *hncf = conf; 497 | 498 | ngx_int_t n; 499 | ngx_str_t *value; 500 | 501 | /* read options */ 502 | if (cf->args->nelts == 2) { 503 | value = cf->args->elts; 504 | n = ngx_atoi(value[1].data, value[1].len); 505 | if (n == NGX_ERROR || n == 0) { 506 | ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, 507 | "ntlm invalid value \"%V\" in \"%V\" directive", 508 | &value[1], &cmd->name); 509 | return NGX_CONF_ERROR; 510 | } 511 | hncf->max_cached = n; 512 | } 513 | 514 | uscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_upstream_module); 515 | 516 | hncf->original_init_upstream = uscf->peer.init_upstream 517 | ? uscf->peer.init_upstream 518 | : ngx_http_upstream_init_round_robin; 519 | 520 | uscf->peer.init_upstream = ngx_http_upstream_init_ntlm; 521 | 522 | return NGX_CONF_OK; 523 | } 524 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "requires": true, 3 | "lockfileVersion": 1, 4 | "dependencies": { 5 | "nginx-upstream-backend-test": { 6 | "version": "file:t/backend", 7 | "requires": { 8 | "express": "^4.17.1" 9 | }, 10 | "dependencies": { 11 | "accepts": { 12 | "version": "1.3.7", 13 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", 14 | "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", 15 | "requires": { 16 | "mime-types": "~2.1.24", 17 | "negotiator": "0.6.2" 18 | } 19 | }, 20 | "array-flatten": { 21 | "version": "1.1.1", 22 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 23 | "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" 24 | }, 25 | "body-parser": { 26 | "version": "1.19.0", 27 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", 28 | "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", 29 | "requires": { 30 | "bytes": "3.1.0", 31 | "content-type": "~1.0.4", 32 | "debug": "2.6.9", 33 | "depd": "~1.1.2", 34 | "http-errors": "1.7.2", 35 | "iconv-lite": "0.4.24", 36 | "on-finished": "~2.3.0", 37 | "qs": "6.7.0", 38 | "raw-body": "2.4.0", 39 | "type-is": "~1.6.17" 40 | } 41 | }, 42 | "bytes": { 43 | "version": "3.1.0", 44 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", 45 | "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" 46 | }, 47 | "content-disposition": { 48 | "version": "0.5.3", 49 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", 50 | "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", 51 | "requires": { 52 | "safe-buffer": "5.1.2" 53 | } 54 | }, 55 | "content-type": { 56 | "version": "1.0.4", 57 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", 58 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" 59 | }, 60 | "cookie": { 61 | "version": "0.4.0", 62 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", 63 | "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" 64 | }, 65 | "cookie-signature": { 66 | "version": "1.0.6", 67 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 68 | "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" 69 | }, 70 | "debug": { 71 | "version": "2.6.9", 72 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 73 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 74 | "requires": { 75 | "ms": "2.0.0" 76 | } 77 | }, 78 | "depd": { 79 | "version": "1.1.2", 80 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", 81 | "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" 82 | }, 83 | "destroy": { 84 | "version": "1.0.4", 85 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", 86 | "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" 87 | }, 88 | "ee-first": { 89 | "version": "1.1.1", 90 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 91 | "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" 92 | }, 93 | "encodeurl": { 94 | "version": "1.0.2", 95 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 96 | "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" 97 | }, 98 | "escape-html": { 99 | "version": "1.0.3", 100 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 101 | "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" 102 | }, 103 | "etag": { 104 | "version": "1.8.1", 105 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 106 | "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" 107 | }, 108 | "express": { 109 | "version": "4.17.1", 110 | "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", 111 | "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", 112 | "requires": { 113 | "accepts": "~1.3.7", 114 | "array-flatten": "1.1.1", 115 | "body-parser": "1.19.0", 116 | "content-disposition": "0.5.3", 117 | "content-type": "~1.0.4", 118 | "cookie": "0.4.0", 119 | "cookie-signature": "1.0.6", 120 | "debug": "2.6.9", 121 | "depd": "~1.1.2", 122 | "encodeurl": "~1.0.2", 123 | "escape-html": "~1.0.3", 124 | "etag": "~1.8.1", 125 | "finalhandler": "~1.1.2", 126 | "fresh": "0.5.2", 127 | "merge-descriptors": "1.0.1", 128 | "methods": "~1.1.2", 129 | "on-finished": "~2.3.0", 130 | "parseurl": "~1.3.3", 131 | "path-to-regexp": "0.1.7", 132 | "proxy-addr": "~2.0.5", 133 | "qs": "6.7.0", 134 | "range-parser": "~1.2.1", 135 | "safe-buffer": "5.1.2", 136 | "send": "0.17.1", 137 | "serve-static": "1.14.1", 138 | "setprototypeof": "1.1.1", 139 | "statuses": "~1.5.0", 140 | "type-is": "~1.6.18", 141 | "utils-merge": "1.0.1", 142 | "vary": "~1.1.2" 143 | } 144 | }, 145 | "finalhandler": { 146 | "version": "1.1.2", 147 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", 148 | "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", 149 | "requires": { 150 | "debug": "2.6.9", 151 | "encodeurl": "~1.0.2", 152 | "escape-html": "~1.0.3", 153 | "on-finished": "~2.3.0", 154 | "parseurl": "~1.3.3", 155 | "statuses": "~1.5.0", 156 | "unpipe": "~1.0.0" 157 | } 158 | }, 159 | "forwarded": { 160 | "version": "0.1.2", 161 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", 162 | "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" 163 | }, 164 | "fresh": { 165 | "version": "0.5.2", 166 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 167 | "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" 168 | }, 169 | "http-errors": { 170 | "version": "1.7.2", 171 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", 172 | "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", 173 | "requires": { 174 | "depd": "~1.1.2", 175 | "inherits": "2.0.3", 176 | "setprototypeof": "1.1.1", 177 | "statuses": ">= 1.5.0 < 2", 178 | "toidentifier": "1.0.0" 179 | } 180 | }, 181 | "iconv-lite": { 182 | "version": "0.4.24", 183 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 184 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 185 | "requires": { 186 | "safer-buffer": ">= 2.1.2 < 3" 187 | } 188 | }, 189 | "inherits": { 190 | "version": "2.0.3", 191 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 192 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 193 | }, 194 | "ipaddr.js": { 195 | "version": "1.9.1", 196 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", 197 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" 198 | }, 199 | "media-typer": { 200 | "version": "0.3.0", 201 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 202 | "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" 203 | }, 204 | "merge-descriptors": { 205 | "version": "1.0.1", 206 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", 207 | "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" 208 | }, 209 | "methods": { 210 | "version": "1.1.2", 211 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 212 | "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" 213 | }, 214 | "mime": { 215 | "version": "1.6.0", 216 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 217 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" 218 | }, 219 | "mime-db": { 220 | "version": "1.47.0", 221 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.47.0.tgz", 222 | "integrity": "sha512-QBmA/G2y+IfeS4oktet3qRZ+P5kPhCKRXxXnQEudYqUaEioAU1/Lq2us3D/t1Jfo4hE9REQPrbB7K5sOczJVIw==" 223 | }, 224 | "mime-types": { 225 | "version": "2.1.30", 226 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.30.tgz", 227 | "integrity": "sha512-crmjA4bLtR8m9qLpHvgxSChT+XoSlZi8J4n/aIdn3z92e/U47Z0V/yl+Wh9W046GgFVAmoNR/fmdbZYcSSIUeg==", 228 | "requires": { 229 | "mime-db": "1.47.0" 230 | } 231 | }, 232 | "ms": { 233 | "version": "2.0.0", 234 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 235 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 236 | }, 237 | "negotiator": { 238 | "version": "0.6.2", 239 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", 240 | "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" 241 | }, 242 | "on-finished": { 243 | "version": "2.3.0", 244 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", 245 | "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", 246 | "requires": { 247 | "ee-first": "1.1.1" 248 | } 249 | }, 250 | "parseurl": { 251 | "version": "1.3.3", 252 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 253 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" 254 | }, 255 | "path-to-regexp": { 256 | "version": "0.1.7", 257 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", 258 | "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" 259 | }, 260 | "proxy-addr": { 261 | "version": "2.0.6", 262 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", 263 | "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", 264 | "requires": { 265 | "forwarded": "~0.1.2", 266 | "ipaddr.js": "1.9.1" 267 | } 268 | }, 269 | "qs": { 270 | "version": "6.7.0", 271 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", 272 | "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" 273 | }, 274 | "range-parser": { 275 | "version": "1.2.1", 276 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 277 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" 278 | }, 279 | "raw-body": { 280 | "version": "2.4.0", 281 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", 282 | "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", 283 | "requires": { 284 | "bytes": "3.1.0", 285 | "http-errors": "1.7.2", 286 | "iconv-lite": "0.4.24", 287 | "unpipe": "1.0.0" 288 | } 289 | }, 290 | "safe-buffer": { 291 | "version": "5.1.2", 292 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 293 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" 294 | }, 295 | "safer-buffer": { 296 | "version": "2.1.2", 297 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 298 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 299 | }, 300 | "send": { 301 | "version": "0.17.1", 302 | "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", 303 | "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", 304 | "requires": { 305 | "debug": "2.6.9", 306 | "depd": "~1.1.2", 307 | "destroy": "~1.0.4", 308 | "encodeurl": "~1.0.2", 309 | "escape-html": "~1.0.3", 310 | "etag": "~1.8.1", 311 | "fresh": "0.5.2", 312 | "http-errors": "~1.7.2", 313 | "mime": "1.6.0", 314 | "ms": "2.1.1", 315 | "on-finished": "~2.3.0", 316 | "range-parser": "~1.2.1", 317 | "statuses": "~1.5.0" 318 | }, 319 | "dependencies": { 320 | "ms": { 321 | "version": "2.1.1", 322 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", 323 | "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" 324 | } 325 | } 326 | }, 327 | "serve-static": { 328 | "version": "1.14.1", 329 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", 330 | "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", 331 | "requires": { 332 | "encodeurl": "~1.0.2", 333 | "escape-html": "~1.0.3", 334 | "parseurl": "~1.3.3", 335 | "send": "0.17.1" 336 | } 337 | }, 338 | "setprototypeof": { 339 | "version": "1.1.1", 340 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", 341 | "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" 342 | }, 343 | "statuses": { 344 | "version": "1.5.0", 345 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", 346 | "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" 347 | }, 348 | "toidentifier": { 349 | "version": "1.0.0", 350 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", 351 | "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" 352 | }, 353 | "type-is": { 354 | "version": "1.6.18", 355 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", 356 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", 357 | "requires": { 358 | "media-typer": "0.3.0", 359 | "mime-types": "~2.1.24" 360 | } 361 | }, 362 | "unpipe": { 363 | "version": "1.0.0", 364 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 365 | "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" 366 | }, 367 | "utils-merge": { 368 | "version": "1.0.1", 369 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 370 | "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" 371 | }, 372 | "vary": { 373 | "version": "1.1.2", 374 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 375 | "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" 376 | } 377 | } 378 | } 379 | } 380 | } 381 | -------------------------------------------------------------------------------- /t/001-sanity.t: -------------------------------------------------------------------------------- 1 | use String::Random; 2 | use Test::Nginx::Socket 'no_plan'; 3 | 4 | #workers(2); 5 | repeat_each(2); 6 | 7 | my $string_gen = String::Random->new; 8 | our $random_token = $string_gen->randpattern("CcCcCcCCcC"); 9 | 10 | # Start the nodejs backend 11 | my $pid = fork(); 12 | if ($pid == 0) { #child 13 | exec("node t/backend/index.js"); 14 | } else { #parent 15 | sleep 1; 16 | } 17 | 18 | add_cleanup_handler(sub { 19 | kill INT => $pid; 20 | }); 21 | 22 | run_tests(); 23 | 24 | __DATA__ 25 | 26 | === TEST 1: NTLM header should trigger keepalive for upstream 27 | When the authorization header contains NTLM the token is saved on the server 28 | connection and all subsequent requests should return it in X-NGX-NTLM-AUTH 29 | header 30 | --- http_config 31 | upstream backend { 32 | server localhost:19841; 33 | server localhost:19842; 34 | ntlm; 35 | } 36 | --- config 37 | location /t { 38 | proxy_pass http://backend; 39 | proxy_http_version 1.1; 40 | proxy_set_header Connection ""; 41 | } 42 | --- pipelined_requests eval 43 | ["GET /t", "GET /t", "GET /t"] 44 | --- more_headers eval 45 | ["Authorization: NTLM " . $::random_token,"",""] 46 | --- response_body eval 47 | ["OK", "OK", "OK"] 48 | --- response_headers eval 49 | ["X-NGX-NTLM-AUTH: " . $::random_token, "X-NGX-NTLM-AUTH: " . $::random_token, "X-NGX-NTLM-AUTH: " . $::random_token] 50 | --- no_error_log 51 | [error] 52 | 53 | 54 | === TEST 2: Negotiate header should trigger keepalive for upstream 55 | When the authorization header contains Negotiate the token is saved on the server 56 | connection and all subsequent requests should return it in X-NGX-NTLM-AUTH 57 | header 58 | --- http_config 59 | upstream backend { 60 | server localhost:19841; 61 | server localhost:19842; 62 | ntlm; 63 | } 64 | --- config 65 | location /t { 66 | proxy_pass http://backend; 67 | proxy_http_version 1.1; 68 | proxy_set_header Connection ""; 69 | } 70 | --- pipelined_requests eval 71 | ["GET /t", "GET /t", "GET /t"] 72 | --- more_headers eval 73 | ["Authorization: Negotiate " . $::random_token,"",""] 74 | --- response_body eval 75 | ["OK", "OK", "OK"] 76 | --- response_headers eval 77 | ["X-NGX-NTLM-AUTH: " . $::random_token, "X-NGX-NTLM-AUTH: " . $::random_token, "X-NGX-NTLM-AUTH: " . $::random_token] 78 | --- no_error_log 79 | [error] 80 | 81 | 82 | === TEST 3: The backend connection should die when client connection dies 83 | When the authorization header contains NTLM the token is saved on the server 84 | connection if the client drops the connection the backend connection must die 85 | also 86 | --- http_config 87 | upstream backend { 88 | server localhost:19841; 89 | server localhost:19842; 90 | ntlm; 91 | } 92 | --- config 93 | location /t { 94 | proxy_pass http://backend; 95 | proxy_http_version 1.1; 96 | proxy_set_header Connection ""; 97 | } 98 | --- request eval 99 | ["GET /t", "GET /t", "GET /t"] 100 | --- more_headers eval 101 | ["Authorization: NTLM " . $::random_token,"",""] 102 | --- response_body eval 103 | ["OK", "OK", "OK"] 104 | --- raw_response_headers_like eval 105 | ["X-NGX-NTLM-AUTH: " . $::random_token, "", ""] 106 | --- raw_response_headers_unlike eval 107 | ["========","X-NGX-NTLM-AUTH: ","X-NGX-NTLM-AUTH: "] 108 | --- no_error_log 109 | [error] 110 | 111 | 112 | === TEST 4: The backend connection should die when client connection dies 113 | When the authorization header contains Negotiate the token is saved on the server 114 | connection if the client drops the connection the backend connection must die 115 | also 116 | --- http_config 117 | upstream backend { 118 | server localhost:19841; 119 | server localhost:19842; 120 | ntlm; 121 | } 122 | --- config 123 | location /t { 124 | proxy_pass http://backend; 125 | proxy_http_version 1.1; 126 | proxy_set_header Connection ""; 127 | } 128 | --- request eval 129 | ["GET /t", "GET /t", "GET /t"] 130 | --- more_headers eval 131 | ["Authorization: Negotiate " . $::random_token,"",""] 132 | --- response_body eval 133 | ["OK", "OK", "OK"] 134 | --- raw_response_headers_like eval 135 | ["X-NGX-NTLM-AUTH: " . $::random_token, "", ""] 136 | --- raw_response_headers_unlike eval 137 | ["========","X-NGX-NTLM-AUTH: ","X-NGX-NTLM-AUTH: "] 138 | --- no_error_log 139 | [error] 140 | -------------------------------------------------------------------------------- /t/002-timeout.t: -------------------------------------------------------------------------------- 1 | use String::Random; 2 | use Test::Nginx::Socket 'no_plan'; 3 | 4 | #workers(2); 5 | repeat_each(2); 6 | 7 | my $string_gen = String::Random->new; 8 | our $random_token = $string_gen->randpattern("CcCcCcCCcC"); 9 | 10 | # Start the nodejs backend 11 | my $pid = fork(); 12 | if ($pid == 0) { #child 13 | exec("node t/backend/index.js"); 14 | } else { #parent 15 | sleep 1; 16 | } 17 | 18 | add_cleanup_handler(sub { 19 | kill INT => $pid; 20 | }); 21 | 22 | run_tests(); 23 | 24 | __DATA__ 25 | 26 | === TEST 1: Handle client connection drop after backend timeout 27 | When the ntlm_timeout expires the backend connection is dropped and 28 | after this event the client connection clean up 29 | should be handled properly (crashed the server before) 30 | --- http_config 31 | upstream backend { 32 | server localhost:19841; 33 | server localhost:19842; 34 | ntlm; 35 | ntlm_timeout 2s; 36 | } 37 | --- config 38 | location /t { 39 | proxy_pass http://backend; 40 | proxy_http_version 1.1; 41 | proxy_set_header Connection ""; 42 | } 43 | --- request eval 44 | ["GET /t/1", "GET /t/2"] 45 | --- more_headers eval 46 | ["Authorization: NTLM " . $::random_token . "\r\nConnection: keep-alive",""] 47 | --- timeout: 3s 48 | --- abort 49 | --- response_body eval 50 | ["OK", "OK"] 51 | --- response_headers eval 52 | ["X-NGX-NTLM-AUTH: " . $::random_token, ""] 53 | --- raw_response_headers_unlike eval 54 | ["========","X-NGX-NTLM-AUTH: "] 55 | --- no_error_log 56 | [error] 57 | 58 | 59 | === TEST 2: Handle client request after backend timeout 60 | --- http_config 61 | upstream backend { 62 | server localhost:19841; 63 | server localhost:19842; 64 | ntlm; 65 | ntlm_timeout 2s; 66 | } 67 | --- config 68 | location /t { 69 | proxy_pass http://backend; 70 | proxy_http_version 1.1; 71 | proxy_set_header Connection ""; 72 | } 73 | --- pipelined_requests eval 74 | ["GET /t/1", "GET /t/2", [{value => "GET /t/3", delay_before =>3}]] 75 | --- more_headers eval 76 | ["Authorization: NTLM " . $::random_token,"",""] 77 | --- response_body eval 78 | ["OK", "OK", "OK"] 79 | --- response_headers eval 80 | ["X-NGX-NTLM-AUTH: " . $::random_token, "X-NGX-NTLM-AUTH: " . $::random_token, ""] 81 | --- raw_response_headers_unlike eval 82 | ["========","==========","X-NGX-NTLM-AUTH: "] 83 | --- no_error_log 84 | [error] 85 | --- SKIP # pipelined_requests does not support spliting into packets ... yet 86 | 87 | -------------------------------------------------------------------------------- /t/backend/index.js: -------------------------------------------------------------------------------- 1 | const util = require('util') 2 | const express = require('express') 3 | const PORT1 = process.env.NGX_TEST_UPS1_PORT || 19841 4 | const PORT2 = process.env.NGX_TEST_UPS2_PORT || 19842 5 | const KEEP_ALIVE = process.env.NGX_TEST_UPS_KEEP_ALIVE || 300_000 6 | 7 | // This is a very simple request handler that will try to emulate the 8 | // connection based authentication (like NTLM or Kerberos). 9 | // If the request contains the NTLM or Negotiate in the Authorization header 10 | // the value is saved into the connection object and is added as custom header 11 | // (X-NGX-NTLM-AUTH) for all subsequent request 12 | var requestHandler = (app, req, res) => { 13 | console.log(`[${app}] response received`); 14 | if (req.headers["authorization"]) { 15 | console.log(`[${app}] authorization header received`); 16 | var tokenValue = ""; 17 | pattern = /(NTLM|Negotiate) (.*)$/; 18 | var match = pattern.exec(req.headers["authorization"]); 19 | if (match) { 20 | tokenValue = match[2]; 21 | console.log(`[${app}] found token in header '${tokenValue}'`); 22 | } 23 | if (!req.connection.xauthData) { 24 | req.connection.xauthData = tokenValue; 25 | console.log(`[${app}] token saved to connection '${tokenValue}'`); 26 | } 27 | } 28 | if (req.connection.xauthData) { 29 | res.setHeader('X-NGX-NTLM-AUTH', req.connection.xauthData); 30 | console.log(`[${app}] found token on connection '${req.connection.xauthData}`); 31 | } 32 | res.send('OK'); 33 | console.log(`[${app}] response sent`); 34 | } 35 | 36 | const app1 = express(); 37 | app1.get('/*', (req, res) => { 38 | requestHandler("app1", req,res); 39 | }); 40 | var server1 = app1.listen(PORT1, () => { 41 | console.log(`[app1] upstream listening at http://localhost:${PORT1}`); 42 | }); 43 | server1.keepAliveTimeout = KEEP_ALIVE; 44 | 45 | const app2 = express(); 46 | app2.get('/*', (req, res) => { 47 | requestHandler("app2",req,res); 48 | }); 49 | var server2 = app2.listen(PORT2, () => { 50 | console.log(`[app2] upstream listening at http://localhost:${PORT2}`); 51 | }); 52 | server2.keepAliveTimeout = KEEP_ALIVE; 53 | 54 | // Hack console log to print data 55 | var log = console.log; 56 | console.log = function () { 57 | var args = [].slice.call(arguments); 58 | log.apply(console, [(new Date()).toISOString()].concat(args)); 59 | }; 60 | -------------------------------------------------------------------------------- /t/backend/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nginx-upstream-backend-test", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "accepts": { 8 | "version": "1.3.7", 9 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", 10 | "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", 11 | "requires": { 12 | "mime-types": "~2.1.24", 13 | "negotiator": "0.6.2" 14 | } 15 | }, 16 | "array-flatten": { 17 | "version": "1.1.1", 18 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 19 | "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" 20 | }, 21 | "body-parser": { 22 | "version": "1.19.0", 23 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", 24 | "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", 25 | "requires": { 26 | "bytes": "3.1.0", 27 | "content-type": "~1.0.4", 28 | "debug": "2.6.9", 29 | "depd": "~1.1.2", 30 | "http-errors": "1.7.2", 31 | "iconv-lite": "0.4.24", 32 | "on-finished": "~2.3.0", 33 | "qs": "6.7.0", 34 | "raw-body": "2.4.0", 35 | "type-is": "~1.6.17" 36 | } 37 | }, 38 | "bytes": { 39 | "version": "3.1.0", 40 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", 41 | "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" 42 | }, 43 | "content-disposition": { 44 | "version": "0.5.3", 45 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", 46 | "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", 47 | "requires": { 48 | "safe-buffer": "5.1.2" 49 | } 50 | }, 51 | "content-type": { 52 | "version": "1.0.4", 53 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", 54 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" 55 | }, 56 | "cookie": { 57 | "version": "0.4.0", 58 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", 59 | "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" 60 | }, 61 | "cookie-signature": { 62 | "version": "1.0.6", 63 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 64 | "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" 65 | }, 66 | "debug": { 67 | "version": "2.6.9", 68 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 69 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 70 | "requires": { 71 | "ms": "2.0.0" 72 | } 73 | }, 74 | "depd": { 75 | "version": "1.1.2", 76 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", 77 | "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" 78 | }, 79 | "destroy": { 80 | "version": "1.0.4", 81 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", 82 | "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" 83 | }, 84 | "ee-first": { 85 | "version": "1.1.1", 86 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 87 | "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" 88 | }, 89 | "encodeurl": { 90 | "version": "1.0.2", 91 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 92 | "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" 93 | }, 94 | "escape-html": { 95 | "version": "1.0.3", 96 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 97 | "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" 98 | }, 99 | "etag": { 100 | "version": "1.8.1", 101 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 102 | "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" 103 | }, 104 | "express": { 105 | "version": "4.17.1", 106 | "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", 107 | "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", 108 | "requires": { 109 | "accepts": "~1.3.7", 110 | "array-flatten": "1.1.1", 111 | "body-parser": "1.19.0", 112 | "content-disposition": "0.5.3", 113 | "content-type": "~1.0.4", 114 | "cookie": "0.4.0", 115 | "cookie-signature": "1.0.6", 116 | "debug": "2.6.9", 117 | "depd": "~1.1.2", 118 | "encodeurl": "~1.0.2", 119 | "escape-html": "~1.0.3", 120 | "etag": "~1.8.1", 121 | "finalhandler": "~1.1.2", 122 | "fresh": "0.5.2", 123 | "merge-descriptors": "1.0.1", 124 | "methods": "~1.1.2", 125 | "on-finished": "~2.3.0", 126 | "parseurl": "~1.3.3", 127 | "path-to-regexp": "0.1.7", 128 | "proxy-addr": "~2.0.5", 129 | "qs": "6.7.0", 130 | "range-parser": "~1.2.1", 131 | "safe-buffer": "5.1.2", 132 | "send": "0.17.1", 133 | "serve-static": "1.14.1", 134 | "setprototypeof": "1.1.1", 135 | "statuses": "~1.5.0", 136 | "type-is": "~1.6.18", 137 | "utils-merge": "1.0.1", 138 | "vary": "~1.1.2" 139 | } 140 | }, 141 | "finalhandler": { 142 | "version": "1.1.2", 143 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", 144 | "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", 145 | "requires": { 146 | "debug": "2.6.9", 147 | "encodeurl": "~1.0.2", 148 | "escape-html": "~1.0.3", 149 | "on-finished": "~2.3.0", 150 | "parseurl": "~1.3.3", 151 | "statuses": "~1.5.0", 152 | "unpipe": "~1.0.0" 153 | } 154 | }, 155 | "forwarded": { 156 | "version": "0.1.2", 157 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", 158 | "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" 159 | }, 160 | "fresh": { 161 | "version": "0.5.2", 162 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 163 | "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" 164 | }, 165 | "http-errors": { 166 | "version": "1.7.2", 167 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", 168 | "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", 169 | "requires": { 170 | "depd": "~1.1.2", 171 | "inherits": "2.0.3", 172 | "setprototypeof": "1.1.1", 173 | "statuses": ">= 1.5.0 < 2", 174 | "toidentifier": "1.0.0" 175 | } 176 | }, 177 | "iconv-lite": { 178 | "version": "0.4.24", 179 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 180 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 181 | "requires": { 182 | "safer-buffer": ">= 2.1.2 < 3" 183 | } 184 | }, 185 | "inherits": { 186 | "version": "2.0.3", 187 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 188 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 189 | }, 190 | "ipaddr.js": { 191 | "version": "1.9.1", 192 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", 193 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" 194 | }, 195 | "media-typer": { 196 | "version": "0.3.0", 197 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 198 | "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" 199 | }, 200 | "merge-descriptors": { 201 | "version": "1.0.1", 202 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", 203 | "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" 204 | }, 205 | "methods": { 206 | "version": "1.1.2", 207 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 208 | "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" 209 | }, 210 | "mime": { 211 | "version": "1.6.0", 212 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 213 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" 214 | }, 215 | "mime-db": { 216 | "version": "1.47.0", 217 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.47.0.tgz", 218 | "integrity": "sha512-QBmA/G2y+IfeS4oktet3qRZ+P5kPhCKRXxXnQEudYqUaEioAU1/Lq2us3D/t1Jfo4hE9REQPrbB7K5sOczJVIw==" 219 | }, 220 | "mime-types": { 221 | "version": "2.1.30", 222 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.30.tgz", 223 | "integrity": "sha512-crmjA4bLtR8m9qLpHvgxSChT+XoSlZi8J4n/aIdn3z92e/U47Z0V/yl+Wh9W046GgFVAmoNR/fmdbZYcSSIUeg==", 224 | "requires": { 225 | "mime-db": "1.47.0" 226 | } 227 | }, 228 | "ms": { 229 | "version": "2.0.0", 230 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 231 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 232 | }, 233 | "negotiator": { 234 | "version": "0.6.2", 235 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", 236 | "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" 237 | }, 238 | "on-finished": { 239 | "version": "2.3.0", 240 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", 241 | "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", 242 | "requires": { 243 | "ee-first": "1.1.1" 244 | } 245 | }, 246 | "parseurl": { 247 | "version": "1.3.3", 248 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 249 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" 250 | }, 251 | "path-to-regexp": { 252 | "version": "0.1.7", 253 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", 254 | "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" 255 | }, 256 | "proxy-addr": { 257 | "version": "2.0.6", 258 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", 259 | "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", 260 | "requires": { 261 | "forwarded": "~0.1.2", 262 | "ipaddr.js": "1.9.1" 263 | } 264 | }, 265 | "qs": { 266 | "version": "6.7.0", 267 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", 268 | "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" 269 | }, 270 | "range-parser": { 271 | "version": "1.2.1", 272 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 273 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" 274 | }, 275 | "raw-body": { 276 | "version": "2.4.0", 277 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", 278 | "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", 279 | "requires": { 280 | "bytes": "3.1.0", 281 | "http-errors": "1.7.2", 282 | "iconv-lite": "0.4.24", 283 | "unpipe": "1.0.0" 284 | } 285 | }, 286 | "safe-buffer": { 287 | "version": "5.1.2", 288 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 289 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" 290 | }, 291 | "safer-buffer": { 292 | "version": "2.1.2", 293 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 294 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 295 | }, 296 | "send": { 297 | "version": "0.17.1", 298 | "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", 299 | "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", 300 | "requires": { 301 | "debug": "2.6.9", 302 | "depd": "~1.1.2", 303 | "destroy": "~1.0.4", 304 | "encodeurl": "~1.0.2", 305 | "escape-html": "~1.0.3", 306 | "etag": "~1.8.1", 307 | "fresh": "0.5.2", 308 | "http-errors": "~1.7.2", 309 | "mime": "1.6.0", 310 | "ms": "2.1.1", 311 | "on-finished": "~2.3.0", 312 | "range-parser": "~1.2.1", 313 | "statuses": "~1.5.0" 314 | }, 315 | "dependencies": { 316 | "ms": { 317 | "version": "2.1.1", 318 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", 319 | "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" 320 | } 321 | } 322 | }, 323 | "serve-static": { 324 | "version": "1.14.1", 325 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", 326 | "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", 327 | "requires": { 328 | "encodeurl": "~1.0.2", 329 | "escape-html": "~1.0.3", 330 | "parseurl": "~1.3.3", 331 | "send": "0.17.1" 332 | } 333 | }, 334 | "setprototypeof": { 335 | "version": "1.1.1", 336 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", 337 | "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" 338 | }, 339 | "statuses": { 340 | "version": "1.5.0", 341 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", 342 | "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" 343 | }, 344 | "toidentifier": { 345 | "version": "1.0.0", 346 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", 347 | "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" 348 | }, 349 | "type-is": { 350 | "version": "1.6.18", 351 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", 352 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", 353 | "requires": { 354 | "media-typer": "0.3.0", 355 | "mime-types": "~2.1.24" 356 | } 357 | }, 358 | "unpipe": { 359 | "version": "1.0.0", 360 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 361 | "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" 362 | }, 363 | "utils-merge": { 364 | "version": "1.0.1", 365 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 366 | "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" 367 | }, 368 | "vary": { 369 | "version": "1.1.2", 370 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 371 | "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" 372 | } 373 | } 374 | } 375 | -------------------------------------------------------------------------------- /t/backend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nginx-upstream-backend-test", 3 | "version": "1.0.0", 4 | "description": "A simple backend to test the nginx ntlm functionality", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "Gabriel Hodoroaga", 10 | "license": "MIT", 11 | "dependencies": { 12 | "express": "^4.17.1" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /utils/build_linux_configure.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd nginx-1.19.3/ 4 | 5 | ./configure --with-debug \ 6 | --prefix= \ 7 | --conf-path=conf/nginx.conf \ 8 | --pid-path=logs/nginx.pid \ 9 | --http-log-path=logs/access.log \ 10 | --error-log-path=logs/error.log \ 11 | --with-pcre=../pcre-8.44 \ 12 | --with-zlib=../zlib-1.2.11 \ 13 | --with-http_v2_module \ 14 | --with-http_realip_module \ 15 | --with-http_addition_module \ 16 | --with-http_sub_module \ 17 | --with-http_dav_module \ 18 | --with-http_stub_status_module \ 19 | --with-http_flv_module \ 20 | --with-http_mp4_module \ 21 | --with-http_gunzip_module \ 22 | --with-http_gzip_static_module \ 23 | --with-http_auth_request_module \ 24 | --with-http_random_index_module \ 25 | --with-http_secure_link_module \ 26 | --with-http_slice_module \ 27 | --with-mail \ 28 | --with-stream \ 29 | --with-openssl=../openssl-1.1.1h \ 30 | --with-http_ssl_module \ 31 | --with-mail_ssl_module \ 32 | --with-stream_ssl_module \ 33 | --add-module=../nginx-ntlm-module 34 | -------------------------------------------------------------------------------- /utils/build_linux_download.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # download nginx 4 | curl -OL http://nginx.org/download/nginx-1.19.3.tar.gz 5 | tar -xvzf nginx-1.19.3.tar.gz && rm nginx-1.19.3.tar.gz 6 | 7 | # download PCRE library 8 | curl -OL https://ftp.pcre.org/pub/pcre/pcre-8.44.tar.gz 9 | tar -xvzf pcre-8.44.tar.gz && rm pcre-8.44.tar.gz 10 | 11 | # download OpenSSL 12 | curl -OL https://www.openssl.org/source/openssl-1.1.1h.tar.gz 13 | tar -xvzf openssl-1.1.1h.tar.gz && rm openssl-1.1.1h.tar.gz 14 | 15 | # download zlib 16 | curl -OL https://zlib.net/zlib-1.2.11.tar.gz 17 | tar -xvzf zlib-1.2.11.tar.gz && rm zlib-1.2.11.tar.gz 18 | 19 | # make sure you have "Development Tools" and "Development Libraries" intalled for your distribution 20 | 21 | # Debian 22 | # sudo apt-get install build-essential 23 | 24 | # Fedora 25 | # sudo dnf groupinstall "Development Tools" "Development Libraries" 26 | -------------------------------------------------------------------------------- /utils/build_linux_make.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd nginx-1.19.3/ 4 | 5 | make 6 | -------------------------------------------------------------------------------- /utils/build_macos_configure.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd nginx-1.19.3/ 4 | 5 | ./configure --with-debug \ 6 | --prefix= \ 7 | --conf-path=conf/nginx.conf \ 8 | --pid-path=logs/nginx.pid \ 9 | --http-log-path=logs/access.log \ 10 | --error-log-path=logs/error.log \ 11 | --with-pcre=../pcre-8.44 \ 12 | --with-zlib=../zlib-1.2.11 \ 13 | --with-http_v2_module \ 14 | --with-http_realip_module \ 15 | --with-http_addition_module \ 16 | --with-http_sub_module \ 17 | --with-http_dav_module \ 18 | --with-http_stub_status_module \ 19 | --with-http_flv_module \ 20 | --with-http_mp4_module \ 21 | --with-http_gunzip_module \ 22 | --with-http_gzip_static_module \ 23 | --with-http_auth_request_module \ 24 | --with-http_random_index_module \ 25 | --with-http_secure_link_module \ 26 | --with-http_slice_module \ 27 | --with-mail \ 28 | --with-stream \ 29 | --with-openssl=../openssl-1.1.1h \ 30 | --with-http_ssl_module \ 31 | --with-mail_ssl_module \ 32 | --with-stream_ssl_module \ 33 | --add-module=../nginx-ntlm-module 34 | -------------------------------------------------------------------------------- /utils/build_macos_download.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # download nginx 4 | curl -OL http://nginx.org/download/nginx-1.19.3.tar.gz 5 | tar -xvzf nginx-1.19.3.tar.gz && rm nginx-1.19.3.tar.gz 6 | 7 | # download PCRE library 8 | curl -OL https://ftp.pcre.org/pub/pcre/pcre-8.44.tar.gz 9 | tar -xvzf pcre-8.44.tar.gz && rm pcre-8.44.tar.gz 10 | 11 | # download OpenSSL 12 | curl -OL https://www.openssl.org/source/openssl-1.1.1h.tar.gz 13 | tar -xvzf openssl-1.1.1h.tar.gz && rm openssl-1.1.1h.tar.gz 14 | 15 | # download zlib 16 | curl -OL https://zlib.net/zlib-1.2.11.tar.gz 17 | tar -xvzf zlib-1.2.11.tar.gz && rm zlib-1.2.11.tar.gz 18 | -------------------------------------------------------------------------------- /utils/build_macos_make.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd nginx-1.19.3/ 4 | 5 | make 6 | -------------------------------------------------------------------------------- /utils/build_win_configure.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd nginx-1.19.3/ 4 | 5 | # update file auto/cc/msvc:16 6 | # NGX_MSVC_VER=19.16 7 | # CFLAGS="$CFLAGS -W4" 8 | 9 | # update file auto/lib/openssl/makefile.msvc 10 | # 11 | # perl Configure VC-WIN64A no-shared 12 | # ... 13 | # if exist ms\do_win64a.bat ( 14 | # ms\do_win64a 15 | 16 | auto/configure \ 17 | --with-cc=cl \ 18 | --builddir=objs \ 19 | --with-debug \ 20 | --prefix= \ 21 | --conf-path=conf/nginx.conf \ 22 | --pid-path=logs/nginx.pid \ 23 | --http-log-path=logs/access.log \ 24 | --error-log-path=logs/error.log \ 25 | --sbin-path=nginx.exe \ 26 | --with-cc-opt=-DFD_SETSIZE=1024 \ 27 | --with-pcre=objs/lib/pcre-8.44 \ 28 | --with-zlib=objs/lib/zlib-1.2.11 \ 29 | --with-http_v2_module \ 30 | --with-http_realip_module \ 31 | --with-http_addition_module \ 32 | --with-http_sub_module \ 33 | --with-http_dav_module \ 34 | --with-http_stub_status_module \ 35 | --with-http_flv_module \ 36 | --with-http_mp4_module \ 37 | --with-http_gunzip_module \ 38 | --with-http_gzip_static_module \ 39 | --with-http_auth_request_module \ 40 | --with-http_random_index_module \ 41 | --with-http_secure_link_module \ 42 | --with-http_slice_module \ 43 | --with-mail \ 44 | --with-stream \ 45 | --with-openssl=objs/lib/openssl-1.1.1h \ 46 | --with-http_ssl_module \ 47 | --with-mail_ssl_module \ 48 | --with-stream_ssl_module \ 49 | --add-module=../nginx-ntlm-module 50 | 51 | 52 | # update file objs/Makefile 53 | # remove next 5 lines after this line (sed does not exists in windows) 54 | # objs/nginx.8: docs/man/nginx.8 objs/ngx_auto_config.h 55 | -------------------------------------------------------------------------------- /utils/build_win_download.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # download nginx 4 | git clone --branch release-1.19.3 https://github.com/nginx/nginx.git nginx-1.19.3 5 | 6 | # create the folder for libraries 7 | mkdir -p nginx-1.19.3/objs/lib 8 | 9 | # download PCRE library 10 | curl -OL https://ftp.pcre.org/pub/pcre/pcre-8.44.tar.gz 11 | tar -xvzf pcre-8.44.tar.gz -C nginx-1.19.3/objs/lib && rm pcre-8.44.tar.gz 12 | 13 | # download OpenSSL 14 | curl -OL https://www.openssl.org/source/openssl-1.1.1h.tar.gz 15 | tar -xvzf openssl-1.1.1h.tar.gz -C nginx-1.19.3/objs/lib && rm openssl-1.1.1h.tar.gz 16 | 17 | # download zlib 18 | curl -OL https://zlib.net/zlib-1.2.11.tar.gz 19 | tar -xvzf zlib-1.2.11.tar.gz -C nginx-1.19.3/objs/lib && rm zlib-1.2.11.tar.gz 20 | -------------------------------------------------------------------------------- /utils/build_win_make.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "This command does not run anything!" 4 | echo "You have to execute this commands manually" 5 | echo "1. Open VS x64 Native Tools Command Prompt for VS 2017" 6 | echo "2. cd nginx-1.19.3" 7 | echo "3. nmake" 8 | echo "Take a coffe and wait until is done" 9 | --------------------------------------------------------------------------------