Proper way to connect to IOT devices (UDP or ICMP) - udp

What is the proper way to connect an app to a device? At the moment, I have a raspberry pi 3 that controls something about electricity and an iPhone app I created. Every time the app goes to foreground, it sends a UDP broadcast message, when the app receives a response from the raspberry pi, it uses that IP address (in the IP header) to consume the web services I created in the hub. This UDP process is done all the time you run the app. Is this what IOT devices usually do? I assume the raspberry pi IP will change sooner or later.
A colleague of mine told me another way: After the first time I get the IP address, instead of using UDP broadcast messages every time the app runs, use ICMP to ping the previously saved IP address to see if it is responding. In that case, I use the web services with that IP address, otherwise, use the UPD broadcast message again.
I don't see the point of that. Basically because the system is not faster using ICMP. (a UDP request is more or less as fast as an ICMP request). Moreover, maybe, another device started using that IP address now (like a smart TV or a smart plug) and for that reason, it is not going to reply to the network requests sent by the app. In that case, the app cannot recover, because it thinks it is already connected to the proper device. As far as I understand, ICMP is a protocol use for diagnosis, not for devices discovery.
What do you think? What's the process used by devices like Alexa, Philips Hue, Smart plugs... to solve the problem of discovering the devices by their apps?
It seems Philips HUE is using SSDP, which under the hood uses a UDP broadcast message. Is it used every time you run the app to discover the IP address? (I am going to check this later with wireshark)
Thanks for suggestions.

You can enable the hostname of your Raspberry Pi to be accessible on your local network through:
http://raspberrypi.local
To enable it, you need to install Bonjour support on your Raspberry Pi by installing the Avahi mDNS daemon (implements Apple's Zeroconf architecture):
$ sudo apt-get install avahi-daemon
Update boot startup:
$ sudo insserv avahi-daemon
Restart to apply the new configuration:
$ sudo /etc/init.d/avahi-daemon restart

Related

Why would IP masquerading fix problematic WebRTC connection?

I'm working with a WebRTC stack that consists of a (firewall-enabled) embedded Linux device, an iOS mobile app, and self-maintained signaling, STUN, and TURN servers.
In 99% of network configurations, the setup works just fine. However, when the embedded Linux device is connected to a Verizon Jetpack (4G LTE), the device cannot establish a WebRTC connection with the mobile app (regardless of whether the mobile phone is connected to the Jetpack or some other network).
In an effort to debug, I took down the entire firewall on both IPv4 and IPv6, but it made no difference.
Then, I kind of randomly discovered that if I add a masquerading post-routing IPv4 rule to the device's NAT table, it starts working! Specifically, this is the iptables command that I used:
$ sudo iptables -t nat -A POSTROUTING -o wlan0 -j MASQUERADE
Why would this rule get the WebRTC connection working? And is there a more proper way to achieve the same result? The rule above seems too liberal.
I found this question because I was also experiencing a WebRTC ICE timeout when trying to connect to a device on the Jetpack's network. I don't know anything about iptables or firewall/DNS/NAT configurations, but your discovery gave me a clue that it must be some settings in the MiFi itself.
Looking at http://my.jetpack (the Jetpacks web config page/app/thing) I discovered a setting that was labelled something like "Enable passthrough VPN" and it was defaulted to true/on. Toggling that to false/off appears to have fixed the connection issue for me.
I'm not 100% sure this is the "real" issue since it seems like two devices on the same VPN should be able to connect. Hopefully it gives you a little bit of a clue in your own search.

How to scan network for devices, using C Obj C or Swift

I have a server running on a Raspberry Pi and a client running on my Mac and iPhone (soon Apple Watch). I would like to connect to my server automatically without finding the Raspberry pi's Ip-address.
Is there a way to lookup all the devices on the network, and select by Mac-address, name or something else? I know that the first 3 bytes of the mac-address is the same for all Pies. (B8:27:EB) Maby i can use that information.
I have been looking for a solution for this issue a while but i can't seem to find one.
Zeroconf (aka Bonjour)
IMO, the best way to do this is to have your Raspberry Pi advertise itself on the network using Zeroconf (aka. Bonjour).
On the Raspberry Pi, install avahi-daemon and configure it to advertise whichever service you'd like to connect to connect to, for example, if you're connecting via SSH, you'll need to do something like this.
In Cocoa, you can use NSNetServiceBrowser to find the advertised service.
Possible MAC Address solution
Alternatively, if Avahi-daemon is not an option, you may be able to use the MAC address. I will not go into the specifics in Objective-C, just a high-level overview using the command-line.
In terminal, type ping 255.255.255.255. You will get back ping packets from every device on the local network. For each IP address, send an individual ping e.g. ping -c 1 192.168.x.x. Then, type arp -a. You will see the MAC address for each IP on the local network. From here, you can perhaps use your MAC address filter to find Raspberry Pis.
Why does this work? Well, the first command ping 255.255.255.255 sends a ping in an IP packet to the 'broadcast' address, which means all machines on the local network respond. When you ping the individual IP addresses, the low-level networking stack uses ARP to find the MAC address of the IP to directly send a ping to it. In doing so, the ARP tables on the local machine are updated with the cached values.
Maybe you can use this method in your app to discover local Raspberry Pis.

How to detect all devices in a LAN?

I want to detect all devices in a LAN which have IP: 10.x.x.x Mask: 255.0.0.0.
I first wrote a synchronous ping program to ping IPs one by one, but it's tooooo slow.
Therefore I improved it by using asynchronous ping, then it's much faster.
Now I can use it to detect 10.x.0~255.0~255 in an acceptable time.
But it still use tooooooooooooo long time to detect all the IPs 10.0~255.0~255.0~255.
Is there any method/protocol that can just broadcast one message and let all devices in a LAN to respond, so I can detect all the devices?
(either Ethernet broadcast or UDP/IP broadcast or any other broadcast.)
(I've researched ARP & ICMP but haven't find suitable methods.)
Or any other method even don't need broadcast?
I just need to detect all the devices, any method is OK.
Not sure if it's what you are looking for but you can go in command prompt and run the command:
arp -a
I recommend "Angry IP Scanner" http://angryip.org/
It is fast, detects all devices in a given ip/netmask.
Angry IP scanner is a very fast IP address and port scanner.
From site:
It can scan IP addresses in any range as well as any their ports. It
is cross-platform and lightweight. Not requiring any installations, it
can be freely copied and used anywhere.
Angry IP scanner simply pings each IP address to check if it’s alive,
then optionally it is resolving its hostname, determines the MAC
address, scans ports, etc. The amount of gathered data about each host
can be extended with plugins.
It also has additional features, like NetBIOS information (computer
name, workgroup name, and currently logged in Windows user), favorite
IP address ranges, web server detection, customizable openers, etc.

UDP Hole punching unsuccessful, but tests show it should work (mobile network)

For the past two week I have been unsuccessfully trying to implement udp hole punching, but I'm not sure why. I understand that the algorithm for hole punching is not guaranteed to work, but I believe it should work in my test case because I have noticed that once I bind my socket on my home-network, the port is the same to the outside world as it is locally, and stays that way for all connections made from this socket. Any help after reviewing my trials would be appreciated.
I have three computers, my osx desktop, my iPhone, and my amazon ec2 ami.
on the desktop I've built a cocoa app which uses the GCDAsyncUDPSocket library to bind a port and contact the ec2 server, where a java app using apache's mina library stores the sockets external ip/port and associates it with a username passed in the payload.
the iphone, which is on the AT&T network runs an app which uses the same GCDAsyncUDPSocket library to contact the ec2 server with the same username, which then the ec2 does a lookup for the username, finds the desktops info and informs the desktop of the iphones address and the iphone of the desktops address.
now the iphone & the desktop know about each other they start shooting off packets at each other in hopes to get a punched hole.
in theory this should work, but maybe I am missing something about mobile networks that would make this difficult? But then again running a simple udp echoer on a 4th external computer to manually msg the desktop did not work either, so maybe its my router, but I don't see how that could be as all my tests show that the port the desktop asks for is the same one assigned by the router.
I've been at this for nearly two weeks with little progress and any tips would be appreciated!
"once I bind my socket on my home-network, the port is the same to the outside world as it is locally"
I highly doubt that. To traverse NAT given peers A and B which have sent datagrams to a 3rd party: S you need to send datagrams from A to B and vice versa using their public IPs as seen by S and their port as seen by S (i.e. not the port A, B are bound to from their point of view).

Slow DNS lookup on iOS simulator

I'm using NSURLConnection to access a web service (on a .local host). When I access the host by hostname, I'm seeing a delay of 5+ seconds, but when I access it by IP, the connection completes almost instantly.
Running the app on an actual iPhone, instead of the simulator, does not show any delays at all (testing was done on the same network connection). So this seems to be a problem specific to the iOS Simulator or OS X.
I'm able to simulate the problem using the following terminal commands:
nslookup webservice.myhost.local (which is fast)
dscacheutil -q host -a name webservice.myhost.local (shows the delay)
When analyzing the network traffic using Wireshark of the dscacheutil command, I'm seeing several Standard query AAAA requests which are marked red and get an empty response. Once these are done, I see a Standard query A request which has a response containing the correct IP address. The AAAA requests take up about 5 seconds, which would explain the delay.
Does the web service perhaps have IPv6 enabled and you can't use that from the simulator?
I see this on OSX for example when running a local IPv4 only DNS service - if I run dig #localhost is hangs for some seconds until the initial IPv6 connection times out, and then it tries IPv4.
This answer solved the problem for me. (Create an IPv6 ::1 loopback entry to go along with each 127.0.0.1.)
For anyone else who stumbles across this issue... I myself had to disable IPv6 on my machine to avoid the hang in the simulator while IPv6 fails. I did so following these instructions: https://discussions.apple.com/message/18097613#18097613
Which were to:
"To disable IPv6 in OS X Lion, you will need to use the Terminal.
Applications > Utilities > Terminal
To determine what are all of your Mac's network interfaces are, issue the following command: networksetup -listallnetworkservices
To disable IPv6 for wireless, issue the following command: networksetup -setv6off Wi-Fi;
To disable IPv6 for Ethernet, issue the following command: networksetup -setv6off Ethernet
To re-enable IPv6, use -setv6automatic instead"