Curl command works in Terminal but not in exec node

I am using node-red 4.0.5 with Node.js v20.18.1

I am using a curl command to interact with a Daikin airconditioner.
The curl command is:

curl --insecure -H "X-Daikin-uuid: xxxxxxxxxxxxxxxxxxxx" -v "https://192.168.11.194/aircon/get_control_info"

In the terminal window the response is:

pi@raspberrypi:/ $ curl --insecure -H "X-Daikin-uuid: xxxxxxxxxxxxxxxxxxxx" -v "https://<local_ip_address>/aircon/get_control_info"
*   Trying 192.168.11.194:443...
* Connected to 192.168.11.194 (192.168.11.194) port 443 (#0)
* ALPN: offers h2,http/1.1
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* ALPN: server did not agree on a protocol. Uses default.
* Server certificate:
*  subject: C=JP; ST=Osaka; O=DAIKIN INDUSTRIES, LTD; CN=015F4441494B494E000000430028079C.svr
*  start date: May 21 22:49:09 2019 GMT
*  expire date: Apr 27 22:49:09 2119 GMT
*  issuer: C=JP; ST=Osaka; O=DAIKIN INDUSTRIES, LTD; CN=CA.daikindev.com
*  SSL certificate verify result: unable to get local issuer certificate (20), continuing anyway.
* using HTTP/1.x
> GET /aircon/get_control_info HTTP/1.1
> Host: 192.168.11.194
> User-Agent: curl/7.88.1
> Accept: */*
> X-Daikin-uuid: xxxxxxxxxxxxxxxxxxxx
>
* HTTP 1.0, assume close after body
< HTTP/1.0 200 OK
< Content-Length: 335
< Content-Type: text/plain
<
* Closing connection 0
* TLSv1.2 (OUT), TLS alert, close notify (256):
ret=OK,pow=0,mode=3,adv=,stemp=25.0,shum=50,dt1=18.0,dt2=M,dt3=25.0,dt4=26.0,dt5=26.0,dt7=18.0,dh1=50,dh2=50,dh3=50,dh4=50,dh5=50,dh7=50,dhh=50,b_mode=3,b_stemp=25.0,b_shum=50,alert=255,f_rate=A,b_f_rate=A,dfr1=7,dfr2=A,dfr3=A,dfr4=A,dfr5=A,dfr6=A,dfr7=7,dfrh=A,f_dir=2,b_f_dir=2,dfd1=2,dfd2=2,dfd3=2,dfd4=2,dfd5=2,dfd6=0,dfd7=2,dfdh=0

The output from the exec node is as follows:

Command failed:  curl --insecure -H "X-Daikin-uuid: xxxxxxxxxxxxxxxxxxxx" -v "https://<local_ip_address>/aircon/get_control_info"
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed

  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0*   Trying 192.168.11.194:443...
* Connected to 192.168.11.194 (192.168.11.194) port 443 (#0)
* ALPN: offers h2,http/1.1
} [5 bytes data]
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
} [512 bytes data]
* TLSv1.3 (IN), TLS handshake, Server hello (2):
{ [74 bytes data]
* TLSv1.2 (OUT), TLS alert, handshake failure (552):
} [2 bytes data]
* OpenSSL/3.0.15: error:0A000152:SSL routines::unsafe legacy renegotiation disabled

  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
* Closing connection 0
curl: (35) OpenSSL/3.0.15: error:0A000152:SSL routines::unsafe legacy renegotiation disabled

This curl command worked fine in an older version of node-red (3.1.0) with Node.js v18.6.0.

The curl command appears to be ignoring the --insecure option when run from the exec node.

Can anyone assist me to get the curl command to run correctly within node-red 4.0.5 and with node.js 20.18.1?

Forgetting for a second why curl works or not via command, why don't you simply use the http-request node?

1 Like

a google search using curl --insecure came up with this thread that might be educational for you, but follow @Steve-Mcl advice.

HI Steve,
I was using the curl command as it was identified at: Daikin Replacement Models: BRP072C42 · Issue #27 · ael-code/daikin-control · GitHub
I have tried using a http-request node previously with a similar error generated.

RequestError: write EPROTO C05AAD59FF7F0000:error:0A000152:SSL routines:final_renegotiate:unsafe legacy renegotiation disabled:../deps/openssl/openssl/ssl/statem/extensions.c:921:
 : https://192.168.11.194/aircon/get_control_info

Is this running in the node-red docker container?

If so how are you testing the curl command? are you actually running it IN the container or on the host machine?

The reason this will be failing is that the OpenSSL config inside the new container has disabled the legacy SSL negotiation because it is VERY unsafe. The correct thing here is that Daikin should release a firmware update for the device, but I doubt that will happen.

You may need to create a modified /etc/ssl/openssl.conf file and mount that into the container to re-enable the old/deprecated/broken SSL protocols.

See curl: (35) error:0A000152:SSL routines::unsafe legacy renegotiation disabled - Stack Overflow for some suggestions

3 Likes

Hi Ben,
Node red is installed on a headless Raspberry Pi 5. At present, until i get this connection to the Daikin AC sorted, it is the only application on the pi after a new installation of the Raspberry Pi OS. The Raspberry Pi is on a local network.
I agree that it is unlikely that Daikin will will update the firmware.
I had come across some info on this curl error and tried editing the file at /etc/ssl/openssl.cnf already. I suppose this is why the command is working in the terminal window. What puzzles me is why it works in a terminal and not in node red.
Anyway, is there a configuration for node red that I need to change, to get it to allow unsafe legacy renegotiation, preferably just for the calls to the Daikin AC? If not, can I set something else up external to node red, that I can call for this?

Can you please try starting node-red as follows:

node-red --openssl-legacy-provider

And then try the http-request approach again please


As for why it works on the cmd line, I have 2 ideas

  1. Did you restart node-red after making the changes to the openssl.conf file? It will only get read at startup iirc
  2. NodeJS may be setting or removing some environment variable when execing curl, this feels less likely and I also think it should be picking up the changes to the openssl.conf file on each run.

This was the result in the terminal window:

pi@raspberrypi:~ $ node-red --openssl-legacy-provider
8 Dec 14:56:39 - [info]

Welcome to Node-RED
===================

8 Dec 14:56:39 - [info] Node-RED version: v4.0.5
8 Dec 14:56:39 - [info] Node.js  version: v20.18.1
8 Dec 14:56:39 - [info] Linux 6.6.51+rpt-rpi-2712 arm64 LE
8 Dec 14:56:39 - [info] Loading palette nodes
8 Dec 14:56:40 - [info] Settings file  : /home/pi/.node-red/settings.js
8 Dec 14:56:40 - [info] Context store  : 'default' [module=memory]
8 Dec 14:56:40 - [info] User directory : /home/pi/.node-red
8 Dec 14:56:40 - [warn] Projects disabled : editorTheme.projects.enabled=false
8 Dec 14:56:40 - [info] Flows file     : /home/pi/.node-red/flows.json
8 Dec 14:56:40 - [info] Server now running at http://127.0.0.1:1880/
8 Dec 14:56:40 - [warn]

---------------------------------------------------------------------
Your flow credentials file is encrypted using a system-generated key.

If the system-generated key is lost for any reason, your credentials
file will not be recoverable, you will have to delete it and re-enter
your credentials.

You should set your own key using the 'credentialSecret' option in
your settings file. Node-RED will then re-encrypt your credentials
file using your chosen key the next time you deploy a change.
---------------------------------------------------------------------

8 Dec 14:56:40 - [info] Starting flows
8 Dec 14:56:40 - [info] Started flows
8 Dec 14:57:28 - [error] [http request:d4bde7bbfb4b7cf4] RequestError: write EPROTO C09A4003FF7F0000:error:0A000152:SSL routines:final_renegotiate:unsafe legacy renegotiation disabled:../deps/openssl/openssl/ssl/statem/extensions.c:921:

No luck as yet unfortunately. You can see the error from the http request above.

OK, next suggestion, try adding to force it to use the same openssl settings.

--openssl-config=/etc/ssl/openssl.cnf

Still no luck - virtually the same result as before.

pi@raspberrypi:~ $ node-red --openssl-legacy-provider --openssl-config=/etc/ssl/openssl.cfg
8 Dec 21:13:08 - [info]

Welcome to Node-RED
===================

8 Dec 21:13:08 - [info] Node-RED version: v4.0.5
8 Dec 21:13:08 - [info] Node.js  version: v20.18.1
8 Dec 21:13:08 - [info] Linux 6.6.51+rpt-rpi-2712 arm64 LE
8 Dec 21:13:08 - [info] Loading palette nodes
8 Dec 21:13:09 - [info] Settings file  : /home/pi/.node-red/settings.js
8 Dec 21:13:09 - [info] Context store  : 'default' [module=memory]
8 Dec 21:13:09 - [info] User directory : /home/pi/.node-red
8 Dec 21:13:09 - [warn] Projects disabled : editorTheme.projects.enabled=false
8 Dec 21:13:09 - [info] Flows file     : /home/pi/.node-red/flows.json
8 Dec 21:13:09 - [info] Server now running at http://127.0.0.1:1880/
8 Dec 21:13:09 - [warn]

---------------------------------------------------------------------
Your flow credentials file is encrypted using a system-generated key.

If the system-generated key is lost for any reason, your credentials
file will not be recoverable, you will have to delete it and re-enter
your credentials.

You should set your own key using the 'credentialSecret' option in
your settings file. Node-RED will then re-encrypt your credentials
file using your chosen key the next time you deploy a change.
---------------------------------------------------------------------

8 Dec 21:13:09 - [info] Starting flows
8 Dec 21:13:09 - [info] Started flows
8 Dec 21:13:53 - [error] [http request:d4bde7bbfb4b7cf4] RequestError: write EPROTO C0DA0235FF7F0000:error:0A000152:SSL routines:final_renegotiate:unsafe legacy renegotiation disabled:../deps/openssl/openssl/ssl/statem/extensions.c:921:

Just to be clear, this is the set of nodes I am using for the http request.

[
    {
        "id": "d4bde7bbfb4b7cf4",
        "type": "http request",
        "z": "6fd55c5a6e4e0248",
        "name": "",
        "method": "GET",
        "ret": "txt",
        "paytoqs": "ignore",
        "url": "",
        "tls": "",
        "persist": false,
        "proxy": "",
        "insecureHTTPParser": false,
        "authType": "",
        "senderr": false,
        "headers": [],
        "x": 750,
        "y": 360,
        "wires": [
            [
                "eb87fe62bca922d2"
            ]
        ]
    },
    {
        "id": "ea4baf7fe0127982",
        "type": "function",
        "z": "6fd55c5a6e4e0248",
        "name": "Assemble Request for Control Info",
        "func": "msg.header = \"X-Daikin-uuid: 0c38d743180f4d96bb6d8ff27bdfb8b0\";\nmsg.url = \"https://192.168.11.194/aircon/get_control_info\";\n\nreturn msg;",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 460,
        "y": 360,
        "wires": [
            [
                "d4bde7bbfb4b7cf4"
            ]
        ]
    },
    {
        "id": "eb87fe62bca922d2",
        "type": "debug",
        "z": "6fd55c5a6e4e0248",
        "name": "debug 2",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "false",
        "statusVal": "",
        "statusType": "auto",
        "x": 940,
        "y": 360,
        "wires": []
    },
    {
        "id": "9e235e6df53adb17",
        "type": "inject",
        "z": "6fd55c5a6e4e0248",
        "name": "Get Control Info",
        "props": [
            {
                "p": "timestamp",
                "v": "",
                "vt": "date"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": "45",
        "topic": "Daikin AC Control Info",
        "x": 140,
        "y": 360,
        "wires": [
            [
                "ea4baf7fe0127982"
            ]
        ]
    }
]

What if you set the node options in the environment before launching node-red?

export NODE_OPTIONS="--openssl-legacy-provider"
node-red

Thank you for your suggestion Steve.
Same error as before.

pi@raspberrypi:~ $ export NODE_OPTIONS="--openssl-legacy-provider"
pi@raspberrypi:~ $ node-red
14 Dec 18:31:57 - [info]

Welcome to Node-RED
===================

14 Dec 18:31:57 - [info] Node-RED version: v4.0.5
14 Dec 18:31:57 - [info] Node.js  version: v20.18.1
14 Dec 18:31:57 - [info] Linux 6.6.51+rpt-rpi-2712 arm64 LE
14 Dec 18:31:57 - [info] Loading palette nodes
14 Dec 18:31:58 - [info] Settings file  : /home/pi/.node-red/settings.js
14 Dec 18:31:58 - [info] Context store  : 'default' [module=memory]
14 Dec 18:31:58 - [info] User directory : /home/pi/.node-red
14 Dec 18:31:58 - [warn] Projects disabled : editorTheme.projects.enabled=false
14 Dec 18:31:58 - [info] Flows file     : /home/pi/.node-red/flows.json
14 Dec 18:31:58 - [info] Server now running at http://127.0.0.1:1880/
14 Dec 18:31:58 - [warn]

---------------------------------------------------------------------
Your flow credentials file is encrypted using a system-generated key.

If the system-generated key is lost for any reason, your credentials
file will not be recoverable, you will have to delete it and re-enter
your credentials.

You should set your own key using the 'credentialSecret' option in
your settings file. Node-RED will then re-encrypt your credentials
file using your chosen key the next time you deploy a change.
---------------------------------------------------------------------

14 Dec 18:31:58 - [info] Starting flows
14 Dec 18:31:58 - [info] Started flows
14 Dec 18:32:36 - [error] [http request:d4bde7bbfb4b7cf4] RequestError: write EPROTO C05ADFF1FE7F0000:error:0A000152:SSL routines:final_renegotiate:unsafe legacy renegotiation disabled:../deps/openssl/openssl/ssl/statem/extensions.c:921:

@Steve-Mcl , @hardillb thank you for your help with this.

It looks as though I might have added to my problem early on in trying to solve it on my own.

Today I found the following line in the settings.js file
process.env.OPENSSL_CONF = "/home/pi/.node-red/openssl.cnf";
and, at the time, there was no such openssl.cnf file in the /home/pi/.node-red directory.

So I added a copy of the modified openssl.cnf file from /etc/ssl directory and tried again.
This time the exec node curl call was successful but the http request still failed.

This might explain why the curl call in the terminal window was successful but not so when run from the node-red exec node. I do not know why the http request node generates the error.

The curl call is sufficient for my needs so... my plan is to start with a clean install, modify the settings.js file as above and include a suitable openssl.cnf in /home/pi/.node-red and see what happens then.

I do have one question: What advantage is there to me in using a http request node (noting I will still have to get that to work) instead of the curl call from the exec node?

You may need to add some of the command line options we played with early again to get NodeJS to pick up that file, but I'm not sure, which takes precedent, env var vs cmd line arg.

The main reason for doing this all in Node rather than shelling out to curl is more a "cleanliness" thing, to be totally honest if curl now works for you that's great.

I think we will see more of this sort of thing as vendors don't update their firmware to modern secure protocol options.

As a Christmas time project I may try and mock up a suitably "broken" http server to test with.

Have you tried to Enable secure (SSL/TLS) connection and leave the configuration as is ? (ie dont verify cert).

No. Unfortunately I am not familiar enough with node-red to understand what you are referring to.

I was referring to the http request node