Ratchet + nginx + SSL/secure websocket - ssl

I've been trying to run Ratchet.io over SSL (this problem: php ratchet websocket SSL connect?).
My webserver is running at myhost.mobi, and I have created a separate virtual host for websocket service "wws.myhost.mobi".
My web socket:
$webSock = new React\Socket\Server($loop);
$webSock->listen(8080, '0.0.0.0');
$webServer = new Ratchet\Server\IoServer(
new Ratchet\Http\HttpServer(
new Ratchet\WebSocket\WsServer(
new Ratchet\Wamp\WampServer(
$pusher
)
)
),
$webSock
);
My nginx config (I'm on nginx 1.5.8):
upstream websocketserver {
server localhost:8080;
}
server {
server_name wss.myapp.mobi;
listen 443;
ssl on;
ssl_certificate /etc/ssl/myapp-mobi-ssl.crt;
ssl_certificate_key /etc/ssl/myapp-mobi.key;
access_log /var/log/wss-access-ssl.log;
error_log /var/log/wss-error-ssl.log;
location / {
proxy_pass http://websocketserver;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
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_set_header X-Forwarded-Proto https;
proxy_read_timeout 86400; # neccessary to avoid websocket timeout disconnect
proxy_redirect off;
}
}
My client-side script:
var conn = new ab.Session('wss://wss.myapp.mobi', function(o) {
// ...
}, function() {
console.warn('WebSocket connection closed');
}, {
skipSubprotocolCheck: true
});
So, when I load the page in Firefox, I see an outgoing connection to wss://wss.myapp.mobi:8080/, which is hanging (the spinner) and never completes or dies. I do not see any trace of request arriving on the backend in the logs.
What am I missing there?
Thanks!
EDIT I have realized that I should be connecting to wss://wss.myapp.mobi, but now I am getting "101 Switching Protocols" status.
EDIT 2 Everything is working now with the config above. "101 Switching Protocols" status turns out to be a normal message. PROBLEM SOLVED!

By checking question edit history, it is clear that, the configuration in the question was correct, temuri was trying to connect from client with port set in,
upstream websocketserver {
server localhost:8080;
}
but this code block tells Nginx there is a tcp server running on port 8080, represents it as websocketserver alias, but the running server is not accessible to public.
Check the below configuration,
server {
server_name wss.myapp.mobi;
listen 443;
ssl on;
ssl_certificate /etc/ssl/myapp-mobi-ssl.crt;
ssl_certificate_key /etc/ssl/myapp-mobi.key;
access_log /var/log/wss-access-ssl.log;
error_log /var/log/wss-error-ssl.log;
location / {
proxy_pass http://websocketserver;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
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_set_header X-Forwarded-Proto https;
proxy_read_timeout 86400; # neccessary to avoid websocket timeout disconnect
proxy_redirect off;
}
}
this configuration binds the domain wss.myapp.mobi to port 443 enabling ssl and proxying the requests to the local websocket server via proxy_pass directive, rest directives are for connection upgrades handling.
So the websocket server can be accessed from browser client with
// connect through binded domain
// instead of wss.myapp.mobi:8080 which will not work
var url = 'wss://wss.myapp.mobi';

Related

Docker-compose + Nginx SSL Reverse proxy

Im trying to setup the reverse proxy using Nginx that will also provide https for the backend service.
I have 3 containers, one for mongodb, one for my .NET core backend app and one for reverse proxy.
Docker containers seems to work well and until ive set up the HTTPS it was working well.
The problem is that the requests from https://localhost:8080 are not translated properly to the .NET core app running on http port.
Problem is in my Nginx conf file, but im not sure how to fix it.
worker_processes 1;
events { worker_connections 1024; }
http {
sendfile on;
upstream web {
server web:443;
}
server {
listen 8080;
location /upstream {
proxy_pass https://web;
proxy_ssl_certificate /etc/nginx/cert.pem;
proxy_ssl_certificate_key /etc/nginx/privkey.pem;
proxy_ssl_session_reuse on;
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_set_header X-Forwarded-Host $server_name;
}
}
server {
listen 443 ssl;
ssl_certificate_key /etc/nginx/privkey.pem;
ssl_client_certificate /etc/nginx/cert.pem;
ssl_verify_client off;
location / {
proxy_pass http://web;
}
}
}
When i do HTTP request, ill get back 502 Bad gateway error, when using https://localhost:8080 it will return ERR_SSL_PROTOCOL_ERROR.
In the terminal, nginx container returns
Any ideas?
After reading a bit trought the docs Ive been able to find the solution.
worker_processes 1;
events { worker_connections 1024; }
http {
sendfile on;
upstream web {
server web:80;
}
server {
listen 8080 ssl;
ssl_certificate /etc/nginx/cert.pem;
ssl_certificate_key /etc/nginx/privkey.pem;
location / {
proxy_pass http://web;
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_set_header X-Forwarded-Host $server_name;
proxy_set_header X-NginX-Proxy true;
}
}
}

How to install SSL Certificate on Centos 7 with Nginx

I've needed to set up SSL on my server, and have been putting it off, I've now done it, and found it a lot simpler than expected, so for anyone else, here's the process I followed.
I have a dedicated server, and have downloaded a GeoTrust Certificate and Private Key (supplied by my host).
I have uploaded both of these to /etc/nginx/ssl/ (as root).
I added the following to my Nginx default.conf:
server {
server_name www.example.com;
listen 443;
ssl on;
ssl_certificate /etc/nginx/ssl/www.example.com_ssl_certificate.cer;
ssl_certificate_key /etc/nginx/ssl/www.example.com_private_key.key;
location / {
allow all;
# Proxy Headers
proxy_http_version 1.1;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-Cluster-Client-Ip $remote_addr;
# The Important Websocket Bits!
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_pass http://examplecom;
}
}
I have opened up port 443 as follows:
firewall-cmd --permanent --zone=public --add-port=443/tcp
And added https service:
firewall-cmd --permanent --zone=public --add-service=https
I can now access the app over https at my domain.
The final issue is setting up the Phoenix web sockets over wss, I will edit this post and add that information as soon as I have it done.
HTH someone.
Centos 7
Nginx 1.10.1
you need to configure it in this way for using it with Nginx
server {
listen 80;
listen 443 ssl;
server_name www.example.com ;
ssl_certificate_key /etc/letsencrypt/live/api.domain.com/privkey.pem;
ssl_certificate /etc/letsencrypt/live/api.domain.com/fullchain.pem;
error_page 403 404 500 502 503 504 /critical_error.html;
if ($scheme = http) {
return 301 https://$server_name$request_uri;
}
access_log /var/log/nginx/exampleApi-access.log main;
error_log /var/log/nginx/exampleApi-error.log;
location / {
proxy_pass http://yourip:port;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $http_host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-NginX-Proxy true;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
It will work for sure you should try this.

Running Apache Zeppelin with nginx as reverse proxy

In our current architecture we have two apache front servers, in front of them, we have an nginx load balancer. And in front of that an nginx reverse proxy.
My problem is that i'm trying to run Apache Zeppelin through the reverse proxy, and i'm having some problems with the websockets.
I get an error like this : 400 HTTP method GET is not supported by this URL
And here is a screenshot of what the Chrome's Networks tab shows :
I add my reverse proxy config for Zeppelin:
error_log /var/log/nginx/nginx_error.log warn;
server {
listen 80;
server_name localhost;
location /zeppelin/ {
proxy_pass http://zeppelin:8080/;
proxy_http_version 1.1;
proxy_set_header Upgrade websocket;
proxy_set_header Connection upgrade;
}
# fallback
location / {
return 301 http://ci.blablalablab.com/app/;
}
}
Zeppelin is running inside a docker container, and i have exposes the 8080 port, its host name is : zeppelin.
If you have any questions on the architecture or so, don't hesitate to ask.
Thank you very much guys !
you can add to your reverse proxy configuration
location /ws { # For websocket support
proxy_pass http://zeppelin:8080/ws;
proxy_http_version 1.1;
proxy_set_header Upgrade websocket;
proxy_set_header Connection upgrade;
proxy_read_timeout 86400;
}
Reference: Zeppelin 0.7 auth docs
After a lot of digging around, i ended up with this configuration :
location /zeppelin/ {
proxy_pass http://zeppelin:8080/;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_redirect off;
}
location /zeppelin/ws {
proxy_pass http://zeppelin:8080/ws;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
}
This is working pretty good, thank you everyone for your efforts ;)

nginx+socket.io+ssl: WebSocket connection to 'ws://wechat.pageguy.tech/socket.io/?EIO=3&transport=websocket' failed: Unexpected response code: 302

I want to configure an node.js project using socket.io through nginx with ssl,But I failed,when I start it an error occours like this:
I spent a whole noon search and read documents but still can not figure out how to solve this..If anyone meet this problem before or have any idea about it please help me,thanks a lot.
This is my client side js code:
let socket = io.connect('//wechat.pageguy.tech/ws', {transports: ['websocket']});
This is nginx code:
server {
listen 443;
server_name wechat.pageguy.tech;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Real-IP $remote_addr;
#charset koi8-r;
#access_log /var/log/nginx/log/host.access.log main;
ssl on;
ssl_certificate /etc/ssl/private/pageguy.crt;
ssl_certificate_key /etc/ssl/private/pageguy.key.unsecure;
location / {
#root /usr/share/nginx/html;
#index index.html index.htm;
proxy_pass http://localhost:3335;
}
location /ws/ {
proxy_pass http://localhost:3005;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 86400;
}
}
My express port is 3335,my socket.io port is 3005.Everything were fine before I added ssl in the nginx configuration file.
Nobody help me 555, but I solved problems by myself.
in client side js code:
let socket = io.connect('https//wechat.pageguy.tech/', {transports: ['websocket']});
in nginx configure file:
location /socket.io/(not /ws/ because its default value)

Nginx as Exchange-proxy

I've been looking for a solution for this for quite a few hours already. I'm rather new to Nginx as well, so if someone could help me with a demo config, it would be superb.
1 public IP address (this is what's causing so much trouble)
Nginx as proxy
Exchange 2013
Current situation:
http: apps.domain.org, video.domain.org, geo.domain.org . Traffic on port 80 goes to the Nginx server.
https: mail.domain.org . Traffic on port 443 goes straight to Exchange 2013.
Now, we need https / SSL on our apps.domain.org .
Our firewall only checks the IP addresses and forwards traffic.
So basically, my idea is to have all traffic go to Nginx.
There, I need to know what's for mail.domain.org and redirect it to Exchange. Specifically, I need everything to work. OWA, autodiscover: OK. But I'm struggling with what seems to be RPC.
Someone mentioned I should use a stream config in Nginx to manage that.
But I don't know how to differentiate, so that only mail.domain.org uses a stream, while apps.domain.org is in a http config?
My current config (thanks to the links below, but in particular tigunov's comment about getting Outlook Anywhere aka RPC to work) gets me further than before. Currently failing at a FolderSync attempt when I try Microsoft's Remote Connectivity Analyzer. In Outlook, the credentials box still pops up.
server {
(server_name , SSL-certs etc)
# Set global proxy settings
proxy_pass_header Date;
proxy_pass_header Server;
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_set_header Accept-Encoding "";
keepalive_timeout 3h;
proxy_read_timeout 3h;
#reset_timedout_connection on;
tcp_nodelay on;
client_max_body_size 3G;
#proxy_pass_header Authorization;
proxy_pass_request_headers on;
proxy_http_version 1.1;
proxy_request_buffering off;
proxy_buffering off;
proxy_set_header Connection "Keep-Alive";
}
Test now results in: (everything fine, including ActiveSync - OPTIONS), but:
Attempting the FolderSync command on the Exchange ActiveSync session.
The test of the FolderSync command failed.
Exception details:
Message: The request was aborted: The request was canceled.
Type: System.Net.WebException
Stack trace:
at System.Net.HttpWebRequest.GetResponse()
at Microsoft.Exchange.Tools.ExRca.Extensions.RcaHttpRequest.GetResponse()
Elapsed Time: 526 ms.
No further details to be seen in the connectivity tool.
This configuration is based on Tad DeVries' configuration found here and Daniel Kempkens' fix for autodiscover and RPC issues found here.
Note that since I don't have an Exchange environment to test against, I'm not sure if this configuration will work properly, but it's worth a try.
server {
listen 80;
#listen [::]:80;
server_name mail.gwtest.us autodiscover.gwtest.us;
return 301 https://$host$request_uri;
}
server {
listen 443;
#listen [::]:443 ipv6only=on;
ssl on;
ssl_certificate /etc/ssl/nginx/mail.gwtest.us.crt;
ssl_certificate_key /etc/ssl/nginx/mail.gwtest.us.open.key;
ssl_session_timeout 5m;
server_name mail.gwtest.us;
location / {
return 301 https://mail.gwtest.us/owa;
}
proxy_http_version 1.1;
proxy_read_timeout 360;
proxy_pass_header Date;
proxy_pass_header Server;
proxy_pass_header Authorization;
proxy_set_header Accept-Encoding "";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
more_set_input_headers 'Authorization: $http_authorization';
more_set_headers -s 401 'WWW-Authenticate: Basic realm="exch1.test.local"';
location ~* ^/owa { proxy_pass https://exch1.test.local; }
location ~* ^/Microsoft-Server-ActiveSync { proxy_pass https://exch1.test.local; }
location ~* ^/ecp { proxy_pass https://exch1.test.local; }
location ~* ^/rpc { proxy_pass https://exch1.test.local; }
#location ~* ^/mailarchiver { proxy_pass https://mailarchiver.local; }
error_log /var/log/nginx/owa-ssl-error.log;
access_log /var/log/nginx/owa-ssl-access.log;
}