Nginx config for WSS - ssl

I am having a problem in connecting through WSS to my server. I followed the following article to setup nginx with websockets: http://www.letseehere.com/reverse-proxy-web-sockets
The following is my nginx config which serves a Play! application:
#user nobody;
worker_processes 1;
error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
events {
worker_connections 1024;
}
tcp {
upstream websockets {
## Play! WS location
server 127.0.0.1:9000;
}
server {
listen 80;
listen 8000;
server_name socket.domain.com;
tcp_nodelay on;
proxy_pass websockets;
proxy_send_timeout 300;
}
# virtual hosting
#include /usr/local/nginx/vhosts/*;
}
http {
server {
listen 443 ssl;
server_name socket.artoo.in;
ssl_certificate /usr/local/nginx/key/socket.domain.com.crt;
ssl_certificate_key /usr/local/nginx/key/socket.domain.com.key;
ssl_session_timeout 5m;
ssl_protocols SSLv2 SSLv3 TLSv1;
ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;
ssl_prefer_server_ciphers on;
location / {
proxy_pass http://127.0.0.1:9000;
}
}
}
While the server is accessible on http://socket.domain.com, https://socket.domain.com, ws://socket.domain.com but not wss://socket.domain.com

I was able to put together a guide in Q&A format that shows you how to do all of this with NGINX modules, much easier ;)
NGINX to reverse proxy websockets AND enable SSL (wss://)?
You will need to rebuild NGINX and follow the config in the question above.

I have at least solved it for the short term by using stunnel (referring to this article: http://www.darkcoding.net/software/proxy-socket-io-and-nginx-on-the-same-port-over-ssl/).
Stunnel can convert HTTPS to HTTP and by that token WSS to WS. Nginx served the socket application running on 9000 port as usual:
/etc/stunnel/stunnel.conf
[https]
accept = 443
connect = 80
TIMEOUTclose = 0
/usr/local/nginx/conf/nginx.conf
#user nobody;
worker_processes 1;
error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
events {
worker_connections 1024;
}
tcp {
upstream websockets {
## Play! WS location
server 127.0.0.1:9000;
check interval=3000 rise=2 fall=5 timeout=1000;
}
server {
listen 80;
listen 8000;
server_name socket.artoo.in;
tcp_nodelay on;
proxy_pass websockets;
proxy_send_timeout 300;
}
# virtual hosting
#include /usr/local/nginx/vhosts/*;
}
#http {
#
# server {
# listen 443 ssl;
# server_name socket.artoo.in;
#
# ssl_certificate /usr/local/nginx/key/socket.domain.com.crt;
# ssl_certificate_key /usr/local/nginx/key/socket.domain.com.key;
#
# ssl_session_timeout 5m;
#
# ssl_protocols SSLv2 SSLv3 TLSv1;
# ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;
# ssl_prefer_server_ciphers on;
#
# location / {
# proxy_pass http://127.0.0.1:9000;
# }
# }
#}
Now the only thing I need to worry about is how to increase the timeout for websockets on nginx, the connection seems to be breaking every 75 secs (default for nginx).

Related

Nginx - Using conf filename as server_name, instead of server_name itself

We're actually trying to setup a simple Nginx config. But actually, we're losing our head on this conf as nginx is doing a strange job :
We've setted up 2 sub-domains on a clean Nginx install from yesterday :
Domain 1 :
upstream 430750ef-08ce-4463-bfae-88043ffc7c82-app {
server localhost:58033;
}
server {
listen 80;
listen [::]:80;
server_name 430750ef-08ce-4463-bfae-88043ffc7c82.app.foobar.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name 430750ef-08ce-4463-bfae-88043ffc7c82.app.foobar.com;
ssl on;
ssl_certificate /etc/letsencrypt/live/430750ef-08ce-4463-bfae-88043ffc7c82.app.foobar.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/430750ef-08ce-4463-bfae-88043ffc7c82.app.foobar.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
location / {
proxy_pass http://430750ef-08ce-4463-bfae-88043ffc7c82-app;
proxy_connect_timeout 1200;
proxy_send_timeout 1200;
proxy_read_timeout 1200;
send_timeout 1200;
client_max_body_size 100M;
}
}
Domain 2 :
upstream 820528fd-a13f-496a-b124-8973f4367db6-app {
server localhost:58033;
}
server {
listen 80;
listen [::]:80;
server_name 820528fd-a13f-496a-b124-8973f4367db6.app.foobar.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name 820528fd-a13f-496a-b124-8973f4367db6.app.foobar.com;
ssl on;
ssl_certificate /etc/letsencrypt/live/820528fd-a13f-496a-b124-8973f4367db6.app.foobar.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/820528fd-a13f-496a-b124-8973f4367db6.app.foobar.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
location / {
proxy_pass http://820528fd-a13f-496a-b124-8973f4367db6-app;
proxy_connect_timeout 1200;
proxy_send_timeout 1200;
proxy_read_timeout 1200;
send_timeout 1200;
client_max_body_size 100M;
}
}
Actually, we're having SSL problems on the domain 2 : Firefox (and chrome aswell) are saying that Domain 2 SSL certificate is not trusted, as the domain 2 is using the cert of domain 1 and is not reached by this one.
We can't understand why the server_name property is not working. From our point of view, nginx should be using the domain 2 cert when any visitor reach 820528fd-a13f-496a-b124-8973f4367db6.app.foobar.com .
1 more specification :
I've updated the server_names_hash_bucket_size to 512 as we're using long subdomains.
"FUN" fact :
When we rename the domain 2 config file from /etc/nginx/sites-enabled/820528fd-a13f-496a-b124-8973f4367db6.conf to /etc/nginx/sites-enabled/000-820528fd-a13f-496a-b124-8973f4367db6.conf, the right cert is served.
In that case, we're thinking that, for a reason that we couldn't find, nginx is using the filename as the server_name property, instead of the server_name prop we've setted up in the file, and for another reason only using the first config file found in /etc/nginx/sites-enabled.
Any ideas ?
Thanks for your support by the way,
Regards,

Cannot configure SSL with nginx on windows server

It's been two days that I've been trying to configure my website in https but nothing works.
Here is my configuration file :
worker_processes 1;
error_log logs/error.log info;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 9998 ssl;
server_name mysubdomain.domain.fr;
ssl_certificate "C:/path_to_cert.crt";
ssl_certificate_key "C:/path_to_rsa.rsa";
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
location / {
root html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
On firefox I have PR_CONNECT_RESET_ERROR.
And with openssl -connect :
4384:error:0200274C:system library:connect:reason(1868):crypto\bio\b_sock2.c:110:
4384:error:2008A067:BIO routines:BIO_connect:connect error:crypto\bio\b_sock2.c:111:
connect:errno=0
Am I missing something?
Thank you in advance for your help
After several days of searching for the source of the problem, it turned out that it came from IIS installed on this computer and previously configured on this port which was blocking the connection.

error using nginx to forward https on centos7

I deployed .net core website using docker on centos.
Then I tried to use nginx for forwarding, but when I only used http to access it without any problems. If I use https I get a 403 error.
I have tried the following solutions: modify permissions, modify users, modify configuration files, but to me they are useless.
Below is my configuration file.
# For more information on configuration, see:
# * Official English Documentation: http://nginx.org/en/docs/
# * Official Russian Documentation: http://nginx.org/ru/docs/
user root;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
# Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;
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 default_server;
listen [::]:80 default_server;
server_name _;
root /usr/share/nginx/html;
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
location / {
index index.html index.htm;
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
# Settings for a TLS enabled server.
#
# server {
# listen 443 ssl http2 default_server;
# listen [::]:443 ssl http2 default_server;
# server_name _;
# root /usr/share/nginx/html;
#
# ssl_certificate "/etc/pki/nginx/server.crt";
# ssl_certificate_key "/etc/pki/nginx/private/server.key";
# ssl_session_cache shared:SSL:1m;
# ssl_session_timeout 10m;
# ssl_ciphers HIGH:!aNULL:!MD5;
# ssl_prefer_server_ciphers on;
#
# # 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 {
# }
# }
# web config(blog)
server {
listen 80;
server_name www.changqingmao.com changqingmao.com;
location / {
proxy_redirect off;
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_pass http://127.0.0.1:5001;
}
}
}
server {
listen 443 ssl;
server_name www.changqingmao.com changqingmao.com;
root /root/core/web;
ssl_certificate "/root/core/webCer/1_www.changqingmao.com_bundle.crt";
ssl_certificate_key "/root/core/webCer/2_www.changqingmao.com.key";
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 10m;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
location / {
#root /usr/share/nginx/html;
root /root/core/web;
index index.html index.htm;
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
server
{
listen 80;
server_name www.changqingmao.com changqingmao.com;
rewrite ^(.*) https://$host$1 permanent;
}
error message:[error] 26994#0: *2 directory index of "/root/core/web/" is forbidden, client: 218.88.84.85, server: www.changqingmao.com, request: "GET / HTTP/1.1", host: "www.changqingmao.com"
I placed the file after posting in"/root/core/web"

NGINX: ssl proxy based on path to multiple apps on localhost with different ports

I'm trying to configure nginx to proxy requests to different servers running on the host machine with different ports depending on request path. To complicate things a bit more, I want all the apps to use ssl. In other words I want nginx to do the following:
https://www.example.com/app1 --> http://localhost:8001
https://www.example.com/app2 --> http://localhost:8002
https://www.example.com/app3 --> http://localhost:8003
...
What I got so far (which is not quite working):
# redirecting from http to https
server {
listen 80;
301 https://$host$request_uri;
}
# proxying path to port
server {
listen 443;
ssl_certificate /path/to/cert.pem
ssl_certificate_key /path/to/privkey.pem
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!MD5;
location /app1 {
proxy_pass http://localhost:8001
}
location /app2 {
proxy_pass http://localhost:8002
}
location /app3 {
proxy_pass http://localhost:8003
}
}
What ends up happening is that nginx only exposes one specific app (that was there first).
Any ideas on what I'm doing wrong would be appreciated. Thanks.
Replace your nginc.conf with the following
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
return 301 https://$host$request_uri;
}
server {
listen 443;
root /usr/share/nginx/html;
ssl on;
ssl_certificate /etc/nginx/ssl/demo.com.crt;
ssl_certificate_key /etc/nginx/ssl/demo.com.key;
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";
chunked_transfer_encoding on;
location /app1 {
proxy_pass http://<private-ip>:8001
}
location /app2 {
proxy_pass http://<private-ip>:8002
}
location /app3 {
proxy_pass http://<private-ip>:8003
}
}
Copy your .crt, .kry file in your required folder

HTTP Upgrade to TLS in Nginx Per RFC 2817

I have been looking into how I can upgrade an HTTP connection to TLS and achieve and end to end tunnel across proxy hops. I would like to use the client certificate in this tunnel to act upon it on the receiving end after a few hops.
I read RFC 2817 (HTTP Upgrade to TLS) and it seems this is possible. I just cannot figure out how to do that using Nginx being new to Nginx.
I was wondering if I am making a complete noob mistake or if this is at all possible in Nginx.
I have Nginx instance 1 with the following config for the http block:
http {
include mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] '
'$ssl_protocol/$ssl_cipher '
'$ssl_client_cert '
'$ssl_client_raw_cert '
'HTTP UPGRADE: $http_upgrade '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent"';
access_log logs/access.log;
sendfile on;
keepalive_timeout 65;
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 80 default_server;
listen [::]:80 default_server;
# Redirect all HTTP requests to HTTPS with a 301 Moved Permanently response.
return 301 https://$host$request_uri;
}
# HTTPS server
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name localhost;
access_log logs/access-ssl.log main;
ssl_certificate /root/certs/server.crt;
ssl_certificate_key /root/certs/server.key;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
# Diffie-Hellman parameter for DHE ciphersuites, recommended 2048 bits
ssl_dhparam /root/certs/dhparams.pem;
# modern configuration. tweak to your needs.
ssl_protocols TLSv1.2;
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';
ssl_prefer_server_ciphers on;
# HSTS (ngx_http_headers_module is required) (15768000 seconds = 6 months)
add_header Strict-Transport-Security max-age=15768000;
location / {
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_pass https://10.0.3.4/;
}
# redirect server error pages to the static page /50x.html
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
The second Nginx instance has the following config has pretty much the same config except for one difference proxy_pass https://10.0.3.5/index.html
The last Nginx instance has the following config:
http {
include mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] '
'$ssl_protocol/$ssl_cipher '
'$ssl_client_cert '
'$ssl_client_raw_cert '
'HTTP UPGRADE: $http_upgrade '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent"';
access_log logs/access.log;
sendfile on;
keepalive_timeout 65;
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 80 default_server;
listen [::]:80 default_server;
# Redirect all HTTP requests to HTTPS with a 301 Moved Permanently response.
return 301 https://$host$request_uri;
}
# HTTPS server
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name localhost;
access_log logs/access-ssl.log main;
ssl_certificate /root/certs/server.crt;
ssl_certificate_key /root/certs/server.key;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
# Diffie-Hellman parameter for DHE ciphersuites, recommended 2048 bits
ssl_dhparam /root/certs/dhparams.pem;
# modern configuration. tweak to your needs.
ssl_protocols TLSv1.2;
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';
ssl_prefer_server_ciphers on;
# HSTS (ngx_http_headers_module is required) (15768000 seconds = 6 months)
add_header Strict-Transport-Security max-age=15768000;
location / {
root html;
index index.html index.htm;
}
# redirect server error pages to the static page /50x.html
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
When I hit the URL using HTTPS, I do get the response but nothing about the client cert is printed in the logs. When I use only HTTP, I get the 301 response. These are the two calls I am making:
$ curl -k -i --cert /root/certs/client-cert.pem --key /root/certs/client-key.pem --header "Upgrade: TLS/1.2" --header "Connection: Upgrade" https://10.0.3.3/
and
$ curl -k -i --cert /root/certs/client-cert.pem --key /root/certs/client-key.pem --header "Upgrade: TLS/1.2" --header "Connection: Upgrade" http://10.0.3.3/
RFC 2817 defines two methods for TLS upgrade: CONNECT request and Connection: Upgrade.
CONNECT is a HTTP request done by the browser when using an explicitly configured HTTP proxy. It gets not used with transparent proxies or reverse proxies. Contrary to for instance squid nginx is a web server and not a HTTP proxy (from the perspective of the browser) and thus does not implement the CONNECT request.
As for the Connection Upgrade to TLS specified in RFC 2817: this was just an idea and no browser supports this. This kind of Upgrade mechanisms is actually used in browsers today but not for upgrading to TLS but only for WebSockets.