Skip to content

Docker https/ssl reverse proxy w/ nginx. Supports: Auto request letsencrypt cert, CORS, HTTP Auth, Real-time/Low Latency...

Notifications You must be signed in to change notification settings

kittenlaserattack/ssl-proxy

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

55 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Simple docker & nginx-based ssl-proxy

Protect any HTTP service with HTTPS!

An Nginx & Docker-based HTTPS/SSL reverse proxy.

Table of Contents

  1. Features
  2. Example
  3. Getting Started
    1. Secure Docker Registry Example
    2. Secure Rancher Server Example
    3. Docker Compose Example
  4. Arguments / Configuration

Features

  • Up-to-date Nginx & Alpine Linux.
  • Fast HTTP2 TLS-enabled reverse proxy
  • Advanced CORS Support (w/ credentials, auto hostname, smart headers)
  • Automatic WebSockets Support
  • NPN/ALPN Application-Layer Protocol Negotiation test here
  • TLS Forward Secrecy, PFS (aka Perfect Forward Secrecy).
  • Supports Optional Username & Password (stored using bcrypt at 14+ rounds)
    • Alternately an .htpasswd file can be volume mounted. (Multiple named users)
  • Great for securing a Docker Registry, Rancher server, Wordpress, etc

Example

Sample SSL Labs/Qualys SSL & TLS Report:

Here's a sample of what you can expect with default configuration.

image image

Getting Started

Requirements

  1. Generate a HTTPS/SSL certificate using letsencrypt.

To provide secure, proxied access to local HTTP service:

  1. Requires any working HTTP service (for UPSTREAM_TARGET.) (Supports local, in-docker, even remote).
  2. Start an instance of justsml/ssl-proxy:latest as shown below.

Secure Docker Registry Example

# Note: Small scale users can set certificates directly in the registry instance (v2+) 
docker run -d --restart=on-failure:5 \
  --name docker-registry \
  -v /data/registry/registry:/var/lib/registry \
  registry:2.5

# Create an ssl-proxy to point at the registry's port 5000 (via UPSTREAM_TARGET option - see below.)
docker run -d --restart=on-failure:5 \
  --name ssl-proxy \
  -p 5000:5000 \
  -e 'SERVER_NAME=hub.example.com' \
  -e 'UPSTREAM_TARGET=docker-registry:5000' \
  -e 'HTTPS_PORT=5000' \
  -e 'USERNAME=devops' \
  -e 'PASSWORD=secure' \
  -e 'CERT_PUBLIC_PATH=/certs/fullchain.pem' \
  -e 'CERT_PRIVATE_PATH=/certs/privkey.pem' \
  -e "ADD_HEADER='Docker-Distribution-Api-Version' 'registry/2.0' always" \
  -v '/certs:/certs:ro' \
  --link 'docker-registry:docker-registry' \
  justsml/ssl-proxy:latest

# ALT Options
# Create an ssl-proxy to point at the registry's port 5000 (via UPSTREAM_TARGET option - see below.)
docker run -d --restart=on-failure:5 \
  --name ssl-proxy \
  -p 5000:5000 \
  -e 'SERVER_NAME=hub.example.com' \
  -e 'UPSTREAM_TARGET=docker-registry:5000' \
  -e 'EXPIRES_DEFAULT=-1' \
  -e 'HTTPS_PORT=5000' \
  -e 'USERNAME=devops' \
  -e 'PASSWORD=secure' \
  -e 'CERT_PUBLIC_PATH=/certs/fullchain.pem' \
  -e 'CERT_PRIVATE_PATH=/certs/privkey.pem' \
  -e "ADD_HEADER='Docker-Distribution-Api-Version' 'registry/2.0' always" \
  -v '/certs:/certs:ro' \
  --link 'docker-registry:docker-registry' \
  justsml/ssl-proxy:latest

Secure Rancher Server Example

# Update Cached Docker Images
docker pull rancher/server:latest
docker pull justsml/ssl-proxy:latest

# Start Rancher w/ default local port 8080
docker run -d --restart=always \
  --name rancher-server \
  -v /data/rancher/mysql:/var/lib/mysql \
  rancher/server:latest

# Create an ssl-proxy with certs in /certs, (w/o user/pass auth) to point at the local rancher-server's port 8080
docker run -d --restart=always \
  --name rancher-proxy \
  -p 8080:8080 \
  -e 'HTTPS_PORT=8080' \
  -e 'SERVER_NAME=_' \
  -e 'UPSTREAM_TARGET=rancher-server:8080' \
  -e 'CERT_PUBLIC_PATH=/certs/fullchain.pem' \
  -e 'CERT_PRIVATE_PATH=/certs/privkey.pem' \
  -v '/certs:/certs:ro' \
  --link 'rancher-server:rancher-server' \
  justsml/ssl-proxy:latest

Docker Compose Example

version: '2'
services:
  ssl-proxy:
    image: justsml/ssl-proxy:latest
    environment:
    - HTTPS_PORT=8080
    - SERVER_NAME=rancher.example.com
    - UPSTREAM_TARGET=rancher-server:8080
    - CERT_PUBLIC_PATH=/certs/fullchain.pem
    - CERT_PRIVATE_PATH=/certs/privkey.pem
    volumes:
    - /certs:/certs:ro
    links:
    - 'rancher-server:rancher-server'
    ports: [ '8080:8080' ]
  rancher-server:
    image: rancher/server:latest
    expose: [ '8080' ]
    volumes:
    - /data/rancher/mysql:/var/lib/mysql

Arguments

Name Default/Reqd Notes
CERT_AUTO Optional Set to true to automatically request certificate for $SERVER_NAME - caution: don't exceed let's encrypts API limits.
CERT_PUBLIC_PATH Reqd. PEM file Bind-mount certificate files to container path /certs - Or override path w/ this var.
CERT_PRIVATE_PATH Reqd. PEM file Bind-mount certificate files to container path /certs - Or override path w/ this var.
SERVER_NAME Required Primary domain name. Not restricting.
UPSTREAM_TARGET Required HTTP target host:port. Typically an internally routable address. e.g. localhost:9090 or rancher-server:8080
HTTPS_PORT 443/Required Needed for URL rewriting.
ALLOW_RC4 Not set Backwards Compatible Option Required for Java 6 or WinXP/IE8
EXPIRES_DEFAULT Not set Set to apply a default expiration value for nginx location /. Useful for app & caching proxies. (For app use -1 and for caching proxy something like 6h)
USERNAME admin Both PASSWORD and USERNAME must be set in order to use Basic authorization
PASSWORD Both PASSWORD and USERNAME must be set in order to use Basic authorization
PASSWD_PATH /etc/nginx/.htpasswd Alternate auth support (don't combine with USERNAME/PASSWORD) Bind-mount a custom path to /etc/nginx/.htpasswd
ADD_HEADER Not set Useful for tagging routes in your infrastructure.

===================


Contributing / Dev Notes

WORK IN PROGRESS:

  1. HTTPS -> HTTPS proxying support. AKA End-to-end TLS. (skipped due to underwhelming performance and extra complexity in the bash startup script.)
  2. Better CORS support: multi host name
  3. haproxy alt version
# Publish 'latest' version
docker build -t ssl-proxy:latest .
docker tag ssl-proxy:latest justsml/ssl-proxy:latest
docker push justsml/ssl-proxy:latest
# Push a tagged version:
# docker tag ssl-proxy:latest justsml/ssl-proxy:v1.0.1
# docker push justsml/ssl-proxy:v1.0.1

# Remember to docker pull on servers
docker pull justsml/ssl-proxy:latest

# Local testing:
docker build -t ssl-proxy:latest .
docker rm -f TEST-ssl-proxy
docker run --rm \
  --name TEST-ssl-proxy \
  -v ~/certs/xray:/certs \
  -p 5000:5000 \
  -e 'HTTPS_PORT=5000' \
  -e 'USERNAME=devops' \
  -e 'PASSWORD=secure' \
  -e 'SERVER_NAME=hub.example.com' \
  -e 'UPSTREAM_TARGET=www.google.com:80' \
  -e 'CERT_PUBLIC_PATH=/certs/fullchain.pem' \
  -e 'CERT_PRIVATE_PATH=/certs/privkey.pem' \
  ssl-proxy:latest

About

Docker https/ssl reverse proxy w/ nginx. Supports: Auto request letsencrypt cert, CORS, HTTP Auth, Real-time/Low Latency...

Resources

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Shell 100.0%