Skip to content

Instantly share code, notes, and snippets.

@pauloricardomg
Last active November 25, 2024 15:33
Show Gist options
  • Save pauloricardomg/7084524 to your computer and use it in GitHub Desktop.
Save pauloricardomg/7084524 to your computer and use it in GitHub Desktop.
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;
}
}
@neskhodovskiy
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
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
Copy link

opsarno commented Nov 13, 2018

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

@julioaze
Copy link

Hey there. Where should I use this code? Please

@cvbuelow
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
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

@libmw
Copy link

libmw commented Aug 12, 2021

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!

@feelchi1star
Copy link

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.

@kasir-barati
Copy link

Hey there. Where should I use this code? Please

@julioaze in your /etc/nginx/sites-available/default or somewhere with similar functionality.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment