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

Parents
  • 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.

  • OK. So you use the "nrf/samples/net/https_client" and you didn't modify it?

    If so, I guess it fails, because the used trusted certificate in the sample is from www.digicert.com, while currently "example.com" uses SSL.com .

    You may try it with the SSL.com root:

    -----BEGIN CERTIFICATE-----
    MIICOjCCAcCgAwIBAgIQFAP1q/s3ixdAW+JDsqXRxDAKBggqhkjOPQQDAzBOMQsw
    CQYDVQQGEwJVUzEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMSUwIwYDVQQDDBxT
    U0wuY29tIFRMUyBFQ0MgUm9vdCBDQSAyMDIyMB4XDTIyMDgyNTE2MzM0OFoXDTQ2
    MDgxOTE2MzM0N1owTjELMAkGA1UEBhMCVVMxGDAWBgNVBAoMD1NTTCBDb3Jwb3Jh
    dGlvbjElMCMGA1UEAwwcU1NMLmNvbSBUTFMgRUNDIFJvb3QgQ0EgMjAyMjB2MBAG
    ByqGSM49AgEGBSuBBAAiA2IABEUpNXP6wrgjzhR9qLFNoFs27iosU8NgCTWyJGYm
    acCzldZdkkAZDsalE3D07xJRKF3nzL35PIXBz5SQySvOkkJYWWf9lCcQZIxPBLFN
    SeR7T5v15wj4A4j3p8OSSxlUgaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSME
    GDAWgBSJjy+j6CugFFR781a4Jl9nOAuc0DAdBgNVHQ4EFgQUiY8vo+groBRUe/NW
    uCZfZzgLnNAwDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMDA2gAMGUCMFXjIlbp
    15IkWE8elDIPDAI2wv2sdDJO4fscgIijzPvX6yv/N33w7deedWo1dlJF4AIxAMeN
    b0Igj762TVntd00pxCAgRWSGOlDGxK0tk/UYfXLtqc/ErFc2KAhl3zx5Zn6g6g==
    -----END CERTIFICATE-----

    but I don't know, if that works.

Reply
  • OK. So you use the "nrf/samples/net/https_client" and you didn't modify it?

    If so, I guess it fails, because the used trusted certificate in the sample is from www.digicert.com, while currently "example.com" uses SSL.com .

    You may try it with the SSL.com root:

    -----BEGIN CERTIFICATE-----
    MIICOjCCAcCgAwIBAgIQFAP1q/s3ixdAW+JDsqXRxDAKBggqhkjOPQQDAzBOMQsw
    CQYDVQQGEwJVUzEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMSUwIwYDVQQDDBxT
    U0wuY29tIFRMUyBFQ0MgUm9vdCBDQSAyMDIyMB4XDTIyMDgyNTE2MzM0OFoXDTQ2
    MDgxOTE2MzM0N1owTjELMAkGA1UEBhMCVVMxGDAWBgNVBAoMD1NTTCBDb3Jwb3Jh
    dGlvbjElMCMGA1UEAwwcU1NMLmNvbSBUTFMgRUNDIFJvb3QgQ0EgMjAyMjB2MBAG
    ByqGSM49AgEGBSuBBAAiA2IABEUpNXP6wrgjzhR9qLFNoFs27iosU8NgCTWyJGYm
    acCzldZdkkAZDsalE3D07xJRKF3nzL35PIXBz5SQySvOkkJYWWf9lCcQZIxPBLFN
    SeR7T5v15wj4A4j3p8OSSxlUgaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSME
    GDAWgBSJjy+j6CugFFR781a4Jl9nOAuc0DAdBgNVHQ4EFgQUiY8vo+groBRUe/NW
    uCZfZzgLnNAwDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMDA2gAMGUCMFXjIlbp
    15IkWE8elDIPDAI2wv2sdDJO4fscgIijzPvX6yv/N33w7deedWo1dlJF4AIxAMeN
    b0Igj762TVntd00pxCAgRWSGOlDGxK0tk/UYfXLtqc/ErFc2KAhl3zx5Zn6g6g==
    -----END CERTIFICATE-----

    but I don't know, if that works.

Children
No Data
Related