Let’s say, hypothetically, that you’re trying to setup something for you and your friends to use. An FTP server, Minecraft server, demo website, whatever. Plus you have already have a simple little website hosted elsewhere with a cPanel and PHP/MySQL for your WordPress blog or something.
And let’s also say you have an ISP, called PictureyThink or MillenniumConnect or DecadeJoin or whatever, that will only give you a static IP for an extra monthly fee. But you’re already pretty upset with them because…
- They practically doubled your monthly bill despite their website saying things like “Price for life”, “No contract”, “No rate hike”, and “Keep your rate as long as you keep your plan” all over it.
- Your ISP is involved in several class-action lawsuits over the exact behavior above. So it definitely isn’t a one-off error on their part.
- You called them about it and they promised they’d resolve it and that your bill would be back to normal but it’s still nearly double the advertised rate months later.
- They advertised and sold you “1 Gig (1000 Mbps)” service, but your speeds are rarely over 30 Mbps, or just 3% of the advertised speed. And you’ve never seen speeds over 200 Mbps. (Yes, even when you connected your computer directly to the modem.)
In such a scenario you may feel justified in side-stepping their extra fee for a static IP, as at this point you’ve effectively paid that monthly fee for years to come.
Here’s how you might do just that.
We’re just focusing on getting the IP of the computer or network your friends/family needs to connect to into that external website you have and displaying it. For that we need three components:
- A page to receive and store the IP on the remote website.
- A page to display the saved IP on the remote website.
- Some code to send the IP to the remote website.
Since your website has PHP and MySQL you can just make simple pages for the first two items. First some preliminary setup that I’m going to gloss over.
Use your cPanel or whatever you want to setup the database. You don’t have to create a new user, but it doesn’t hurt to make one with permissions limited to just the one table used in this project. In this example we’re using a table named “ftp_ip” with just one varchar(30) column called ip_address
. Go ahead and add a single record to the table. We’ll just be issuing UPDATE
and SELECT
statements for that one record in that one column of that table.
Receiving IP on remote website
You could put the send/view operations in the same page and use GET/POST to determine which to do, but a little “security through obscurity” and separation of duties is nice here. Luckily there’s a neat little program on Ubuntu called uuidgen
that should create a good random UUID, or you could use random.org. Take that random text and use it in the file name, so you have something like puship0eb2e304d7594a35b86c649022cf7af0.php
.
Now for the contents of that page, you’ll want to do something like this:
<!DOCTYPE html> <html> <head> </head> <body> <?php $servername = "localhost"; $username = "username-here"; $password = "password-for-user"; $dbname = "your-database-name"; // another uuidgen value $expected_token = "b916c295-19b5-40ee-80de-6fc5a98b5d66"; $table_name = "ftp_ip"; $conn = new mysqli($servername, $username, $password, $dbname); if($conn->connect_error) { die("Connection failed: " . $conn->connect_error); } if($_SERVER["REQUEST_METHOD"] === "POST") { $ipset = isset($_POST["ipaddr"]) && !empty($_POST["ipaddr"]); $tokenset = isset($_POST["token"]) && !empty($_POST["token"]); if($ipset && $tokenset) { // data exists, fetch it $ipaddr = $_POST["ipaddr"]; $token = $_POST["token"]; $ip_good = preg_match("/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/", $ipaddr); if($ip_good != 1 || $token != $expected_token) { if($ip_good != 1) { echo "invalid IP address format <br />"; } if($token != $expected_token) { echo "invalid or missing token <br />"; } } else { // data is valid, add to database $sql = "UPDATE " . $table_name . " SET ip_address='" . $ipaddr . "';"; if($conn->query($sql) === TRUE) { echo "updated ip address to " . $ipaddr . " <br />"; } else { echo "update failed"; } } } } ?> </body>
One feature built into that page is that it requires the IP address to be in the proper format, that should help with SQL injection.
Another feature is that it requires a user to send an additional “token” value with the POST data for the address to actually get saved. That should help protect against people sending invalid IP addresses. So go ahead and run uuidgen
again and paste a different value in there. Save it for later too when you make your code that actually sends the IP to this page.
Displaying the saved IP on the remote site
For this one we’ll again use uuidgen
to both add to the file name, and as a GET parameter needed as a simple authorization. Sure having the token in the URL isn’t secure, but it really doesn’t make things any worse. So your file might be named peekip6517a730b10a43b7abe8f57ac1e0b537.php
with code like the following.
<!DOCTYPE html> <html> <head> </head> <body> <?php $username = "username-here"; $servername = "localhost"; $password = "user-password-here"; $dbname = "database-name"; $expected_token = "3a32c33c-6f14-41de-8a81-639003d8055c"; $table_name = "ftp_ip"; $conn = new mysqli($servername, $username, $password, $dbname); if($conn->connect_error) { die("Connection failed: " . $conn->connect_error); } if($_SERVER["REQUEST_METHOD"] === "GET") { $sql = "SELECT ip_address FROM " . $table_name . ";"; $result = $conn->query($sql); $tokenset = isset($_GET["token"]) && !empty($_GET["token"]); if($tokenset) { $token = $_GET["token"]; if($token != $expected_token) { echo "invalid or missing token"; } else { if($result->num_rows > 0) { $row = $result->fetch_assoc(); echo $row["ip_address"]; } else { echo "could not fetch ip"; } } } else { echo "missing token"; } } ?> </body>
So for the users to get to page that has the IP address, they’ll have to bookmark a URL like: https://yourwebsite.com/path/to/peekip6517a730b10a43b7abe8f57ac1e0b537.php?token=3a32c33c-6f14-41de-8a81-639003d8055c
.
Sending the network IP to the website
This is the part that actually lives on your home network. It’ll need to run on a computer that’s powered on as close to 100% as possible. Maybe you have a raspberry pi for just such simple tasks.
The following bash script will both get the IP address of your local network and send it to your website. It’s dead simple.
#!/bin/bash # get your external ip IP=$(curl https://ipinfo.io/ip) # send it to your website curl -d "ipaddr=$IP&token=b916c295-19b5-40ee-80de-6fc5a98b5d66" \ -X POST https://yourwebsite.com/path/to/puship0eb2e304d7594a35b86c649022cf7af0.php
Save that to wherever, like /home/jeff/ipsend.sh
. Go ahead and make it executable
chmod a+x /home/jeff/ipsend.sh
Now, the final step is to make sure that script actually runs every so often and updates the value stored on your website. We just need to add a crontab entry for that. So open up your file:
crontab -e
And lets say you want it to run every 15 minutes. Just add this line:
*/15 * * * * /home/jeff/ipsend.sh
Save the file, exit, wait a while, check that peekip page and Bob’s your uncle!