ratchetphp / Ratchet

Asynchronous WebSocket server
http://socketo.me
MIT License
6.28k stars 743 forks source link

ws to wss #161

Closed t3chn0r closed 10 years ago

t3chn0r commented 10 years ago

I need some help as I've been trying to do this for the last couple of days without luck. I recently switched my application to https, everything is working fine except for websockets. If I still try to connect to my server using the address ws://ws.myserver.com:8888/ I get the following error now:

SecurityError: The operation is insecure.

I guess this error makes sense as I'm trying to establish an unsecured connection from a secured site. So, I changed the connection string to wss://ws.myserver.com:8888/, and I know Ratchet doesn't support SSL as it will be too slow for PHP to handle.

Because I'm using Nginx I'm trying to do some kind of redirect from wss to ws to no avail. My Ratchet server is running in port 8888, I went ahead and changed the connection string to wss://ws.myserver.com:18888/ and then put these lines (based on documentation I found) in nginx but it still doesn't work...

server {
    listen 18888;
    server_name *.myserver.com;

    ssl on;
    ssl_certificate /etc/nginx/ssl/server.crt;
    ssl_certificate_key /etc/nginx/ssl/server.key;
    ssl_session_timeout 5m;
    ssl_protocols SSLv2 SSLv3 TLSv1;
    ssl_ciphers HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;

    location / {
        proxy_pass http://192.168.1.100:8888;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_read_timeout 86400;
    }
}

Now, I get the following error, I guess something is still not quite right but at this point I'm lost...

Firefox can't establish a connection to the server at wss://ws.myserver.com:18888/.

Any ideas what I'm missing?

Appreciate any help...

t3chn0r commented 10 years ago

Anyone? :(

igorw commented 10 years ago

Try and toy around with openssl s_client -connect ws.myserver.com:18888. That might tell you if it's the SSL connection that is failing. Also, look at the nginx error logs.

t3chn0r commented 10 years ago

Hello @igorw, I've been doing that for the last couple of days, trying the openssl command (openssl s_client -connect ws.acme.net:10088) gives me this (it doesn't look like there's any error at all):

CONNECTED(00000003)
depth=0 C = US, ST = New Jersey, O = Acme LLC, CN = *.acme.net, emailAddress = admin@acme.com
verify error:num=18:self signed certificate
verify return:1
depth=0 C = US, ST = New Jersey, O = Acme LLC, CN = *.acme.net, emailAddress = admin@acme.com
verify return:1
---
Certificate chain
 0 s:/C=US/ST=New Jersey/O=Acme LLC/CN=*.acme.net/emailAddress=admin@acme.com
   i:/C=US/ST=New Jersey/O=Acme LLC/CN=*.acme.net/emailAddress=admin@acme.com
---
Server certificate
-----BEGIN CERTIFICATE-----
MIICZzCCAdACCQD0wTwc3sllnDANBgkqhkiG9w0BAQUFADB4MQswCQYDVQQGEwJV
...
6tuOw1XFyhjkvp7eFJiCR6R+Vq0AnX4okVJfj3CfpmG4tMyCEr2RIoK/Xw==
-----END CERTIFICATE-----
subject=/C=US/ST=New Jersey/O=Acme LLC/CN=*.acme.net/emailAddress=admin@acme.com
issuer=/C=US/ST=New Jersey/O=Acme LLC/CN=*.acme.net/emailAddress=admin@acme.com
---
No client certificate CA names sent
---
SSL handshake has read 1172 bytes and written 375 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-SHA
Server public key is 1024 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
    Protocol  : TLSv1.1
    Cipher    : ECDHE-RSA-AES256-SHA
    Session-ID: C42F ... 2722
    Session-ID-ctx: 
    Master-Key: D022 ... 7ABA
    Key-Arg   : None
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    TLS session ticket lifetime hint: 300 (seconds)
    TLS session ticket:
    0000 - 9d 2c 0e 9c 7c 00 1b 4a-97 e7 2c 3e 44 65 26 7e   .,..|..J..,>De&~
    0010 - 9a 0f 2b 36 fc 60 c4 2c-c4 79 dd 9e 23 23 a8 14   ..+6.`.,.y..##..
    0020 - f0 36 49 c7 f0 b6 c8 f5-09 c0 b1 ce 99 e1 b1 8d   .6I.............
    0030 - b6 07 c5 1e e8 19 33 d1-b8 91 9c 94 5f b3 69 db   ......3....._.i.
    0040 - d0 b6 be 44 59 14 36 62-66 ba 9e 9d 1c 31 cd 2c   ...DY.6bf....1.,
    0050 - cb d2 e5 2d a9 1f 48 1a-25 8d fb c5 8d 09 f7 93   ...-..H.%.......
    0060 - 7f f9 71 4b 5e d3 8e 06-3a a7 38 5c b4 be b9 ec   ..qK^...:.8\....
    0070 - 8c a5 f3 46 d0 2b 53 83-f4 78 c9 bc b2 25 73 95   ...F.+S..x...%s.
    0080 - bc 89 1a 48 e7 78 20 24-63 1e 94 c7 e9 80 68 3d   ...H.x $c.....h=
    0090 - fa 7c f3 de dc 92 9e 8b-e3 51 16 66 95 48 2d 7e   .|.......Q.f.H-~

    Start Time: 1389133543
    Timeout   : 300 (sec)
    Verify return code: 18 (self signed certificate)
---
closed

Nginx logs don't show anything at all, like nothing was "handled" by Nginx. This is what I have in Nginx right now:

upstream websocket {
        server ws.acme.net:8888;
}

server {
    listen 10088;
    server_name ws.acme.net;

    ssl on;
    ssl_certificate /etc/nginx/ssl/server.crt;
    ssl_certificate_key /etc/nginx/ssl/server.key;

    # Logging
    error_log /var/log/nginx/ws.acme.net.error.log;
    access_log /var/log/nginx/ws.acme.net.access.log;

    location / {
        proxy_pass http://websocket;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        # WebSocket support (nginx 1.4)
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_read_timeout 86400;
    }
}

If I try to connect using wss://ws.acme.net:10088 nothing is shown on the Nginx logs, however, if I remove the ssl lines I get the following in the access log:

192.168.1.100 - - [07/Jan/2014:17:34:37 -0500] "\x16\x03\x01\x00\xA8\x01\x00\x00\xA4\x03\x03R\xCC\x80\xFDRB\x82\xB9\x85\x7F\xC2\xEC\xB3-l\xB6\x84\xE1;H\x1D\xCE\xD7\x97\xC1\xDA\xB1\x89\xD8\x8C\xEE\x9E\x00\x00$\xC0+\xC0/\x00\x9E\x00\x9C\xC0" 400 172 "-" "-"

Not sure at this point what else I can test really... If you think of anything else I'll be more than glad to test it.

Regards and thanks for the help.

t3chn0r commented 10 years ago

Some more tests... Not sure if there's anything else that I should change in Ratchet on somewhere else at this point.

Ratchet WebSocket server is running at ws.acme.net:8888

This works (client connection string: ws://ws.acme.net:10088):

Nginx configration (ssl is disabled):

upstream websocket {
        server ws.acme.net:8888;
}

server {
    listen 10088;
    server_name ws.acme.net;

    #ssl on;
    ssl_certificate /etc/nginx/ssl/server.crt;
    ssl_certificate_key /etc/nginx/ssl/server.key;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 5m;
    ssl_protocols SSLv2 SSLv3 TLSv1;
    ssl_ciphers HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;

    # Logging
    error_log /var/log/nginx/ws.acme.net.error.log;
    access_log /var/log/nginx/ws.acme.net.access.log;

    location / {
        #access_log off;
        proxy_pass http://websocket;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        # WebSocket support (nginx 1.4)
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_read_timeout 86400;

        proxy_redirect off;
    }
}

This doesn't work but it's fine because I'm trying to access wss but ssl is still disabled in Nginx (client connection string: wss://ws.acme.net:10088):

Nginx setup (ssl is still disabled):

upstream websocket {
        server ws.acme.net:8888;
}

server {
    listen 10088;
    server_name ws.acme.net;

    #ssl on;
    ssl_certificate /etc/nginx/ssl/server.crt;
    ssl_certificate_key /etc/nginx/ssl/server.key;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 5m;
    ssl_protocols SSLv2 SSLv3 TLSv1;
    ssl_ciphers HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;

    # Logging
    error_log /var/log/nginx/ws.acme.net.error.log;
    access_log /var/log/nginx/ws.acme.net.access.log;

    location / {
        #access_log off;
        proxy_pass http://websocket;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        # WebSocket support (nginx 1.4)
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_read_timeout 86400;

        proxy_redirect off;
    }
}
Nginx logging entry:
192.168.1.100 - - [08/Jan/2014:11:11:17 -0500] "\x16\x03\x01\x00\xA8\x01\x00\x00\xA4\x03\x03R\xCDx\xA5H\xB9b:%\xEA\xE235\xF6K\x8D\xB4\x9A]L\xF6\xBBC\x9D\x04\x88'\x07\x8F\xD3\xE6\x02\x00\x00$\xC0+\xC0/\x00\x9E\x00\x9C\xC0" 400 172 "-" "-"

This doesn't work either but nothing is being written to the Nginx logs (client connection string same as before: wss://ws.acme.net:10088):

Nginx setup (ssl is now enabled):

upstream websocket {
        server ws.acme.net:8888;
}

server {
    listen 10088;
    server_name ws.acme.net;

    ssl on;
    ssl_certificate /etc/nginx/ssl/server.crt;
    ssl_certificate_key /etc/nginx/ssl/server.key;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 5m;
    ssl_protocols SSLv2 SSLv3 TLSv1;
    ssl_ciphers HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;

    # Logging
    error_log /var/log/nginx/ws.acme.net.error.log;
    access_log /var/log/nginx/ws.acme.net.access.log;

    location / {
        #access_log off;
        proxy_pass http://websocket;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        # WebSocket support (nginx 1.4)
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_read_timeout 86400;

        proxy_redirect off;
    }
}

By the way, I'm running Nginx 1.4.4 in case someone is wondering.

t3chn0r commented 10 years ago

Ended up installing stunnel... I couldn't make it work with Nginx.

L0HENGRIN commented 9 years ago

Had similar problems with nginx installed from the ubtuntu 12.04.x Linux repository, which was an 1.2.x version: No connection possible via wss://. Using the wscat tool* didn't succeed, also. After trying around a lot i suspected nginx to be the root of the problem. So i uninstalled nginx, grabbed the latest of nginx via PPA*, installed it (for me it was a 1.6.2 version) and problems were gone. And as nginx config i wrote this, wich is based on the nginx websocket example:

map $http_upgrade $connection_upgrade {
    default upgrade;
    '' close;
}

# my ratchet websocket server internal
upstream websocket {
    server 192.168.1.12:8080;
}

server {
        # listen on this port external
        listen 8081;

        # SSL
        ssl on;
        ssl_certificate /opt/lampp/etc/ssl.crt/server.crt;
        ssl_certificate_key /opt/lampp/etc/ssl.key/server.key;
        ssl_session_cache shared:SSL:10m;
        ssl_session_timeout 5m;

        # route all to "websocket"
        location / {
                proxy_pass http://websocket;
                proxy_http_version 1.1;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection "upgrade";
        }
}

The above works fine at least if i use Chrome Browser for Client. If using Firefox, the Browser says: "Firefox can't establish a connection to the server at wss://dev.mvc.de:8081/". This is due to the fact that FF does have problems with my self signed certificate but thanks to this google groups post***, it can be fixed by simply calling the websocket address via Firefox Browser with a https protocol once - so in my case: https://dev.mvc.de:8081 . Then FF opens a dialogue which allows to accept the self signed certificate.

[EDIT] 2014-12-04 20:22:00, added FF Fix and Link to the google groups post

kevspadillo commented 9 years ago

Hi @t3chn0r!

Recently, I started using ratchet for my project using web socket. And now I am trying to use wss: for secured connection. My question is, how did you managed to use stunnel for ratchet. I saw your comment last Jan 24, 2014 that you ended up using stunnel. Did it worked? How? Can you help me out?

Thanks!

bobvandevijver commented 9 years ago

@makhulhet I also use the secure websockets with stunnel, which is easy to setup. I just run stunnel and specify the config location als argument, which has the following content:

sslVersion = all
foreground = no
debug = 1
; Disable support for insecure SSLv2 protocol
options = NO_SSLv2
[websockets]
accept  = 8080
connect = 8081
TIMEOUTclose = 0
cert = /etc/apache2/ssl/mycert.cert
key = /etc/apache2/ssl/mykey.key

That's all! Notice that I run the websocket server on port 8081 on the local machine, and that stunnel enables clients to connect to port 8080 with the wss protocol.

t3chn0r commented 9 years ago

Hi @makhulhet, using pretty much same values as @bobvandevijver:

key = /etc/nginx/ssl/domain.com.key
cert =  /etc/nginx/ssl/domain.com.unified.crt
CApath = /etc/ssl/certs

socket = l:TCP_NODELAY=1
socket = r:TCP_NODELAY=1

setuid = stunnel4
setgid = stunnel4
pid = /var/run/stunnel4/websocket.pid

debug = 6
output = /var/log/stunnel4/websocket.log

[websocket]
accept = 4443
connect = domain.com:8888

Just replace domain.com with your domain.

Regards

kevspadillo commented 9 years ago

@bobvandevijver, thanks dude... I'll try that config... by the way... i forgot to mention that I am currently running under apache web server.. will it work?

@t3chn0r, I already used that configuration and it seems it doesn't work on mine.. maybe there's something else you did.. :smile:

kevspadillo commented 9 years ago

Hi @bobvandevijver, i tried the your configuration... but how am I going to run my server it seems they'll be having port conflict...

PHP Fatal error:  Uncaught exception 'React\Socket\ConnectionException' with message 'Could not bind to tcp://0.0.0.0:8080: Address already in use' in ../vendor/react/socket/src/Server.php:29
Stack trace:
#0 ../bin/push-server.php(22): React\Socket\Server->listen(8080, '0.0.0.0')
#1 {main} thrown in ../vendor/react/socket/src/Server.php on line 29
t3chn0r commented 9 years ago

Ho @makhulhet, I just double checked my server and remembered that I ended up using haproxy instead as I was already using it and decided to not run and maintain the stunnel service when haproxy could also take care of that...

If you need the haproxy setup that I'm using just let me know.

kevspadillo commented 9 years ago

Hi @t3chn0r, if im going to use haproxy instead of stunnel. Will it work with apache web server?

bobvandevijver commented 9 years ago

@makhulhet Just change the port used in you websocket script to 8081, or interchange the ports in the stunnel config.

I use Apache, works perfect.

kevspadillo commented 9 years ago

Awesome! It worked!

I just need to create separate vhost for my webserver and add some ssl configuration to my vhost.

Thanks!

kergdgreat commented 6 years ago

@bobvandevijver i used your code but its not working. sslVersion = all foreground = no debug = 1 ; Disable support for insecure SSLv2 protocol options = NO_SSLv2 [websockets] accept = 8080 connect = 8081 TIMEOUTclose = 0 cert = /etc/apache2/ssl/mycert.cert key = /etc/apache2/ssl/mykey.key

i got apache 2.2 version in my server.