How to setup Nginx as smtp proxy to external smtp server? - email

I am trying to setup nginx mail proxy Gmail smtp server. Nginx server runs on docker.
During tests, I use openssl s_client -connect mail.localhost.com:12465 -starttls smtp (ports are different from config for port availability reasons).
Openssl connects successfully and I manage to get EHLO and run AUTH LOGIN. Still, I receive error 502 5.5.1 Unrecognized command. u6sm12628547ejn.14 - gsmtp. Same message appears when less secure apps security is on in account.
Running command above directly to smpt.gmail.com works great, and error is displayed correctly if less secure apps security is not allowed.
Current nginx.conf is below.
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 9101;
server_name localhost;
location /smtpauthssl {
if ($http_auth_user ~* "(?<=#)(\S+$)" ) {
set $domain $1;
}
set $smtp_port '587';
add_header Auth-Status "OK";
add_header Auth-Port $smtp_port;
add_header Auth-Server "108.177.119.108";
return 200;
}
location = / {
return 403;
}
}
}
mail {
server_name mail.mydomain.com;
auth_http localhost:9101/smtpauthssl;
proxy_pass_error_message on;
proxy_smtp_auth on;
xclient on;
ssl_certificate /etc/ssl/certs/certificate.pem;
ssl_certificate_key /etc/ssl/certs/key.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
server {
listen 587 ssl;
protocol smtp;
smtp_auth login plain cram-md5;
}
}
My assumption is that something with logon is not passed to Gmail SMTP, but not sure what.
One more thing, what does Auth-Server header should contain, FQDN or IP address?

Related

Nginx ssl redirection and certbot

I have a test server with docker compose + nginx + certbot (get certificates from let's encript).
Nginx config:
server {
listen [::]:80;
listen 80;
server_name testdomain.com www.testdomain.com;
location ~ /.well-known/acme-challenge {
allow all;
root /var/www/certbot;
}
server_tokens off;
# redirect http to https www
return 301 https://www.testdomain.com$request_uri;
}
#other server configs
certbot says in logs:
Certbot failed to authenticate some domains (authenticator: webroot). The Certificate Authority reported these problems:
Domain: testdomain.com
Type: connection
Detail: Fetching http://testdomain.com/.well-known/acme-challenge/vXDwOBgMA9DEq2IvxqUxxxxxxxxxx: Connection refused
Domain: www.testdomain.com
Type: connection
Detail: Fetching http://www.testdomain.com/.well-known/acme-challenge/shRZla5V7iFXB6D__xxxxx: Connection refused
Hint: The Certificate Authority failed to download the temporary challenge files created by Certbot. Ensure that the listed domains serve their content from the provided --webroot-path/-w and that files created there can be downloaded from the internet.
I've put a temporary file to the /.well-known/acme-challenge/(http) but it can't be downloaded (if I try to open mydomain.com/index.html - works fine, but redirects to https version).
I think that problem is in the fact, my config tryes to redirect certbot requests to https, too. Do you have any idea how to get /.well-known/acme-challenge/ out of https rules?
I've found solution:
server {
listen [::]:80;
listen 80;
server_name testdomain.com www.testdomain.com;
location ^~ /.well-known/acme-challenge {
allow all;
root /var/www/certbot;
}
location / {
# redirect http to https www
return 301 https://www.testdomain.com$request_uri;
}
server_tokens off;
}
Now everithing is redirecting to https excluding content of this folder /.well-known/acme-challenge

Nginx serving from a different location with SSL

I have a webserver running Nginx. I have successfully managed to get SSL working with a Let's Encrypt Certificate, but whenever I connect to HTTPS, the webserver serves me the default index page for Nginx (this). I have been unable to find where this is coming from.
This is the server block I have in the config for the SSL:
##
# SSL Settings
##
ssl_ciphers EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
ssl_prefer_server_ciphers on;
server {
listen 139.59.163.228:443 ssl;
server_name sulphate.me www.sulphate.me;
keepalive_timeout 75 75;
ssl_certificate /etc/ssl/certs/sites/sulphate.me.crt;
ssl_certificate_key /etc/ssl/private/sites/sulphate.me.key;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
}
I want to be able to redirect it to where HTTP is served from (/var/www/html/), and also find out where this is coming from, since I haven't touched any location blocks.
Thanks in advance!

nginx: how much of the https server block is required for a redirect

My site will run exclusively at https://www.example.net
I have a server block for port 80 which returns a 301 to https://www.example.net, which works as expected.
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name www.example.net example.net;
return 301 https://www.example.net$request_uri;
}
In terms of doing the same on port 443, I read somewhere that certificate negotiation happens before all else, and so this 443 redirect block needs to have all of the certificate details. My question is, how much of that stuff needs to be repeated in this block? Currently I have the following:
server {
listen 443 ssl;
listen [::]:443 ssl;
# certs sent to the client in SERVER HELLO are concatenated in ssl_certificate
ssl_certificate /etc/ssl/certs/x.example.net.pem;
ssl_certificate_key /etc/ssl/private/example.net.key;
ssl_session_cache shared:SSL:20m;
ssl_session_timeout 1d;
ssl_session_tickets off;
# Diffie-Hellman parameter for DHE ciphersuites, recommended 2048 bits
ssl_dhparam /etc/ssl/certs/dhparam.pem;
# intermediate configuration. tweak to your needs.
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';
ssl_prefer_server_ciphers on;
# HSTS (ngx_http_headers_module is required) (15768000 seconds = 6 months)
add_header Strict-Transport-Security max-age=15768000;
# OCSP Stapling ---
# fetch OCSP records from URL in ssl_certificate and cache them
ssl_stapling on;
ssl_stapling_verify on;
## verify chain of trust of OCSP response using Root CA and Intermediate certs
ssl_trusted_certificate /etc/ssl/certs/x.example.net.pem;
resolver 8.8.8.8 8.8.4.4;
server_name example.net;
return 301 https://www.example.net$request_uri;
}
Should I be setting Strict-Transport-Security headers? OSCP stapling? ssl_ciphers? Just for a redirect?
Many thanks!
Edited to add: that my certificate is valid on both www and non-www, and so this is not an effort to avoid an ugly certificate mismatch warning.
The following should be in an http block in nginx.conf so it applies to all SSL server configs and avoids this bug:
ssl_session_cache shared:SSL:20m;
ssl_session_timeout 1d;
ssl_session_tickets off;
# Diffie-Hellman parameter for DHE ciphersuites, recommended 2048 bits
ssl_dhparam /etc/ssl/certs/dhparam.pem;
# intermediate configuration. tweak to your needs.
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';
ssl_prefer_server_ciphers on;
The rest should remain.

Nginx dropping SSL handshakes with multiple virtual hosts

I have an Nginx server set up on an Ubuntu VPS with multiple hosts (1 IP). Previously, 1 host had certificates set up and NO redirecting (http allowed) and 1 host had certificates and forced HTTPS via 301. Now that I am attempting to force all of my hosts on SSL and force HTTPS, I am seeing that Nginx is dropping handshakes when I have more than 1 vhost with 301 directives. In particular, the error I am seeing is:
[error] 12370#0: *30 no "ssl_certificate" is defined in server listening on SSL port while SSL handshaking, client: (removed), server: 0.0.0.0:443
The issue definitely seems to be with my 301's, because if I exclude them I do not have an issue. What's the best way I can force HTTPS and non-www in my server blocks?
All of my vhosts are in /etc/nginx/conf.d, along with ssl.conf (listed below). I can provide nginx.conf if requested, but I didn't see anything that would seem useful in there.
example1.conf
server {
server_name www.example1.com example1.com;
return 301 https://example1.com$request_uri;
}
server {
listen 443;
server_name www.example1.com
return 301 https://example1.com$request_uri;
}
server {
listen 443 ssl;
server_name example1.com;
ssl_certificate /etc/letsencrypt/live/example1.com/cert.pem;
ssl_certificate_key /etc/letsencrypt/live/example1.com/privkey.pem;
root /var/www/example1.com;
location / {
try_files $uri $uri/ $uri.html =404;
}
access_log /var/log/nginx/example1.com.access.log;
error_log /var/log/nginx/example1.com.error.log;
}
example2.conf
same as example1.conf (except with example2.com instead of example1.com)
ssl.conf
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
# Perfect Forward Security
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH+aRSA RC4 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS +RC4 RC4";
# HSTS
add_header Strict-Transport-Security max-age=31536000;
Pointing out other obvious errors is also appreciated.
Solved (at least for now) by removing
server {
listen 443;
server_name www.example1.com
return 301 https://example1.com$request_uri;
}
It seems that since there's no cert specified, this block would get hit for all HTTPS requests and then the connection would get dropped.

Nginx Redirect HTTP to HTTPS and non-www to ww

I'm setting up an Nginx server with an SSL.
The domain with the SSL is www.mydomain.example
I want to redirect all requests from:
http://mydomain.example, http://www.mydomain.example, & https://mydomain.example to
https://www.mydomain.example
I have the following server blocks setup currently:
server{
listen 443 ssl;
root /www/mydomain.example/;
ssl_certificate /ssl/domain.crt;
ssl_certificate /ssl/domain.key;
.
.
.
}
server{
listen 80;
server_name mydomain.example;
return 301 https://www.mydomain.example$request_uri;
}
server{
listen 80;
server_name www.mydomain.example;
return 301 https://www.mydomain.example$request_uri;
}
server{
listen ssl 443;
server_name mydomain.example;
return 301 https://www.mydomain.example$request_uri;
}
This currently does not work, but I don't understand why not. I can get a combination of either HTTP -> HTTPS working or no-www to -> www working, but mixing them as above does not work.
The SSL redirect won't work if your SSL certificate doesn't support the non-www domain.
The config is correct but can be reduced to just 1 redirect server
Also don't forget to reload Nginx sudo service nginx reload
server {
listen 80;
listen 443 ssl;
server_name example.com;
# add ssl settings
return 301 https://www.example.com$request_uri;
}
I am late, But you can do like this
server{
listen 443 ssl;
server_name www.mydomain.example;
root /www/mydomain.example/;
ssl on;
ssl_certificate /ssl/domain.crt;
ssl_certificate /ssl/domain.key;
.
.
.
}
server{
listen 80;
server_name www.mydomain.example mydomain.example;
return 301 https://$server_name$request_uri;
}
server{
listen 443;
server_name mydomain.example;
return 301 https://www.$server_name$request_uri;
}
Or you can replace return 301 https://www.$server_name$request_uri; with rewrite ^ http://www.$server_name$request_uri? permanent;, both will work.
You also need to set this in google webmaster for better SEO.
this works for me for HTTP to HTTPS redirection,
server {
listen 80 default_server;
listen [::]:80 default_server;
root /var/www/html;
index index.php index.html index.htm index.nginx-debian.html;
server_name example.com;
#For HTTP to HTTPS:
proxy_set_header X-Forwarded-Proto $scheme;
if ( $http_x_forwarded_proto != 'https' )
{
return 301 https://$host$request_uri;
}
location / {
try_files $uri $uri/ /index.php;
add_header 'Access-Control-Allow-Origin' '*';
}
location ~ \.php$ {
include fastcgi.conf;
fastcgi_pass unix:/var/run/php/php7.3-fpm.sock;
}
location ~ /\.ht {
deny all;
}
}
Use a rewrite to send all HTTP traffic to HTTPS:
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
return 301 https://$host$request_uri;
}
This configuration listens on port 80 as the default server for both IPv4 and IPv6 and
for any hostname. The return statement returns a 301 permanent redirect to the
HTTPS server at the same host and request URI.
#If you like to redirect all "http" to "https" then add the following:
server {
listen 80;
server_name yourdomain.example;
server_name www.yourdomain.example;
if ($scheme = "http")
{
rewrite ^(.*)$ https://yourdomain.example$1 permanent;
}
}
Please add two given things on your file.
Code to paste on top:
server {
listen 80;
server_name example.com www.example.com;
return 301 https://example.com$request_uri;
}
Code to paste on bottom:
server {
listen 443 ssl http2;
server_name www.example.com;
# . . . other code
return 301 https://example.com$request_uri;
}
Source
I was trying to fix the problem by redirecting the request URI to HTTPS if it was requested with the HTTP scheme. But this solution does not work in some conditions.
if ($scheme = http) {
return 301 https://$server_name$request_uri;
}
When we type a domain name in the search bar of a browser, it makes a request with the HTTP scheme by default. This behavior of the browser is not handled by nginx, but it can be done manually. We have to handle 497 status code by adding error_page 497 https://$server_name$request_uri;.
error_page 497 https://$server_name$request_uri;
if ($scheme = http) {
return 301 https://$server_name$request_uri;
}
What does the 497 indicate, and when occur?
The 497 HTTP Request Sent to HTTPS Port is used when a client has made an HTTP request to a port that is listening for HTTPS requests specifically.
I couldn't figure out why HTTP http://example.com wouldn't redirect to HTTPS https://example.com. i had configured it the following way like others have and according to https://nginx.org/en/docs/http/configuring_https_servers.html, even after restarting the server with nginx -s reload && sudo systemctl restart nginx
/etc/nginx/sites-available/example.com
server {
listen 80;
server_name www.example.com example.com;
return 301 https://$server_name$request_uri;
}
server {
ssl_certificate /etc/letsencrypt/live/www.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/www.example.com/privkey.pem;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 1m;
listen 443 ssl http2 default_server;
listen [::]:443 ssl http2 default_server;
server_name www.example.com example.com;
root /var/www/build;
index index.html;
location / {
try_files $uri /index.html =404;
}
}
But even though i'm using the latest browsers, the redirection from HTTP to HTTPS only works with the latest in incognito window:
Firefox: 110.0 (64-bit) (both on Desktop and Mobile)
But not with the latest in incognito window even after clear cache and hard reload:
Brave: Version 1.48.164 Chromium: 110.0.5481.100 (Official Build) (x86_64)
Chrome: Version 110.0.5481.100 (Official Build) (x86_64)
With Brave and Chrome it just loads the default HTTP page "Welcome to nginx!" from /var/www/html/
index.nginx-debian.html