在这篇文章中,我们开发了一个Python脚本来获取私人、公共IP地址以及其他细节。
目录
- 什么是IP地址
- 私人与公共IP地址
- 域名系统(DNS)
- 使用案例
- 亲身体验。玩转IP地址
什么是IP地址
网络上的每一个节点(计算机)都被分配了一个唯一的号码,以识别它在网络上的身份。这个唯一的号码被编码在网络上为该节点发送的每个数据包中。
私人地址与公共地址
当你建立你的家庭网络时,分配给你的网络设备的地址将是私有的,除非你把它们公开。除非你在你的网关(面向互联网的路由器)上配置端口转发,否则公共地址是无法访问的。简而言之,私有地址是不能路由的。
而当你连接到ISP(互联网服务提供商)的网络时,你就获得了一个公共地址。与私人地址不同,公共地址是可路由的。
域名系统
人们通常称它为互联网的电话簿,确实如此。当你确实需要给保存在电话簿中的朋友打电话时,你能记住的最接近的东西就是他们的名字,这样就不需要记住你朋友的号码了。
上述情况类似于DNS对互联网的作用,而不是记住一个IP地址(8.8.8.8--谷歌的IP地址),你所要记住的只是google.com。
使用案例
除了允许网络上的通信,IP地址还被创造性地用于访问控制、地理位置等应用。
实践 玩转IP地址
#!/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")
了解代码
该脚本有三个程序(函数):
-
get_my_public_ip():
调用ipify的JSON端点,然后将响应转换为一个python字典,其中只有ip键(字段)。而这个字段有向API发出请求的节点的公共地址,这个节点就是你的电脑。 -
get_my_private_ip():
返回分配给节点的私有地址。
它使用了socket模块的两个函数:
gethostname()。返回节点的主机名
gethostbyname()。将主机名解析为一个IP地址。 -
resolve_fqdn():
获取服务器的IP地址是一个DNS解析,因此,你需要一个服务器的完全合格的域名。
FQDN解析是由*socket.gethostbyname()*完成的,它需要一个主机名作为参数,但对于我们的例子,我们需要FQDN,因为服务器不属于我们的域或本地网络。 -
echo_ip_address()。这是一个展示性的函数,只是为了避免在代码中到处出现打印语句来打印一个IP地址。
-
*如果 __name__ == '__main__':*这将检查模块(这个脚本)是否作为主程序运行,而不是从另一个模块运行,即由另一个python模块(文件)导入。
-
该脚本还使用了ArgumentParser模块,因为它做了两个相关的任务,即获取公共IP和解析服务器的IP。所以我使用了一些开关来操纵它的行为。
我想做得更花哨一些,所以请随意将代码分成两个文件,甚至实现一个更好的方法。
使用方法。
-
获取公共IP

-
获取私有IP

-
获取服务器的IP地址

注意: 一个完全合格的域名(FQDN)是包含一个主机名和由点(.)连接起来的域名。
不通过外部API获得公共IP
关于公共IP地址,第一种方法是你会发现的最常见的解决方案,尽管不是唯一的方法。另一个选择是使用UpnP标准与你的互联网网关设备(IGD)进行通信。UpnP标准允许本地网络上的设备相互发现。
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软件包
pip install upnpy
了解代码
- 第1行:通过发送广播信息在网络上找到互联网网关设备(IGD)(Under the hood)。
- 第二行:网络设备可以提供广泛的服务,这些服务由一个ID来识别,特别是对于我们的情况,我们可以使用WANPPPConnection.1或WANIPConnection。对于一个设备提供的服务列表,你可以使用。
<device>.get_services() - 第3行:将目标服务分配给服务变量。
- 最后,脚本向该服务发出请求,以检索公共IP地址。
使用方法

Suprised!!!!, 是的,你应该这样做。
上述输出意味着,我的网络没有IGD,但我确实有,只是它不理解UPnP协议。
并非所有的设备都符合UPnP协议,因此在我的网络上测试,我的网关不理解UPnP协议。
编码愉快。