Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot get TLS to work on proxied websocket with nginx #142

Open
TaiTair opened this issue Jul 21, 2022 · 0 comments
Open

Cannot get TLS to work on proxied websocket with nginx #142

TaiTair opened this issue Jul 21, 2022 · 0 comments

Comments

@TaiTair
Copy link

TaiTair commented Jul 21, 2022

I can get it to work with a javascript websocket but it will not work with a Pawl websocket. It seems like the handshake always fails and I'm not too sure how to debug it.

Here's my client code:

$secureContext = array(
  'verify_peer' => false,
  'verify_peer_name' => true,
  'local_cert' => '/redacted/fullchain.pem',
  'local_pk' => '/redacted/privkey.pem'
);
$reactConnector = new \React\Socket\Connector([
    'dns' => '8.8.8.8',
    'timeout' => 10,
    'tls' => $secureContext
]);
$loop = \React\EventLoop\Loop::get();
$connector = new \Ratchet\Client\Connector($loop, $reactConnector, $secureContext);

$connector('wss://vps1.mazion.tv/wss')->then(function($conn) {
    $conn->send('eyyy!');
    $conn->close();
}, function ($e) {
    echo "Could not connect: {$e->getMessage()}\n";
});

Here is my server code:

class saveTheBeardWS implements MessageComponentInterface {
    protected $clients;

    public function __construct() {
        $this->clients = new \SplObjectStorage;
    }

    public function onOpen(ConnectionInterface $conn) {
        $this->clients->attach($conn);
    }

    public function onMessage(ConnectionInterface $from, $msg) {
        echo $msg;
        foreach ($this->clients as $client) {
            if ($from != $client) {
                $client->send($msg);
            }
        }
    }

    public function onClose(ConnectionInterface $conn) {
        $this->clients->detach($conn);
    }

    public function onError(ConnectionInterface $conn, \Exception $e) {
        $conn->close();
    }
}

$loop = Factory::create();

$server = new Server('127.0.0.1:8843', $loop);

$secureServer = new SecureServer($server, $loop, [
    'local_cert'  => '/redacted/fullchain.pem',
    'local_pk' => '/redacted/privkey.pem',
    'verify_peer' => false,
]);

$httpServer = new HttpServer(
    new WsServer(
        new saveTheBeardWS()
    )
);

$ioServer = new IoServer($httpServer, $secureServer, $loop);

$loop->run();

Here's my nginx configuration with the proxy for the websocket:

map $http_upgrade $connection_upgrade {                                                                                                                                                                            
    default upgrade;                                                                                                                                                                                               
    '' close;                                                                                            
}                                 
                                                    
upstream localhost{                                                                                                                                                                                                
    server 127.0.0.1:8843;                                                                               
}                                                                                                        
                                                                                                         
server{                                  
    listen [::]:443 ssl ipv6only=on; # managed by Certbot                                                
    listen 443 ssl; # managed by Certbot                                                                 
    ssl_certificate /redacted/fullchain.pem; # managed by Certbot             
    ssl_certificate_key /redacted/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                                  
    server_name redacted;                                                                          
    error_log /redacted/error_log warn;       
    root /redacted;                                                                    
    index index.php;                                                                                                                                                                                               
                                                                                                                                                                                                                   
    #error_page 404 /404.html;                                                                                                                                                                                     
    #error_page 500 502 503 504 /50x.html;                                                                                                                                                                         
                                                                                                                                                                                                                   
    location /wss {                                
        proxy_pass https://localhost;                                                                    
        proxy_ssl_certificate /redacted/fullchain.pem;                                                                                                                                  
        proxy_ssl_certificate_key /redacted/privkey.pem;                      
        proxy_ssl_session_reuse on;                                                                      
        proxy_set_header X-Real-IP $remote_addr;                                                                                                                                                                   
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;                                     
        proxy_http_version 1.1;                                                                          
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;             
        proxy_set_header Host $host;                                                                                                                                                                               
        proxy_set_header X-Forwarded-Proto https;
        proxy_redirect off;                                                                              
        proxy_read_timeout 86400s;             
        proxy_send_timeout 86400s;
        keepalive_timeout 86400s;
        reset_timedout_connection on;
    }

    location / {
        try_files $uri $uri/ =404;
    }

    location ~ \.php$ {
        include /etc/nginx/conf.d/fastcgi.conf;
        try_files $uri =404;
        fastcgi_index  index.php;
        fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
        include fastcgi_params;
    }

    location ~ (\.ht|\.json|\.db) {
        deny all;
        return 404;
    }

    location ^~ /vendor {
        deny all;
        return 404;
    }
}

server{
    listen 80;
    listen [::]:80;
    server_name redacted;
    return 301 https://$host$request_uri;
}

If I enable verify_peer on the client-side. It fails to handshake.

If I understand correctly, with verify_peer disabled I am leaving the door open for MITM attacks. What are the risks associated with keeping verify_peer disabled?

What am I missing to get the TLS handshake to work?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant