andr13 / ESP32-Web-WireGuard

ESP32 Wireguard Hall Sensor
BSD 2-Clause "Simplified" License
11 stars 2 forks source link

Can't see webpage by WireGuard ip #1

Open webportpl opened 1 year ago

webportpl commented 1 year ago

Server is external in internet. Can't see webpage by WireGuard ip for example when i have client WireGuard from laptop ... what i do wrong? Can;t see hall webserver in interal WireGuard tunnel

andr13 commented 1 year ago

Hi, @webportpl 😊

Are you experiencing the problem only when connecting via Wireguard? Can you please share your Wireguard server configuration? I'm interested in options like preshared_key and keepalive.

Also, as a Wireguard VPN server, you can use the YIoT Portal. That's what I used for my tests. At the moment the service is absolutely free, and does not require any personal information from you, such as phone number or credit card.

samkhan2050 commented 8 months ago

Hi @andr13 I am facing a similar issue. I will explain to you my scenario in detail as below. I have setup a Wireguard Server on Google cloud platform on a Ubuntu OS. I have setup 2 clients, one on my android mobile phone with a wireguard App and another my ESP32 (M5Tough). I am able to connect both the phone and ESP32 device and i can see the latest handshake time on my wireguard server as well. The Local IP of the server i have set is 10.0.0.1, while the local IPs of the client phone is 10.0.0.2 and ESP32 is 10.0.0.4. When i open my browser on the phone and type in 10.0.0.4, it shows server timeout. I am not sure what am i doing wrong. Below i have the codes and file for your further understanding: I have hidden some sensitive information on a public forum. Please note that i am not a software engineer, i just learned through blogs, forums and chatGPT, so i might be making some very silly mistake :)

Output for Wireguard server command: "sudo wg":

interface: wg0
  public key: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
  private key: (hidden)
  listening port: 51820

peer: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
  endpoint: 70.29.71.140:51820
  allowed ips: 10.0.0.4/32
  latest handshake: 2 minutes, 9 seconds ago
  transfer: 21.67 KiB received, 6.42 KiB sent

peer: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
  endpoint: 70.29.71.140:57643
  allowed ips: 10.0.0.2/32
  latest handshake: 54 minutes, 52 seconds ago
  transfer: 148 B received, 124 B sent

Wire Guard Server wg0.conf file:

[Interface]
Address = 10.0.0.1/24
SaveConfig = true
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -t nat -A POSTROUTING -o 34.122>
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -t nat -D POSTROUTING -o 34.1>
ListenPort = 51820
PrivateKey = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX  // Hidden for privacy Private Key for the WG Server

[Peer] // Android Phone info
PublicKey = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX  // Hidden for privacy Public Key for the Android phone client 
AllowedIPs = 10.0.0.2/32
Endpoint = 174.95.18.117:49393

[Peer] // ESP32 info
PublicKey = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX  // Hidden for privacy Public Key for the ESP32 client 
AllowedIPs = 10.0.0.4/32
Endpoint = 174.95.18.117:51820

My config file which i imported to my android phone is as below:

[Interface]
PrivateKey = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX  // Hidden for privacy Clients Private Key
Address = 10.0.0.1/24
DNS = 1.1.1.1, 1.0.0.1
MTU = 1360
[Peer]
PublicKey = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX  // Hidden for privacy, Public Key for the WG Server
AllowedIPs = 0.0.0.0/0
Endpoint = XX.XXX.XXX.XXX:51820 // Hidden for privacy

My ESP32 code is as below:

// Include libraries
#include <WireGuard-ESP32.h>
#include <WiFi.h>
#include <WebServer.h>
#include <M5Unified.h>

// WiFi settings
const char ssid[] = "XXXXX";
const char password[] = "XXXXXX";

// WireGuard settings
IPAddress local_ip(10, 0, 0, 4);                                           // IP address of the local interface
const char private_key[] = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; // Private key of the local interface
const char endpoint_address[] = "XX.XXX.XXX.XXX";                          // Address of the endpoint peer
const char public_key[] = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";  // Public key of the endpoint peer
uint16_t endpoint_port = 51820; // Port of the endpoint peer

// WireGuard class instance
static WireGuard wg;

// Set the server port
WebServer server(80);
void handleHall();
void handleRoot();

void setup()
{
  // Setting up a serial port for debugging
  Serial.begin(115200);
  M5.begin();
  // Connecting to a WiFi AP
  WiFi.begin(ssid, password);

  // Waiting until we connect to WiFi
  while (!WiFi.isConnected())
  {
    delay(1000);
    Serial.println("Connecting to WiFi...");
  }

  // Print the IP address in the local network
  Serial.print("Local IP: ");
  Serial.println(WiFi.localIP());
  M5.Lcd.setTextSize(3);
  M5.Lcd.setCursor(5, 5);
  M5.Lcd.print(WiFi.localIP());

  // Print the IP address in the WireGuard network
  Serial.print("WireGuard IP: ");
  Serial.println(local_ip.toString());

  // Handling requests to the root path
  server.on("/", handleRoot);

  // Handling requests to the readHall path
  server.on("/readHall", handleHall);

  // Starting a web server
  server.begin();
  M5.Lcd.setTextSize(3);
  M5.Lcd.setCursor(5, 40);
  M5.Lcd.print("WEBSERVER STARTED");

  // Synchronize system time via NTP
  configTime(9 * 60 * 60, 0, "time.google.com", "ntp.nict.jp", "ntp.jst.mfeed.ad.jp");

  // Starting the WireGuard interface
  Serial.println("Initializing WG interface...");
  if (wg.begin(local_ip, private_key, endpoint_address, public_key, endpoint_port))
  {
    Serial.println("OK");
    M5.Lcd.setTextSize(3);
    M5.Lcd.setCursor(5, 75);
    M5.Lcd.print("WIREGUARD STARTED");
    }
  else
  {
    Serial.println("FAIL");
  }
  M5.update();
}

void loop()
{
  wg.is_initialized();
  // Client service
  server.handleClient();

}

void handleHall()
{
  // Read the value of the built-in Hall sensor
  int hall = hallRead();

  // Get current time in seconds
  unsigned long time = millis() / 1000;

  // Format JSON string with data
  String json = "{\"hall\": " + String(hall) + ", \"time\": " + String(time) + "}";

  // Send JSON response
  server.send(200, "application/json", json);
}

void handleRoot()
{
  // Send HTML page with an AJAX script
  server.send(200, "text/html",
              "<!DOCTYPE html>\
  <html>\
    <head>\
      <meta charset=\"UTF-8\">\
      <style>\
        { box-sizing: border-box; margin: 0; padding: 0; }\
        body {\
          background-color: #333;\
          color: white; font-family: \"Lucida Console\", \"Courier New\", monospace;\
          display: flex; flex-direction: column;\
          align-items: center; justify-content: center;\
          height: 100vh;\
        }\
        h1 {\
          font-size: 36px;\
          margin-bottom: 20px;\
        }\
        h2 { margin-bottom: 20px; }\
        canvas { border: 2px solid white; border-radius: 15px; }\
      </style>\
    </head>\
    <body>\
      <h1>ESP32 Web Server with Wireguard</h1>\
      <h2>Hall Sensor: <span id=\"hallText\"></span></h2>\
      <canvas id=\"canvas\" width=\"400\" height=\"300\"></canvas>\
      <script>\
        var ctx = document.getElementById(\"canvas\").getContext(\"2d\");\
        var data = [];\
        \
        var maxData = 50;\
        var margin = 20;\
        var width = ctx.canvas.width - margin * 2;\
        var height = ctx.canvas.height - margin * 2;\
        var xStep = width / maxData;\
        var yMin = -100;\
        var yMax = 100;\
        var yScale = height / (yMax - yMin);\
        \
        function drawGrid() {\
          ctx.strokeStyle = \"#3A3A3A\";\
          ctx.lineWidth = 1;\
          ctx.beginPath();\
          \
          for (var x = margin; x <= ctx.canvas.width - margin; x += xStep) {\
            ctx.moveTo(x, margin);\
            ctx.lineTo(x, ctx.canvas.height - margin);\
          }\
          \
          for (var y = margin; y <= ctx.canvas.height - margin; y += yScale) {\
            ctx.moveTo(margin, y);\
            ctx.lineTo(ctx.canvas.width - margin, y);\
          }\
          \
          ctx.stroke();\
          ctx.strokeStyle = \"white\";\
          ctx.lineWidth = 2;\
          ctx.beginPath();\
          var y = margin + height - (0 - yMin) * yScale;ctx.moveTo(margin, y);\
          ctx.lineTo(ctx.canvas.width - margin, y);\
          ctx.stroke();\
        }\
        \
        function drawLine() {\
          ctx.strokeStyle = \"#2196F3\";\
          ctx.lineWidth = 2;\
          ctx.beginPath();\
          \
          for (var i = 0; i < data.length; i++) {\
            var x = margin + i * xStep;\
            var y = margin + height - (data[i] - yMin) * yScale;\
            if (i == 0) {\
              ctx.moveTo(x, y);\
            } else {\
              ctx.lineTo(x, y);\
            }\
          }\
          \
          ctx.stroke();\
        }\
        \
        function getData() {\
          var xhttp = new XMLHttpRequest();\
          xhttp.onreadystatechange = function() {\
            if (this.readyState == 4 && this.status == 200) {\
              var response = JSON.parse(this.responseText);\
              var hall = response.hall;\
              document.getElementById(\"hallText\").innerHTML = hall;\
              data.push(hall);\
              if (data.length > maxData) {\
                data.shift();\
              }\
              ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);\
              drawGrid();\
              drawLine();\
            }\
          };\
          xhttp.open(\"GET\", \"readHall\", true);\
          xhttp.send();\
        }\
        \
        setInterval(getData, 500);\
      </script>\
    </body>\
  </html>");
}
samkhan2050 commented 8 months ago

After i sent this msg i consulted ChatGPT one more time and it helped me figure the issue. Firstly i had programmed the android client IP address wrong. It should have been Address = 10.0.0.2/24 instead of Address = 10.0.0.1/24. Secondly, my post up and post down should have ens4 instead of the IP address of the server. So now, i changed it and its working perfectly. Just updating so someone else can benefit if they have this issue.

andr13 commented 8 months ago

Hi, @samkhan2050 👋

Glad to see that you managed to solve your problem! Also thank you for sharing your solution here. Always happy to collaborate)

Let me also ask you one question: did you use YIoT Portal and its services in your tests? If yes, how would you describe the experience?

samkhan2050 commented 8 months ago

Hi @andr13 I checked the link above for YIOT but i didnt understand how to setup a VPN server, when i clicked create VPN it showed an error "Cannot start service". Then i clicked on download VPN client, it took me to Node Red, which i didnt know how to work on. And since i had spent so much time setting up a Wireguard VPN on Google cloud platform, that i preferred solving my issues there only instead of learning something new at this point. But i can give it a try some other time if you can explain how to setup a VPN there and use the public and private keys to connect to it using my ESP32. Just for your information, i have successfully created a small android app in flutter which can connect to the same wireguard server without the need to download wireguard VPN app. This way i can access the ESP32 directly from the app. Additionally, it will prevent exposing the private and public keys to the user who otherwise can see it in the wireguard app. Anyway, its just under development and i think would need a lot more work on security measures etc.

samkhan2050 commented 8 months ago

Hi @andr13, One more thing, i just noticed that when i initially connect my ESP32 to the wireguard server, it connects fine, then if i restart my ESP32 (switch off and switch the ESP32)it reconnects again as well. But if i switch off the ESP32 for a longer duration (around more than an an hour) and then switch it on later, it doesnt reconnect. In this case, i have to restart the wireguard server and then my ESP32 reconnects. What could be the reason for this behaviour?

andr13 commented 8 months ago

But i can give it a try some other time if you can explain how to setup a VPN there and use the public and private keys to connect to it using my ESP32.

Hi @samkhan2050,

I'm glad to hear that you were able to solve your problem with GCP. I'm always happy to collaborate on projects like this)

Regarding your questions about YIoT Portal, I understand that you had some trouble setting up a VPN server. I'd like to encourage you to give it another try, just follow my instructions in the video I've attached below. Also, the documentation is very detailed, and I'm always available to help if you get stuck!

Here are some resources that might be helpful: 1. My video on how to use this project with YIoT Portal 2. YIoT Portal documentation on personal VPN server I'm also happy to answer any questions you have in a direct message.

Thanks for your interest in YIoT Portal! I hope you'll give it another try.

Best, Andrii

P.S. If you do manage to get the VPN server set up, I'd love to hear about your experience. 😊

andr13 commented 8 months ago

Hi @andr13, One more thing, i just noticed that when i initially connect my ESP32 to the wireguard server, it connects fine, then if i restart my ESP32 (switch off and switch the ESP32)it reconnects again as well. But if i switch off the ESP32 for a longer duration (around more than an an hour) and then switch it on later, it doesnt reconnect. In this case, i have to restart the wireguard server and then my ESP32 reconnects. What could be the reason for this behaviour?

Interesting behavior indeed... I believe the problem could be in the WireGuard-ESP32-Arduino library, or on the server side.

Either way, this kind of bug requires long term testing. I may be able to fix this problem in the future!

samkhan2050 commented 8 months ago

Hi @andr13, One more thing, i just noticed that when i initially connect my ESP32 to the wireguard server, it connects fine, then if i restart my ESP32 (switch off and switch the ESP32)it reconnects again as well. But if i switch off the ESP32 for a longer duration (around more than an an hour) and then switch it on later, it doesnt reconnect. In this case, i have to restart the wireguard server and then my ESP32 reconnects. What could be the reason for this behaviour?

Interesting behavior indeed... I believe the problem could be in the WireGuard-ESP32-Arduino library, or on the server side.

Either way, this kind of bug requires long term testing. I may be able to fix this problem in the future!

I edited the Wireguard server wg0.conf file with the ESP32 client settings to have PersistentKeepalive = 25. And switched off the ESP32 for 7 hours. Switched it on now and it connected without problem. Will test it for longer durations, but i think this solved the issue FINGERS CROSSED. Lets see.

samkhan2050 commented 8 months ago

But i can give it a try some other time if you can explain how to setup a VPN there and use the public and private keys to connect to it using my ESP32.

Hi @samkhan2050,

I'm glad to hear that you were able to solve your problem with GCP. I'm always happy to collaborate on projects like this)

Regarding your questions about YIoT Portal, I understand that you had some trouble setting up a VPN server. I'd like to encourage you to give it another try, just follow my instructions in the video I've attached below. Also, the documentation is very detailed, and I'm always available to help if you get stuck!

Here are some resources that might be helpful: 1. My video on how to use this project with YIoT Portal 2. YIoT Portal documentation on personal VPN server I'm also happy to answer any questions you have in a direct message.

Thanks for your interest in YIoT Portal! I hope you'll give it another try.

Best, Andrii

P.S. If you do manage to get the VPN server set up, I'd love to hear about your experience. 😊

Sure @andr13, I will work on it and give you my updates after a few days. Need to complete this project for a upcoming demo in December!!

andr13 commented 8 months ago

Hi, @samkhan2050 👋🏻

Just wondering if there are any updates on the project we talked about last week?