I'm trying to setup nginx as reverse proxy.
When I using just this simple config, all works well.
location / {
proxy_pass https://domain.name;
proxy_ssl_server_name on;
}
But in my case I have a legacy API and a lot of conditions, and when I using more complex prefix, regex or exact match in case, when my URI looks like this one:
/v1/Server.ashx?parameter=value
nginx looking for file Server.ashx in default root folder "/usr/share/nginx/html/v1/Server.ashx" instead of proxying, and returns 404.
How can I fix this problem?
In my case, this approach helped.
Open for any other advices.
server{
listen 8111;
server_name 192.168.137.43;
location /v1/Server.ashx {
error_page 418 = #specificpage;
error_page 419 = #websocket;
if ($query_string = "parameter=value") {
return 418;
}
if ($query_string = "") {
return 419;
}
if ($query_string = "otherparameter=othervalue") {
return 419;
}
proxy_pass https://domain.name;
proxy_ssl_server_name on;
}
location / {
error_page 419 = #websocket;
if ($request_uri = "/v2") {
return 419;
}
if ($request_uri = "/v2?parameter=value") {
return 419;
}
proxy_pass https://domain.name;
proxy_ssl_server_name on;
}
location #specificpage {
proxy_pass https://other.domain.name;
proxy_ssl_server_name on;
}
location #websocket {
proxy_pass http://domain.name;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
}
}
Related
I have a very simple nginx.conf nginx configuration to test Nginx limit_req rate limiting,
here the below is the part of the config,
limit_req_zone $binary_remote_addr zone=req_zone:10m rate=1r/s;
server {
listen 8012;
location / {
limit_req zone=req_zone burst=2 nodelay;
proxy_pass "http://127.0.0.1:3001";
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
location ^~ /api/ {
limit_req zone=req_zone burst=1 nodelay;
proxy_pass "http://127.0.0.1:8000";
}
location ^~ /accounts/ { proxy_pass "http://127.0.0.1:8000"; }
location ^~ /comments/ { proxy_pass "http://127.0.0.1:8000"; }
location = /api/ { return 401; }
location = /api/comments/ { return 401; }
}
Then open up http://localhost:8012/, trying a many set of requests through chrome dev console. i.e. I run the below like 10 times a second
axios.get('/api/comments/22')
But nothing happens, no 503 error, just succeeds to get the response.
Since the setup is pretty simple, I have really no idea what's missing (or a nginx bug?) here. Thanks for your help.
My url like this:
http://myserver/app/inf?ConId=Obj%3Acom.aaa.bbb%3A3712 # Only IP in whitelist can access
http://myserver/app/...... # all user can access
When the parameter of ConId is Obj%3Acom.aaa.bbb%3A3712, I need to restrict only specific IP can access my server.
I tried the following Nginx configuration but not working.
location / {
if ( $arg_ConId = "Obj%3Acom.aaa.bbb%3A3712" ) {
allow 192.168.1.104;
deny all;
}
proxy_pass http://192.168.234.130:80;
add_header Access-Control-Allow-Origin *;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
allow all;
}
Please help, thanks!
Thanks #araisch,my final working Nginx Configuration is:
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
#keepalive_timeout 0;
keepalive_timeout 65;
server {
listen 80;
server_name localhost;
error_page 403 /403.html;
location = /403.html {
root html;
}
if ($arg_ConId = "Obj%3Acom.aaa.bbb%3A3712") {
set $BLOCKING A;
}
if ($remote_addr != "192.168.3.11") {
set $BLOCKING "${BLOCKING}B";
}
if ($BLOCKING = AB) {
return 403;
break;
}
location / {
proxy_pass http://192.168.234.130:80;
add_header Access-Control-Allow-Origin *;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
allow all;
}
}
}
Could use something like:
if ($arg_ConId = "Obj%3Acom.aaa.bbb%3A3712") {
set $BLOCKING A;
}
if ($remote_addr != 192.168.1.104) {
set $BLOCKING "${BLOCKING}B";
}
if ($BLOCKING = AB) {
return 403;
break;
}
in server block.
Problems in your code:
if Directives in location are considered as evil due to nginx` strange declaration rules. They're doing most of the time strange things, so try to avoid it.
$arg_ContainerOID does not catch an argument named "ConId"
Remark: This is not working in dockerized nginx in bridge mode, because the real IP is masked by the firewall.
You can use something like this:
location / {
auth_request /auth-here;
}
location /auth-here {
internal;
proxy_pass http://192.168.234.130:80/auth.php;
proxy_pass_request_body off;
proxy_set_header Content-Length "";
proxy_set_header X-Original-URI $request_uri;
}
Then in your script you can check $_SERVER['HTTP_X_ORIGINAL_URI'] and return HTTP 200 to allow the request or HTTP 403 to deny the request.
You will need the http_auth_request_module for the above to work, as explained in the documentation.
I have an nginx as a reverse proxy, which does some proxy_pass things. The Proxy is in front of an angular SPA with HTML5 routing enabled + other ugly stuff around so I can't handle the 404 on the Server which deliveres the Page.
At the moment I have the following config:
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
server {
listen 3000;
location /int {
proxy_pass http://localhost:9131/int;
proxy_set_header X-Forwarded-For "127.0.0.1";
}
location /app/static {
proxy_pass http://localhost:9131/int/static;
proxy_set_header X-Forwarded-For "127.0.0.1";
}
location /app/api {
proxy_pass http://localhost:9131/int/api;
proxy_set_header X-Forwarded-For "127.0.0.1";
}
location / {
proxy_set_header Accept-Encoding "";
proxy_pass https://example.com/;
sub_filter 'https://example.com/int' 'http://$host:$server_port/int';
sub_filter '<base />' '<base href="/app/" />';
proxy_intercept_errors on;
error_page 404 = #fallback;
}
# EDIT: after comment, but got the following Error:
# "proxy_pass" cannot have URI part in location given by regular
# expression, or inside named location, or inside "if" statement,
# or inside "limit_except" block in ...\nginx-1.14.2/conf
# /nginx.conf:37
location #fallback {
proxy_pass http://localhost:3000/app;
}
}
}
When I go to example.com/app/foobar I got a redirect to example.com/app. What I want is a forward, so that I got the content of example.com/app without modifying the URL or the Statuscode. Then the SPA could handle the routing.
Edit:
Added config with named location (#fallback}
I have a working nginx instance with the rules below. But I'm having difficulties pointing all the requests to domain.com/ghost
I tried modifying the location / {} block to location /ghost/ {} but with no success. I just get a 404 from the ghost app. Any suggestions?
server {
listen 80;
server_name domain.com;
root /home//user/ghost/;
index index.php;
# if ($http_host != "domain.com") {
# rewrite ^ http://domain.com$request_uri permanent;
# }
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
proxy_pass http://127.0.0.1:2368;
}
location ~* \.(?:ico|css|js|gif|jpe?g|png|ttf|woff)$ {
access_log off;
expires 30d;
add_header Pragma public;
add_header Cache-Control "public, mustrevalidate, proxy-revalidate";
proxy_pass http://127.0.0.1:2368;
}
location = /robots.txt { access_log off; log_not_found off; }
location = /favicon.ico { access_log off; log_not_found off; }
location ~ /\.ht {
deny all;
}
}
I'm using a regexp location directive for a similar proxy setup. This is the minified configuration file:
worker_processes 1;
pid /path/to/file.pid;
worker_priority 15;
events {
worker_connections 512;
accept_mutex on;
}
http {
server {
error_log /path/to/log/error.log error;
listen 127.0.0.1:9000;
server_name example.com;
location ~* (/ghost) {
expires epoch;
proxy_no_cache 1;
proxy_pass http://localhost:1234;
}
location / {
proxy_pass http://localhost:1234;
}
}
}
Have solved similar problem with other apps which have no support for subfolders. Both apps are built on one platform, so they both tries to work in /fx dir. I had to place one of them in to subfolder /gpms .
The idea is to redirect requests with referer from subfolder to destinations which links outside of subfolder - i just add subfolder to beginning of such uris. It is not ideal, but it works.
Here is my nginx config:
server {
listen 80;
server_name mydomain.com;
location / {
rewrite ^/$ /fx/;
proxy_pass http://127.0.0.1:56943/;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_read_timeout 300;
}
error_log /var/log/nginx/debug.log debug;
set $if_and_hack "";
if ( $http_referer ~ '^http://mydomain.com/gpms/.*$' ) {
set $if_and_hack "refgpms";
}
if ( $uri !~ '^/gpms/.*$' ) {
set $if_and_hack "${if_and_hack}_urinogpms";
}
if ( $if_and_hack = "refgpms_urinogpms" ) {
rewrite ^/(.*)$ http://$host/gpms/$1;
}
location /gpms/ {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_cookie_path /fx /;
proxy_pass http://127.0.0.1:12788/fx/;
proxy_redirect default;
}
}
External links will be broken, but it is not critical for me and i guess it may be corrected.
$if_and_hack is for overcome nginx limitation on nested conditions.
By the way i have got a cookies issue, because they was set with path, and hit browser bug with not sending cookies for a new path after redirect, so i just remove path from cookies.
Note full link form in rewrite - this form of rewrite immediately redirects browser to new page, you should not change it to just "/gpms/$1".
As alternative, i guess, it may be possible to use nginx module to inspect html content and modify links. I have not tried this. Or consider to use subdomains instead of subfolders.
Good news! As of version 0.4.0 Ghost now supports subdirectory installation. And there are already people who've figured this out and created tutorials.
I am trying to rewrite a secure link, here is my nginx conf:
location /files/ {
deny all;
return 403;
}
# MEMBERS ONLY #####
location /auth/ {
secure_link $arg_h,$arg_e;
secure_link_md5 authkey$uri$arg_e;
if ($secure_link = "") {
return 403;
}
if ($secure_link = "0") {
return 403;
}
rewrite ^/auth/(.*)$ /files/$1 break;
add_header Content-Disposition "attachment; filename=$arg_f";
}
Its work if I put download link like this:
http://13.37.13.37/auth/path/to/dir/file.zip?h=sdiouqosid&e=1337&f=the_file.zip
but it does not if I print link like this:
http://subdir.mysite.org/auth/path/to/dir/file.zip?h=sdiouqosid&e=1337&f=the_file.zip
Please note:
subdir.mysite.org has "A" redir to 13.37.13.37 in DNS records
13.37.13.37 is different server than mysite.org
Also:
- http://subdir.mysite.org/path/to/something/somefile.zip works great, it's only when I use secure_link that it fails (returns either a 403 or a fail to load ressource). I guess it has something to do with my url_rewrite. I tried a lot of things without any success regarding this weird behaviour.
Thank you for your help
EDIT:
full nginx below:
user www-data;
worker_processes 2;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
#server_tokens off;
keepalive_timeout 65;
gzip on;
gzip_disable "msie6";
limit_conn_zone $binary_remote_addr zone=freeuser:10m;
map $request_uri $request_qs {
default '';
~.*\?(?P<key>.+)$ $key;
}
server {
listen 80;
server_name localhost;
root /var/www;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
access_log off;
add_header Cache-Control public;
}
location ~* \.(jpg|jpeg|gif|css|png|js|ico|swf|mp3)$ {
expires 365d;
access_log off;
}
location /file/ {
deny all;
return 403;
}
location /auth/ {
secure_link $arg_h,$arg_e;
secure_link_md5 authkey$uri$arg_e$remote_addr;
if ($secure_link = "") {
return 403;
}
if ($secure_link = "0") {
return 403;
}
rewrite ^/auth/(.*)$ /file/$1 break;
add_header Content-Disposition "attachment; filename=$arg_f";
}
}
}
I'd say change the /files block, because right now it's logical to return 403, because you just deny all.
location /files/ {
internal;
}
This would return 404 for non authorized instead of 403, don't know if that works for you.
I solved my problem editing the "Reverse" (hostname).
Regards,