Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WifiClientSecure connect(IPAddress ip, hostport) not working !! #1487

Closed
iamneo2416 opened this issue Jun 12, 2018 · 13 comments
Closed

WifiClientSecure connect(IPAddress ip, hostport) not working !! #1487

iamneo2416 opened this issue Jun 12, 2018 · 13 comments

Comments

@iamneo2416
Copy link

iamneo2416 commented Jun 12, 2018

Hi all, please help.

All WifiClientSecure searched on internet sample code use ** "host name" ** in connect( ), but no sample use IPAddress ipv4 to do connect( ). Recently, I built a web server(apache2) + php + mysql + phpMyAdmin (ubuntu 16.04 apache2 w/TSL). I can use https://192.168.1.210/phpMyAdmin to login to mysql web management page successfully, BUT I cannot use following code to do connect. PLEASE HELP. Can anyone give me a working sample? I can also use command line to do
C:> telnet 192.168.1.210 443 <== that also works. means 443 is listening.

Did I miss something here or I miss use connect(ipv4, hostport) ??

P.S. I followed exactly the same steps to built this web server.
https://www.digitalocean.com/community/tutorials/how-to-create-a-self-signed-ssl-certificate-for-apache-in-ubuntu-16-04

======================================

const char* host = "192.168.1.210";
IPAddress host_ip(ipStrToNum(host));
Wificlientsecure client;

wifi.begin(user_name, passwd);
if( !client.connect(host_ip, 443))  //<== this line always return failed ! (this line)
{
     Serial.println(">>> connection failed");
     return;
}
.....
...

"this line" API is in here line(88) ,but not working ~
[https://github.com/espressif/arduino-esp32/blob/master/libraries/WiFiClientSecure/src/WiFiClientSecure.cpp](https://github.com/espressif/arduino-esp32/blob/master/libraries/WiFiClientSecure/src/WiFiClientSecure.cpp)

Therefore, connect with ipv4 should work, but doesn't !! always return fail. cannot execute following code after this line.

// I found this utility function working great to transfer char ipv4 to uint32.
uint32_t ipStrToNum(const char* ipStr)
{
  const int SIZE_OF_NUMS = 4;
  union
  {
    uint8_t bytes[SIZE_OF_NUMS];  // IPv4 address
    uint32_t dword;
  } _address;
  _address.dword = 0; // clear return

  int i = 0;
  uint8_t num = 0; // start with 0
  while ((*ipStr) != '\0')
  {
    // while not end of string
    if ((*ipStr == '.') || (*ipStr == ','))
    {
      // store num and move on to next position
      _address.bytes[i++] = num;
      num = 0;
      if (i>=SIZE_OF_NUMS)
      {
        break; // filled array
      }
    }
    else
    {  
      if (*ipStr != ' ')
      {      // skip blanks
        num = (num << 3) + (num << 1); // *10 = *8+*2
        num = num +  (*ipStr - '0');
      }  
    }  
    ipStr++;
  }  
  if (i<SIZE_OF_NUMS)
  {
    // store last num
    _address.bytes[i++] = num;
  }
  return _address.dword; 
}  
@iamneo2416
Copy link
Author

iamneo2416 commented Jun 12, 2018

Here is my actual file attached. Please someone to help me. I need to create a web server within INTRANET not in INTERNET. Therefore, I use private IP stack class c (192.168.1.x)

WiFiClientSecureTest.txt

@iamneo2416
Copy link
Author

iamneo2416 commented Jun 12, 2018

serial.println log here.

.....
WiFi connected
IP address:
192.168.1.132
connecting to 192.168.1.210
">>> connection failed"

@iamneo2416
Copy link
Author

iamneo2416 commented Jun 12, 2018

I tried 5 different samples original from host name based like "google.com" , "api.github.com" , .... all working fine with connect(host_name, 443), but once I changed to connect( IPAddress, 443) and all get fails ! Can it be bug when your team push BearSSL into this git ? Or, no one has time to chech for ipv4 connect() ever ?

Did I miss something here or I miss use connect(ipv4, hostport) ??

@iamneo2416
Copy link
Author

iamneo2416 commented Jun 12, 2018

here is another sample code I tried. I only add ipStrToNum function() and change host to host_ipv4 and put that into connect(ipv4, 443).

=============================

#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>

const char* ssid = "mywifissid";
const char* password = "password";

//const char* host = "api.github.com";  <== use this to connect. it works !
const char* host = "192.168.1.210";  <== change to this. it does not work !
const int httpsPort = 443;

// Use web browser to view and copy
// SHA1 fingerprint of the certificate
const char* fingerprint = "CF 05 98 89 CA FF 8E D8 5E 5C E0 C2 E4 F7 E6 C3 C7 50 DD 5C";

void setup()
{
  Serial.begin(115200);
  Serial.println();
  Serial.print("connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());

  // Use WiFiClientSecure class to create TLS connection
  WiFiClientSecure client;
 
  IPAddress host_ipv4(ipStrToNum(host));
  Serial.print("connecting to ");
  Serial.println(host_ipv4);
  
  if (!client.connect(host_ipv4, httpsPort))
  {
    Serial.println(">>> connection failed");
    return;
  }

  if (client.verify(fingerprint, host))
  {
    Serial.println("certificate matches");
  }
  else
  {
    Serial.println("certificate doesn't match");
  }

  String url = "/repos/esp8266/Arduino/commits/esp8266/status";
  Serial.print("requesting URL: ");
  Serial.println(url);

  client.print(String("GET ") + url + " HTTP/1.1\r\n" +
               "Host: " + host + "\r\n" +
               "User-Agent: BuildFailureDetectorESP8266\r\n" +
               "Connection: close\r\n\r\n");

  Serial.println("request sent");
  while (client.connected())
  {
    String line = client.readStringUntil('\n');
    if (line == "\r")
    {
      Serial.println("headers received");
      break;
    }
  }
  String line = client.readStringUntil('\n');
  if (line.startsWith("{\"state\":\"success\""))
  {
    Serial.println("esp8266/Arduino CI successfull!");
  }
  else
  {
    Serial.println("esp8266/Arduino CI has failed");
  }
  Serial.println("reply was:");
  Serial.println("==========");
  Serial.println(line);
  Serial.println("==========");
  Serial.println("closing connection");
}

uint32_t ipStrToNum(const char* ipStr)
{
  const int SIZE_OF_NUMS = 4;
  union
  {
    uint8_t bytes[SIZE_OF_NUMS];  // IPv4 address
    uint32_t dword;
  } _address;
  _address.dword = 0; // clear return

  int i = 0;
  uint8_t num = 0; // start with 0
  while ((*ipStr) != '\0')
  {
    // while not end of string
    if ((*ipStr == '.') || (*ipStr == ','))
    {
      // store num and move on to next position
      _address.bytes[i++] = num;
      num = 0;
      if (i>=SIZE_OF_NUMS)
      {
        break; // filled array
      }
    }
    else
    {  
      if (*ipStr != ' ')
      {      // skip blanks
        num = (num << 3) + (num << 1); // *10 = *8+*2
        num = num +  (*ipStr - '0');
      }  
    }  
    ipStr++;
  }  
  if (i<SIZE_OF_NUMS)
  {
    // store last num
    _address.bytes[i++] = num;
  }
  return _address.dword; 
}  

void loop() {
}

=============================

@lbernstone
Copy link
Contributor

lbernstone commented Jun 12, 2018

Wow. Way to overcomplicate things. Set the IPAddress like so:

IPAddress host_ip = {192,168,1,210};

Then, set Core Debug Level to Verbose in the Tools menu.

#include <WiFiClientSecure.h>
void setup() {
  WiFi.begin();
  while (WiFi.status() != WL_CONNECTED) delay(500);
  delay(500);
  IPAddress host = {172,217,12,4}; //www.google.com
  WiFiClientSecure client;
  client.connect(host, 443);
}
void loop() {}

@iamneo2416
Copy link
Author

iamneo2416 commented Jun 13, 2018

@lbernstone

Can you help me to see what's going on when I switch from google.com back to 192.168.1.210, it's still not working !!

I followed link below to set up my server. Not change anything. It must be server problem, but I can use browser to use https://192.168.1.210/phpMyAdmin securly login and also see warning sign from browser ! I also use dos command line to check 443 port

C:> telnet 192.168.1.210 443 <== that works. means 443 port is listening. I just don't know why a single TCP connect is so difficult ! telnet also use TCP, browser use TCP, and so is WiFiClientSecure.

Did I miss something or any step here ?? Or, I should not use this one tutorial for building my web server ? Or, should I use CA certificate to load like setCA. Any working sample code that can do ca ? Why google.com does not ask me for a .cert ?? How can I do that without pre-load a ca to my test program?

https://www.digitalocean.com/community/tutorials/how-to-create-a-self-signed-ssl-certificate-for-apache-in-ubuntu-16-04

=======================


#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>

String wifi = "hify";
String pass = "12345678";
void setup()
{
  Serial.begin(115200);
  
  WiFi.begin(wifi.c_str(), pass.c_str());
  while (WiFi.status() != WL_CONNECTED) { Serial.print("."); delay(500); }
  delay(500);
  //IPAddress host = {172,217,12,4}; //www.google.com; this working !
  IPAddress host = {192,168,1,210}; //<=== this NOT working !
  WiFiClientSecure client;
  if(!client.connect(host, 443))
  {
    Serial.println("not connect !!");
    return;
  }
  Serial.println("WiFiClientSecure connected !!");
}
void loop() {}

=======================

LOG here. Apparently, handshake fail at very first step. so, now the question is how can I build a self-signed SSL/TSL web server ? Can you help me with that ?

**

connected with hify channel 1
dhcp client start...
....ip:192.168.1.132,mask:255.255.255.0,gw:192.168.1.1
State: sending Client Hello (1)
Alert: handshake failure
Error: SSL error 40
Alert: unexpected message
Error: SSL error 40
Alert: close notify
not connect !!
pm open,type:2 0

=============

**

@lbernstone
Copy link
Contributor

Google will be a much better resource than me for this. wget -d is a much better testing tool than a browser, which will hide lots of errors from you.

@iamneo2416
Copy link
Author

DEBUG output created by Wget 1.17.1 on linux-gnu.

Reading HSTS entries from /root/.wget-hsts
URI encoding = aUTF-8a
--2018-06-14 18:58:55--  http:https://localhost/
Resolving localhost (localhost)... ::1, 127.0.0.1
Caching localhost => ::1 127.0.0.1
Connecting to localhost (localhost)|::1|:80... connected.
Created socket 3.
Releasing 0x000055fed6214610 (new refcount 1).

---request begin---
GET / HTTP/1.1
User-Agent: Wget/1.17.1 (linux-gnu)
Accept: */*
Accept-Encoding: identity
Host: localhost
Connection: Keep-Alive

---request end---
HTTP request sent, awaiting response...
---response begin---
HTTP/1.1 302 Found
Date: Thu, 14 Jun 2018 10:58:55 GMT
Server: Apache/2.4.18 (Ubuntu)
Strict-Transport-Security: max-age=63072000; includeSubdomains
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
Location: https://192.168.1.210/
Content-Length: 281
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html; charset=iso-8859-1

---response end---
302 Found
Registered socket 3 for persistent reuse.
Parsed Strict-Transport-Security max-age = 63072000, includeSubDomains = true
Updated HSTS host: localhost:80 (max-age: 63072000, includeSubdomains: true)
URI content encoding = aiso-8859-1a
Location: https://192.168.1.210/ [following]
Skipping 281 bytes of body: [<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>302 Found</title>
</head><body>
<h1>Found</h1>
<p>The document has moved <a href="https://192.168.1.210/">here</a>.</p>
<hr>
<address>Apache/2.4.18 (Ubuntu) Server at localhost Port 80</address>
</body></html>
] done.
URI content encoding = None
--2018-06-14 18:58:55--  https://192.168.1.210/
Connecting to 192.168.1.210:443... connected.
Created socket 4.
Releasing 0x000055fed6235ff0 (new refcount 0).
Deleting unused 0x000055fed6235ff0.
Initiating SSL handshake.
Handshake successful; connected socket 4 to SSL handle 0x000055fed6236080
certificate:
  subject: [email protected],CN=192.168.1.210,OU=MIS,O=BakeMe CO.,L=Taipei,ST=Singaphore,C=SP
  issuer:  [email protected],CN=192.168.1.210,OU=MIS,O=BakeMe CO.,L=Taipei,ST=Singaphore,C=SP
ERROR: cannot verify 192.168.1.210's certificate, issued by [email protected],CN=192.168.1.210,OU=MIS,O=BakeMe CO.,L=Taipei,ST=Singaphore,C=SPa:
  Self-signed certificate encountered.
To connect to 192.168.1.210 insecurely, use `--no-check-certificate'.
Closed 4/SSL 0x000055fed6236080
Saving HSTS entries to /root/.wget-hsts

@iamneo2416
Copy link
Author

iamneo2416 commented Jun 14, 2018

what does that mean "The document has moved "https://192.168.1.210/" ??

Should I need to add some other service for this Virtual Machine (web server) ?
Did you find anything here? for logger ?

I saw connect to 443 is success, and later check self-signed certificate with failed ! so, does that means that I need to put certificate in sketch and feed that to WiFiClientSecure for client initialization ?

If yes, how ? can you show me how to feed certificate to sketch ?

@copercini
Copy link
Contributor

@iamneo2416 please report this issue on ESP8266 forum, here is for ESP32

@brnyza
Copy link

brnyza commented May 13, 2019

Just include in your code:
client.setInsecure();

@nospam2k
Copy link

nospam2k commented Feb 2, 2020

No, you can't. setinsecure() is ESP8266 not ESP32

@LucaMannella
Copy link

Your application is trying to verify the certificate through a Certification Authority but, due to the fact that is self-signed, this operation fails.
You have to avoid this verification for having a positive answer from the web server.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants