14

What would be the easiest way to find, with a script, if my IP address has changed?


Background info:

I have a standard home cable modem connexion, and my ISP assigns me a dynamic IP. It changes every now and then, the DHCP lease times seems irregular.

Basically, I'm doing my own dynamic DNS thing, and can update the DNS records pointing to my home server with a click. The only thing remaining is to detect an IP change so I can fully automate the process.

Now there are several websites here which can return your IP address, and I could use a cron job to wget one of these pages and grep the IP address from it... But it seems overkill in terms of CPU / bandwidth usage, and it's not very KISS.

Am I missing some simple and elegant way to retrieve my public IP and check if it has changed?

Extra info: my modem/router is a cheap brick, it does nothing very interesting in that regard. My server runs with Centos 6.

7

Assuming you're behind NAT, the most elegant way I can think of is to run a cron job on the router itself, periodically checking ifconfig too check its current WAN address. This may even be possible on a 'cheap brick' if you are able to install custom firmware. However elegant, hardly simple.

As discussed here, on Windows, but the argument is equally valid for Centos, in polling the WAN IP from behind NAT, you run into the problem that you don't technically have an external address. Instead, you are routed through one at the router's discretion. Obviously, you would still have access to this information as long as the router is under your control, but there is no universal way of communicating this IP address to hosts on the local network. As a result, your server cannot simply ask the router for the external IP it will be using.

The most efficient alternative would be to just let the router do its magic and actually make the connection to an external server, then asking it to return the address the request originated from. A lot of webservers have been set up specifically for this purpose. For scripting, I can recommend http://icanhazip.com/, as it requires no further parsing on your part (only the IP is returned in plain-text).

If necessary, the answers to the question linked to before ought to provide plenty of tips on implementation.

3
  • 1
    Good ideas and links. +1, if only for the icanhazip website that I did not know, and makes the downloading of extra HTML and parsing unnecessary. – Silver Quettier Mar 6 '13 at 14:54
  • 1
    Or checkip.net-me.net/plain – Alex Mar 6 '13 at 15:44
  • 2
    Also ifconfig.me/ip and wtfismyip.com/text – Dmitry Fedorkov Aug 31 '17 at 19:55
6

You can query any website that displays your IP for this task. Using checkip.dyndns.com, since it it text.only.

Example:

wget -q -O - checkip.dyndns.com | grep -Po "[\d\.]+"
1

The previous answers excluding the PS implementation, don't actually tell you if the IP has changed. (I want to love PowerShell. Ryan has done a good job of identifying why I don't: execution security permissions are nuisance).

Parsing the IP is not necessary so long as any additional output does not change when then the IP has not changed. For example checkip.dyndns.com returns something like Current IP Address: ddd.ddd.ddd.ddd. Thus it is enough to simply compare the entire output.

Also if you are using curl, you may want to hide progress using the -s flag. Since it is written to stderr, it does not pollute stdout.

So, here is a simple .cmd script, which uses curl to save the output. It then uses FC to compare it to the previous output, if any. I do not need to set FC options for Unicode, case sensitivity etc, since the output should be a binary match, when the IP has not changed. Unix has cmp instead of FC.

@REM 12/30/2017 The following work:
@REM                checkip.dyndns.com
@REM                wtfismyip.com/text
@REM                icanhazip.com
@REM                ifconfig.me/ip -- can be slow

curl icanhazip.com > CurrentIp.txt
fc /B LastIp.txt CurrentIp.txt 1> nul: 2>>&1

if ERRORLEVEL 1 (
    ECHO Ip Changed
    REM Remember for next time
    MOVE /Y CurrentIp.txt LastIp.txt 1>nul:
    exit /b 1
) else (
    ECHO Ip not Changed
)

Obviously CurrentIp.txt LastIp.txt can be changed to suit, e.g prefix with "%TMP%\" This script should work from Task Scheduler, with minor changes.

1

In response to OP: "Am I missing some simple and elegant way to retrieve my public IP and check if it has changed?"

A really simple answer is don't. Just periodically update your IP.

It seems wasteful, but "smarter" solutions are just more complex and less reliable, without saving CPU, bandwidth etc. Sending 1500 bytes or less (a packet) once an hour is very cheap. An entire year will consume 365 * 24 * 1,500 = 13 Meg Bytes or about 3 minutes of the Rifleman on Netflix.

The CPU/bandwidth cost of getting your external ip and occasionally posting your new ip, is most likely higher than just redundantly posting your ip periodically. I have been posting my ip to duckdns every hour for years, without problem. Obviously if you start doing this 1/second your domain service may figure it out and get annoyed. Likewise any service you use for looking up your ip will not be happy if you do this.

One last thought, the question you ask is a part of the problem that you mention. The trigger for refreshing your dynamic dns could be when your domain name does not resolve to your server. You could use ping, but if your old ip address gets reused, the new ip lease holder may well respond to ping.

With this in mind you could periodically attempt to download a small signature/magic file from your server. Really this could be any static file that tells you that you found your server, even your home web page would work, but an unusual name would be much better than default.html.

If the d/l fails, then update your IP, clear your DNS cache and try again. It may take a few minutes for the update to be effective, depending on your DNS service. This approach removes reliance on some other external ip site, and actually tests what you really want to know: Can others reach my site?

0

I had this same question today, and I wasn't satisfied with the answers I saw here or on Google, so I wrote a PowerShell script to send me a Slack notification whenever my IP address changes.

If you'd prefer to receive an email, you could click the links in the script to look at a different version that supports Outlook emails.

I hope this helps someone and earns a vote. :-)

Save the following text to a .ps1 file. Edit it as appropriate with your own Slack webhook URL. Save. Right-click the file to "Run with PowerShell".

Or you can schedule it to run daily or however often.

#Script to compare current IP with old IP and sends Slack notification if different (and do nothing if there was no change).
#We can put this as a scheduled task to run daily.
#ScriptName: IP_change_detection_notification.ps1

$slackWebhookUrl = "XXXXXXXXXX" #put yours here
$ipDetectionUrl = "https://wtfismyip.com/text"
$IPAddFile = "C:\code\IP_change_detection_notification.dat" #absolute path to file that stores the old IP record
$slackOutputFile = "C:\code\IP_change_detection_notification_Slack.txt"
$optionalDebuggingFile = "C:\code\IP_change_detection_notification_debugging.txt"

$Request = Invoke-WebRequest $ipDetectionUrl
$IP_new = ($Request.Content.Trim())
Write-Host "Current IP address: [$IP_new]"

#Check if old IP record exists
If(Test-Path "$IPAddFile")
{
#Get old IP
$IP_old = Get-Content "$IPAddFile"
    #Compare IPs
    if(-not($IP_new -eq $IP_old))
    {
        Write-Host "Old IP address: [$IP_old]"
        $msg = "Your WAN IP has changed to $IP_new (was $IP_old)!"
        Write-Host "$msg"               
        $body = $("{""text"":""$msg""}")
        Write-Host "$body"
        Invoke-RestMethod -Uri $slackWebhookUrl -Method Post -ContentType 'application/json' -Body $body -OutFile $slackOutputFile

        "Notification Sent"     

        #Overwrite and update new IP
        $IP_new |  Out-File $IPAddFile

    }
    else
    {"No change, no notification"}

}
else
{
#Create new, as file not found
$IP_new |  Out-File $IPAddFile
"File created"
}
$(get-date -f yyyy-MM-dd_HH_mm_ss)  |  Out-File $optionalDebuggingFile
#Read-Host -Prompt "Press Enter to exit" #Comment out this line if this script will be run by a cron job. Otherwise, uncomment it so that you can see the results of the script in the console.

#This script was adapted from https://gallery.technet.microsoft.com/scriptcenter/Detect-IP-address-change-aeb51118 by Satyajit

To get the Task Scheduler working:

I had to run PowerShell as an administrator and then run Get-ExecutionPolicy, which then told me that my current ExecutionPolicy was "Restricted".

Then I ran Set-ExecutionPolicy RemoteSigned (as shown here, but it makes me nervous: https://stackoverflow.com/a/26955050/470749).

Then from a basic Windows command prompt, I tried running the following command a couple times: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy ByPass -File "C:\code\IP_change_detection_notification.ps1" (once to store the IP, and a second time to check whether it had changed).

(Until you get that to work, don't bother trying to use Task Scheduler.)

Then I scheduled a task with C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe as the program and -ExecutionPolicy ByPass -File C:\code\IP_change_detection_notification.ps1 as the Arguments.

1
  • Its a great solution, but unfortunately the OP noted that he is using CentOS, so this technically doesn't answer the question. – MaQleod Dec 31 '17 at 6:52
0

As an alternative option that might help you, I've written a python script designed to monitor for external IP address changes. I use it under Linux but since it's python it should work on Windows just fine after setting up the appropriate Python environment. It currently saves the "current" external IP address to a file and, when run, grabs a new IP address and then checks it against the old one. It is design to email you with if a change is detected.

It's designed to run as a cronjob (Linux) or scheduled task (Windows) and does not run as a background daemon on its own.

Here's the link to the github repository: https://github.com/begleysm/ipwatch

Hopefully it helps!

-2

I use curl ifconfig.me, but it is not something I have tried on platforms other than Debian.

1

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.