If you've been searching for a way to easily resolve hostnames to IP addresses and vice versa, you've come to the right place. In this post, we'll explore the Python Socket Module and its capabilities to resolve hostnames to IP addresses and vice versa, let's get started!
Intro
The Python socket
module provides functions for working with network sockets and can be used to resolve hostnames to IP addresses and vice versa. You can use the gethostbyname()
function to resolve a hostname to an IP address and gethostbyaddr()
function to convert an IP address to a hostname.
Example 1 - Resolving a Single Host
Here's a simple example demonstrating how to resolve a single hostname to an IP address and an IP address to a hostname using the Python socket
module.
import socket
# Resolving a single hostname to an IP address
hostname = 'example.com'
ip_address = socket.gethostbyname(hostname)
print(f'{hostname} - {ip_address}')
# Resolving a single IP address to a hostname
ip_address = '8.8.8.8'
host_info = socket.gethostbyaddr(ip_address)
hostname = host_info[0] # Extracting the primary hostname using indexing
print(f'{ip_address} - {hostname}')
#output
example.com - 93.184.216.34
8.8.8.8 - dns.google
One thing to note when we resolve an IP address to a hostname is that, we store the tuple returned by socket.gethostbyaddr()
in the host_info
variable. Then, we extract the primary hostname by indexing the tuple with host_info[0]
. If you were to just print host_info
without indexing, it would look like the following.
print(host_info)
#output
('dns.google', ['8.8.8.8.in-addr.arpa'], ['8.8.8.8'])
The socket.gethostbyaddr()
function returns a tuple with three elements:
- The primary hostname is associated with the IP address (The one we are interested in) (string)
- An alias list containing alternative hostnames (list of strings)
- A list of IP addresses associated with the host (list of strings)
Alternatively, you can also use the following method to unpack the tuple. The end result is exactly the same.
ip_address = '8.8.8.8'
hostname, _, _ = socket.gethostbyaddr(ip_address)
print(f'{ip_address} - {hostname}')
In the above example, hostname, _, _
is a way to unpack the tuple returned by the socket.gethostbyaddr()
function while ignoring the other two elements of the tuple.
When using hostname, _, _
, the primary hostname is assigned to the hostname
variable, while the alias list and the list of IP addresses are assigned to the dummy variables _
. The underscore _
is a common convention in Python to indicate that a variable is a placeholder and its value will not be used later in the code. This is a way to make the code more readable and clear about its intentions.
Example 2 - Resolving Multiple Hosts with Error Handling
Here's an example of how to resolve a list of hostnames to IP addresses and convert a list of IP addresses to hostnames.
Exception handling is particularly useful for hostname and IP address resolution tasks, as it ensures your program remains functional when encountering incorrect hostnames or IP addresses. By handling exceptions, you can catch these errors and provide appropriate feedback, allowing your program to continue running without interruption.
import socket
# List of hostnames
hostnames = ['example.com', 'google.com', 'apple.com', 'dummp_host25.com']
# Resolving hostnames to IP addresses
for hostname in hostnames:
try:
ip_address = socket.gethostbyname(hostname)
print(f'{hostname} - {ip_address}')
except socket.gaierror as e:
print(f'Error resolving {hostname}: {e}')
print() #Print an empty line
# List of IP addresses
ip_addresses_to_resolve = ['8.8.8.8', '8.8.4.4', '208.67.222.222', '192.168.0.100']
# Converting IP addresses to hostnames
for ip_address in ip_addresses_to_resolve:
try:
host, _, _ = socket.gethostbyaddr(ip_address)
print(f'{ip_address} - {host}')
except socket.herror as e:
print(f'Error resolving {ip_address}: {e}')
#output
example.com - 93.184.216.34
google.com - 216.58.213.14
apple.com - 17.253.144.10
Error resolving dummp_host25.com: [Errno 8] nodename nor servname provided, or not known
8.8.8.8 - dns.google
8.8.4.4 - dns.google
208.67.222.222 - dns.umbrella.com
Error resolving 192.168.0.100: [Errno 1] Unknown host
Let's breakdown the code line by line:
import socket
: This line imports thesocket
module, which provides functions for working with network sockets and resolving hostnames and IP addresses.hostnames = ['example.com', 'google.com', 'apple.com', 'dummp_host25.com']
: This line creates a list of hostnames that you want to resolve to IP addresses. I intentionally included a random FQDN that will not resolve.for hostname in hostnames:
: This line starts afor
loop, iterating through each hostname in thehostnames
list.try:
: This line starts atry
block, used to catch exceptions that might occur during the hostname resolution process.ip_address = socket.gethostbyname(hostname)
: This line calls thesocket.gethostbyname()
function to resolve the currenthostname
to an IP address and stores it in theip_address
variable.print(f'{hostname} - {ip_address}')
: This line prints the hostname and its corresponding IP address.except socket.gaierror as e:
: This line starts anexcept
block that catches thesocket.gaierror
exception, which occurs when the hostname cannot be resolved.print(f'Error resolving {hostname}: {e}')
: This line prints an error message if the hostname resolution fails.print()
: This line prints an empty line to separate the outputs of the two loops.ip_addresses_to_resolve = ['8.8.8.8', '8.8.4.4', '208.67.222.222', '192.168.0.100']
: This line creates a list of IP addresses that you want to resolve to hostnames. I intentionally included a random IP address that will not resolve.for ip_address in ip_addresses_to_resolve:
: This line starts afor
loop, iterating through each IP address in theip_addresses_to_resolve
list.try:
: This line starts atry
block, used to catch exceptions that might occur during the IP address resolution process.host, _, _ = socket.gethostbyaddr(ip_address)
: This line calls thesocket.gethostbyaddr()
function to resolve the currentip_address
to a hostname and stores the primary hostname in thehost
variable. The_
characters are placeholders for the other two elements in the tuple returned by the function, indicating that they are not used.print(f'{ip_address} - {host}')
: This line prints the IP address and its corresponding hostname.except socket.herror as e:
: This line starts anexcept
block that catches thesocket.herror
exception, which occurs when the IP address cannot be resolved to a hostname.print(f'Error resolving {ip_address}: {e}')
: This line prints an error message if the IP address resolution fails.
Conclusion
In conclusion, the Python Socket Module provides a powerful and efficient way to resolve hostnames to IP addresses and vice versa. By incorporating exception handling, you can create reliable and robust programs that gracefully handle incorrect inputs and network issues. With these techniques in your toolbox, you'll be well-equipped to tackle your Network Automation tasks.