Nginx reverse proxy causing infinite loop - redirect

I have the following in my Nginx site config file:
server {
listen 80 default_server;
listen [::]:80 default_server ipv6only=on;
root /usr/share/nginx/html;
index index.php index.html index.htm;
server_name example.com;
location / {
try_files $uri $uri/ /index.php?q=$uri&$args;
}
error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
}
}
server {
listen 80;
server_name example2.com;
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://localhost/page-1/;
}
}
The issue only seems to occur when I add the proxy_set_header Host $host; line. It appears that the $host variable creates a redirect loop and the GET request from the error server logs goes something like this ...page-1/page-1/page-1/page-1... with the server responding with an internal error 500.
I'd be really grateful if anyone could tell me what I'm doing wrong. Many thanks in advance!

I had the same issue, and as suggested by Alexey Ten, the solution is to remove the Host header.

Related

NGINX not respecting server_name regex

I have this nginx config.. i want it to accept all domains that have the word competitions in it and end with .com.au.. I have tested with a domain name that should NOT be accepted but it reaches the application.. is the server_name being ignore because I'm using a proxy?
server {
listen 80 default_server;
server_name ~^(.+)competitions?(.+)\.com\.au;
access_log /var/log/nginx/$host.access.log;
error_log /var/log/nginx/error.log;
if ($host !~* ^www){
rewrite ^/(.*)$ https://www.$host/$1 permanent;
}
location / {
proxy_no_cache 1;
proxy_set_header Host $host;
proxy_pass http://127.0.0.1:8888;
try_files $uri $uri/ #proxy;
}
location #proxy {
proxy_set_header Host $host;
proxy_pass http://127.0.0.1:8888;
proxy_intercept_errors on;
recursive_error_pages on;
error_page 404 = #rewrite_proxy;
}
location #rewrite_proxy {
rewrite /(.*) /index.cfm?path=$1;
proxy_set_header Host $host;
proxy_pass http://127.0.0.1:8888;
}
}
You'd have to remove the default_server from there, because this is a catch-all directive.And you still could setup another one server with the default_server directive, if required.
See How nginx processes a request for a more detailed explanation:
If its value does not match any server name, or the request does not contain this header field at all, then nginx will route the request to the default server for this port.

Facebook messenger bot callback url curl error 35

I am trying to create a facebook messenger bot. every thing work woth heroku. then i transfer it to my own server. then i got the error "curl errno =35" i tried it with ngrok work fine on the server but not work with my server.
using debian with nginx x and letsencrypt.
the url is preetombot.bddevwork.net
my setting
server {
listen 80;
server_name preetombot.bddevwork.net www.preetombot.bddevwork.net;
#root /usr/share/nginx/www/preetombot.bddevwork.net;
#return 301 https://$server_name$request_uri;
}
server {
listen 443 default_server ssl http2;
server_name preetombot.bddevwork.net
www.preetombot.bddevwork.net;
ssl_stapling on;
ssl_stapling_verify on;
ssl_certificate /etc/letsencrypt/live/preetombot.bddevwork.net/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/preetombot.bddevwork.net/privkey.pem;
ssl_trusted_certificate /test/ca-certs.pem;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:ECDHE-RSA-AES128-GCM-SHA256:AES256+EECDH:DHE-RSA-AES128-GCM-SHA256:AES256+EDH:ECDHE-RSA-AES256-GCM$
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_dhparam /test/dhparam.pem;
root /usr/share/nginx/www/preetombot.bddevwork.net;
index index.php index.html index.htm;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For
$proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_pass http://localhost:5000$request_uri;
proxy_redirect off;
proxy_http_version 1.1;
}
location ~ /.well-known{
allow all;
}
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
expires 365d;
}
error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/www;
}
location ~ \.php$ {
try_files $uri =404;
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME
$document_root$fastcgi_script_name;
include fastcgi_params;
}
}
I have multiple secure ports listening within a single server, in this case for FB bot I'm using port 8083.
upstream botd {
server application_1:8083 max_fails=3 fail_timeout=30s;
keepalive 64;
}
server {
listen 443 default_server;
listen [::]:443 default_server;
# SSL configuration
#
# listen 443 ssl default_server;
# listen [::]:443 ssl default_server;
#
# Note: You should disable gzip for SSL traffic.
# See: https://bugs.debian.org/773332
#
# Read up on ssl_ciphers to ensure a secure configuration.
# See: https://bugs.debian.org/765782
#
# Self signed certs generated by the ssl-cert package
# Don't use them in a production server!
#
# include snippets/snakeoil.conf;
rewrite_log on;
ssl on;
server_name _;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log debug;
ssl_certificate /etc/ssl/techie8.io/api.techie8.io.bundle;
ssl_certificate_key /etc/ssl/techie8.io/api.techie8.io.key;
# Botd skill.
location /botd {
proxy_redirect off;
if (!-f $request_filename) {
proxy_pass http://botd;
break;
}
}
# Techie8 API.
location / {
proxy_set_header X-Forward-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
#Timeout after 8 hours
proxy_read_timeout 43200000;
proxy_connect_timeout 43200000;
proxy_redirect off;
if (!-f $request_filename) {
proxy_pass http://application;
break;
}
}
}
In Flask App:
#app.route('/botd', methods=['GET'])
def handle_verification():
"""Handle Token verification."""
print "Handling Verification."
if request.args.get('hub.verify_token') == VERIFY_TOKEN:
print "Verification successful!"
return request.args.get('hub.challenge')
else:
print "Verification failed!"
return 'Error, wrong validation token'
#app.route('/botd', methods=['POST'])
def handle_messages():
print "Handling Incoming Messages\n"
payload = request.get_data()
print payload
for sender, message in messaging_events(payload):
print "Incoming Message from %s: %s" % (sender, message)
print ("Access Token: %s" % ACCESS_TOKEN)
send_message(ACCESS_TOKEN, sender, message)
return "ok"
In Facebook WebHook Callback URL I have my host configured:
https://api.mycompany.io/botd

Nginx Subdomains: Redirect /.well-known path for Let's Encrypt

I have an Nginx Server running with two sub-domains. One of them uses a proxy_pass to redirect everything to a Meteor Application and the other sub-domain just uses Laravel but in a diffrent directory than the normal domain.
So, when I start ./letsencrypt-auto I get the following error-message for both sub-domains:
Failed authorization procedure. subdomain.mydomain.com (http-01): urn:acme:error:unauthorized ::
The client lacks sufficient authorization :: Invalid response from http://subdomain.mydomain.com/.well-known/acme-challenge/xyzxyzxy_xzyzxyxyyx_xyzyxzyxz: "<html>
<head><title>404 Not Found</title></head>
<body bgcolor="white">
<center><h1>404 Not Found</h1></center>
My interpretation of that is, that it doesn't work because my Laravel-Subdomain is not in /var/www/domain.com/html but in /var/www/laravel/html and my Meteor-Application is somwhere else and ngnix just does the proxy passing.
So my question is: Can I redirect /.well-known/acme-challenge for both subdomains to the real /.well-known so that letsencrypt-auto doesn't throw this error?
More Information:
I've tried
location '/.well-known/acme-challenge' {
default_type "text/plain";
root /tmp/letsencrypt-auto;
}
but it didn't work...
Config for my Meteor sub-domain:
server {
listen 80;
listen [::]:80;
# SSL configuration
listen 443 ssl;
listen [::]:443 ssl;
ssl_certificate /etc/letsencrypt/live/domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/domain.com/privkey.pem;
[…] SSL stuff […]
server_name meteor.domain.com;
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header X-Forwarded-For $remote_addr;
}
location ~ /.well-known {
allow all;
}
}
Config for my Laravel sub-domain:
server {
listen 80;
server_name laravel.domain.com;
listen 443 ssl;
listen [::]:443 ssl;
ssl_certificate /etc/letsencrypt/live/domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/domain.com/privkey.pem;
[…] SSL stuff […]
root /var/www/laravel/html;
location / {
try_files $uri $uri/ /index.php$is_args$args;
}
location ~ /.well-known {
allow all;
}
location ~ \.(hh|php)$ {
fastcgi_keep_conn on;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
Your location ~ /.well-known blocks are regex locations and will take precedence over the prefix location you are attempting to add.
You need to delete them.
See this document on the location directive.
Okay, thanks to the tips from Richard Smith I solved it:
I kept this in the Config-Part for the domain.com-Part as described in this tutorial.
location / {
try_files $uri $uri/ =404;
}
but put that into the Config-Part for subdomain.domain.com instead:
location /.well-known/ {
root /var/www/domain.com/html;
}
What it does is handling any request to subdomain.domain.com/.well-known/[anything] as domain.com/.well-known/[anything], thus no error from letsencrypt-auto.

Nginx HTTP to HTTPS redirect loop

I have the folloiwng Nginx configuration:
server {
listen 80;
server_name .example.net .example.com;
return 301 https://example.com$request_uri;
}
server {
listen 80;
server_name beta.example.com;
error_page 403 /403;
error_page 404 /404;
error_page 500 /500;
client_max_body_size 5M;
# Handle all locations
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;
}
}
server {
listen 443;
ssl on;
ssl_certificate /etc/ssl/cert_chain.crt;
ssl_certificate_key /etc/ssl/csr.pem;
server_name example.com;
error_page 403 /403;
error_page 404 /404;
error_page 500 /500;
client_max_body_size 5M;
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
I'm wanting to redirect HTTP requests to HTTPS however I get a redirect loop. I've read other answers on different questions including this one and this one however none of their solutions solved mine. Any ideas? Thanks.
It seems like your backend (running on 127.0.0.1:8000) issues Location: http://example.com/ header.
Please look into the access logs, nginx's and backend's too.
Or use httpliveheaders or tcpdump to investigate the traffic.

Laravel/Homestead Nginx SSL Redirect Loop

I have seen other topics like this one: Nginx configuration leads to endless redirect loop, however all of the configurations I have tried with no change.
Problem: I want to force ALL routes to https in my Laravel 4 application but they always result in a redirect loop.
The nginx config is inside a Laravel Homestead environment. Here is the config:
server {
listen 80;
server_name dev.subdomain.mysite.com;
root /home/vagrant/sites/work/dev.subdomain.mysite.com/public;
index index.html index.htm index.php;
charset utf-8;
location / {
try_files $uri $uri/ /index.php?$query_string;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-Url-Scheme $scheme;
proxy_redirect off;
proxy_max_temp_file_size 0;
}
location = /favicon.ico { access_log off; log_not_found off; }
location = /robots.txt { access_log off; log_not_found off; }
access_log off;
error_log /var/log/nginx/dev.subdomain.mysite.com-error.log error;
error_page 404 /index.php;
sendfile off;
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
}
location ~ /\.ht {
deny all;
}
}
server {
listen 443;
server_name dev.subdomain.mysite.com;
root /home/vagrant/sites/work/dev.subdomain.mysite.com/public;
index index.html index.htm index.php;
charset utf-8;
location / {
try_files / /index.php?;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-Url-Scheme $scheme;
proxy_redirect off;
proxy_max_temp_file_size 0;
}
location = /favicon.ico { access_log off; log_not_found off; }
location = /robots.txt { access_log off; log_not_found off; }
access_log off;
error_log /var/log/nginx/dev.subdomain.mysite.com-error.log error;
error_page 404 /index.php;
sendfile off;
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
}
location ~ /\.ht {
deny all;
}
ssl on;
ssl_certificate /etc/nginx/ssl/server.crt;
ssl_certificate_key /etc/nginx/ssl/server.key;
}
I have disabled all routes in my application, my .htaccess is the Laravel provided default. I'm not sure what else to try.
First off, Laravel Homestead uses 44300 as an alias for 443 on the vagrant box.
Your http to https redirect should also be accomplished simply by:
server {
listen 80;
server_name mysite.com;
return 301 https://example.com$request_uri;
}
server {
listen 443;
server_name example.com;
root /home/vagrant/sites/work/example.com/public;
[...] // All other Laravel-related stuff
}
Secondly, you seem to be using a dev-site with Homestead, double check that your host-file and homestead.yaml is set up accordingly and everything is on order there.
Also, when making changes to SSL-certs and nginx-files, your safest bet is always to do a vagrant reload to make sure all edits are reloaded.