Dying Technologies: IRC

It was just before the day break on a lovely Sunday night, that I realised, I was facing two big issues: first, I was stuck with a dynamic public IP; second, sleep was hitting me hard. 
I had just successfully pulled an all nighter to set up my home server, with an Arch Linux running in a headless mode, powering my archaic pentium Core 2 Duo machine. All of my data had been categorically listed and filed into my new home 'Server', which I conveniently named 'The Upside Down' drawing inspirations from the nerdy Netflix series: The Stranger Things.
Like every other human being, I also grew a bit greedy after I had set up my local server. I wanted to access it from the wild, from the comfort of my bus ride, where I could sync files, dump pictures and everything else I could think of, while being on a mobile network. The only problem seemed to be the ever changing dynamic IP of my home network which somehow devised ways to disappear from my prying eyes.

The Dynamic IP Problem

DNS providers:
This seemed like a good solution where I could register my server on a Dynamic domain name service provider like dynDNS or NO-IP, but the prospect of having my home server accessible through a domain name seemed a bit scary and naive, primarily since I was just planning to use the SSH, and din't actually plan on hosting a web service, and secondly because the solution was way too simple.
Email:
The second solution presented me with an idea of sending an email to my personal email account whenever the IP changed. The challenge was with disabling the spam filters, which I later found out had opened up its own can of worms.
Slack bot:
Then I diverted my attention to building a slack bot, which I planned on getting subscribed to a 'CHANNEL' on a 'FAKE' organisation. The fake part put me off a bit, since the little voice in my head kept yelling that it was wrong.
Google Docs:
I even thought of going full brute force by letting my home Server periodically update a shared Google Doc. It was good when it all started, and it looked neat, but my heart was not yet satisfied. primarily because the code was tied down to a service, which faced a prospect of being discontinued if Google felt so.

Other Innovative Ideas:
1. Twitter: I could have my home PC tweet my public IP on every IP change.
2. Facebook: It could make a status update with the IP address whenever the IP changed.
3. Github: It could make a commit; push to remote git repo when ever the IP changed.
4. CI/CD: Trigger a parametrised build - with IP as the parameter - on CircleCI whenever the IP changed.
All these Ideas seemed good and weird at the same time, and they all required my machine to constantly poll for IP change (Except for Slack bot, which I discarded due to being owned by a corporate), and also since all these services were not in essence open services or standards. I wanted a simpler solution, which was both ethical, as well as open standards based, and one which din't require my home server to be constantly polling to check for IP changes.
Then the thought hit me,
What if, I could just ask my home server what its IP was, and it could tell me. 
This prospect piqued my interest.


The Hashtag Hipster

    
I turned my attention to Internet Relay Chat (IRC), which I used to actively use during my early days with Linux. It was long forgotten since, buried underneath a plethora of communication apps from the 'future'.

The steps were simple
  1. Set up an IRC bot
  2. Connect it to an IRC server
  3. Subscribe to a channel
  4. Specifically program it  to listen to the command to check for dynamic IP
  5. Fetch the IP using one of the many IP host checker APIs available in the market. 
  6. Encrypt it using RSA, and 
  7. Dump it into the IRC channel to be consumed.  
Once the idea was set, rest of the solution was simple. With a little online help,  I was ready with my very own IP reporting IRC bot.
And thus the IP teller was born.

irc.py


import socket
import sys

 
class IRC:
  
    irc = socket.socket()
    
    def __init__(self):  
      self.irc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
      
    def send(self, chan, msg):
      self.irc.send("PRIVMSG " + chan + " " + msg + "\n")
      
    def connect(self, server, channel, botnick):
      #defines the socket
        print "connecting to:"+server
        self.irc.connect((server, 6667))
        while 1:
          text = self.irc.recv(2040)
          if 'No Ident response' in text:
            break

        # self.irc.send("PASS " + "secret_key")  #user authentication
        self.irc.send("USER " + botnick + " " + botnick +" " + botnick + " :IP bot!\n") #user authentication
        self.irc.send("NICK " + botnick + "\n")
        while 1:
          text = self.irc.recv(2040)
          if 'MODE '+botnick+' :+i' in text:
            break
        self.irc.send("JOIN " + channel + "\n")        #join the chan
        
    def get_text(self):
      text=self.irc.recv(2040)  #receive the text
      if text.find('PING') != -1:
        self.irc.send('PONG ' + text.split() [1] + 'rn')
      return text


ip_teller.py


from irc import *
import requests
from Crypto.PublicKey import RSA
import base64

channel = "#myipchannel"
server = "irc.freenode.net"
nickname = "ip-teller-bot"

irc = IRC()
irc.connect(server, channel, nickname)

def getIP():
  URL = 'http://icanhazip.com'
  r = requests.get(url = URL)
  return r.text

def encrypt_message(msg):
  with open('public.key', 'r') as public_file:
    pubkey = public_file.read()
    publickey = RSA.importKey(pubkey)
    return base64.b64encode(publickey.encrypt(str(msg), 'T9')[0])
 
while 1:
  text = irc.get_text()
  if "PRIVMSG" in text and channel in text and "What is my IP" in text:
    reply_text = encrypt_message(getIP())
    irc.send(channel, reply_text)

With the IP teller bot running in my home server, all I was supposed to do was to connect to freenode, join the #myipchannel and just type in "What is my IP" and the IRC bot sitting in my home network would fetch my public IP, encrypt it using RSA and dump it into the channel. 


02:41 <justinj> What is your IP
02:41 <ip-teller-bot> hsE20H1iK/hAs64sSj8DXWiWnV1jzkN7Tr4KZ3wVl50JEAC6KQIBI9sAXi97jtPoYV/sBCaXjE6BeA0Um/DrOVs0ksYt8sgYxBR/kP2nkNVaOsQToXtzdkZYHQ8VamppP2vXpK18x8f6uGna13QtZrnfV9Iu5USkgsBqBBXugNqknzIbLoEZu9J49BNI3Zsqmq0yTx00TMbYlyNMngDWueK9I7GNUUgQ0gqTzcNjjcnEssdGgeY+DYqrjqWOuRsaYf+khcFq19ZWFXXXspKqeKXNM8dfF+4DkZbU6J1Sy1QlWHjnpVSOhOXcHtD/n4M7zigsKoszwzZvdRmcKSa5fg==

To retireve my public IP all I had to do was to decrypt the message


with open('private.key', 'r') as private_file:
     prkey = private_file.read()

privatekey = RSA.importKey(prkey)

privatekey.decrypt(base64.b64decode('hsE20H1iK/hAs64sSj8DXWiWnV1jzkN7Tr4KZ3wVl50JEAC6KQIBI9sAXi97jtPoYV/sBCaXjE6BeA0Um/DrOVs0ksYt8sgYxBR/kP2nkNVaOsQToXtzdkZYHQ8VamppP2vXpK18x8f6uGna13QtZrnfV9Iu5USkgsBqBBXugNqknzIbLoEZu9J49BNI3Zsqmq0yTx00TMbYlyNMngDWueK9I7GNUUgQ0gqTzcNjjcnEssdGgeY+DYqrjqWOuRsaYf+khcFq19ZWFXXXspKqeKXNM8dfF+4DkZbU6J1Sy1QlWHjnpVSOhOXcHtD/n4M7zigsKoszwzZvdRmcKSa5fg=='))

With my basic IP telling bot in place, I realised the actual gold mine I had hit.
 I am bit more ambitious now, and mostly would be planning on making the bot do a lot more than just tell me the IP. I might most probably give it some intelligence. There does exist a plethora of AI bots on IRC channels, but the prospect of designing one by my self is something which makes this entire process a bit more challenging and fun.

Other Resources:
Connecting to IRC using Telnet
IRC RFC standards
FreeNode

Comments

Popular posts from this blog

Perceptron Networks - 1: Did I Win?

Logic of Discovery - The happy accidents