How if condition work inside location block in nginx conf? - nginx-location

location /x/ {
limit_conn x 500;
add_header Access-Control-Allow-Origin *;
allow all;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $http_connection;
chunked_transfer_encoding off;
proxy_buffering off;
proxy_cache off;
proxy_read_timeout 2073600;
if ($http_upgrade = websocket) {
proxy_pass http://x;
}
if ($http_upgrade != websocket) {
proxy_pass http://y;
}
}
Here i want to make "websocket" to case insensitive(ignore case).How can i make? I have tried some things myself. Like:
1.
if ($http_upgrade = ~*websocket) {
proxy_pass http://x;
}
if ($http_upgrade != ~*websocket) {
proxy_pass http://y;
}
2.
if ($http_upgrade = "(?i) websocket") {
proxy_pass http://x;
}
if ($http_upgrade != "(?i) websocket") {
proxy_pass http://y;
}
But both of case, these are not working.

Please try like these :
if ($http_upgrade == "websocket")
{
proxy_pass http://x;
}
if ($http_upgrade != "websocket")
{
proxy_pass http://y;
}
OR
if ($http_upgrade == "websocket")
{
proxy_pass http://x;
}
else
{
proxy_pass http://y;
}

Related

When using Nginx reverse proxy, how can I set IP whitelist based on request URI parameter?

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.

Using proxy_set_header with proxy_redirect?

We have a nuxt app, and we need to have:
https://outer.domain.com/windows/thank-you
to be proxied to:
https://inner.domain.com/thank-you
I tried this:
server {
server_name outer.domain.com;
listen 80;
location /windows {
location /windows/ {
proxy_set_header Host inner.domain.com;
proxy_pass http://127.0.0.1:4300/;
}
location /windows/thank-you/ {
proxy_set_header Host inner.domain.com;
proxy_redirect http://$host/windows/thank-you/ /;
proxy_pass http://127.0.0.1:4300;
}
}
}#server block
But proxy_redirect seems not working, is there anything I am missing?

Nginx looking for files instead of URI when proxying

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;
}
}

Can't change url with map and do redirect

I need to set up redirecting some requests to api depending on the value of variables. When using if statements, everything works fine. But when I try to use map instead of if, I get a "the rewritten URI has a zero length" error.
My working config file using if:
proxy_set_header X-Forwarded-Proto $scheme;
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_set_header X-Forwarded-Server $host;
proxy_redirect off;
upstream backend {
server 192.168.2.2:5987;
}
server {
listen 80;
server_name exemple.com;
client_max_body_size 32m;
charset utf-8;
location /static/ {
alias /opt/project/public/;
}
location /media/ {
alias /opt/project/media/;
}
location /api/v2/ {
set $go "";
# abc query parameter exists
if ($arg_abc) {
set $abc $arg_abc;
set $go "abc";
}
# id query parameter exists
if ($arg_id) {
set $mid $arg_id;
set $go "${go}id";
}
# For v2 REST API remove id query parameter from URL
if ($args ~ (.*)id=[^&]*(.*)) {
set $args $1$2;
}
# For v2 REST API remove abc query parameter from URL
if ($args ~ (.*)abc=[^&]*(.*)) {
set $args $1$2;
}
# only id query parameter exists
if ($go = "id") {
rewrite ^/api/v2/(.*)$ /api/v1/$1$mid/ last;
}
# only id and abc query parameters exists
if ($go = "abcid") {
rewrite ^/api/v2/(.*)$ /api/v1/$1$mid/$abc/ last;
}
}
location / {
proxy_pass http://backend;
}
}
And my not working config using map:
proxy_set_header X-Forwarded-Proto $scheme;
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_set_header X-Forwarded-Server $host;
proxy_redirect off;
map $arg_abc $abc {
default $arg_abc;
}
map $arg_abc $go {
default abc;
}
map $arg_id $mid {
default $arg_id;
}
map $arg_id $go {
default ${go}id;
}
map $args $args {
~(.*)id=[^&]*(.*) $1$2;
~(.*)abc=[^&]*(.*) $1$2;
}
map $go $api_v1 {
id /api/v1/$1$mid/;
abcid /api/v1/$1$mid/$abc/;
}
upstream backend {
server 192.168.2.2:5987;
}
server {
listen 80;
server_name exemple.com;
client_max_body_size 32m;
charset utf-8;
location /static/ {
alias /opt/project/public/;
}
location /media/ {
alias /opt/project/media/;
}
location /api/v2/ {
set $go "";
rewrite ^/api/v2/(.*)$ $api_v1 last;
}
location / {
proxy_pass http://backend;
}
}
As I found out, I get the error "the rewritten URI has a zero length" because the $api_v1 variable remains empty, since the $go value remains empty, but why is map not processing the url? I tried installing / before $api_v1 in location, but then only parameters without the /api/v1/ part come to my backend.
For example, after processing the request http://exemple.com/api/v2/exemple/test/?id=9090&abc=xyz&stop=pots&rest=api
I expect to get http://exemple.com/api/v1/exemple/test/9090/xyz/?stop=pots&rest=api
But I get http://exemple.com/?id=9090&abc=xyz&stop=pots&rest=api
What's wrong with my map settings?

Always 'proxy_pass' and require 'auth_basic' on requests started with '/admin'. How to write the nginx config?

This is what I have. The problem is the proxy settings are duplicated. What's the better way to do it?
proxy_redirect off;
location / {
if (!-f $request_filename) {
proxy_pass http://backend;
}
}
location /admin {
auth_basic 'Restricted';
auth_basic_user_file passwd;
if (!-f $request_filename) {
proxy_pass http://backend;
}
}
Try it:
Location / {
proxy_redirect off;
if (!-f $request_filename) {
proxy_pass http://backend;
}
location ~ ^/admin {
auth_basic 'Restricted';
auth_basic_user_file passwd;
}
}
This may help.
proxy_redirect off;
location / {
try_files $uri #proxy;
}
location #proxy {
if ( $uri ~* "^/admin/? ) {
auth_basic 'Restricted';
auth_basic_user_file passwd;
}
proxy_pass http://backend;
}

Resources