Nethvoice CTI rest api SSL handshake failure

Hi,
I am trying to develop simple php app for displaying Nethvoice CTI Phonebook in XML format for use with old Cisco SPA504G phones. The php app is working well on my test web server (Ubuntu / Apache / php 8.3). But after transferring it to Webserver app running on the same NS8 server / node as the Nethvoice app, I am not able to get it to work. No matter what I try, I am still getting this error:

cURL Error: error:14094410:SSL routines:ssl3_read_bytes:sslv3 alert handshake failure

Fragment of my php code:

<?php

function getStaticSecret($apiUrl, $username, $password) {
  // Step 1: Make an initial request to get the `nonce` value
  $ch = curl_init();
curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2); // makes no difference when ommited
  curl_setopt($ch, CURLOPT_URL, $apiUrl . "authentication/login");
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  curl_setopt($ch, CURLOPT_HEADER, true);
  curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // makes no difference when set to true
  curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); // makes no difference when ommited
  curl_setopt($ch, CURLOPT_POST, true);
  curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query(['username' => $username, 'password' => $password]));
  curl_setopt($ch, CURLOPT_VERBOSE, true);
  $response = curl_exec($ch);
  
     if (curl_errno($ch)) {
        echo 'Error: ' . curl_error($ch);
    } else {
        echo $response;
    } 
      
  curl_close($ch);

Interestingly, when I connect to Nethvoice from the command line within the webserver1 containter, it connect just fine.

 /usr/local/bin/runagent -m webserver1
[webserver1@my-ns8 state]$ curl --insecure -i -X POST -d 'username=myuser&password=mypassword' https://nvcti.twr.cz/webrest/authentication/login
HTTP/2 401
access-control-allow-credentials: true
access-control-allow-headers: *
access-control-allow-origin: *
date: Fri, 25 Apr 2025 08:27:47 GMT
www-authenticate: Digest xxxxxx.......

Both Nethvoice and Webserver apps have obtained their LetsEncrypt certificates.
Tried to set various php versions on Webserver with no effect.

I would be thankful for any suggestions.

NethServer Version: NS8
Module: your_module

It seems like ssl 3 is used instead of tls 1.2, maybe it helps to not set CURLOPT_SSLVERSION to allow auto negotiation?

Maybe you also need to add following option:

curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);

Full code example from reqbin:

<?php

$url = "https://nvcti.twr.cz/webrest/authentication/login";

$curl = curl_init($url);
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);

$headers = array(
   "Content-Type: application/x-www-form-urlencoded",
);
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);

$data = "username=myuser&password=mypassword";

curl_setopt($curl, CURLOPT_POSTFIELDS, $data);

//for debug only!
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);

$resp = curl_exec($curl);
curl_close($curl);
var_dump($resp);

?>

Sources:

Thanks a lot @mrmarkuz!

Unfortunately, the result is the same.

What have I found in between:

When I enter the webserver1 module

[root@hur-ns8 admin] /usr/local/bin/runagent -m webserver1
[webserver1@hur-ns8 state]$ curl -v https://nvcti.twr.cz

the connection works (full output below).

But when I further go into the php container, it is not able to connect at all

[webserver1@hur-ns8 state]$ podman exec -ti php8.0-fpm bash
root@webserver:/app# curl -v https://nvcti.twr.cz
*   Trying 192.168.111.2:443...
* connect to 192.168.111.2 port 443 failed: Connection refused
* Failed to connect to nvcti.twr.cz port 443: Connection refused
* Closing connection 0
curl: (7) Failed to connect to nvcti.twr.cz port 443: Connection refused

When I pass the public IP to curl, the handshake failure occurs:

root@webserver:/app# curl -v --resolve "nvcti.twr.cz:443:88.146.128.2" https://nvcti.twr.cz/webrest/
* Added nvcti.twr.cz:443:88.146.128.2 to DNS cache
* Hostname nvcti.twr.cz was found in DNS cache
*   Trying 88.146.128.2:443...
* Connected to nvcti.twr.cz (88.146.128.2) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*  CAfile: /etc/ssl/certs/ca-certificates.crt
*  CApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS alert, handshake failure (552):
* error:14094410:SSL routines:ssl3_read_bytes:sslv3 alert handshake failure
* Closing connection 0
curl: (35) error:14094410:SSL routines:ssl3_read_bytes:sslv3 alert handshake failure

When I try to connect to other server from the php container, it works:

root@webserver:/app# curl -v https://google.com
*   Trying 142.251.36.110:443...
* Connected to google.com (142.251.36.110) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*  CAfile: /etc/ssl/certs/ca-certificates.crt
*  CApath: /etc/ssl/certs
...

As for now I am stuck here and dont know where to move on. Any ideas appreciated.

Thank you!

Full output listings of aforementioned commands follows:

Connection from within webserver1 module:

[root@hur-ns8 admin]# /usr/local/bin/runagent -m webserver1
runagent: [INFO] starting bash -l
runagent: [INFO] working directory: /home/webserver1/.config/state
[webserver1@hur-ns8 state]$ curl -v https://nvcti.twr.cz
*   Trying 192.168.111.2:443...
* Connected to nvcti.twr.cz (192.168.111.2) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
*  CAfile: /etc/pki/tls/certs/ca-bundle.crt
* TLSv1.0 (OUT), TLS header, Certificate Status (22):
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS header, Certificate Status (22):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS header, Finished (20):
* TLSv1.2 (IN), TLS header, Unknown (23):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.2 (IN), TLS header, Unknown (23):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS header, Unknown (23):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.2 (IN), TLS header, Unknown (23):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.2 (OUT), TLS header, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS header, Unknown (23):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_128_GCM_SHA256
* ALPN, server accepted to use h2
* Server certificate:
*  subject: CN=hur.twr.cz
*  start date: Apr 24 19:44:31 2025 GMT
*  expire date: Jul 23 19:44:30 2025 GMT
*  subjectAltName: host "nvcti.twr.cz" matched cert's "nvcti.twr.cz"
*  issuer: C=US; O=Let's Encrypt; CN=R11
*  SSL certificate verify ok.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* TLSv1.2 (OUT), TLS header, Unknown (23):
* TLSv1.2 (OUT), TLS header, Unknown (23):
* TLSv1.2 (OUT), TLS header, Unknown (23):
* Using Stream ID: 1 (easy handle 0x55b948ed8660)
* TLSv1.2 (OUT), TLS header, Unknown (23):
> GET / HTTP/2
> Host: nvcti.twr.cz
> user-agent: curl/7.76.1
> accept: */*
>
* TLSv1.2 (IN), TLS header, Unknown (23):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.2 (IN), TLS header, Unknown (23):
* Connection state changed (MAX_CONCURRENT_STREAMS == 250)!
* TLSv1.2 (OUT), TLS header, Unknown (23):
* TLSv1.2 (IN), TLS header, Unknown (23):
* TLSv1.2 (IN), TLS header, Unknown (23):
< HTTP/2 200
< content-type: text/html; charset=utf-8
< date: Sun, 27 Apr 2025 10:46:32 GMT
< etag: "14os4h3b21420s"
< vary: Accept-Encoding
< x-powered-by: Next.js
<
* TLSv1.2 (IN), TLS header, Unknown (23):
<!DOCTYPE html><html><head><.....

Connection from within php container:

[webserver1@hur-ns8 state]$ podman exec -ti php8.0-fpm bash
root@webserver:/app# curl -v https://nvcti.twr.cz
*   Trying 192.168.111.2:443...
* connect to 192.168.111.2 port 443 failed: Connection refused
* Failed to connect to nvcti.twr.cz port 443: Connection refused
* Closing connection 0
curl: (7) Failed to connect to nvcti.twr.cz port 443: Connection refused



root@webserver:/app# curl -v --resolve "nvcti.twr.cz:443:88.146.128.2" https://nvcti.twr.cz/webrest/
* Added nvcti.twr.cz:443:88.146.128.2 to DNS cache
* Hostname nvcti.twr.cz was found in DNS cache
*   Trying 88.146.128.2:443...
* Connected to nvcti.twr.cz (88.146.128.2) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*  CAfile: /etc/ssl/certs/ca-certificates.crt
*  CApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS alert, handshake failure (552):
* error:14094410:SSL routines:ssl3_read_bytes:sslv3 alert handshake failure
* Closing connection 0
curl: (35) error:14094410:SSL routines:ssl3_read_bytes:sslv3 alert handshake failure




root@webserver:/app# curl -v https://google.com
*   Trying 142.251.36.110:443...
* Connected to google.com (142.251.36.110) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*  CAfile: /etc/ssl/certs/ca-certificates.crt
*  CApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN, server accepted to use h2
* Server certificate:
*  subject: CN=*.google.com
*  start date: Mar 31 08:54:37 2025 GMT
*  expire date: Jun 23 08:54:36 2025 GMT
*  subjectAltName: host "google.com" matched cert's "google.com"
*  issuer: C=US; O=Google Trust Services; CN=WE2
*  SSL certificate verify ok.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x55f32003e540)
> GET / HTTP/2
> Host: google.com
> user-agent: curl/7.74.0
> accept: */*
>
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* old SSL session ID is stale, removing
* Connection state changed (MAX_CONCURRENT_STREAMS == 100)!
< HTTP/2 301
< location: https://www.google.com/
< content-type: text/html; charset=UTF-8
< content-security-policy-report-only: object-src 'none';base-uri 'self';script-src 'nonce-QAalRp8PewI3MZ3iGCx1vA' 'strict-dynamic' 'report-sample' 'unsafe-eval' 'unsafe-inline' https: http:;report-uri https://csp.withgoogle.com/csp/gws/other-hp
< date: Sun, 27 Apr 2025 10:49:35 GMT
< expires: Tue, 27 May 2025 10:49:35 GMT
< cache-control: public, max-age=2592000
< server: gws
< content-length: 220
< x-xss-protection: 0
< x-frame-options: SAMEORIGIN
< alt-svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000
<
<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>301 Moved</TITLE></HEAD><BODY>
<H1>301 Moved</H1>
The document has moved
<A HREF="https://www.google.com/">here</A>.
</BODY></HTML>
* Connection #0 to host google.com left intact


Update: I tried to install the not certified ns8-lamp app instead of webserver. From there my php script runs and connects to Nethvoice out of the box right away.

1 Like