machinezone / IXWebSocket

websocket and http client and server library, with TLS support and very few dependencies
BSD 3-Clause "New" or "Revised" License
539 stars 173 forks source link

Not able to use wss with an IP address #437

Closed peterphonic closed 1 year ago

peterphonic commented 1 year ago

Hello,

I have a IXWebSocket client connecting to a node.js wss server. Everything is fine as long has the client connect to "wss://localhost:8080". Soon as I use the ip address of the node.js wss server, I have the infamous error "OpenSSL failed - error:0A000086:SSL routines::certificate verify failed"

I tried my own combination of certificates and certificates generated by the script generated from generate.sh as well. So far none of this works.

The certificate chain looks valid between my root ca and my server:

C:\Adacel\Adacel-SSL\ca>openssl verify -CAfile root-ca\certs\ca.crt server\certs\server.crt
server\certs\server.crt: OK

My server.crt has a reference to my ip address, I used the subjectAltName parameter to defined it. I though that my root ca would need it, but it doesn't make any difference.

My c++ IXWebSocket client :

    ix::initNetSystem();
    ix::WebSocket webSocket;
    ix::SocketTLSOptions tlsOptions;
    tlsOptions.caFile = "ca.crt";
    webSocket.setTLSOptions(tlsOptions);
    std::string url("wss://localhost:8080");
    //std::string url("wss://192.168.230.138:8080"); // Cannot connect to the ip address
    webSocket.setUrl(url);

My Node.js server :

const httpsSignalServer = https.createServer(
  {
    key: fs.readFileSync("./server.private.key"),
    cert: fs.readFileSync("./server.crt"),
  },
  (req, res) => {
    console.log(`signal server : we have received the request ${req}`);
  }
);
const signalWebsocket = new WebSockerServer.server({
  httpServer: httpsSignalServer,
});
signalWebsocket.on("request", (request) => onRequest(request));
httpsSignalServer.listen(8080, () =>
  console.log("---> My signal server is listening <---")
);

Thank you for any advices how I could fix that.

bsergean commented 1 year ago

This might be a high level SSL stuff, where you actually need a real hostname and can't use an IP.

$ curl -I google.com/
HTTP/1.1 301 Moved Permanently
Location: http://www.google.com/
Content-Type: text/html; charset=UTF-8
Date: Fri, 10 Feb 2023 20:17:07 GMT
Expires: Sun, 12 Mar 2023 20:17:07 GMT
Cache-Control: public, max-age=2592000
Server: gws
Content-Length: 219
X-XSS-Protection: 0
X-Frame-Options: SAMEORIGIN
Connection: close

$ ping google.com 
PING google.com (142.251.214.142): 56 data bytes
64 bytes from 142.251.214.142: icmp_seq=0 ttl=118 time=6.540 ms
^C
--- google.com ping statistics ---
1 packets transmitted, 1 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 6.540/6.540/6.540/0.000 ms
DataMover$ curl -I https://142.251.214.142
curl: (60) SSL certificate problem: self signed certificate
More details here: https://curl.se/docs/sslcerts.html

curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.
peterphonic commented 1 year ago

Ahhh, thank you, I'll see what I can do in our test environment.

peterphonic commented 1 year ago

I coded a small javascript wss client (using same npm package than my wss server) and this wss client can connect to the same wss server (usingn ip address). Would it be possible that the javascript client and IXWebSocket client have a different implementation of OpenSSL interface?

bsergean commented 1 year ago

Yes the ixwebsocket client uses openssl in its own way.

peterphonic commented 1 year ago

So, I updated my hosts file. I added a fake url pointing to the wss server. Then, I created a new certificate with a SAN pointing to the fake URL et voilà, my c++ wss client can connect to my wss javascript server.

So, your assumption is correct, the IXWebSocket implementation of openssl cannot use an ip address, only domain.

Thank you!