In this article, we have developed a Python script to get private, public IP address along with other details.
Table of Contents
- What is an IP Address
- Private vs Public IP Addresses
- Domain Name System (DNS)
- Use Cases
- Hands On: Have fun with IP Addresses
What is an IP Address
Every node(computer) on a network is assigned a unique number that identifies it on the network. This unique number is encoded with in each packet sent and destined for that node across the network.
Private vs Public Addresses
When you set up your home network, The addresses assigned to your network devices will be private unless you do make them public. Private addresses are not accessible to the public unless you configure port forwarding on your gateway (Internet facing router). In a nutshell, private addresses are not routable.
And whereas, you attain a public address when you connect to the ISP's (Internet Service Providers) network. Unlike private addresses, public addresses are routable.
Domain Name System
People normally call it the phonebook of the internet and indeed it is. When you do need to call your friend saved in the phonebook, the closest thing you can remember is their name, and this eliminates the need to memorize your friend's number.
The above is analogous to what DNS does for the internet, rather than memorize an IP Address(126.96.36.199 - Google's IP Address), All you have to recall is google.com
Besides allowing communication over the network, IP Addresses have been creatively uitilized by applications such as Access Control, Geographical Location
Hands On: Have fun with IP Addresses
#!/usr/bin/python import sys import socket import requests import json from argparse import ArgumentParser ipify_json_endpoint = "https://api.ipify.org?format=json" def get_my_public_ip(): response = requests.get(ipify_json_endpoint) return json.loads(response.text)["ip"] def get_my_private_ip(): return socket.gethostbyname(socket.gethostname()) def resolve_fqdn(fqdn): """ fqdn: Fully Qualified Domain Name of the server """ return socket.gethostbyname(fqdn) def echo_ip_address(ip_address): print("The IP Address is: %s" %(ip_address)) if __name__ == "__main__": args_parser = ArgumentParser() args_parser.add_argument("--server", action="store_true") args_parser.add_argument("--fqdn", help="FQDN of server") args_parser.add_argument("--public", action="store_true") args_parser.add_argument("--private", action="store_true") args = args_parser.parse_args() if args.server: if not args.fqdn: args_parser.error("The Fully Qualified Domain Name is required") sys.eixt(-1) ip_address = resolve_fqdn(args.fqdn) echo_ip_address(ip_address) elif args.private: ip_address = get_my_private_ip() echo_ip_address(ip_address) elif args.public: ip_address = get_my_public_ip() echo_ip_address(ip_address) else: args_parser.error("Missing an action: --server or --private or --public")
Understanding the code
The script has three procedures(functions):
Calls the ipify JSON endpoint and then converts the response into a python dictionary which only has the ip key(field). And this field has the public address of the node that made the request to the API and that node is your computer.
Returns the private address assigned to the node.
It uses two functions from the socket module:
gethostname(): Returns hostname of the node
gethostbyname(<hostname>): Resolves the hostname to an IP address.
Obtaining a server's IP address is a DNS resolution and so, you will need a server's fully qualified domain name.
The FQDN resolution is accomplished by socket.gethostbyname(), and it takes a host name as its argument but for our case, we shall need the FQDN, since the server doesnot belong to our domain or local network.
echo_ip_address(): This is a presentational function just to avoid littering the code with print statements everywhere just to print an IP addresss.
if __name__ == '__main__': This checks if the module(this script) is being run as the main program and not just being run from another module i.e. Imported by another python module(file).
The script also uses the ArgumentParser module because it does two related tasks ie getting the public IP and resolving a server's IP. So I used some switches to manipulate its behaviour.
I was trying to be fancy, so feel free to separate the code into two files or even implement a better approach.
Getting public IP.
Getting private IP.
Getting server's IP address.
NOTE: A Fully Qualified Domain Name (FQDN) is one that contains a hostname and the domain name concatenated by a dot(.) Examples:
Getting Public IP without External API
Regarding the public IP address, the first method is the most common solution you will find, though not the only one. The other option is to use the UpnP standard to communicate with your Internet Gateway Device (IGD). The UpnP standard allows devices on the local network to discover each other.
import upnpy upnp = upnpy.UPnP() internet_gateway_device = upnp.get_igd() #1 service_id = "WANPPPConnection.1" #2 It can also be WANIPConnection depeding on the connection type. PPP Point to Point protocol service = device[service_id] #3 print(service.GetExternalIPAddress(["NewExternalIPAddress"])
- upnpy package
pip install upnpy
Understanding the code
- Line #1: Locates the Internet Gateway Device (IGD) on the network by sending a broadcast message(Under the hood).
- Line #2: Network devices can offer a wide range of services and these services are identified by an ID and particularly for our case, we can either use WANPPPConnection.1 or WANIPConnection. For a list of services a device offers you can use:
- Line #3: Assigns the target service to the service variable.
- And then finally, the script makes a request to the service in order to retrieve the public IP address.
Suprised!!!!, Yes, you should be.
The above output means, that my network doesnot have an IGD, but I do have it, its just that It doesn't understand UPnP protocols.
Not all devices are UPnP compliant and thus for my network I tested this on, my gateway didnot understand UPnP protocols.