I’ve always had some sort of server at my house, for various reasons, but one thing that I never have to go along with those servers is a static IP address. Either they are way too expensive and not worth it for something that I am not making any money from, or they are completely unavailable. One day, hopefully my ISP will provide them for something other than a huge monthly business package, but that is probably wishful thinking.
Because I have servers, and this dynamic IP address, every once in a while my IP address changes. It’s much less frequent than I thought it would be, but it still happens from time to time. And since it doesn’t happen often, it’s usually one of those things I don’t notice until I am away from home and trying to access something on one of my servers, with no way to check the new IP address. I also try to keep some DNS records updated with the address, for easy reference.
So, my solution was to make a simple WebAPI service that simply returns the clients IP address, and then to have a simple application that consumes that service and keeps track of the addresses that are returned. Once a change is found, it will shoot out an e-mail to me with the new address and a reference to the old address. Then I can update my DNS, etc… No more unknown address changes. And if it changes while I’m out of the house, I will still be able to get access to my systems.
The WebAPI is very simple, just a Get() method with some very simple IP logic in it.
public class IpPingController : ApiController
{
public string Get()
{
string ipAddr = HttpContext.Current.Request.UserHostAddress;
if(string.IsNullOrEmpty(ipAddr)) {
object property;
Request.Properties.TryGetValue(typeof(RemoteEndpointMessageProperty).FullName, out property);
RemoteEndpointMessageProperty remoteProperty = property as RemoteEndpointMessageProperty;
if (remoteProperty != null) {
ipAddr = remoteProperty.Address;
}
}
return ipAddr;
}
}
You can test this service by hitting this address in your browser, http://www.santsys.com/api/ipping/.
The application is a very simple console application that I run using windows scheduled tasks. I have it setup to run every 2 hours.
private static Configuration _cfg = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
public static Configuration Config { get { return _cfg; } }
public static string ApiAddress { get { return ConfigurationManager.AppSettings["IpPingAddress"]; } }
public static string PreviousIpAddress
{
get { return ConfigurationManager.AppSettings["PreviousIpAddress"]; }
set { _cfg.AppSettings.Settings["PreviousIpAddress"].Value = value; }
}
public static string LastUpdate
{
get { return ConfigurationManager.AppSettings["LastCheck"]; }
set { _cfg.AppSettings.Settings["LastCheck"].Value = value; }
}
public static string SmtpHost { get { return ConfigurationManager.AppSettings["SmtpHost"]; } }
public static int SmtpPort
{
get
{
string port = ConfigurationManager.AppSettings["SmtpPort"];
int iPort;
if (int.TryParse(port, out iPort)) {
return iPort;
}
return 25;
}
}
public static string SmtpUser { get { return ConfigurationManager.AppSettings["SmtpUser"]; } }
public static string SmtpPassword { get { return ConfigurationManager.AppSettings["SmtpPassword"]; } }
public static string SmtpFrom { get { return ConfigurationManager.AppSettings["SmtpFrom"]; } }
public static string SmtpTo { get { return ConfigurationManager.AppSettings["SmtpTo"]; } }
static void Main(string[] args)
{
try {
DoWork();
#if DEBUG
Console.Write("\r\nPress any key to exit.");
Console.ReadKey();
#endif
}
catch (Exception ex) {
Console.WriteLine("{0}\r\n\r\n{1}", ex.Message, ex.StackTrace);
}
}
public static void DoWork()
{
Version ver = Assembly.GetAssembly(typeof(Program)).GetName().Version;
Console.WriteLine("IpPing v{0}.{1} build {2}", ver.Major, ver.Minor, ver.Revision);
Console.WriteLine("\r\nLast Run: {0} @ {1}", PreviousIpAddress, LastUpdate);
Console.Write("\r\n");
if (string.IsNullOrEmpty(ApiAddress)) {
Console.WriteLine("Error: No Api Address found in configuration. (IpPingAddress)");
return;
}
HttpClient client = new HttpClient();
client.BaseAddress = new Uri(ApiAddress);
// Add an Accept header for JSON format.
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = client.GetAsync("api/IpPing/").Result;
if (response.IsSuccessStatusCode) {
var ipAddrInfo = response.Content.ReadAsAsync<string>().Result;
Task emailUpdate = null;
// if the IP Address has not changed
if (PreviousIpAddress != ipAddrInfo) {
Console.WriteLine("New IP address detected.\r\n\tOld Address:{0}\r\n\tNew Address:{1}\r\n\r\nSending notification.", PreviousIpAddress, ipAddrInfo);
emailUpdate = SendUpdateEmail(ipAddrInfo, PreviousIpAddress);
PreviousIpAddress = ipAddrInfo;
}
LastUpdate = DateTime.Now.ToString();
Config.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection("appSettings");
// wait for the email to send, if one is being sent
if (emailUpdate != null) {
emailUpdate.Wait();
}
}
else {
Console.WriteLine("Error: {0} ({1})", (int)response.StatusCode, response.ReasonPhrase);
}
}
public static Task SendUpdateEmail(string newIp, string oldIp)
{
return Task.Factory.StartNew(() => {
try {
SmtpClient smtpClient = new SmtpClient(SmtpHost, SmtpPort);
if (!string.IsNullOrEmpty(SmtpUser) && !string.IsNullOrEmpty(SmtpPassword)) {
smtpClient.UseDefaultCredentials = false;
smtpClient.Credentials = new NetworkCredential(SmtpUser, SmtpPassword);
}
MailMessage msg = new MailMessage(SmtpFrom, SmtpTo);
msg.IsBodyHtml = true;
msg.Priority = MailPriority.High;
msg.Headers.Add("X-IP-PING", "Automated message from IP PING");
msg.Headers.Add("X-IP-PING-ADDRESS", newIp);
msg.Subject = "Ip Address Changed!";
msg.Body =
"<style type=\"text/css\">body, p { color: #555; font-size: 12px; font-family: Arial; } a, a:link, a:visited { color: #486db5; text-decoration:none;}</style>"
+ "<p style=\"color: #555;font-size: 12px; font-family: Arial;\">This is a notification from Ip Ping. Your IP Address has changed.</p>"
+ "<p style=\"color: #555;font-size: 12px; font-family: Arial;\">Your new IP Address is <b style=\"font-size: 14px; color: #000;\">" + newIp + "</b></p>"
+ "<p style=\"color: #555;font-size: 12px; font-family: Arial;\">Your old IP Address was " + (string.IsNullOrEmpty(oldIp) ? "(blank)" : oldIp) + "</p>"
+ "<br /><br /><p style=\"color: #666;font-size: 10px; font-family: Arial;\">© " + DateTime.Now.Year.ToString() + " Santomieri Systems - <a href=\"http://www.santsys.com/\">www.santsys.com</a></p>";
smtpClient.Send(msg);
}
catch (Exception ex) {
Console.WriteLine("{0}\r\n\r\n{1}", ex.Message, ex.StackTrace);
}
});
}
That’s pretty much it. Feel free to use this if it will help you out. I know it solved a lot of issues for me.