-
-
Save pauloricardomg/7084524 to your computer and use it in GitHub Desktop.
# | |
# 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; | |
} | |
} |
Thank you!
What is this piece for in the regex?
(:[0-9]+)?
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?
(:[0-9]+)?
That covers an optional port in the url
I believe https://badsite.com/?q=sub.mckinsey.com
will also match the $http_origin
regex check, might be an security issue.
Good work, really, thank you.
Thanks for sharing.
Does anyone know how to get add_header on RHEL7? Seems like I can't install the nginx extras needed for this to work
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]+)?$
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.
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
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';
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]+)?$
Thank you so much, this was helpful.
@anastasiosyal you are right. The most secure regex will at least look something like
https?:\/\/([a-z0-9-]+\.)*mckinsey\.com(:[0-9]+)?$
Since hostname parts cannot contain anything except alphanumeric characters and dash RFC 952.
Why don't we define $http_origin ?
Access nginx website https://nginx.org/en/docs/varindex.html ,I don't see this variable.
If use https request, the $http_origin it's invalid.
Hey there. Where should I use this code? Please
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
Thanks for inspiration. Here's what we use with added exposed headers: https://gist.github.com/iki/1247cd182acd1aa3ee4876acb7263def
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
Yeah,I think so!
Thank you Very very Much For Posting this solution. I had been Battling with this for 2 months. But in less than 3min, i was able to fix it with the solution you provided.
Hey there. Where should I use this code? Please
@julioaze in your /etc/nginx/sites-available/default
or somewhere with similar functionality.
Thanks 🙇