SNI not working? multiple ssl reverse proxies nginx - nginx

I want to configure two reverse proxies with ssl that proxy pass to different applications
https://api.example.com --> http://app:8080
https://pg.example.com --> http://pgadmin:80
Given the following nginx configuration, both sub-domains redirect to the first 443-server config (app). The problem occurs when hitting the 443 port. The redirect from 80 to 433 works fine for both. But when I browse https://pg.example.com it passes to app instead of pgadmin.
server {
listen 80;
listen [::]:80;
server_name api.example.com pg.example.com;
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
location / {
rewrite ^ https://$host$request_uri? permanent;
}
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name api.example.com;
server_tokens off;
ssl_certificate /etc/letsencrypt/live/api.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/api.example.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
location / {
proxy_pass http://app:8080;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
add_header Content-Security-Policy "default-src * data: 'unsafe-eval' 'unsafe-inline'" always;
# add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
# enable strict transport security only if you understand the implications
}
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name pg.example.com;
server_tokens off;
# note that api.example.com certificate has pg.example.com as alias
ssl_certificate /etc/letsencrypt/live/api.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/api.example.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
location / {
proxy_set_header X-Scheme $scheme;
proxy_set_header Host $host;
proxy_pass http://pgadmin:80;
proxy_redirect off;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
add_header Content-Security-Policy "default-src * data: 'unsafe-eval' 'unsafe-inline'" always;
# add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
# enable strict transport security only if you understand the implications
}
}
Feels like the SNI is not working or so..?! But it is enabled in nginx:
nginx -V
nginx version: nginx/1.17.10
built by gcc 9.2.0 (Alpine 9.2.0)
built with OpenSSL 1.1.1d 10 Sep 2019 (running with OpenSSL 1.1.1g 21 Apr 2020)
TLS SNI support enabled
What am I missing to make both reverse proxies work?
Edit:
When I remove the server block for server_name api.example.com; (on 443) then the other (pg.example.com:443) does work as expected. The api.example.com:443 then shows the same pgadmin upstream).

I think the easiest way is to split up the first server block into two server-blocks.
For example:
server {
listen 80;
listen [::]:80;
server_name api.example.com;
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
location / {
rewrite ^ https://$host$request_uri? permanent;
}
}
and
server {
listen 80;
listen [::]:80;
server_name pg.example.com;
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
location / {
rewrite ^ https://$host$request_uri? permanent;
}
}
I hope this helps, but I can't guarantee, that this config is working properly with certbot.

Turns out the reason is a misspelled domain for the sever_name of the
pg.example.com:433. Hence, not sever_name would match and nginx would then use the best match - which is the api.example.com:433.
I found out by adding a default (by making them the first in the conf file and both using sever_name _) server config for both 80 and 443 so I could ensure that the specific server configs are only used if the server_name matches. The result was that api.example.com:433 showed the same behavior as before (indicating that it works) while the pg.example.com:433 would show the newly configured default server - so it must be something that prevents the proper match on the server_name in the config. I triple checked the sever_name and finally saw the typo.

Related

nginx add_header not applied to some server contexts

I have several add_header directives in my main http context of the nginx.conf file, such as:
add_header X-Frame-Options "SAMEORIGIN";
add_header X-XSS-Protection "1; mode=block";
There no other such directives in server and location contexts. For some reason, the header is not applied to server contexts. For example, this one:
server {
server_name my.example.com;
location / {
proxy_pass http://192.168.1.1:12345;
}
location /robots.txt {
return 200 "User-agent: *\nDisallow: /\n";
}
client_max_body_size 300M;
listen 443 ssl; # managed by Certbot
ssl_certificate fullchain.pem; # managed by Certbot
ssl_certificate_key privkey.pem; # managed by Certbot
include options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam ssl-dhparams.pem; # managed by Certbot
}
What could be causing this?
EDIT: nginx version is 1.23.3.
The file options-ssl-nginx.conf in /etc/letsencrypt/ has:
ssl_session_cache shared:le_nginx_SSL:10m;
ssl_session_timeout 1440m;
ssl_session_tickets off;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;
# + one line of ssl_ciphers
As explained in comment, adding the always parameter to the add_header directive allows the header to be added for all kind of HTTP responses (errors included), see the doc for more details: http://nginx.org/en/docs/http/ngx_http_headers_module.html#add_header

Nginx non-www not redirecting

I am a total noob when it comes to servers but I am learning. I got this Nginx server block that is working as we would like it to do. The only thing that goes wrong is that when someone goes to the url mysite.nl instead of https://mysite.nl or https://www.mysite.nl, they will get an error page saying the page is insecure.
I tried looking on Google and Stackoverflow for examples but I cannot get them to work either.
Can anyone tell me how I can fix this? my server block is displayed below. The top part should redirect any non-www to www but I think it is not working. So what I want is when someone goes to mysite.nl they will end up at https://www.mysite.nl.
Hope someone can help me out.
server {
server_name mysite.nl;
listen 443 ssl; # managed by Certbot
return 301 $scheme://www.mysite.nl$request_uri;
ssl_certificate /etc/letsencrypt/live/mysite.nl-0001/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/mysite.nl-0001/privkey.pem; # managed by Certbot
}
server {
root /var/www/mysite.nl/;
index index.html index.htm index.php;
server_name *.mysite.nl;
location / {
proxy_pass http://localhost:3009/;
}
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header Referrer-Policy "origin";
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/mysite.nl-0001/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/mysite.nl-0001/privkey.pem; # managed by Certbot
}
server {
root /var/www/mysite.nl/;
index index.html index.htm index.php;
server_name mysite.nl;
location / {
proxy_pass http://localhost:3009/;
}
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header Referrer-Policy "origin";
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/mysite.nl-0001/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/mysite.nl-0001/privkey.pem; # managed by Certbot
}
server {
if ($host = www.mysite.nl) {
return 301 https://$host$request_uri;
} # managed by Certbot
if ($host = mysite.nl) {
return 301 https://$host$request_uri;
} # managed by Certbot
server_name mysite.nl www.mysite.nl;
listen 80;
return 301 https://$host$request_uri; # managed by Certbot
} ```
There are a few issues with your config. Namely that you have 2 server blocks using the same sever_name so that's going to cause odd behavior. Recommend using a single server block. Also, the return blocks at the bottom are kind of broken and may be adding to the confusion.
You could just have the cert issued with all the names you're going to access the server with.
One option is to use docker + nginx-proxy + acme-companion to handle all the heavy lifting. https://github.com/nginx-proxy/nginx-proxy and https://github.com/nginx-proxy/acme-companion

Serve a JSON response from an Endpoint using a Subdomain with Nginx

I currently have a deployed application. https://dostoevsky.rest/
It works well with Nginx and Docker.
However, I want to get a JSON response when I hit the endpoint https://dostoevsky.rest/api/rand with a subdomain.
So, I want the subdomain api.dostoevsky.rest to give the response https://dostoevsky.rest/api/rand would give.
I thought I could configure Nginx with proxy_pass, so I did the following:
server {
server_name api.dostoevsky.rest www.api.dostoevsky.rest;
location / {
default_type application/json;
proxy_pass http://<IP>:80/api/rand/;
}
}
However, when I do curl api.dostoevsky.rest I get this timeout message:
<html>
<head><title>504 Gateway Time-out</title></head>
<body>
<center><h1>504 Gateway Time-out</h1></center>
<hr><center>nginx/1.21.3</center>
</body>
</html>
Nginx Logs:
*1 upstream timed out (110: Operation timed out) while connecting to upstream, client:
I'm assuming the resource isn't found?
If I do curl https://dostoevsky.rest/api/rand it works fine. So, I think I'm making a mistake with the proxy or how the server is configured. Any help would be appreciated. Sorry if this is a low-quality question; I'm new to using Nginx.
Deployed on a DigitalOcean droplet.
I've also configured the DNS for the IP to point to api.dostoevsky.rest, by the way.
Following is my complete nginx.conf file:
server {
listen 80;
listen [::]:80;
server_name dostoevsky.rest www.dostoevsky.rest;
location ~ /.well-known/acme-challenge {
allow all;
root /var/www/html;
}
location / {
rewrite ^ https://$host$request_uri? permanent;
}
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name dostoevsky.rest www.dostoevsky.rest;
server_tokens off;
ssl_certificate /etc/letsencrypt/live/dostoevsky.rest/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/dostoevsky.rest/privkey.pem;
ssl_buffer_size 8k;
ssl_dhparam /etc/ssl/certs/dhparam-2048.pem;
ssl_protocols TLSv1.2 TLSv1.1 TLSv1;
ssl_prefer_server_ciphers on;
ssl_ciphers ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DH+3DES:!ADH:!AECDH:!MD5;
ssl_ecdh_curve secp384r1;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8;
location / {
try_files $uri #nodejs;
}
location #nodejs {
proxy_pass http://nodejs:8080;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
add_header Content-Security-Policy "default-src * data: 'unsafe-eval' 'unsafe-inline'" always;
# add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
# enable strict transport security only if you understand the implications
}
root /var/www/html;
index index.html index.htm index.nginx-debian.html;
}
server {
server_name api.dostoevsky.rest www.api.dostoevsky.rest;
location / {
default_type application/json;
proxy_pass http://<IP>:80/api/rand/;
}
}

how to remove www from redirect url in nginx conf

Below is my nginx conf, how to remove www. from redirect url.
right now when i am entering url www.platform.iamwoken.com/ its redirecting to https://www.platform.iamwoken.com/ which is wrong
i need to redirect it to https://platform.iamwoken.com/
server_tokens off;
server {
if ($host ~ (platform.iamwoken.com|www.platform.iamwoken.com)) {
return 301 https://platform.iamwoken.com;
} # managed by Certbot
listen 80 default_server;
listen [::]:80 default_server;
server_name platform.iamwoken.com www.platform.iamwoken.com;
return 301 https://platform.iamwoken.com;
}
server {
listen 443 ssl http2 default_server;
listen [::]:443 ssl http2 default_server;
server_name platform.iamwoken.com www.platform.iamwoken.com;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
# Disable SSL
ssl_protocols TLSv1 TLSv1.1;
# Optimise cipher suites
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
# Enable HSTS
add_header Strict-Transaport-Security "max-age=31536000" always;
add_header X-Frame-Options "SAMEORIGIN";
add_header X-XSS-Protection "1; mode=block";
# SSL sessions
#ssl_session_cache shared:devplatform.iamwoken.com:40m;
# ssl_session_tickets on;
# Skip buffering for static files
sendfile on;
location /static/ {
access_log off;
add_header Cache-Control public;
add_header Pragma public;
add_header Vary Accept-Encoding;
expires 1m;
root /home/ubuntu/wokencrm;
}
location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
# try_files $uri $uri/ =404;
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# we don't want nginx trying to do something clever with
# redirects, we set the Host: header above already.
proxy_redirect off;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
how to resolve this issue
use below NGiNX block to redirect www to non-www
server {
server_name www.platform.iamwoken.com;
return 301 $scheme://platform.iamwoken.com$request_uri;
}
Restart the nginx web-server and test the URL in browser. It will work as expected.

Use subdomain instead of another subdomain

I know this asks too much but I really don't get it.
I am using a subdomain for my server like sub.domain.com. I can reach it with ssh with typing ssh root#sub.domain.com.
I am trying use nextcloud on this server like cloud.domain.com. I can reach nextcloud when I type sub.domain.com/nextcloud. My conf file is:
upstream php-handler {
server 127.0.0.1:9000;
#server unix:/var/run/php5-fpm.sock;
}
server {
listen 80;
server_name sub.domain.com;
# enforce https
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl;
server_name sub.domain.com;
ssl_certificate /etc/nginx/ssl/server.crt;
ssl_certificate_key /etc/nginx/ssl/server.key;
# Add headers to serve security related headers
# Before enabling Strict-Transport-Security headers please read into this
# topic first.
add_header Strict-Transport-Security "max-age=15768000;
includeSubDomains; preload;";
add_header X-Content-Type-Options nosniff;
add_header X-Frame-Options "SAMEORIGIN";
add_header X-XSS-Protection "1; mode=block";
add_header X-Robots-Tag none;
add_header X-Download-Options noopen;
add_header X-Permitted-Cross-Domain-Policies none;
# Path to the root of your installation
root /usr/share/nextcloud/;
location = /robots.txt {
allow all;
log_not_found off;
access_log off;
}
I am trying to change sub.domain.com to cloud.domain.com but it doesn't working.
Where is my mistake? Can you guys help me?
Thanks.

Resources