trying to set up Nginx reverse proxy in front of AWS Elastic Load Balancer with TSL enabled on it.
The configuration I've tried:
events {}
http {
upstream pricing {
server pricing-api.my-awselb.com:443;
}
server {
listen 80;
server_name localhost;
location /pricing {
proxy_pass https://pricing;
}
}
}
Now when I run Nginx in docker locally on port 8080 when I try test it I get 404
> http http://localhost:8080/pricing
HTTP/1.1 404 Not Found
Connection: keep-alive
Content-Length: 0
Date: Wed, 21 Oct 2020 21:47:56 GMT
Server: nginx/1.19.3
upstream itself is accessible from my local machine:
> http https://pricing-api.my-awselb.com
HTTP/1.1 302 Found
Connection: keep-alive
Content-Length: 0
Date: Wed, 21 Oct 2020 21:54:36 GMT
Location: /swagger
Server: Kestrel
Whats wrong with my Nginx configuration?
Related
I tried to follow the blog post How to setup secure subdomains using nginx and certbot on a VPS, but get the error "ERR_TOO_MANY_REDIRECTS" when I try to connect to my website on my Browser.
I also tried deleting the Cache and all other data.
The only solutions I found are about Cloudflare or other big providers, but I am using a VPS from IONOS.
My config file looks like this:
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name fleeser.com www.fleeser.com;
return 301 https://fleeser.com$request_uri;
}
server {
listen 443 ssl;
root /var/www/fleeser.com;
index index.html index.htm;
server_name www.fleeser.com;
ssl_certificate /etc/letsencrypt/live/fleeser.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/fleeser.com/privkey.pem;
return 301 https://fleeser.com$request_uri;
}
server {
listen 443 ssl;
root /var/www/fleeser.com;
index index.html index.htm;
ssl_certificate /etc/letsencrypt/live/fleeser.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/fleeser.com/privkey.pem;
}
My subdomain config for blog.fleeser.com looks the exact same, only change I made was removing default_server from the file and adding blog. infront of every fleeser.com.
Output of wget -S https://fleeser.com:
--2022-02-27 16:06:10-- https://fleeser.com/
Resolving fleeser.com (fleeser.com)... 82.165.108.165
Connecting to fleeser.com (fleeser.com)|82.165.108.165|:443... connected.
HTTP request sent, awaiting response...
HTTP/1.1 301 Moved Permanently
Server: nginx/1.18.0 (Ubuntu)
Date: Sun, 27 Feb 2022 16:06:10 GMT
Content-Type: text/html
Content-Length: 178
Connection: keep-alive
Location: https://fleeser.com/
Location: https://fleeser.com/ [following]
--2022-02-27 16:06:10-- https://fleeser.com/
Reusing existing connection to fleeser.com:443.
HTTP request sent, awaiting response...
HTTP/1.1 301 Moved Permanently
Server: nginx/1.18.0 (Ubuntu)
Date: Sun, 27 Feb 2022 16:06:10 GMT
Content-Type: text/html
Content-Length: 178
Connection: keep-alive
Location: https://fleeser.com/
Location: https://fleeser.com/ [following]
--2022-02-27 16:06:10-- https://fleeser.com/
Reusing existing connection to fleeser.com:443.
...
20 redirections exceeded.
I'm running into an issue that I can't solve myself...
I'm running a Debian 10 server with nginx freshly installed on it.
IPV4: 149.56.45.129, DNS: yocha.app
Result of hostnamectl:
Static hostname: yocha.app
Icon name: computer-vm
Chassis: vm
Machine ID: d72735cff36a41f0a5326f0bb7eb1778
Boot ID: 72dd9022a4894eeea82bc74480543823
Virtualization: kvm
Operating System: Debian GNU/Linux 10 (buster)
Kernel: Linux 4.19.0-13-cloud-amd64
Architecture: x86-64
My /etc/hosts:
127.0.0.1 localhost
149.56.45.129 yocha.app
# The following lines are desirable for IPv6 capable hosts
::1 localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
My nginx sites-avaible/default:
server {
listen 80 default_server;
listen [::]:80 default_server;
root /var/www/html;
# Add index.php to the list if you are using PHP
index index.html index.htm index.nginx-debian.html;
server_name yocha.app;
location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
try_files $uri $uri/ =404;
}
}
When I access my ip address in the browser, I do get the nginx welcome message which is good I guess.
BUT when I try to access the dns the request timed out with no return...
I can log with ssh on my dns, I can ping it with no problems I even can curl it but when It comes to access it on a Browser, nothing happens.
curl -I http://149.56.45.129:80
HTTP/1.1 200 OK
Server: nginx/1.14.2
Date: Thu, 21 Jan 2021 13:40:16 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Thu, 21 Jan 2021 13:05:20 GMT
Connection: keep-alive
ETag: "60097c10-264"
Accept-Ranges: bytes
me#yocha:~$ curl -I http://yocha.app:80
HTTP/1.1 200 OK
Server: nginx/1.14.2
Date: Thu, 21 Jan 2021 13:40:25 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Thu, 21 Jan 2021 13:05:20 GMT
Connection: keep-alive
ETag: "60097c10-264"
Accept-Ranges: bytes
http://yocha.app on a browser
Anyone having a clue for me ?
Thanks a lot in advance !
Your site is redirecting to https:
$ curl -v http://yocha.app
< HTTP/1.1 301 Moved Permanently
< Server: nginx/1.14.2
< Date: Fri, 29 Jan 2021 20:21:46 GMT
< Content-Type: text/html
< Content-Length: 185
< Connection: keep-alive
< Location: https://yocha.app/
and port 443 is not open or it's blocked:
$ telnet yocha.app 443
Trying 149.56.45.129...
telnet: Unable to connect to remote host: Connection timed out
DNS is fine: check your firewall or make sure nginx is propertly configured to listen on port 443 and to serve an ssl certificate.
I am trying to build a reverse proxy with nginx to make all Is in my project reachable from single address.
For a single service the configuration below works without problem
/etc/nginx/sites-enabled/reverse-proxy.conf
server {
listen 80;
listen [::]:80;
location / {
resolver 127.0.0.1;
allow "x.x.x.x";
deny all;
proxy_pass http://consul:8500;
}
}
So when I call server's ip x.x.x.x in my browser I see the Consul UI and the URL showing x.x.x.x/ui/dc1. Besides that, I see that the UI did requests for asset files successfully.
My question; is it possible two host different services on the same server and just reference to them with different location? For example, if I want to include Vault UI then I would think of doing something like this:
server {
listen 80;
listen [::]:80;
location /consul {
resolver 127.0.0.1;
allow "x.x.x.x";
deny all;
proxy_pass http://consul:8500;
}
location /vault {
resolver 127.0.0.1;
allow "x.x.x.x";
deny all;
proxy_pass http://vault:8200;
}
}
However I am not sure if this could be done this way. The farest I got, is to open the Consul UI with all other sub requests not found (i.e. loading assets).
UPDATE
I think my problem is that I am wrongly using location and proxy_pass
observing the first configuration (which is working)
server {
listen 80;
listen [::]:80;
location / {
resolver 127.0.0.1;
allow "x.x.x.x";
deny all;
proxy_pass http://consul:8500;
}
}
If I look at the curl command curl localhost -L -vvvv
* Trying 127.0.0.1:80...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 80 (#0)
> GET / HTTP/1.1
> Host: localhost
> User-Agent: curl/7.68.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 301 Moved Permanently
< Server: nginx/1.18.0 (Ubuntu)
< Date: Fri, 10 Jul 2020 16:24:38 GMT
< Content-Type: text/html; charset=utf-8
< Content-Length: 39
< Connection: keep-alive
< Location: /ui/
<
* Ignoring the response-body
* Connection #0 to host localhost left intact
* Issue another request to this URL: 'http://localhost/ui/'
* Found bundle for host localhost: 0x557b754549e0 [serially]
* Can not multiplex, even if we wanted to!
* Re-using existing connection! (#0) with host localhost
* Connected to localhost (127.0.0.1) port 80 (#0)
> GET /ui/ HTTP/1.1
> Host: localhost
> User-Agent: curl/7.68.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Server: nginx/1.18.0 (Ubuntu)
< Date: Fri, 10 Jul 2020 16:24:38 GMT
< Content-Type: text/html; charset=utf-8
< Content-Length: 7806
< Connection: keep-alive
< Accept-Ranges: bytes
< Last-Modified: Fri, 10 Jul 2020 07:37:44 GMT
<
<!DOCTYPE html>
<html lang="en" class="ember-loading">
...
and I can see the html already. However, if I changed the conf file to this:
server {
listen 80;
listen [::]:80;
location /consul/ {
resolver 127.0.0.1;
allow "x.x.x.x";
deny all;
proxy_pass http://consul:8500;
}
}
and then try to call it like curl localhost/consul -L -vvvv, I get the following:
* Trying 127.0.0.1:80...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 80 (#0)
> GET /consul HTTP/1.1
> Host: localhost
> User-Agent: curl/7.68.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 301 Moved Permanently
< Server: nginx/1.18.0 (Ubuntu)
< Date: Fri, 10 Jul 2020 16:32:35 GMT
< Content-Type: text/html
< Content-Length: 178
< Location: http://localhost/consul/
< Connection: keep-alive
<
* Ignoring the response-body
* Connection #0 to host localhost left intact
* Issue another request to this URL: 'http://localhost/consul/'
* Found bundle for host localhost: 0x55ba7959f9e0 [serially]
* Can not multiplex, even if we wanted to!
* Re-using existing connection! (#0) with host localhost
* Connected to localhost (127.0.0.1) port 80 (#0)
> GET /consul/ HTTP/1.1
> Host: localhost
> User-Agent: curl/7.68.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 404 Not Found
< Server: nginx/1.18.0 (Ubuntu)
< Date: Fri, 10 Jul 2020 16:32:35 GMT
< Content-Length: 0
< Connection: keep-alive
I would appreciate any ideas on this issue
You are right, you are using location and proxy_pass a wrong way. When you use the
location /vault {
proxy_pass http://vault:8200;
}
construction, you are passing your URI to the upstream as-is, while most likely you want to strip the /vault prefix from it. To do it, you should use this one:
location /vault/ {
proxy_pass http://vault:8200/;
}
You can read more about the difference of the first and the second one here. However this still can prevent the assets from loading correctly.
This question - how to proxy some webapp under some URI prefix - is being asked again and again on stackoverflow. The only right way to do it is to made your proxied app request its assets via relative URLs only (consider assets/script.js instead of /assets/script.js) or using the right prefix (/vault/assets/script.js). Some well-written apps are able to detect if they are used under such an URI prefix and use it when an asset link is being generated, some apps allows to specify it via some settings, but some are not suited for the such use at all. The reason why the webapp won't work without fulfilling these requirements is quite obvious - any URL not started with /vault won't match your location /vault/ { ... } block and would be served via main location block instead. So the best way to do it is to fix your webapp, however several workarounds can be used if you really cannot.
Some web frameworks already builds their webapps with relative URLs, but uses a <base href="/"> in the head section of index.html. For example, React or Angular use this approach. If you have such a line within your webapp root index.html, just change it to <base href="/vault/">.
Using conditional routing based on HTTP Referer header value. This approach works quite well for a single page applications for loading assets, but if a webapp contains several pages this approach won't work, it's logic for the right upstream detection would break after the first jump from one page to another. Here is an example:
map $http_referer $prefix {
~https?://[^/]+/vault/ vault;
# other webapps prefixes could be defined here
# ...
default base;
}
server {
# listen port, server name and other global definitions here
# ...
location / {
try_files "" #$prefix;
}
location /vault/ {
# proxy request to the vault upstream, remove "/vault" part from the URI
proxy_pass http://vault:8200/;
}
location #vault {
# proxy request to the vault upstream, do not change the URI
proxy_pass http://vault:8200;
}
location #base {
# default "root" location
proxy_pass http://consul:8500;
}
}
Update # 2022.02.19
Here is one more possible approach using conditional rewrite:
server {
# listen port, server name and other global definitions here
# ...
if ($http_referer ~ https?://[^/]+/vault/)
# rewrite request URI only if it isn't already started with '/vault' prefix
rewrite ^((?!/vault).*) /vault$1;
}
# locations here
# ...
}
Rewriting the links inside the response body using sub_filter directive from ngx_http_sub_module. This is the ugliest one, but still can be used as the last available option. This approach has an obvious perfomance impact. Rewrite patterns should be determined from your upstream response body. Usually that type of configuration looked like
location /vault/ {
proxy_pass http://vault:8200/;
sub_filter_types text/css application/javascript;
sub_filter_once off;
sub_filter 'href="/' 'href="/vault/';
sub_filter "href='/" "href='/vault/";
sub_filter 'src="/' 'src="/vault/';
sub_filter "src='/" "src='/vault/";
sub_filter 'url("/' 'url("/vault/';
sub_filter "url('/" "url('/vault/";
sub_filter "url(/" "url(/vault/";
}
Update # 2022.02.19
Related thread at the ServerFault: How to handle relative urls correctly with a nginx reverse proxy.
Possible caveats using sub_filter on the JavaScript code: Nginx as reverse proxy to two nodejs app on the same domain.
I use Kong as my API Gateway, running in a Docker container. By executing the following command from docker host, i get the correct answer.
root#prod-s-swarm01:~# curl -i -X GET --url http://prod-s-swarm:8000 --header 'Host: example.com' --header 'apikey: auth-key-maks'
HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
Transfer-Encoding: chunked
Connection: keep-alive
Date: Thu, 24 Oct 2019 11:16:10 GMT
Server: Apache/2.4.7 (Ubuntu)
Vary: Accept-Encoding
X-RateLimit-Remaining-hour: 4
X-RateLimit-Limit-second: 2
X-RateLimit-Remaining-second: 1
X-RateLimit-Limit-hour: 5
X-Kong-Upstream-Latency: 25
X-Kong-Proxy-Latency: 139
Via: kong/1.3.0
<!DOCTYPE html>
<html lang="ru">
<head>
.......
But, this request over my nginx proxy return not correct answer:
root#prod-s-swarm01:~# curl -i -X GET --url https://kong.myserver.com --header 'Host: example.com' --header 'apikey: auth-key-maks'
HTTP/1.1 200 OK
Server: nginx
Date: Thu, 24 Oct 2019 11:14:33 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 97
Connection: keep-alive
X-Powered-By: Express
ETag: W/"61-Mn0BCF+92vC7dF087oyDAFsiE"
{"Status":"ERROR","Error":"Bad authorize","ErrorDesc":"Не верная авторизация"}
My nginx proxy config:
server {
listen 443 ssl;
server_name kong.myserver.com;
ssl_certificate /etc/letsencrypt/live/appgw/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/appgw/privkey.pem;
location / {
proxy_pass http://prod-s-swarm:8000;
proxy_set_header Host $host;
}
}
I tried to use, $http_host - this also not work.
Another Host's fall into in default_server on nginx. Or in server_name is necessary write all domains in kong api.
Hi I am new to Nginx and looking some help to redirect my http request to https.
I have two configuration on load balance with port 80 and 444 at Linode cloud system.
If request comes from https then load balancer if sending request to my serving tomcat after terminating SSL to LB.
If request comes from http then load balancer is sending to my nginx server which is redirecting request to https.
I see whenever, I start my nginx server, I see continues logs in my tomcat server of redirect url even no one is hitting my http url. I have following complete nginx.conf file.
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
events {
worker_connections 1024;
}
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
# Load modular configuration files from the /etc/nginx/conf.d directory.
# See http://nginx.org/en/docs/ngx_core_module.html#include
# for more information.
include /etc/nginx/conf.d/*.conf;
server {
listen 80 ;
server_name example.com;
#return 301 https://$server_name$request_uri;
rewrite ^ https://$server_name/$request_uri permanent;
root /usr/share/nginx/html;
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
location =/ {
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
Same configuration works perfectly, if I put IP address in place of actual domain name.
Following are the curl results based on location and I see in after redirecting from HTTPS location header is showing https://example.com/login which is doing correctly
# curl -i http://example.com
HTTP/1.1 301 Moved Permanently
Server: nginx/1.6.3
Date: Fri, 29 Jan 2016 07:43:54 GMT
Content-Type: text/html
Content-Length: 184
Connection: close
Location: https://example.com/
<html>
<head><title>301 Moved Permanently</title></head>
<body bgcolor="white">
<center><h1>301 Moved Permanently</h1></center>
<hr><center>nginx/1.6.3</center>
</body>
</html>
# curl -i https://example.com
HTTP/1.1 302 Found
Server: Apache-Coyote/1.1
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
Strict-Transport-Security: max-age=31536000 ; includeSubDomains
X-XSS-Protection: 1; mode=block
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
Set-Cookie: JSESSIONID=C3B65BD4E015F05705B585F5F8D70074; Path=/; Secure; HttpOnly
Location: https://example.com/login
Content-Length: 0
Date: Fri, 29 Jan 2016 07:44:03 GMT
Connection: close
#curl -i https://example.com/login
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
Strict-Transport-Security: max-age=31536000 ; includeSubDomains
X-XSS-Protection: 1; mode=block
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
Set-Cookie: JSESSIONID=6B30D6D70672A99F13B2F441B2F2150E; Path=/; Secure; HttpOnly
Content-Type: text/html;charset=ISO-8859-1
Content-Language: en-US
Transfer-Encoding: chunked
Date: Fri, 29 Jan 2016 07:44:18 GMT
Connection: close
<HTML context of login page>
Please suggest me what I am missing here.
To simply redirect all requests to port 80 to https, use the following configuration. No further lines are required, and might skip the purpose of the server:
server {
listen 80 default_server;
server_name _;
rewrite ^ https://$host$request_uri permanent;
}
This way, whichever host or even IP address will be forwarded to the https counterpart. If you are sure there'll be only one destination host, you may use it instead of the $host variable (do not enter a / afterwards):
rewrite ^ https://example.com$request_uri permanent;
It'd be even better if you use return:
return 301 https://example.com$request_uri;
# or
# return 301 https://$host$request_uri;
Since this is the only purpose of this server block, remove all other directives, like root, location, error_page and include.
Beware of additional files at /etc/nginx/conf.d/*.conf or /etc/nginx/sites-enabled/*.conf, they may overwrite these settings.
Reload nginx configuration and test. I suggest using cURL — here's the expected result:
$ curl -i http://example.com
HTTP/1.1 301 Moved Permanently
Server: nginx/1.8.0
Date: Wed, 27 Jan 2016 17:33:45 GMT
Content-Type: text/html
Content-Length: 184
Connection: keep-alive
Location: https://example.com/
<html>
<head><title>301 Moved Permanently</title></head>
<body bgcolor="white">
<center><h1>301 Moved Permanently</h1></center>
<hr><center>nginx/1.8.0</center>
</body>
</html>
Look and copy the Location: header content, then test again using cURL (use -k if you use a self-signed certificate):
curl -i https://example.com
The result should be from your tomcat application, and NOT another redirect to the same page. If the result is the same (safe from the date), then your LB is probably sending the https requests back to nginx, causing a loop.
Please note that the tomcat application may also be forwarding to https if it doesn't understand it's behind a proxy (the LB). In this case, you'll need to setup the application config to properly understand this (let me know if this is the case).
I see that my Nginx server is exposed on public IP using port:80 and it was receiving traffic from unwanted hosts.
Since I had a default configuration in Nginx server block which was redirecting my all incoming http:80 traffic from any host to my tomcat on https:443, thats why I saw tons of logs in my tomcat server.
I had to add below configuration to my /etc/nginx.conf to redirect port:80 traffic to https if request is coming from my domain only.
if ($host ~ ^(example.com|www.example.com)$) {
return 301 https://$server_name$request_uri;
}