https_client sample: connection refused

Hi,

We are working on a project in which data must be sent to server using NB-Iot.

We are struggling establishing an HTTPS connection with a server using the NRF9160 development kit.

As a starting point I copied some parts of the https_client sample from the sdk-nrf repo (v3.2.2). Here is the code:

static int Test()
{
	int err;

	printk("HTTPS client sample started\n\r");

	/* Setup handler for Zephyr NET Connection Manager events. */
	net_mgmt_init_event_callback(&l4_cb, l4_event_handler, L4_EVENT_MASK);
	net_mgmt_add_event_callback(&l4_cb);

	/* Setup handler for Zephyr NET Connection Manager Connectivity layer. */
	net_mgmt_init_event_callback(&conn_cb, connectivity_event_handler, CONN_LAYER_EVENT_MASK);
	net_mgmt_add_event_callback(&conn_cb);

	printk("Bringing network interface up\n");

	/* Connecting to the configured connectivity layer.
	 * Wi-Fi or LTE depending on the board that the sample was built for.
	 */
	err = conn_mgr_all_if_up(true);
	if (err) {
		printk("conn_mgr_all_if_up, error: %d\n", err);
		return err;
	}

	 /* Provision certificates before connecting to the network */
	err = cert_provision();
	if (err) {
		return 0;
	}

	printk("Connecting to the network\n");

	err = conn_mgr_all_if_connect(true);
	if (err) {
		printk("conn_mgr_all_if_connect, error: %d\n", err);
		return 0;
	}

	/* Resend connection status if the sample is built for NATIVE_SIM.
	 * This is necessary because the network interface is automatically brought up
	 * at SYS_INIT() before main() is called.
	 * This means that NET_EVENT_L4_CONNECTED fires before the
	 * appropriate handler l4_event_handler() is registered.
	 */
	if (IS_ENABLED(CONFIG_BOARD_NATIVE_SIM)) {
		conn_mgr_mon_resend_status();
	}

	k_sem_take(&network_connected_sem, K_FOREVER);

	send_http_request();

	/* A small delay for the TCP connection teardown */
	k_sleep(K_SECONDS(1));

	/* The HTTP transaction is done, take the network connection down */
	err = conn_mgr_all_if_disconnect(true);
	if (err) {
		printk("conn_mgr_all_if_disconnect, error: %d\n", err);
	}

	err = conn_mgr_all_if_down(true);
	if (err) {
		printk("conn_mgr_all_if_down, error: %d\n", err);
	}

	return 0;
}

int cert_provision(void)
{
	int err;

	printk("Provisioning certificate\n");

#if CONFIG_MODEM_KEY_MGMT
	bool exists;
	int mismatch;

	/* It may be sufficient for you application to check whether the correct
	 * certificate is provisioned with a given tag directly using modem_key_mgmt_cmp().
	 * Here, for the sake of the completeness, we check that a certificate exists
	 * before comparing it with what we expect it to be.
	 */
	err = modem_key_mgmt_exists(TLS_SEC_TAG, MODEM_KEY_MGMT_CRED_TYPE_CA_CHAIN, &exists);
	if (err) {
		printk("Failed to check for certificates err %d\n", err);
		return err;
	}

	if (exists) {
		mismatch = modem_key_mgmt_cmp(TLS_SEC_TAG, MODEM_KEY_MGMT_CRED_TYPE_CA_CHAIN, cert,
					      sizeof(cert));
		if (!mismatch) {
			printk("Certificate match\n");
			return 0;
		}

		printk("Certificate mismatch\n");
		err = modem_key_mgmt_delete(TLS_SEC_TAG, MODEM_KEY_MGMT_CRED_TYPE_CA_CHAIN);
		if (err) {
			printk("Failed to delete existing certificate, err %d\n", err);
		}
	}

	printk("Provisioning certificate to the modem\n");

	/*  Provision certificate to the modem */
	err = modem_key_mgmt_write(TLS_SEC_TAG, MODEM_KEY_MGMT_CRED_TYPE_CA_CHAIN, cert,
				   sizeof(cert));
	if (err) {
		printk("Failed to provision certificate, err %d\n", err);
		return err;
	}
#else /* CONFIG_MODEM_KEY_MGMT */
	err = tls_credential_add(TLS_SEC_TAG,
				 TLS_CREDENTIAL_CA_CERTIFICATE,
				 cert,
				 sizeof(cert));
	if (err == -EEXIST) {
		printk("CA certificate already exists, sec tag: %d\n", TLS_SEC_TAG);
	} else if (err < 0) {
		printk("Failed to register CA certificate: %d\n", err);
		return err;
	}
#endif /* !CONFIG_MODEM_KEY_MGMT */

	return 0;
}

int tls_setup(int fd)
{
	int err;
	int verify;

	/* Security tag that we have provisioned the certificate with */
	const sec_tag_t tls_sec_tag[] = {
		TLS_SEC_TAG,
	};

	/* Set up TLS peer verification */
	enum {
		NONE = 0,
		OPTIONAL = 1,
		REQUIRED = 2,
	};

	verify = REQUIRED;

	err = setsockopt(fd, SOL_TLS, TLS_PEER_VERIFY, &verify, sizeof(verify));
	if (err) {
		printk("Failed to setup peer verification, err %d\n", errno);
		return err;
	}

	/* Associate the socket with the security tag
	 * we have provisioned the certificate with.
	 */
	err = setsockopt(fd, SOL_TLS, TLS_SEC_TAG_LIST, tls_sec_tag, sizeof(tls_sec_tag));
	if (err) {
		printk("Failed to setup TLS sec tag, err %d\n", errno);
		return err;
	}

	err = setsockopt(fd, SOL_TLS, TLS_HOSTNAME,
			CONFIG_HTTPS_HOSTNAME,
			sizeof(CONFIG_HTTPS_HOSTNAME) - 1);
	if (err) {
		printk("Failed to setup TLS hostname, err %d\n", errno);
		return err;
	}
	return 0;
}

static void on_net_event_l4_disconnected(void)
{
	printk("Disconnected from the network\n");
}

static void on_net_event_l4_connected(void)
{
	k_sem_give(&network_connected_sem);
}

static void l4_event_handler(struct net_mgmt_event_callback *cb,
			     uint64_t event,
			     struct net_if *iface)
{
	switch (event) {
	case NET_EVENT_L4_CONNECTED:
		printk("Network connectivity established and IP address assigned\n");
		on_net_event_l4_connected();
		break;
	case NET_EVENT_L4_DISCONNECTED:
		printk("Network connectivity lost\n");
		on_net_event_l4_disconnected();
		break;
	default:
		break;
	}
}

static void connectivity_event_handler(struct net_mgmt_event_callback *cb,
				       uint64_t event,
				       struct net_if *iface)
{
	if (event == NET_EVENT_CONN_IF_FATAL_ERROR) {
		printk("Fatal error received from the connectivity layer\n");
		return;
	}
}

I am getting this warning and error : 

<wrn> modem_key_mgmt: Failed to retrieve CMEE status, err -1
Failed to check for certificates err -1

I noticed that in this example the function nrf_modem_lib_init() is never called, i don't really understand why it use in some examples and not in others.
I thought that maybe the problem was coming from the project configuration so secondly I used directly the sample by cloning it on my computer.
Now I am getting this log:

HTTPS client sample started
Bringing network interface up
Provisioning certificate
Certificate match
Connecting to the network
+CEREG: 2,"BD84","09A19608",7
+CSCON: 1
+CGEV: ME PDN ACT 0,0
+CNEC_ESM: 50,0
%MDMEV: SEARCH STATUS 2
+CEREG: 5,"BD84","09A19608",7,,,"11100000","11100000"
Network connectivity established and IP address assigned
Looking up example.com
Resolved 172.66.147.243 (AF_INET)
Connecting to example.com:443
connect() failed, err: 111
+CGEV: ME PDN DEACT 0
+CEREG: 0
+CGEV: ME DETACH
+CSCON: 0
Network connectivity lost
Disconnected from the network

connect() returns 111 (connection refused).

I must admit I am quite lost on which libraries to use (zephyr vs nrf) to setup Nb-IOT vs Lte-M and TLS.

I just want to make a simple HTTPS POST request via NB-IOT.

Any help would be greatly appreciated.

Thank you,

Arthur

  • I must admit I am quite lost on which libraries to use (zephyr vs nrf) to setup Nb-IOT vs Lte-M and TLS.

    The common setup is:

    TCP/TLS is done by the modem's firmware

    NCS comes with the additional libraries to use the modem

    zephyr is the framework to use it.

    So you use both zephyr and NCS.

    A special setup uses 

    TCP by the modem's firmware

    TLS by zephyr

    If that helps, is more a question, which issues you faced with the common approach.

    In general:

    NB-IoT would only support TCP/TLS on pretty good radio conditions. If the signals goes low, the RTT goes up and that may break TCP.

  • Hi,

    Thanks for the detailed information. Before we suggest any changes, a few quick questions:

    1. What is the hostname of your actual target server?
    2. Which SIM/operator are you using, and do you know if NB-IoT is supported on it?
    3. What modem firmware version are you on? You can check by running AT+CGMR via the AT Client sample.

    On your nrf_modem_lib_init() question, you don't need to call it explicitly when using the https_client sample. The board configuration for the nRF9160 DK handles modem initialization automatically in the background.

    Regarding the connect() failed, err: 111, this error on the nRF9160 typically means the TLS handshake failed, most commonly due to a certificate mismatch. Let us know the answers above and we'll get you to a working HTTPS POST over NB-IoT with minimal changes.

    Best Regards,
    Syed Maysum

  • Hi,

    Thank you very much for the quick answers   !

    1. The actual server hostname is something like *******.eu-west-1.amazonaws.com 

    2. I use the test SIM card provided by Nordic (IBASIS), I was thinking maybe there are restrictions with this plan?

    3. The modem firmware version is: mfw_nrf9160_1.3.7

    Also the radio conditions are not very good in our lab...

    Thank you,

    Arthur

  • From your first message:

    +CEREG: 5,"BD84","09A19608",7,,,"11100000","11100000"
    Network connectivity established and IP address assigned
    Looking up example.com
    Resolved 172.66.147.243 (AF_INET)
    Connecting to example.com:443
    connect() failed, err: 111

    From the last message:

    The actual server hostname is something like *******.eu-west-1.amazonaws.com 

    What I see:

    > +CEREG: 5,"BD84","09A19608",7,,,"11100000","11100000"
    > Network connectivity established and IP address assigned

    device has registered successfully in the mobile network

    > Looking up example.com
    > Resolved 172.66.147.243 (AF_INET)

    Your destination is "example.com"

    > The actual server hostname is something like *******.eu-west-1.amazonaws.com 

    But "example.com" is not "eu-west-1.amazonaws.com".

    the TLS handshake failed, most commonly due to a certificate mismatch.

    The is pretty frequently the reason, when connecting to a different server. You would need to trust the proper CA (anchor certificate).  

  • As I said in my first my message, I tried to use the sdk-nrf example https_client that's why the hostname is not the same as the one for my application... I just wanted to test if connection is even possible in my lab that's all.

Related