Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Nginx configuration for CORS-enabled HTTPS proxy with origin white-list defined by a simple regex
#
# Acts as a nginx HTTPS proxy server
# enabling CORS only to domains matched by regex
# /https?://.*\.mckinsey\.com(:[0-9]+)?)/
#
# Based on:
# * http://blog.themillhousegroup.com/2013/05/nginx-as-cors-enabled-https-proxy.html
# * http://enable-cors.org/server_nginx.html
#
server {
listen 443 default_server ssl;
server_name localhost;
# Fake certs - fine for development purposes :-)
ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem;
ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key;
ssl_session_timeout 5m;
location / {
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# Nginx doesn't support nested If statements, so we
# concatenate compound conditions on the $cors variable
# and process later
# If request comes from allowed subdomain
# (*.mckinsey.com) then we enable CORS
if ($http_origin ~* (https?://.*\.mckinsey\.com(:[0-9]+)?$)) {
set $cors "1";
}
# OPTIONS indicates a CORS pre-flight request
if ($request_method = 'OPTIONS') {
set $cors "${cors}o";
}
# Append CORS headers to any request from
# allowed CORS domain, except OPTIONS
if ($cors = "1") {
more_set_headers 'Access-Control-Allow-Origin: $http_origin';
more_set_headers 'Access-Control-Allow-Credentials: true';
proxy_pass http://serverIP:serverPort;
}
# OPTIONS (pre-flight) request from allowed
# CORS domain. return response directly
if ($cors = "1o") {
more_set_headers 'Access-Control-Allow-Origin: $http_origin';
more_set_headers 'Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE';
more_set_headers 'Access-Control-Allow-Credentials: true';
more_set_headers 'Access-Control-Allow-Headers: Origin,Content-Type,Accept';
add_header Content-Length 0;
add_header Content-Type text/plain;
return 204;
}
# Requests from non-allowed CORS domains
proxy_pass http://serverIP:serverPort;
}
}
@marcwebbie

This comment has been minimized.

Copy link

marcwebbie commented Oct 21, 2013

Thank you for sharing.

@ochko

This comment has been minimized.

Copy link

ochko commented Mar 31, 2015

Thanks 🙇

@meglio

This comment has been minimized.

Copy link

meglio commented Mar 18, 2016

Thank you!
What is this piece for in the regex?

(:[0-9]+)?
@meglio

This comment has been minimized.

Copy link

meglio commented Mar 18, 2016

Another question: why are you using more_set_headers instead of add_header with "always" option? Any special reason for that, or was it jut not available at the time when you created this gist?

@studious

This comment has been minimized.

Copy link

studious commented Mar 30, 2016

(:[0-9]+)?
That covers an optional port in the url

@boltgolt

This comment has been minimized.

Copy link

boltgolt commented Nov 19, 2016

I believe https://badsite.com/?q=sub.mckinsey.com will also match the $http_origin regex check, might be an security issue.

@plrunner

This comment has been minimized.

Copy link

plrunner commented Nov 24, 2016

Good work, really, thank you.

@cchang62

This comment has been minimized.

Copy link

cchang62 commented Jan 25, 2017

Thanks for sharing.

@genomics-geek

This comment has been minimized.

Copy link

genomics-geek commented Feb 27, 2017

Does anyone know how to get add_header on RHEL7? Seems like I can't install the nginx extras needed for this to work

@gantaa

This comment has been minimized.

Copy link

gantaa commented Apr 4, 2017

Here is the regex that does NOT match badsite.com security flaw proposed by @boltgolt, but still matches desired domains:

https?:\/\/.[^?]*\.mckinsey\.com(:[0-9]+)?$

@gopal-g

This comment has been minimized.

Copy link

gopal-g commented Aug 15, 2017

I am running nginix 1.11.9 and i get the error : unknown directive more_set_headers, I am actually working on vagrant environment with laravel homestead platform hence i am also not sure if this configuration change needs to be updated every time i reload the vagrant. this is my first project on vagrant/homestead.

#Update

I ran sudo apt-get install nginx-extras
restarted nginx - its working just fine

and i even rebooted the vagrant to see if i will lose the changes luckily i didn't thank you very much for this. I am using this script to allow CORS for a angular app satellizer as front-end client with laravel as backend just in case any one is wondering if they can use it for the one of these :) Thank you.

@fkoksal

This comment has been minimized.

Copy link

fkoksal commented Sep 27, 2017

Here is the regex that worked for me:
https?:\/\/(.[^?]*\.)?mckinsey\.com(:[0-9]+)?$

  • matches both http and https
  • matches with or without subdomains
  • does not match badsite.com
@ZeusMode

This comment has been minimized.

Copy link

ZeusMode commented Sep 29, 2017

for those who are having problems with more_set_headers, you should use add_header.

PS: add_header need 2 params
add_header 'Access-Control-Allow-Credentials' 'true';

@anastasiosyal

This comment has been minimized.

Copy link

anastasiosyal commented Mar 9, 2018

Security by regex, will always be weak. Here's another expression that will bypass the 'fixed' version of the regex:
https://badsite.com/#sub.mckinsey.com
There's probably more attack vectors even if you did expand the regex to include the hash exclusion as below
https?:\/\/(.[^?#]*\.)?mckinsey\.com(:[0-9]+)?$

@cholnhial

This comment has been minimized.

Copy link

cholnhial commented Jun 25, 2018

Thank you so much, this was helpful.

@neskhodovskiy

This comment has been minimized.

Copy link

neskhodovskiy commented Aug 31, 2018

@anastasiosyal you are right. The most secure regex will at least look something like

https?:\/\/([a-z0-9-]+\.)*mckinsey\.com(:[0-9]+)?$

Test on regex101

Since hostname parts cannot contain anything except alphanumeric characters and dash RFC 952.

@opsarno

This comment has been minimized.

Copy link

opsarno commented Nov 9, 2018

Why don't we define $http_origin ?
Access nginx website https://nginx.org/en/docs/varindex.html ,I don't see this variable.

@opsarno

This comment has been minimized.

Copy link

opsarno commented Nov 13, 2018

If use https request, the $http_origin it's invalid.

@julioaze

This comment has been minimized.

Copy link

julioaze commented Nov 30, 2018

Hey there. Where should I use this code? Please

@cvbuelow

This comment has been minimized.

Copy link

cvbuelow commented Jan 5, 2019

Not sure why you people are concerned about the regex security when using $http_origin. This variable will not include any path info so you don't have to worry about ? and #.
Ref:
https://nginx.org/en/docs/http/ngx_http_core_module.html#var_http_
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Origin

@iki

This comment has been minimized.

Copy link

iki commented Sep 15, 2019

Thanks for inspiration. Here's what we use with added exposed headers: https://gist.github.com/iki/1247cd182acd1aa3ee4876acb7263def

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.