This container aims to be a generic proxy layer for your web services. It includes OpenResty with Lua and NAXSI filtering compiled in.
In this section I'll show you some examples of how you might run this container with docker.
In order to run this container you'll need docker installed.
When an update has been deployed to master, tag and push the master branch to kick off a Drone build:
git tag <next_version>
git push --tags
Authentic GEOIP credentials are needed when curling MaxMind Urls otherwise a 401 is returned. Therefore if no GEOIP_LICENSE_KEY
secret/env var is set when running ./ci-build.sh
, a LOCAL_TEST
variable is set to true to ensure the relevant urls are not called. This means not having to start up a Drone build every single time you want to test something and your local machine reuses any Docker cache available to it making the test/retry process much faster.
MAC USERS
You will need to install wget so that this can run in the ./ci-build.sh
script:
brew install wget
Variables to control how to configure the proxy (can be set per location, see Using Multiple Locations).
PROXY_SERVICE_HOST
- The upstream host you want this service to proxy.PROXY_SERVICE_PORT
- The port of the upstream host you want this service to proxy.NAXSI_RULES_URL_CSV
- A CSV of Naxsi URL's of files to download and use. (Files must end in .rules to be loaded)NAXSI_RULES_MD5_CSV
- A CSV of md5 hashes for the files specified aboveEXTRA_NAXSI_RULES
- Allows NAXSI rules to be specified as an environment variable. This allows one or two extra rules to be specified without downloading or mounting in a rule file.NAXSI_USE_DEFAULT_RULES
- If set to "FALSE" will delete the default rules file.ENABLE_UUID_PARAM
- If set to "FALSE", will NOT add a UUID url parameter to all requests. The Default will add this for easy tracking in down stream logs e.g.nginxId=50c91049-667f-4286-c2f0-86b04b27d3f0
. If set toHEADER
it will addnginxId
to the headers, not append to the get params.CLIENT_CERT_REQUIRED
- if set toTRUE
, will deny access at this location, see Client Certs.VERIFY_SERVER_CERT
- if set toTRUE
, will verify the upstream server's TLS certificate is valid and signed by the CA, see Verifying Upstream Server.USE_UPSTREAM_CLIENT_CERT
- if set toTRUE
, will use the set of upstream client certs when connecting upstream, see Upstream Client Certs.ERROR_REDIRECT_CODES
- Can override when Nginx will redirect requests to its own error page. Defaults to "500 501 502 503 504
". To support a new code, say505
, an error page must be provided at/usr/local/openresty/nginx/html/505.shtml
, see Useful File Locations. Set toFALSE
to disable all error pages.ADD_NGINX_LOCATION_CFG
- Arbitrary extra NGINX configuration to be added to the location context, see Arbitrary Config.PORT_IN_HOST_HEADER
- If FALSE will remove the port from the httpHost
header.BASIC_AUTH
- Define a path for username and password file (inusername:password
format), this will turn the file into a .htpasswd file.REQS_PER_MIN_PER_IP
- Will limit requests based on IP e.g. set to 60 to allow one request per second.CONCURRENT_CONNS_PER_IP
- Will limit concurrent connections based on IP e.g. set to 10 to allow max of 10 connections per browser or proxy!REQS_PER_PAGE
- Will limit requests to 'bursts' of x requests at a time before terminating (will default to 20)DENY_COUNTRY_ON
- Set toTRUE
to deny access to countries not listed in ALLOW_COUNTRY_CSV with 403 status for a location (set location for 403 with ADD_NGINX_LOCATION_CFG).VERBOSE_ERROR_PAGES
- Set to TRUE to display debug info in 418 error pages.FEEDBACK_EMAIL
- Set to add feedback email in 418 error pages.
Note the following variables can only be set once:
ADD_NGINX_SERVER_CFG
- Arbitrary extra NGINX configuration to be added to the server context, see Arbitrary ConfigADD_NGINX_HTTP_CFG
- Arbitrary extra NGINX configuration to be added to the http context, see Arbitrary ConfigLOCATIONS_CSV
- Set to a list of locations that are to be independently proxied, see the example Using Multiple Locations. Note, if this isn't set,/
will be used as the default location.LOAD_BALANCER_CIDR
- Set to preserve client IP addresses. Important, to enable, see Preserve Client IP.NAME_RESOLVER
- Can override the default DNS server used to re-resolve the backend proxy (based on TTL). The Default DNS Server is the first entry in the resolve.conf file in the container and is normally correct and managed by Docker or Kubernetes.CLIENT_MAX_BODY_SIZE
- Can set a larger upload than Nginx defaults in MB.HTTPS_REDIRECT_PORT
- Only required for http to https redirect and only when a non-standard https port is in use. This is useful when testing or for development instances or when a load-balancer mandates a non-standard port.LOG_FORMAT_NAME
- Can be set totext
orjson
(default).NO_LOGGING_URL_PARAMS
- Can be set toTRUE
if you don't want to log url params. Default is empty which means URL params are loggedNO_LOGGING_BODY
- Defaults to trueTRUE
. Set otherwise and nginx should log the request_body.NO_LOGGING_RESPONSE
- Defaults to trueTRUE
. Set otherwise and nginx should log the response_bodySERVER_CERT
- Can override where to find the server's SSL cert.SERVER_KEY
- Can override where to find the server's SSL key.SSL_CIPHERS
- Change the SSL ciphers support default only AES256+EECDH:AES256+EDH:!aNULLSSL_PROTOCOLS
- Change the SSL protocols supported default only TLSv1.2SSL_SESSION_TIMEOUT
- Specifies a time during which a client may reuse the session parameters (defaults to 10min)HTTP_LISTEN_PORT
- Change the default inside the container from 10080.HTTPS_LISTEN_PORT
- Change the default inside the container from 10443.HTTP2
- Defaults to falseFALSE
. Specifies whether http2 should be usedHTTPS_REDIRECT
- Toggle whether or not we force redirects to HTTPS. Defaults to true.ALLOW_COUNTRY_CSV
- List of country codes to allow.STATSD_METRICS
- Toggle if metrics are logged to statsd (defaults to true)STATSD_SERVER
- Server to send statsd metrics to, defaults to 127.0.0.1DISABLE_SYSDIG_METRICS
- Set to any non-empty string to disable support for Sysdig's metric collection
This container exposes
10080
- HTTP10443
- HTTPS
N.B. see HTTP(S)_LISTEN_PORT above
nginx.conf
is stored at/usr/local/openresty/nginx/conf/nginx.conf
/etc/keys/crt
&/etc/keys/key
- A certificate can be mounted here to make OpenResty use it. However a self signed one is provided if they have not been mounted./etc/keys/client-ca
If a client CA is mounted here, it will be loaded and configured. SeeCLIENT_CERT_REQUIRED
above in Environment Variables./etc/keys/upstream-server-ca
A CA public cert must be mounted here when verifying the upstream server's certificate is required. SeeVERIFY_SERVER_CERT
above in Environment Variables./etc/keys/upstream-client-crt
A public client cert must be mounted here when when the upstream server requires client cert authentication. SeeUSE_UPSTREAM_CLIENT_CERT
above in Environment Variables./etc/keys/upstream-client-key
A private client key must be mounted here when when the upstream server requires client cert authentication. SeeUSE_UPSTREAM_CLIENT_CERT
above in Environment Variables./usr/local/openresty/naxsi/*.conf
- Naxsi rules location in default nginx.conf./usr/local/openresty/nginx/html/$CODE.shtml
- HTML (with SSI support) displayed when a the status code $CODE is encountered upstream and the proxy is configured to intercept. See ERROR_REDIRECT_CODES to change this./usr/local/openresty/nginx/html/418-request-denied.shtml
- HTML (with SSI support) displayed when NAXSI blocks a request.
docker run -e 'PROXY_SERVICE_HOST=http://stackexchange.com' \
-e 'PROXY_SERVICE_PORT=80' \
-p 8443:443 \
quay.io/ukhomeofficedigital/nginx-proxy:v1.0.0
docker run -e 'PROXY_SERVICE_HOST=http://stackexchange.com' \
-e 'PROXY_SERVICE_PORT=80' \
-p 8443:443 \
-v /path/to/key:/etc/keys/key:ro \
-v /path/to/crt:/etc/keys/crt:ro \
quay.io/ukhomeofficedigital/nginx-proxy:v1.0.0
This proxy supports Proxy Protocol.
To use this feature you will need:
- To enable proxy protocol on your load balancer. For AWS, see Enabling Proxy Protocol for AWS.
- Find the private address range of your load balancer. For AWS, this could be any address in the destination network. E.g. if you have three compute subnets defined as 10.50.0.0/24, 10.50.1.0/24 and 10.50.2.0/24, then a suitable range would be 10.50.0.0/22 see CIDR Calculator.
docker run -e 'PROXY_SERVICE_HOST=http://stackexchange.com' \
-e 'PROXY_SERVICE_PORT=80' \
-e 'LOAD_BALANCER_CIDR=10.50.0.0/22' \
-p 8443:443 \
quay.io/ukhomeofficedigital/nginx-proxy:v1.0.0
The example below allows large documents to be POSTED to the /documents/uploads and /documents/other_uploads locations. See Whitelist NAXSI rules for more examples.
docker run -e 'PROXY_SERVICE_HOST=http://myapp.svc.cluster.local' \
-e 'PROXY_SERVICE_PORT=8080' \
-e 'EXTRA_NAXSI_RULES=BasicRule wl:2 "mz:$URL:/documents/uploads|BODY";
BasicRule wl:2 "mz:$URL:/documents/other_uploads|BODY";' \
-p 8443:443 \
quay.io/ukhomeofficedigital/nginx-proxy:v1.0.0
When the LOCATIONS_CSV option is set, multiple locations can be proxied. The settings for each proxy location can be controlled with the use of any Multi-location Variables by suffixing the variable name with both a number, and the '_' character, as listed in the LOCATIONS_CSV variable.
The example below configures a simple proxy with two locations '/' (location 1) and '/api' (location 2):
docker run -e 'PROXY_SERVICE_HOST_1=http://stackexchange.com' \
-e 'PROXY_SERVICE_PORT_1=80' \
-e 'PROXY_SERVICE_HOST_2=https://api.svc.cluster.local' \
-e 'PROXY_SERVICE_PORT_2=8888' \
-e 'LOCATIONS_CSV=/,/api' \
-p 8443:443 \
quay.io/ukhomeofficedigital/nginx-proxy:v1.0.0
For more detail, see the generated config.
The example below will proxy the same address for two locations but will disable the UUID (nginxId) parameter for the /about location only.
See the generated config for below:
docker run -e 'PROXY_SERVICE_HOST=http://stackexchange.com' \
-e 'PROXY_SERVICE_PORT=80' \
-e 'LOCATIONS_CSV=/,/about' \
-e 'ENABLE_UUID_PARAM_2=FALSE' \
-p 8443:443 \
quay.io/ukhomeofficedigital/nginx-proxy:v1.0.0
If a client CA certificate is mounted, the proxy will be configured to load it. If a client has the cert, the client CN will be set in the X-Username header and logged.
docker run -e 'PROXY_SERVICE_HOST=http://stackexchange.com' \
-e 'PROXY_SERVICE_PORT=80' \
-v "${PWD}/client_certs/ca.crt:/etc/keys/client-ca" \
-p 8443:443 \
quay.io/ukhomeofficedigital/nginx-proxy:v1.0.0
The following example will specifically deny access to clients without a cert:
docker run -e 'PROXY_SERVICE_HOST=http://serverfault.com' \
-e 'PROXY_SERVICE_PORT=80' \
-e 'LOCATIONS_CSV=/,/about' \
-e 'CLIENT_CERT_REQUIRED_2=TRUE' \
-v "${PWD}/client_certs/ca.crt:/etc/keys/client-ca" \
-p 8443:443 \
quay.io/ukhomeofficedigital/nginx-proxy:v1.0.0
See ./client_certs for scripts that can be used to generate a CA and client certs.
If the environment variable USE_UPSTREAM_CLIENT_CERT
is set to TRUE
then the client certs at /etc/keys/upstream-client-crt
and
/etc/keys/upstream-client-key
will be used to authenticate with the
upstream HTTPS service.
docker run -e 'PROXY_SERVICE_HOST=https://stackexchange.com' \
-e 'PROXY_SERVICE_PORT=443' \
-e 'USE_UPSTREAM_CLIENT_CERT=TRUE' \
-v "/path/to/client-public.crt:/etc/keys/upstream-client-crt" \
-v "/path/to/client-private.key:/etc/keys/upstream-client-key" \
-p 8443:443 \
quay.io/ukhomeofficedigital/nginx-proxy:v2.1.0
If the environment variable VERIFY_SERVER_CERT
is set to TRUE
then
the upstream server's certificate will be validated against the CA
public cert at /etc/keys/upstream-server-ca
.
docker run -e 'PROXY_SERVICE_HOST=https://stackexchange.com' \
-e 'PROXY_SERVICE_PORT=443' \
-e 'VERIFY_SERVER_CERT=TRUE' \
-v "/path/to/ca.crt:/etc/keys/upstream-server-ca" \
-p 8443:443 \
quay.io/ukhomeofficedigital/nginx-proxy:v2.1.0
The example below will return "ping ok" for the URL /ping.
docker run -e 'PROXY_SERVICE_HOST=http://stackexchange.com' \
-e 'PROXY_SERVICE_PORT=80' \
-e 'ADD_NGINX_LOCATION_CFG=if ($uri = /proxy-ping) return 200 "ping ok";' \
-p 8443:443 \
quay.io/ukhomeofficedigital/nginx-proxy:v1.0.0
The example below will return "404" for the URL /notfound.
docker run -e 'PROXY_SERVICE_HOST=http://stackexchange.com' \
-e 'PROXY_SERVICE_PORT=80' \
-e 'ADD_NGINX_SERVER_CFG=location /notfound { return 404; };' \
-p 8443:443 \
quay.io/ukhomeofficedigital/nginx-proxy:v1.0.0
The example below enables proxy_cache_path directive. Allows you to define where cached files are stored.
docker run -e 'PROXY_SERVICE_HOST=http://stackexchange.com' \
-e 'PROXY_SERVICE_PORT=80' \
-e 'ADD_NGINX_HTTP_CFG=proxy_cache_path /data/nginx/cache levels=1:2 keys_zone=static:10m;' \
-p 8443:443 \
quay.io/ukhomeofficedigital/nginx-proxy:v1.0.0
To add basic auth to your server you need to define the username and password by mounting a file and defining that file in the BASIC_AUTH
variable, then add the location config to you config.
docker run -e 'PROXY_SERVICE_HOST=http://stackexchange.com' \
-e 'PROXY_SERVICE_PORT=80' \
-e 'ADD_NGINX_LOCATION_CFG='auth_basic "Restricted"; auth_basic_user_file /etc/secrets/.htpasswd;' \
-e BASIC_AUTH='/etc/secrets/basic-auth'
-p 8443:443 \
-v ~/Documents:/etc/secrets/
quay.io/ukhomeofficedigital/nginx-proxy:v1.0.0
The basic auth file will look like this.
admin:testing
username:password
If you're using multiple locations then we need to define the location that basic_auth will be set in relation to the LOCATIONS_CSV
docker run -e 'PROXY_SERVICE_HOST=http://serverfault.com' \
-e 'PROXY_SERVICE_PORT=80' \
-e 'LOCATIONS_CSV=/,/about' \
-e 'CLIENT_CERT_REQUIRED_2=TRUE' \
-e BASIC_AUTH_2=/etc/secrets/basic-auth \
-v "${PWD}/client_certs/ca.crt:/etc/keys/client-ca" \
-p 8443:443 \
quay.io/ukhomeofficedigital/nginx-proxy:v1.0.0
this will setup basic-auth for the the /about
location or simply swap the 2 for a 1 to setup basic auth for the root location.
- OpenResty - OpenResty (aka. ngx_openresty) is a full-fledged web application server by bundling the standard Nginx core, lots of 3rd-party Nginx modules, as well as most of their external dependencies.
- Nginx - The proxy server core software.
- ngx_lua - Embed the power of Lua into Nginx
- Naxsi - NAXSI is an open-source, high performance, low rules maintenance WAF for NGINX
- GeoLite data This product includes GeoLite data created by MaxMind.
Feel free to submit pull requests and issues. If it's a particularly large PR, you may wish to discuss it in an issue first.
Please note that this project is released with a Contributor Code of Conduct. By participating in this project you agree to abide by its terms.
We use SemVer for the version tags available See the tags on this repository.
- Lewis Marshal - Initial work - lewismarshall
See also the list of contributors who participated in this project.
This project is licensed under the MIT License - see the LICENSE.md file for details