I am breaking into making my own IoT tech and am using an ESP8266 with C/C++. I have set up a program which allows me to toggle a relay using Google Assistant through gbridge.io. I have it subscribed using MQTT to gbridge which tells it when to toggle the switch. Unfortunately I am very new to dealing with network related things, so I this probably is worded incorrectly. It listens (i think is the right word) to port 1883. I am using this method as I don't want to open a port on my home router. By listening to port 1883, is there any way that my router is exposed or network vulnerable? This code comes from the Adafruit MQTT Library Examples.
#include <ESP8266WiFi.h>
#include "Adafruit_MQTT.h"
#include "Adafruit_MQTT_Client.h"
/************************* WiFi Access Point *********************************/
const char* WLAN_SSID = "SSID";
const char* WLAN_PASS = "password";
/************************* Adafruit.io Setup *********************************/
#define AIO_SERVER "mqtt.gbridge.io"
#define AIO_SERVERPORT 1883 // use 8883 for SSL
#define AIO_USERNAME "gbridge-username"
#define AIO_KEY "mqqt password"
/************ Global State (you don't need to change this!) ******************/
// Create an ESP8266 WiFiClient class to connect to the MQTT server.
WiFiClient client;
// or... use WiFiFlientSecure for SSL
//WiFiClientSecure client;
// Setup the MQTT client class by passing in the WiFi client and MQTT server and login details.
Adafruit_MQTT_Client mqtt(&client, AIO_SERVER, AIO_SERVERPORT, AIO_USERNAME, AIO_KEY);
/****************************** Feeds ***************************************/
// Setup a feed called 'photocell' for publishing.
// Notice MQTT paths for AIO follow the form: <username>/feeds/<feedname>
Adafruit_MQTT_Publish onoffset = Adafruit_MQTT_Publish(&mqtt,"on off set link");
// Setup a feed called 'onoff' for subscribing to changes.
Adafruit_MQTT_Subscribe onoffbutton = Adafruit_MQTT_Subscribe(&mqtt,"on off link");
Update August 2020:
gbridge has shutdown their servers
Port 1883 is commonly used for unsecured MQTT. This has nothing to do with your router or network being vulnerable. What it means is:
you can't be sure that the MQTT server you connected to is the one you meant to
an intermediate party can eavesdrop on your MQTT communication
When you run MQTT over SSL, SSL will verify that the connection is encrypted using a certificate belonging to the domain name that you were trying to connect to. The two ends will also encrypt all traffic so that an observing party will be unable to eavesdrop.
MQTT over SSL is commonly run on port 8883.
None of this compromises your network or endangers your router. It only affects the communication between the MQTT client and broker.
Your MQTT client is not listening on port 1883 - it's connecting to port 1883 on the broker. The broker is the one listening on port 1883 - that's why you don't have to open a port on your router.
In the code you quoted above, you'd need use WiFIClientSecure instead of WiFiClient. You'd also need to provide a certificate or fingerprint for the server you're connecting to. But that's a different question from the one you asked; if you need help with it that would belong in a separate post.
Related
I am facing a peculiar problem. The below code snippet connects to new WiFi network. No hard-coded ssid or password in the program. I am using AsyncWifiManager and AsyncWebServer modules. When I am connecting to my home WiFi router providing ssid and password in autoconnect portal, NodeMCU is getting connected and the server is working fine. But whenever I am changing the WiFi, connecting to my mobile phone hotspot, then server is not running, though I am getting local IP address in Serial Monitor.
#include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <ESPAsyncWiFiManager.h>
#include <FS.h>
#include <Wire.h>
AsyncWiFiManager wifiManager(&server,&dns);
// To clean previous settings. Use one time, then comment
// wifiManager.resetSettings();
// set custom static ip for portal
IPAddress staticIP(192,168,0,20); //ESP static ip
IPAddress gateway(192,168,0,1); //IP Address of your WiFi Router (Gateway)
IPAddress subnet(255,255,255,0); //Subnet mask
wifiManager.setSTAStaticIPConfig(staticIP, gateway, subnet);
// Open WiFi Setup portal
wifiManager.autoConnect();
Serial.println("Connecting to WiFi..");
// Print ESP32 Local IP Address
Serial.println(WiFi.localIP());
WiFi.begin();
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi..");
}
I am programming the NodeMCU board via Arduino IDE.
As your code uses fix parameters for IP/subnet/gateway you have to setup your different hotspots accordingly or you have the following options to choose from as you connect your ESP8266 server to different hotspots:
always being in the same network/subnetwork (all hotspots are part of a local network) you can use fix IP-addresses for all devices irrelevant of the hotspot you connect to
If you do not want to use above (=fix IP for all devices): Set the DHCP server to always give the same IP addresses to the NodeMCUs based on their MAC addresses.
You use mDNS and give the ESP8266 a fixed name and call via http://nyPreferredESP.local (allthough the IP varies) and use on your Android phone something like this APP
If you want to work with changing gateways (Devices not on the same net/subnet, access over the internet): This would require something a little more robust. Use a Dynamic DNS service along with a domain name. The Dynamic DNS will update your DNS records in almost real time if your gateway address changes. Example here
The complexity of the solution results from the factor always in the same network/subnet and a fixed gateway or everything (except MAC-address and name of the device are fix) and the rest may be variable. Read some basics about setting up a local network here
I want to write an app, that establishes direct TCP\IP connection between two devices over the internet.
I have a server to exchange IP addresses and ports, but is it enough to establish a connection?
How to handle cases, where both devices are on the one IP (connected to the same Wi-Fi hotspot)?
Also, I don't understand how open ports on the device could be accessible without port forwarding settings on hotspot? Is there any range of ports open for apps usage?
You are correct about port forwarding for most cases.
TCP/IP is OSI Layer 4 protocol. You need to be able to send data to the sever application with a known IP address and port number. Now when on the internet, this can get more complicated because you normally do not directly interface with the IP address that the rest of the internet reaches you at. This is your public IP address. The modem you have from your ISP likely implements a NAT
, which turns your private address into your public address. You modem will block all TCP SYN requests unless there is forwarding rule specifically for it.
This is just the typical case, you can also look into setting your modem up for DMZ mode and even implementing your own reverse proxy like nginx.
I have sim800 module ,i want to control relay from webserver so i need mqtt library and sample code for arduino uno please help to me,What is AT command for publish and subscribe the tag in sim800 using arduino uno
I think it is very unlikely that your SIM800 module will have an AT command for MQTT.
There are a couple of MQTT libraries for Arduino:
AdaFruit: https://github.com/adafruit/Adafruit_MQTT_Library
PubSubClient by Nick O'Leary: http://pubsubclient.knolleary.net/
Both of these libraries should work with any library than implements the Client interface. So it should be possible to create a TCP client that talks to the GSM module.
If the SIM800 supports the GSM library then that implements the Client interface:
https://www.arduino.cc/en/Reference/GSM
If you are using the hardware serial port in the Arduino, you might be better using a Leonardo than a Uno, because you can use the USB to programme the Arduino, and the hardware serial to talk to the GSM module.
MQTT Library for SIM800 GSM Modem is available at ElementzTechBlog, ElementzGithubRepository,ElementzOnlineCart
Functionalities:
Auto connect
Automatically connect to TCP and to MQTT server.
connect function
This function can be used to connect your client to MQTT broker.
Use only if you do not use Auto connect functionality.
Optionally you can use username, password, WILL topic and WILL Message.
OnConnect CallBack function
This call back function is called when MQTT connection is established.
You can call subscription and publish functions inside it (according to your need).
publish function
This function can be used to publish messages to different topics.
You can select QoS levels and RETAIN flag according to your need.
subscribe function
This function can be used to subscribe messages from different topics.
OnMessage CallBack function
This callback function is called when messages are received from subscribed topics
Topic, TopicLength, Message, MessageLength are the arguments of OnMessage callback function.
Inside this, you can write your custom code.
unsubscribe function
This function can be used to unsubscribe from a previously subscribed topic.
disconnect function
This function can be used to disconnect your client from MQTT broker.
Keep Alive
You can specify your KeepAlive duration while initializing.
Ping requests are sent and received automatically.
You can try using Paho Arduino client library. It features full fledged MQTT library with support to MQTT 3.1, MQTT 3.1.1 & SSL/TLS.
So I have been trying to create two GCDAsyncSocket's in my project, one (socket) that uploads a file to my server and the other (listenSocket) waits for another process from the server to communicate with it. In my ViewController I have initialized them in viewDidLoad method and setup delegate to self for both sockets.
socket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
listenSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
I then made the listenSocket start listening by
NSError *err = nil;
if (![listenSocket acceptOnPort:19920 error:&err]) {
NSLog(#"listenSocket failed to accept: %#", err);
}
I then made socket to connect to remote server and start uploading files.
The problem is that socket works fine and can upload and also read response from my server, but it seems that I can't access the accepting listenSocket by any way. Not by the other process on server, nor by using telnet or by typing the ip address and port number into browser. Why is this and how do I fix it?
Edit:
Here's what I am doing with my app:
I am working on an app that programs for Arduino on iPhone. Due to App Store policy the compiling and uploading process has to be on server, so I'm using socket to upload the code to server to get it compiled. In order to upload the compiled binaries to Arduino, I have to run avrdude which fortunately would accept an ip + port address instead of a usb connection as target. avrdude is implemented so that it connects to the address as a client, so I have to open a listening socket on my app.
I imagine your issue relates to your device not having a routable IP address from the outside world. I have assumed here that you are not testing on a local network with your server and phone both using this network via wifi/cable.
When you are on your device using a mobile network, it is assigned an IP address from the mobile operator. This address is more than likely an address which is part of their internal mobile network. When you connect outside of the mobile network to a server, the address the server sees for your device is not the address you see on the device. The addresses are mapped in transit as your IP packet passes through the various gateways while on its way to the server. Thus when you server sees a connection requested on a listen socket, it has a reply address which when used allows the reply to traverse back to your device.
A similar issue occurs when your device is on WiFi behind a NAT router. Connections made outgoing are seen by the router and it changes the from IP address to be that of the router. Since it sees the start of the conversation, it know where return packets with a given port and sequencing should be routed. However if somebody wants to connect to your device from outside, you have to have set up port forwarding on the router for a known port telling it where to send connection packets.
So applying this to your situation:
Outgoing Works (Why):
Your outgoing socket works, because you are connecting to an externally visible IP. When you connect, the network knows exactly where the packet has to go and the reply address is provided in the packet by the network.
Incoming Does Not Work (Why):
Your listen socket will not be working because the address you are sending to does not exist on the open internet. To make a connection from the server or anywhere else to your device you would need an IP which has a routing mapped through to your device. If the device is on a mobile network, you need an external IP for the mobile network which maps to your device. If the device was behind a NAT router, you would need port forwarding set up.
Solution:
Unfortunately, there is no easy solution as your need an IP address for your device in the outside world. Much depends on your use case which you have not mentioned. You either need an external IP which is reliable or you need to use an intermediate server to handle messaging or you need to change your approach and have the device poll every so often for information.
This is a problem which has existed for a long time and is why peer to peer companies have smart algoithms for connecting peer to peer services which use clever techniques like hole punching to connect devices.
IMHO I would move to a model where your device always initiates the connection if you can.
iam trying to test my application to public network so i will use my own ip as server , i already did port forward in my router settings, " my goal is reach this application to computers out side my network " but i only can receive data i cannot send from my main ip to other computer ,, i have disabled my firewall also the other pc firewall is this problem of my router ? or my network ?
i tried to disable router firewall but still same problem is there other things i have to check ? also i set my indtCP server binding to 0.0.0.0 to reach all network.
You should be able to send, but only after the client connects to your server.
When a client connects you should handle OnConnect event of your TIdTCPServer component. AThread parameter represent your client. You can respond to it by, for example:
AThread.Connection.Write ('Hi!');
You can disconnect the client by:
AThread.Connection.Disconnect;
Of course, many clients can be connected at the same time. In this case, you should keep track on all (dis)connected clients.