I posted a few years ago about using Twilio and Node-Red to send/receive SMS messages. Using that flow you gain the ability to text your server and have it read back values. Any values you want, as long as you have them stored as a global some where along the way. If you haven’t already done it toss $20 on an account at Twilio for a year and get to it, its so worth it! Here I am going to add a new reading to my setup.
There are occasions when I need to access my home network when I am, well, not home. Everyone screams use a VPN! Yeah, of course, I have one, and I use it. But my problem is I have a dynamic WAN IP and I am not paying for a static IP. It doesn’t change very often but it always seems to when I need to use it the most. Step in Node-Red and Twilio. With both of those at my disposal I can now send a text message to my home server and have it respond with my WAN IP address. I can then modify my VPN settings on my phone or whatever if needed. Fucking fantastic! I had been using Twilio/NR for sensor readings and alerts but I had never thought about using it to report my IP. Theres a few ways to do this.
Lets grab our IP (the flow)
(This flow grabs the WAN IP via an exec node)
|
[{"id":"7f1bbd2b.a6589","type":"inject","z":"fcba3961.0b2298","name":"Get IP","topic":"ip","payload":"eth0","payloadType":"str","repeat":"43200","crontab":"","once":true,"x":200,"y":300,"wires":[["8cc4e026.8ead5"]]},{"id":"8cc4e026.8ead5","type":"exec","z":"fcba3961.0b2298","command":"wget -qO- http://bot.whatismyipaddress.com/ ; echo","addpay":true,"append":"","useSpawn":"","timer":"","oldrc":false,"name":"Get IP from whatismyipaddress.com","x":490,"y":300,"wires":[["ee0179dd.1761d8"],[],[]]},{"id":"ee0179dd.1761d8","type":"function","z":"fcba3961.0b2298","name":"Format and Store IP Address","func":"var str = msg.payload;\nstr = str.substring(0, str.length - 5); // \"12345.0\"\nmsg.payload = str;\ncontext.global.ipaddress = str;\nreturn msg;","outputs":1,"noerr":0,"x":840,"y":280,"wires":[["11f7b4e8.96208b","ea16599d.f688d8"]]},{"id":"11f7b4e8.96208b","type":"debug","z":"fcba3961.0b2298","name":"","active":true,"console":"false","complete":"false","x":1070,"y":280,"wires":[]},{"id":"ea16599d.f688d8","type":"file","z":"fcba3961.0b2298","name":"","filename":"ipaddress.txt","appendNewline":false,"createDir":false,"overwriteFile":"true","x":1070,"y":320,"wires":[[]]},{"id":"733c803e.66e25","type":"file in","z":"fcba3961.0b2298","name":"","filename":"ipaddress.txt","format":"utf8","chunk":false,"sendError":false,"x":400,"y":180,"wires":[["3838c3a9.4d660c"]]},{"id":"80d4c332.f0685","type":"inject","z":"fcba3961.0b2298","name":"","topic":"","payload":"","payloadType":"str","repeat":"","crontab":"","once":false,"x":190,"y":180,"wires":[["733c803e.66e25"]]},{"id":"3838c3a9.4d660c","type":"debug","z":"fcba3961.0b2298","name":"","active":true,"console":"false","complete":"false","x":590,"y":180,"wires":[]},{"id":"840cfc29.9b1a7","type":"comment","z":"fcba3961.0b2298","name":"Gets and stores the WAN ip address every 12hrs","info":"","x":240,"y":80,"wires":[]},{"id":"f530187f.9ec5a8","type":"comment","z":"fcba3961.0b2298","name":"Read the exisiting IP address stored","info":"","x":260,"y":140,"wires":[]},{"id":"c2bd3cd1.999d2","type":"comment","z":"fcba3961.0b2298","name":"Get the IP and store it","info":"","x":220,"y":260,"wires":[]}] |
First we use an inject node and set it to fire off once on start, this grabs the IP first thing and makes sure we have some data to work with. Then we move off to an execute node. We are gonna execute some command line code and echo it back, then we’ll save it in a file and as a global. This goes in the exec node:
wget -qO- http://bot.whatismyipaddress.com/ ; echo
This goes out to whatismyipaddress.com and echoes back our IP, simple and very fast. There are a few other sites that can be used also. Ifconfig.io and ipinfo.io both are alternative sites (you just have to change the truncation from 5 to 6 characters to drop the return sign in the following function node).
Alternatively, and preferably we can use an HTTP node instead of an exec node. What? Yeah I just found this out.
(This flow grabs the IP via an HTTP node)
|
[{"id":"7f1bbd2b.a65894","type":"inject","z":"fcba3961.0b2298","name":"Get IP","topic":"ip","payload":"eth0","payloadType":"str","repeat":"43200","crontab":"","once":true,"x":200,"y":300,"wires":[["75a86b0c.02a094"]]},{"id":"75a86b0c.02a094","type":"http request","z":"fcba3961.0b2298","name":"GET current-ip","method":"GET","ret":"txt","url":"ipv4bot.whatismyipaddress.com","tls":"","x":440,"y":300,"wires":[["ee0179dd.1761d8"]]},{"id":"ee0179dd.1761d8","type":"function","z":"fcba3961.0b2298","name":"Format and Store IP Address","func":"var str = msg.payload;\n//str = str.substring(0, str.length - 5); // \"12345.0\"\nmsg.payload = str;\ncontext.global.ipaddress = str;\nreturn msg;","outputs":1,"noerr":0,"x":760,"y":300,"wires":[["11f7b4e8.96208b","ea16599d.f688d8"]]},{"id":"11f7b4e8.96208b","type":"debug","z":"fcba3961.0b2298","name":"","active":true,"console":"false","complete":"false","x":1070,"y":280,"wires":[]},{"id":"ea16599d.f688d8","type":"file","z":"fcba3961.0b2298","name":"","filename":"ipaddress.txt","appendNewline":false,"createDir":false,"overwriteFile":"true","x":1070,"y":320,"wires":[[]]}] |
That will get you your WAN IP quickly via an HTTP node formats it then saves it to a file. We have to comment out the substring trimming command if we use the HTTP node over the exec node. Ok no problem. Don’t forget.
After we grab the IP we need to format it and save it as a global for Twilio (and Alexa!).
|
var str = msg.payload; str = str.substring(0, str.length - 6); // "12345.0" msg.payload = str; context.global.ipaddress = str; return msg; |
This will trim the returned output from the website to 6 characters, dropping off anything extra. It also saves our trimmed value as a global. Then we slap on a debug node and a file node to save the IP to a file for later use. You don’t have to save the IP to a file, I just like to in the even the server is restarted/power loss.
Thats it! Once the IP has been picked up and set as a global you are good to go (as long as you followed the other flow for Twilio I posted previously).
It figures…
After typing this up and saving the draft I decided to update NPM/nodejs/Node-Red. Upon updating I came across a Node-Red node, node-red-contrib-ip.
A simple install via Palette Manager (which doesn’t work for me) or manually installed via
npm install node-red-contrib-ip and you’re good. The node works simply, nothing to configure. Add an inject node to trigger it and it spits out your machines IPv4 and IPv6 address and well as your WAN IP address. Just have to format the data the way you want and boom. I did notice it is slow, painfully slow. It doesn’t need to be lightning quick but it is noticeable compared to the wget option above. Choose your weapon, either method works. Heres the flow for using the IP node.
(This flow grabs the WAN IP via the node red IP node)
|
[{"id":"d828747e.e32f38","type":"inject","z":"fcba3961.0b2298","name":"Get IP","topic":"ip","payload":"eth0","payloadType":"str","repeat":"","crontab":"","once":false,"x":230,"y":680,"wires":[["1b303571.8b4e0b"]]},{"id":"1b303571.8b4e0b","type":"ip","z":"fcba3961.0b2298","name":"ip","x":430,"y":680,"wires":[["4e1efd6f.8b4c94","9e07f9d2.9336f8"]]},{"id":"4e1efd6f.8b4c94","type":"debug","z":"fcba3961.0b2298","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload.public.v4","x":660,"y":640,"wires":[]},{"id":"9e07f9d2.9336f8","type":"function","z":"fcba3961.0b2298","name":"Format IP Address","func":"var str = msg.payload.public.v4;\nmsg.payload = str;\ncontext.global.ipaddress = str;\nreturn msg;","outputs":1,"noerr":0,"x":650,"y":680,"wires":[["fc459952.525688","79055bdc.85c924"]]},{"id":"fc459952.525688","type":"debug","z":"fcba3961.0b2298","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","x":870,"y":680,"wires":[]},{"id":"79055bdc.85c924","type":"file","z":"fcba3961.0b2298","name":"","filename":"ipaddress.txt","appendNewline":false,"createDir":false,"overwriteFile":"true","x":870,"y":720,"wires":[[]]}] |
After the IP node put a function node and fill it with this code
|
var str = msg.payload.public.v4; msg.payload = str; context.global.ipaddress = str; return msg; |
This drops all the other node info and just gives us the WAN IP. Easy as pie.
Lets get notified
So far we check our IP every 12hrs and write it to a file and a global for use. Thats great, we can take it one step further. Want to get a notification when the IP does change? Lets go.
(This flow grabs the IP via an HTTP node and checks if it has been updated, then sends a notification if it has)
|
[{"id":"4166dda1.675464","type":"debug","z":"fcba3961.0b2298","name":"Notification","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","x":910,"y":1040,"wires":[]},{"id":"34c1c1a1.38ebae","type":"template","z":"fcba3961.0b2298","name":"template for the notification","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"{{payload}} first seen {{headers.date}}","x":680,"y":1040,"wires":[["4166dda1.675464"]]},{"id":"59a486eb.38d258","type":"switch","z":"fcba3961.0b2298","name":"check if ip changed","property":"current-ip","propertyType":"msg","rules":[{"t":"neq","v":"previous-ip","vt":"msg"}],"checkall":"true","outputs":1,"x":390,"y":980,"wires":[["eed97968.cecfb8","34c1c1a1.38ebae"]]},{"id":"1340ce8e.147161","type":"change","z":"fcba3961.0b2298","name":"set","rules":[{"t":"set","p":"current-ip","pt":"msg","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":890,"y":920,"wires":[["59a486eb.38d258","69978370.78fabc"]]},{"id":"eed97968.cecfb8","type":"file","z":"fcba3961.0b2298","name":"","filename":"ipaddress.txt","appendNewline":false,"createDir":false,"overwriteFile":"true","x":630,"y":980,"wires":[[]]},{"id":"3c44be19.b30272","type":"http request","z":"fcba3961.0b2298","name":"GET current-ip","method":"GET","ret":"txt","url":"ipv4bot.whatismyipaddress.com","tls":"","x":720,"y":920,"wires":[["1340ce8e.147161"]]},{"id":"69978370.78fabc","type":"debug","z":"fcba3961.0b2298","name":"get current ip","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":1080,"y":920,"wires":[]},{"id":"6a48408b.2e06f","type":"change","z":"fcba3961.0b2298","name":"set","rules":[{"t":"move","p":"payload","pt":"msg","to":"previous-ip","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":550,"y":920,"wires":[["3c44be19.b30272"]]},{"id":"87c22384.e21ec","type":"file in","z":"fcba3961.0b2298","name":"read previous-ip","filename":"ipaddress.txt","format":"utf8","sendError":true,"x":380,"y":920,"wires":[["6a48408b.2e06f"]]},{"id":"ab2f8849.0ea388","type":"inject","z":"fcba3961.0b2298","name":"Every 24h","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"00 1 * * *","once":false,"x":170,"y":920,"wires":[["87c22384.e21ec"]]}] |
- Inject and repeat every 24hrs at a set time
- Read the stored IP address by reading the file
- Get the current IP address and set it as a global
- Cross check to see if the new IP matches the old IP and save it to a file if it is newer.
- Format the message payload and send a notification (however you like, pushbullet, email, Twilio etc)
Check out this site, its where I got the notifications from https://steve.zazeski.com/get-a-notification-when-your-wan-ip-changes/.